summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2022-08-01 13:53:49 -0400
committerBrad King <brad.king@kitware.com>2022-08-02 12:54:56 -0400
commit6b427d8da9b5f5db3753c499765b4b62f8e9020d (patch)
tree8c474dee4b3f9fafed9ecd813f3c69aa2603e2d5
parent067ba3a2bd1ce168b2867de74d2ea6b944a936fc (diff)
downloadcmake-6b427d8da9b5f5db3753c499765b4b62f8e9020d.tar.gz
cmCoreTryCompile: Port to cmArgumentParser
-rw-r--r--Source/cmCoreTryCompile.cxx603
-rw-r--r--Source/cmCoreTryCompile.h43
-rw-r--r--Source/cmTryCompileCommand.cxx8
-rw-r--r--Source/cmTryRunCommand.cxx192
-rw-r--r--Tests/RunCMake/try_compile/NoCStandard-result.txt1
-rw-r--r--Tests/RunCMake/try_compile/NoCStandard-stderr.txt7
-rw-r--r--Tests/RunCMake/try_compile/NoCStandard.cmake2
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFile-stderr.txt5
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt5
-rw-r--r--Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt5
-rw-r--r--Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt5
-rw-r--r--Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt5
-rw-r--r--Tests/RunCMake/try_compile/NoSources-stderr.txt5
-rw-r--r--Tests/RunCMake/try_compile/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/try_compile/TryRunArgs-stderr.txt76
-rw-r--r--Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt8
-rw-r--r--Tests/RunCMake/try_run/NoOutputVariable-stderr.txt8
-rw-r--r--Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt8
-rw-r--r--Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt8
-rw-r--r--Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt8
-rw-r--r--Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt8
21 files changed, 430 insertions, 581 deletions
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 3c749edab9..c2c3118f6e 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCoreTryCompile.h"
+#include <array>
#include <cstdio>
#include <cstring>
#include <set>
@@ -13,12 +14,14 @@
#include "cmsys/Directory.hxx"
+#include "cmArgumentParser.h"
#include "cmExportTryCompileFileGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -28,142 +31,6 @@
#include "cmake.h"
namespace {
-class LanguageStandardState
-{
-public:
- LanguageStandardState(std::string&& lang)
- : StandardFlag(lang + "_STANDARD")
- , RequiredFlag(lang + "_STANDARD_REQUIRED")
- , ExtensionFlag(lang + "_EXTENSIONS")
- {
- }
-
- void Enabled(bool isEnabled) { this->IsEnabled = isEnabled; }
-
- bool UpdateIfMatches(std::vector<std::string> const& argv, size_t& index)
- {
- bool updated = false;
- if (argv[index] == this->StandardFlag) {
- this->DidStandard = true;
- this->StandardValue = argv[++index];
- updated = true;
- } else if (argv[index] == this->RequiredFlag) {
- this->DidStandardRequired = true;
- this->RequiredValue = argv[++index];
- updated = true;
- } else if (argv[index] == this->ExtensionFlag) {
- this->DidExtensions = true;
- this->ExtensionValue = argv[++index];
- updated = true;
- }
- return updated;
- }
-
- bool Validate(cmMakefile* const makefile) const
- {
- if (this->DidStandard) {
- makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(this->StandardFlag,
- " allowed only in source file signature."));
- return false;
- }
- if (this->DidStandardRequired) {
- makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(this->RequiredFlag,
- " allowed only in source file signature."));
- return false;
- }
- if (this->DidExtensions) {
- makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(this->ExtensionFlag,
- " allowed only in source file signature."));
- return false;
- }
-
- return true;
- }
-
- bool DidNone() const
- {
- return !this->DidStandard && !this->DidStandardRequired &&
- !this->DidExtensions;
- }
-
- void LoadUnsetPropertyValues(cmMakefile* const makefile, bool honorStandard,
- bool warnCMP0067,
- std::vector<std::string>& warnCMP0067Variables)
- {
- if (!this->IsEnabled) {
- return;
- }
-
- auto lookupStdVar = [&](std::string const& var) -> std::string {
- std::string value = makefile->GetSafeDefinition(var);
- if (warnCMP0067 && !value.empty()) {
- value.clear();
- warnCMP0067Variables.emplace_back(var);
- }
- return value;
- };
-
- if (honorStandard || warnCMP0067) {
- if (!this->DidStandard) {
- this->StandardValue =
- lookupStdVar(cmStrCat("CMAKE_", this->StandardFlag));
- }
- if (!this->DidStandardRequired) {
- this->RequiredValue =
- lookupStdVar(cmStrCat("CMAKE_", this->RequiredFlag));
- }
- if (!this->DidExtensions) {
- this->ExtensionValue =
- lookupStdVar(cmStrCat("CMAKE_", this->ExtensionFlag));
- }
- }
- }
-
- void WriteProperties(FILE* fout, std::string const& targetName) const
- {
- if (!this->IsEnabled) {
- return;
- }
-
- auto writeProp = [&](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());
- };
-
- if (!this->StandardValue.empty()) {
- writeProp(this->StandardFlag, this->StandardValue);
- }
- if (!this->RequiredValue.empty()) {
- writeProp(this->RequiredFlag, this->RequiredValue);
- }
- if (!this->ExtensionValue.empty()) {
- writeProp(this->ExtensionFlag, this->ExtensionValue);
- }
- }
-
-private:
- bool IsEnabled = false;
- bool DidStandard = false;
- bool DidStandardRequired = false;
- bool DidExtensions = false;
-
- std::string StandardFlag;
- std::string RequiredFlag;
- std::string ExtensionFlag;
-
- std::string StandardValue;
- std::string RequiredValue;
- std::string ExtensionValue;
-};
-
constexpr size_t lang_property_start = 0;
constexpr size_t lang_property_size = 4;
constexpr size_t pie_property_start = 4;
@@ -233,12 +100,132 @@ std::set<std::string> const ghs_platform_vars{
"GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME",
"GHS_OS_DIR_OPTION"
};
+using Arguments = cmCoreTryCompile::Arguments;
+
+ArgumentParser::Continue TryCompileLangProp(Arguments& args,
+ cm::string_view key,
+ cm::string_view val)
+{
+ args.LangProps[std::string(key)] = std::string(val);
+ return ArgumentParser::Continue::No;
+}
+
+ArgumentParser::Continue TryCompileCompileDefs(Arguments& args,
+ cm::string_view val)
+{
+ cmExpandList(val, args.CompileDefs);
+ return ArgumentParser::Continue::Yes;
}
-bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
+#define BIND_LANG_PROPS(lang) \
+ Bind(#lang "_STANDARD"_s, TryCompileLangProp) \
+ .Bind(#lang "_STANDARD_REQUIRED"_s, TryCompileLangProp) \
+ .Bind(#lang "_EXTENSIONS"_s, TryCompileLangProp)
+
+auto const TryCompileArgParser =
+ cmArgumentParser<Arguments>{}
+ .Bind(0, &Arguments::CompileResultVariable)
+ .Bind(1, &Arguments::BinaryDirectory)
+ .Bind(2, &Arguments::SourceDirectoryOrFile)
+ .Bind(3, &Arguments::ProjectName)
+ .Bind(4, &Arguments::TargetName)
+ .Bind("SOURCES"_s, &Arguments::Sources)
+ .Bind("CMAKE_FLAGS"_s, &Arguments::CMakeFlags)
+ .Bind("COMPILE_DEFINITIONS"_s, TryCompileCompileDefs,
+ ArgumentParser::ExpectAtLeast{ 0 })
+ .Bind("LINK_LIBRARIES"_s, &Arguments::LinkLibraries)
+ .Bind("LINK_OPTIONS"_s, &Arguments::LinkOptions)
+ .Bind("__CMAKE_INTERNAL"_s, &Arguments::CMakeInternal)
+ .Bind("OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
+ .Bind("COPY_FILE"_s, &Arguments::CopyFileTo)
+ .Bind("COPY_FILE_ERROR"_s, &Arguments::CopyFileError)
+ .BIND_LANG_PROPS(C)
+ .BIND_LANG_PROPS(CUDA)
+ .BIND_LANG_PROPS(CXX)
+ .BIND_LANG_PROPS(HIP)
+ .BIND_LANG_PROPS(OBJC)
+ .BIND_LANG_PROPS(OBJCXX)
+ .Bind("COMPILE_OUTPUT_VARIABLE"_s, &Arguments::CompileOutputVariable)
+ .Bind("RUN_OUTPUT_VARIABLE"_s, &Arguments::RunOutputVariable)
+ .Bind("RUN_OUTPUT_STDOUT_VARIABLE"_s, &Arguments::RunOutputStdOutVariable)
+ .Bind("RUN_OUTPUT_STDERR_VARIABLE"_s, &Arguments::RunOutputStdErrVariable)
+ .Bind("WORKING_DIRECTORY"_s, &Arguments::RunWorkingDirectory)
+ .Bind("ARGS"_s, &Arguments::RunArgs)
+ /* keep semicolon on own line */;
+
+#undef BIND_LANG_PROPS
+}
+
+Arguments cmCoreTryCompile::ParseArgs(
+ cmRange<std::vector<std::string>::const_iterator> args, bool isTryRun)
+{
+ std::vector<std::string> unparsedArguments;
+ auto arguments = TryCompileArgParser.Parse(args, &unparsedArguments, 0);
+ if (!arguments.MaybeReportError(*(this->Makefile)) &&
+ !unparsedArguments.empty()) {
+ std::string m = "Unknown arguments:";
+ for (const auto& i : unparsedArguments) {
+ m = cmStrCat(m, "\n ", i, "\"");
+ }
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m);
+ }
+ // For historical reasons, treat some empty-valued keyword
+ // arguments as if they were not specified at all.
+ if (arguments.OutputVariable && arguments.OutputVariable->empty()) {
+ arguments.OutputVariable = cm::nullopt;
+ }
+ if (isTryRun) {
+ if (arguments.CompileOutputVariable &&
+ arguments.CompileOutputVariable->empty()) {
+ arguments.CompileOutputVariable = cm::nullopt;
+ }
+ if (arguments.RunOutputVariable && arguments.RunOutputVariable->empty()) {
+ arguments.RunOutputVariable = cm::nullopt;
+ }
+ if (arguments.RunOutputStdOutVariable &&
+ arguments.RunOutputStdOutVariable->empty()) {
+ arguments.RunOutputStdOutVariable = cm::nullopt;
+ }
+ if (arguments.RunOutputStdErrVariable &&
+ arguments.RunOutputStdErrVariable->empty()) {
+ arguments.RunOutputStdErrVariable = cm::nullopt;
+ }
+ if (arguments.RunWorkingDirectory &&
+ arguments.RunWorkingDirectory->empty()) {
+ arguments.RunWorkingDirectory = cm::nullopt;
+ }
+ } else {
+ std::string tryRunArgs;
+ if (arguments.CompileOutputVariable) {
+ tryRunArgs = cmStrCat(tryRunArgs, " COMPILE_OUTPUT_VARIABLE\n");
+ }
+ if (arguments.RunOutputVariable) {
+ tryRunArgs = cmStrCat(tryRunArgs, " RUN_OUTPUT_VARIABLE\n");
+ }
+ if (arguments.RunOutputStdOutVariable) {
+ tryRunArgs = cmStrCat(tryRunArgs, " RUN_OUTPUT_STDOUT_VARIABLE\n");
+ }
+ if (arguments.RunOutputStdErrVariable) {
+ tryRunArgs = cmStrCat(tryRunArgs, " RUN_OUTPUT_STDERR_VARIABLE\n");
+ }
+ if (arguments.RunWorkingDirectory) {
+ tryRunArgs = cmStrCat(tryRunArgs, " WORKING_DIRECTORY\n");
+ }
+ if (arguments.RunArgs) {
+ tryRunArgs = cmStrCat(tryRunArgs, " ARGS\n");
+ }
+ if (!tryRunArgs.empty()) {
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat("Ignoring try_run arguments for try_compile:\n", tryRunArgs));
+ }
+ }
+ return arguments;
+}
+
+bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
cmStateEnums::TargetType targetType)
{
- std::string const& resultVar = argv[0];
this->OutputFile.clear();
// which signature were we called with ?
this->SrcFileSignature = true;
@@ -246,82 +233,47 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string sourceDirectory;
std::string projectName;
std::string targetName;
- std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0]
- std::vector<std::string> compileDefs;
- std::string cmakeInternal;
- std::string outputVariable;
- std::string copyFile;
- std::string copyFileError;
- LanguageStandardState cState("C");
- LanguageStandardState cudaState("CUDA");
- LanguageStandardState cxxState("CXX");
- LanguageStandardState hipState("HIP");
- LanguageStandardState objcState("OBJC");
- LanguageStandardState objcxxState("OBJCXX");
+ if (arguments.SourceDirectoryOrFile && arguments.ProjectName) {
+ this->SrcFileSignature = false;
+ sourceDirectory = *arguments.SourceDirectoryOrFile;
+ projectName = *arguments.ProjectName;
+ if (arguments.TargetName) {
+ targetName = *arguments.TargetName;
+ }
+ } else {
+ projectName = "CMAKE_TRY_COMPILE";
+ /* Use a random file name to avoid rapid creation and deletion
+ of the same executable name (some filesystems fail on that). */
+ char targetNameBuf[64];
+ snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x",
+ cmSystemTools::RandomSeed() & 0xFFFFF);
+ targetName = targetNameBuf;
+ }
+
+ if (arguments.BinaryDirectory && !arguments.BinaryDirectory->empty()) {
+ if (!cmSystemTools::FileIsFullPath(*arguments.BinaryDirectory)) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("<bindir> is not an absolute path:\n '",
+ *arguments.BinaryDirectory, "'"));
+ return false;
+ }
+ this->BinaryDirectory = *arguments.BinaryDirectory;
+ // compute the binary dir when TRY_COMPILE is called with a src file
+ // signature
+ if (this->SrcFileSignature) {
+ this->BinaryDirectory += "/CMakeFiles/CMakeTmp";
+ }
+ } else {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "No <bindir> specified.");
+ return false;
+ }
+
std::vector<std::string> targets;
- std::vector<std::string> linkOptions;
- std::string libsToLink = " ";
- bool useOldLinkLibs = true;
- bool didOutputVariable = false;
- bool didCopyFile = false;
- bool didCopyFileError = false;
- bool useSources = false;
- std::vector<std::string> sources;
-
- enum Doing
- {
- DoingNone,
- DoingCMakeFlags,
- DoingCompileDefinitions,
- DoingLinkOptions,
- DoingLinkLibraries,
- DoingOutputVariable,
- DoingCopyFile,
- DoingCopyFileError,
- DoingSources,
- DoingCMakeInternal
- };
- Doing doing = DoingNone;
- for (size_t i = 1; i < argv.size(); ++i) {
- if (argv[i] == "SOURCES") {
- useSources = true;
- doing = DoingSources;
- } else if (argv[i] == "CMAKE_FLAGS") {
- doing = DoingCMakeFlags;
- } else if (argv[i] == "COMPILE_DEFINITIONS") {
- doing = DoingCompileDefinitions;
- } else if (argv[i] == "LINK_OPTIONS") {
- doing = DoingLinkOptions;
- } else if (argv[i] == "LINK_LIBRARIES") {
- doing = DoingLinkLibraries;
- useOldLinkLibs = false;
- } else if (argv[i] == "OUTPUT_VARIABLE") {
- doing = DoingOutputVariable;
- didOutputVariable = true;
- } else if (argv[i] == "COPY_FILE") {
- doing = DoingCopyFile;
- didCopyFile = true;
- } else if (argv[i] == "COPY_FILE_ERROR") {
- doing = DoingCopyFileError;
- didCopyFileError = true;
- } else if (cState.UpdateIfMatches(argv, i) ||
- cxxState.UpdateIfMatches(argv, i) ||
- cudaState.UpdateIfMatches(argv, i) ||
- hipState.UpdateIfMatches(argv, i) ||
- objcState.UpdateIfMatches(argv, i) ||
- objcxxState.UpdateIfMatches(argv, i)) {
- continue;
- } else if (argv[i] == "__CMAKE_INTERNAL") {
- doing = DoingCMakeInternal;
- } else if (doing == DoingCMakeFlags) {
- cmakeFlags.emplace_back(argv[i]);
- } else if (doing == DoingCompileDefinitions) {
- cmExpandList(argv[i], compileDefs);
- } else if (doing == DoingLinkOptions) {
- linkOptions.emplace_back(argv[i]);
- } else if (doing == DoingLinkLibraries) {
- libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" ";
- if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) {
+ if (arguments.LinkLibraries) {
+ for (std::string const& i : *arguments.LinkLibraries) {
+ if (cmTarget* tgt = this->Makefile->FindTargetToUse(i)) {
switch (tgt->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::STATIC_LIBRARY:
@@ -343,98 +295,33 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
return false;
}
if (tgt->IsImported()) {
- targets.emplace_back(argv[i]);
+ targets.emplace_back(i);
}
}
- } else if (doing == DoingOutputVariable) {
- outputVariable = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCopyFile) {
- copyFile = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCopyFileError) {
- copyFileError = argv[i];
- doing = DoingNone;
- } else if (doing == DoingSources) {
- sources.emplace_back(argv[i]);
- } else if (doing == DoingCMakeInternal) {
- cmakeInternal = argv[i];
- doing = DoingNone;
- } else if (i == 1) {
- this->BinaryDirectory = argv[i];
- } else if (i == 2) {
- sourceDirectory = argv[i];
- } else if (i == 3) {
- this->SrcFileSignature = false;
- projectName = argv[i];
- } else if (i == 4 && !this->SrcFileSignature) {
- targetName = argv[i];
- } else {
- std::ostringstream m;
- m << "try_compile given unknown argument \"" << argv[i] << "\".";
- this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m.str());
- }
- }
-
- if (!this->BinaryDirectory.empty()) {
- if (!cmSystemTools::FileIsFullPath(this->BinaryDirectory)) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("<bindir> is not an absolute path:\n '",
- this->BinaryDirectory, "'"));
- // Do not try to clean up the ill-specified directory.
- this->BinaryDirectory.clear();
- return false;
- }
- // compute the binary dir when TRY_COMPILE is called with a src file
- // signature
- if (this->SrcFileSignature) {
- this->BinaryDirectory += "/CMakeFiles/CMakeTmp";
}
- } else {
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
- "No <bindir> specified.");
- return false;
- }
-
- if (this->SrcFileSignature) {
- projectName = "CMAKE_TRY_COMPILE";
- /* Use a random file name to avoid rapid creation and deletion
- of the same executable name (some filesystems fail on that). */
- char targetNameBuf[64];
- snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x",
- cmSystemTools::RandomSeed() & 0xFFFFF);
- targetName = targetNameBuf;
}
- if (didCopyFile && copyFile.empty()) {
+ if (arguments.CopyFileTo && arguments.CopyFileTo->empty()) {
this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
"COPY_FILE must be followed by a file path");
return false;
}
- if (didCopyFileError && copyFileError.empty()) {
+ if (arguments.CopyFileError && arguments.CopyFileError->empty()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"COPY_FILE_ERROR must be followed by a variable name");
return false;
}
- if (didCopyFileError && !didCopyFile) {
+ if (arguments.CopyFileError && !arguments.CopyFileTo) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"COPY_FILE_ERROR may be used only with COPY_FILE");
return false;
}
- if (didOutputVariable && outputVariable.empty()) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "OUTPUT_VARIABLE must be followed by a variable name");
- return false;
- }
-
- if (useSources && sources.empty()) {
+ if (arguments.Sources && arguments.Sources->empty()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"SOURCES must be followed by at least one source file");
@@ -443,32 +330,20 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// only valid for srcfile signatures
if (!this->SrcFileSignature) {
- if (!cState.Validate(this->Makefile)) {
- return false;
- }
- if (!cudaState.Validate(this->Makefile)) {
- return false;
- }
- if (!hipState.Validate(this->Makefile)) {
- return false;
- }
- if (!cxxState.Validate(this->Makefile)) {
- return false;
- }
- if (!objcState.Validate(this->Makefile)) {
- return false;
- }
- if (!objcxxState.Validate(this->Makefile)) {
+ if (!arguments.LangProps.empty()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(arguments.LangProps.begin()->first,
+ " allowed only in source file signature."));
return false;
}
-
- if (!compileDefs.empty()) {
+ if (!arguments.CompileDefs.empty()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE");
return false;
}
- if (!copyFile.empty()) {
+ if (arguments.CopyFileTo) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"COPY_FILE specified on a srcdir type TRY_COMPILE");
@@ -495,8 +370,12 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmSystemTools::RemoveFile(ccFile);
// Choose sources.
- if (!useSources) {
- sources.emplace_back(argv[2]);
+ std::vector<std::string> sources;
+ if (arguments.Sources) {
+ sources = std::move(*arguments.Sources);
+ } else {
+ // TODO: ensure SourceDirectoryOrFile has a value
+ sources.emplace_back(*arguments.SourceDirectoryOrFile);
}
// Detect languages to enable.
@@ -608,7 +487,7 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str());
- if (cmakeInternal == "ABI") {
+ if (arguments.CMakeInternal == "ABI") {
// This is the ABI detection step, also used for implicit includes.
// Erase any include_directories() calls from the toolchain file so
// that we do not see them as implicit. Our ABI detection source
@@ -715,10 +594,10 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
fprintf(fout, "set(CMAKE_SUPPRESS_REGENERATION 1)\n");
fprintf(fout, "link_directories(${LINK_DIRECTORIES})\n");
// handle any compile flags we need to pass on
- if (!compileDefs.empty()) {
+ if (!arguments.CompileDefs.empty()) {
// Pass using bracket arguments to preserve content.
fprintf(fout, "add_definitions([==[%s]==])\n",
- cmJoin(compileDefs, "]==] [==[").c_str());
+ cmJoin(arguments.CompileDefs, "]==] [==[").c_str());
}
if (!targets.empty()) {
@@ -782,18 +661,10 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
fprintf(fout, ")\n");
- cState.Enabled(testLangs.find("C") != testLangs.end());
- cxxState.Enabled(testLangs.find("CXX") != testLangs.end());
- cudaState.Enabled(testLangs.find("CUDA") != testLangs.end());
- hipState.Enabled(testLangs.find("HIP") != testLangs.end());
- objcState.Enabled(testLangs.find("OBJC") != testLangs.end());
- objcxxState.Enabled(testLangs.find("OBJCXX") != testLangs.end());
-
bool warnCMP0067 = false;
bool honorStandard = true;
- if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() &&
- objcxxState.DidNone() && cudaState.DidNone() && hipState.DidNone()) {
+ if (arguments.LangProps.empty()) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
case cmPolicies::WARN:
warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -818,18 +689,33 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::vector<std::string> warnCMP0067Variables;
- cState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067,
- warnCMP0067Variables);
- cxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- cudaState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- hipState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- objcState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
- objcxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
- warnCMP0067, warnCMP0067Variables);
+ if (honorStandard || warnCMP0067) {
+ static std::array<std::string, 6> const possibleLangs{
+ { "C", "CXX", "CUDA", "HIP", "OBJC", "OBJCXX" }
+ };
+ static std::array<cm::string_view, 3> const langPropSuffixes{
+ { "_STANDARD"_s, "_STANDARD_REQUIRED"_s, "_EXTENSIONS"_s }
+ };
+ for (std::string const& lang : possibleLangs) {
+ if (testLangs.find(lang) == testLangs.end()) {
+ continue;
+ }
+ for (cm::string_view propSuffix : langPropSuffixes) {
+ std::string langProp = cmStrCat(lang, propSuffix);
+ if (!arguments.LangProps.count(langProp)) {
+ std::string langPropVar = cmStrCat("CMAKE_"_s, langProp);
+ std::string value = this->Makefile->GetSafeDefinition(langPropVar);
+ if (warnCMP0067 && !value.empty()) {
+ value.clear();
+ warnCMP0067Variables.emplace_back(langPropVar);
+ }
+ if (!value.empty()) {
+ arguments.LangProps[langProp] = value;
+ }
+ }
+ }
+ }
+ }
if (!warnCMP0067Variables.empty()) {
std::ostringstream w;
@@ -845,17 +731,20 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
- cState.WriteProperties(fout, targetName);
- cxxState.WriteProperties(fout, targetName);
- cudaState.WriteProperties(fout, targetName);
- hipState.WriteProperties(fout, targetName);
- objcState.WriteProperties(fout, targetName);
- objcxxState.WriteProperties(fout, targetName);
+ for (auto const& p : arguments.LangProps) {
+ if (p.second.empty()) {
+ continue;
+ }
+ fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n",
+ targetName.c_str(),
+ cmOutputConverter::EscapeForCMake(p.first).c_str(),
+ cmOutputConverter::EscapeForCMake(p.second).c_str());
+ }
- if (!linkOptions.empty()) {
+ if (!arguments.LinkOptions.empty()) {
std::vector<std::string> options;
- options.reserve(linkOptions.size());
- for (const auto& option : linkOptions) {
+ options.reserve(arguments.LinkOptions.size());
+ for (const auto& option : arguments.LinkOptions) {
options.emplace_back(cmOutputConverter::EscapeForCMake(option));
}
@@ -869,12 +758,16 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
- if (useOldLinkLibs) {
- fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
- targetName.c_str());
- } else {
+ if (arguments.LinkLibraries) {
+ std::string libsToLink = " ";
+ for (std::string const& i : *arguments.LinkLibraries) {
+ libsToLink += "\"" + cmTrimWhitespace(i) + "\" ";
+ }
fprintf(fout, "target_link_libraries(%s %s)\n", targetName.c_str(),
libsToLink.c_str());
+ } else {
+ fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
+ targetName.c_str());
}
fclose(fout);
}
@@ -965,13 +858,13 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) {
vars.erase(kCMAKE_OSX_ARCHITECTURES);
std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs;
- cmakeFlags.emplace_back(std::move(flag));
+ arguments.CMakeFlags.emplace_back(std::move(flag));
}
for (std::string const& var : vars) {
if (cmValue val = this->Makefile->GetDefinition(var)) {
std::string flag = "-D" + var + "=" + *val;
- cmakeFlags.emplace_back(std::move(flag));
+ arguments.CMakeFlags.emplace_back(std::move(flag));
}
}
}
@@ -981,7 +874,7 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
for (std::string const& var : ghs_platform_vars) {
if (cmValue val = this->Makefile->GetDefinition(var)) {
std::string flag = "-D" + var + "=" + "'" + *val + "'";
- cmakeFlags.emplace_back(std::move(flag));
+ arguments.CMakeFlags.emplace_back(std::move(flag));
}
}
}
@@ -992,26 +885,27 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// actually do the try compile now that everything is setup
int res = this->Makefile->TryCompile(
sourceDirectory, this->BinaryDirectory, projectName, targetName,
- this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, &cmakeFlags,
- output);
+ this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL,
+ &arguments.CMakeFlags, output);
if (erroroc) {
cmSystemTools::SetErrorOccurred();
}
// set the result var to the return value to indicate success or failure
- this->Makefile->AddCacheDefinition(resultVar, (res == 0 ? "TRUE" : "FALSE"),
- "Result of TRY_COMPILE",
- cmStateEnums::INTERNAL);
+ this->Makefile->AddCacheDefinition(
+ *arguments.CompileResultVariable, (res == 0 ? "TRUE" : "FALSE"),
+ "Result of TRY_COMPILE", cmStateEnums::INTERNAL);
- if (!outputVariable.empty()) {
- this->Makefile->AddDefinition(outputVariable, output);
+ if (arguments.OutputVariable) {
+ this->Makefile->AddDefinition(*arguments.OutputVariable, output);
}
if (this->SrcFileSignature) {
std::string copyFileErrorMessage;
this->FindOutputFile(targetName, targetType);
- if ((res == 0) && !copyFile.empty()) {
+ if ((res == 0) && arguments.CopyFileTo) {
+ std::string const& copyFile = *arguments.CopyFileTo;
if (this->OutputFile.empty() ||
!cmSystemTools::CopyFileAlways(this->OutputFile, copyFile)) {
std::ostringstream emsg;
@@ -1024,7 +918,7 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
if (!this->FindErrorMessage.empty()) {
emsg << this->FindErrorMessage;
}
- if (copyFileError.empty()) {
+ if (!arguments.CopyFileError) {
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, emsg.str());
return false;
}
@@ -1032,7 +926,8 @@ bool cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
- if (!copyFileError.empty()) {
+ if (arguments.CopyFileError) {
+ std::string const& copyFileError = *arguments.CopyFileError;
this->Makefile->AddDefinition(copyFileError, copyFileErrorMessage);
}
}
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index 6ca08e8dfb..deefe5768a 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -4,12 +4,19 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
#include <string>
#include <vector>
+#include <cm/optional>
+
+#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmStateTypes.h"
class cmMakefile;
+template <typename Iter>
+class cmRange;
/** \class cmCoreTryCompile
* \brief Base class for cmTryCompileCommand and cmTryRunCommand
@@ -25,12 +32,46 @@ public:
{
}
+ struct Arguments : public ArgumentParser::ParseResult
+ {
+ cm::optional<std::string> CompileResultVariable;
+ cm::optional<std::string> BinaryDirectory;
+ cm::optional<std::string> SourceDirectoryOrFile;
+ cm::optional<std::string> ProjectName;
+ cm::optional<std::string> TargetName;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> Sources;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> CMakeFlags{
+ 1, "CMAKE_FLAGS"
+ }; // fake argv[0]
+ std::vector<std::string> CompileDefs;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>>
+ LinkLibraries;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> LinkOptions;
+ std::map<std::string, std::string> LangProps;
+ std::string CMakeInternal;
+ cm::optional<std::string> OutputVariable;
+ cm::optional<std::string> CopyFileTo;
+ cm::optional<std::string> CopyFileError;
+
+ // Argument for try_run only.
+ // Keep in sync with warnings in cmCoreTryCompile::ParseArgs.
+ cm::optional<std::string> CompileOutputVariable;
+ cm::optional<std::string> RunOutputVariable;
+ cm::optional<std::string> RunOutputStdOutVariable;
+ cm::optional<std::string> RunOutputStdErrVariable;
+ cm::optional<std::string> RunWorkingDirectory;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> RunArgs;
+ };
+
+ Arguments ParseArgs(cmRange<std::vector<std::string>::const_iterator> args,
+ bool isTryRun);
+
/**
* This is the core code for try compile. It is here so that other
* commands, such as TryRun can access the same logic without
* duplication.
*/
- bool TryCompileCode(std::vector<std::string> const& argv,
+ bool TryCompileCode(Arguments& arguments,
cmStateEnums::TargetType targetType);
/**
diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx
index 971dccbe57..b59c2258f2 100644
--- a/Source/cmTryCompileCommand.cxx
+++ b/Source/cmTryCompileCommand.cxx
@@ -6,6 +6,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -50,7 +51,12 @@ bool cmTryCompileCommand(std::vector<std::string> const& args,
}
cmCoreTryCompile tc(&mf);
- tc.TryCompileCode(args, targetType);
+ cmCoreTryCompile::Arguments arguments =
+ tc.ParseArgs(cmMakeRange(args), false);
+ if (!arguments) {
+ return true;
+ }
+ tc.TryCompileCode(arguments, targetType);
// if They specified clean then we clean up what we can
if (tc.SrcFileSignature) {
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 2cf75e2da3..7a29521a9f 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -4,8 +4,11 @@
#include <cstdio>
+#include <cm/optional>
+
#include "cmsys/FStream.hxx"
+#include "cmArgumentParserTypes.h"
#include "cmCoreTryCompile.h"
#include "cmDuration.h"
#include "cmExecutionStatus.h"
@@ -32,115 +35,35 @@ public:
bool TryRunCode(std::vector<std::string> const& args);
void RunExecutable(const std::string& runArgs,
+ cm::optional<std::string> const& workDir,
std::string* runOutputContents,
std::string* runOutputStdOutContents,
std::string* runOutputStdErrContents);
void DoNotRunExecutable(const std::string& runArgs,
const std::string& srcFile,
+ std::string const& compileResultVariable,
std::string* runOutputContents,
std::string* runOutputStdOutContents,
std::string* runOutputStdErrContents);
- std::string CompileResultVariable;
std::string RunResultVariable;
- std::string OutputVariable;
- std::string RunOutputVariable;
- std::string RunOutputStdOutVariable;
- std::string RunOutputStdErrVariable;
- std::string CompileOutputVariable;
- std::string WorkingDirectory;
};
bool TryRunCommandImpl::TryRunCode(std::vector<std::string> const& argv)
{
- // build an arg list for TryCompile and extract the runArgs,
- std::vector<std::string> tryCompile;
-
- this->CompileResultVariable.clear();
- this->RunResultVariable.clear();
- this->OutputVariable.clear();
- this->RunOutputVariable.clear();
- this->RunOutputStdOutVariable.clear();
- this->RunOutputStdErrVariable.clear();
- this->CompileOutputVariable.clear();
-
- std::string runArgs;
- unsigned int i;
- for (i = 1; i < argv.size(); ++i) {
- if (argv[i] == "ARGS") {
- ++i;
- while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" &&
- argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_OPTIONS" &&
- argv[i] != "LINK_LIBRARIES") {
- runArgs += " ";
- runArgs += argv[i];
- ++i;
- }
- if (i < argv.size()) {
- tryCompile.push_back(argv[i]);
- }
- } else {
- if (argv[i] == "OUTPUT_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "OUTPUT_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->OutputVariable = argv[i];
- } else if (argv[i] == "RUN_OUTPUT_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "RUN_OUTPUT_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->RunOutputVariable = argv[i];
- } else if (argv[i] == "RUN_OUTPUT_STDOUT_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "RUN_OUTPUT_STDOUT_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->RunOutputStdOutVariable = argv[i];
- } else if (argv[i] == "RUN_OUTPUT_STDERR_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "RUN_OUTPUT_STDERR_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->RunOutputStdErrVariable = argv[i];
- } else if (argv[i] == "COMPILE_OUTPUT_VARIABLE") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "COMPILE_OUTPUT_VARIABLE specified but there is no variable");
- return false;
- }
- i++;
- this->CompileOutputVariable = argv[i];
- } else if (argv[i] == "WORKING_DIRECTORY") {
- if (argv.size() <= (i + 1)) {
- cmSystemTools::Error(
- "WORKING_DIRECTORY specified but there is no variable");
- return false;
- }
- i++;
- this->WorkingDirectory = argv[i];
- } else {
- tryCompile.push_back(argv[i]);
- }
- }
+ this->RunResultVariable = argv[0];
+ cmCoreTryCompile::Arguments arguments =
+ this->ParseArgs(cmMakeRange(argv).advance(1), true);
+ if (!arguments) {
+ return true;
}
// although they could be used together, don't allow it, because
// using OUTPUT_VARIABLE makes crosscompiling harder
- if (!this->OutputVariable.empty() &&
- (!this->RunOutputVariable.empty() ||
- !this->CompileOutputVariable.empty() ||
- !this->RunOutputStdOutVariable.empty() ||
- !this->RunOutputStdErrVariable.empty())) {
+ if (arguments.OutputVariable &&
+ (arguments.CompileOutputVariable || arguments.RunOutputVariable ||
+ arguments.RunOutputStdOutVariable ||
+ arguments.RunOutputStdErrVariable)) {
cmSystemTools::Error(
"You cannot use OUTPUT_VARIABLE together with COMPILE_OUTPUT_VARIABLE "
", RUN_OUTPUT_VARIABLE, RUN_OUTPUT_STDOUT_VARIABLE or "
@@ -151,9 +74,9 @@ bool TryRunCommandImpl::TryRunCode(std::vector<std::string> const& argv)
return false;
}
- if ((!this->RunOutputStdOutVariable.empty() ||
- !RunOutputStdErrVariable.empty()) &&
- !this->RunOutputVariable.empty()) {
+ if ((arguments.RunOutputStdOutVariable ||
+ arguments.RunOutputStdErrVariable) &&
+ arguments.RunOutputVariable) {
cmSystemTools::Error(
"You cannot use RUN_OUTPUT_STDOUT_VARIABLE or "
"RUN_OUTPUT_STDERR_VARIABLE together "
@@ -162,43 +85,40 @@ bool TryRunCommandImpl::TryRunCode(std::vector<std::string> const& argv)
return false;
}
- if (!this->WorkingDirectory.empty()) {
- if (!cmSystemTools::MakeDirectory(this->WorkingDirectory)) {
+ if (arguments.RunWorkingDirectory) {
+ if (!cmSystemTools::MakeDirectory(*arguments.RunWorkingDirectory)) {
cmSystemTools::Error(cmStrCat("Error creating working directory \"",
- this->WorkingDirectory, "\"."));
+ *arguments.RunWorkingDirectory, "\"."));
return false;
}
}
bool captureRunOutput = false;
bool captureRunOutputStdOutErr = false;
- if (!this->OutputVariable.empty()) {
+ if (arguments.OutputVariable) {
captureRunOutput = true;
- tryCompile.emplace_back("OUTPUT_VARIABLE");
- tryCompile.push_back(this->OutputVariable);
- }
- if (!this->CompileOutputVariable.empty()) {
- tryCompile.emplace_back("OUTPUT_VARIABLE");
- tryCompile.push_back(this->CompileOutputVariable);
+ } else if (arguments.CompileOutputVariable) {
+ arguments.OutputVariable = arguments.CompileOutputVariable;
}
- if (!this->RunOutputStdOutVariable.empty() ||
- !RunOutputStdErrVariable.empty()) {
+ if (arguments.RunOutputStdOutVariable || arguments.RunOutputStdErrVariable) {
captureRunOutputStdOutErr = true;
- } else if (!this->RunOutputVariable.empty()) {
+ } else if (arguments.RunOutputVariable) {
captureRunOutput = true;
}
- this->RunResultVariable = argv[0];
- this->CompileResultVariable = argv[1];
-
// do the try compile
- bool compiled = this->TryCompileCode(tryCompile, cmStateEnums::EXECUTABLE);
+ bool compiled = this->TryCompileCode(arguments, cmStateEnums::EXECUTABLE);
// now try running the command if it compiled
if (compiled) {
if (this->OutputFile.empty()) {
cmSystemTools::Error(this->FindErrorMessage);
} else {
+ std::string runArgs;
+ if (arguments.RunArgs) {
+ runArgs = cmStrCat(" ", cmJoin(*arguments.RunArgs, " "));
+ }
+
// "run" it and capture the output
std::string runOutputContents;
std::string runOutputStdOutContents;
@@ -206,47 +126,51 @@ bool TryRunCommandImpl::TryRunCode(std::vector<std::string> const& argv)
if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") &&
!this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) {
this->DoNotRunExecutable(
- runArgs, argv[3], captureRunOutput ? &runOutputContents : nullptr,
- captureRunOutputStdOutErr && !RunOutputStdOutVariable.empty()
+ runArgs, *arguments.SourceDirectoryOrFile,
+ *arguments.CompileResultVariable,
+ captureRunOutput ? &runOutputContents : nullptr,
+ captureRunOutputStdOutErr && arguments.RunOutputStdOutVariable
? &runOutputStdOutContents
: nullptr,
- captureRunOutputStdOutErr && !RunOutputStdErrVariable.empty()
+ captureRunOutputStdOutErr && arguments.RunOutputStdErrVariable
? &runOutputStdErrContents
: nullptr);
} else {
this->RunExecutable(
- runArgs, captureRunOutput ? &runOutputContents : nullptr,
- captureRunOutputStdOutErr && !RunOutputStdOutVariable.empty()
+ runArgs, arguments.RunWorkingDirectory,
+ captureRunOutput ? &runOutputContents : nullptr,
+ captureRunOutputStdOutErr && arguments.RunOutputStdOutVariable
? &runOutputStdOutContents
: nullptr,
- captureRunOutputStdOutErr && !RunOutputStdErrVariable.empty()
+ captureRunOutputStdOutErr && arguments.RunOutputStdErrVariable
? &runOutputStdErrContents
: nullptr);
}
// now put the output into the variables
- if (!this->RunOutputVariable.empty()) {
- this->Makefile->AddDefinition(this->RunOutputVariable,
+ if (arguments.RunOutputVariable) {
+ this->Makefile->AddDefinition(*arguments.RunOutputVariable,
runOutputContents);
}
- if (!this->RunOutputStdOutVariable.empty()) {
- this->Makefile->AddDefinition(this->RunOutputStdOutVariable,
+ if (arguments.RunOutputStdOutVariable) {
+ this->Makefile->AddDefinition(*arguments.RunOutputStdOutVariable,
runOutputStdOutContents);
}
- if (!this->RunOutputStdErrVariable.empty()) {
- this->Makefile->AddDefinition(this->RunOutputStdErrVariable,
+ if (arguments.RunOutputStdErrVariable) {
+ this->Makefile->AddDefinition(*arguments.RunOutputStdErrVariable,
runOutputStdErrContents);
}
- if (!this->OutputVariable.empty()) {
+ if (arguments.OutputVariable && !arguments.CompileOutputVariable) {
// if the TryCompileCore saved output in this outputVariable then
// prepend that output to this output
cmValue compileOutput =
- this->Makefile->GetDefinition(this->OutputVariable);
+ this->Makefile->GetDefinition(*arguments.OutputVariable);
if (compileOutput) {
runOutputContents = *compileOutput + runOutputContents;
}
- this->Makefile->AddDefinition(this->OutputVariable, runOutputContents);
+ this->Makefile->AddDefinition(*arguments.OutputVariable,
+ runOutputContents);
}
}
}
@@ -259,6 +183,7 @@ bool TryRunCommandImpl::TryRunCode(std::vector<std::string> const& argv)
}
void TryRunCommandImpl::RunExecutable(const std::string& runArgs,
+ cm::optional<std::string> const& workDir,
std::string* out, std::string* stdOut,
std::string* stdErr)
{
@@ -286,8 +211,8 @@ void TryRunCommandImpl::RunExecutable(const std::string& runArgs,
bool worked = cmSystemTools::RunSingleCommand(
finalCommand, stdOut || stdErr ? stdOut : out,
stdOut || stdErr ? stdErr : out, &retVal,
- this->WorkingDirectory.empty() ? nullptr : this->WorkingDirectory.c_str(),
- cmSystemTools::OUTPUT_NONE, cmDuration::zero());
+ workDir ? workDir->c_str() : nullptr, cmSystemTools::OUTPUT_NONE,
+ cmDuration::zero());
// set the run var
char retChar[16];
const char* retStr;
@@ -306,11 +231,10 @@ void TryRunCommandImpl::RunExecutable(const std::string& runArgs,
executable, two cache variables are created which will hold the results
the executable would have produced.
*/
-void TryRunCommandImpl::DoNotRunExecutable(const std::string& runArgs,
- const std::string& srcFile,
- std::string* out,
- std::string* stdOut,
- std::string* stdErr)
+void TryRunCommandImpl::DoNotRunExecutable(
+ const std::string& runArgs, const std::string& srcFile,
+ std::string const& compileResultVariable, std::string* out,
+ std::string* stdOut, std::string* stdErr)
{
// copy the executable out of the CMakeFiles/ directory, so it is not
// removed at the end of try_run() and the user can run it manually
@@ -490,7 +414,7 @@ void TryRunCommandImpl::DoNotRunExecutable(const std::string& runArgs,
}
comment += "The ";
- comment += this->CompileResultVariable;
+ comment += compileResultVariable;
comment += " variable holds the build result for this try_run().\n\n"
"Source file : ";
comment += srcFile + "\n";
diff --git a/Tests/RunCMake/try_compile/NoCStandard-result.txt b/Tests/RunCMake/try_compile/NoCStandard-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/try_compile/NoCStandard-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_compile/NoCStandard-stderr.txt b/Tests/RunCMake/try_compile/NoCStandard-stderr.txt
new file mode 100644
index 0000000000..8d2b3f131e
--- /dev/null
+++ b/Tests/RunCMake/try_compile/NoCStandard-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at NoCStandard.cmake:1 \(try_compile\):
+ Error after keyword "C_STANDARD":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCStandard.cmake b/Tests/RunCMake/try_compile/NoCStandard.cmake
new file mode 100644
index 0000000000..b2c9ce6ada
--- /dev/null
+++ b/Tests/RunCMake/try_compile/NoCStandard.cmake
@@ -0,0 +1,2 @@
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ C_STANDARD)
diff --git a/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt
index d65d94883f..36d889faca 100644
--- a/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at NoCopyFile.cmake:1 \(try_compile\):
- COPY_FILE must be followed by a file path
+ Error after keyword "COPY_FILE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt
index e88952475a..7f60e77f47 100644
--- a/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at NoCopyFile2.cmake:1 \(try_compile\):
- COPY_FILE must be followed by a file path
+ Error after keyword "COPY_FILE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt
index ed552fd8e4..dc242c384e 100644
--- a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at NoCopyFileError.cmake:1 \(try_compile\):
- COPY_FILE_ERROR must be followed by a variable name
+ Error after keyword "COPY_FILE_ERROR":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt
index 18ad751cf3..b26be1dd81 100644
--- a/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at NoOutputVariable.cmake:1 \(try_compile\):
- OUTPUT_VARIABLE must be followed by a variable name
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt
index 8b2cc254c7..02d226bfb7 100644
--- a/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at NoOutputVariable2.cmake:1 \(try_compile\):
- OUTPUT_VARIABLE must be followed by a variable name
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/NoSources-stderr.txt b/Tests/RunCMake/try_compile/NoSources-stderr.txt
index 023032b604..a8410d201d 100644
--- a/Tests/RunCMake/try_compile/NoSources-stderr.txt
+++ b/Tests/RunCMake/try_compile/NoSources-stderr.txt
@@ -1,4 +1,7 @@
CMake Error at NoSources.cmake:1 \(try_compile\):
- SOURCES must be followed by at least one source file
+ Error after keyword "SOURCES":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
index 881ef16466..2fe3001b2c 100644
--- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake
@@ -7,6 +7,7 @@ run_cmake(TwoArgs)
run_cmake(NoCopyFile)
run_cmake(NoCopyFile2)
run_cmake(NoCopyFileError)
+run_cmake(NoCStandard)
run_cmake(NoOutputVariable)
run_cmake(NoOutputVariable2)
run_cmake(NoSources)
diff --git a/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt b/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt
index d9346be860..717c208931 100644
--- a/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt
+++ b/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt
@@ -1,71 +1,13 @@
^CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "COMPILE_OUTPUT_VARIABLE".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "compOutputVar".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "RUN_OUTPUT_VARIABLE".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "runOutputVar".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "RUN_OUTPUT_STDOUT_VARIABLE".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "runOutputStdOutVar".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "RUN_OUTPUT_STDERR_VARIABLE".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "runOutputStdErrVar".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "WORKING_DIRECTORY".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "runWorkDir".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "ARGS".
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
-+
-CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\):
- try_compile given unknown argument "runArgs".
+ Ignoring try_run arguments for try_compile:
+
+ COMPILE_OUTPUT_VARIABLE
+ RUN_OUTPUT_VARIABLE
+ RUN_OUTPUT_STDOUT_VARIABLE
+ RUN_OUTPUT_STDERR_VARIABLE
+ WORKING_DIRECTORY
+ ARGS
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt
index 6feaf4f0ec..e8baffb122 100644
--- a/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt
+++ b/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt
@@ -1,5 +1,7 @@
-^CMake Error: COMPILE_OUTPUT_VARIABLE specified but there is no variable
-CMake Error at NoCompileOutputVariable.cmake:[0-9]+ \(try_run\):
- try_run unknown error.
+^CMake Error at NoCompileOutputVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "COMPILE_OUTPUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt
index 33e7df172b..46cfca07de 100644
--- a/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt
+++ b/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt
@@ -1,5 +1,7 @@
-^CMake Error: OUTPUT_VARIABLE specified but there is no variable
-CMake Error at NoOutputVariable.cmake:[0-9]+ \(try_run\):
- try_run unknown error.
+^CMake Error at NoOutputVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt
index 5ec697b8e0..8ccbdab162 100644
--- a/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt
+++ b/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt
@@ -1,5 +1,7 @@
-^CMake Error: RUN_OUTPUT_VARIABLE specified but there is no variable
-CMake Error at NoRunOutputVariable.cmake:[0-9]+ \(try_run\):
- try_run unknown error.
+^CMake Error at NoRunOutputVariable.cmake:[0-9]+ \(try_run\):
+ Error after keyword "RUN_OUTPUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt
index 8dee05695b..04ffc5ddf9 100644
--- a/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt
+++ b/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt
@@ -1,5 +1,7 @@
-^CMake Error: RUN_OUTPUT_STDERR_VARIABLE specified but there is no variable
-CMake Error at NoRunStdErrVariable.cmake:1 \(try_run\):
- try_run unknown error.
+^CMake Error at NoRunStdErrVariable.cmake:1 \(try_run\):
+ Error after keyword "RUN_OUTPUT_STDERR_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt
index 5ea6d23aeb..40e0e27e65 100644
--- a/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt
+++ b/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt
@@ -1,5 +1,7 @@
-^CMake Error: RUN_OUTPUT_STDOUT_VARIABLE specified but there is no variable
-CMake Error at NoRunStdOutVariable.cmake:1 \(try_run\):
- try_run unknown error.
+^CMake Error at NoRunStdOutVariable.cmake:1 \(try_run\):
+ Error after keyword "RUN_OUTPUT_STDOUT_VARIABLE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt b/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt
index 10ad85c628..b6e258f8e6 100644
--- a/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt
+++ b/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt
@@ -1,5 +1,7 @@
-^CMake Error: WORKING_DIRECTORY specified but there is no variable
-CMake Error at NoWorkingDirectory.cmake:[0-9]+ \(try_run\):
- try_run unknown error.
+^CMake Error at NoWorkingDirectory.cmake:[0-9]+ \(try_run\):
+ Error after keyword "WORKING_DIRECTORY":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$