浏览代码

try_compile: extend CMP0067 to honor language standards for CUDA.

Robert Maynard 9 年之前
父节点
当前提交
1371eec4c3

+ 10 - 6
Help/command/try_compile.rst

@@ -87,16 +87,17 @@ The options are:
   Store the output from the build process the given variable.
   Store the output from the build process the given variable.
 
 
 ``<LANG>_STANDARD <std>``
 ``<LANG>_STANDARD <std>``
-  Specify the :prop_tgt:`C_STANDARD` or :prop_tgt:`CXX_STANDARD`
-  target property of the generated project.
+  Specify the :prop_tgt:`C_STANDARD`, :prop_tgt:`CXX_STANDARD`,
+  or :prop_tgt:`CUDA_STANDARD` target property of the generated project.
 
 
 ``<LANG>_STANDARD_REQUIRED <bool>``
 ``<LANG>_STANDARD_REQUIRED <bool>``
-  Specify the :prop_tgt:`C_STANDARD_REQUIRED` or
-  :prop_tgt:`CXX_STANDARD_REQUIRED` target property of the generated project.
+  Specify the :prop_tgt:`C_STANDARD_REQUIRED`,
+  :prop_tgt:`CXX_STANDARD_REQUIRED`, or :prop_tgt:`CUDA_STANDARD_REQUIRED`
+  target property of the generated project.
 
 
 ``<LANG>_EXTENSIONS <bool>``
 ``<LANG>_EXTENSIONS <bool>``
-  Specify the :prop_tgt:`C_EXTENSIONS` or :prop_tgt:`CXX_EXTENSIONS`
-  target property of the generated project.
+  Specify the :prop_tgt:`C_EXTENSIONS`, :prop_tgt:`CXX_EXTENSIONS`,
+  or :prop_tgt:`CUDA_EXTENSIONS` target property of the generated project.
 
 
 In this version all files in ``<bindir>/CMakeFiles/CMakeTmp`` will be
 In this version all files in ``<bindir>/CMakeFiles/CMakeTmp`` will be
 cleaned automatically.  For debugging, ``--debug-trycompile`` can be
 cleaned automatically.  For debugging, ``--debug-trycompile`` can be
@@ -146,6 +147,9 @@ then the language standard variables are honored:
 * :variable:`CMAKE_CXX_STANDARD`
 * :variable:`CMAKE_CXX_STANDARD`
 * :variable:`CMAKE_CXX_STANDARD_REQUIRED`
 * :variable:`CMAKE_CXX_STANDARD_REQUIRED`
 * :variable:`CMAKE_CXX_EXTENSIONS`
 * :variable:`CMAKE_CXX_EXTENSIONS`
+* :variable:`CMAKE_CUDA_STANDARD`
+* :variable:`CMAKE_CUDA_STANDARD_REQUIRED`
+* :variable:`CMAKE_CUDA_EXTENSIONS`
 
 
 Their values are used to set the corresponding target properties in
 Their values are used to set the corresponding target properties in
 the generated project (unless overridden by an explicit option).
 the generated project (unless overridden by an explicit option).

+ 4 - 1
Help/policy/CMP0067.rst

@@ -8,7 +8,7 @@ callers to check whether they will be able to compile a given source file
 with the current toolchain.  In order to match compiler behavior, any
 with the current toolchain.  In order to match compiler behavior, any
 language standard mode should match.  However, CMake 3.7 and below did not
 language standard mode should match.  However, CMake 3.7 and below did not
 do this.  CMake 3.8 and above prefer to honor the language standard settings
 do this.  CMake 3.8 and above prefer to honor the language standard settings
-for ``C`` and ``CXX`` (C++) using the values of the variables:
+for ``C``, ``CXX`` (C++), and ``CUDA`` using the values of the variables:
 
 
 * :variable:`CMAKE_C_STANDARD`
 * :variable:`CMAKE_C_STANDARD`
 * :variable:`CMAKE_C_STANDARD_REQUIRED`
 * :variable:`CMAKE_C_STANDARD_REQUIRED`
@@ -16,6 +16,9 @@ for ``C`` and ``CXX`` (C++) using the values of the variables:
 * :variable:`CMAKE_CXX_STANDARD`
 * :variable:`CMAKE_CXX_STANDARD`
 * :variable:`CMAKE_CXX_STANDARD_REQUIRED`
 * :variable:`CMAKE_CXX_STANDARD_REQUIRED`
 * :variable:`CMAKE_CXX_EXTENSIONS`
 * :variable:`CMAKE_CXX_EXTENSIONS`
