Browse Source

Merge topic 'add_cuda_meta_compiler_features'

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

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3992
Brad King 5 years ago
parent
commit
4fb9c88042
50 changed files with 652 additions and 71 deletions
  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
             \ CLEAN_NO_CUSTOM
             \ CMAKE_CONFIGURE_DEPENDS
             \ CMAKE_CONFIGURE_DEPENDS
             \ CMAKE_CXX_KNOWN_FEATURES
             \ CMAKE_CXX_KNOWN_FEATURES
+            \ CMAKE_CUDA_KNOWN_FEATURES
             \ CMAKE_C_KNOWN_FEATURES
             \ CMAKE_C_KNOWN_FEATURES
             \ CMAKE_ROLE
             \ CMAKE_ROLE
             \ COMMON_LANGUAGE_RUNTIME
             \ COMMON_LANGUAGE_RUNTIME
@@ -725,6 +726,7 @@ syn keyword cmakeVariable contained
             \ CMAKE_CUDA_COMPILER_AR
             \ CMAKE_CUDA_COMPILER_AR
             \ CMAKE_CUDA_COMPILER_ARCHITECTURE_ID
             \ CMAKE_CUDA_COMPILER_ARCHITECTURE_ID
             \ CMAKE_CUDA_COMPILER_EXTERNAL_TOOLCHAIN
             \ CMAKE_CUDA_COMPILER_EXTERNAL_TOOLCHAIN
+            \ CMAKE_CUDA_COMPILE_FEATURES
             \ CMAKE_CUDA_COMPILER_ID
             \ CMAKE_CUDA_COMPILER_ID
             \ CMAKE_CUDA_COMPILER_LAUNCHER
             \ CMAKE_CUDA_COMPILER_LAUNCHER
             \ CMAKE_CUDA_COMPILER_LOADED
             \ 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> [...])
   target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
 
 
 Specifies compiler features required when compiling a given target.  If the
 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
 an additional compiler flag, such as ``-std=gnu++11``, the flag will be added
 automatically.
 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
 CMake provides a primary user interface based on granular handling of
 the features, not the language standard that introduced the feature.
 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.
 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
 CMake knows are known to the compiler, regardless of language standard
 or compile flags needed to use them.
 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++.
 * all compilers and versions listed above with only meta-features for C++.
 * ``TI``: Texas Instruments compiler.
 * ``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:
 versions specified for each:
 
 
 * ``NVIDIA``: NVIDIA nvcc compiler 7.5+.
 * ``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/AUTOMOC_TARGETS_FOLDER
    /prop_gbl/AUTORCC_SOURCE_GROUP
    /prop_gbl/AUTORCC_SOURCE_GROUP
    /prop_gbl/CMAKE_C_KNOWN_FEATURES
    /prop_gbl/CMAKE_C_KNOWN_FEATURES
+   /prop_gbl/CMAKE_CUDA_KNOWN_FEATURES
    /prop_gbl/CMAKE_CXX_KNOWN_FEATURES
    /prop_gbl/CMAKE_CXX_KNOWN_FEATURES
    /prop_gbl/CMAKE_ROLE
    /prop_gbl/CMAKE_ROLE
    /prop_gbl/DEBUG_CONFIGURATIONS
    /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_GNUCC
    /variable/CMAKE_COMPILER_IS_GNUCXX
    /variable/CMAKE_COMPILER_IS_GNUCXX
    /variable/CMAKE_COMPILER_IS_GNUG77
    /variable/CMAKE_COMPILER_IS_GNUG77
+   /variable/CMAKE_CUDA_COMPILE_FEATURES
    /variable/CMAKE_CUDA_HOST_COMPILER
    /variable/CMAKE_CUDA_HOST_COMPILER
    /variable/CMAKE_CUDA_EXTENSIONS
    /variable/CMAKE_CUDA_EXTENSIONS
    /variable/CMAKE_CUDA_STANDARD
    /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.
 Compiler features enabled for this target.
 
 
 The list of features in this property are a subset of the features listed
 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
 Contents of ``COMPILE_FEATURES`` may use "generator expressions" with the
 syntax ``$<...>``.  See the :manual:`cmake-generator-expressions(7)` manual for
 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_ID "@CMAKE_CUDA_COMPILER_ID@")
 set(CMAKE_CUDA_COMPILER_VERSION "@CMAKE_CUDA_COMPILER_VERSION@")
 set(CMAKE_CUDA_COMPILER_VERSION "@CMAKE_CUDA_COMPILER_VERSION@")
 set(CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT "@CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT@")
 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_ID "@CMAKE_CUDA_SIMULATE_ID@")
 set(CMAKE_CUDA_SIMULATE_VERSION "@CMAKE_CUDA_SIMULATE_VERSION@")
 set(CMAKE_CUDA_SIMULATE_VERSION "@CMAKE_CUDA_SIMULATE_VERSION@")
 @SET_MSVC_CUDA_ARCHITECTURE_ID@
 @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
 #elif __cplusplus >= 201103L
   "11"
   "11"
 #else
 #else
