Merge branch 'origin/release-2020' into master
[alexxy/gromacs.git] / src / testutils / TestMacros.cmake
index 1c4e0d71af97a5f7708fe24e4bf0ed80df9a5021..d668cb5d9c92e091fea6daa099d8cf130aee9de1 100644 (file)
@@ -1,7 +1,8 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+# Copyright (c) 2016,2017,2018,2019,2020, 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.
@@ -33,6 +34,7 @@
 # the research papers on the package. Check out http://www.gromacs.org.
 
 include(CMakeParseArguments)
+include(gmxClangCudaUtils)
 
 function (gmx_add_unit_test_library NAME)
     if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
@@ -41,21 +43,52 @@ function (gmx_add_unit_test_library NAME)
         target_compile_definitions(${NAME} PRIVATE HAVE_CONFIG_H)
         target_include_directories(${NAME} SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
         target_link_libraries(${NAME} PRIVATE testutils gmock)
-        # clang-3.6 warns about a number of issues that are not reported by more modern compilers
-        # and we know they are not real issues. So we only check that it can compile without error
-        # but ignore all warnings.
-        if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^3\.6")
-            target_compile_options(${NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-w>)
+        if(GMX_CLANG_TIDY)
+            set_target_properties(${NAME} PROPERTIES CXX_CLANG_TIDY
+                "${CLANG_TIDY_EXE};-warnings-as-errors=*;-header-filter=.*")
+        endif()
+        if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7")
+            target_compile_options(${NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Weverything ${IGNORED_CLANG_ALL_WARNINGS} -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-as-null-pointer-constant -Wno-missing-variable-declarations>)
         endif()
 
     endif()
 endfunction ()
 
+# This function creates a GoogleTest test executable for a module.  It
+# hides all the complexity of how to treat different source files
+# under different configuration conditions. It should be extended
+# if we ever support another GPU compilation approach.
+#
+# It can be called with extra options and arguments:
+#   MPI
+#     To trigger the ctest runner to run this test with multiple ranks
+#   HARDWARE_DETECTION
+#     To trigger the test executable setup code to run hardware detection
+#   CPP_SOURCE_FILES          file1.cpp file2.cpp ...
+#     All the normal C++ .cpp source files
+#   GPU_CPP_SOURCE_FILES  file1.cpp file2.cpp ...
+#     All the C++ .cpp source files that are always needed, but must be
+#     compiled in the way that suits GMX_GPU.
+#   CUDA_CU_SOURCE_FILES      file1.cu  file2.cu  ...
+#     All the normal CUDA .cu source files
+#   CUDA_CPP_SOURCE_FILES     file1.cpp file2.cpp ...
+#     All the other .cpp source files to be compiled as CUDA
+#   OPENCL_CPP_SOURCE_FILES   file1.cpp file2.cpp ...
+#     All the other C++ .cpp source files needed only with OpenCL
+#   NON_GPU_CPP_SOURCE_FILES  file1.cpp file2.cpp ...
+#     All the other C++ .cpp source files needed only with neither OpenCL nor CUDA
 function (gmx_add_gtest_executable EXENAME)
     if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
         set(_options MPI HARDWARE_DETECTION)
-        cmake_parse_arguments(ARG "${_options}" "" "" ${ARGN})
-        set(_source_files ${ARG_UNPARSED_ARGUMENTS})
+        set(_multi_value_keywords
+            CPP_SOURCE_FILES
+            CUDA_CU_SOURCE_FILES
+            GPU_CPP_SOURCE_FILES
+            CUDA_CPP_SOURCE_FILES
+            OPENCL_CPP_SOURCE_FILES
+            NON_GPU_CPP_SOURCE_FILES
+            )
+        cmake_parse_arguments(ARG "${_options}" "" "${_multi_value_keywords}" ${ARGN})
 
         file(RELATIVE_PATH _input_files_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
         set(_temporary_files_path "${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary")
@@ -79,8 +112,43 @@ function (gmx_add_gtest_executable EXENAME)
                  TEST_USES_HARDWARE_DETECTION=true)
         endif()
 
-        add_executable(${EXENAME} ${UNITTEST_TARGET_OPTIONS}
-            ${_source_files} ${TESTUTILS_DIR}/unittest_main.cpp)
+        if (GMX_USE_CUDA AND NOT GMX_CLANG_CUDA)
+            # Work around FindCUDA that prevents using target_link_libraries()
+            # with keywords otherwise...
+            set(CUDA_LIBRARIES PRIVATE ${CUDA_LIBRARIES})
+            cuda_add_executable(${EXENAME} ${UNITTEST_TARGET_OPTIONS}
+                ${ARG_CPP_SOURCE_FILES}
+                ${ARG_CUDA_CU_SOURCE_FILES}
+                ${ARG_CUDA_CPP_SOURCE_FILES}
+                ${ARG_GPU_CPP_SOURCE_FILES}
+                ${TESTUTILS_DIR}/unittest_main.cpp)
+        else()
+            add_executable(${EXENAME} ${UNITTEST_TARGET_OPTIONS}
+                ${ARG_CPP_SOURCE_FILES}
+                ${TESTUTILS_DIR}/unittest_main.cpp)
+        endif()
+
+        if (GMX_USE_CUDA)
+            if (GMX_CLANG_CUDA)
+                target_sources(${EXENAME} PRIVATE
+                    ${ARG_CUDA_CU_SOURCE_FILES}
+                    ${ARG_CUDA_CPP_SOURCE_FILES}
+                    ${ARG_GPU_CPP_SOURCE_FILES})
+                set_source_files_properties(${ARG_CUDA_CPP_SOURCE_FILES} ${ARG_GPU_CPP_SOURCE_FILES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
+                gmx_compile_cuda_file_with_clang(${ARG_CUDA_CU_SOURCE_FILES})
+                if(ARG_CUDA_CPP_SOURCE_FILES OR ARG_CUDA_CU_SOURCE_FILES OR ARG_GPU_CPP_SOURCE_FILES)
+                    target_link_libraries(${EXENAME} PRIVATE ${GMX_EXTRA_LIBRARIES})
+                endif()
+            endif()
+        elseif (GMX_USE_OPENCL)
+            target_sources(${EXENAME} PRIVATE ${ARG_OPENCL_CPP_SOURCE_FILES} ${ARG_GPU_CPP_SOURCE_FILES})
+            if(ARG_OPENCL_CPP_SOURCE_FILES OR ARG_GPU_CPP_SOURCE_FILES)
+                target_link_libraries(${EXENAME} PRIVATE ${OpenCL_LIBRARIES})
+            endif()
+        else()
+            target_sources(${EXENAME} PRIVATE ${ARG_NON_GPU_CPP_SOURCE_FILES} ${ARG_GPU_CPP_SOURCE_FILES})
+        endif()
+
         gmx_target_compile_options(${EXENAME})
         target_compile_definitions(${EXENAME} PRIVATE HAVE_CONFIG_H ${EXTRA_COMPILE_DEFINITIONS})
         target_include_directories(${EXENAME} SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
@@ -98,7 +166,7 @@ function (gmx_add_gtest_executable EXENAME)
             set_target_properties(${EXENAME} PROPERTIES CXX_CLANG_TIDY
                 "${CLANG_TIDY_EXE};-warnings-as-errors=*;-header-filter=.*")
         endif()
-        if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^6\.0")
+        if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7")
             target_compile_options(${EXENAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Weverything ${IGNORED_CLANG_ALL_WARNINGS} -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-as-null-pointer-constant -Wno-missing-variable-declarations>)
         endif()
         # clang-3.6 warns about a number of issues that are not reported by more modern compilers
@@ -117,13 +185,14 @@ endfunction()
 #   INTEGRATION_TEST      requires the use of the IntegrationTest label in CTest
 #   SLOW_TEST             requires the use of the SlowTest label in CTest, and
 #                         increase the length of the ctest timeout.
+#   IGNORE_LEAKS          Skip some memory safety checks.
 #
 # TODO When a test case needs it, generalize the MPI_RANKS mechanism so
 # that ctest can run the test binary over a range of numbers of MPI
 # ranks.
 function (gmx_register_gtest_test NAME EXENAME)
     if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
-        set(_options INTEGRATION_TEST SLOW_TEST)
+        set(_options INTEGRATION_TEST SLOW_TEST IGNORE_LEAKS)
         set(_one_value_args MPI_RANKS OPENMP_THREADS)
         cmake_parse_arguments(ARG "${_options}" "${_one_value_args}" "" ${ARGN})
         set(_xml_path ${CMAKE_BINARY_DIR}/Testing/Temporary/${NAME}.xml)
@@ -142,15 +211,16 @@ function (gmx_register_gtest_test NAME EXENAME)
             else()
                 set(_timeout 120)
             endif()
-            gmx_get_test_prefix_cmd(_prefix_cmd IGNORE_LEAKS)
         elseif (ARG_SLOW_TEST)
             list(APPEND _labels SlowTest)
             set(_timeout 480)
-            gmx_get_test_prefix_cmd(_prefix_cmd IGNORE_LEAKS)
         else()
             list(APPEND _labels UnitTest)
             gmx_get_test_prefix_cmd(_prefix_cmd)
         endif()
+        if (ARG_IGNORE_LEAKS)
+            gmx_get_test_prefix_cmd(_prefix_cmd IGNORE_LEAKS)
+        endif ()
         set(_cmd ${_prefix_cmd} $<TARGET_FILE:${EXENAME}>)
         if (ARG_OPENMP_THREADS)
             if (GMX_OPENMP)