1
0
Эх сурвалжийг харах

CUDA: Fix CUDA_STANDARD selection via cxx_std_11 with CXX_STANDARD

When C++ features require a certain C++/CUDA level, verify or update the
standard level target property for each language independently.

While at it, add missing rejection of invalid `CUDA_STANDARD` property
values.

Co-Author: Brad King <[email protected]>
Fixes: #17519
Robert Maynard 8 жил өмнө
parent
commit
4b7618d170

+ 26 - 0
Source/cmMakefile.cxx

@@ -4486,6 +4486,27 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
     }
   }
 
+  const char* existingCudaStandard = target->GetProperty("CUDA_STANDARD");
+  const char* const* existingCudaLevel = nullptr;
+  if (existingCudaStandard) {
+    existingCudaLevel =
+      std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+                   cmStrCmp(existingCudaStandard));
+    if (existingCudaLevel == cm::cend(CXX_STANDARDS)) {
+      std::ostringstream e;
+      e << "The CUDA_STANDARD property on target \"" << target->GetName()
+        << "\" contained an invalid value: \"" << existingCudaStandard
+        << "\".";
+      if (error) {
+        *error = e.str();
+      } else {
+        this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+                                               this->Backtrace);
+      }
+      return false;
+    }
+  }
+
   /* clang-format off */
   const char* const* needCxxLevel =
     needCxx17 ? &CXX_STANDARDS[3]
@@ -4500,6 +4521,11 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
     // the needed C++ features.
     if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
       target->SetProperty("CXX_STANDARD", *needCxxLevel);
+    }
+
+    // Ensure the CUDA language level is high enough to support
+    // the needed C++ features.
+    if (!existingCudaLevel || existingCudaLevel < needCxxLevel) {
       target->SetProperty("CUDA_STANDARD", *needCxxLevel);
     }
   }

+ 1 - 0
Tests/Cuda/CMakeLists.txt

@@ -2,6 +2,7 @@
 ADD_TEST_MACRO(Cuda.Complex CudaComplex)
 ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures)
 ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary)
+ADD_TEST_MACRO(Cuda.MixedStandardLevels MixedStandardLevels)
 ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude)
 ADD_TEST_MACRO(Cuda.ProperLinkFlags ProperLinkFlags)
 ADD_TEST_MACRO(Cuda.WithC CudaWithC)

+ 14 - 0
Tests/Cuda/MixedStandardLevels/CMakeLists.txt

@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.7)
+project(CudaComplex CXX CUDA)
+
+string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
+
+set(CMAKE_CXX_STANDARD 11)
+
+add_executable(MixedStandardLevels main.cu)
+target_compile_features(MixedStandardLevels PUBLIC cxx_std_11)
+
+if(APPLE)
+  # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+  set_property(TARGET MixedStandardLevels PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()

+ 10 - 0
Tests/Cuda/MixedStandardLevels/main.cu

@@ -0,0 +1,10 @@
+
+#include <type_traits>
+
+int main(int argc, char** argv)
+{
+  // Verify that issue #17519 Setting CXX_STANDARD breaks CUDA_STANDARD
+  // selection via cxx_std_11 has been corrected
+  using returnv = std::integral_constant<int, 0>;
+  return returnv::value;
+}