From 1371eec4c38b0a3b83f1416774c6c213ad0db6fc Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Fri, 2 Dec 2016 16:56:12 -0500 Subject: try_compile: extend CMP0067 to honor language standards for CUDA. --- Help/command/try_compile.rst | 16 +++-- Help/policy/CMP0067.rst | 5 +- Source/cmCoreTryCompile.cxx | 79 +++++++++++++++++++++- Tests/RunCMake/CMakeLists.txt | 1 + Tests/RunCMake/try_compile/CudaStandard-result.txt | 1 + Tests/RunCMake/try_compile/CudaStandard-stderr.txt | 7 ++ Tests/RunCMake/try_compile/CudaStandard.cmake | 7 ++ Tests/RunCMake/try_compile/RunCMakeTest.cmake | 3 + Tests/RunCMake/try_compile/src.cu | 4 ++ 9 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 Tests/RunCMake/try_compile/CudaStandard-result.txt create mode 100644 Tests/RunCMake/try_compile/CudaStandard-stderr.txt create mode 100644 Tests/RunCMake/try_compile/CudaStandard.cmake create mode 100644 Tests/RunCMake/try_compile/src.cu diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst index cde3776..66ea3d7 100644 --- a/Help/command/try_compile.rst +++ b/Help/command/try_compile.rst @@ -87,16 +87,17 @@ The options are: Store the output from the build process the given variable. ``_STANDARD `` - 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. ``_STANDARD_REQUIRED `` - 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. ``_EXTENSIONS `` - 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 ``/CMakeFiles/CMakeTmp`` will 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_REQUIRED` * :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 the generated project (unless overridden by an explicit option). diff --git a/Help/policy/CMP0067.rst b/Help/policy/CMP0067.rst index d52ba7f..e6dda80 100644 --- a/Help/policy/CMP0067.rst +++ b/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 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 -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_REQUIRED` @@ -16,6 +16,9 @@ for ``C`` and ``CXX`` (C++) using the values of the variables: * :variable:`CMAKE_CXX_STANDARD` * :variable:`CMAKE_CXX_STANDARD_REQUIRED` * :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 the language standard settings to be used automatically. diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index f12c9e8..ff9ffc0 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -108,10 +108,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, std::string copyFileError; std::string cStandard; std::string cxxStandard; + std::string cudaStandard; std::string cStandardRequired; std::string cxxStandardRequired; + std::string cudaStandardRequired; std::string cExtensions; std::string cxxExtensions; + std::string cudaExtensions; std::vector targets; std::string libsToLink = " "; bool useOldLinkLibs = true; @@ -121,10 +124,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, bool didCopyFileError = false; bool didCStandard = false; bool didCxxStandard = false; + bool didCudaStandard = false; bool didCStandardRequired = false; bool didCxxStandardRequired = false; + bool didCudaStandardRequired = false; bool didCExtensions = false; bool didCxxExtensions = false; + bool didCudaExtensions = false; bool useSources = argv[2] == "SOURCES"; std::vector sources; @@ -139,10 +145,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, DoingCopyFileError, DoingCStandard, DoingCxxStandard, + DoingCudaStandard, DoingCStandardRequired, DoingCxxStandardRequired, + DoingCudaStandardRequired, DoingCExtensions, DoingCxxExtensions, + DoingCudaExtensions, DoingSources }; Doing doing = useSources ? DoingSources : DoingNone; @@ -169,18 +178,27 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (argv[i] == "CXX_STANDARD") { doing = DoingCxxStandard; didCxxStandard = true; + } else if (argv[i] == "CUDA_STANDARD") { + doing = DoingCudaStandard; + didCudaStandard = true; } else if (argv[i] == "C_STANDARD_REQUIRED") { doing = DoingCStandardRequired; didCStandardRequired = true; } else if (argv[i] == "CXX_STANDARD_REQUIRED") { doing = DoingCxxStandardRequired; didCxxStandardRequired = true; + } else if (argv[i] == "CUDA_STANDARD_REQUIRED") { + doing = DoingCudaStandardRequired; + didCudaStandardRequired = true; } else if (argv[i] == "C_EXTENSIONS") { doing = DoingCExtensions; didCExtensions = true; } else if (argv[i] == "CXX_EXTENSIONS") { doing = DoingCxxExtensions; didCxxExtensions = true; + } else if (argv[i] == "CUDA_EXTENSIONS") { + doing = DoingCudaExtensions; + didCudaExtensions = true; } else if (doing == DoingCMakeFlags) { cmakeFlags.push_back(argv[i]); } else if (doing == DoingCompileDefinitions) { @@ -227,18 +245,27 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (doing == DoingCxxStandard) { cxxStandard = argv[i]; doing = DoingNone; + } else if (doing == DoingCudaStandard) { + cudaStandard = argv[i]; + doing = DoingNone; } else if (doing == DoingCStandardRequired) { cStandardRequired = argv[i]; doing = DoingNone; } else if (doing == DoingCxxStandardRequired) { cxxStandardRequired = argv[i]; doing = DoingNone; + } else if (doing == DoingCudaStandardRequired) { + cudaStandardRequired = argv[i]; + doing = DoingNone; } else if (doing == DoingCExtensions) { cExtensions = argv[i]; doing = DoingNone; } else if (doing == DoingCxxExtensions) { cxxExtensions = argv[i]; doing = DoingNone; + } else if (doing == DoingCudaExtensions) { + cudaExtensions = argv[i]; + doing = DoingNone; } else if (doing == DoingSources) { sources.push_back(argv[i]); } else if (i == 3) { @@ -297,6 +324,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, "CXX_STANDARD allowed only in source file signature."); 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) { this->Makefile->IssueMessage( cmake::FATAL_ERROR, @@ -309,6 +342,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, "CXX_STANDARD_REQUIRED allowed only in source file signature."); 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) { this->Makefile->IssueMessage( cmake::FATAL_ERROR, @@ -321,6 +360,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, "CXX_EXTENSIONS allowed only in source file signature."); 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 // signature @@ -630,12 +675,15 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, bool const testC = testLangs.find("C") != testLangs.end(); bool const testCxx = testLangs.find("CXX") != testLangs.end(); + bool const testCuda = testLangs.find("CUDA") != testLangs.end(); bool warnCMP0067 = false; 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)) { case cmPolicies::WARN: warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled( @@ -682,6 +730,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, 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()) { @@ -725,6 +787,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector 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) { fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n", targetName.c_str()); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 1b88d46..adfd37d 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -222,6 +222,7 @@ foreach(var CMAKE_CXX_COMPILER_ID CMAKE_CXX_COMPILER_VERSION CMAKE_CXX_STANDARD_DEFAULT + CMake_TEST_CUDA ) if(DEFINED ${var}) list(APPEND try_compile_ARGS -D${var}=${${var}}) diff --git a/Tests/RunCMake/try_compile/CudaStandard-result.txt b/Tests/RunCMake/try_compile/CudaStandard-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/CudaStandard-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/CudaStandard-stderr.txt b/Tests/RunCMake/try_compile/CudaStandard-stderr.txt new file mode 100644 index 0000000..3c6bdf6 --- /dev/null +++ b/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\)$ diff --git a/Tests/RunCMake/try_compile/CudaStandard.cmake b/Tests/RunCMake/try_compile/CudaStandard.cmake new file mode 100644 index 0000000..96da422 --- /dev/null +++ b/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}") diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index d1b0217..5452e6d 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -35,6 +35,9 @@ if(CMAKE_CXX_STANDARD_DEFAULT) elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT) run_cmake(CxxStandardNoDefault) 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) run_cmake(CStandardGNU) endif() diff --git a/Tests/RunCMake/try_compile/src.cu b/Tests/RunCMake/try_compile/src.cu new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/RunCMake/try_compile/src.cu @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} -- cgit v0.12