-  "98"
+  "03"
 #endif
 #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)
     set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE)
 
 
     message(CHECK_PASS "done")
     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()
   endif()
 
 
 endfunction()
 endfunction()

+ 3 - 0
Modules/CMakeTestCUDACompiler.cmake

@@ -58,6 +58,9 @@ else()
   # Try to identify the ABI and configure it into CMakeCUDACompiler.cmake
   # Try to identify the ABI and configure it into CMakeCUDACompiler.cmake
   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
   CMAKE_DETERMINE_COMPILER_ABI(CUDA ${CMAKE_ROOT}/Modules/CMakeCUDACompilerABI.cu)
   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")
   if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
     set(CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES "${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}")
     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)
     unset(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT)
   endif()
   endif()
 endmacro()
 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_COMPILER_HAS_DEVICE_LINK_PHASE True)
 set(CMAKE_CUDA_VERBOSE_FLAG "-v")
 set(CMAKE_CUDA_VERBOSE_FLAG "-v")
 set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-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=)
 set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=)
 
 
 if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
 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()
 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_STANDARD_COMPILE_OPTION "-std=c++11")
   set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11")
   set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11")
 
 
   if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0)
   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_STANDARD_COMPILE_OPTION "-std=c++14")
     set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "-std=c++14")
     set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "-std=c++14")
   endif()
   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_LINK_FLAG "--options-file ")
   set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ")
   set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ")
 endif()
 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)
   unset(lang_level_has_features)
 endmacro()
 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)
 macro(_has_compiler_features lang level compile_flags feature_list)
   # presume all known features are supported
   # presume all known features are supported
   get_property(known_features GLOBAL PROPERTY CMAKE_${lang}${level}_KNOWN_FEATURES)
   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})
   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)
   _has_compiler_features(CXX ${std} "${CMAKE_CXX${std}_STANDARD_COMPILE_OPTION}" CMAKE_CXX${std}_COMPILE_FEATURES)
 endmacro()
 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>;
   using LanguagePair = std::pair<std::string, std::string>;
   std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" },
   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) {
   for (auto const& lang : pairedLanguages) {
     if (this->Makefile->GetState()->GetLanguageEnabled(lang.first)) {
     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)));
             target->GetProperty(cmStrCat(lang.second, property)));
         }
         }
       };
       };
-      for (auto const& lang : objcEnabledLanguages) {
+      for (auto const& lang : pairedLanguages) {
         if (copyStandardToObjLang(lang)) {
         if (copyStandardToObjLang(lang)) {
           copyPropertyToObjLang(lang, "_STANDARD_REQUIRED");
           copyPropertyToObjLang(lang, "_STANDARD_REQUIRED");
           copyPropertyToObjLang(lang, "_EXTENSIONS");
           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("99");
     langStdMap["OBJC"].emplace_back("90");
     langStdMap["OBJC"].emplace_back("90");
 
 
+    langStdMap["CUDA"].emplace_back("20");
+    langStdMap["CUDA"].emplace_back("17");
     langStdMap["CUDA"].emplace_back("14");
     langStdMap["CUDA"].emplace_back("14");
     langStdMap["CUDA"].emplace_back("11");
     langStdMap["CUDA"].emplace_back("11");
-    langStdMap["CUDA"].emplace_back("98");
+    langStdMap["CUDA"].emplace_back("03");
   }
   }
 
 
   std::string standard(standardProp);
   std::string standard(standardProp);
-
+  if (lang == "CUDA" && standard == "98") {
+    standard = "03";
+  }
   std::vector<std::string>& stds = langStdMap[lang];
   std::vector<std::string>& stds = langStdMap[lang];
 
 
   auto stdIt = std::find(stds.begin(), stds.end(), standard);
   auto stdIt = std::find(stds.begin(), stds.end(), standard);
   if (stdIt == stds.end()) {
   if (stdIt == stds.end()) {
+
     std::string e =
     std::string e =
       lang + "_STANDARD is set to invalid value '" + standard + "'";
       lang + "_STANDARD is set to invalid value '" + standard + "'";
     this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
     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(
 static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE(
   FEATURE_STRING) };
   FEATURE_STRING) };
+
+static const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE(
+  FEATURE_STRING) };
 #undef FEATURE_STRING
 #undef FEATURE_STRING
 
 
 static const char* const C_STANDARDS[] = { "90", "99", "11" };
 static const char* const C_STANDARDS[] = { "90", "99", "11" };
 static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" };
 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,
 bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
                                           const std::string& feature,
                                           const std::string& feature,
@@ -4578,9 +4582,13 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
 
 
   target->AppendProperty("COMPILE_FEATURES", feature.c_str());
   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,
 bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
@@ -4604,6 +4612,13 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
     lang = "CXX";
     lang = "CXX";
     return true;
     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;
   std::ostringstream e;
   if (error) {
   if (error) {
     e << "specified";
     e << "specified";
@@ -4672,9 +4687,13 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
                                        std::string const& lang,
                                        std::string const& lang,
                                        const std::string& feature) const
                                        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,
 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)) !=
     return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) !=
       cm::cend(C_STANDARDS);
       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(
   const char* const* rhsIt = std::find_if(
     cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs));
     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 */
   /* clang-format off */
   const char* const* needCxxLevel =
   const char* const* needCxxLevel =
     needCxx20 ? &CXX_STANDARDS[4]
     needCxx20 ? &CXX_STANDARDS[4]
