diff options
author | Brad King <brad.king@kitware.com> | 2016-12-07 14:22:22 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2016-12-07 14:22:22 (GMT) |
commit | a0d64ecf8b9eac29cbfeb7461cf3bcb1688f7aa7 (patch) | |
tree | 99011b6e805e6032e1679d0fa98ecd5f8e846458 /Source | |
parent | 0478314e13e6d04a0100cc3be4ab84540a8beaa5 (diff) | |
parent | f72ba42b7c643b1b217d1b8f6684cec3289e7201 (diff) | |
download | CMake-a0d64ecf8b9eac29cbfeb7461cf3bcb1688f7aa7.zip CMake-a0d64ecf8b9eac29cbfeb7461cf3bcb1688f7aa7.tar.gz CMake-a0d64ecf8b9eac29cbfeb7461cf3bcb1688f7aa7.tar.bz2 |
Merge topic 'try_compile-lang-std'
f72ba42b try_compile: Add policy CMP0067 to honor language standards
45aa03b9 try_compile: Add options to specify language standards
3bb2051e try_compile: Stop processing when test build system fails to generate
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmCoreTryCompile.cxx | 207 | ||||
-rw-r--r-- | Source/cmCoreTryCompile.h | 4 | ||||
-rw-r--r-- | Source/cmMakefile.cxx | 16 | ||||
-rw-r--r-- | Source/cmPolicies.h | 5 |
4 files changed, 225 insertions, 7 deletions
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index fbad778..1b7180c 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -46,6 +46,25 @@ static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = "CMAKE_TRY_COMPILE_PLATFORM_VARIABLES"; static std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; +static void writeProperty(FILE* fout, std::string const& targetName, + std::string const& prop, std::string const& value) +{ + fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", targetName.c_str(), + cmOutputConverter::EscapeForCMake(prop).c_str(), + cmOutputConverter::EscapeForCMake(value).c_str()); +} + +std::string cmCoreTryCompile::LookupStdVar(std::string const& var, + bool warnCMP0067) +{ + std::string value = this->Makefile->GetSafeDefinition(var); + if (warnCMP0067 && !value.empty()) { + value.clear(); + this->WarnCMP0067.push_back(var); + } + return value; +} + int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, bool isTryRun) { @@ -87,6 +106,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string outputVariable; std::string copyFile; std::string copyFileError; + std::string cStandard; + std::string cxxStandard; + std::string cStandardRequired; + std::string cxxStandardRequired; + std::string cExtensions; + std::string cxxExtensions; std::vector<std::string> targets; std::string libsToLink = " "; bool useOldLinkLibs = true; @@ -94,6 +119,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, bool didOutputVariable = false; bool didCopyFile = false; bool didCopyFileError = false; + bool didCStandard = false; + bool didCxxStandard = false; + bool didCStandardRequired = false; + bool didCxxStandardRequired = false; + bool didCExtensions = false; + bool didCxxExtensions = false; bool useSources = argv[2] == "SOURCES"; std::vector<std::string> sources; @@ -106,6 +137,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, DoingOutputVariable, DoingCopyFile, DoingCopyFileError, + DoingCStandard, + DoingCxxStandard, + DoingCStandardRequired, + DoingCxxStandardRequired, + DoingCExtensions, + DoingCxxExtensions, DoingSources }; Doing doing = useSources ? DoingSources : DoingNone; @@ -126,6 +163,24 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (argv[i] == "COPY_FILE_ERROR") { doing = DoingCopyFileError; didCopyFileError = true; + } else if (argv[i] == "C_STANDARD") { + doing = DoingCStandard; + didCStandard = true; + } else if (argv[i] == "CXX_STANDARD") { + doing = DoingCxxStandard; + didCxxStandard = 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] == "C_EXTENSIONS") { + doing = DoingCExtensions; + didCExtensions = true; + } else if (argv[i] == "CXX_EXTENSIONS") { + doing = DoingCxxExtensions; + didCxxExtensions = true; } else if (doing == DoingCMakeFlags) { cmakeFlags.push_back(argv[i]); } else if (doing == DoingCompileDefinitions) { @@ -166,6 +221,24 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (doing == DoingCopyFileError) { copyFileError = argv[i]; doing = DoingNone; + } else if (doing == DoingCStandard) { + cStandard = argv[i]; + doing = DoingNone; + } else if (doing == DoingCxxStandard) { + cxxStandard = 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 == DoingCExtensions) { + cExtensions = argv[i]; + doing = DoingNone; + } else if (doing == DoingCxxExtensions) { + cxxExtensions = argv[i]; + doing = DoingNone; } else if (doing == DoingSources) { sources.push_back(argv[i]); } else if (i == 3) { @@ -213,6 +286,42 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, return -1; } + if (didCStandard && !this->SrcFileSignature) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, "C_STANDARD allowed only in source file signature."); + return -1; + } + if (didCxxStandard && !this->SrcFileSignature) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "CXX_STANDARD allowed only in source file signature."); + return -1; + } + if (didCStandardRequired && !this->SrcFileSignature) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "C_STANDARD_REQUIRED allowed only in source file signature."); + return -1; + } + if (didCxxStandardRequired && !this->SrcFileSignature) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "CXX_STANDARD_REQUIRED allowed only in source file signature."); + return -1; + } + if (didCExtensions && !this->SrcFileSignature) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "C_EXTENSIONS allowed only in source file signature."); + return -1; + } + if (didCxxExtensions && !this->SrcFileSignature) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "CXX_EXTENSIONS allowed only in source file signature."); + return -1; + } + // compute the binary dir when TRY_COMPILE is called with a src file // signature if (this->SrcFileSignature) { @@ -518,6 +627,104 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } } fprintf(fout, ")\n"); + + bool const testC = testLangs.find("C") != testLangs.end(); + bool const testCxx = testLangs.find("CXX") != testLangs.end(); + + bool warnCMP0067 = false; + bool honorStandard = true; + + if (!didCStandard && !didCxxStandard && !didCStandardRequired && + !didCxxStandardRequired && !didCExtensions && !didCxxExtensions) { + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) { + case cmPolicies::WARN: + warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled( + "CMAKE_POLICY_WARNING_CMP0067"); + case cmPolicies::OLD: + // OLD behavior is to not honor the language standard variables. + honorStandard = false; + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0067)); + case cmPolicies::NEW: + // NEW behavior is to honor the language standard variables. + // We already initialized honorStandard to true. + break; + } + } + + if (honorStandard || warnCMP0067) { + if (testC) { + if (!didCStandard) { + cStandard = this->LookupStdVar("CMAKE_C_STANDARD", warnCMP0067); + } + if (!didCStandardRequired) { + cStandardRequired = + this->LookupStdVar("CMAKE_C_STANDARD_REQUIRED", warnCMP0067); + } + if (!didCExtensions) { + cExtensions = this->LookupStdVar("CMAKE_C_EXTENSIONS", warnCMP0067); + } + } + if (testCxx) { + if (!didCxxStandard) { + cxxStandard = this->LookupStdVar("CMAKE_CXX_STANDARD", warnCMP0067); + } + if (!didCxxStandardRequired) { + cxxStandardRequired = + this->LookupStdVar("CMAKE_CXX_STANDARD_REQUIRED", warnCMP0067); + } + if (!didCxxExtensions) { + cxxExtensions = + this->LookupStdVar("CMAKE_CXX_EXTENSIONS", warnCMP0067); + } + } + } + + if (!this->WarnCMP0067.empty()) { + std::ostringstream w; + /* clang-format off */ + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0067) << "\n" + "For compatibility with older versions of CMake, try_compile " + "is not honoring language standard variables in the test project:\n" + ; + /* clang-format on */ + for (std::vector<std::string>::iterator vi = this->WarnCMP0067.begin(); + vi != this->WarnCMP0067.end(); ++vi) { + w << " " << *vi << "\n"; + } + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + } + + if (testC) { + if (!cStandard.empty()) { + writeProperty(fout, targetName, "C_STANDARD", cStandard); + } + if (!cStandardRequired.empty()) { + writeProperty(fout, targetName, "C_STANDARD_REQUIRED", + cStandardRequired); + } + if (!cExtensions.empty()) { + writeProperty(fout, targetName, "C_EXTENSIONS", cExtensions); + } + } + + if (testCxx) { + if (!cxxStandard.empty()) { + writeProperty(fout, targetName, "CXX_STANDARD", cxxStandard); + } + if (!cxxStandardRequired.empty()) { + writeProperty(fout, targetName, "CXX_STANDARD_REQUIRED", + cxxStandardRequired); + } + if (!cxxExtensions.empty()) { + writeProperty(fout, targetName, "CXX_EXTENSIONS", cxxExtensions); + } + } + if (useOldLinkLibs) { fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n", targetName.c_str()); diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index 1c94f09..4b96aed 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -47,6 +47,10 @@ protected: std::string OutputFile; std::string FindErrorMessage; bool SrcFileSignature; + +private: + std::vector<std::string> WarnCMP0067; + std::string LookupStdVar(std::string const& var, bool warnCMP0067); }; #endif diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ed0f73b..f52fe26 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3158,8 +3158,10 @@ int cmMakefile::TryCompile(const std::string& srcdir, cmGlobalGenerator* gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); if (!gg) { - cmSystemTools::Error( - "Internal CMake error, TryCompile bad GlobalGenerator"); + this->IssueMessage(cmake::INTERNAL_ERROR, "Global generator '" + + this->GetGlobalGenerator()->GetName() + + "' could not be created."); + cmSystemTools::SetFatalErrorOccured(); // return to the original directory cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; @@ -3222,8 +3224,9 @@ int cmMakefile::TryCompile(const std::string& srcdir, cmStateEnums::INTERNAL); } if (cm.Configure() != 0) { - cmSystemTools::Error( - "Internal CMake error, TryCompile configure of cmake failed"); + this->IssueMessage(cmake::FATAL_ERROR, + "Failed to configure test project build system."); + cmSystemTools::SetFatalErrorOccured(); // return to the original directory cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; @@ -3231,8 +3234,9 @@ int cmMakefile::TryCompile(const std::string& srcdir, } if (cm.Generate() != 0) { - cmSystemTools::Error( - "Internal CMake error, TryCompile generation of cmake failed"); + this->IssueMessage(cmake::FATAL_ERROR, + "Failed to generate test project build system."); + cmSystemTools::SetFatalErrorOccured(); // return to the original directory cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 9b86435..62e67c7 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -197,7 +197,10 @@ class cmMakefile; 3, 4, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0066, \ "Honor per-config flags in try_compile() source-file signature.", 3, \ - 7, 0, cmPolicies::WARN) + 7, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0067, \ + "Honor language standard in try_compile() source-file signature.", \ + 3, 8, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ |