From bd2051fa45d33296db5202d948ceb991562ccee5 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 15:04:21 +0000 Subject: [PATCH 01/11] conftest.py: add -B, --build-dir option --- test/conftest.py => conftest.py | 14 ++++++++------ test/module_testing.py => module_testing.py | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) rename test/conftest.py => conftest.py (93%) rename test/module_testing.py => module_testing.py (99%) diff --git a/test/conftest.py b/conftest.py similarity index 93% rename from test/conftest.py rename to conftest.py index 1bfb63e3..b06fd9fd 100644 --- a/test/conftest.py +++ b/conftest.py @@ -5,6 +5,7 @@ from typing import List, Tuple import pytest + from module_testing import create_test_command_dcaspt2 slow_only_option = "--slowonly" @@ -16,6 +17,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: parser.addoption(slow_only_option, action="store_true", default=False, help="run only very slow tests") parser.addoption(dev_option, action="store_true", default=False, help="run tests for development") parser.addoption(runall_option, action="store_true", default=False, help="run all tests") + parser.addoption("-B", "--build-dir", action="store", default="bin", help="build directory [default: bin]") parser.addoption( "--mpi", type=int, @@ -48,7 +50,6 @@ def save(request: pytest.FixtureRequest): @pytest.fixture(scope="function") def env_setup_caspt2(request: pytest.FixtureRequest, mpi_num_process: int, omp_num_threads: int, save: bool) -> Tuple[Path, Path, Path, Path, str]: - root_path = Path(__file__).parent.parent test_path = Path(request.fspath).parent # test_name is the name of the test file without the extension and the first test_. # (e.g.) /path/to/test/slow/c1_methane_slow/test_c1_methane_slow.py -> c1_methane_slow @@ -63,7 +64,7 @@ def env_setup_caspt2(request: pytest.FixtureRequest, mpi_num_process: int, omp_n ref_output_path = test_path / ref_output_file output_path = test_path / output_filename latest_passed_path = test_path / latest_passed_output - dcaspt2 = root_path / "bin/dcaspt2" + dcaspt2 = request.config.build_dir / "dcaspt2" test_command = create_test_command_dcaspt2(dcaspt2, mpi_num_process, omp_num_threads, input_path, output_path, test_path, save) return ( @@ -77,7 +78,6 @@ def env_setup_caspt2(request: pytest.FixtureRequest, mpi_num_process: int, omp_n @pytest.fixture(scope="function") def env_setup_ivo(request: pytest.FixtureRequest, mpi_num_process: int, omp_num_threads: int, save: bool) -> Tuple[Path, Path, Path, Path, str]: - root_path = Path(__file__).parent.parent test_path = Path(request.fspath).parent # test_name is the name of the test file without the extension and the first test_. # (e.g.) /path/to/test/dev/ivo_c32h_n2_dev_dirac22/test_ivo_c32h_n2_dev_dirac22.py -> ivo_c32h_n2_dev_dirac22 @@ -95,7 +95,7 @@ def env_setup_ivo(request: pytest.FixtureRequest, mpi_num_process: int, omp_num_ latest_passed_DFPCMONEW_path = test_path / latest_passed_output output_path = test_path / output_filename latest_passed_output_path = test_path / latest_passed_output - dcaspt2 = root_path / "bin/dcaspt2" + dcaspt2 = request.config.build_dir / "dcaspt2" is_ivo = True test_command = create_test_command_dcaspt2(dcaspt2, mpi_num_process, omp_num_threads, input_path, output_path, test_path, save, is_ivo) @@ -115,8 +115,7 @@ def env_setup_gen_restart_file(request: pytest.FixtureRequest) -> Tuple[Path, Pa caller_name = request.function.__name__ caller_path = Path(request.node.path).expanduser().resolve().parent - root_path = Path(__file__).parent.parent - gen_restart_path = root_path / "bin/gen_dcaspt2_restart" + gen_restart_path = request.config.build_dir / "gen_dcaspt2_restart" test_path = Path(request.node.path).parent input_path = caller_path / f"{caller_name}.in" expected_path = caller_path / f"expected_{caller_name}" @@ -124,6 +123,9 @@ def env_setup_gen_restart_file(request: pytest.FixtureRequest) -> Tuple[Path, Pa def pytest_configure(config: pytest.Config) -> None: + config.build_dir = Path(config.getoption("--build-dir")).expanduser().resolve() + if not config.build_dir.exists(): + raise FileNotFoundError(f"build directory {config.build_dir} does not exist.") config.addinivalue_line("markers", "slowonly: mark test as slow to run") config.addinivalue_line("markers", "dev: mark test as for development") diff --git a/test/module_testing.py b/module_testing.py similarity index 99% rename from test/module_testing.py rename to module_testing.py index d71eb4ea..2c11d9ab 100644 --- a/test/module_testing.py +++ b/module_testing.py @@ -79,6 +79,7 @@ def check_test_returncode(process: "subprocess.CompletedProcess[str]") -> None: if process.returncode != 0: raise Exception("ERROR: Process failed. return code status : " + str(process.returncode)) + def get_multi_caspt2_energy_from_output_file(file_path: str) -> List[float]: with open(file_path, encoding="utf-8", mode="r") as output_file: try: @@ -91,6 +92,7 @@ def get_multi_caspt2_energy_from_output_file(file_path: str) -> List[float]: error_message = f"{error}\nERROR: Failed to get the CASPT2 energy from the reference file {file_path}." raise Exception(error_message) + def get_caspt2_energy_from_output_file(file_path: str) -> float: with open(file_path, encoding="utf-8", mode="r") as output_file: try: From 2bfa578964f8c69f16474a69db774461c865084f Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 15:05:09 +0000 Subject: [PATCH 02/11] .gitignore: Ignore build* directories --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 0b6f7f37..2cae0937 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,8 @@ # Ignore object files bin/ -# Ignore build directory -build/ +# Ignore build* directory +build* # Ignore object files and module files *.o From 1556c8dd70e97811f3ebb2dad8e44db107446f67 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 15:10:40 +0000 Subject: [PATCH 03/11] CMakeLists.txt: Don't set EXECUTABLE_OUTPUT_PATH manually executables are placed in PROJECT_BINARY_DIR --- CMakeLists.txt | 13 ++++++------- cmake/commit_hash.cmake | 4 ++-- src/CMakeLists.txt | 3 +++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cff1adc..4bf4c32d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,6 @@ option(MPI "Enable MPI?" OFF) option(OPENMP "Enable OpenMP?" OFF) option(MKL "Enable MKL?" ON) -set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) # Set executable output path set(CMAKE_Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules) # Set module output path # Deny In-source build ( Ref : https://github.com/eigenteam/eigen-git-mirror/blob/36b95962756c1fce8e29b1f8bc45967f30773c00/CMakeLists.txt#L7-L9) @@ -73,10 +72,10 @@ endif() add_subdirectory(src) add_subdirectory(test) -configure_file(${PROJECT_SOURCE_DIR}/tools/dcaspt2_input ${EXECUTABLE_OUTPUT_PATH}/dcaspt2 COPYONLY) -configure_file(${PROJECT_SOURCE_DIR}/tools/gen_dcaspt2_restart ${EXECUTABLE_OUTPUT_PATH}/gen_dcaspt2_restart COPYONLY) -install(PROGRAMS ${EXECUTABLE_OUTPUT_PATH}/dcaspt2 DESTINATION ${CMAKE_INSTALL_PREFIX}) -install(PROGRAMS ${EXECUTABLE_OUTPUT_PATH}/gen_dcaspt2_restart DESTINATION ${CMAKE_INSTALL_PREFIX}) +configure_file(${PROJECT_SOURCE_DIR}/tools/dcaspt2_input ${PROJECT_BINARY_DIR}/dcaspt2 COPYONLY) +configure_file(${PROJECT_SOURCE_DIR}/tools/gen_dcaspt2_restart ${PROJECT_BINARY_DIR}/gen_dcaspt2_restart COPYONLY) +install(PROGRAMS ${PROJECT_BINARY_DIR}/dcaspt2 DESTINATION ${CMAKE_INSTALL_PREFIX}) +install(PROGRAMS ${PROJECT_BINARY_DIR}/gen_dcaspt2_restart DESTINATION ${CMAKE_INSTALL_PREFIX}) # Create a custom target named commit_hash add_custom_target(commit_hash ALL) @@ -87,9 +86,9 @@ add_custom_command( PRE_BUILD COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} - -DEXECUTABLE_OUTPUT_PATH=${EXECUTABLE_OUTPUT_PATH} + -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR} -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} -P ${PROJECT_SOURCE_DIR}/cmake/commit_hash.cmake ALWAYS ) -install(FILES ${EXECUTABLE_OUTPUT_PATH}/.commit_hash DESTINATION ${CMAKE_INSTALL_PREFIX}) +install(FILES ${PROJECT_BINARY_DIR}/.commit_hash DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/cmake/commit_hash.cmake b/cmake/commit_hash.cmake index a70ea348..a982330a 100644 --- a/cmake/commit_hash.cmake +++ b/cmake/commit_hash.cmake @@ -1,6 +1,6 @@ message(STATUS "Getting git hash") message(STATUS "commit_hash.cmake PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}") -message(STATUS "commit_hash.cmake EXECUTABLE_OUTPUT_PATH: ${EXECUTABLE_OUTPUT_PATH}") +message(STATUS "commit_hash.cmake PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}") message(STATUS "commit_hash.cmake CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") set(git_hash "unknown") # Default value @@ -17,4 +17,4 @@ else() set(git_hash "unknown") endif() -file(WRITE ${EXECUTABLE_OUTPUT_PATH}/.commit_hash "${git_hash}") +file(WRITE ${PROJECT_BINARY_DIR}/.commit_hash "${git_hash}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0bbbb09..4545b71b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,4 +83,7 @@ add_executable(r4dcaspt2exe ) target_link_libraries(r4dcaspt2exe dcaspt2_module) +# r4dcaspt2exe is placed in the PROJECT_BINARY_DIR on build time +set_target_properties(r4dcaspt2exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") + install(TARGETS r4dcaspt2exe RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) From 219d0aa9b47cbfa9763f0cb0244f6aa4bd47c5d8 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 15:14:19 +0000 Subject: [PATCH 04/11] setup: add build_path argument to specify the build directory --- setup | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/setup b/setup index 5206c337..d55533b7 100755 --- a/setup +++ b/setup @@ -29,10 +29,11 @@ def define_args() -> "argparse.Namespace": parser.add_argument("--no-mkl", action="store_true", help="Disable MKL support. The path to the BLAS/LAPACK library should be specified in the --flags option.") parser.add_argument("--omp", "--openmp", action="store_true", help="Enable OpenMP support.") parser.add_argument("--prefix", type=str, metavar="INSTALL_DIR", help="Specify the installation directory. [default: /usr/local/bin]") + parser.add_argument("build_path", nargs="?", default="build", help="Specify the build directory. [default: build]") return parser.parse_args() -def preprocess(args: "argparse.Namespace", exec_path: Path, script_path: Path) -> str: +def preprocess(args: "argparse.Namespace", build_dir: Path) -> str: def check_cmake_version() -> None: logging.info("Checking if CMake is installed and the version is 3.14 or later...") try: @@ -69,15 +70,12 @@ def preprocess(args: "argparse.Namespace", exec_path: Path, script_path: Path) - raise # raise the FileNotFoundError exception to exit the script with an error code. def clean_dir() -> None: - """Remove build and bin directories before configuring the source code.""" + """Remove build directories before configuring the source code.""" logging.info("Cleaning the build directory...") - remove_dirs_name = ["build", "bin"] - for rmdir_name in remove_dirs_name: - rmdir = (script_path / rmdir_name).resolve() - logging.info(f"Checking if {rmdir} exists...") - if rmdir.exists(): - shutil.rmtree(rmdir) - logging.info(f"Removed the directory {rmdir}") + logging.info(f"Checking if {build_dir} exists...") + if build_dir.exists(): + shutil.rmtree(build_dir) + logging.info(f"Removed the directory {build_dir}") def set_compiler() -> str: if args.fc is not None: @@ -135,27 +133,26 @@ def preprocess(args: "argparse.Namespace", exec_path: Path, script_path: Path) - return cmake_flags -def configure_source(cmake_flags: str, script_path: Path) -> None: +def configure_source(build_dir: Path, cmake_flags: str) -> None: logging.info(f"CMake flags are {cmake_flags}") - build_dir = (script_path / "build").resolve() build_dir.mkdir(exist_ok=True) command = f"cmake -B {build_dir} {cmake_flags}" with open("cmake_build_command.log", "w") as f: f.write(command) logging.info(f"BUILD COMMAND is {command}") - logging.info(f"Build command is saved in {script_path}/cmake_build_command.log") + logging.info(f"Build command is saved in {Path.cwd().resolve()}/cmake_build_command.log") subprocess.run(command.split(), check=True) logging.info("Successfully configured the source code.") -def build(args: "argparse.Namespace") -> None: +def build(args: "argparse.Namespace", build_path: Path) -> None: num_of_process = args.parallel if num_of_process == -1: # const value of -j option, which means the native build tool's default number is used. # (https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-build-j) - cmd = "cmake --build build -j" + cmd = f"cmake --build {build_path} -j" else: - cmd = f"cmake --build build -j {num_of_process}" + cmd = f"cmake --build {build_path} -j {num_of_process}" subprocess.run(cmd.split(), check=True) logging.info("Successfully built the project.") @@ -163,23 +160,25 @@ def build(args: "argparse.Namespace") -> None: def main(): logging.info("Start dirac_caspt2 setup script.") - exec_path = Path.cwd().resolve() script_path = Path(__file__).parent.resolve() os.chdir(script_path) args = define_args() - cmake_flags = preprocess(args, exec_path, script_path) - configure_source(cmake_flags, script_path) + build_path = Path(args.build_path).expanduser().resolve() + logging.info(f"build path is {build_path}") + cmake_flags = preprocess(args, build_path) + configure_source(build_path, cmake_flags) if not args.build: finish_message = "Finished the setup script.\n\n If you want to build the project, please run the following command: \n\tcmake --build build\n or\n\tmake -C build\n After building the project successfully, you should run tests!\n" else: - build(args) + build(args, build_path) finish_message = "Finished the setup script.\n" logging.info(finish_message) mpi_option_message = " --mpi=[number of MPI processes]" if args.mpi else "" omp_option_message = " --omp=[number of OpenMP threads per one process]" if args.omp else "" + build_dir_option_message = f" --build-dir={build_path}" enable_or_disable_mpi = "set" if args.mpi else "do not set" logging.info( @@ -189,9 +188,9 @@ def main(): \tpip install pytest\n\n\ You {enable_or_disable_mpi} --mpi option. Therefore, you should run one of the following tests:\n\ - Run all tests:\n\ - \tpytest --all{mpi_option_message}{omp_option_message}\n\ + \tpytest --all{build_dir_option_message}{mpi_option_message}{omp_option_message}\n\ - Run tests excluding the tests long time to run:\n\ - \tpytest{mpi_option_message}{omp_option_message}\n\ + \tpytest{build_dir_option_message}{mpi_option_message}{omp_option_message}\n\ For more information, please read the {script_path}/README.md file." ) From aaaee7231553f8139816066d57b9159a0371106c Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 15:15:38 +0000 Subject: [PATCH 05/11] conftest.py: update default build directory from 'bin' to 'build' --- conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conftest.py b/conftest.py index b06fd9fd..5045f235 100644 --- a/conftest.py +++ b/conftest.py @@ -17,7 +17,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: parser.addoption(slow_only_option, action="store_true", default=False, help="run only very slow tests") parser.addoption(dev_option, action="store_true", default=False, help="run tests for development") parser.addoption(runall_option, action="store_true", default=False, help="run all tests") - parser.addoption("-B", "--build-dir", action="store", default="bin", help="build directory [default: bin]") + parser.addoption("-B", "--build-dir", action="store", default="build", help="build directory [default: build]") parser.addoption( "--mpi", type=int, From 439b4a428ab800220603f9576a5c5de86a92d8f5 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 15:21:08 +0000 Subject: [PATCH 06/11] README: update default binary and dcaspt2 script location to build directory --- README.ja.md | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.ja.md b/README.ja.md index 576fb89c..8a05b2bb 100644 --- a/README.ja.md +++ b/README.ja.md @@ -101,7 +101,7 @@ git clone --depth=1 https://github.com/RQC-HU/dirac_caspt2.git - このプログラムはsetupスクリプトを使用してビルドできます - CMakeコマンドを直接使用してビルドすることもできますが、setupスクリプトを使用することをおすすめします - CMakeを直接使用してビルドしたい場合は、[CMakeビルドオプション](#cmakeビルドオプション)を参照してください -- デフォルトでは、ビルドした結果のバイナリとdcaspt2スクリプトはbinディレクトリ直下に配置されます +- デフォルトでは、ビルドした結果のバイナリとdcaspt2スクリプトはbuildディレクトリ直下に配置されます ### Basic build @@ -247,7 +247,7 @@ pytest --all ### Calculation -- ビルド後に作られるbinディレクトリ直下またはprefixを指定した場合はインストール先のディレクトリ直下のdcaspt2スクリプトを用いて計算を行います +- ビルド後に作られるbuildディレクトリ直下またはprefixを指定した場合はインストール先のディレクトリ直下のdcaspt2スクリプトを用いて計算を行います - dcaspt2スクリプトで使用可能なオプションはdcaspt2 -hで確認できます - 例えば以下のように使用します diff --git a/README.md b/README.md index 41d37246..cc9fb93a 100644 --- a/README.md +++ b/README.md @@ -237,11 +237,11 @@ The following custom CMake build options are currently supported ### Calculation - You can use this program with the dcaspt2 script - - The dcaspt2 script is located in the bin directory or in the destination directory if installed by specifying with a --prefix option. + - The dcaspt2 script is located in the build directory (by default) or in the destination directory if installed by specifying with a --prefix option. ```sh # If you did not install with --prefix - /path/to/dirac_caspt2/bin/dcaspt2 -i input_file + /path/to/dirac_caspt2/build/dcaspt2 -i input_file # If you installed with --prefix $PREFIX/dcaspt2 -i input_file ``` From c79e7b1f7d2d7e841e17d899892c494a79ff2518 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 16:32:37 +0000 Subject: [PATCH 07/11] conftest.py: add unittest environment setup fixture --- conftest.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/conftest.py b/conftest.py index 5045f235..b1a9106b 100644 --- a/conftest.py +++ b/conftest.py @@ -121,6 +121,13 @@ def env_setup_gen_restart_file(request: pytest.FixtureRequest) -> Tuple[Path, Pa expected_path = caller_path / f"expected_{caller_name}" return (gen_restart_path, test_path, input_path, expected_path) +@pytest.fixture(scope="function") +def env_setup_unittest(request: pytest.FixtureRequest): + def _env_setup_unittest(exe_name: str) -> Path: + build_dir = request.config.build_dir + exe_path = build_dir / exe_name + return exe_path + return _env_setup_unittest def pytest_configure(config: pytest.Config) -> None: config.build_dir = Path(config.getoption("--build-dir")).expanduser().resolve() From 05bb9fca7e59ad83a5ec32f80f1b50c08a39f719 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Thu, 6 Feb 2025 16:33:58 +0000 Subject: [PATCH 08/11] test/unit_test: set unit_test binary output directory to PROJECT_BINARY_DIR --- test/unit_test/lowercase/CMakeLists.txt | 1 + test/unit_test/lowercase/test_lowercase.py | 6 ++--- test/unit_test/ras3_bitcheck/CMakeLists.txt | 1 + .../ras3_bitcheck/test_ras3_bitcheck.py | 5 ++-- .../unit_test/ras_input_reader/CMakeLists.txt | 1 + .../ras_input_reader/test_ras_input_reader.py | 6 ++--- test/unit_test/sort_test/CMakeLists.txt | 5 ++++ test/unit_test/sort_test/test_sort.py | 24 +++++++------------ test/unit_test/time_calc/CMakeLists.txt | 1 + test/unit_test/time_calc/test_time_calc.py | 5 ++-- test/unit_test/uppercase/CMakeLists.txt | 1 + test/unit_test/uppercase/test_uppercase.py | 6 ++--- 12 files changed, 29 insertions(+), 33 deletions(-) diff --git a/test/unit_test/lowercase/CMakeLists.txt b/test/unit_test/lowercase/CMakeLists.txt index 9cbd9fd6..6807ba43 100644 --- a/test/unit_test/lowercase/CMakeLists.txt +++ b/test/unit_test/lowercase/CMakeLists.txt @@ -4,3 +4,4 @@ add_executable(test_lowercase_exe test_lowercase.f90 ) target_link_libraries(test_lowercase_exe dcaspt2_module) +set_target_properties(test_lowercase_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") diff --git a/test/unit_test/lowercase/test_lowercase.py b/test/unit_test/lowercase/test_lowercase.py index 25a4df0c..b2862733 100644 --- a/test/unit_test/lowercase/test_lowercase.py +++ b/test/unit_test/lowercase/test_lowercase.py @@ -11,13 +11,14 @@ @pytest.mark.dev -def test_lowercase(): +def test_lowercase(env_setup_unittest): + exe_file_path = env_setup_unittest("test_lowercase_exe") + print(f"Test command: {exe_file_path}") # Set file names ref_output_file = "expected" # Reference output_filename = "result.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.result.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_lowercase_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -28,7 +29,6 @@ def test_lowercase(): ref_output_file_path = os.path.abspath(os.path.join(test_path, ref_output_file)) output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) diff --git a/test/unit_test/ras3_bitcheck/CMakeLists.txt b/test/unit_test/ras3_bitcheck/CMakeLists.txt index 8389fa5a..35a32803 100644 --- a/test/unit_test/ras3_bitcheck/CMakeLists.txt +++ b/test/unit_test/ras3_bitcheck/CMakeLists.txt @@ -4,3 +4,4 @@ add_executable(ras3_bitcheck_exe test_ras3_bitcheck.f90 ) target_link_libraries(ras3_bitcheck_exe dcaspt2_module) +set_target_properties(ras3_bitcheck_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") diff --git a/test/unit_test/ras3_bitcheck/test_ras3_bitcheck.py b/test/unit_test/ras3_bitcheck/test_ras3_bitcheck.py index 68f5afab..e26347ef 100644 --- a/test/unit_test/ras3_bitcheck/test_ras3_bitcheck.py +++ b/test/unit_test/ras3_bitcheck/test_ras3_bitcheck.py @@ -9,7 +9,8 @@ @pytest.mark.dev -def test_ras3_bitcheck(): +def test_ras3_bitcheck(env_setup_unittest): + exe_file_path = env_setup_unittest("ras3_bitcheck_exe") # Current path test_path = os.path.dirname(os.path.abspath(__file__)) @@ -19,12 +20,10 @@ def test_ras3_bitcheck(): # input/output/executable file names ref_output_file = "expected" result_filename = "result.out" - exe_filename = "ras3_bitcheck_exe" # Absolute path to input/output/executable files ref_output_file_path = os.path.abspath(os.path.join(test_path, ref_output_file)) result_file_path = os.path.abspath(os.path.join(test_path, result_filename)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) test_command = create_test_command(mpi_num_process=1, binaries=[exe_file_path]) diff --git a/test/unit_test/ras_input_reader/CMakeLists.txt b/test/unit_test/ras_input_reader/CMakeLists.txt index 32a9e8d3..f5ffb133 100644 --- a/test/unit_test/ras_input_reader/CMakeLists.txt +++ b/test/unit_test/ras_input_reader/CMakeLists.txt @@ -4,3 +4,4 @@ add_executable(test_ras_input_reader_exe test_ras_input_reader.f90 ) target_link_libraries(test_ras_input_reader_exe dcaspt2_module) +set_target_properties(test_ras_input_reader_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") diff --git a/test/unit_test/ras_input_reader/test_ras_input_reader.py b/test/unit_test/ras_input_reader/test_ras_input_reader.py index 48ae05b6..136f3dcb 100644 --- a/test/unit_test/ras_input_reader/test_ras_input_reader.py +++ b/test/unit_test/ras_input_reader/test_ras_input_reader.py @@ -12,13 +12,12 @@ @pytest.mark.dev -def test_ras_input_reader(): - +def test_ras_input_reader(env_setup_unittest): + exe_file_path = env_setup_unittest("test_ras_input_reader_exe") # Set file names ref_output_file = "expected" # Reference output_filename = "result.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.result.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_ras_input_reader_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -29,7 +28,6 @@ def test_ras_input_reader(): ref_output_file_path = os.path.abspath(os.path.join(test_path, ref_output_file)) output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) diff --git a/test/unit_test/sort_test/CMakeLists.txt b/test/unit_test/sort_test/CMakeLists.txt index ca23edaa..4925e142 100644 --- a/test/unit_test/sort_test/CMakeLists.txt +++ b/test/unit_test/sort_test/CMakeLists.txt @@ -16,3 +16,8 @@ add_executable(test_sort_real_reverse_exe test_sort_real_reverse.f90 ) target_link_libraries(test_sort_real_reverse_exe dcaspt2_module) + +set_target_properties(test_sort_int_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") +set_target_properties(test_sort_int_reverse_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") +set_target_properties(test_sort_real_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") +set_target_properties(test_sort_real_reverse_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") diff --git a/test/unit_test/sort_test/test_sort.py b/test/unit_test/sort_test/test_sort.py index 5bd18020..2167a199 100644 --- a/test/unit_test/sort_test/test_sort.py +++ b/test/unit_test/sort_test/test_sort.py @@ -13,12 +13,11 @@ @pytest.mark.dev -def test_int_sort(): - +def test_int_sort(env_setup_unittest): + exe_file_path = env_setup_unittest("test_sort_int_exe") # Set file names output_filename = "int.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.int.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_sort_int_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -28,7 +27,6 @@ def test_int_sort(): # Set file paths output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) @@ -75,12 +73,11 @@ def test_int_sort(): @pytest.mark.dev -def test_int_sort_reverse(): - +def test_int_sort_reverse(env_setup_unittest): + exe_file_path = env_setup_unittest("test_sort_int_reverse_exe") # Set file names output_filename = "int_reverse.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.int_reverse.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_sort_int_reverse_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -90,7 +87,6 @@ def test_int_sort_reverse(): # Set file paths output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) @@ -137,12 +133,11 @@ def test_int_sort_reverse(): @pytest.mark.dev -def test_real_sort(): - +def test_real_sort(env_setup_unittest): + exe_file_path = env_setup_unittest("test_sort_real_exe") # Set file names output_filename = "real.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.real.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_sort_real_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -152,7 +147,6 @@ def test_real_sort(): # Set file paths output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) @@ -177,12 +171,11 @@ def test_real_sort(): @pytest.mark.dev -def test_real_sort_reverse(): - +def test_real_sort_reverse(env_setup_unittest): + exe_file_path = env_setup_unittest("test_sort_real_reverse_exe") # Set file names output_filename = "real_reverse.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.real_reverse.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_sort_real_reverse_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -192,7 +185,6 @@ def test_real_sort_reverse(): # Set file paths output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) diff --git a/test/unit_test/time_calc/CMakeLists.txt b/test/unit_test/time_calc/CMakeLists.txt index 40ece1dd..0b197aff 100644 --- a/test/unit_test/time_calc/CMakeLists.txt +++ b/test/unit_test/time_calc/CMakeLists.txt @@ -4,3 +4,4 @@ add_executable(test_time_calc_exe test_time_calc.f90 ) target_link_libraries(test_time_calc_exe dcaspt2_module) +set_target_properties(test_time_calc_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") diff --git a/test/unit_test/time_calc/test_time_calc.py b/test/unit_test/time_calc/test_time_calc.py index 4ca82e19..1659fd2f 100644 --- a/test/unit_test/time_calc/test_time_calc.py +++ b/test/unit_test/time_calc/test_time_calc.py @@ -13,7 +13,7 @@ @pytest.mark.dev -def test_time_calc(): +def test_time_calc(env_setup_unittest): def create_date_time_from_input(input_str: str) -> datetime: # (e.g. "2021 01 01 00 00 00 00\n") @@ -31,11 +31,11 @@ def create_date_time_from_output(output_str: str) -> datetime: day, hour, minute, second = int(splitted[-8]), int(splitted[-6]), int(splitted[-4]), float(splitted[-2]) return timedelta(days=day, hours=hour, minutes=minute, seconds=second) + exe_file_path = env_setup_unittest("test_time_calc_exe") # Set file names input_file = "input" output_filename = "stdout.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.result.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_time_calc_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -46,7 +46,6 @@ def create_date_time_from_output(output_str: str) -> datetime: input_file_path = os.path.abspath(os.path.join(test_path, input_file)) output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) diff --git a/test/unit_test/uppercase/CMakeLists.txt b/test/unit_test/uppercase/CMakeLists.txt index 7e0b1877..088451ab 100644 --- a/test/unit_test/uppercase/CMakeLists.txt +++ b/test/unit_test/uppercase/CMakeLists.txt @@ -4,3 +4,4 @@ add_executable(test_uppercase_exe test_uppercase.f90 ) target_link_libraries(test_uppercase_exe dcaspt2_module) +set_target_properties(test_uppercase_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") diff --git a/test/unit_test/uppercase/test_uppercase.py b/test/unit_test/uppercase/test_uppercase.py index c179669f..42e42315 100644 --- a/test/unit_test/uppercase/test_uppercase.py +++ b/test/unit_test/uppercase/test_uppercase.py @@ -11,13 +11,12 @@ @pytest.mark.dev -def test_uppercase(): - +def test_uppercase(env_setup_unittest): + exe_file_path = env_setup_unittest("test_uppercase_exe") # Set file names ref_output_file = "expected" # Reference output_filename = "result.out" # Output (This file is compared with Reference) latest_passed_output = "latest_passed.result.out" # latest passed output (After test, the output file is moved to this) - exe_filename = "test_uppercase_exe" # Executable file # Get this files path and change directory to this path test_path = os.path.dirname(os.path.abspath(__file__)) # The path of this file @@ -28,7 +27,6 @@ def test_uppercase(): ref_output_file_path = os.path.abspath(os.path.join(test_path, ref_output_file)) output_file_path = os.path.abspath(os.path.join(test_path, output_filename)) latest_passed_path = os.path.abspath(os.path.join(test_path, latest_passed_output)) - exe_file_path = os.path.abspath(os.path.join(test_path, exe_filename)) is_binary_file_exist(exe_file_path) delete_scratch_files([output_filename], test_path) From 7d52c8a62ba465593ca87ca1a33a9ff6eee56192 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Sat, 8 Feb 2025 11:53:06 +0000 Subject: [PATCH 09/11] setup: make build_path option into the option with -B, --build-dir args in order to avoid conflict with -j option --- setup | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/setup b/setup index d55533b7..dbee92ef 100755 --- a/setup +++ b/setup @@ -12,6 +12,7 @@ from pathlib import Path def define_args() -> "argparse.Namespace": parser = argparse.ArgumentParser(description="This script is used as a setup script for this project.") + parser.add_argument("-B", "--build-dir", type=str, dest="build_dir", default="build", help="Specify the build directory. [default: build]") parser.add_argument("--build", action="store_true", help="Build the project after the setup. [default: False]") parser.add_argument("--build-type", type=str, help="Specify the build type. (release, debug can be specified.) [default: release]") parser.add_argument("--fc", type=str, help="The path to the Fortran compiler.(If not specified, the default compiler will be used.)") @@ -29,7 +30,6 @@ def define_args() -> "argparse.Namespace": parser.add_argument("--no-mkl", action="store_true", help="Disable MKL support. The path to the BLAS/LAPACK library should be specified in the --flags option.") parser.add_argument("--omp", "--openmp", action="store_true", help="Enable OpenMP support.") parser.add_argument("--prefix", type=str, metavar="INSTALL_DIR", help="Specify the installation directory. [default: /usr/local/bin]") - parser.add_argument("build_path", nargs="?", default="build", help="Specify the build directory. [default: build]") return parser.parse_args() @@ -145,14 +145,14 @@ def configure_source(build_dir: Path, cmake_flags: str) -> None: logging.info("Successfully configured the source code.") -def build(args: "argparse.Namespace", build_path: Path) -> None: +def build(args: "argparse.Namespace", build_dir: Path) -> None: num_of_process = args.parallel if num_of_process == -1: # const value of -j option, which means the native build tool's default number is used. # (https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-build-j) - cmd = f"cmake --build {build_path} -j" + cmd = f"cmake --build {build_dir} -j" else: - cmd = f"cmake --build {build_path} -j {num_of_process}" + cmd = f"cmake --build {build_dir} -j {num_of_process}" subprocess.run(cmd.split(), check=True) logging.info("Successfully built the project.") @@ -164,21 +164,21 @@ def main(): os.chdir(script_path) args = define_args() - build_path = Path(args.build_path).expanduser().resolve() - logging.info(f"build path is {build_path}") - cmake_flags = preprocess(args, build_path) - configure_source(build_path, cmake_flags) + build_dir = Path(args.build_dir).expanduser().resolve() + logging.info(f"build path is {build_dir}") + cmake_flags = preprocess(args, build_dir) + configure_source(build_dir, cmake_flags) if not args.build: finish_message = "Finished the setup script.\n\n If you want to build the project, please run the following command: \n\tcmake --build build\n or\n\tmake -C build\n After building the project successfully, you should run tests!\n" else: - build(args, build_path) + build(args, build_dir) finish_message = "Finished the setup script.\n" logging.info(finish_message) mpi_option_message = " --mpi=[number of MPI processes]" if args.mpi else "" omp_option_message = " --omp=[number of OpenMP threads per one process]" if args.omp else "" - build_dir_option_message = f" --build-dir={build_path}" + build_dir_option_message = f" --build-dir={build_dir}" enable_or_disable_mpi = "set" if args.mpi else "do not set" logging.info( From 7333390e63b6be5755559753eb00d0e7d9e45316 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Sat, 8 Feb 2025 12:05:48 +0000 Subject: [PATCH 10/11] setup: add function to avoid to override source code --- setup | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setup b/setup index dbee92ef..f5914cd9 100755 --- a/setup +++ b/setup @@ -33,6 +33,15 @@ def define_args() -> "argparse.Namespace": return parser.parse_args() +def validate_build_dir(build_dir: Path, script_path: Path): + banned_dir_names = ["__pycache__", ".devcontainer", ".git", ".github", ".pytest_cache", ".vscode", "cmake", "src", "test", "tools"] + banned_dirs = set(script_path / banned_dir_name for banned_dir_name in banned_dir_names) + if build_dir in banned_dirs: + logging.error(f"Build directory {build_dir} is not allowed because it is a reserved directory.") + logging.error(f"baned_dirs: {[d.as_posix() for d in banned_dirs]}") + raise ValueError(f"Build directory {build_dir} is not allowed.") + + def preprocess(args: "argparse.Namespace", build_dir: Path) -> str: def check_cmake_version() -> None: logging.info("Checking if CMake is installed and the version is 3.14 or later...") @@ -165,6 +174,7 @@ def main(): args = define_args() build_dir = Path(args.build_dir).expanduser().resolve() + validate_build_dir(build_dir, script_path) logging.info(f"build path is {build_dir}") cmake_flags = preprocess(args, build_dir) configure_source(build_dir, cmake_flags) From 1229220defac5bc0d537f73a794f9e1a04c8de36 Mon Sep 17 00:00:00 2001 From: Kohei Noda Date: Sat, 8 Feb 2025 12:08:49 +0000 Subject: [PATCH 11/11] setup: s/baned/banned --- setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup b/setup index f5914cd9..0f806102 100755 --- a/setup +++ b/setup @@ -38,7 +38,7 @@ def validate_build_dir(build_dir: Path, script_path: Path): banned_dirs = set(script_path / banned_dir_name for banned_dir_name in banned_dir_names) if build_dir in banned_dirs: logging.error(f"Build directory {build_dir} is not allowed because it is a reserved directory.") - logging.error(f"baned_dirs: {[d.as_posix() for d in banned_dirs]}") + logging.error(f"banned_dirs: {[d.as_posix() for d in banned_dirs]}") raise ValueError(f"Build directory {build_dir} is not allowed.")