@@ -4938,11 +4944,164 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
     if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
     if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
       target->SetProperty(cmStrCat(lang, "_STANDARD"), *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
     // 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,
   bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
                                  std::string const& lang,
                                  std::string const& lang,
                                  std::string* error = nullptr) const;
                                  std::string* error = nullptr) const;
-
   bool AddRequiredTargetCxxFeature(cmTarget* target,
   bool AddRequiredTargetCxxFeature(cmTarget* target,
                                    const std::string& feature,
                                    const std::string& feature,
                                    std::string const& lang,
                                    std::string const& lang,
                                    std::string* error = nullptr) const;
                                    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,
   void CheckNeededCLanguage(const std::string& feature,
                             std::string const& lang, bool& needC90,
                             std::string const& lang, bool& needC90,
@@ -1151,6 +1154,10 @@ private:
                               std::string const& lang, bool& needCxx98,
                               std::string const& lang, bool& needCxx98,
                               bool& needCxx11, bool& needCxx14,
                               bool& needCxx11, bool& needCxx14,
                               bool& needCxx17, bool& needCxx20) const;
                               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,
   bool HaveCStandardAvailable(cmTarget const* target,
                               const std::string& feature,
                               const std::string& feature,
@@ -1158,6 +1165,9 @@ private:
   bool HaveCxxStandardAvailable(cmTarget const* target,
   bool HaveCxxStandardAvailable(cmTarget const* target,
                                 const std::string& feature,
                                 const std::string& feature,
                                 std::string const& lang) const;
                                 std::string const& lang) const;
+  bool HaveCudaStandardAvailable(cmTarget const* target,
+                                 const std::string& feature,
+                                 std::string const& lang) const;
 
 
   void CheckForUnusedVariables() 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") {
   if (prop == "CMAKE_CXX14_KNOWN_FEATURES") {
     return &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1];
     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
 #undef STRING_LIST_ELEMENT
   return this->GlobalProperties.GetPropertyValue(prop);
   return this->GlobalProperties.GetPropertyValue(prop);

+ 7 - 0
Source/cmake.h

@@ -746,4 +746,11 @@ private:
   FOR_EACH_CXX11_FEATURE(F)                                                   \
   FOR_EACH_CXX11_FEATURE(F)                                                   \
   FOR_EACH_CXX14_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
 #endif

+ 3 - 1
Tests/CMakeLists.txt

@@ -436,7 +436,9 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(Assembler HelloAsm)
   ADD_TEST_MACRO(Assembler HelloAsm)
   ADD_TEST_MACRO(SourceGroups SourceGroups)
   ADD_TEST_MACRO(SourceGroups SourceGroups)
   ADD_TEST_MACRO(Preprocess Preprocess)
   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(ExportImport ExportImport)
   ADD_TEST_MACRO(Unset Unset)
   ADD_TEST_MACRO(Unset Unset)
   ADD_TEST_MACRO(PolicyScope PolicyScope)
   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.Complex CudaComplex)
 ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures)
 ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures)
