# # This file is part of the GROMACS molecular simulation package. # # Copyright (c) 2012,2013,2014,2015,2016, The GROMACS development team. # Copyright (c) 2017,2018,2019,2020,2021, by the GROMACS development team, led by # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, # and including many others, as listed in the AUTHORS file in the # top-level source directory and at http://www.gromacs.org. # # GROMACS is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License # as published by the Free Software Foundation; either version 2.1 # of the License, or (at your option) any later version. # # GROMACS is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with GROMACS; if not, see # http://www.gnu.org/licenses, or write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # If you want to redistribute modifications to GROMACS, please # consider that scientific software is very special. Version # control is crucial - bugs must be traceable. We will be happy to # consider code for inclusion in the official distribution, but # derived work must not be called official GROMACS. Details are found # in the README & COPYING files - if they are missing, get the # official version at http://www.gromacs.org. # # To help us fund GROMACS development, we humbly ask that you cite # the research papers on the package. Check out http://www.gromacs.org. set(REGRESSIONTEST_PATH "" CACHE PATH "Directory containing regressiontests") mark_as_advanced(REGRESSIONTEST_PATH) option(REGRESSIONTEST_DOWNLOAD "Automatically download regressiontests. Tests can be run with ctest." OFF) if(REGRESSIONTEST_DOWNLOAD) if (NOT SOURCE_IS_SOURCE_DISTRIBUTION) set(REGRESSIONTEST_URL https://gitlab.com/gromacs/gromacs-regressiontests/-/archive/${REGRESSIONTEST_BRANCH}/gromacs-regressiontests-${REGRESSIONTEST_BRANCH}.tar.gz) # REGRESSIONTEST_PATH for dev trees is set later based on the dirname found in the tar else() set(REGRESSIONTEST_URL https://ftp.gromacs.org/regressiontests/regressiontests-${REGRESSIONTEST_VERSION}.tar.gz) set(REGRESSIONTEST_PATH "${CMAKE_CURRENT_BINARY_DIR}/regressiontests-${REGRESSIONTEST_VERSION}" CACHE PATH "Path to auto-downloaded regressiontests" FORCE) endif() set(REGRESSIONTEST_FILE "${CMAKE_CURRENT_BINARY_DIR}/regressiontests.tgz") message("Downloading: ${REGRESSIONTEST_URL}") file(DOWNLOAD ${REGRESSIONTEST_URL} "${REGRESSIONTEST_FILE}" SHOW_PROGRESS STATUS status LOG log) list(GET status 0 status_code) list(GET status 1 status_string) if(NOT status_code EQUAL 0) message(FATAL_ERROR "error: downloading '${REGRESSIONTEST_URL}' failed status_code: ${status_code} status_string: ${status_string} log: ${log}") endif() if (SOURCE_IS_SOURCE_DISTRIBUTION) file(MD5 ${REGRESSIONTEST_FILE} COMPUTED_MD5SUM) if(NOT ${REGRESSIONTEST_MD5SUM} STREQUAL ${COMPUTED_MD5SUM}) message(FATAL_ERROR "Download of regressiontests failed. Expected MD5 of ${REGRESSIONTEST_MD5SUM} but download has ${COMPUTED_MD5SUM}") endif() else() # Extract the REGRESSIONTEST_PATH from the tar when using dev tree. execute_process(COMMAND ${CMAKE_COMMAND} -E tar tf "${REGRESSIONTEST_FILE}" RESULT_VARIABLE _tar_tf_res OUTPUT_VARIABLE _tar_tf_out) if (${_tar_tf_res} EQUAL 0) string(REGEX REPLACE "/\n.*$" "" _regressiontest_dir "${_tar_tf_out}") set(REGRESSIONTEST_PATH "${CMAKE_CURRENT_BINARY_DIR}/${_regressiontest_dir}" CACHE PATH "Path to auto-downloaded regressiontests" FORCE) else() message(FATAL_ERROR "Failed to list the contents of the downloaded tarball: ${REGRESSIONTEST_FILE}") endif() endif() file(REMOVE_RECURSE "${REGRESSIONTEST_PATH}") #delete potential prior folder execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${REGRESSIONTEST_FILE}" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") if(NOT EXISTS ${REGRESSIONTEST_PATH}/gmxtest.pl) message(FATAL_ERROR "Download incorrect. Doesn't contain required gmxtest.pl") endif() set(REGRESSIONTEST_DOWNLOAD OFF CACHE BOOL "Tests already downloaded. Set to yes to download again" FORCE) endif() if(REGRESSIONTEST_PATH AND (CMAKE_CROSSCOMPILING OR CMAKE_CONFIGURATION_TYPES)) # TODO: It would be nicer to do these checks before potentially downloading the tests. # Cross-compiling toolchains require us to compile both front-end and # back-end binaries to run gmxtest.pl. message(WARNING "With cross-compiling or multi-configuration generators (e.g. Visual Studio), running regressiontests from build system is not supported. Please run gmxtest.pl directly.") set(REGRESSIONTEST_PATH OFF CACHE BOOL "With cross-compiling or multi-configuration generators, running regressiontests from build system is not supported." FORCE) endif() if(REGRESSIONTEST_PATH) if(NOT EXISTS ${REGRESSIONTEST_PATH}/gmxtest.pl) message(FATAL_ERROR "REGRESSIONTEST_PATH invalid. The path needs to contain gmxtest.pl.") endif() # gmxtests target builds all binaries required for running gmxtest add_custom_target(gmxtests DEPENDS gmx) add_dependencies(run-ctest gmxtests) add_dependencies(run-ctest-nophys gmxtests) if(GMX_DOUBLE) list(APPEND ARGS -double) endif() if(GMX_LIB_MPI AND NOT MPIEXEC) # find_program failed message(WARNING "Please set MPIEXEC. Otherwise mpirun is assumed for running tests.") endif() if(DEFINED ENV{CI_JOB_ID} AND GMX_OPENMP) set(GMX_REGRESSIONTEST_OMP_THREADS 2 CACHE STRING "Number of OpenMP threads to use with the regression tests") mark_as_advanced(GMX_REGRESSIONTEST_OMP_THREADS) list(APPEND ARGS -ntomp ${GMX_REGRESSIONTEST_OMP_THREADS}) endif() if(GMX_LIB_MPI) set(GMX_TEST_NUMBER_PROCS 8 CACHE STRING "Number of processors used for testing") mark_as_advanced(GMX_TEST_NUMBER_PROCS) list(APPEND ARGS -np ${GMX_TEST_NUMBER_PROCS}) if(MPIEXEC) list(APPEND ARGS -mpirun ${MPIEXEC}) endif() #We should use MPIEXEC_NUMPROC_FLAG but gmxtest.pl doesn't let us pass it endif() if(GMX_BINARY_SUFFIX) list(APPEND ARGS -suffix ${GMX_BINARY_SUFFIX}) endif() #crosscompile is only used to disable checking whether binaries work #given that we know they are there and that mdrun might not be executable #(e.g. Cray) we enable it. list(APPEND ARGS -crosscompile) set(REGRESSIONTEST_EXTRA_ARGS "" CACHE STRING "Extra arguments passed to gmxtest") mark_as_advanced(REGRESSIONTEST_EXTRA_ARGS) list(APPEND ARGS ${REGRESSIONTEST_EXTRA_ARGS}) if(DEFINED ENV{CI_JOB_ID} AND GMX_THREAD_MPI) set(GMX_REGRESSIONTEST_THREAD_MPI_THREADS 2 CACHE STRING "Number of thread MPI threads to use for testing") mark_as_advanced(GMX_REGRESSIONTEST_THREAD_MPI_THREADS) list(APPEND ARGS -nt ${GMX_REGRESSIONTEST_THREAD_MPI_THREADS}) endif() list(APPEND ARGS -noverbose -nosuffix) if(GMX_NATIVE_WINDOWS) set(PATH_SEPARATOR "\\;") #replacing \ with / shouldn't be neccessary. But otherwise "..\bin\;c:\.." #gets turned into "...\bin\\c:\.." don't know why and don't have a better #workaround. This workaround doesn't hurt. string(REPLACE "\\" "/" PATH "$ENV{PATH}") #protect ; (don't treat as list) string(REPLACE ";" "\\;" PATH "${PATH}") else() set(PATH_SEPARATOR ":") set(PATH "$ENV{PATH}") endif() foreach(FOLDER bin lib) #lib folders might be needed for #e.g. DLLs. For GMX paths native ("\") is needed for GMXLIB detection file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/${FOLDER}" DIR) set(PATH "${DIR}${PATH_SEPARATOR}${PATH}") endforeach() find_program(PERL_EXECUTABLE NAMES "perl") mark_as_advanced(PERL_EXECUTABLE) if (NOT PERL_EXECUTABLE) message(FATAL_ERROR "Perl not found. Install perl, set PERL_EXECUTABLE to the perl location, or unset REGRESSIONTEST_PATH to disable testing.") endif() #currently not testing tools because they don't contain any useful tests foreach(subtest complex freeenergy rotation essentialdynamics) add_test(NAME regressiontests/${subtest} #windows requires the command to be perl and not the script COMMAND perl "${REGRESSIONTEST_PATH}/gmxtest.pl" ${subtest} ${ARGS}) set_tests_properties(regressiontests/${subtest} PROPERTIES ENVIRONMENT "PATH=${PATH}") endforeach() else() gmx_add_missing_tests_notice("Regression tests have not been run. If you want to run them from the build system, get the correct version of the regression tests package and set REGRESSIONTEST_PATH in CMake to point to it, or set REGRESSIONTEST_DOWNLOAD=ON.") endif() # # Physical validation tests are opt-in via -DGMX_PHYSICAL_VALIDATION=ON # if(GMX_PHYSICAL_VALIDATION) include(FindPythonModule) # physical validation suite is distributed with the source set(PHYSVALTEST_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/physicalvalidation") # CACHE PATH "Source directory containing physical validation tests.") if(NOT EXISTS ${PHYSVALTEST_SOURCE_PATH}/gmx_physicalvalidation.py) message(FATAL_ERROR "GMX_PHYSICAL_VALIDATION set, but physical validation script not found in ${PHYSVALTEST_SOURCE_PATH}.") endif() if(CMAKE_CROSSCOMPILING OR CMAKE_CONFIGURATION_TYPES) # The following comment is copied from regression tests: # Cross-compiling toolchains require us to compile both front-end and # back-end binaries to run gmxtest.pl. # TODO: Look into the details of this. # For now, turn it off - our python-gmx interface is probably not that stable for special cases anyway message(WARNING "With cross-compiling or multi-configuration generators (e.g. Visual Studio),\ running physical validation tests from build system is not supported.\ Please run physicalvalidation.py directly.") set(GMX_PHYSICAL_VALIDATION OFF CACHE BOOL "With cross-compiling or multi-configuration generators, running physical validation tests from build\ system is not supported." FORCE) else() # # Making sure gmx is built before running physical validation tests # add_dependencies(run-ctest-phys gmx) add_dependencies(run-ctest gmx) # # Determine arguments passed to physicalvalidation.py # set(PARGS "") list(APPEND PARGS --wd ${CMAKE_CURRENT_BINARY_DIR}/physicalvalidation) list(APPEND PARGS --bindir ${CMAKE_BINARY_DIR}/bin) if(GMX_LIB_MPI AND NOT MPIEXEC) # find_program failed message(WARNING "Please set MPIEXEC. Otherwise mpirun is assumed for running tests.") endif() if(GMX_LIB_MPI) # define number of processors in analogy to regression tests? if(MPIEXEC) list(APPEND ARGS --mpicmd ${MPIEXEC}) else() list(APPEND ARGS --mpicmd mpirun) endif() endif() if(GMX_LIB_MPI) message(FATAL_ERROR "Physical validation using MPI not supported.") endif() if(GMX_BINARY_SUFFIX) list(APPEND PARGS --suffix ${GMX_BINARY_SUFFIX}) endif() # # Give possibility to add args via cache # set(PHYSVALTEST_EXTRA_ARGS "" CACHE STRING "Extra arguments passed to phystest") mark_as_advanced(PHYSVALTEST_EXTRA_ARGS) list(APPEND PARGS ${PHYSVALTEST_EXTRA_ARGS}) # # The following lines are directly copied from regression tests. # They seem to be applicable to physical validation tests as well. # if(GMX_NATIVE_WINDOWS) set(PATH_SEPARATOR "\\;") #replacing \ with / shouldn't be neccessary. But otherwise "..\bin\;c:\.." #gets turned into "...\bin\\c:\.." don't know why and don't have a better #workaround. This workaround doesn't hurt. string(REPLACE "\\" "/" PATH "$ENV{PATH}") #protect ; (don't treat as list) string(REPLACE ";" "\\;" PATH "${PATH}") else() set(PATH_SEPARATOR ":") set(PATH "$ENV{PATH}") endif() foreach(FOLDER bin lib) #lib folders might be needed for #e.g. DLLs. For GMX paths native ("\") is needed for GMXLIB detection file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/${FOLDER}" DIR) set(PATH "${DIR}${PATH_SEPARATOR}${PATH}") endforeach() # # End copied from regression tests. # if (NOT Python3_Interpreter_FOUND) message(FATAL_ERROR "Python not found. Physical validation requires python. \ Install python, set Python3_ROOT_DIR or PYTHON_EXECUTABLE to a valid location, \ or set GMX_PHYSICAL_VALIDATION=OFF to disable the physical validation tests.") endif() # foreach(module numpy scipy pymbar) # add further modules if necessary find_python_module(${module}) string(TOUPPER ${module} module_upper) if(NOT PYTHONMODULE_${module_upper}) message(WARNING "Python module ${module} not found. Physical validation relies on ${module}. Make sure\ ${module} can be found by PYTHON_EXECUTABLE, or set GMX_PHYSICAL_VALIDATION=OFF to disable\ the physical validation tests.") endif() endforeach() # # Hook in our own tests # Read them from json file to make every system a separate test # if (GMX_DOUBLE) set(PHYSVALTEST_JSON "${PHYSVALTEST_SOURCE_PATH}/systems_d.json") else() set(PHYSVALTEST_JSON "${PHYSVALTEST_SOURCE_PATH}/systems.json") endif() file(STRINGS "${PHYSVALTEST_JSON}" json) string(REPLACE "\"" "" json ${json}) string(REPLACE "," "" json ${json}) string(REPLACE " " "" json ${json}) string(REPLACE ";" "<<>>" json ${json}) string(REPLACE "[" "" json ${json}) string(REPLACE "]" "" json ${json}) string(REPLACE "{" "" json ${json}) string(REPLACE "}" "" json ${json}) string(REPLACE "<<>>" ";" json ${json}) foreach(line ${json}) if("${line}" MATCHES "name:") string(REPLACE "name:" "" testname ${line}) add_test(NAME physicalvalidationtests/${testname} COMMAND ${PYTHON_EXECUTABLE} "${PHYSVALTEST_SOURCE_PATH}/gmx_physicalvalidation.py" "${PHYSVALTEST_JSON}" -s ${testname} -a ${PARGS}) set_tests_properties(physicalvalidationtests/${testname} PROPERTIES ENVIRONMENT "PATH=${PATH}" LABELS "PhysicalValidationTest") endif() endforeach() # # Create prepare and run targets while all variables are set # Will be referenced in CheckTarget.cmake # # "check-phys-prepare" prepares the systems needed for physical validation for external running add_custom_target(check-phys-prepare COMMAND ${PYTHON_EXECUTABLE} "${PHYSVALTEST_SOURCE_PATH}/gmx_physicalvalidation.py" "${PHYSVALTEST_JSON}" -p ${PARGS} COMMENT "Preparing systems for physical validation" DEPENDS gmx) # "run-physval-sims" prepares and runs the systems needed for physical validation add_custom_target(run-physval-sims COMMAND ${PYTHON_EXECUTABLE} "${PHYSVALTEST_SOURCE_PATH}/gmx_physicalvalidation.py" "${PHYSVALTEST_JSON}" -r ${PARGS} COMMENT "Preparing and running systems for physical validation" DEPENDS gmx) endif() else() # # Create dummy prepare and run targets # Will be referenced in CheckTarget.cmake # # "check-phys-prepare" prepares the systems needed for physical validation for external running add_custom_target(check-phys-prepare COMMAND ${CMAKE_COMMAND} -E echo "NOTE: You called the target `check-phys-prepare`, but ran cmake with\ `-DGMX_PHYSICAL_VALIDATION=OFF`. The physical validation tests are therefore unavailable,\ and this target is not doing anything." COMMENT "No physical validation" VERBATIM) # "run-physval-sims" prepares and runs the systems needed for physical validation add_custom_target(run-physval-sims COMMAND ${CMAKE_COMMAND} -E echo "NOTE: You called the target `run-physval-sims`, but ran cmake with\ `-DGMX_PHYSICAL_VALIDATION=OFF`. The physical validation tests are therefore unavailable,\ and this target is not doing anything." COMMENT "No physical validation" VERBATIM) endif() gmx_create_missing_tests_notice_target()