diff options
author | Brad King <brad.king@kitware.com> | 2023-09-22 13:18:43 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2023-09-22 13:18:53 (GMT) |
commit | d2655c59dc914ec24f2bca142a748612caeb9e3d (patch) | |
tree | 389ee99aeb3b58b7bc92b78398fbd9ba2f238392 /Modules | |
parent | 2dafd1f09227915197eb268cac6affdb37a24647 (diff) | |
parent | b32ea7cff050574c00b5207035762e3b24f8a405 (diff) | |
download | CMake-d2655c59dc914ec24f2bca142a748612caeb9e3d.zip CMake-d2655c59dc914ec24f2bca142a748612caeb9e3d.tar.gz CMake-d2655c59dc914ec24f2bca142a748612caeb9e3d.tar.bz2 |
Merge topic 'cuda-factor-out-lang'
b32ea7cff0 CUDA: Factor out helper to generate CUDA architecture flags
b3a1f17567 CUDA: Factor out helper to validate CMAKE_CUDA_ARCHITECTURES
8617c28221 CUDA: Factor out helper for detecting native CUDA architectures
0db0fe7958 CUDA: Factor out helper to compute all CUDA architectures
c16f1e2b93 CUDA: Factor out helper to find CUDA Toolkit for compiler
a6841a967b CUDA: Factor out helper to filter implicit link libraries
deff0e638d CUDA: Factor out helper to parse NVCC implicit compiler and linker flags
e1b2a5062f CUDA: Factor out some NVCC compiler information
...
Acked-by: Kitware Robot <kwrobot@kitware.com>
Reviewed-by: Raul Tambre <raul@tambre.ee>
Merge-request: !8816
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/CMakeCUDACompilerABI.cu | 25 | ||||
-rw-r--r-- | Modules/CMakeCompilerCUDAArch.h | 29 | ||||
-rw-r--r-- | Modules/CMakeDetermineCUDACompiler.cmake | 432 | ||||
-rw-r--r-- | Modules/CMakeTestCUDACompiler.cmake | 67 | ||||
-rw-r--r-- | Modules/CUDA/architectures.cmake | 69 | ||||
-rw-r--r-- | Modules/Compiler/NVIDIA-CUDA.cmake | 94 | ||||
-rw-r--r-- | Modules/Compiler/NVIDIA.cmake | 99 | ||||
-rw-r--r-- | Modules/Internal/CMakeCUDAArchitecturesAll.cmake | 88 | ||||
-rw-r--r-- | Modules/Internal/CMakeCUDAArchitecturesNative.cmake | 49 | ||||
-rw-r--r-- | Modules/Internal/CMakeCUDAArchitecturesValidate.cmake | 19 | ||||
-rw-r--r-- | Modules/Internal/CMakeCUDAFilterImplicitLibs.cmake | 20 | ||||
-rw-r--r-- | Modules/Internal/CMakeCUDAFindToolkit.cmake | 173 | ||||
-rw-r--r-- | Modules/Internal/CMakeNVCCFilterImplicitInfo.cmake | 16 | ||||
-rw-r--r-- | Modules/Internal/CMakeNVCCParseImplicitInfo.cmake | 149 |
14 files changed, 709 insertions, 620 deletions
diff --git a/Modules/CMakeCUDACompilerABI.cu b/Modules/CMakeCUDACompilerABI.cu index 8463e86..b04d0ec 100644 --- a/Modules/CMakeCUDACompilerABI.cu +++ b/Modules/CMakeCUDACompilerABI.cu @@ -2,11 +2,8 @@ # error "A C or C++ compiler has been selected for CUDA" #endif -#include <cstdio> - -#include <cuda_runtime.h> - #include "CMakeCompilerABI.h" +#include "CMakeCompilerCUDAArch.h" int main(int argc, char* argv[]) { @@ -19,25 +16,7 @@ int main(int argc, char* argv[]) #endif static_cast<void>(argv); - int count = 0; - if (cudaGetDeviceCount(&count) != cudaSuccess || count == 0) { - std::fprintf(stderr, "No CUDA devices found.\n"); - return -1; - } - - int found = 0; - const char* sep = ""; - for (int device = 0; device < count; ++device) { - cudaDeviceProp prop; - if (cudaGetDeviceProperties(&prop, device) == cudaSuccess) { - std::printf("%s%d%d", sep, prop.major, prop.minor); - sep = ";"; - found = 1; - } - } - - if (!found) { - std::fprintf(stderr, "No CUDA architecture detected from any devices.\n"); + if (!cmakeCompilerCUDAArch()) { // Convince the compiler that the non-zero return value depends // on the info strings so they are not optimized out. return require ? -1 : 1; diff --git a/Modules/CMakeCompilerCUDAArch.h b/Modules/CMakeCompilerCUDAArch.h new file mode 100644 index 0000000..dcb030f --- /dev/null +++ b/Modules/CMakeCompilerCUDAArch.h @@ -0,0 +1,29 @@ +#include <cstdio> + +#include <cuda_runtime.h> + +static bool cmakeCompilerCUDAArch() +{ + int count = 0; + if (cudaGetDeviceCount(&count) != cudaSuccess || count == 0) { + std::fprintf(stderr, "No CUDA devices found.\n"); + return -1; + } + + bool found = false; + const char* sep = ""; + for (int device = 0; device < count; ++device) { + cudaDeviceProp prop; + if (cudaGetDeviceProperties(&prop, device) == cudaSuccess) { + std::printf("%s%d%d", sep, prop.major, prop.minor); + sep = ";"; + found = true; + } + } + + if (!found) { + std::fprintf(stderr, "No CUDA architecture detected from any devices.\n"); + } + + return found; +} diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 53c5f78..585b2aa 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -4,13 +4,13 @@ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake) -if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR - ("${CMAKE_GENERATOR}" MATCHES "Ninja") OR - ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[9][0-9])") ) ) +if(NOT ((CMAKE_GENERATOR MATCHES "Make") OR + (CMAKE_GENERATOR MATCHES "Ninja") OR + (CMAKE_GENERATOR MATCHES "Visual Studio (1|[9][0-9])"))) message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator") endif() -if(${CMAKE_GENERATOR} MATCHES "Visual Studio") +if(CMAKE_GENERATOR MATCHES "Visual Studio") if(DEFINED ENV{CUDAHOSTCXX} OR DEFINED CMAKE_CUDA_HOST_COMPILER) message(WARNING "Visual Studio does not support specifying CUDAHOSTCXX or CMAKE_CUDA_HOST_COMPILER. Using the C++ compiler provided by Visual Studio.") endif() @@ -62,7 +62,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) - if(${CMAKE_GENERATOR} MATCHES "Visual Studio") + if(CMAKE_GENERATOR MATCHES "Visual Studio") # We will not know CMAKE_CUDA_COMPILER until the main compiler id step # below extracts it, but we do know that the compiler id will be NVIDIA. set(CMAKE_CUDA_COMPILER_ID "NVIDIA") @@ -78,176 +78,18 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) message(FATAL_ERROR "Clang with CUDA is not yet supported on Windows. See CMake issue #20776.") endif() - # Find the CUDA toolkit. We store the CMAKE_CUDA_COMPILER_TOOLKIT_ROOT, CMAKE_CUDA_COMPILER_TOOLKIT_VERSION and - # CMAKE_CUDA_COMPILER_LIBRARY_ROOT in CMakeCUDACompiler.cmake so FindCUDAToolkit can avoid searching on future - # runs and the toolkit is the same. - # This is very similar to FindCUDAToolkit, but somewhat simplified since we can issue fatal errors - # if we fail and we don't need to account for searching the libraries. - - # For NVCC we can easily deduce the SDK binary directory from the compiler path. - if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") - set(_CUDA_NVCC_EXECUTABLE "${CMAKE_CUDA_COMPILER}") - else() - # Search using CUDAToolkit_ROOT and then CUDA_PATH for equivalence with FindCUDAToolkit. - # In FindCUDAToolkit CUDAToolkit_ROOT is searched automatically due to being in a find_package(). - # First we search candidate non-default paths to give them priority. - find_program(_CUDA_NVCC_EXECUTABLE - NAMES nvcc nvcc.exe - PATHS ${CUDAToolkit_ROOT} - ENV CUDAToolkit_ROOT - ENV CUDA_PATH - PATH_SUFFIXES bin - NO_DEFAULT_PATH - ) - - # If we didn't find NVCC, then try the default paths. - find_program(_CUDA_NVCC_EXECUTABLE - NAMES nvcc nvcc.exe - PATH_SUFFIXES bin - ) - - # If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error. - if(NOT _CUDA_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT})) - set(fail_base "Could not find nvcc executable in path specified by") - - if(DEFINED CUDAToolkit_ROOT) - message(FATAL_ERROR "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}") - elseif(DEFINED ENV{CUDAToolkit_ROOT}) - message(FATAL_ERROR "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}") - endif() - endif() - - # CUDAToolkit_ROOT cmake/env variable not specified, try platform defaults. - # - # - Linux: /usr/local/cuda-X.Y - # - macOS: /Developer/NVIDIA/CUDA-X.Y - # - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y - # - # We will also search the default symlink location /usr/local/cuda first since - # if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked - # directory is the desired location. - if(NOT _CUDA_NVCC_EXECUTABLE) - if(UNIX) - if(NOT APPLE) - set(platform_base "/usr/local/cuda-") - else() - set(platform_base "/Developer/NVIDIA/CUDA-") - endif() - else() - set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v") - endif() - - # Build out a descending list of possible cuda installations, e.g. - file(GLOB possible_paths "${platform_base}*") - # Iterate the glob results and create a descending list. - set(versions) - foreach(p ${possible_paths}) - # Extract version number from end of string - string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p}) - if(IS_DIRECTORY ${p} AND p_version) - list(APPEND versions ${p_version}) - endif() - endforeach() - - # Sort numerically in descending order, so we try the newest versions first. - list(SORT versions COMPARE NATURAL ORDER DESCENDING) - - # With a descending list of versions, populate possible paths to search. - set(search_paths) - foreach(v ${versions}) - list(APPEND search_paths "${platform_base}${v}") - endforeach() - - # Force the global default /usr/local/cuda to the front on Unix. - if(UNIX) - list(INSERT search_paths 0 "/usr/local/cuda") - endif() - - # Now search for nvcc again using the platform default search paths. - find_program(_CUDA_NVCC_EXECUTABLE - NAMES nvcc nvcc.exe - PATHS ${search_paths} - PATH_SUFFIXES bin - ) - - # We are done with these variables now, cleanup. - unset(platform_base) - unset(possible_paths) - unset(versions) - unset(search_paths) - - if(NOT _CUDA_NVCC_EXECUTABLE) - message(FATAL_ERROR "Failed to find nvcc.\nCompiler ${CMAKE_CUDA_COMPILER_ID} requires the CUDA toolkit. Please set the CUDAToolkit_ROOT variable.") - endif() - endif() - endif() - - # Given that NVCC can be provided by multiple different sources (NVIDIA HPC SDK, CUDA Toolkit, distro) - # each of which has a different layout, we need to extract the CUDA toolkit root from the compiler - # itself, allowing us to support numerous different scattered toolkit layouts - execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda" - OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT) - if(_CUDA_NVCC_OUT MATCHES "\\#\\$ TOP=([^\r\n]*)") - get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_MATCH_1}" ABSOLUTE) - else() - get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY) - get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY) - endif() - - if(_CUDA_NVCC_OUT MATCHES "\\#\\$ NVVMIR_LIBRARY_DIR=([^\r\n]*)") - get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${CMAKE_MATCH_1}" ABSOLUTE) - - #We require the path to end in `/nvvm/libdevice' - if(_CUDA_NVVMIR_LIBRARY_DIR MATCHES "nvvm/libdevice$") - get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}/../.." ABSOLUTE) - set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}") - endif() - - unset(_CUDA_NVVMIR_LIBRARY_DIR) - unset(_cuda_nvvmir_dir_name) - endif() - unset(_CUDA_NVCC_OUT) + # Find the CUDA toolkit to get: + # - CMAKE_CUDA_COMPILER_TOOLKIT_VERSION + # - CMAKE_CUDA_COMPILER_TOOLKIT_ROOT + # - CMAKE_CUDA_COMPILER_LIBRARY_ROOT + # We save them in CMakeCUDACompiler.cmake so FindCUDAToolkit can + # avoid searching on future runs and the toolkit is the same. + # Match arguments with cmake_cuda_architectures_all call. + include(Internal/CMakeCUDAFindToolkit) + cmake_cuda_find_toolkit(CUDA CMAKE_CUDA_COMPILER_) set(CMAKE_CUDA_DEVICE_LINKER "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/nvlink${CMAKE_EXECUTABLE_SUFFIX}") set(CMAKE_CUDA_FATBINARY "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/fatbinary${CMAKE_EXECUTABLE_SUFFIX}") - - # In a non-scattered installation the following are equivalent to CMAKE_CUDA_COMPILER_TOOLKIT_ROOT. - # We first check for a non-scattered installation to prefer it over a scattered installation. - - # CMAKE_CUDA_COMPILER_LIBRARY_ROOT contains the device library. - if(DEFINED CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR) - set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR}") - elseif(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/nvvm/libdevice") - set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}") - elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/nvvm/libdevice") - set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda") - elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/nvvm/libdevice") - set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/cuda") - else() - message(FATAL_ERROR "Couldn't find CUDA library root.") - endif() - unset(CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR) - - # CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT contains the linking stubs necessary for device linking and other low-level library files. - if(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/nvidia-cuda-toolkit/bin/crt/link.stub") - set(CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/nvidia-cuda-toolkit") - elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/nvidia-cuda-toolkit/bin/crt/link.stub") - set(CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/nvidia-cuda-toolkit") - else() - set(CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}") - endif() - endif() - - # For regular nvcc we the toolkit version is the same as the compiler version and we can parse it from the vendor test output. - # For Clang we need to invoke nvcc to get version output. - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio") - if(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") - execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE CMAKE_CUDA_COMPILER_ID_OUTPUT) - endif() - - if(CMAKE_CUDA_COMPILER_ID_OUTPUT MATCHES [=[V([0-9]+\.[0-9]+\.[0-9]+)]=]) - set(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION "${CMAKE_MATCH_1}") - endif() endif() set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-v") @@ -269,23 +111,9 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) endif() endif() - # Rest of the code treats an empty value as equivalent to "use the defaults". - # Error out early to prevent confusing errors as a result of this. - # Note that this also catches invalid non-numerical values such as "a". - if(DEFINED CMAKE_CUDA_ARCHITECTURES) - if(CMAKE_CUDA_ARCHITECTURES STREQUAL "") - message(FATAL_ERROR "CMAKE_CUDA_ARCHITECTURES must be non-empty if set.") - elseif(CMAKE_CUDA_ARCHITECTURES AND NOT CMAKE_CUDA_ARCHITECTURES MATCHES "^([0-9]+a?(-real|-virtual)?(;[0-9]+a?(-real|-virtual)?|;)*|all|all-major|native)$") - message(FATAL_ERROR - "CMAKE_CUDA_ARCHITECTURES:\n" - " ${CMAKE_CUDA_ARCHITECTURES}\n" - "is not one of the following:\n" - " * a semicolon-separated list of integers, each optionally\n" - " followed by '-real' or '-virtual'\n" - " * a special value: all, all-major, native\n" - ) - endif() - endif() + # If the user set CMAKE_CUDA_ARCHITECTURES, validate its value. + include(Internal/CMakeCUDAArchitecturesValidate) + cmake_cuda_architectures_validate(CUDA) if(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") # Clang doesn't automatically select an architecture supported by the SDK. @@ -306,7 +134,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) CMAKE_DETERMINE_COMPILER_ID(CUDA CUDAFLAGS CMakeCUDACompilerId.cu) - if(${CMAKE_GENERATOR} MATCHES "Visual Studio") + if(CMAKE_GENERATOR MATCHES "Visual Studio") # Now that we have the path to nvcc, we can compute the toolkit root. get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER}" DIRECTORY) get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY) @@ -316,7 +144,12 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) set(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION ${CMAKE_CUDA_COMPILER_VERSION}) endif() - include(${CMAKE_ROOT}/Modules/CUDA/architectures.cmake) + include(Internal/CMakeCUDAArchitecturesAll) + # From CMAKE_CUDA_COMPILER_TOOLKIT_VERSION and CMAKE_CUDA_COMPILER_{ID,VERSION}, get: + # - CMAKE_CUDA_ARCHITECTURES_ALL + # - CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR + # Match arguments with cmake_cuda_find_toolkit call. + cmake_cuda_architectures_all(CUDA CMAKE_CUDA_COMPILER_) _cmake_find_compiler_sysroot(CUDA) endif() @@ -331,7 +164,7 @@ if(MSVC_CUDA_ARCHITECTURE_ID) "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})") endif() -if(${CMAKE_GENERATOR} MATCHES "Visual Studio") +if(CMAKE_GENERATOR MATCHES "Visual Studio") set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "") @@ -351,11 +184,12 @@ if(${CMAKE_GENERATOR} MATCHES "Visual Studio") set(_SET_CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT \"${CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT}\")") elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") - string(REGEX MATCHALL "-target-cpu sm_([0-9]+)" target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") + string(REGEX MATCHALL "-target-cpu sm_([0-9]+)" _clang_target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - foreach(cpu ${target_cpus}) - string(REGEX MATCH "-target-cpu sm_([0-9]+)" dont_care "${cpu}") - list(APPEND architectures_detected "${CMAKE_MATCH_1}") + foreach(_clang_target_cpu ${_clang_target_cpus}) + if(_clang_target_cpu MATCHES "-target-cpu sm_([0-9]+)") + list(APPEND CMAKE_CUDA_ARCHITECTURES_DEFAULT "${CMAKE_MATCH_1}") + endif() endforeach() # Find target directory when crosscompiling. @@ -411,141 +245,32 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "${_CUDA_LIBRARY_DIR}") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") -elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") - set(_nvcc_log "") - string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - if(_nvcc_output_orig MATCHES "#\\\$ +PATH= *([^\n]*)\n") - set(_nvcc_path "${CMAKE_MATCH_1}") - string(APPEND _nvcc_log " found 'PATH=' string: [${_nvcc_path}]\n") - string(REPLACE ":" ";" _nvcc_path "${_nvcc_path}") - else() - set(_nvcc_path "") - string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") - string(APPEND _nvcc_log " no 'PATH=' string found in nvcc output:${_nvcc_output_log}\n") - endif() - if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n") - set(_nvcc_libraries "${CMAKE_MATCH_1}") - string(APPEND _nvcc_log " found 'LIBRARIES=' string: [${_nvcc_libraries}]\n") - else() - set(_nvcc_libraries "") - string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") - string(APPEND _nvcc_log " no 'LIBRARIES=' string found in nvcc output:${_nvcc_output_log}\n") - endif() - - set(_nvcc_link_line "") - if(_nvcc_libraries) - # Remove variable assignments. - string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output_orig}") - # Encode [] characters that break list expansion. - string(REPLACE "[" "{==={" _nvcc_output "${_nvcc_output}") - string(REPLACE "]" "}===}" _nvcc_output "${_nvcc_output}") - # Split lines. - string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}") - foreach(line IN LISTS _nvcc_output) - set(_nvcc_output_line "${line}") - string(REPLACE "{==={" "[" _nvcc_output_line "${_nvcc_output_line}") - string(REPLACE "}===}" "]" _nvcc_output_line "${_nvcc_output_line}") - string(APPEND _nvcc_log " considering line: [${_nvcc_output_line}]\n") - if("${_nvcc_output_line}" MATCHES "^ *nvlink") - string(APPEND _nvcc_log " ignoring nvlink line\n") - elseif(_nvcc_libraries) - if("${_nvcc_output_line}" MATCHES "(@\"?((tmp/)?a\\.exe\\.res)\"?)") - set(_nvcc_link_res_arg "${CMAKE_MATCH_1}") - set(_nvcc_link_res_file "${CMAKE_MATCH_2}") - set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/${_nvcc_link_res_file}") - if(EXISTS "${_nvcc_link_res}") - file(READ "${_nvcc_link_res}" _nvcc_link_res_content) - string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}") - endif() - endif() - string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos) - if(NOT _nvcc_libraries_pos EQUAL -1) - set(_nvcc_link_line "${_nvcc_output_line}") - string(APPEND _nvcc_log " extracted link line: [${_nvcc_link_line}]\n") - endif() - endif() - endforeach() - endif() - - if(_nvcc_link_line) - if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") - set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}") - else() - #extract the compiler that is being used for linking - separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}") - list(GET _nvcc_link_line_args 0 _nvcc_host_link_launcher) - if(IS_ABSOLUTE "${_nvcc_host_link_launcher}") - string(APPEND _nvcc_log " extracted link launcher absolute path: [${_nvcc_host_link_launcher}]\n") - set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}") - else() - string(APPEND _nvcc_log " extracted link launcher name: [${_nvcc_host_link_launcher}]\n") - find_program(_nvcc_find_host_link_launcher - NAMES ${_nvcc_host_link_launcher} - PATHS ${_nvcc_path} NO_DEFAULT_PATH) - find_program(_nvcc_find_host_link_launcher - NAMES ${_nvcc_host_link_launcher}) - if(_nvcc_find_host_link_launcher) - string(APPEND _nvcc_log " found link launcher absolute path: [${_nvcc_find_host_link_launcher}]\n") - set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_find_host_link_launcher}") - else() - string(APPEND _nvcc_log " could not find link launcher absolute path\n") - set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}") - endif() - unset(_nvcc_find_host_link_launcher CACHE) - endif() - endif() - #prefix the line with cuda-fake-ld so that implicit link info believes it is - #a link line - set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}") - CMAKE_PARSE_IMPLICIT_LINK_INFO("${_nvcc_link_line}" - CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES - CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES - CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES - log - "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}" - LANGUAGE CUDA) - - # Detect CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT from the compiler by looking at which - # cudart library exists in the implicit link libraries passed to the host linker. - # This is required when a project sets the cuda runtime library as part of the - # initial flags. - if(";${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES};" MATCHES [[;cudart_static(\.lib)?;]]) - set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "STATIC") - elseif(";${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES};" MATCHES [[;cudart(\.lib)?;]]) - set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "SHARED") - else() - set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "NONE") - endif() - set(_SET_CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT - "set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT \"${CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT}\")") + # Don't leak variables unnecessarily to user code. + unset(_CUDA_INCLUDE_DIR) + unset(_CUDA_LIBRARY_DIR) + unset(_CUDA_TARGET_DIR) + unset(_CUDA_TARGET_NAME) +elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") + include(Internal/CMakeNVCCParseImplicitInfo) + # Parse CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT to get: + # - CMAKE_CUDA_ARCHITECTURES_DEFAULT + # - CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES + # - CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + # - CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES + # - CMAKE_CUDA_HOST_LINK_LAUNCHER + # - CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT + # - CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES + # Match arguments with cmake_nvcc_filter_implicit_info call in CMakeTestCUDACompiler. + cmake_nvcc_parse_implicit_info(CUDA CMAKE_CUDA_) - message(CONFIGURE_LOG - "Parsed CUDA nvcc implicit link information:\n${_nvcc_log}\n${log}\n\n") - else() - message(CONFIGURE_LOG - "Failed to parse CUDA nvcc implicit link information:\n${_nvcc_log}\n\n") - message(FATAL_ERROR "Failed to extract nvcc implicit link line.") - endif() + set(_SET_CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT + "set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT \"${CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT}\")") endif() -# CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES is detected above as the list of -# libraries that the CUDA compiler implicitly passes to the host linker. -# CMake invokes the host linker directly and so needs to pass these libraries. -# We filter out those that should not be passed unconditionally both here -# and from CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES in CMakeTestCUDACompiler. -set(CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES_EXCLUDE - # The CUDA runtime libraries are controlled by CMAKE_CUDA_RUNTIME_LIBRARY. - cudart cudart.lib - cudart_static cudart_static.lib - cudadevrt cudadevrt.lib - - # Dependencies of the CUDA static runtime library on Linux hosts. - rt - pthread - dl - ) -list(REMOVE_ITEM CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES ${CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES_EXCLUDE}) +include(Internal/CMakeCUDAFilterImplicitLibs) +# Filter out implicit link libraries that should not be passed unconditionally. +cmake_cuda_filter_implicit_libs(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES) if(CMAKE_CUDA_COMPILER_SYSROOT) string(CONCAT _SET_CMAKE_CUDA_COMPILER_SYSROOT @@ -555,55 +280,17 @@ else() set(_SET_CMAKE_CUDA_COMPILER_SYSROOT "") endif() -# Determine CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES -if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") - set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES) - string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n") - set(_nvcc_includes "${CMAKE_MATCH_1}") - string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n") - else() - set(_nvcc_includes "") - string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") - string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n") - endif() - if(_nvcc_includes) - # across all operating system each include directory is prefixed with -I - separate_arguments(_nvcc_output NATIVE_COMMAND "${_nvcc_includes}") - foreach(line IN LISTS _nvcc_output) - string(REGEX REPLACE "^-I" "" line "${line}") - get_filename_component(line "${line}" ABSOLUTE) - list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}") - endforeach() - - message(CONFIGURE_LOG - "Parsed CUDA nvcc include information:\n${_nvcc_log}\n${log}\n\n") - else() - message(CONFIGURE_LOG - "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") - endif() - - string(REGEX MATCHALL "-arch compute_([0-9]+)" target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - - foreach(cpu ${target_cpus}) - string(REGEX MATCH "-arch compute_([0-9]+)" dont_care "${cpu}") - list(APPEND architectures_detected "${CMAKE_MATCH_1}") - endforeach() -endif() - -# If the user didn't set the architectures, then set them to a default. -# If the user did, then make sure those architectures worked. +# If the user did not set CMAKE_CUDA_ARCHITECTURES, use the compiler's default. if("${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") cmake_policy(GET CMP0104 _CUDA_CMP0104) - if(NOT CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" OR _CUDA_CMP0104 STREQUAL "NEW") - set(CMAKE_CUDA_ARCHITECTURES "${architectures_detected}" CACHE STRING "CUDA architectures") - + set(CMAKE_CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES_DEFAULT}" CACHE STRING "CUDA architectures") if(NOT CMAKE_CUDA_ARCHITECTURES) message(FATAL_ERROR "Failed to detect a default CUDA architecture.\n\nCompiler output:\n${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") endif() endif() endif() +unset(CMAKE_CUDA_ARCHITECTURES_DEFAULT) # configure all variables set in this file configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in @@ -611,14 +298,5 @@ configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in @ONLY ) -# Don't leak variables unnecessarily to user code. -unset(_CUDA_INCLUDE_DIR CACHE) -unset(_CUDA_NVCC_EXECUTABLE CACHE) -unset(_CUDA_LIBRARY_DIR) -unset(_CUDA_TARGET_DIR) -unset(_CUDA_TARGET_NAME) - -unset(architectures_detected) - set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX") set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX") diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index 5779e4b..3057fe9 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -22,51 +22,10 @@ if(CMAKE_CUDA_ABI_COMPILED) set(CMAKE_CUDA_COMPILER_WORKS TRUE) message(STATUS "Check for working CUDA compiler: ${CMAKE_CUDA_COMPILER} - skipped") - # Run the test binary to detect the native architectures. - execute_process(COMMAND "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_CUDA.bin" - RESULT_VARIABLE _CUDA_ARCHS_RESULT - OUTPUT_VARIABLE _CUDA_ARCHS_OUTPUT - ERROR_VARIABLE _CUDA_ARCHS_OUTPUT - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if(_CUDA_ARCHS_RESULT EQUAL 0) - if("$ENV{CMAKE_CUDA_ARCHITECTURES_NATIVE_CLAMP}") - # Undocumented hook used by CMake's CI. - # Clamp native architecture to version range supported by this CUDA. - list(GET CMAKE_CUDA_ARCHITECTURES_ALL 0 _CUDA_ARCH_MIN) - list(GET CMAKE_CUDA_ARCHITECTURES_ALL -1 _CUDA_ARCH_MAX) - set(CMAKE_CUDA_ARCHITECTURES_NATIVE "") - foreach(_CUDA_ARCH IN LISTS _CUDA_ARCHS_OUTPUT) - if(_CUDA_ARCH LESS _CUDA_ARCH_MIN) - set(_CUDA_ARCH "${_CUDA_ARCH_MIN}") - endif() - if(_CUDA_ARCH GREATER _CUDA_ARCH_MAX) - set(_CUDA_ARCH "${_CUDA_ARCH_MAX}") - endif() - list(APPEND CMAKE_CUDA_ARCHITECTURES_NATIVE ${_CUDA_ARCH}) - endforeach() - unset(_CUDA_ARCH) - unset(_CUDA_ARCH_MIN) - unset(_CUDA_ARCH_MAX) - else() - set(CMAKE_CUDA_ARCHITECTURES_NATIVE "${_CUDA_ARCHS_OUTPUT}") - endif() - list(REMOVE_DUPLICATES CMAKE_CUDA_ARCHITECTURES_NATIVE) - list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_NATIVE APPEND "-real") - else() - if(NOT _CUDA_ARCHS_RESULT MATCHES "[0-9]+") - set(_CUDA_ARCHS_STATUS " (${_CUDA_ARCHS_RESULT})") - else() - set(_CUDA_ARCHS_STATUS "") - endif() - string(REPLACE "\n" "\n " _CUDA_ARCHS_OUTPUT " ${_CUDA_ARCHS_OUTPUT}") - message(CONFIGURE_LOG - "Detecting the CUDA native architecture(s) failed with " - "the following output:\n${_CUDA_ARCHS_OUTPUT}\n\n") - endif() - unset(_CUDA_ARCHS_EXE) - unset(_CUDA_ARCHS_RESULT) - unset(_CUDA_ARCHS_OUTPUT) + include(Internal/CMakeCUDAArchitecturesNative) + # Run the test binary to get: + # - CMAKE_CUDA_ARCHITECTURES_NATIVE + cmake_cuda_architectures_native(CUDA) endif() # This file is used by EnableLanguage in cmGlobalGenerator to @@ -114,22 +73,14 @@ if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES "${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}") endif() +include(Internal/CMakeCUDAFilterImplicitLibs) # Filter out implicit link libraries that should not be passed unconditionally. -# See CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES_EXCLUDE in CMakeDetermineCUDACompiler. -list(REMOVE_ITEM CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES ${CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES_EXCLUDE}) +cmake_cuda_filter_implicit_libs(CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES) if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") - # Remove the CUDA Toolkit include directories from the set of - # implicit system include directories. - # This resolves the issue that NVCC doesn't specify these - # includes as SYSTEM includes when compiling device code, and sometimes - # they contain headers that generate warnings, so let users mark them - # as SYSTEM explicitly - if(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES) - list(REMOVE_ITEM CMAKE_CUDA_IMPLICIT_INCLUDE_DIRECTORIES - ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES} - ) - endif() + include(Internal/CMakeNVCCFilterImplicitInfo) + # Match arguments with cmake_nvcc_parse_implicit_info call in CMakeDetermineCUDACompiler. + cmake_nvcc_filter_implicit_info(CUDA CMAKE_CUDA_) endif() # Re-configure to save learned information. diff --git a/Modules/CUDA/architectures.cmake b/Modules/CUDA/architectures.cmake deleted file mode 100644 index 7d6a6e0..0000000 --- a/Modules/CUDA/architectures.cmake +++ /dev/null @@ -1,69 +0,0 @@ -# See supported GPUs on Wikipedia -# https://en.wikipedia.org/wiki/CUDA#GPUs_supported - -# Initial set based on CUDA 7.0. -set(CMAKE_CUDA_ARCHITECTURES_ALL 20 21 30 35 37 50 52 53) -set(CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 20 30 35 50) - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 8.0) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 60 61 62) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 60) -endif() - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 9.0) - if(NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 70 72) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 70) - endif() - - list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 20 21) - list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 20) -endif() - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 10.0 - AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 75) -endif() - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.0) - if(NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 80) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 80) - endif() - - list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 30) - list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 30) -endif() - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.1 - AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0)) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 86) -endif() - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.4 - AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang")) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 87) -endif() - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.8 - AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang")) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 89 90) - list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 90) -endif() - -if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 12.0 - AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang")) - list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 35 37) - list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 35) -endif() - -# only generate jit code for the newest arch for all/all-major -list(POP_BACK CMAKE_CUDA_ARCHITECTURES_ALL _latest_arch) -list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_ALL APPEND "-real") -list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL ${_latest_arch}) - -list(POP_BACK CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR _latest_arch) -list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR APPEND "-real") -list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR ${_latest_arch}) - -unset(_latest_arch) diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index 13d8d8e..93ad182 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -1,11 +1,9 @@ include(Compiler/NVIDIA) __compiler_nvidia_cxx_standards(CUDA) +__compiler_nvidia_cuda_flags(CUDA) set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True) -set(CMAKE_CUDA_VERBOSE_FLAG "-v") -set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") -set(_CMAKE_COMPILE_AS_CUDA_FLAG "-x cu") set(_CMAKE_CUDA_WHOLE_FLAG "-c") set(_CMAKE_CUDA_RDC_FLAG "-rdc=true") set(_CMAKE_CUDA_PTX_FLAG "-ptx") @@ -15,101 +13,11 @@ if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.7.0") set(_CMAKE_CUDA_OPTIX_FLAG "-optix-ir") endif() -if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) - # The -forward-unknown-to-host-compiler flag was only - # added to nvcc in 10.2 so before that we had no good - # way to invoke the CUDA compiler and propagate unknown - # flags such as -pthread to the host compiler - set(_CMAKE_CUDA_EXTRA_FLAGS "-forward-unknown-to-host-compiler") -else() - set(_CMAKE_CUDA_EXTRA_FLAGS "") -endif() - -if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") - set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") -else() - set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") -endif() - -if(CMAKE_CUDA_HOST_COMPILER AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") - string(APPEND _CMAKE_CUDA_EXTRA_FLAGS " -ccbin=<CMAKE_CUDA_HOST_COMPILER>") -endif() - -if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) - # Starting in 10.2, nvcc supported treating all warnings as errors - set(CMAKE_CUDA_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror" "all-warnings") -endif() - -if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) - # The -MD flag was only added to nvcc in 10.2 so - # before that we had to invoke the compiler twice - # to get header dependency information - set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") -else() - set(CMAKE_CUDA_DEPENDS_EXTRA_COMMANDS "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M <SOURCE> -MT <OBJECT> -o <DEP_FILE>") -endif() -set(CMAKE_CUDA_DEPFILE_FORMAT gcc) -if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) - AND CMAKE_GENERATOR MATCHES "Makefiles|WMake") - set(CMAKE_CUDA_DEPENDS_USE_COMPILER TRUE) -endif() - if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.2) - set(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE YES) - set(_CMAKE_CUDA_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) - set(CMAKE_CUDA_DEVICE_LINK_OPTIONS_IPO " -dlto") endif() -if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") - set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE) - set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC) - set(CMAKE_CUDA_COMPILE_OPTIONS_VISIBILITY -Xcompiler=-fvisibility=) - # CMAKE_SHARED_LIBRARY_CUDA_FLAGS is sent to the host linker so we - # don't need to forward it through nvcc. - set(CMAKE_SHARED_LIBRARY_CUDA_FLAGS -fPIC) - string(APPEND CMAKE_CUDA_FLAGS_INIT " ") - string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -g") - string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") - string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") - string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") -endif() - -set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared) -set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA "-isystem ") - -if (CMAKE_CUDA_SIMULATE_ID STREQUAL "GNU") - set(CMAKE_CUDA_LINKER_WRAPPER_FLAG "-Wl,") - set(CMAKE_CUDA_LINKER_WRAPPER_FLAG_SEP ",") -elseif(CMAKE_CUDA_SIMULATE_ID STREQUAL "Clang") - set(CMAKE_CUDA_LINKER_WRAPPER_FLAG "-Xlinker" " ") - set(CMAKE_CUDA_LINKER_WRAPPER_FLAG_SEP) -endif() - set(CMAKE_CUDA_DEVICE_COMPILER_WRAPPER_FLAG "-Xcompiler=") set(CMAKE_CUDA_DEVICE_COMPILER_WRAPPER_FLAG_SEP ",") set(CMAKE_CUDA_DEVICE_LINKER_WRAPPER_FLAG "-Xlinker=") set(CMAKE_CUDA_DEVICE_LINKER_WRAPPER_FLAG_SEP ",") - -set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static") -set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "cudadevrt;cudart") -set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_NONE "") - -if(UNIX AND NOT (CMAKE_SYSTEM_NAME STREQUAL "QNX")) - list(APPEND CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl") -endif() - -if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0") - set(CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG "--options-file ") - set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ") -endif() - -if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0") - set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 1) - set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 1) - set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 1) -else() - set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0) - set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0) - set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0) -endif() diff --git a/Modules/Compiler/NVIDIA.cmake b/Modules/Compiler/NVIDIA.cmake index 686c03d..a126c57 100644 --- a/Modules/Compiler/NVIDIA.cmake +++ b/Modules/Compiler/NVIDIA.cmake @@ -67,3 +67,102 @@ macro(__compiler_nvidia_cxx_standards lang) __compiler_check_default_language_standard(${lang} 6.0 03) endmacro() + +macro(__compiler_nvidia_cuda_flags lang) + set(CMAKE_${lang}_VERBOSE_FLAG "-v") + set(CMAKE_${lang}_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") + set(_CMAKE_COMPILE_AS_${lang}_FLAG "-x cu") + + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) + # The -forward-unknown-to-host-compiler flag was only + # added to nvcc in 10.2 so before that we had no good + # way to invoke the NVCC compiler and propagate unknown + # flags such as -pthread to the host compiler + set(_CMAKE_${lang}_EXTRA_FLAGS "-forward-unknown-to-host-compiler") + else() + set(_CMAKE_${lang}_EXTRA_FLAGS "") + endif() + + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") + set(_CMAKE_${lang}_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") + else() + set(_CMAKE_${lang}_EXTRA_DEVICE_LINK_FLAGS "") + endif() + + if(CMAKE_${lang}_HOST_COMPILER AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") + string(APPEND _CMAKE_${lang}_EXTRA_FLAGS " -ccbin=<CMAKE_${lang}_HOST_COMPILER>") + endif() + + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) + # Starting in 10.2, nvcc supported treating all warnings as errors + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror" "all-warnings") + endif() + + set(CMAKE_${lang}_DEPFILE_FORMAT gcc) + if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake") + set(CMAKE_${lang}_DEPENDS_USE_COMPILER TRUE) + endif() + + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) + # The -MD flag was only added to nvcc in 10.2 so + # before that we had to invoke the compiler twice + # to get header dependency information + set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") + else() + set(CMAKE_${lang}_DEPENDS_EXTRA_COMMANDS "<CMAKE_${lang}_COMPILER> ${_CMAKE_${lang}_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_${lang}_FLAG} -M <SOURCE> -MT <OBJECT> -o <DEP_FILE>") + endif() + + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 11.2) + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + endif() + + if(NOT "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE) + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC) + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY -Xcompiler=-fvisibility=) + # CMAKE_SHARED_LIBRARY_${lang}_FLAGS is sent to the host linker so we + # don't need to forward it through nvcc. + set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS -fPIC) + string(APPEND CMAKE_${lang}_FLAGS_INIT " ") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g") + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") + endif() + + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS -shared) + set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + + if (CMAKE_${lang}_SIMULATE_ID STREQUAL "GNU") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") + elseif(CMAKE_${lang}_SIMULATE_ID STREQUAL "Clang") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP) + endif() + + set(CMAKE_${lang}_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static") + set(CMAKE_${lang}_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "cudadevrt;cudart") + set(CMAKE_${lang}_RUNTIME_LIBRARY_LINK_OPTIONS_NONE "") + + if(UNIX AND NOT (CMAKE_SYSTEM_NAME STREQUAL "QNX")) + list(APPEND CMAKE_${lang}_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl") + endif() + + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0") + set(CMAKE_${lang}_RESPONSE_FILE_DEVICE_LINK_FLAG "--options-file ") + set(CMAKE_${lang}_RESPONSE_FILE_FLAG "--options-file ") + endif() + + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0") + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1) + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 1) + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1) + else() + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 0) + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 0) + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 0) + endif() +endmacro() diff --git a/Modules/Internal/CMakeCUDAArchitecturesAll.cmake b/Modules/Internal/CMakeCUDAArchitecturesAll.cmake new file mode 100644 index 0000000..873400a --- /dev/null +++ b/Modules/Internal/CMakeCUDAArchitecturesAll.cmake @@ -0,0 +1,88 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# See supported GPUs on Wikipedia +# https://en.wikipedia.org/wiki/CUDA#GPUs_supported + +function(cmake_cuda_architectures_all lang lang_var_) + # Initial set based on CUDA 7.0. + set(CMAKE_CUDA_ARCHITECTURES_ALL 20 21 30 35 37 50 52 53) + set(CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 20 30 35 50) + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 8.0) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 60 61 62) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 60) + endif() + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 9.0) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA" + OR (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang" AND CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + ) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 70 72) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 70) + endif() + + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 20 21) + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 20) + endif() + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 10.0) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA" + OR (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang" AND CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) + ) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 75) + endif() + endif() + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.0) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA" + OR (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang" AND CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) + ) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 80) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 80) + endif() + + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 30) + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 30) + endif() + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.1) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA" + OR (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang" AND CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + ) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 86) + endif() + endif() + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.4) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA") + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 87) + endif() + endif() + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.8) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA") + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 89 90) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 90) + endif() + endif() + + if(${lang_var_}TOOLKIT_VERSION VERSION_GREATER_EQUAL 12.0) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA") + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 35 37) + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 35) + endif() + endif() + + # only generate jit code for the newest arch for all/all-major + list(POP_BACK CMAKE_CUDA_ARCHITECTURES_ALL _latest_arch) + list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_ALL APPEND "-real") + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL ${_latest_arch}) + + list(POP_BACK CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR _latest_arch) + list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR APPEND "-real") + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR ${_latest_arch}) + + set(CMAKE_${lang}_ARCHITECTURES_ALL "${CMAKE_CUDA_ARCHITECTURES_ALL}" PARENT_SCOPE) + set(CMAKE_${lang}_ARCHITECTURES_ALL_MAJOR "${CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR}" PARENT_SCOPE) +endfunction() diff --git a/Modules/Internal/CMakeCUDAArchitecturesNative.cmake b/Modules/Internal/CMakeCUDAArchitecturesNative.cmake new file mode 100644 index 0000000..4185eda --- /dev/null +++ b/Modules/Internal/CMakeCUDAArchitecturesNative.cmake @@ -0,0 +1,49 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +function(cmake_cuda_architectures_native lang) + # Run the test binary to detect the native architectures. + execute_process(COMMAND "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_${lang}.bin" + RESULT_VARIABLE archs_result + OUTPUT_VARIABLE archs_output + ERROR_VARIABLE archs_output + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(archs_result EQUAL 0) + if("$ENV{CMAKE_CUDA_ARCHITECTURES_NATIVE_CLAMP}") + # Undocumented hook used by CMake's CI. + # Clamp native architecture to version range supported by this CUDA. + list(GET CMAKE_${lang}_ARCHITECTURES_ALL 0 arch_min) + list(GET CMAKE_${lang}_ARCHITECTURES_ALL -1 arch_max) + set(CMAKE_CUDA_ARCHITECTURES_NATIVE "") + foreach(arch IN LISTS archs_output) + if(arch LESS arch_min) + set(arch "${arch_min}") + endif() + if(arch GREATER arch_max) + set(arch "${arch_max}") + endif() + list(APPEND CMAKE_CUDA_ARCHITECTURES_NATIVE ${arch}) + endforeach() + unset(arch) + unset(arch_min) + unset(arch_max) + else() + set(CMAKE_CUDA_ARCHITECTURES_NATIVE "${archs_output}") + endif() + list(REMOVE_DUPLICATES CMAKE_CUDA_ARCHITECTURES_NATIVE) + list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_NATIVE APPEND "-real") + else() + if(NOT archs_result MATCHES "[0-9]+") + set(archs_status " (${archs_result})") + else() + set(archs_status "") + endif() + string(REPLACE "\n" "\n " archs_output " ${archs_output}") + message(CONFIGURE_LOG + "Detecting the CUDA native architecture(s) failed with " + "the following output${archs_status}:\n${archs_output}\n\n") + endif() + + set(CMAKE_${lang}_ARCHITECTURES_NATIVE "${CMAKE_CUDA_ARCHITECTURES_NATIVE}" PARENT_SCOPE) +endfunction() diff --git a/Modules/Internal/CMakeCUDAArchitecturesValidate.cmake b/Modules/Internal/CMakeCUDAArchitecturesValidate.cmake new file mode 100644 index 0000000..b6997d2 --- /dev/null +++ b/Modules/Internal/CMakeCUDAArchitecturesValidate.cmake @@ -0,0 +1,19 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +function(cmake_cuda_architectures_validate lang) + if(DEFINED CMAKE_${lang}_ARCHITECTURES) + if(CMAKE_${lang}_ARCHITECTURES STREQUAL "") + message(FATAL_ERROR "CMAKE_${lang}_ARCHITECTURES must be non-empty if set.") + elseif(CMAKE_${lang}_ARCHITECTURES AND NOT CMAKE_${lang}_ARCHITECTURES MATCHES "^([0-9]+a?(-real|-virtual)?(;[0-9]+a?(-real|-virtual)?|;)*|all|all-major|native)$") + message(FATAL_ERROR + "CMAKE_${lang}_ARCHITECTURES:\n" + " ${CMAKE_${lang}_ARCHITECTURES}\n" + "is not one of the following:\n" + " * a semicolon-separated list of integers, each optionally\n" + " followed by '-real' or '-virtual'\n" + " * a special value: all, all-major, native\n" + ) + endif() + endif() +endfunction() diff --git a/Modules/Internal/CMakeCUDAFilterImplicitLibs.cmake b/Modules/Internal/CMakeCUDAFilterImplicitLibs.cmake new file mode 100644 index 0000000..60287af --- /dev/null +++ b/Modules/Internal/CMakeCUDAFilterImplicitLibs.cmake @@ -0,0 +1,20 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# In CMakeDetermineCUDACompiler and CMakeTestCUDACompiler we detect +# libraries that the CUDA compiler implicitly passes to the host linker. +# CMake invokes the host linker directly and so needs to pass these libraries. +# Filter out implicit link libraries that should not be passed unconditionally. +macro(cmake_cuda_filter_implicit_libs _var_CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES) + list(REMOVE_ITEM "${_var_CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES}" + # The CUDA runtime libraries are controlled by CMAKE_CUDA_RUNTIME_LIBRARY. + cudart cudart.lib + cudart_static cudart_static.lib + cudadevrt cudadevrt.lib + + # Dependencies of the CUDA static runtime library on Linux hosts. + rt + pthread + dl + ) +endmacro() diff --git a/Modules/Internal/CMakeCUDAFindToolkit.cmake b/Modules/Internal/CMakeCUDAFindToolkit.cmake new file mode 100644 index 0000000..58d1e55 --- /dev/null +++ b/Modules/Internal/CMakeCUDAFindToolkit.cmake @@ -0,0 +1,173 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +macro(cmake_cuda_find_toolkit lang lang_var_) + # This is very similar to FindCUDAToolkit, but somewhat simplified since we can issue fatal errors + # if we fail and we don't need to account for searching the libraries. + + # For NVCC we can easily deduce the SDK binary directory from the compiler path. + if(CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA") + set(_CUDA_NVCC_EXECUTABLE "${CMAKE_${lang}_COMPILER}") + else() + # Search using CUDAToolkit_ROOT and then CUDA_PATH for equivalence with FindCUDAToolkit. + # In FindCUDAToolkit CUDAToolkit_ROOT is searched automatically due to being in a find_package(). + # First we search candidate non-default paths to give them priority. + find_program(_CUDA_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ${CUDAToolkit_ROOT} + ENV CUDAToolkit_ROOT + ENV CUDA_PATH + PATH_SUFFIXES bin + NO_DEFAULT_PATH + NO_CACHE + ) + + # If we didn't find NVCC, then try the default paths. + find_program(_CUDA_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATH_SUFFIXES bin + NO_CACHE + ) + + # If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error. + if(NOT _CUDA_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT})) + set(fail_base "Could not find nvcc executable in path specified by") + + if(DEFINED CUDAToolkit_ROOT) + message(FATAL_ERROR "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}") + elseif(DEFINED ENV{CUDAToolkit_ROOT}) + message(FATAL_ERROR "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}") + endif() + endif() + + # CUDAToolkit_ROOT cmake/env variable not specified, try platform defaults. + # + # - Linux: /usr/local/cuda-X.Y + # - macOS: /Developer/NVIDIA/CUDA-X.Y + # - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y + # + # We will also search the default symlink location /usr/local/cuda first since + # if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked + # directory is the desired location. + if(NOT _CUDA_NVCC_EXECUTABLE) + if(UNIX) + if(NOT APPLE) + set(platform_base "/usr/local/cuda-") + else() + set(platform_base "/Developer/NVIDIA/CUDA-") + endif() + else() + set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v") + endif() + + # Build out a descending list of possible cuda installations, e.g. + file(GLOB possible_paths "${platform_base}*") + # Iterate the glob results and create a descending list. + set(versions) + foreach(p ${possible_paths}) + # Extract version number from end of string + string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p}) + if(IS_DIRECTORY ${p} AND p_version) + list(APPEND versions ${p_version}) + endif() + endforeach() + + # Sort numerically in descending order, so we try the newest versions first. + list(SORT versions COMPARE NATURAL ORDER DESCENDING) + + # With a descending list of versions, populate possible paths to search. + set(search_paths) + foreach(v ${versions}) + list(APPEND search_paths "${platform_base}${v}") + endforeach() + + # Force the global default /usr/local/cuda to the front on Unix. + if(UNIX) + list(INSERT search_paths 0 "/usr/local/cuda") + endif() + + # Now search for nvcc again using the platform default search paths. + find_program(_CUDA_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ${search_paths} + PATH_SUFFIXES bin + NO_CACHE + ) + + # We are done with these variables now, cleanup. + unset(platform_base) + unset(possible_paths) + unset(versions) + unset(search_paths) + + if(NOT _CUDA_NVCC_EXECUTABLE) + message(FATAL_ERROR "Failed to find nvcc.\nCompiler ${CMAKE_${lang}_COMPILER_ID} requires the CUDA toolkit. Please set the CUDAToolkit_ROOT variable.") + endif() + endif() + endif() + + # Given that NVCC can be provided by multiple different sources (NVIDIA HPC SDK, CUDA Toolkit, distro) + # each of which has a different layout, we need to extract the CUDA toolkit root from the compiler + # itself, allowing us to support numerous different scattered toolkit layouts + execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda" + OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT) + if(_CUDA_NVCC_OUT MATCHES "\\#\\$ TOP=([^\r\n]*)") + get_filename_component(${lang_var_}TOOLKIT_ROOT "${CMAKE_MATCH_1}" ABSOLUTE) + else() + get_filename_component(${lang_var_}TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY) + get_filename_component(${lang_var_}TOOLKIT_ROOT "${${lang_var_}TOOLKIT_ROOT}" DIRECTORY) + endif() + + if(_CUDA_NVCC_OUT MATCHES "\\#\\$ NVVMIR_LIBRARY_DIR=([^\r\n]*)") + get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${CMAKE_MATCH_1}" ABSOLUTE) + + #We require the path to end in `/nvvm/libdevice' + if(_CUDA_NVVMIR_LIBRARY_DIR MATCHES "nvvm/libdevice$") + get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}/../.." ABSOLUTE) + set(_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}") + endif() + + unset(_CUDA_NVVMIR_LIBRARY_DIR) + unset(_cuda_nvvmir_dir_name) + endif() + unset(_CUDA_NVCC_OUT) + + # In a non-scattered installation the following are equivalent to ${lang_var_}TOOLKIT_ROOT. + # We first check for a non-scattered installation to prefer it over a scattered installation. + + # ${lang_var_}LIBRARY_ROOT contains the device library. + if(DEFINED _CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR) + set(${lang_var_}LIBRARY_ROOT "${_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR}") + elseif(EXISTS "${${lang_var_}TOOLKIT_ROOT}/nvvm/libdevice") + set(${lang_var_}LIBRARY_ROOT "${${lang_var_}TOOLKIT_ROOT}") + elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/nvvm/libdevice") + set(${lang_var_}LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda") + elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/nvvm/libdevice") + set(${lang_var_}LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/cuda") + else() + message(FATAL_ERROR "Couldn't find CUDA library root.") + endif() + unset(_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR) + + # ${lang_var_}TOOLKIT_LIBRARY_ROOT contains the linking stubs necessary for device linking and other low-level library files. + if(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/nvidia-cuda-toolkit/bin/crt/link.stub") + set(${lang_var_}TOOLKIT_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/nvidia-cuda-toolkit") + elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/nvidia-cuda-toolkit/bin/crt/link.stub") + set(${lang_var_}TOOLKIT_LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/nvidia-cuda-toolkit") + else() + set(${lang_var_}TOOLKIT_LIBRARY_ROOT "${${lang_var_}TOOLKIT_ROOT}") + endif() + + # For regular nvcc we the toolkit version is the same as the compiler version and we can parse it from the vendor test output. + # For Clang we need to invoke nvcc to get version output. + if(CMAKE_${lang}_COMPILER_ID STREQUAL "Clang") + execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT) + endif() + + if(CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES [=[V([0-9]+\.[0-9]+\.[0-9]+)]=]) + set(${lang_var_}TOOLKIT_VERSION "${CMAKE_MATCH_1}") + endif() + + # Don't leak variables unnecessarily to user code. + unset(_CUDA_NVCC_EXECUTABLE) +endmacro() diff --git a/Modules/Internal/CMakeNVCCFilterImplicitInfo.cmake b/Modules/Internal/CMakeNVCCFilterImplicitInfo.cmake new file mode 100644 index 0000000..dee7580 --- /dev/null +++ b/Modules/Internal/CMakeNVCCFilterImplicitInfo.cmake @@ -0,0 +1,16 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +macro(cmake_nvcc_filter_implicit_info lang lang_var_) + # Remove the CUDA Toolkit include directories from the set of + # implicit system include directories. + # This resolves the issue that NVCC doesn't specify these + # includes as SYSTEM includes when compiling device code, and sometimes + # they contain headers that generate warnings, so let users mark them + # as SYSTEM explicitly + if(${lang_var_}TOOLKIT_INCLUDE_DIRECTORIES) + list(REMOVE_ITEM CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES + ${${lang_var_}TOOLKIT_INCLUDE_DIRECTORIES} + ) + endif() +endmacro() diff --git a/Modules/Internal/CMakeNVCCParseImplicitInfo.cmake b/Modules/Internal/CMakeNVCCParseImplicitInfo.cmake new file mode 100644 index 0000000..32ff28a --- /dev/null +++ b/Modules/Internal/CMakeNVCCParseImplicitInfo.cmake @@ -0,0 +1,149 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +macro(cmake_nvcc_parse_implicit_info lang lang_var_) + set(_nvcc_log "") + string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_${lang}_COMPILER_PRODUCED_OUTPUT}") + if(_nvcc_output_orig MATCHES "#\\\$ +PATH= *([^\n]*)\n") + set(_nvcc_path "${CMAKE_MATCH_1}") + string(APPEND _nvcc_log " found 'PATH=' string: [${_nvcc_path}]\n") + string(REPLACE ":" ";" _nvcc_path "${_nvcc_path}") + else() + set(_nvcc_path "") + string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") + string(APPEND _nvcc_log " no 'PATH=' string found in nvcc output:${_nvcc_output_log}\n") + endif() + if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n") + set(_nvcc_libraries "${CMAKE_MATCH_1}") + string(APPEND _nvcc_log " found 'LIBRARIES=' string: [${_nvcc_libraries}]\n") + else() + set(_nvcc_libraries "") + string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") + string(APPEND _nvcc_log " no 'LIBRARIES=' string found in nvcc output:${_nvcc_output_log}\n") + endif() + if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n") + set(_nvcc_includes "${CMAKE_MATCH_1}") + string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n") + else() + set(_nvcc_includes "") + string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") + string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n") + endif() + string(REGEX MATCHALL "-arch compute_([0-9]+)" _nvcc_target_cpus "${_nvcc_output_orig}") + foreach(_nvcc_target_cpu ${_nvcc_target_cpus}) + if(_nvcc_target_cpu MATCHES "-arch compute_([0-9]+)") + list(APPEND CMAKE_${lang}_ARCHITECTURES_DEFAULT "${CMAKE_MATCH_1}") + endif() + endforeach() + + set(_nvcc_link_line "") + if(_nvcc_libraries) + # Remove variable assignments. + string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output_orig}") + # Encode [] characters that break list expansion. + string(REPLACE "[" "{==={" _nvcc_output "${_nvcc_output}") + string(REPLACE "]" "}===}" _nvcc_output "${_nvcc_output}") + # Split lines. + string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}") + foreach(line IN LISTS _nvcc_output) + set(_nvcc_output_line "${line}") + string(REPLACE "{==={" "[" _nvcc_output_line "${_nvcc_output_line}") + string(REPLACE "}===}" "]" _nvcc_output_line "${_nvcc_output_line}") + string(APPEND _nvcc_log " considering line: [${_nvcc_output_line}]\n") + if("${_nvcc_output_line}" MATCHES "^ *nvlink") + string(APPEND _nvcc_log " ignoring nvlink line\n") + elseif(_nvcc_libraries) + if("${_nvcc_output_line}" MATCHES "(@\"?((tmp/)?a\\.exe\\.res)\"?)") + set(_nvcc_link_res_arg "${CMAKE_MATCH_1}") + set(_nvcc_link_res_file "${CMAKE_MATCH_2}") + set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerId${lang}/${_nvcc_link_res_file}") + if(EXISTS "${_nvcc_link_res}") + file(READ "${_nvcc_link_res}" _nvcc_link_res_content) + string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}") + endif() + endif() + string(FIND "${_nvcc_output_line}" "${_nvcc_libraries}" _nvcc_libraries_pos) + if(NOT _nvcc_libraries_pos EQUAL -1) + set(_nvcc_link_line "${_nvcc_output_line}") + string(APPEND _nvcc_log " extracted link line: [${_nvcc_link_line}]\n") + endif() + endif() + endforeach() + endif() + + if(_nvcc_link_line) + if("x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_${lang}_HOST_LINK_LAUNCHER "${CMAKE_LINKER}") + else() + #extract the compiler that is being used for linking + separate_arguments(_nvcc_link_line_args UNIX_COMMAND "${_nvcc_link_line}") + list(GET _nvcc_link_line_args 0 _nvcc_host_link_launcher) + if(IS_ABSOLUTE "${_nvcc_host_link_launcher}") + string(APPEND _nvcc_log " extracted link launcher absolute path: [${_nvcc_host_link_launcher}]\n") + set(CMAKE_${lang}_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}") + else() + string(APPEND _nvcc_log " extracted link launcher name: [${_nvcc_host_link_launcher}]\n") + find_program(_nvcc_find_host_link_launcher + NAMES ${_nvcc_host_link_launcher} + PATHS ${_nvcc_path} NO_DEFAULT_PATH) + find_program(_nvcc_find_host_link_launcher + NAMES ${_nvcc_host_link_launcher}) + if(_nvcc_find_host_link_launcher) + string(APPEND _nvcc_log " found link launcher absolute path: [${_nvcc_find_host_link_launcher}]\n") + set(CMAKE_${lang}_HOST_LINK_LAUNCHER "${_nvcc_find_host_link_launcher}") + else() + string(APPEND _nvcc_log " could not find link launcher absolute path\n") + set(CMAKE_${lang}_HOST_LINK_LAUNCHER "${_nvcc_host_link_launcher}") + endif() + unset(_nvcc_find_host_link_launcher CACHE) + endif() + endif() + + #prefix the line with cuda-fake-ld so that implicit link info believes it is + #a link line + set(_nvcc_link_line "cuda-fake-ld ${_nvcc_link_line}") + CMAKE_PARSE_IMPLICIT_LINK_INFO("${_nvcc_link_line}" + CMAKE_${lang}_HOST_IMPLICIT_LINK_LIBRARIES + CMAKE_${lang}_HOST_IMPLICIT_LINK_DIRECTORIES + CMAKE_${lang}_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES + log + "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}" + LANGUAGE ${lang}) + + # Detect CMAKE_${lang}_RUNTIME_LIBRARY_DEFAULT from the compiler by looking at which + # cudart library exists in the implicit link libraries passed to the host linker. + # This is required when a project sets the cuda runtime library as part of the + # initial flags. + if(";${CMAKE_${lang}_HOST_IMPLICIT_LINK_LIBRARIES};" MATCHES [[;cudart_static(\.lib)?;]]) + set(CMAKE_${lang}_RUNTIME_LIBRARY_DEFAULT "STATIC") + elseif(";${CMAKE_${lang}_HOST_IMPLICIT_LINK_LIBRARIES};" MATCHES [[;cudart(\.lib)?;]]) + set(CMAKE_${lang}_RUNTIME_LIBRARY_DEFAULT "SHARED") + else() + set(CMAKE_${lang}_RUNTIME_LIBRARY_DEFAULT "NONE") + endif() + + message(CONFIGURE_LOG + "Parsed ${lang} nvcc implicit link information:\n${_nvcc_log}\n${log}\n\n") + else() + message(CONFIGURE_LOG + "Failed to parse ${lang} nvcc implicit link information:\n${_nvcc_log}\n\n") + message(FATAL_ERROR "Failed to extract nvcc implicit link line.") + endif() + + set(${lang_var_}TOOLKIT_INCLUDE_DIRECTORIES) + if(_nvcc_includes) + # across all operating system each include directory is prefixed with -I + separate_arguments(_nvcc_output NATIVE_COMMAND "${_nvcc_includes}") + foreach(line IN LISTS _nvcc_output) + string(REGEX REPLACE "^-I" "" line "${line}") + get_filename_component(line "${line}" ABSOLUTE) + list(APPEND ${lang_var_}TOOLKIT_INCLUDE_DIRECTORIES "${line}") + endforeach() + + message(CONFIGURE_LOG + "Parsed CUDA nvcc include information:\n${_nvcc_log}\n${log}\n\n") + else() + message(CONFIGURE_LOG + "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") + endif() +endmacro() |