+ADD_TEST_MACRO(Cuda.CXXStandardSetTwice CXXStandardSetTwice)
 ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary)
 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.NotEnabled CudaNotEnabled)
 ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude)
 ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude)
 ADD_TEST_MACRO(Cuda.ProperDeviceLibraries ProperDeviceLibraries)
 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)
 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")
 string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
 
 
 set(CMAKE_CXX_STANDARD 11)
 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)
 if(APPLE)
   # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
   # 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()
 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.GPUDebugFlag CudaOnlyGPUDebugFlag)
 ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
 ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
 ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
 ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
+ADD_TEST_MACRO(CudaOnly.Standard98 CudaOnlyStandard98)
 ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs)
 ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs)
 
 
 add_test(NAME CudaOnly.DontResolveDeviceSymbols COMMAND
 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)
 add_executable(CudaOnlyEnableStandard main.cu)
 target_link_libraries(CudaOnlyEnableStandard PRIVATE CUDAStatic11 CUDADynamic11)
 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
 #Verify CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES
 foreach(dir ${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
 # 3. Verify that we can't use those device symbols from anything that links
 # to the static library
 # to the static library
 string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=[sm_30] -gencode arch=compute_50,code=\\\"compute_50\\\"")
 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(CUDAResolveDeviceDepsA STATIC file1.cu)
 add_library(CUDAResolveDeviceDepsB STATIC file2.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
 set_target_properties(CUDAResolveDeviceDepsA CUDAResolveDeviceDepsB
                       PROPERTIES
                       PROPERTIES
                       CUDA_SEPARABLE_COMPILATION ON
                       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
 #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 " -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]")
 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)
 set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
 add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu)
 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)
 get_property(sep_comp TARGET CUDASeparateLibA PROPERTY CUDA_SEPARABLE_COMPILATION)
 if(NOT sep_comp)
 if(NOT sep_comp)
   message(FATAL_ERROR "CUDA_SEPARABLE_COMPILATION not initialized")
   message(FATAL_ERROR "CUDA_SEPARABLE_COMPILATION not initialized")
@@ -36,11 +35,14 @@ endif()
 #cause a segv when trying to run the executable
 #cause a segv when trying to run the executable
 #
 #
 add_library(CUDASeparateLibB STATIC file4.cu file5.cu)
 add_library(CUDASeparateLibB STATIC file4.cu file5.cu)
+target_compile_features(CUDASeparateLibB PRIVATE cuda_std_11)
 target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA)
 target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA)
 
 
 add_executable(CudaOnlySeparateCompilation main.cu)
 add_executable(CudaOnlySeparateCompilation main.cu)
 target_link_libraries(CudaOnlySeparateCompilation
 target_link_libraries(CudaOnlySeparateCompilation
                       PRIVATE CUDASeparateLibB)
                       PRIVATE CUDASeparateLibB)
+set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD 11)
+set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD_REQUIRED TRUE)
 
 
 set_target_properties(CUDASeparateLibA
 set_target_properties(CUDASeparateLibA
                       CUDASeparateLibB
                       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)
   export(TARGETS testLinkDepends NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
 endif()
 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.
 # Test the presence of targets named the same as languages.
 # IMPORTED_LINK_INTERFACE_LANGUAGES entries should not be targets.
 # IMPORTED_LINK_INTERFACE_LANGUAGES entries should not be targets.
 add_library(C INTERFACE)
 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(bld_testLinkDepends "INTERFACE_LINK_DEPENDS" "BUILD_LINK_DEPENDS")
   checkForProperty(Req::testLinkDepends "INTERFACE_LINK_DEPENDS" "${CMAKE_INSTALL_PREFIX}/INSTALL_LINK_DEPENDS")
   checkForProperty(Req::testLinkDepends "INTERFACE_LINK_DEPENDS" "${CMAKE_INSTALL_PREFIX}/INSTALL_LINK_DEPENDS")
 endif()
 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_INSTALL_PREFIX "@ExportImport_BINARY_DIR@/Root" CACHE STRING "Installation Prefix")
 set(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH")
 set(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH")
 set(CMAKE_GNUtoMS "@ExportImport_GNUtoMS@" CACHE BOOL "CMAKE_GNUtoMS")
 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)
   run_cmake(ObjCxxStandard)
 endif()
 endif()
 if(CMake_TEST_CUDA)
 if(CMake_TEST_CUDA)
-  if(CMAKE_HOST_WIN32)
-    run_cmake(CudaStandardNoDefault)
-  else()
-    run_cmake(CudaStandard)
-  endif()
+  run_cmake(CudaStandard)
 endif()
 endif()
 if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4)
 if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4)
   run_cmake(CStandardGNU)
   run_cmake(CStandardGNU)