+* :variable:`CMAKE_CUDA_STANDARD`
+* :variable:`CMAKE_CUDA_STANDARD_REQUIRED`
+* :variable:`CMAKE_CUDA_EXTENSIONS`
 
 
 This policy provides compatibility for projects that do not expect
 This policy provides compatibility for projects that do not expect
 the language standard settings to be used automatically.
 the language standard settings to be used automatically.

+ 77 - 2
Source/cmCoreTryCompile.cxx

@@ -108,10 +108,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
   std::string copyFileError;
   std::string copyFileError;
   std::string cStandard;
   std::string cStandard;
   std::string cxxStandard;
   std::string cxxStandard;
+  std::string cudaStandard;
   std::string cStandardRequired;
   std::string cStandardRequired;
   std::string cxxStandardRequired;
   std::string cxxStandardRequired;
+  std::string cudaStandardRequired;
   std::string cExtensions;
   std::string cExtensions;
   std::string cxxExtensions;
   std::string cxxExtensions;
+  std::string cudaExtensions;
   std::vector<std::string> targets;
   std::vector<std::string> targets;
   std::string libsToLink = " ";
   std::string libsToLink = " ";
   bool useOldLinkLibs = true;
   bool useOldLinkLibs = true;
@@ -121,10 +124,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
   bool didCopyFileError = false;
   bool didCopyFileError = false;
   bool didCStandard = false;
   bool didCStandard = false;
   bool didCxxStandard = false;
   bool didCxxStandard = false;
+  bool didCudaStandard = false;
   bool didCStandardRequired = false;
   bool didCStandardRequired = false;
   bool didCxxStandardRequired = false;
   bool didCxxStandardRequired = false;
+  bool didCudaStandardRequired = false;
   bool didCExtensions = false;
   bool didCExtensions = false;
   bool didCxxExtensions = false;
   bool didCxxExtensions = false;
+  bool didCudaExtensions = false;
   bool useSources = argv[2] == "SOURCES";
   bool useSources = argv[2] == "SOURCES";
   std::vector<std::string> sources;
   std::vector<std::string> sources;
 
 
@@ -139,10 +145,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
     DoingCopyFileError,
     DoingCopyFileError,
     DoingCStandard,
     DoingCStandard,
     DoingCxxStandard,
     DoingCxxStandard,
+    DoingCudaStandard,
     DoingCStandardRequired,
     DoingCStandardRequired,
     DoingCxxStandardRequired,
     DoingCxxStandardRequired,
+    DoingCudaStandardRequired,
     DoingCExtensions,
     DoingCExtensions,
     DoingCxxExtensions,
     DoingCxxExtensions,
+    DoingCudaExtensions,
     DoingSources
     DoingSources
   };
   };
   Doing doing = useSources ? DoingSources : DoingNone;
   Doing doing = useSources ? DoingSources : DoingNone;
