Browse Source

CUDA: Factor out helper for detecting native CUDA architectures

Prepare to use it for other languages.
Brad King 2 years ago
parent
commit
8617c28221

+ 2 - 23
Modules/CMakeCUDACompilerABI.cu

@@ -2,11 +2,8 @@
 #  error "A C or C++ compiler has been selected for CUDA"
 #  error "A C or C++ compiler has been selected for CUDA"
 #endif
 #endif
 
 
-#include <cstdio>
-
-#include <cuda_runtime.h>
-
 #include "CMakeCompilerABI.h"
 #include "CMakeCompilerABI.h"
+#include "CMakeCompilerCUDAArch.h"
 
 
 int main(int argc, char* argv[])
 int main(int argc, char* argv[])
 {
 {
@@ -19,25 +16,7 @@ int main(int argc, char* argv[])
 #endif
 #endif
   static_cast<void>(argv);
   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
     // Convince the compiler that the non-zero return value depends
     // on the info strings so they are not optimized out.
     // on the info strings so they are not optimized out.
     return require ? -1 : 1;
     return require ? -1 : 1;

+ 29 - 0
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;
+}

+ 4 - 45
Modules/CMakeTestCUDACompiler.cmake

@@ -22,51 +22,10 @@ if(CMAKE_CUDA_ABI_COMPILED)
   set(CMAKE_CUDA_COMPILER_WORKS TRUE)
   set(CMAKE_CUDA_COMPILER_WORKS TRUE)
   message(STATUS "Check for working CUDA compiler: ${CMAKE_CUDA_COMPILER} - skipped")
   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()
 endif()
 
 
 # This file is used by EnableLanguage in cmGlobalGenerator to
 # This file is used by EnableLanguage in cmGlobalGenerator to

+ 49 - 0
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()