diff options
-rw-r--r-- | .gitlab/ci/configure_cuda12.2_nvidia_common.cmake | 2 | ||||
-rwxr-xr-x | .gitlab/ci/docker/cuda12.2/install_deps.sh | 1 | ||||
-rw-r--r-- | .gitlab/os-linux.yml | 2 | ||||
-rw-r--r-- | Help/release/dev/FindOpenMP-CUDA.rst | 5 | ||||
-rw-r--r-- | Modules/FindOpenMP.cmake | 78 | ||||
-rw-r--r-- | Tests/FindOpenMP/CMakeLists.txt | 6 | ||||
-rw-r--r-- | Tests/FindOpenMP/Test/CMakeLists.txt | 13 |
7 files changed, 70 insertions, 37 deletions
diff --git a/.gitlab/ci/configure_cuda12.2_nvidia_common.cmake b/.gitlab/ci/configure_cuda12.2_nvidia_common.cmake index 51a2511..5dc1788 100644 --- a/.gitlab/ci/configure_cuda12.2_nvidia_common.cmake +++ b/.gitlab/ci/configure_cuda12.2_nvidia_common.cmake @@ -1,5 +1,7 @@ set(CMake_TEST_CUDA "NVIDIA" CACHE STRING "") set(CMake_TEST_CUDA_CUPTI "ON" CACHE STRING "") set(CMake_TEST_CUDA_STANDARDS "03;11;14;17;20" CACHE STRING "") +set(CMake_TEST_FindOpenMP "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenMP_CUDA "ON" CACHE BOOL "") include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/docker/cuda12.2/install_deps.sh b/.gitlab/ci/docker/cuda12.2/install_deps.sh index 94fbd98..4708277 100755 --- a/.gitlab/ci/docker/cuda12.2/install_deps.sh +++ b/.gitlab/ci/docker/cuda12.2/install_deps.sh @@ -14,6 +14,7 @@ env DEBIAN_FRONTEND=noninteractive \ apt-get install -y \ g++ \ clang-18 \ + libomp-18-dev \ curl \ git diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index fbe6720..3edef20 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -396,7 +396,7 @@ .cuda12.2: extends: .cuda - image: "kitware/cmake:ci-cuda12.2-x86_64-2024-04-05" + image: "kitware/cmake:ci-cuda12.2-x86_64-2024-09-25" variables: CMAKE_ARCH: x86_64 diff --git a/Help/release/dev/FindOpenMP-CUDA.rst b/Help/release/dev/FindOpenMP-CUDA.rst new file mode 100644 index 0000000..3880855 --- /dev/null +++ b/Help/release/dev/FindOpenMP-CUDA.rst @@ -0,0 +1,5 @@ +FindOpenMP-CUDA +--------------- + +* The :module:`FindOpenMP` module gained support for ``CUDA`` when using + a CUDA compiler that supports OpenMP on the host. diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index f88e43c..32e4cf2 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -37,6 +37,10 @@ Result Variables The module exposes the components ``C``, ``CXX``, and ``Fortran``. Each of these controls the various languages to search OpenMP support for. +.. versionadded:: 3.31 + The ``CUDA`` language component is supported when using a CUDA compiler + that supports OpenMP on the host. + Depending on the enabled components the following variables will be set: ``OpenMP_FOUND`` @@ -48,7 +52,7 @@ Depending on the enabled components the following variables will be set: or all enabled languages if no components were specified. This module will set the following variables per language in your -project, where ``<lang>`` is one of C, CXX, or Fortran: +project, where ``<lang>`` is one of C, CXX, CUDA, or Fortran: ``OpenMP_<lang>_FOUND`` Variable indicating if OpenMP support for ``<lang>`` was detected. @@ -153,11 +157,17 @@ function(_OPENMP_FLAG_CANDIDATES LANG) set(OMP_FLAG_Fujitsu "-Kopenmp" "-KOMP") set(OMP_FLAG_FujitsuClang "-fopenmp" "-Kopenmp") + if(CMAKE_${LANG}_COMPILER_ID STREQUAL "NVIDIA" AND CMAKE_${LANG}_HOST_COMPILER_ID) + set(compiler_id "${CMAKE_${LANG}_HOST_COMPILER_ID}") + else() + set(compiler_id "${CMAKE_${LANG}_COMPILER_ID}") + endif() + # If we know the correct flags, use those - if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}) - set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}") - # Fall back to reasonable default tries otherwise + if(DEFINED OMP_FLAG_${compiler_id}) + set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${compiler_id}}") else() + # Fall back to reasonable default tries otherwise set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ") endif() set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE) @@ -204,6 +214,9 @@ macro(_OPENMP_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VA elseif("${LANG}" STREQUAL "CXX") set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp") set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}") + elseif("${LANG}" STREQUAL "CUDA") + set(${FULLNAME_VAR} "${NAME_PREFIX}.cu") + set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}") elseif("${LANG}" STREQUAL "Fortran") set(${FULLNAME_VAR} "${NAME_PREFIX}.F90") string(CONFIGURE "${OpenMP_Fortran_${CONTENT_ID}}" ${CONTENT_VAR} @ONLY) @@ -217,29 +230,32 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) _OPENMP_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenMPTryFlag _OPENMP_TEST_SRC_NAME _OPENMP_TEST_SRC_CONTENT) - unset(OpenMP_VERBOSE_COMPILE_OPTIONS) separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}") - foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS) - if(NOT _VERBOSE_OPTION MATCHES "^-Wl,") - list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION}) - endif() - endforeach() foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES) - set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}") - if(OpenMP_VERBOSE_COMPILE_OPTIONS) - string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}") - endif() string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") unset(_includeDirFlags) if(OpenMP_${LANG}_INCLUDE_DIR) set(_includeDirFlags "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}") endif() + if(CMAKE_${LANG}_COMPILER_ID STREQUAL "NVIDIA") + # With NVCC we drive linking directly through the host compiler, but + # without language-wide flags since they may be specific to nvcc. + # Pass the candidate OpenMP flag to the host compiler when linking. + set(_OpenMP_LINK_OPTIONS "${OPENMP_FLAG}") + # Exclude CUDA runtime libraries that we may add ourselves. + # See the Compiler/NVIDIA module. Do not exclude pthread, + # as that is typically a dependency of OpenMP too. + set(_OpenMP_EXCLUDE_IMPLICIT_LIBS cudart cudart_static cudadevrt rt dl) + else() + set(_OpenMP_LINK_OPTIONS "") + set(_OpenMP_EXCLUDE_IMPLICIT_LIBS "") + endif() try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT LOG_DESCRIPTION "Detecting ${LANG} OpenMP compiler info" - CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" ${_includeDirFlags} - LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAG}" ${_includeDirFlags} + LINK_OPTIONS ${OpenMP_VERBOSE_OPTIONS} ${_OpenMP_LINK_OPTIONS} OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT ) @@ -290,6 +306,7 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}") string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}") if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES + OR "${_OPENMP_IMPLICIT_LIB}" IN_LIST _OpenMP_EXCLUDE_IMPLICIT_LIBS OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) ) if(_OPENMP_IMPLICIT_LIB_DIR) @@ -310,6 +327,9 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN}) endif() endforeach() + list(REVERSE _OPENMP_LIB_NAMES) + list(REMOVE_DUPLICATES _OPENMP_LIB_NAMES) + list(REVERSE _OPENMP_LIB_NAMES) set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE) else() # We do not know how to extract implicit OpenMP libraries for this compiler. @@ -336,8 +356,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT LOG_DESCRIPTION "Trying ${LANG} OpenMP compiler with '${OpenMP_libomp_LIBRARY}'" - CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" - LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} + COMPILE_DEFINITIONS ${OPENMP_FLAG} + LINK_LIBRARIES ${OpenMP_libomp_LIBRARY} ) if(NOT OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) find_path(OpenMP_${LANG}_INCLUDE_DIR omp.h) @@ -347,9 +367,9 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT LOG_DESCRIPTION "Trying ${LANG} OpenMP compiler with '${OpenMP_libomp_LIBRARY}' and '${OpenMP_${LANG}_INCLUDE_DIR}'" - CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" - "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}" - LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}" + COMPILE_DEFINITIONS ${OPENMP_FLAG} + LINK_LIBRARIES ${OpenMP_libomp_LIBRARY} ) endif() endif() @@ -370,8 +390,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT LOG_DESCRIPTION "Trying ${LANG} OpenMP compiler with '${OpenMP_libomp_LIBRARY}'" - CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" - LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} + COMPILE_DEFINITIONS ${OPENMP_FLAG} + LINK_LIBRARIES ${OpenMP_libomp_LIBRARY} ) if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) @@ -383,8 +403,6 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE) set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE) endforeach() - - unset(OpenMP_VERBOSE_COMPILE_OPTIONS) endfunction() set(OpenMP_C_CXX_CHECK_VERSION_SOURCE @@ -499,7 +517,7 @@ macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG) unset(OpenMP_SPEC_DATE_MAP) endmacro() -foreach(LANG IN ITEMS C CXX) +foreach(LANG IN ITEMS C CXX CUDA) if(CMAKE_${LANG}_COMPILER_LOADED) if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND" OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") @@ -565,7 +583,7 @@ if(CMAKE_Fortran_COMPILER_LOADED) endif() if(NOT OpenMP_FIND_COMPONENTS) - set(OpenMP_FINDLIST C CXX Fortran) + set(OpenMP_FINDLIST C CXX CUDA Fortran) else() set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS}) endif() @@ -644,7 +662,7 @@ foreach(LANG IN LISTS OpenMP_FINDLIST) endforeach() unset(_OpenMP_REQ_VARS) -foreach(LANG IN ITEMS C CXX Fortran) +foreach(LANG IN ITEMS C CXX CUDA Fortran) if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS) list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND") endif() @@ -666,8 +684,8 @@ if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND) endif() endif() -if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED )) - message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled") +if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_CUDA_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED )) + message(SEND_ERROR "FindOpenMP requires the C, CXX, CUDA, or Fortran languages to be enabled") endif() unset(OpenMP_C_CXX_TEST_SOURCE) diff --git a/Tests/FindOpenMP/CMakeLists.txt b/Tests/FindOpenMP/CMakeLists.txt index ea90baa..c8d684a 100644 --- a/Tests/FindOpenMP/CMakeLists.txt +++ b/Tests/FindOpenMP/CMakeLists.txt @@ -1,4 +1,4 @@ -foreach(c C CXX Fortran) +foreach(c C CXX CUDA Fortran) if(CMake_TEST_FindOpenMP_${c}) set(CMake_TEST_FindOpenMP_FLAG_${c} 1) else() @@ -16,9 +16,13 @@ add_test(NAME FindOpenMP.Test COMMAND --build-options ${build_options} -DOpenMP_TEST_C=${CMake_TEST_FindOpenMP_FLAG_C} -DOpenMP_TEST_CXX=${CMake_TEST_FindOpenMP_FLAG_CXX} + -DOpenMP_TEST_CUDA=${CMake_TEST_FindOpenMP_FLAG_CUDA} -DOpenMP_TEST_Fortran=${CMake_TEST_FindOpenMP_FLAG_Fortran} --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) +if(CMake_TEST_FindOpenMP_FLAG_CUDA) + set_property(TEST FindOpenMP.Test APPEND PROPERTY LABELS "CUDA") +endif() if(CMake_TEST_FindOpenMP_FLAG_Fortran) set_property(TEST FindOpenMP.Test APPEND PROPERTY LABELS "Fortran") endif() diff --git a/Tests/FindOpenMP/Test/CMakeLists.txt b/Tests/FindOpenMP/Test/CMakeLists.txt index 4083855..7b05372 100644 --- a/Tests/FindOpenMP/Test/CMakeLists.txt +++ b/Tests/FindOpenMP/Test/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.30) project(TestFindOpenMP NONE) include(CTest) @@ -8,6 +8,9 @@ macro(source_code_mapper_helper LANG_NAME SRC_FILE_NAME) elseif("${LANG_NAME}" STREQUAL "CXX") configure_file("${SRC_FILE_NAME}.c" "${SRC_FILE_NAME}.cxx" COPYONLY) set(OpenMPTEST_SOURCE_FILE "${SRC_FILE_NAME}.cxx") + elseif("${LANG_NAME}" STREQUAL "CUDA") + configure_file("${SRC_FILE_NAME}.c" "${SRC_FILE_NAME}.cu" COPYONLY) + set(OpenMPTEST_SOURCE_FILE "${SRC_FILE_NAME}.cu") elseif("${LANG_NAME}" STREQUAL "Fortran") set(OpenMPTEST_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/${SRC_FILE_NAME}.f90") if(OpenMP_Fortran_HAVE_OMPLIB_MODULE) @@ -19,7 +22,7 @@ macro(source_code_mapper_helper LANG_NAME SRC_FILE_NAME) endif() endmacro() -foreach(c C CXX Fortran) +foreach(c C CXX CUDA Fortran) if("${OpenMP_TEST_${c}}") message("Testing ${c}") enable_language(${c}) @@ -41,7 +44,7 @@ if(test_msvc_runtime) endif() endif() -foreach(c C CXX Fortran) +foreach(c C CXX CUDA Fortran) if(NOT "${OpenMP_TEST_${c}}") continue() endif() @@ -65,11 +68,11 @@ foreach(c C CXX Fortran) set_property(TARGET scalprod_${c} PROPERTY LINKER_LANGUAGE ${c}) endforeach() -foreach(c C CXX Fortran) +foreach(c C CXX CUDA Fortran) if(NOT "${OpenMP_TEST_${c}}") continue() endif() - foreach(d C CXX Fortran) + foreach(d C CXX CUDA Fortran) if(NOT "${OpenMP_TEST_${d}}") continue() endif() |