diff options
-rw-r--r-- | Help/policy/CMP0104.rst | 25 | ||||
-rw-r--r-- | Help/prop_tgt/CUDA_ARCHITECTURES.rst | 10 | ||||
-rw-r--r-- | Help/release/3.18.rst | 8 | ||||
-rw-r--r-- | Modules/CMakeCUDACompiler.cmake.in | 3 | ||||
-rw-r--r-- | Modules/CMakeDetermineCUDACompiler.cmake | 212 | ||||
-rw-r--r-- | Modules/Compiler/Clang.cmake | 9 | ||||
-rw-r--r-- | Modules/FindCUDAToolkit.cmake | 235 | ||||
-rw-r--r-- | Modules/Internal/CUDAToolkit.cmake | 227 | ||||
-rw-r--r-- | Source/cmFindProgramCommand.cxx | 2 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 74 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 1 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 1 | ||||
-rw-r--r-- | Tests/CudaOnly/Architecture/CMakeLists.txt | 14 | ||||
-rw-r--r-- | Tests/RunCMake/CMP0104/CMP0104-OFF.cmake | 3 | ||||
-rw-r--r-- | Tests/RunCMake/CMP0104/RunCMakeTest.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/find_program/ExeNoRead-stdout.txt | 2 | ||||
-rw-r--r-- | Tests/RunCMake/find_program/RunCMakeTest.cmake | 12 |
17 files changed, 548 insertions, 291 deletions
diff --git a/Help/policy/CMP0104.rst b/Help/policy/CMP0104.rst index ca2c571..8516716 100644 --- a/Help/policy/CMP0104.rst +++ b/Help/policy/CMP0104.rst @@ -23,9 +23,34 @@ The ``NEW`` behavior of this policy is to initialize :variable:`CMAKE_CUDA_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` is ``NVIDIA`` and raise an error if :prop_tgt:`CUDA_ARCHITECTURES` is empty during generation. +If :prop_tgt:`CUDA_ARCHITECTURES` is set to a false value no architectures +flags are passed to the compiler. This is intended to support packagers and +the rare cases where full control over the passed flags is required. + This policy was introduced in CMake version 3.18. CMake version |release| warns when the policy is not set and uses ``OLD`` behavior. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. .. include:: DEPRECATED.txt + +Examples +^^^^^^^^ + +.. code-block:: cmake + + set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 35 50 72) + +Generates code for real and virtual architectures ``30``, ``50`` and ``72``. + +.. code-block:: cmake + + set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 70-real 72-virtual) + +Generates code for real architecture ``70`` and virtual architecture ``72``. + +.. code-block:: cmake + + set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES OFF) + +CMake will not pass any architecture flags to the compiler. diff --git a/Help/prop_tgt/CUDA_ARCHITECTURES.rst b/Help/prop_tgt/CUDA_ARCHITECTURES.rst index 328f40b..bae3c6f 100644 --- a/Help/prop_tgt/CUDA_ARCHITECTURES.rst +++ b/Help/prop_tgt/CUDA_ARCHITECTURES.rst @@ -8,6 +8,10 @@ the kind of architecture to generate code for. If no suffix is given then code is generated for both real and virtual architectures. +A non-empty false value (e.g. ``OFF``) disables adding architectures. +This is intended to support packagers and rare cases where full control +over the passed flags is required. + This property is initialized by the value of the :variable:`CMAKE_CUDA_ARCHITECTURES` variable if it is set when a target is created. @@ -28,3 +32,9 @@ Generates code for real and virtual architectures ``30``, ``50`` and ``72``. set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 70-real 72-virtual) Generates code for real architecture ``70`` and virtual architecture ``72``. + +.. code-block:: cmake + + set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES OFF) + +CMake will not pass any architecture flags to the compiler. diff --git a/Help/release/3.18.rst b/Help/release/3.18.rst index 71f9d85..db5f62a 100644 --- a/Help/release/3.18.rst +++ b/Help/release/3.18.rst @@ -194,6 +194,14 @@ Modules .. _`SWIG-Fortran`: https://github.com/swig-fortran/swig +* The :module:`FindCUDAToolkit` module: + + * gained the variable + ``CUDAToolkit_LIBRARY_ROOT``, which is the directory containing the + ``nvvm`` directory and ``version.txt``. + + * uses toolkit and library root found during ``CUDA`` compiler detection. + Generator Expressions --------------------- diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 64fb469..704ad09 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -43,6 +43,9 @@ if(CMAKE_CUDA_LIBRARY_ARCHITECTURE) set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_CUDA_LIBRARY_ARCHITECTURE@") endif() +set(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "@CMAKE_CUDA_COMPILER_TOOLKIT_ROOT@") +set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "@CMAKE_CUDA_COMPILER_LIBRARY_ROOT@") + set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "@CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES@") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES@") diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 5ae3908..a0f7202 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -65,18 +65,144 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2) set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-v") - # nvcc - set(nvcc_test_flags "--keep --keep-dir tmp") - if(CMAKE_CUDA_HOST_COMPILER) - string(APPEND nvcc_test_flags " -ccbin=${CMAKE_CUDA_HOST_COMPILER}") + # We determine the vendor to help with find the toolkit and use the right flags for detection right away. + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + CMAKE_DETERMINE_COMPILER_ID_VENDOR(CUDA "--version") + + # Find the CUDA toolkit. We store the CMAKE_CUDA_COMPILER_TOOLKIT_ROOT and CMAKE_CUDA_COMPILER_LIBRARY_ROOT + # in CMakeCUDACompiler.cmake, so FindCUDAToolkit can avoid searching on future runs and the toolkit stays the same. + # This is very similar to FindCUDAToolkit, but somewhat simplified since we can issue fatal errors + # if we fail to find things we need 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") + get_filename_component(_CUDA_BIN_DIR "${CMAKE_CUDA_COMPILER}" DIRECTORY) + find_program(CUDAToolkit_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ${_CUDA_BIN_DIR} + NO_DEFAULT_PATH + ) + unset(_CUDA_BIN_DIR) endif() - # Clang - if(CMAKE_CROSSCOMPILING) - # Need to pass the host target and include directories if we're crosscompiling. - set(clang_test_flags "--sysroot=\"${CMAKE_SYSROOT}\" --target=${CMAKE_CUDA_COMPILER_TARGET}") - else() - set(clang_test_flags) + # 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 "Could not find nvcc, please set CUDAToolkit_ROOT.") + endif() + endif() + + 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 ABSOLUTE) + + # CMAKE_CUDA_COMPILER_LIBRARY_ROOT contains the device library and version file. + # In a non-scattered installation this is equivalent to CMAKE_CUDA_COMPILER_TOOLKIT_ROOT. + # We first check for a non-scattered installation to prefer it over a scattered installation. + if(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/version.txt") + set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}") + elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt") + set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda") + elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt") + set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/cuda") + endif() + + if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") + set(nvcc_test_flags "--keep --keep-dir tmp") + if(CMAKE_CUDA_HOST_COMPILER) + string(APPEND nvcc_test_flags " -ccbin=${CMAKE_CUDA_HOST_COMPILER}") + endif() + elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") + set(clang_test_flags "--cuda-path=\"${CMAKE_CUDA_COMPILER_LIBRARY_ROOT}\"") + if(CMAKE_CROSSCOMPILING) + # Need to pass the host target and include directories if we're crosscompiling. + string(APPEND clang_test_flags " --sysroot=\"${CMAKE_SYSROOT}\" --target=${CMAKE_CUDA_COMPILER_TARGET}") + endif() endif() # First try with the user-specified architectures. @@ -108,7 +234,12 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) # Finally also try the default. list(APPEND CMAKE_CUDA_COMPILER_ID_TEST_FLAGS_FIRST "${clang_test_flags}") - include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + # We perform compiler identification for a second time to extract implicit linking info and host compiler for NVCC. + # We also use it to verify that CMAKE_CUDA_ARCHITECTURES and additionaly on Clang that CUDA toolkit path works. + # The latter could be done during compiler testing in the future to avoid doing this for Clang. + # We need to unset the compiler ID otherwise CMAKE_DETERMINE_COMPILER_ID() doesn't work. + unset(CMAKE_CUDA_COMPILER_ID) + CMAKE_DETERMINE_COMPILER_ID(CUDA CUDAFLAGS CMakeCUDACompilerId.cu) _cmake_find_compiler_sysroot(CUDA) @@ -157,12 +288,54 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") endforeach() endif() + # Find target directory. Account for crosscompiling. + if(CMAKE_CROSSCOMPILING) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a") + # Support for NVPACK + set(_CUDA_TARGET_NAME "armv7-linux-androideabi") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") + set(_CUDA_TARGET_NAME "armv7-linux-gnueabihf") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + if(ANDROID_ARCH_NAME STREQUAL "arm64") + set(_CUDA_TARGET_NAME "aarch64-linux-androideabi") + else() + set(_CUDA_TARGET_NAME "aarch64-linux") + endif() + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(_CUDA_TARGET_NAME "x86_64-linux") + endif() + + if(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/targets/${_CUDA_TARGET_NAME}") + set(_CUDA_TARGET_DIR "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/targets/${_CUDA_TARGET_NAME}") + endif() + else() + set(_CUDA_TARGET_DIR "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}") + endif() + + # We can't use find_library() yet at this point, so try a few guesses. + if(EXISTS "${_CUDA_TARGET_DIR}/lib64") + set(_CUDA_LIBRARY_DIR "${_CUDA_TARGET_DIR}/lib64") + elseif(EXISTS "${_CUDA_TARGET_DIR}/lib/x64") + set(_CUDA_LIBRARY_DIR "${_CUDA_TARGET_DIR}/lib/x64") + elseif(EXISTS "${_CUDA_TARGET_DIR}/lib") + set(_CUDA_LIBRARY_DIR "${_CUDA_TARGET_DIR}/lib") + else() + message(FATAL_ERROR "Unable to find _CUDA_LIBRARY_DIR based on _CUDA_TARGET_DIR=${_CUDA_TARGET_DIR}") + endif() + + # _CUDA_TARGET_DIR always points to the directory containing the include directory. + # On a scattered installation /usr, on a non-scattered something like /usr/local/cuda or /usr/local/cuda-10.2/targets/aarch64-linux. + if(EXISTS "${_CUDA_TARGET_DIR}/include/cuda_runtime.h") + set(_CUDA_INCLUDE_DIR "${_CUDA_TARGET_DIR}/include") + else() + message(FATAL_ERROR "Unable to find cuda_runtime.h in \"${_CUDA_TARGET_DIR}/include\" for _CUDA_INCLUDE_DIR.") + endif() + # Clang does not add any CUDA SDK libraries or directories when invoking the host linker. # Add the CUDA toolkit library directory ourselves so that linking works. # The CUDA runtime libraries are handled elsewhere by CMAKE_CUDA_RUNTIME_LIBRARY. - include(Internal/CUDAToolkit) - set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${CUDAToolkit_INCLUDE_DIR}") - set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "${CUDAToolkit_LIBRARY_DIR}") + set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${_CUDA_INCLUDE_DIR}") + 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") @@ -352,7 +525,7 @@ 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(DEFINED detected_architecture) +if(DEFINED detected_architecture AND "${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") set(CMAKE_CUDA_ARCHITECTURES "${detected_architecture}" CACHE STRING "CUDA architectures") if(NOT CMAKE_CUDA_ARCHITECTURES) @@ -382,7 +555,14 @@ endif() configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in ${CMAKE_PLATFORM_INFO_DIR}/CMakeCUDACompiler.cmake @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) set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX") set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX") diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index cd47aa6..bb516d3 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -146,7 +146,14 @@ macro(__compiler_clang_cxx_standards lang) set(CMAKE_${lang}17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() - if (NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}") + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 6.0) + set(CMAKE_${lang}17_STANDARD__HAS_FULL_SUPPORT ON) + endif() + + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 11.0) + set(CMAKE_${lang}20_STANDARD_COMPILE_OPTION "-std=c++20") + set(CMAKE_${lang}20_EXTENSION_COMPILE_OPTION "-std=gnu++20") + elseif(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}") set(CMAKE_${lang}20_STANDARD_COMPILE_OPTION "-std=c++2a") set(CMAKE_${lang}20_EXTENSION_COMPILE_OPTION "-std=gnu++2a") endif() diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 7d4e168..00d1a50 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -421,6 +421,10 @@ Result variables The path to the CUDA Toolkit library directory that contains the CUDA Runtime library ``cudart``. +``CUDAToolkit_LIBRARY_ROOT`` + The path to the CUDA Toolkit directory containing the nvvm directory and + version.txt. + ``CUDAToolkit_TARGET_DIR`` The path to the CUDA Toolkit directory including the target architecture when cross-compiling. When not cross-compiling this will be equivalant to @@ -473,8 +477,207 @@ Result variables # ############################################################################### -# Include shared CUDA toolkit location code. -include(Internal/CUDAToolkit) +# The toolkit is located during compiler detection for CUDA and stored in CMakeCUDACompiler.cmake as +# CMAKE_CUDA_COMPILER_TOOLKIT_ROOT and CMAKE_CUDA_COMPILER_LIBRARY_ROOT. +# We compute the rest based on those here to avoid re-searching and to avoid finding a possibly +# different installation. +if(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT) + set(CUDAToolkit_ROOT_DIR "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}") + set(CUDAToolkit_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_LIBRARY_ROOT}") + set(CUDAToolkit_BIN_DIR "${CUDAToolkit_ROOT_DIR}/bin") + set(CUDAToolkit_NVCC_EXECUTABLE "${CUDAToolkit_BIN_DIR}/nvcc${CMAKE_EXECUTABLE_SUFFIX}") +else() + # For NVCC we can easily deduce the SDK binary directory from the compiler path. + if(CMAKE_CUDA_COMPILER_LOADED AND NOT CUDAToolkit_BIN_DIR AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") + get_filename_component(CUDAToolkit_BIN_DIR "${CMAKE_CUDA_COMPILER}" DIRECTORY) + set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "") + mark_as_advanced(CUDAToolkit_BIN_DIR) + endif() + + # Try language- or user-provided path first. + if(CUDAToolkit_BIN_DIR) + find_program(CUDAToolkit_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ${CUDAToolkit_BIN_DIR} + NO_DEFAULT_PATH + ) + endif() + + # Search using CUDAToolkit_ROOT + find_program(CUDAToolkit_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ENV CUDA_PATH + PATH_SUFFIXES bin + ) + + # If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error. + if(NOT CUDAToolkit_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT})) + # Declare error messages now, print later depending on find_package args. + set(fail_base "Could not find nvcc executable in path specified by") + set(cuda_root_fail "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}") + set(env_cuda_root_fail "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}") + + if(CUDAToolkit_FIND_REQUIRED) + if(DEFINED CUDAToolkit_ROOT) + message(FATAL_ERROR ${cuda_root_fail}) + elseif(DEFINED ENV{CUDAToolkit_ROOT}) + message(FATAL_ERROR ${env_cuda_root_fail}) + endif() + else() + if(NOT CUDAToolkit_FIND_QUIETLY) + if(DEFINED CUDAToolkit_ROOT) + message(STATUS ${cuda_root_fail}) + elseif(DEFINED ENV{CUDAToolkit_ROOT}) + message(STATUS ${env_cuda_root_fail}) + endif() + endif() + set(CUDAToolkit_FOUND FALSE) + unset(fail_base) + unset(cuda_root_fail) + unset(env_cuda_root_fail) + return() + 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 CUDAToolkit_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(CUDAToolkit_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ${search_paths} + PATH_SUFFIXES bin + ) + + # We are done with these variables now, cleanup for caller. + unset(platform_base) + unset(possible_paths) + unset(versions) + unset(search_paths) + + if(NOT CUDAToolkit_NVCC_EXECUTABLE) + if(CUDAToolkit_FIND_REQUIRED) + message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.") + elseif(NOT CUDAToolkit_FIND_QUIETLY) + message(STATUS "Could not find nvcc, please set CUDAToolkit_ROOT.") + endif() + + set(CUDAToolkit_FOUND FALSE) + return() + endif() + endif() + + if(NOT CUDAToolkit_BIN_DIR AND CUDAToolkit_NVCC_EXECUTABLE) + get_filename_component(CUDAToolkit_BIN_DIR "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY) + set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "" FORCE) + mark_as_advanced(CUDAToolkit_BIN_DIR) + endif() + + get_filename_component(CUDAToolkit_ROOT_DIR ${CUDAToolkit_BIN_DIR} DIRECTORY ABSOLUTE) + + # CUDAToolkit_LIBRARY_ROOT contains the device library and version file. + # In a non-scattered installation this is equivalent to CUDAToolkit_ROOT_DIR. + # We first check for a non-scattered installation to prefer it over a scattered installation. + if(EXISTS "${CUDAToolkit_ROOT_DIR}/version.txt") + set(CUDAToolkit_LIBRARY_ROOT "${CUDAToolkit_ROOT_DIR}") + elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt") + set(CUDAToolkit_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda") + elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt") + set(CUDAToolkit_LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/cuda") + endif() +endif() + +# Handle cross compilation +if(CMAKE_CROSSCOMPILING) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a") + # Support for NVPACK + set(CUDAToolkit_TARGET_NAME "armv7-linux-androideabi") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") + # Support for arm cross compilation + set(CUDAToolkit_TARGET_NAME "armv7-linux-gnueabihf") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + # Support for aarch64 cross compilation + if(ANDROID_ARCH_NAME STREQUAL "arm64") + set(CUDAToolkit_TARGET_NAME "aarch64-linux-androideabi") + else() + set(CUDAToolkit_TARGET_NAME "aarch64-linux") + endif(ANDROID_ARCH_NAME STREQUAL "arm64") + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(CUDAToolkit_TARGET_NAME "x86_64-linux") + endif() + + if(EXISTS "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}") + set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}") + # add known CUDA target root path to the set of directories we search for programs, libraries and headers + list(PREPEND CMAKE_FIND_ROOT_PATH "${CUDAToolkit_TARGET_DIR}") + + # Mark that we need to pop the root search path changes after we have + # found all cuda libraries so that searches for our cross-compilation + # libraries work when another cuda sdk is in CMAKE_PREFIX_PATH or + # PATh + set(_CUDAToolkit_Pop_ROOT_PATH True) + endif() +else() + # Not cross compiling + set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}") + # Now that we have the real ROOT_DIR, find components inside it. + list(APPEND CMAKE_PREFIX_PATH ${CUDAToolkit_ROOT_DIR}) + + # Mark that we need to pop the prefix path changes after we have + # found the cudart library. + set(_CUDAToolkit_Pop_Prefix True) +endif() + +# CUDAToolkit_TARGET_DIR always points to the directory containing the include directory. +# On a scattered installation /usr, on a non-scattered something like /usr/local/cuda or /usr/local/cuda-10.2/targets/aarch64-linux. +if(EXISTS "${CUDAToolkit_TARGET_DIR}/include/cuda_runtime.h") + set(CUDAToolkit_INCLUDE_DIR "${CUDAToolkit_TARGET_DIR}/include") +elseif(NOT CUDAToolkit_FIND_QUIETLY) + message(STATUS "Unable to find cuda_runtime.h in \"${CUDAToolkit_TARGET_DIR}/include\" for CUDAToolkit_INCLUDE_DIR.") +endif() if(CUDAToolkit_NVCC_EXECUTABLE AND CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER) @@ -488,7 +691,7 @@ if(CUDAToolkit_NVCC_EXECUTABLE AND endif() else() # Compute the version by invoking nvcc - execute_process (COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT) + execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT) if(NVCC_OUT MATCHES [=[ V([0-9]+)\.([0-9]+)\.([0-9]+)]=]) set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") @@ -503,12 +706,10 @@ find_library(CUDA_CUDART NAMES cudart PATH_SUFFIXES lib64 lib/x64 ) -if(NOT CUDA_CUDART) - find_library(CUDA_CUDART - NAMES cudart - PATH_SUFFIXES lib64/stubs lib/x64/stubs - ) -endif() +find_library(CUDA_CUDART + NAMES cudart + PATH_SUFFIXES lib64/stubs lib/x64/stubs +) if(NOT CUDA_CUDART AND NOT CUDAToolkit_FIND_QUIETLY) message(STATUS "Unable to find cudart library.") @@ -559,16 +760,14 @@ if(CUDAToolkit_FOUND) PATH_SUFFIXES nvidia/current lib64 lib/x64 lib ${arg_EXTRA_PATH_SUFFIXES} ) - # Don't try any stub directories intil we have exhausted all other + # Don't try any stub directories until we have exhausted all other # search locations. - if(NOT CUDA_${lib_name}_LIBRARY) - find_library(CUDA_${lib_name}_LIBRARY - NAMES ${search_names} - HINTS ${CUDAToolkit_LIBRARY_DIR} - ENV CUDA_PATH - PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs - ) - endif() + find_library(CUDA_${lib_name}_LIBRARY + NAMES ${search_names} + HINTS ${CUDAToolkit_LIBRARY_DIR} + ENV CUDA_PATH + PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs + ) mark_as_advanced(CUDA_${lib_name}_LIBRARY) diff --git a/Modules/Internal/CUDAToolkit.cmake b/Modules/Internal/CUDAToolkit.cmake deleted file mode 100644 index 291bb01..0000000 --- a/Modules/Internal/CUDAToolkit.cmake +++ /dev/null @@ -1,227 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -# This file is for sharing code for finding basic CUDA toolkit information between -# CMakeDetermineCUDACompiler.cmake and FindCUDAToolkit.cmake. - -# For NVCC we can easily deduce the SDK binary directory from the compiler path. -if(CMAKE_CUDA_COMPILER_LOADED AND NOT CUDAToolkit_BIN_DIR AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") - get_filename_component(cuda_dir "${CMAKE_CUDA_COMPILER}" DIRECTORY) - set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "") - mark_as_advanced(CUDAToolkit_BIN_DIR) - unset(cuda_dir) -endif() - -# Try language- or user-provided path first. -if(CUDAToolkit_BIN_DIR) - find_program(CUDAToolkit_NVCC_EXECUTABLE - NAMES nvcc nvcc.exe - PATHS ${CUDAToolkit_BIN_DIR} - NO_DEFAULT_PATH - ) -endif() - -# Search using CUDAToolkit_ROOT -find_program(CUDAToolkit_NVCC_EXECUTABLE - NAMES nvcc nvcc.exe - PATHS ENV CUDA_PATH - PATH_SUFFIXES bin -) - -# If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error. -if(NOT CUDAToolkit_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT})) - # Declare error messages now, print later depending on find_package args. - set(fail_base "Could not find nvcc executable in path specified by") - set(cuda_root_fail "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}") - set(env_cuda_root_fail "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}") - - if(CUDAToolkit_FIND_REQUIRED) - if(DEFINED CUDAToolkit_ROOT) - message(FATAL_ERROR ${cuda_root_fail}) - elseif(DEFINED ENV{CUDAToolkit_ROOT}) - message(FATAL_ERROR ${env_cuda_root_fail}) - endif() - else() - if(NOT CUDAToolkit_FIND_QUIETLY) - if(DEFINED CUDAToolkit_ROOT) - message(STATUS ${cuda_root_fail}) - elseif(DEFINED ENV{CUDAToolkit_ROOT}) - message(STATUS ${env_cuda_root_fail}) - endif() - endif() - set(CUDAToolkit_FOUND FALSE) - unset(fail_base) - unset(cuda_root_fail) - unset(env_cuda_root_fail) - return() - 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 CUDAToolkit_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(possible_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 possible_versions ${p_version}) - endif() - endforeach() - - # Cannot use list(SORT) because that is alphabetical, we need numerical. - # NOTE: this is not an efficient sorting strategy. But even if a user had - # every possible version of CUDA installed, this wouldn't create any - # significant overhead. - set(versions) - foreach (v ${possible_versions}) - list(LENGTH versions num_versions) - # First version, nothing to compare with so just append. - if(num_versions EQUAL 0) - list(APPEND versions ${v}) - else() - # Loop through list. Insert at an index when comparison is - # VERSION_GREATER since we want a descending list. Duplicates will not - # happen since this came from a glob list of directories. - set(i 0) - set(early_terminate FALSE) - while (i LESS num_versions) - list(GET versions ${i} curr) - if(v VERSION_GREATER curr) - list(INSERT versions ${i} ${v}) - set(early_terminate TRUE) - break() - endif() - math(EXPR i "${i} + 1") - endwhile() - # If it did not get inserted, place it at the end. - if(NOT early_terminate) - list(APPEND versions ${v}) - endif() - endif() - endforeach() - - # 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(CUDAToolkit_NVCC_EXECUTABLE - NAMES nvcc nvcc.exe - PATHS ${search_paths} - PATH_SUFFIXES bin - ) - - # We are done with these variables now, cleanup for caller. - unset(platform_base) - unset(possible_paths) - unset(possible_versions) - unset(versions) - unset(i) - unset(early_terminate) - unset(search_paths) - - if(NOT CUDAToolkit_NVCC_EXECUTABLE) - if(CUDAToolkit_FIND_REQUIRED) - message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.") - elseif(NOT CUDAToolkit_FIND_QUIETLY) - message(STATUS "Could not find nvcc, please set CUDAToolkit_ROOT.") - endif() - - set(CUDAToolkit_FOUND FALSE) - return() - endif() -endif() - -if(NOT CUDAToolkit_BIN_DIR AND CUDAToolkit_NVCC_EXECUTABLE) - get_filename_component(cuda_dir "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY) - set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "" FORCE) - mark_as_advanced(CUDAToolkit_BIN_DIR) - unset(cuda_dir) -endif() - -get_filename_component(CUDAToolkit_ROOT_DIR ${CUDAToolkit_BIN_DIR} DIRECTORY ABSOLUTE) - -# Handle cross compilation -if(CMAKE_CROSSCOMPILING) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7-a") - # Support for NVPACK - set(CUDAToolkit_TARGET_NAME "armv7-linux-androideabi") - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") - # Support for arm cross compilation - set(CUDAToolkit_TARGET_NAME "armv7-linux-gnueabihf") - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") - # Support for aarch64 cross compilation - if(ANDROID_ARCH_NAME STREQUAL "arm64") - set(CUDAToolkit_TARGET_NAME "aarch64-linux-androideabi") - else() - set(CUDAToolkit_TARGET_NAME "aarch64-linux") - endif(ANDROID_ARCH_NAME STREQUAL "arm64") - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - set(CUDAToolkit_TARGET_NAME "x86_64-linux") - endif() - - if(EXISTS "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}") - set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}/targets/${CUDAToolkit_TARGET_NAME}") - # add known CUDA target root path to the set of directories we search for programs, libraries and headers - list(PREPEND CMAKE_FIND_ROOT_PATH "${CUDAToolkit_TARGET_DIR}") - - # Mark that we need to pop the root search path changes after we have - # found all cuda libraries so that searches for our cross-compilation - # libraries work when another cuda sdk is in CMAKE_PREFIX_PATH or - # PATh - set(_CUDAToolkit_Pop_ROOT_PATH True) - endif() -else() - # Not cross compiling - set(CUDAToolkit_TARGET_DIR "${CUDAToolkit_ROOT_DIR}") - # Now that we have the real ROOT_DIR, find components inside it. - list(APPEND CMAKE_PREFIX_PATH ${CUDAToolkit_ROOT_DIR}) - - # Mark that we need to pop the prefix path changes after we have - # found the cudart library. - set(_CUDAToolkit_Pop_Prefix True) -endif() - -# Find the include/ directory -find_path(CUDAToolkit_INCLUDE_DIR - NAMES cuda_runtime.h -) - -# Find a tentative CUDAToolkit_LIBRARY_DIR. FindCUDAToolkit overrides it by searching for the CUDA runtime, -# but we can't do that here, as CMakeDetermineCUDACompiler wants to use it before the variables necessary -# for find_library() have been initialized. -if(EXISTS "${CUDAToolkit_TARGET_DIR}/lib64") - set(CUDAToolkit_LIBRARY_DIR "${CUDAToolkit_TARGET_DIR}/lib64") -elseif(EXISTS "${CUDAToolkit_TARGET_DIR}/lib/x64") - set(CUDAToolkit_LIBRARY_DIR "${CUDAToolkit_TARGET_DIR}/lib/x64") -elseif(EXISTS "${CUDAToolkit_TARGET_DIR}/lib") - set(CUDAToolkit_LIBRARY_DIR "${CUDAToolkit_TARGET_DIR}/lib") -endif() diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 599b1d2..4b88bea 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -85,7 +85,7 @@ struct cmFindProgramHelper this->TestNameExt = cmStrCat(name, ext); this->TestPath = cmSystemTools::CollapseFullPath(this->TestNameExt, path); - bool exists = cmSystemTools::FileIsExecutable(this->TestPath); + bool exists = cmSystemTools::FileExists(this->TestPath, true); exists ? this->DebugSearches.FoundAt(this->TestPath) : this->DebugSearches.FailedAt(this->TestPath); if (exists) { diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 250910a..f2011ee 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -37,6 +37,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmOutputConverter.h" #include "cmPropertyMap.h" #include "cmRange.h" #include "cmSourceFile.h" @@ -3044,6 +3045,34 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config, void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const { + const std::string& property = this->GetSafeProperty("CUDA_ARCHITECTURES"); + + if (property.empty()) { + switch (this->GetPolicyStatusCMP0104()) { + case cmPolicies::WARN: + if (!this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile()) { + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0104) + + "\nCUDA_ARCHITECTURES is empty for target \"" + this->GetName() + + "\"."); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + default: + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "CUDA_ARCHITECTURES is empty for target \"" + this->GetName() + + "\"."); + } + } + + // If CUDA_ARCHITECTURES is false we don't add any architectures. + if (cmIsOff(property)) { + return; + } + struct CudaArchitecture { std::string name; @@ -3054,28 +3083,7 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const { std::vector<std::string> options; - cmExpandList(this->GetSafeProperty("CUDA_ARCHITECTURES"), options); - - if (options.empty()) { - switch (this->GetPolicyStatusCMP0104()) { - case cmPolicies::WARN: - if (!this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile()) { - this->Makefile->IssueMessage( - MessageType::AUTHOR_WARNING, - cmPolicies::GetPolicyWarning(cmPolicies::CMP0104) + - "\nCUDA_ARCHITECTURES is empty for target \"" + - this->GetName() + "\"."); - } - CM_FALLTHROUGH; - case cmPolicies::OLD: - break; - default: - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "CUDA_ARCHITECTURES is empty for target \"" + this->GetName() + - "\"."); - } - } + cmExpandList(property, options); for (std::string& option : options) { CudaArchitecture architecture; @@ -3145,6 +3153,28 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const } } +void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const +{ + std::string const& compiler = + this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID"); + + if (compiler == "Clang") { + // Pass CUDA toolkit explicitly to Clang. + // Clang's searching for the system CUDA toolkit isn't very good and it's + // expected the user will explicitly pass the toolkit path. + // This also avoids Clang having to search for the toolkit on every + // invocation. + std::string toolkitRoot = + this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_LIBRARY_ROOT"); + + if (!toolkitRoot.empty()) { + flags += " --cuda-path=" + + this->LocalGenerator->ConvertToOutputFormat(toolkitRoot, + cmOutputConverter::SHELL); + } + } +} + //---------------------------------------------------------------------------- std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable( std::string const& var, std::string const& lang, diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a7201dc..3aedbf5 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -426,6 +426,7 @@ public: std::vector<std::string>& archVec) const; void AddCUDAArchitectureFlags(std::string& flags) const; + void AddCUDAToolkitFlags(std::string& flags) const; std::string GetFeatureSpecificLinkRuleVariable( std::string const& var, std::string const& lang, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index fba9cdb..f748822 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1986,6 +1986,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } else if (lang == "CUDA") { target->AddCUDAArchitectureFlags(flags); + target->AddCUDAToolkitFlags(flags); std::string const& compiler = this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID"); diff --git a/Tests/CudaOnly/Architecture/CMakeLists.txt b/Tests/CudaOnly/Architecture/CMakeLists.txt index 7270b56..03e972f 100644 --- a/Tests/CudaOnly/Architecture/CMakeLists.txt +++ b/Tests/CudaOnly/Architecture/CMakeLists.txt @@ -1,5 +1,15 @@ -cmake_minimum_required(VERSION 3.17) +cmake_minimum_required(VERSION 3.18) project(Architecture CUDA) -set(CMAKE_CUDA_ARCHITECTURES 52) add_executable(Architecture main.cu) +set_property(TARGET Architecture PROPERTY CUDA_ARCHITECTURES 52) + +# Make sure CMake doesn't pass architectures if CUDA_ARCHITECTURES is OFF. +if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -arch=sm_52") +elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --cuda-gpu-arch=sm_52") +endif() + +add_executable(ArchitectureOff main.cu) +set_property(TARGET ArchitectureOff PROPERTY CUDA_ARCHITECTURES OFF) diff --git a/Tests/RunCMake/CMP0104/CMP0104-OFF.cmake b/Tests/RunCMake/CMP0104/CMP0104-OFF.cmake new file mode 100644 index 0000000..f3b6682 --- /dev/null +++ b/Tests/RunCMake/CMP0104/CMP0104-OFF.cmake @@ -0,0 +1,3 @@ +include(CMP0104-Common.cmake) + +set_property(TARGET cuda PROPERTY CUDA_ARCHITECTURES OFF) diff --git a/Tests/RunCMake/CMP0104/RunCMakeTest.cmake b/Tests/RunCMake/CMP0104/RunCMakeTest.cmake index bc8e1b1..b26f72a 100644 --- a/Tests/RunCMake/CMP0104/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMP0104/RunCMakeTest.cmake @@ -2,4 +2,5 @@ include(RunCMake) run_cmake(CMP0104-OLD) run_cmake(CMP0104-NEW) +run_cmake(CMP0104-OFF) run_cmake(CMP0104-WARN) diff --git a/Tests/RunCMake/find_program/ExeNoRead-stdout.txt b/Tests/RunCMake/find_program/ExeNoRead-stdout.txt index 35a83f2..f231178 100644 --- a/Tests/RunCMake/find_program/ExeNoRead-stdout.txt +++ b/Tests/RunCMake/find_program/ExeNoRead-stdout.txt @@ -1 +1 @@ --- ExeNoRead_EXECUTABLE='.*/Tests/RunCMake/find_program/ExeNoRead-build/ExeNoRead' +-- ExeNoRead_EXECUTABLE='ExeNoRead_EXECUTABLE-NOTFOUND' diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake index 95ffd84..2bb777b 100644 --- a/Tests/RunCMake/find_program/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake @@ -9,8 +9,14 @@ run_cmake(Required) if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN)$") run_cmake(WindowsCom) run_cmake(WindowsExe) -endif() +else() + # test non readable file only if not root + execute_process( + COMMAND id -u $ENV{USER} + OUTPUT_VARIABLE uid + OUTPUT_STRIP_TRAILING_WHITESPACE) -if(UNIX) - run_cmake(ExeNoRead) + if(NOT "${uid}" STREQUAL "0") + run_cmake(ExeNoRead) + endif() endif() |