@@ -169,18 +178,27 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
     } else if (argv[i] == "CXX_STANDARD") {
     } else if (argv[i] == "CXX_STANDARD") {
       doing = DoingCxxStandard;
       doing = DoingCxxStandard;
       didCxxStandard = true;
       didCxxStandard = true;
+    } else if (argv[i] == "CUDA_STANDARD") {
+      doing = DoingCudaStandard;
+      didCudaStandard = true;
     } else if (argv[i] == "C_STANDARD_REQUIRED") {
     } else if (argv[i] == "C_STANDARD_REQUIRED") {
       doing = DoingCStandardRequired;
       doing = DoingCStandardRequired;
       didCStandardRequired = true;
       didCStandardRequired = true;
     } else if (argv[i] == "CXX_STANDARD_REQUIRED") {
     } else if (argv[i] == "CXX_STANDARD_REQUIRED") {
       doing = DoingCxxStandardRequired;
       doing = DoingCxxStandardRequired;
       didCxxStandardRequired = true;
       didCxxStandardRequired = true;
+    } else if (argv[i] == "CUDA_STANDARD_REQUIRED") {
+      doing = DoingCudaStandardRequired;
+      didCudaStandardRequired = true;
     } else if (argv[i] == "C_EXTENSIONS") {
     } else if (argv[i] == "C_EXTENSIONS") {
       doing = DoingCExtensions;
       doing = DoingCExtensions;
       didCExtensions = true;
       didCExtensions = true;
     } else if (argv[i] == "CXX_EXTENSIONS") {
     } else if (argv[i] == "CXX_EXTENSIONS") {
       doing = DoingCxxExtensions;
       doing = DoingCxxExtensions;
       didCxxExtensions = true;
       didCxxExtensions = true;
+    } else if (argv[i] == "CUDA_EXTENSIONS") {
+      doing = DoingCudaExtensions;
+      didCudaExtensions = true;
     } else if (doing == DoingCMakeFlags) {
     } else if (doing == DoingCMakeFlags) {
       cmakeFlags.push_back(argv[i]);
       cmakeFlags.push_back(argv[i]);
     } else if (doing == DoingCompileDefinitions) {
     } else if (doing == DoingCompileDefinitions) {
@@ -227,18 +245,27 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
     } else if (doing == DoingCxxStandard) {
     } else if (doing == DoingCxxStandard) {
       cxxStandard = argv[i];
       cxxStandard = argv[i];
       doing = DoingNone;
       doing = DoingNone;
+    } else if (doing == DoingCudaStandard) {
+      cudaStandard = argv[i];
+      doing = DoingNone;
     } else if (doing == DoingCStandardRequired) {
     } else if (doing == DoingCStandardRequired) {
       cStandardRequired = argv[i];
       cStandardRequired = argv[i];
       doing = DoingNone;
       doing = DoingNone;
     } else if (doing == DoingCxxStandardRequired) {
     } else if (doing == DoingCxxStandardRequired) {
       cxxStandardRequired = argv[i];
       cxxStandardRequired = argv[i];
       doing = DoingNone;
       doing = DoingNone;
+    } else if (doing == DoingCudaStandardRequired) {
+      cudaStandardRequired = argv[i];
+      doing = DoingNone;
     } else if (doing == DoingCExtensions) {
     } else if (doing == DoingCExtensions) {
       cExtensions = argv[i];
       cExtensions = argv[i];
       doing = DoingNone;
       doing = DoingNone;
     } else if (doing == DoingCxxExtensions) {
     } else if (doing == DoingCxxExtensions) {
       cxxExtensions = argv[i];
       cxxExtensions = argv[i];
       doing = DoingNone;
       doing = DoingNone;
+    } else if (doing == DoingCudaExtensions) {
+      cudaExtensions = argv[i];
+      doing = DoingNone;
     } else if (doing == DoingSources) {
     } else if (doing == DoingSources) {
       sources.push_back(argv[i]);
       sources.push_back(argv[i]);
     } else if (i == 3) {
     } else if (i == 3) {
@@ -297,6 +324,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       "CXX_STANDARD allowed only in source file signature.");
       "CXX_STANDARD allowed only in source file signature.");
     return -1;
     return -1;
   }
   }
+  if (didCudaStandard && !this->SrcFileSignature) {
+    this->Makefile->IssueMessage(
+      cmake::FATAL_ERROR,
+      "CUDA_STANDARD allowed only in source file signature.");
+    return -1;
+  }
   if (didCStandardRequired && !this->SrcFileSignature) {
   if (didCStandardRequired && !this->SrcFileSignature) {
     this->Makefile->IssueMessage(
     this->Makefile->IssueMessage(
       cmake::FATAL_ERROR,
       cmake::FATAL_ERROR,
@@ -309,6 +342,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       "CXX_STANDARD_REQUIRED allowed only in source file signature.");
       "CXX_STANDARD_REQUIRED allowed only in source file signature.");
     return -1;
     return -1;
   }
   }
+  if (didCudaStandardRequired && !this->SrcFileSignature) {
+    this->Makefile->IssueMessage(
+      cmake::FATAL_ERROR,
+      "CUDA_STANDARD_REQUIRED allowed only in source file signature.");
+    return -1;
+  }
   if (didCExtensions && !this->SrcFileSignature) {
   if (didCExtensions && !this->SrcFileSignature) {
     this->Makefile->IssueMessage(
     this->Makefile->IssueMessage(
       cmake::FATAL_ERROR,
       cmake::FATAL_ERROR,
@@ -321,6 +360,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       "CXX_EXTENSIONS allowed only in source file signature.");
       "CXX_EXTENSIONS allowed only in source file signature.");
     return -1;
     return -1;
   }
   }
+  if (didCudaExtensions && !this->SrcFileSignature) {
+    this->Makefile->IssueMessage(
+      cmake::FATAL_ERROR,
+      "CUDA_EXTENSIONS allowed only in source file signature.");
+    return -1;
+  }
 
 
   // compute the binary dir when TRY_COMPILE is called with a src file
   // compute the binary dir when TRY_COMPILE is called with a src file
   // signature
   // signature
@@ -630,12 +675,15 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
 
 
     bool const testC = testLangs.find("C") != testLangs.end();
     bool const testC = testLangs.find("C") != testLangs.end();
     bool const testCxx = testLangs.find("CXX") != testLangs.end();
     bool const testCxx = testLangs.find("CXX") != testLangs.end();
