diff options
author | Brad King <brad.king@kitware.com> | 2024-09-27 20:38:44 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2024-09-27 20:45:24 (GMT) |
commit | 8f4cea94da32a2eb3c4603ce7af166eff50982fa (patch) | |
tree | e421ed56083ccb5f1eedbbb930cb3f0c118c16fe | |
parent | f8ed4d7c21e5835682cb0ebea12cfeaa35c62232 (diff) | |
download | CMake-8f4cea94da32a2eb3c4603ce7af166eff50982fa.zip CMake-8f4cea94da32a2eb3c4603ce7af166eff50982fa.tar.gz CMake-8f4cea94da32a2eb3c4603ce7af166eff50982fa.tar.bz2 |
FindOpenMP: Add support for CUDA when supported by the toolchain
NVCC supports OpenMP on the host when the host compiler does.
-rw-r--r-- | .gitlab/ci/configure_cuda12.2_nvidia_common.cmake | 2 | ||||
-rw-r--r-- | Help/release/dev/FindOpenMP-CUDA.rst | 5 | ||||
-rw-r--r-- | Modules/FindOpenMP.cmake | 44 | ||||
-rw-r--r-- | Tests/FindOpenMP/CMakeLists.txt | 6 | ||||
-rw-r--r-- | Tests/FindOpenMP/Test/CMakeLists.txt | 13 |
5 files changed, 56 insertions, 14 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/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 d01b7e4..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,7 +157,11 @@ function(_OPENMP_FLAG_CANDIDATES LANG) set(OMP_FLAG_Fujitsu "-Kopenmp" "-KOMP") set(OMP_FLAG_FujitsuClang "-fopenmp" "-Kopenmp") - set(compiler_id "${CMAKE_${LANG}_COMPILER_ID}") + 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_${compiler_id}) @@ -206,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) @@ -227,11 +238,24 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) 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_FLAG}" ${_includeDirFlags} - LINK_OPTIONS ${OpenMP_VERBOSE_OPTIONS} + LINK_OPTIONS ${OpenMP_VERBOSE_OPTIONS} ${_OpenMP_LINK_OPTIONS} OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT ) @@ -282,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) @@ -302,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. @@ -489,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") @@ -555,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() @@ -634,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() @@ -656,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() |