summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-12-07 14:22:22 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2016-12-07 14:22:22 (GMT)
commita0d64ecf8b9eac29cbfeb7461cf3bcb1688f7aa7 (patch)
tree99011b6e805e6032e1679d0fa98ecd5f8e846458
parent0478314e13e6d04a0100cc3be4ab84540a8beaa5 (diff)
parentf72ba42b7c643b1b217d1b8f6684cec3289e7201 (diff)
downloadCMake-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
-rw-r--r--Help/command/try_compile.rst32
-rw-r--r--Help/manual/cmake-policies.7.rst8
-rw-r--r--Help/policy/CMP0067.rst34
-rw-r--r--Help/release/dev/try_compile-lang-std.rst9
-rw-r--r--Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst2
-rw-r--r--Source/cmCoreTryCompile.cxx207
-rw-r--r--Source/cmCoreTryCompile.h4
-rw-r--r--Source/cmMakefile.cxx16
-rw-r--r--Source/cmPolicies.h5
-rw-r--r--Tests/RunCMake/CMakeLists.txt12
-rw-r--r--Tests/RunCMake/try_compile/CMP0067-stderr.txt25
-rw-r--r--Tests/RunCMake/try_compile/CMP0067.cmake40
-rw-r--r--Tests/RunCMake/try_compile/CStandard-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/CStandard-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/CStandard.cmake7
-rw-r--r--Tests/RunCMake/try_compile/CStandardGNU.c10
-rw-r--r--Tests/RunCMake/try_compile/CStandardGNU.cmake23
-rw-r--r--Tests/RunCMake/try_compile/CStandardNoDefault.cmake9
-rw-r--r--Tests/RunCMake/try_compile/CxxStandard-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/CxxStandard-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/CxxStandard.cmake7
-rw-r--r--Tests/RunCMake/try_compile/CxxStandardGNU.cmake23
-rw-r--r--Tests/RunCMake/try_compile/CxxStandardGNU.cxx11
-rw-r--r--Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake9
-rw-r--r--Tests/RunCMake/try_compile/RunCMakeTest.cmake18
-rw-r--r--Tests/RunCMake/try_compile/src.cxx4
26 files changed, 523 insertions, 8 deletions
diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst
index 7830deb..cde3776 100644
--- a/Help/command/try_compile.rst
+++ b/Help/command/try_compile.rst
@@ -35,7 +35,11 @@ Try Compiling Source Files
[COMPILE_DEFINITIONS <defs>...]
[LINK_LIBRARIES <libs>...]
[OUTPUT_VARIABLE <var>]
- [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]])
+ [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]]
+ [<LANG>_STANDARD <std>]
+ [<LANG>_STANDARD_REQUIRED <bool>]
+ [<LANG>_EXTENSIONS <bool>]
+ )
Try building an executable from one or more source files. The success or
failure of the ``try_compile``, i.e. ``TRUE`` or ``FALSE`` respectively, is
@@ -82,6 +86,18 @@ The options are:
``OUTPUT_VARIABLE <var>``
Store the output from the build process the given variable.
+``<LANG>_STANDARD <std>``
+ Specify the :prop_tgt:`C_STANDARD` or :prop_tgt:`CXX_STANDARD`
+ target property of the generated project.
+
+``<LANG>_STANDARD_REQUIRED <bool>``
+ Specify the :prop_tgt:`C_STANDARD_REQUIRED` or
+ :prop_tgt:`CXX_STANDARD_REQUIRED` target property of the generated project.
+
+``<LANG>_EXTENSIONS <bool>``
+ Specify the :prop_tgt:`C_EXTENSIONS` or :prop_tgt:`CXX_EXTENSIONS`
+ target property of the generated project.
+
In this version all files in ``<bindir>/CMakeFiles/CMakeTmp`` will be
cleaned automatically. For debugging, ``--debug-trycompile`` can be
passed to ``cmake`` to avoid this clean. However, multiple sequential
@@ -119,3 +135,17 @@ the type of target used for the source file signature.
Set the :variable:`CMAKE_TRY_COMPILE_PLATFORM_VARIABLES` variable to specify
variables that must be propagated into the test project. This variable is
meant for use only in toolchain files.
+
+If :policy:`CMP0067` is set to ``NEW``, or any of the ``<LANG>_STANDARD``,
+``<LANG>_STANDARD_REQUIRED``, or ``<LANG>_EXTENSIONS`` options are used,
+then the language standard variables are honored:
+
+* :variable:`CMAKE_C_STANDARD`
+* :variable:`CMAKE_C_STANDARD_REQUIRED`
+* :variable:`CMAKE_C_EXTENSIONS`
+* :variable:`CMAKE_CXX_STANDARD`
+* :variable:`CMAKE_CXX_STANDARD_REQUIRED`
+* :variable:`CMAKE_CXX_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/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 0cfe983..3266958 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or
functions.
+Policies Introduced by CMake 3.8
+================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0067: Honor language standard in try_compile() source-file signature. </policy/CMP0067>
+
Policies Introduced by CMake 3.7
================================
diff --git a/Help/policy/CMP0067.rst b/Help/policy/CMP0067.rst
new file mode 100644
index 0000000..d52ba7f
--- /dev/null
+++ b/Help/policy/CMP0067.rst
@@ -0,0 +1,34 @@
+CMP0067
+-------
+
+Honor language standard in :command:`try_compile` source-file signature.
+
+The :command:`try_compile` source file signature is intended to allow
+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:
+
+* :variable:`CMAKE_C_STANDARD`
+* :variable:`CMAKE_C_STANDARD_REQUIRED`
+* :variable:`CMAKE_C_EXTENSIONS`
+* :variable:`CMAKE_CXX_STANDARD`
+* :variable:`CMAKE_CXX_STANDARD_REQUIRED`
+* :variable:`CMAKE_CXX_EXTENSIONS`
+
+This policy provides compatibility for projects that do not expect
+the language standard settings to be used automatically.
+
+The ``OLD`` behavior of this policy is to ignore language standard
+setting variables when generating the ``try_compile`` test project.
+The ``NEW`` behavior of this policy is to honor language standard
+setting variables.
+
+This policy was introduced in CMake version 3.8. Unlike most policies,
+CMake version |release| does *not* warn by default when this policy
+is not set and simply uses OLD behavior. See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0067 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/dev/try_compile-lang-std.rst b/Help/release/dev/try_compile-lang-std.rst
new file mode 100644
index 0000000..849cecc
--- /dev/null
+++ b/Help/release/dev/try_compile-lang-std.rst
@@ -0,0 +1,9 @@
+try_compile-lang-std
+--------------------
+
+* The :command:`try_compile` command source file signature gained new options
+ to specify the language standard to use in the generated test project.
+
+* The :command:`try_compile` command source file signature now honors
+ language standard variables like :variable:`CMAKE_CXX_STANDARD`.
+ See policy :policy:`CMP0067`.
diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index 36cf75f..aa23b65 100644
--- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
+++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
@@ -17,6 +17,8 @@ warn by default:
policy :policy:`CMP0065`.
* ``CMAKE_POLICY_WARNING_CMP0066`` controls the warning for
policy :policy:`CMP0066`.
+* ``CMAKE_POLICY_WARNING_CMP0067`` controls the warning for
+ policy :policy:`CMP0067`.
This variable should not be set by a project in CMake code. Project
developers running CMake may set this variable in their cache to
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) \
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index c02b917..1b88d46 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -215,6 +215,18 @@ add_RunCMake_test(project -DCMake_TEST_RESOURCES=${CMake_TEST_RESOURCES})
add_RunCMake_test(return)
add_RunCMake_test(set_property)
add_RunCMake_test(string)
+foreach(var
+ CMAKE_C_COMPILER_ID
+ CMAKE_C_COMPILER_VERSION
+ CMAKE_C_STANDARD_DEFAULT
+ CMAKE_CXX_COMPILER_ID
+ CMAKE_CXX_COMPILER_VERSION
+ CMAKE_CXX_STANDARD_DEFAULT
+ )
+ if(DEFINED ${var})
+ list(APPEND try_compile_ARGS -D${var}=${${var}})
+ endif()
+endforeach()
add_RunCMake_test(try_compile)
add_RunCMake_test(try_run)
add_RunCMake_test(set)
diff --git a/Tests/RunCMake/try_compile/CMP0067-stderr.txt b/Tests/RunCMake/try_compile/CMP0067-stderr.txt
new file mode 100644
index 0000000..e2677ed
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CMP0067-stderr.txt
@@ -0,0 +1,25 @@
+before try_compile with CMP0067 WARN-enabled but no variables
+after try_compile with CMP0067 WARN-enabled but no variables
+before try_compile with CMP0067 WARN-default
+after try_compile with CMP0067 WARN-default
+before try_compile with CMP0067 WARN-enabled
+CMake Warning \(dev\) at CMP0067.cmake:[0-9]+ \(try_compile\):
+ Policy CMP0067 is not set: Honor language standard in try_compile\(\)
+ source-file signature. Run "cmake --help-policy CMP0067" for policy
+ details. Use the cmake_policy command to set the policy and suppress this
+ warning.
+
+ For compatibility with older versions of CMake, try_compile is not honoring
+ language standard variables in the test project:
+
+ CMAKE_C_STANDARD
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+after try_compile with CMP0067 WARN-enabled
+before try_compile with CMP0067 OLD
+after try_compile with CMP0067 OLD
+before try_compile with CMP0067 NEW
+after try_compile with CMP0067 NEW
diff --git a/Tests/RunCMake/try_compile/CMP0067.cmake b/Tests/RunCMake/try_compile/CMP0067.cmake
new file mode 100644
index 0000000..dd05d96
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CMP0067.cmake
@@ -0,0 +1,40 @@
+enable_language(C)
+
+set(CMAKE_POLICY_WARNING_CMP0067 ON)
+message("before try_compile with CMP0067 WARN-enabled but no variables")
+try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ )
+message("after try_compile with CMP0067 WARN-enabled but no variables")
+set(CMAKE_POLICY_WARNING_CMP0067 OFF)
+
+#-----------------------------------------------------------------------------
+
+set(CMAKE_C_STANDARD 90)
+
+message("before try_compile with CMP0067 WARN-default")
+try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ )
+message("after try_compile with CMP0067 WARN-default")
+
+set(CMAKE_POLICY_WARNING_CMP0067 ON)
+message("before try_compile with CMP0067 WARN-enabled")
+try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ )
+message("after try_compile with CMP0067 WARN-enabled")
+
+cmake_policy(SET CMP0067 OLD)
+message("before try_compile with CMP0067 OLD")
+try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ )
+message("after try_compile with CMP0067 OLD")
+
+cmake_policy(SET CMP0066 NEW)
+message("before try_compile with CMP0067 NEW")
+try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ )
+message("after try_compile with CMP0067 NEW")
diff --git a/Tests/RunCMake/try_compile/CStandard-result.txt b/Tests/RunCMake/try_compile/CStandard-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CStandard-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/CStandard-stderr.txt b/Tests/RunCMake/try_compile/CStandard-stderr.txt
new file mode 100644
index 0000000..209afcc
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CStandard-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at .*/Tests/RunCMake/try_compile/CStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+ C_STANDARD is set to invalid value '3'
++
+CMake Error at CStandard.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/CStandard.cmake b/Tests/RunCMake/try_compile/CStandard.cmake
new file mode 100644
index 0000000..2849ed4
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CStandard.cmake
@@ -0,0 +1,7 @@
+enable_language(C)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ C_STANDARD 3
+ OUTPUT_VARIABLE out
+ )
+message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/CStandardGNU.c b/Tests/RunCMake/try_compile/CStandardGNU.c
new file mode 100644
index 0000000..ac26c15
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CStandardGNU.c
@@ -0,0 +1,10 @@
+#if __STDC_VERSION__ != 199901L
+#error "Not GNU C 99 mode!"
+#endif
+#ifndef __STRICT_ANSI__
+#error "Not GNU C strict ANSI!"
+#endif
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/try_compile/CStandardGNU.cmake b/Tests/RunCMake/try_compile/CStandardGNU.cmake
new file mode 100644
index 0000000..79ae874
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CStandardGNU.cmake
@@ -0,0 +1,23 @@
+enable_language(C)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c
+ C_STANDARD 99
+ C_STANDARD_REQUIRED 1
+ C_EXTENSIONS 0
+ OUTPUT_VARIABLE out
+ )
+if(NOT result)
+ message(FATAL_ERROR "try_compile failed:\n${out}")
+endif()
+
+cmake_policy(SET CMP0067 NEW)
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_STANDARD_REQUIRED 1)
+set(CMAKE_C_EXTENSIONS 0)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c
+ OUTPUT_VARIABLE out
+ )
+if(NOT result)
+ message(FATAL_ERROR "try_compile failed:\n${out}")
+endif()
diff --git a/Tests/RunCMake/try_compile/CStandardNoDefault.cmake b/Tests/RunCMake/try_compile/CStandardNoDefault.cmake
new file mode 100644
index 0000000..97e72ea
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CStandardNoDefault.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ C_STANDARD 3 # bogus, but not used
+ OUTPUT_VARIABLE out
+ )
+if(NOT result)
+ message(FATAL_ERROR "try_compile failed:\n${out}")
+endif()
diff --git a/Tests/RunCMake/try_compile/CxxStandard-result.txt b/Tests/RunCMake/try_compile/CxxStandard-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CxxStandard-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/CxxStandard-stderr.txt b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
new file mode 100644
index 0000000..ec7245f
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+ CXX_STANDARD is set to invalid value '3'
++
+CMake Error at CxxStandard.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/CxxStandard.cmake b/Tests/RunCMake/try_compile/CxxStandard.cmake
new file mode 100644
index 0000000..bcb49b9
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CxxStandard.cmake
@@ -0,0 +1,7 @@
+enable_language(CXX)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
+ CXX_STANDARD 3
+ OUTPUT_VARIABLE out
+ )
+message("try_compile output:\n${out}")
diff --git a/Tests/RunCMake/try_compile/CxxStandardGNU.cmake b/Tests/RunCMake/try_compile/CxxStandardGNU.cmake
new file mode 100644
index 0000000..e714fe4
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CxxStandardGNU.cmake
@@ -0,0 +1,23 @@
+enable_language(CXX)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED 1
+ CXX_EXTENSIONS 0
+ OUTPUT_VARIABLE out
+ )
+if(NOT result)
+ message(FATAL_ERROR "try_compile failed:\n${out}")
+endif()
+
+cmake_policy(SET CMP0067 NEW)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED 1)
+set(CMAKE_CXX_EXTENSIONS 0)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx
+ OUTPUT_VARIABLE out
+ )
+if(NOT result)
+ message(FATAL_ERROR "try_compile failed:\n${out}")
+endif()
diff --git a/Tests/RunCMake/try_compile/CxxStandardGNU.cxx b/Tests/RunCMake/try_compile/CxxStandardGNU.cxx
new file mode 100644
index 0000000..7990a78
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CxxStandardGNU.cxx
@@ -0,0 +1,11 @@
+#if __cplusplus != 201103L && \
+ !(__cplusplus < 201103L && defined(__GXX_EXPERIMENTAL_CXX0X__))
+#error "Not GNU C++ 11 mode!"
+#endif
+#ifndef __STRICT_ANSI__
+#error "Not GNU C++ strict ANSI!"
+#endif
+int main()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake b/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake
new file mode 100644
index 0000000..35caa9d
--- /dev/null
+++ b/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake
@@ -0,0 +1,9 @@
+enable_language(CXX)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx
+ CXX_STANDARD 3 # bogus, but not used
+ OUTPUT_VARIABLE out
+ )
+if(NOT result)
+ message(FATAL_ERROR "try_compile failed:\n${out}")
+endif()
diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
index 4934bcd..d1b0217 100644
--- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
@@ -25,8 +25,26 @@ run_cmake(TargetTypeExe)
run_cmake(TargetTypeInvalid)
run_cmake(TargetTypeStatic)
+if(CMAKE_C_STANDARD_DEFAULT)
+ run_cmake(CStandard)
+elseif(DEFINED CMAKE_C_STANDARD_DEFAULT)
+ run_cmake(CStandardNoDefault)
+endif()
+if(CMAKE_CXX_STANDARD_DEFAULT)
+ run_cmake(CxxStandard)
+elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT)
+ run_cmake(CxxStandardNoDefault)
+endif()
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4)
+ run_cmake(CStandardGNU)
+endif()
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4)
+ run_cmake(CxxStandardGNU)
+endif()
+
run_cmake(CMP0056)
run_cmake(CMP0066)
+run_cmake(CMP0067)
if(RunCMake_GENERATOR MATCHES "Make|Ninja")
# Use a single build tree for a few tests without cleaning.
diff --git a/Tests/RunCMake/try_compile/src.cxx b/Tests/RunCMake/try_compile/src.cxx
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/RunCMake/try_compile/src.cxx
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}