Jelajahi Sumber

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 tahun lalu
induk
melakukan
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``
 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.

+ 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
 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.

+ 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 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)

+ 29 - 22
Source/cmGeneratorTarget.cxx

@@ -3044,6 +3044,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 +3082,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;

+ 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)
 
-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)

+ 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-NEW)
+run_cmake(CMP0104-OFF)
 run_cmake(CMP0104-WARN)