+    bool const testCuda = testLangs.find("CUDA") != testLangs.end();
 
 
     bool warnCMP0067 = false;
     bool warnCMP0067 = false;
     bool honorStandard = true;
     bool honorStandard = true;
 
 
-    if (!didCStandard && !didCxxStandard && !didCStandardRequired &&
-        !didCxxStandardRequired && !didCExtensions && !didCxxExtensions) {
+    if (!didCStandard && !didCxxStandard && !didCudaStandard &&
+        !didCStandardRequired && !didCxxStandardRequired &&
+        !didCudaStandardRequired && !didCExtensions && !didCxxExtensions &&
+        !didCudaExtensions) {
       switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
       switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
         case cmPolicies::WARN:
         case cmPolicies::WARN:
           warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
           warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -682,6 +730,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
             this->LookupStdVar("CMAKE_CXX_EXTENSIONS", warnCMP0067);
             this->LookupStdVar("CMAKE_CXX_EXTENSIONS", warnCMP0067);
         }
         }
       }
       }
+      if (testCuda) {
+        if (!didCudaStandard) {
+          cudaStandard =
+            this->LookupStdVar("CMAKE_CUDA_STANDARD", warnCMP0067);
+        }
+        if (!didCudaStandardRequired) {
+          cudaStandardRequired =
+            this->LookupStdVar("CMAKE_CUDA_STANDARD_REQUIRED", warnCMP0067);
+        }
+        if (!didCudaExtensions) {
+          cudaExtensions =
+            this->LookupStdVar("CMAKE_CUDA_EXTENSIONS", warnCMP0067);
+        }
+      }
     }
     }
 
 
     if (!this->WarnCMP0067.empty()) {
     if (!this->WarnCMP0067.empty()) {
@@ -725,6 +787,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       }
       }
     }
     }
 
 
+    if (testCuda) {
+      if (!cudaStandard.empty()) {
+        writeProperty(fout, targetName, "CUDA_STANDARD", cudaStandard);
+      }
+      if (!cudaStandardRequired.empty()) {
+        writeProperty(fout, targetName, "CUDA_STANDARD_REQUIRED",
+                      cudaStandardRequired);
+      }
+      if (!cudaExtensions.empty()) {
+        writeProperty(fout, targetName, "CUDA_EXTENSIONS", cudaExtensions);
+      }
+    }
+
     if (useOldLinkLibs) {
     if (useOldLinkLibs) {
       fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
       fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
               targetName.c_str());
               targetName.c_str());

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -222,6 +222,7 @@ foreach(var
     CMAKE_CXX_COMPILER_ID
     CMAKE_CXX_COMPILER_ID
     CMAKE_CXX_COMPILER_VERSION
     CMAKE_CXX_COMPILER_VERSION
     CMAKE_CXX_STANDARD_DEFAULT
     CMAKE_CXX_STANDARD_DEFAULT
+    CMake_TEST_CUDA
     )
     )
   if(DEFINED ${var})
   if(DEFINED ${var})
     list(APPEND try_compile_ARGS -D${var}=${${var}})
     list(APPEND try_compile_ARGS -D${var}=${${var}})

+ 1 - 0
Tests/RunCMake/try_compile/CudaStandard-result.txt

@@ -0,0 +1 @@
+1

+ 7 - 0
Tests/RunCMake/try_compile/CudaStandard-stderr.txt

@@ -0,0 +1,7 @@
+^CMake Error at .*/Tests/RunCMake/try_compile/CudaStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+  CUDA_STANDARD is set to invalid value '3'
++
+CMake Error at CudaStandard.cmake:[0-9]+ \(try_compile\):
+  Failed to generate test project build system.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 7 - 0
Tests/RunCMake/try_compile/CudaStandard.cmake

@@ -0,0 +1,7 @@
+enable_language(CUDA)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+  SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cu
+  CUDA_STANDARD 3
+  OUTPUT_VARIABLE out
+  )
+message("try_compile output:\n${out}")

+ 3 - 0
Tests/RunCMake/try_compile/RunCMakeTest.cmake

@@ -35,6 +35,9 @@ if(CMAKE_CXX_STANDARD_DEFAULT)
 elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT)
 elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT)
   run_cmake(CxxStandardNoDefault)
   run_cmake(CxxStandardNoDefault)
 endif()
 endif()
+if(CMake_TEST_CUDA)
+  run_cmake(CudaStandard)
+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)
 endif()
 endif()

+ 4 - 0
Tests/RunCMake/try_compile/src.cu

@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}