Browse Source

CUDA: Add support for disabling CUDA_ARCHITECTURES

The ability to disable adding architectures completely for packaging purposes
and cases requiring passing the architectures flags explicitly has been
requested.
Support a false value for CUDA_ARCHITECTURES and CMAKE_CUDA_ARCHITECTURES
for this purpose.

Implements #20821.
Raul Tambre 5 years ago
parent
commit
877a92e968

+ 25 - 0
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``
 :variable:`CMAKE_CUDA_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` is ``NVIDIA``
 and raise an error if :prop_tgt:`CUDA_ARCHITECTURES` is empty during generation.
 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
 This policy was introduced in CMake version 3.18.  CMake version
 |release| warns when the policy is not set and uses ``OLD`` behavior.
 |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``
 Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
 explicitly.
 explicitly.
 
 
 .. include:: DEPRECATED.txt
 .. 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.

+ 10 - 0
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
 If no suffix is given then code is generated for both real and virtual
 architectures.
 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`
 This property is initialized by the value of the :variable:`CMAKE_CUDA_ARCHITECTURES`
 variable if it is set when a target is created.
 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)
   set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 70-real 72-virtual)
 
 
 Generates code for real architecture ``70`` and virtual architecture ``72``.
 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.

+ 1 - 1
Modules/CMakeDetermineCUDACompiler.cmake

@@ -352,7 +352,7 @@ endif()
 
 
 # If the user didn't set the architectures, then set them to a default.
 # 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, 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")
   set(CMAKE_CUDA_ARCHITECTURES "${detected_architecture}" CACHE STRING "CUDA architectures")
 
 
   if(NOT CMAKE_CUDA_ARCHITECTURES)
   if(NOT CMAKE_CUDA_ARCHITECTURES)

+ 29 - 22
Source/cmGeneratorTarget.cxx

@@ -3044,6 +3044,34 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
 
 
 void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
 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
   struct CudaArchitecture
   {
   {
     std::string name;
     std::string name;
@@ -3054,28 +3082,7 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
 
 
   {
   {
     std::vector<std::string> options;
     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) {
     for (std::string& option : options) {
       CudaArchitecture architecture;
       CudaArchitecture architecture;

+ 12 - 2
Tests/CudaOnly/Architecture/CMakeLists.txt

@@ -1,5 +1,15 @@
-cmake_minimum_required(VERSION 3.17)
+cmake_minimum_required(VERSION 3.18)
 project(Architecture CUDA)
 project(Architecture CUDA)
 
 
-set(CMAKE_CUDA_ARCHITECTURES 52)
 add_executable(Architecture main.cu)
 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)

+ 3 - 0
Tests/RunCMake/CMP0104/CMP0104-OFF.cmake

@@ -0,0 +1,3 @@
+include(CMP0104-Common.cmake)
+
+set_property(TARGET cuda PROPERTY CUDA_ARCHITECTURES OFF)

+ 1 - 0
Tests/RunCMake/CMP0104/RunCMakeTest.cmake

@@ -2,4 +2,5 @@ include(RunCMake)
 
 
 run_cmake(CMP0104-OLD)
 run_cmake(CMP0104-OLD)
 run_cmake(CMP0104-NEW)
 run_cmake(CMP0104-NEW)
+run_cmake(CMP0104-OFF)
 run_cmake(CMP0104-WARN)
 run_cmake(CMP0104-WARN)