فهرست منبع

CUDA: Add cuda meta-features (e.g. ``cuda_std_11``) support

Robert Maynard 6 سال پیش
والد
کامیت
2467a2b318
50فایلهای تغییر یافته به همراه652 افزوده شده و 71 حذف شده
  1. 2 0
      Auxiliary/vim/syntax/cmake.vim
  2. 3 3
      Help/command/target_compile_features.rst
  3. 7 6
      Help/manual/cmake-compile-features.7.rst
  4. 1 0
      Help/manual/cmake-properties.7.rst
  5. 1 0
      Help/manual/cmake-variables.7.rst
  6. 30 0
      Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
  7. 2 1
      Help/prop_tgt/COMPILE_FEATURES.rst
  8. 7 0
      Help/release/dev/cuda-gains-meta-features.rst
  9. 11 0
      Help/variable/CMAKE_CUDA_COMPILE_FEATURES.rst
  10. 7 0
      Modules/CMakeCUDACompiler.cmake.in
  11. 1 1
      Modules/CMakeCUDACompilerId.cu.in
  12. 51 0
      Modules/CMakeDetermineCompileFeatures.cmake
  13. 3 0
      Modules/CMakeTestCUDACompiler.cmake
  14. 44 0
      Modules/Compiler/CMakeCommonCompilerMacros.cmake
  15. 19 6
      Modules/Compiler/NVIDIA-CUDA.cmake
  16. 14 0
      Modules/Internal/FeatureTesting.cmake
  17. 17 6
      Source/cmLocalGenerator.cxx
  18. 189 30
      Source/cmMakefile.cxx
  19. 11 1
      Source/cmMakefile.h
  20. 3 0
      Source/cmState.cxx
  21. 7 0
      Source/cmake.h
  22. 3 1
      Tests/CMakeLists.txt
  23. 6 1
      Tests/Cuda/CMakeLists.txt
  24. 4 4
      Tests/Cuda/CXXStandardSetTwice/CMakeLists.txt
  25. 0 0
      Tests/Cuda/CXXStandardSetTwice/main.cu
  26. 14 0
      Tests/Cuda/MixedStandardLevels1/CMakeLists.txt
  27. 7 0
      Tests/Cuda/MixedStandardLevels1/lib.cpp
  28. 9 0
      Tests/Cuda/MixedStandardLevels1/main.cu
  29. 14 0
      Tests/Cuda/MixedStandardLevels2/CMakeLists.txt
  30. 7 0
      Tests/Cuda/MixedStandardLevels2/lib.cpp
  31. 11 0
      Tests/Cuda/MixedStandardLevels2/main.cu
  32. 12 0
      Tests/Cuda/MixedStandardLevels3/CMakeLists.txt
  33. 7 0
      Tests/Cuda/MixedStandardLevels3/lib.cpp
  34. 5 0
      Tests/Cuda/MixedStandardLevels3/main.cu
  35. 14 0
      Tests/Cuda/MixedStandardLevels4/CMakeLists.txt
  36. 16 0
      Tests/Cuda/MixedStandardLevels4/lib.cpp
  37. 5 0
      Tests/Cuda/MixedStandardLevels4/main.cu
  38. 13 0
      Tests/Cuda/MixedStandardLevels5/CMakeLists.txt
  39. 13 0
      Tests/Cuda/MixedStandardLevels5/lib.cpp
  40. 8 0
      Tests/Cuda/MixedStandardLevels5/main.cu
  41. 1 0
      Tests/CudaOnly/CMakeLists.txt
  42. 3 2
      Tests/CudaOnly/EnableStandard/CMakeLists.txt
  43. 2 2
      Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt
  44. 4 2
      Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
  45. 15 0
      Tests/CudaOnly/Standard98/CMakeLists.txt
  46. 8 0
      Tests/CudaOnly/Standard98/main.cu
  47. 12 0
      Tests/ExportImport/Export/CMakeLists.txt
  48. 7 0
      Tests/ExportImport/Import/A/CMakeLists.txt
  49. 1 0
      Tests/ExportImport/InitialCache.cmake.in
  50. 1 5
      Tests/RunCMake/try_compile/RunCMakeTest.cmake

+ 2 - 0
Auxiliary/vim/syntax/cmake.vim

@@ -101,6 +101,7 @@ syn keyword cmakeProperty contained
             \ CLEAN_NO_CUSTOM
             \ CMAKE_CONFIGURE_DEPENDS
             \ CMAKE_CXX_KNOWN_FEATURES
+            \ CMAKE_CUDA_KNOWN_FEATURES
             \ CMAKE_C_KNOWN_FEATURES
             \ CMAKE_ROLE
             \ COMMON_LANGUAGE_RUNTIME
@@ -725,6 +726,7 @@ syn keyword cmakeVariable contained
             \ CMAKE_CUDA_COMPILER_AR
             \ CMAKE_CUDA_COMPILER_ARCHITECTURE_ID
             \ CMAKE_CUDA_COMPILER_EXTERNAL_TOOLCHAIN
+            \ CMAKE_CUDA_COMPILE_FEATURES
             \ CMAKE_CUDA_COMPILER_ID
             \ CMAKE_CUDA_COMPILER_LAUNCHER
             \ CMAKE_CUDA_COMPILER_LOADED

+ 3 - 3
Help/command/target_compile_features.rst

@@ -8,9 +8,9 @@ Add expected compiler features to a target.
   target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
 
 Specifies compiler features required when compiling a given target.  If the
-feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable
-or :variable:`CMAKE_CXX_COMPILE_FEATURES` variable,
-then an error will be reported by CMake.  If the use of the feature requires
+feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES`,
+:variable:`CMAKE_CUDA_COMPILE_FEATURES`, or :variable:`CMAKE_CXX_COMPILE_FEATURES`
+variables, then an error will be reported by CMake.  If the use of the feature requires
 an additional compiler flag, such as ``-std=gnu++11``, the flag will be added
 automatically.
 

+ 7 - 6
Help/manual/cmake-compile-features.7.rst

@@ -19,11 +19,11 @@ While features are typically specified in programming language standards,
 CMake provides a primary user interface based on granular handling of
 the features, not the language standard that introduced the feature.
 
-The :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and
-:prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties contain all the
+The :prop_gbl:`CMAKE_C_KNOWN_FEATURES`, :prop_gbl:`CMAKE_CUDA_KNOWN_FEATURES`,
+and :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties contain all the
 features known to CMake, regardless of compiler support for the feature.
-The :variable:`CMAKE_C_COMPILE_FEATURES` and
-:variable:`CMAKE_CXX_COMPILE_FEATURES` variables contain all features
+The :variable:`CMAKE_C_COMPILE_FEATURES`, :variable:`CMAKE_CUDA_COMPILE_FEATURES`
+, and :variable:`CMAKE_CXX_COMPILE_FEATURES` variables contain all features
 CMake knows are known to the compiler, regardless of language standard
 or compile flags needed to use them.
 
@@ -368,8 +368,9 @@ versions specified for each:
 * all compilers and versions listed above with only meta-features for C++.
 * ``TI``: Texas Instruments compiler.
 
-CMake is currently aware of the :prop_tgt:`CUDA standards <CUDA_STANDARD>`
-from the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
+CMake is currently aware of the :prop_tgt:`CUDA standards <CUDA_STANDARD>` and
+their associated meta-features (e.g. ``cuda_std_11``) available from the
+following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
 versions specified for each:
 
 * ``NVIDIA``: NVIDIA nvcc compiler 7.5+.

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -22,6 +22,7 @@ Properties of Global Scope
    /prop_gbl/AUTOMOC_TARGETS_FOLDER
    /prop_gbl/AUTORCC_SOURCE_GROUP
    /prop_gbl/CMAKE_C_KNOWN_FEATURES
+   /prop_gbl/CMAKE_CUDA_KNOWN_FEATURES
    /prop_gbl/CMAKE_CXX_KNOWN_FEATURES
    /prop_gbl/CMAKE_ROLE
    /prop_gbl/DEBUG_CONFIGURATIONS

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -472,6 +472,7 @@ Variables for Languages
    /variable/CMAKE_COMPILER_IS_GNUCC
    /variable/CMAKE_COMPILER_IS_GNUCXX
    /variable/CMAKE_COMPILER_IS_GNUG77
+   /variable/CMAKE_CUDA_COMPILE_FEATURES
    /variable/CMAKE_CUDA_HOST_COMPILER
    /variable/CMAKE_CUDA_EXTENSIONS
    /variable/CMAKE_CUDA_STANDARD

+ 30 - 0
Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst

@@ -0,0 +1,30 @@
+CMAKE_CUDA_KNOWN_FEATURES
+-------------------------
+
+List of CUDA features known to this version of CMake.
+
+The features listed in this global property may be known to be available to the
+CUDA compiler.  If the feature is available with the C++ compiler, it will
+be listed in the :variable:`CMAKE_CUDA_COMPILE_FEATURES` variable.
+
+The features listed here may be used with the :command:`target_compile_features`
+command.  See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
+
+
+The features known to this version of CMake are:
+
+``cuda_std_03``
+  Compiler mode is at least CUDA/C++ 03.
+
+``cuda_std_11``
+  Compiler mode is at least CUDA/C++ 11.
+
+``cuda_std_14``
+  Compiler mode is at least CUDA/C++ 14.
+
+``cuda_std_17``
+  Compiler mode is at least CUDA/C++ 17.
+
+``cuda_std_20``
+  Compiler mode is at least CUDA/C++ 20.

+ 2 - 1
Help/prop_tgt/COMPILE_FEATURES.rst

@@ -4,7 +4,8 @@ COMPILE_FEATURES
 Compiler features enabled for this target.
 
 The list of features in this property are a subset of the features listed
-in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
+in the :variable:`CMAKE_C_COMPILE_FEATURES`, :variable:`CMAKE_CUDA_COMPILE_FEATURES`, and
+:variable:`CMAKE_CXX_COMPILE_FEATURES` variables.
 
 Contents of ``COMPILE_FEATURES`` may use "generator expressions" with the
 syntax ``$<...>``.  See the :manual:`cmake-generator-expressions(7)` manual for

+ 7 - 0
Help/release/dev/cuda-gains-meta-features.rst

@@ -0,0 +1,7 @@
+cuda-gains-meta-features
+------------------------
+
+* The :manual:`Compile Features <cmake-compile-features(7)>` functionality
+  now offers meta-features for the CUDA language standard levels
+  (e.g. ``cuda_std_03``, ``cuda_std_14``).  See
+  :prop_gbl:`CMAKE_CUDA_KNOWN_FEATURES`.

+ 11 - 0
Help/variable/CMAKE_CUDA_COMPILE_FEATURES.rst

@@ -0,0 +1,11 @@
+CMAKE_CUDA_COMPILE_FEATURES
+---------------------------
+
+List of features known to the CUDA compiler
+
+These features are known to be available for use with the CUDA compiler. This
+list is a subset of the features listed in the
+:prop_gbl:`CMAKE_CUDA_KNOWN_FEATURES` global property.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.

+ 7 - 0
Modules/CMakeCUDACompiler.cmake.in

@@ -4,6 +4,13 @@ set(CMAKE_CUDA_HOST_LINK_LAUNCHER "@CMAKE_CUDA_HOST_LINK_LAUNCHER@")
 set(CMAKE_CUDA_COMPILER_ID "@CMAKE_CUDA_COMPILER_ID@")
 set(CMAKE_CUDA_COMPILER_VERSION "@CMAKE_CUDA_COMPILER_VERSION@")
 set(CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT "@CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_CUDA_COMPILE_FEATURES "@CMAKE_CUDA_COMPILE_FEATURES@")
+set(CMAKE_CUDA03_COMPILE_FEATURES "@CMAKE_CUDA03_COMPILE_FEATURES@")
+set(CMAKE_CUDA11_COMPILE_FEATURES "@CMAKE_CUDA11_COMPILE_FEATURES@")
+set(CMAKE_CUDA14_COMPILE_FEATURES "@CMAKE_CUDA14_COMPILE_FEATURES@")
+set(CMAKE_CUDA17_COMPILE_FEATURES "@CMAKE_CUDA17_COMPILE_FEATURES@")
+set(CMAKE_CUDA20_COMPILE_FEATURES "@CMAKE_CUDA20_COMPILE_FEATURES@")
+
 set(CMAKE_CUDA_SIMULATE_ID "@CMAKE_CUDA_SIMULATE_ID@")
 set(CMAKE_CUDA_SIMULATE_VERSION "@CMAKE_CUDA_SIMULATE_VERSION@")
 @SET_MSVC_CUDA_ARCHITECTURE_ID@

+ 1 - 1
Modules/CMakeCUDACompilerId.cu.in

@@ -26,7 +26,7 @@ const char* info_language_dialect_default = "INFO" ":" "dialect_default["
 #elif __cplusplus >= 201103L
   "11"
 #else
-  "98"
+  "03"
 #endif
 "]";
 

+ 51 - 0
Modules/CMakeDetermineCompileFeatures.cmake

@@ -91,6 +91,57 @@ function(cmake_determine_compile_features lang)
     set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE)
 
     message(CHECK_PASS "done")
+
+  elseif(lang STREQUAL CUDA AND COMMAND cmake_record_cuda_compile_features)
+    message(CHECK_START "Detecting ${lang} compile features")
+
+    set(CMAKE_CUDA03_COMPILE_FEATURES)
+    set(CMAKE_CUDA11_COMPILE_FEATURES)
+    set(CMAKE_CUDA14_COMPILE_FEATURES)
+    set(CMAKE_CUDA17_COMPILE_FEATURES)
+    set(CMAKE_CUDA20_COMPILE_FEATURES)
+
+    include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
+
+    cmake_record_cuda_compile_features()
+
+    if(NOT _result EQUAL 0)
+      message(CHECK_FAIL "failed")
+      return()
+    endif()
+
+  if (CMAKE_CUDA17_COMPILE_FEATURES AND CMAKE_CUDA20_COMPILE_FEATURES)
+      list(REMOVE_ITEM CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES})
+    endif()
+    if (CMAKE_CUDA14_COMPILE_FEATURES AND CMAKE_CUDA17_COMPILE_FEATURES)
+      list(REMOVE_ITEM CMAKE_CUDA17_COMPILE_FEATURES ${CMAKE_CUDA14_COMPILE_FEATURES})
+    endif()
+    if (CMAKE_CUDA11_COMPILE_FEATURES AND CMAKE_CUDA14_COMPILE_FEATURES)
+      list(REMOVE_ITEM CMAKE_CUDA14_COMPILE_FEATURES ${CMAKE_CUDA11_COMPILE_FEATURES})
+    endif()
+    if (CMAKE_CUDA03_COMPILE_FEATURES AND CMAKE_CUDA11_COMPILE_FEATURES)
+      list(REMOVE_ITEM CMAKE_CUDA11_COMPILE_FEATURES ${CMAKE_CUDA03_COMPILE_FEATURES})
+    endif()
+
+    if(NOT CMAKE_CUDA_COMPILE_FEATURES)
+      set(CMAKE_CUDA_COMPILE_FEATURES
+        ${CMAKE_CUDA03_COMPILE_FEATURES}
+        ${CMAKE_CUDA11_COMPILE_FEATURES}
+        ${CMAKE_CUDA14_COMPILE_FEATURES}
+        ${CMAKE_CUDA17_COMPILE_FEATURES}
+        ${CMAKE_CUDA20_COMPILE_FEATURES}
+      )
+    endif()
+
+    set(CMAKE_CUDA_COMPILE_FEATURES ${CMAKE_CUDA_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CUDA03_COMPILE_FEATURES ${CMAKE_CUDA03_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CUDA11_COMPILE_FEATURES ${CMAKE_CUDA11_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CUDA14_COMPILE_FEATURES ${CMAKE_CUDA14_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CUDA17_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES} PARENT_SCOPE)
+
+    message(CHECK_PASS "done")
+
   endif()
 
 endfunction()

+ 3 - 0
Modules/CMakeTestCUDACompiler.cmake

@@ -58,6 +58,9 @@ else()
   # Try to identify the ABI and configure it into CMakeCUDACompiler.cmake
   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
   CMAKE_DETERMINE_COMPILER_ABI(CUDA ${CMAKE_ROOT}/Modules/CMakeCUDACompilerABI.cu)
+  # Try to identify the compiler features
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+  CMAKE_DETERMINE_COMPILE_FEATURES(CUDA)
 
   if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
     set(CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES "${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}")

+ 44 - 0
Modules/Compiler/CMakeCommonCompilerMacros.cmake

@@ -134,3 +134,47 @@ macro(cmake_record_cxx_compile_features)
     unset(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT)
   endif()
 endmacro()
+
+macro(cmake_record_cuda_compile_features)
+  set(_result 0)
+  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA20_STANDARD_COMPILE_OPTION)
+    if(CMAKE_CUDA20_STANDARD__HAS_FULL_SUPPORT)
+      _has_compiler_features_cuda(20)
+    else()
+      _record_compiler_features_cuda(20)
+    endif()
+    unset(CMAKE_CUDA20_STANDARD__HAS_FULL_SUPPORT)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA17_STANDARD_COMPILE_OPTION)
+    if(CMAKE_CUDA17_STANDARD__HAS_FULL_SUPPORT)
+      _has_compiler_features_cuda(17)
+    else()
+      _record_compiler_features_cuda(17)
+    endif()
+    unset(CMAKE_CUDA17_STANDARD__HAS_FULL_SUPPORT)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA14_STANDARD_COMPILE_OPTION)
+    if(CMAKE_CUDA14_STANDARD__HAS_FULL_SUPPORT)
+      _has_compiler_features_cuda(14)
+    else()
+      _record_compiler_features_cuda(14)
+    endif()
+    unset(CMAKE_CUDA14_STANDARD__HAS_FULL_SUPPORT)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA11_STANDARD_COMPILE_OPTION)
+    if(CMAKE_CUDA11_STANDARD__HAS_FULL_SUPPORT)
+      _has_compiler_features_cuda(11)
+    else()
+      _record_compiler_features_cuda(11)
+    endif()
+    unset(CMAKE_CUDA11_STANDARD__HAS_FULL_SUPPORT)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_CUDA03_STANDARD_COMPILE_OPTION)
+    if(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT)
+      _has_compiler_features_cuda(03)
+    else()
+      _record_compiler_features_cuda(03)
+    endif()
+    unset(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT)
+  endif()
+endmacro()

+ 19 - 6
Modules/Compiler/NVIDIA-CUDA.cmake

@@ -1,3 +1,5 @@
+include(Compiler/CMakeCommonCompilerMacros)
+
 set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True)
 set(CMAKE_CUDA_VERBOSE_FLAG "-v")
 set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v")
@@ -42,17 +44,26 @@ set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared)
 set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=)
 
 if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
-  set(CMAKE_CUDA_STANDARD_DEFAULT "")
+  set(CMAKE_CUDA03_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_CUDA03_EXTENSION_COMPILE_OPTION "")
+
+  set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "")
+
+  if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0)
+    set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "")
+    set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "")
+  endif()
 else()
-  set(CMAKE_CUDA_STANDARD_DEFAULT 98)
-  set(CMAKE_CUDA98_STANDARD_COMPILE_OPTION "")
-  set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_CUDA03_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_CUDA03_EXTENSION_COMPILE_OPTION "")
+
   set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "-std=c++11")
   set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11")
 
   if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0)
-    set(CMAKE_CUDA98_STANDARD_COMPILE_OPTION "-std=c++03")
-    set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "-std=c++03")
+    set(CMAKE_CUDA03_STANDARD_COMPILE_OPTION "-std=c++03")
+    set(CMAKE_CUDA03_EXTENSION_COMPILE_OPTION "-std=c++03")
     set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "-std=c++14")
     set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "-std=c++14")
   endif()
@@ -69,3 +80,5 @@ if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0")
   set(CMAKE_CUDA_RESPONSE_FILE_LINK_FLAG "--options-file ")
   set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ")
 endif()
+
+__compiler_check_default_language_standard(CUDA 6.0 03)

+ 14 - 0
Modules/Internal/FeatureTesting.cmake

@@ -89,6 +89,16 @@ macro(_record_compiler_features_cxx std)
   unset(lang_level_has_features)
 endmacro()
 
+macro(_record_compiler_features_cuda std)
+  list(APPEND CMAKE_CUDA${std}_COMPILE_FEATURES cuda_std_${std})
+
+  get_property(lang_level_has_features GLOBAL PROPERTY CMAKE_CUDA${std}_KNOWN_FEATURES)
+  if(lang_level_has_features)
+    _record_compiler_features(CUDA "${CMAKE_CUDA${std}_STANDARD_COMPILE_OPTION}" CMAKE_CUDA${std}_COMPILE_FEATURES)
+  endif()
+  unset(lang_level_has_features)
+endmacro()
+
 macro(_has_compiler_features lang level compile_flags feature_list)
   # presume all known features are supported
   get_property(known_features GLOBAL PROPERTY CMAKE_${lang}${level}_KNOWN_FEATURES)
@@ -103,3 +113,7 @@ macro(_has_compiler_features_cxx std)
   list(APPEND CMAKE_CXX${std}_COMPILE_FEATURES cxx_std_${std})
   _has_compiler_features(CXX ${std} "${CMAKE_CXX${std}_STANDARD_COMPILE_OPTION}" CMAKE_CXX${std}_COMPILE_FEATURES)
 endmacro()
+macro(_has_compiler_features_cuda std)
+  list(APPEND CMAKE_CUDA${std}_COMPILE_FEATURES cuda_std_${std})
+  _has_compiler_features(CUDA ${std} "${CMAKE_CUDA${std}_STANDARD_COMPILE_OPTION}" CMAKE_CUDA${std}_COMPILE_FEATURES)
+endmacro()

+ 17 - 6
Source/cmLocalGenerator.cxx

@@ -696,11 +696,12 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
 
   using LanguagePair = std::pair<std::string, std::string>;
   std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" },
-                                             { "OBJCXX", "CXX" } };
-  std::set<LanguagePair> objcEnabledLanguages;
+                                             { "OBJCXX", "CXX" },
+                                             { "CUDA", "CXX" } };
+  std::set<LanguagePair> inferredEnabledLanguages;
   for (auto const& lang : pairedLanguages) {
     if (this->Makefile->GetState()->GetLanguageEnabled(lang.first)) {
-      objcEnabledLanguages.insert(lang);
+      inferredEnabledLanguages.insert(lang);
     }
   }
 
@@ -739,12 +740,17 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
             target->GetProperty(cmStrCat(lang.second, property)));
         }
       };
-      for (auto const& lang : objcEnabledLanguages) {
+      for (auto const& lang : pairedLanguages) {
         if (copyStandardToObjLang(lang)) {
           copyPropertyToObjLang(lang, "_STANDARD_REQUIRED");
           copyPropertyToObjLang(lang, "_EXTENSIONS");
         }
       }
+      if (const char* standard = target->GetProperty("CUDA_STANDARD")) {
+        if (std::string{ standard } == "98") {
+          target->Target->SetProperty("CUDA_STANDARD", "03");
+        }
+      }
     }
   }
 
@@ -2090,17 +2096,22 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
     langStdMap["OBJC"].emplace_back("99");
     langStdMap["OBJC"].emplace_back("90");
 
+    langStdMap["CUDA"].emplace_back("20");
+    langStdMap["CUDA"].emplace_back("17");
     langStdMap["CUDA"].emplace_back("14");
     langStdMap["CUDA"].emplace_back("11");
-    langStdMap["CUDA"].emplace_back("98");
+    langStdMap["CUDA"].emplace_back("03");
   }
 
   std::string standard(standardProp);
-
+  if (lang == "CUDA" && standard == "98") {
+    standard = "03";
+  }
   std::vector<std::string>& stds = langStdMap[lang];
 
   auto stdIt = std::find(stds.begin(), stds.end(), standard);
   if (stdIt == stds.end()) {
+
     std::string e =
       lang + "_STANDARD is set to invalid value '" + standard + "'";
     this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(

+ 189 - 30
Source/cmMakefile.cxx

@@ -4535,10 +4535,14 @@ static const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE(
 
 static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE(
   FEATURE_STRING) };
+
+static const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE(
+  FEATURE_STRING) };
 #undef FEATURE_STRING
 
 static const char* const C_STANDARDS[] = { "90", "99", "11" };
 static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" };
+static const char* const CUDA_STANDARDS[] = { "03", "11", "14", "17", "20" };
 
 bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
                                           const std::string& feature,
@@ -4578,9 +4582,13 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
 
   target->AppendProperty("COMPILE_FEATURES", feature.c_str());
 
-  return lang == "C" || lang == "OBJC"
-    ? this->AddRequiredTargetCFeature(target, feature, lang, error)
-    : this->AddRequiredTargetCxxFeature(target, feature, lang, error);
+  if (lang == "C" || lang == "OBJC") {
+    return this->AddRequiredTargetCFeature(target, feature, lang, error);
+  }
+  if (lang == "CUDA") {
+    return this->AddRequiredTargetCudaFeature(target, feature, lang, error);
+  }
+  return this->AddRequiredTargetCxxFeature(target, feature, lang, error);
 }
 
 bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
@@ -4604,6 +4612,13 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
     lang = "CXX";
     return true;
   }
+  bool isCudaFeature =
+    std::find_if(cm::cbegin(CUDA_FEATURES) + 1, cm::cend(CUDA_FEATURES),
+                 cmStrCmp(feature)) != cm::cend(CUDA_FEATURES);
+  if (isCudaFeature) {
+    lang = "CUDA";
+    return true;
+  }
   std::ostringstream e;
   if (error) {
     e << "specified";
@@ -4672,9 +4687,13 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
                                        std::string const& lang,
                                        const std::string& feature) const
 {
-  return lang == "C" || lang == "OBJC"
-    ? this->HaveCStandardAvailable(target, feature, lang)
-    : this->HaveCxxStandardAvailable(target, feature, lang);
+  if (lang == "C" || lang == "OBJC") {
+    return this->HaveCStandardAvailable(target, feature, lang);
+  }
+  if (lang == "CUDA") {
+    return this->HaveCudaStandardAvailable(target, feature, lang);
+  }
+  return this->HaveCxxStandardAvailable(target, feature, lang);
 }
 
 bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
@@ -4757,6 +4776,14 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
     return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) !=
       cm::cend(C_STANDARDS);
   }
+  if (lang == "CUDA") {
+    const char* const* rhsIt = std::find_if(
+      cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), cmStrCmp(rhs));
+
+    return std::find_if(rhsIt, cm::cend(CUDA_STANDARDS), cmStrCmp(lhs)) !=
+      cm::cend(CUDA_STANDARDS);
+  }
+
   const char* const* rhsIt = std::find_if(
     cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs));
 
@@ -4901,27 +4928,6 @@ 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(MessageType::FATAL_ERROR,
-                                               e.str(), this->Backtrace);
-      }
-      return false;
-    }
-  }
-
   /* clang-format off */
   const char* const* needCxxLevel =
     needCxx20 ? &CXX_STANDARDS[4]
@@ -4938,11 +4944,164 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
     if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
       target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel);
     }
+  }
+
+  return true;
+}
+
+bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target,
+                                           const std::string& feature,
+                                           std::string const& lang) const
+{
+  const char* defaultCudaStandard =
+    this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+  if (!defaultCudaStandard) {
+    this->IssueMessage(
+      MessageType::INTERNAL_ERROR,
+      cmStrCat("CMAKE_", lang,
+               "_STANDARD_DEFAULT is not set.  COMPILE_FEATURES support "
+               "not fully configured for this compiler."));
+    // Return true so the caller does not try to lookup the default standard.
+    return true;
+  }
+  if (std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
+                   cmStrCmp(defaultCudaStandard)) ==
+      cm::cend(CUDA_STANDARDS)) {
+    const std::string e =
+      cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
+               "invalid value: \"", defaultCudaStandard, "\".");
+    this->IssueMessage(MessageType::INTERNAL_ERROR, e);
+    return false;
+  }
+
+  bool needCuda03 = false;
+  bool needCuda11 = false;
+  bool needCuda14 = false;
+  bool needCuda17 = false;
+  bool needCuda20 = false;
+  this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
+                                needCuda14, needCuda17, needCuda20);
+
+  const char* existingCudaStandard =
+    target->GetProperty(cmStrCat(lang, "_STANDARD"));
+  if (!existingCudaStandard) {
+    existingCudaStandard = defaultCudaStandard;
+  }
 
+  const char* const* existingCudaLevel =
+    std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
+                 cmStrCmp(existingCudaStandard));
+  if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
+    const std::string e = cmStrCat(
+      "The ", lang, "_STANDARD property on target \"", target->GetName(),
+      "\" contained an invalid value: \"", existingCudaStandard, "\".");
+    this->IssueMessage(MessageType::FATAL_ERROR, e);
+    return false;
+  }
+
+  /* clang-format off */
+  const char* const* needCudaLevel =
+    needCuda20 ? &CUDA_STANDARDS[4]
+    : needCuda17 ? &CUDA_STANDARDS[3]
+    : needCuda14 ? &CUDA_STANDARDS[2]
+    : needCuda11 ? &CUDA_STANDARDS[1]
+    : needCuda03 ? &CUDA_STANDARDS[0]
+    : nullptr;
+  /* clang-format on */
+
+  return !needCudaLevel || needCudaLevel <= existingCudaLevel;
+}
+
+void cmMakefile::CheckNeededCudaLanguage(const std::string& feature,
+                                         std::string const& lang,
+                                         bool& needCuda03, bool& needCuda11,
+                                         bool& needCuda14, bool& needCuda17,
+                                         bool& needCuda20) const
+{
+  if (const char* propCuda03 =
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "03_COMPILE_FEATURES"))) {
+    std::vector<std::string> props = cmExpandedList(propCuda03);
+    needCuda03 = cmContains(props, feature);
+  }
+  if (const char* propCuda11 =
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
+    std::vector<std::string> props = cmExpandedList(propCuda11);
+    needCuda11 = cmContains(props, feature);
+  }
+  if (const char* propCuda14 =
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) {
+    std::vector<std::string> props = cmExpandedList(propCuda14);
+    needCuda14 = cmContains(props, feature);
+  }
+  if (const char* propCuda17 =
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) {
+    std::vector<std::string> props = cmExpandedList(propCuda17);
+    needCuda17 = cmContains(props, feature);
+  }
+  if (const char* propCuda20 =
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) {
+    std::vector<std::string> props = cmExpandedList(propCuda20);
+    needCuda20 = cmContains(props, feature);
+  }
+}
+
+bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
+                                              const std::string& feature,
+                                              std::string const& lang,
+                                              std::string* error) const
+{
+  bool needCuda03 = false;
+  bool needCuda11 = false;
+  bool needCuda14 = false;
+  bool needCuda17 = false;
+  bool needCuda20 = false;
+
+  this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
+                                needCuda14, needCuda17, needCuda20);
+
+  const char* existingCudaStandard =
+    target->GetProperty(cmStrCat(lang, "_STANDARD"));
+  if (existingCudaStandard == nullptr) {
+    const char* defaultCudaStandard =
+      this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+    if (defaultCudaStandard && *defaultCudaStandard) {
+      existingCudaStandard = defaultCudaStandard;
+    }
+  }
+  const char* const* existingCudaLevel = nullptr;
+  if (existingCudaStandard) {
+    existingCudaLevel =
+      std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
+                   cmStrCmp(existingCudaStandard));
+    if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
+      const std::string e = cmStrCat(
+        "The ", lang, "_STANDARD property on target \"", target->GetName(),
+        "\" contained an invalid value: \"", existingCudaStandard, "\".");
+      if (error) {
+        *error = e;
+      } else {
+        this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+                                               this->Backtrace);
+      }
+      return false;
+    }
+  }
+
+  /* clang-format off */
+  const char* const* needCudaLevel =
+    needCuda20 ? &CUDA_STANDARDS[4]
+    : needCuda17 ? &CUDA_STANDARDS[3]
+    : needCuda14 ? &CUDA_STANDARDS[2]
+    : needCuda11 ? &CUDA_STANDARDS[1]
+    : needCuda03 ? &CUDA_STANDARDS[0]
+    : nullptr;
+  /* clang-format on */
+
+  if (needCudaLevel) {
     // Ensure the CUDA language level is high enough to support
-    // the needed C++ features.
-    if (!existingCudaLevel || existingCudaLevel < needCxxLevel) {
-      target->SetProperty("CUDA_STANDARD", *needCxxLevel);
+    // the needed CUDA features.
+    if (!existingCudaLevel || existingCudaLevel < needCudaLevel) {
+      target->SetProperty("CUDA_STANDARD", *needCudaLevel);
     }
   }
 

+ 11 - 1
Source/cmMakefile.h

@@ -1138,11 +1138,14 @@ private:
   bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
                                  std::string const& lang,
                                  std::string* error = nullptr) const;
-
   bool AddRequiredTargetCxxFeature(cmTarget* target,
                                    const std::string& feature,
                                    std::string const& lang,
                                    std::string* error = nullptr) const;
+  bool AddRequiredTargetCudaFeature(cmTarget* target,
+                                    const std::string& feature,
+                                    std::string const& lang,
+                                    std::string* error = nullptr) const;
 
   void CheckNeededCLanguage(const std::string& feature,
                             std::string const& lang, bool& needC90,
@@ -1151,6 +1154,10 @@ private:
                               std::string const& lang, bool& needCxx98,
                               bool& needCxx11, bool& needCxx14,
                               bool& needCxx17, bool& needCxx20) const;
+  void CheckNeededCudaLanguage(const std::string& feature,
+                               std::string const& lang, bool& needCuda03,
+                               bool& needCuda11, bool& needCuda14,
+                               bool& needCuda17, bool& needCuda20) const;
 
   bool HaveCStandardAvailable(cmTarget const* target,
                               const std::string& feature,
@@ -1158,6 +1165,9 @@ private:
   bool HaveCxxStandardAvailable(cmTarget const* target,
                                 const std::string& feature,
                                 std::string const& lang) const;
+  bool HaveCudaStandardAvailable(cmTarget const* target,
+                                 const std::string& feature,
+                                 std::string const& lang) const;
 
   void CheckForUnusedVariables() const;
 

+ 3 - 0
Source/cmState.cxx

@@ -615,6 +615,9 @@ const char* cmState::GetGlobalProperty(const std::string& prop)
   if (prop == "CMAKE_CXX14_KNOWN_FEATURES") {
     return &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1];
   }
+  if (prop == "CMAKE_CUDA_KNOWN_FEATURES") {
+    return &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1];
+  }
 
 #undef STRING_LIST_ELEMENT
   return this->GlobalProperties.GetPropertyValue(prop);

+ 7 - 0
Source/cmake.h

@@ -746,4 +746,11 @@ private:
   FOR_EACH_CXX11_FEATURE(F)                                                   \
   FOR_EACH_CXX14_FEATURE(F)
 
+#define FOR_EACH_CUDA_FEATURE(F)                                              \
+  F(cuda_std_03)                                                              \
+  F(cuda_std_11)                                                              \
+  F(cuda_std_14)                                                              \
+  F(cuda_std_17)                                                              \
+  F(cuda_std_20)
+
 #endif

+ 3 - 1
Tests/CMakeLists.txt

@@ -436,7 +436,9 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(Assembler HelloAsm)
   ADD_TEST_MACRO(SourceGroups SourceGroups)
   ADD_TEST_MACRO(Preprocess Preprocess)
-  set(ExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM})
+  set(ExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
+                                 -DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA}
+                                 )
   ADD_TEST_MACRO(ExportImport ExportImport)
   ADD_TEST_MACRO(Unset Unset)
   ADD_TEST_MACRO(PolicyScope PolicyScope)

+ 6 - 1
Tests/Cuda/CMakeLists.txt

@@ -1,8 +1,13 @@
 
 ADD_TEST_MACRO(Cuda.Complex CudaComplex)
 ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures)
+ADD_TEST_MACRO(Cuda.CXXStandardSetTwice CXXStandardSetTwice)
 ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary)
-ADD_TEST_MACRO(Cuda.MixedStandardLevels MixedStandardLevels)
+ADD_TEST_MACRO(Cuda.MixedStandardLevels1 MixedStandardLevels1)
+ADD_TEST_MACRO(Cuda.MixedStandardLevels2 MixedStandardLevels2)
+ADD_TEST_MACRO(Cuda.MixedStandardLevels3 MixedStandardLevels3)
+ADD_TEST_MACRO(Cuda.MixedStandardLevels4 MixedStandardLevels4)
+ADD_TEST_MACRO(Cuda.MixedStandardLevels5 MixedStandardLevels5)
 ADD_TEST_MACRO(Cuda.NotEnabled CudaNotEnabled)
 ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude)
 ADD_TEST_MACRO(Cuda.ProperDeviceLibraries ProperDeviceLibraries)

+ 4 - 4
Tests/Cuda/MixedStandardLevels/CMakeLists.txt → Tests/Cuda/CXXStandardSetTwice/CMakeLists.txt

@@ -1,14 +1,14 @@
 cmake_minimum_required(VERSION 3.7)
-project(MixedStandardLevels CXX CUDA)
+project(CXXStandardSetTwice 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)
+add_executable(CXXStandardSetTwice main.cu)
+target_compile_features(CXXStandardSetTwice 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})
+  set_property(TARGET CXXStandardSetTwice PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
 endif()

+ 0 - 0
Tests/Cuda/MixedStandardLevels/main.cu → Tests/Cuda/CXXStandardSetTwice/main.cu


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

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

+ 7 - 0
Tests/Cuda/MixedStandardLevels1/lib.cpp

@@ -0,0 +1,7 @@
+
+int func(int A, int B)
+{
+  // Verify that we have at least c++14
+  auto mult_func = [](auto a, auto b) { return a * b; };
+  return mult_func(A, B);
+}

+ 9 - 0
Tests/Cuda/MixedStandardLevels1/main.cu

@@ -0,0 +1,9 @@
+
+#include <type_traits>
+
+int main(int argc, char** argv)
+{
+  // Verify that we have at least c++11
+  using returnv = std::integral_constant<int, 0>;
+  return returnv::value;
+}

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

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

+ 7 - 0
Tests/Cuda/MixedStandardLevels2/lib.cpp

@@ -0,0 +1,7 @@
+
+int func(int A, int B)
+{
+  // Verify that we have at least c++14
+  auto mult_func = [](auto a, auto b) { return a * b; };
+  return mult_func(A, B);
+}

+ 11 - 0
Tests/Cuda/MixedStandardLevels2/main.cu

@@ -0,0 +1,11 @@
+
+#if __cplusplus < 201103L && !defined(_MSC_VER)
+#  error "invalid standard value"
+#endif
+#include <type_traits>
+
+int main(int argc, char** argv)
+{
+  using returnv = std::integral_constant<int, 0>;
+  return returnv::value;
+}

+ 12 - 0
Tests/Cuda/MixedStandardLevels3/CMakeLists.txt

@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 3.7)
+project(MixedStandardLevels3 CXX CUDA)
+
+string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
+
+add_executable(MixedStandardLevels3 main.cu lib.cpp)
+target_compile_features(MixedStandardLevels3 PUBLIC cuda_std_03 cxx_std_14)
+
+if(APPLE)
+  # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+  set_property(TARGET MixedStandardLevels3 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()

+ 7 - 0
Tests/Cuda/MixedStandardLevels3/lib.cpp

@@ -0,0 +1,7 @@
+
+int func(int A, int B)
+{
+  // Verify that we have at least c++14
+  auto mult_func = [](auto a, auto b) { return a * b; };
+  return mult_func(A, B);
+}

+ 5 - 0
Tests/Cuda/MixedStandardLevels3/main.cu

@@ -0,0 +1,5 @@
+
+int main(int argc, char** argv)
+{
+  return 0;
+}

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

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

+ 16 - 0
Tests/Cuda/MixedStandardLevels4/lib.cpp

@@ -0,0 +1,16 @@
+
+
+constexpr int func(int A, int B)
+{
+#if defined(_MSC_VER) && _MSC_VER < 1913
+  // no suppport for extended constexpr
+  return B * A;
+#else
+  // Verify that we have at least c++14
+  if (A < B) {
+    return A + B;
+  } else {
+    return B * A;
+  }
+#endif
+}

+ 5 - 0
Tests/Cuda/MixedStandardLevels4/main.cu

@@ -0,0 +1,5 @@
+
+int main(int argc, char** argv)
+{
+  return 0;
+}

+ 13 - 0
Tests/Cuda/MixedStandardLevels5/CMakeLists.txt

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

+ 13 - 0
Tests/Cuda/MixedStandardLevels5/lib.cpp

@@ -0,0 +1,13 @@
+
+#if __cplusplus >= 201103L
+#  error "invalid standard value"
+#endif
+int func(int A, int B)
+{
+  // Verify that we have at least c++14
+  if (A < B) {
+    return A + B;
+  } else {
+    return B * A;
+  }
+}

+ 8 - 0
Tests/Cuda/MixedStandardLevels5/main.cu

@@ -0,0 +1,8 @@
+
+#if __cplusplus >= 201103L
+#  error "invalid standard value"
+#endif
+int main(int argc, char** argv)
+{
+  return 0;
+}

+ 1 - 0
Tests/CudaOnly/CMakeLists.txt

@@ -5,6 +5,7 @@ ADD_TEST_MACRO(CudaOnly.ExportPTX CudaOnlyExportPTX)
 ADD_TEST_MACRO(CudaOnly.GPUDebugFlag CudaOnlyGPUDebugFlag)
 ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
 ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
+ADD_TEST_MACRO(CudaOnly.Standard98 CudaOnlyStandard98)
 ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs)
 
 add_test(NAME CudaOnly.DontResolveDeviceSymbols COMMAND

+ 3 - 2
Tests/CudaOnly/EnableStandard/CMakeLists.txt

@@ -11,8 +11,9 @@ add_library(CUDADynamic11 SHARED shared.cu)
 add_executable(CudaOnlyEnableStandard main.cu)
 target_link_libraries(CudaOnlyEnableStandard PRIVATE CUDAStatic11 CUDADynamic11)
 
-set_target_properties(CUDAStatic11 CUDADynamic11 PROPERTIES CUDA_STANDARD 11)
-set_target_properties(CUDAStatic11 CUDADynamic11 PROPERTIES CUDA_STANDARD_REQUIRED TRUE)
+target_compile_features(CUDADynamic11 PRIVATE cuda_std_11)
+set_target_properties(CUDAStatic11 PROPERTIES CUDA_STANDARD 11)
+set_target_properties(CUDAStatic11 PROPERTIES CUDA_STANDARD_REQUIRED TRUE)
 
 #Verify CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES
 foreach(dir ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})

+ 2 - 2
Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt

@@ -22,11 +22,11 @@ endif()
 # 3. Verify that we can't use those device symbols from anything that links
 # to the static library
 string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=[sm_30] -gencode arch=compute_50,code=\\\"compute_50\\\"")
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CUDA_STANDARD 11)
 
 add_library(CUDAResolveDeviceDepsA STATIC file1.cu)
 add_library(CUDAResolveDeviceDepsB STATIC file2.cu)
+target_compile_features(CUDAResolveDeviceDepsA PUBLIC cuda_std_11)
+target_compile_features(CUDAResolveDeviceDepsB PUBLIC cuda_std_11)
 set_target_properties(CUDAResolveDeviceDepsA CUDAResolveDeviceDepsB
                       PROPERTIES
                       CUDA_SEPARABLE_COMPILATION ON

+ 4 - 2
Tests/CudaOnly/SeparateCompilation/CMakeLists.txt

@@ -11,11 +11,10 @@ project (SeparateCompilation CUDA)
 #all containing cuda separable compilation code links properly
 string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=\\\"compute_30,sm_30,sm_35\\\"")
 string(APPEND CMAKE_CUDA_FLAGS " --generate-code=arch=compute_50,code=[compute_50,sm_50,sm_52]")
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CUDA_STANDARD 11)
 
 set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
 add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu)
+target_compile_features(CUDASeparateLibA PRIVATE cuda_std_11)
 get_property(sep_comp TARGET CUDASeparateLibA PROPERTY CUDA_SEPARABLE_COMPILATION)
 if(NOT sep_comp)
   message(FATAL_ERROR "CUDA_SEPARABLE_COMPILATION not initialized")
@@ -36,11 +35,14 @@ endif()
 #cause a segv when trying to run the executable
 #
 add_library(CUDASeparateLibB STATIC file4.cu file5.cu)
+target_compile_features(CUDASeparateLibB PRIVATE cuda_std_11)
 target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA)
 
 add_executable(CudaOnlySeparateCompilation main.cu)
 target_link_libraries(CudaOnlySeparateCompilation
                       PRIVATE CUDASeparateLibB)
+set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD 11)
+set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD_REQUIRED TRUE)
 
 set_target_properties(CUDASeparateLibA
                       CUDASeparateLibB

+ 15 - 0
Tests/CudaOnly/Standard98/CMakeLists.txt

@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.7)
+project(CudaOnlyStandard98 CUDA)
+
+string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
+
+# Support setting CUDA Standard to 98 which internally gets transformed to
+# CUDA03
+set(CMAKE_CUDA_STANDARD 98)
+
+add_executable(CudaOnlyStandard98 main.cu)
+
+if(APPLE)
+  # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+  set_property(TARGET CudaOnlyStandard98 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()

+ 8 - 0
Tests/CudaOnly/Standard98/main.cu

@@ -0,0 +1,8 @@
+
+#if __cplusplus >= 201103L
+#  error "invalid standard value"
+#endif
+int main(int argc, char** argv)
+{
+  return 0;
+}

+ 12 - 0
Tests/ExportImport/Export/CMakeLists.txt

@@ -646,6 +646,18 @@ if(CMAKE_GENERATOR MATCHES "Make|Ninja")
   export(TARGETS testLinkDepends NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
 endif()
 
+#------------------------------------------------------------------------------
+# test export of CUDA language
+if(CMake_TEST_CUDA)
+  enable_language(CUDA)
+  add_library(cudaInterfaceLib INTERFACE)
+  target_compile_features(cudaInterfaceLib INTERFACE $<BUILD_INTERFACE:cuda_std_11> $<INSTALL_INTERFACE:cuda_std_14>)
+
+  install(TARGETS cudaInterfaceLib
+    EXPORT RequiredExp DESTINATION lib)
+  export(TARGETS cudaInterfaceLib NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
+endif()
+
 # Test the presence of targets named the same as languages.
 # IMPORTED_LINK_INTERFACE_LANGUAGES entries should not be targets.
 add_library(C INTERFACE)

+ 7 - 0
Tests/ExportImport/Import/A/CMakeLists.txt

@@ -499,3 +499,10 @@ if(CMAKE_GENERATOR MATCHES "Make|Ninja")
   checkForProperty(bld_testLinkDepends "INTERFACE_LINK_DEPENDS" "BUILD_LINK_DEPENDS")
   checkForProperty(Req::testLinkDepends "INTERFACE_LINK_DEPENDS" "${CMAKE_INSTALL_PREFIX}/INSTALL_LINK_DEPENDS")
 endif()
+
+#------------------------------------------------------------------------------
+# test import of CUDA language level
+if(CMake_TEST_CUDA)
+  checkForProperty(bld_cudaInterfaceLib "INTERFACE_COMPILE_FEATURES" "cuda_std_11")
+  checkForProperty(Req::cudaInterfaceLib "INTERFACE_COMPILE_FEATURES" "cuda_std_14")
+endif()

+ 1 - 0
Tests/ExportImport/InitialCache.cmake.in

@@ -14,3 +14,4 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "@CMAKE_CXX_FLAGS_RELWITHDEBINFO@" CACHE STRI
 set(CMAKE_INSTALL_PREFIX "@ExportImport_BINARY_DIR@/Root" CACHE STRING "Installation Prefix")
 set(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH")
 set(CMAKE_GNUtoMS "@ExportImport_GNUtoMS@" CACHE BOOL "CMAKE_GNUtoMS")
+set(CMake_TEST_CUDA "@CMake_TEST_CUDA@" CACHE BOOL "CMake_TEST_CUDA")

+ 1 - 5
Tests/RunCMake/try_compile/RunCMakeTest.cmake

@@ -49,11 +49,7 @@ if(CMAKE_OBJCXX_STANDARD_DEFAULT)
   run_cmake(ObjCxxStandard)
 endif()
 if(CMake_TEST_CUDA)
-  if(CMAKE_HOST_WIN32)
-    run_cmake(CudaStandardNoDefault)
-  else()
-    run_cmake(CudaStandard)
-  endif()
+  run_cmake(CudaStandard)
 endif()
 if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4)
   run_cmake(CStandardGNU)