summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/cmCoreTryCompile.cxx103
-rw-r--r--Source/cmCoreTryCompile.h20
-rw-r--r--Source/cmake.cxx3
3 files changed, 103 insertions, 23 deletions
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 7b9dc2e..0a6c359 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -31,6 +31,7 @@
#include "cmake.h"
namespace {
+constexpr const char* unique_binary_directory = "CMAKE_BINARY_DIR_USE_MKDTEMP";
constexpr size_t lang_property_start = 0;
constexpr size_t lang_property_size = 4;
constexpr size_t pie_property_start = 4;
@@ -122,13 +123,9 @@ ArgumentParser::Continue TryCompileCompileDefs(Arguments& args,
.Bind(#lang "_STANDARD_REQUIRED"_s, TryCompileLangProp) \
.Bind(#lang "_EXTENSIONS"_s, TryCompileLangProp)
-auto const TryCompileArgParser =
+auto const TryCompileBaseArgParser =
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,
@@ -136,7 +133,6 @@ auto const TryCompileArgParser =
.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)
@@ -147,8 +143,31 @@ auto const TryCompileArgParser =
.BIND_LANG_PROPS(OBJCXX)
/* keep semicolon on own line */;
-auto const TryRunArgParser =
+auto const TryCompileArgParser =
+ cmArgumentParser<Arguments>{ TryCompileBaseArgParser }.Bind(
+ "OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
+ /* keep semicolon on own line */;
+
+auto const TryCompileOldArgParser =
cmArgumentParser<Arguments>{ TryCompileArgParser }
+ .Bind(1, &Arguments::BinaryDirectory)
+ .Bind(2, &Arguments::SourceDirectoryOrFile)
+ .Bind(3, &Arguments::ProjectName)
+ .Bind(4, &Arguments::TargetName)
+ /* keep semicolon on own line */;
+
+auto const TryRunArgParser =
+ cmArgumentParser<Arguments>{ TryCompileBaseArgParser }
+ .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 */;
+
+auto const TryRunOldArgParser =
+ cmArgumentParser<Arguments>{ TryCompileOldArgParser }
.Bind("COMPILE_OUTPUT_VARIABLE"_s, &Arguments::CompileOutputVariable)
.Bind("RUN_OUTPUT_VARIABLE"_s, &Arguments::RunOutputVariable)
.Bind("RUN_OUTPUT_STDOUT_VARIABLE"_s, &Arguments::RunOutputStdOutVariable)
@@ -161,10 +180,10 @@ auto const TryRunArgParser =
}
Arguments cmCoreTryCompile::ParseArgs(
- cmRange<std::vector<std::string>::const_iterator> args, bool isTryRun)
+ const cmRange<std::vector<std::string>::const_iterator>& args,
+ const cmArgumentParser<Arguments>& parser,
+ std::vector<std::string>& unparsedArguments)
{
- std::vector<std::string> unparsedArguments;
- const auto& parser = (isTryRun ? TryRunArgParser : TryCompileArgParser);
auto arguments = parser.Parse(args, &unparsedArguments, 0);
if (!arguments.MaybeReportError(*(this->Makefile)) &&
!unparsedArguments.empty()) {
@@ -174,6 +193,26 @@ Arguments cmCoreTryCompile::ParseArgs(
}
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m);
}
+ return arguments;
+}
+
+Arguments cmCoreTryCompile::ParseArgs(
+ cmRange<std::vector<std::string>::const_iterator> args, bool isTryRun)
+{
+ std::vector<std::string> unparsedArguments;
+ if (cmHasLiteralPrefix(*(++args.begin()), "SOURCE")) {
+ // New signature.
+ auto arguments =
+ this->ParseArgs(args, isTryRun ? TryRunArgParser : TryCompileArgParser,
+ unparsedArguments);
+ arguments.BinaryDirectory = unique_binary_directory;
+ return arguments;
+ }
+
+ // Old signature.
+ auto arguments = this->ParseArgs(
+ args, isTryRun ? TryRunOldArgParser : TryCompileOldArgParser,
+ unparsedArguments);
// For historical reasons, treat some empty-valued keyword
// arguments as if they were not specified at all.
if (arguments.OutputVariable && arguments.OutputVariable->empty()) {
@@ -210,6 +249,7 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
// which signature were we called with ?
this->SrcFileSignature = true;
+ bool useUniqueBinaryDirectory = false;
std::string sourceDirectory;
std::string projectName;
std::string targetName;
@@ -230,7 +270,17 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
targetName = targetNameBuf;
}
- if (arguments.BinaryDirectory && !arguments.BinaryDirectory->empty()) {
+ if (!arguments.BinaryDirectory || arguments.BinaryDirectory->empty()) {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "No <bindir> specified.");
+ return false;
+ }
+ if (*arguments.BinaryDirectory == unique_binary_directory) {
+ // leave empty until we're ready to create it, so we don't try to remove
+ // a non-existing directory if we abort due to e.g. bad arguments
+ this->BinaryDirectory.clear();
+ useUniqueBinaryDirectory = true;
+ } else {
if (!cmSystemTools::FileIsFullPath(*arguments.BinaryDirectory)) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
@@ -244,10 +294,6 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
if (this->SrcFileSignature) {
this->BinaryDirectory += "/CMakeFiles/CMakeTmp";
}
- } else {
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
- "No <bindir> specified.");
- return false;
}
std::vector<std::string> targets;
@@ -331,7 +377,14 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
}
}
// make sure the binary directory exists
- cmSystemTools::MakeDirectory(this->BinaryDirectory);
+ if (useUniqueBinaryDirectory) {
+ this->BinaryDirectory =
+ cmStrCat(this->Makefile->GetHomeOutputDirectory(),
+ "/CMakeFiles/CMakeScratch/TryCompile-XXXXXX");
+ cmSystemTools::MakeTempDirectory(this->BinaryDirectory);
+ } else {
+ cmSystemTools::MakeDirectory(this->BinaryDirectory);
+ }
// do not allow recursive try Compiles
if (this->BinaryDirectory == this->Makefile->GetHomeOutputDirectory()) {
@@ -635,7 +688,7 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
fprintf(fout, " \"%s\"", si.c_str());
// Add dependencies on any non-temporary sources.
- if (si.find("CMakeTmp") == std::string::npos) {
+ if (!IsTemporary(si)) {
this->Makefile->AddCMakeDependFile(si);
}
}
@@ -914,17 +967,23 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
return res == 0;
}
+bool cmCoreTryCompile::IsTemporary(std::string const& path)
+{
+ return ((path.find("CMakeTmp") != std::string::npos) ||
+ (path.find("CMakeScratch") != std::string::npos));
+}
+
void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
{
if (binDir.empty()) {
return;
}
- if (binDir.find("CMakeTmp") == std::string::npos) {
+ if (!IsTemporary(binDir)) {
cmSystemTools::Error(
"TRY_COMPILE attempt to remove -rf directory that does not contain "
- "CMakeTmp:" +
- binDir);
+ "CMakeTmp or CMakeScratch: \"" +
+ binDir + "\"");
return;
}
@@ -970,6 +1029,10 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
}
}
}
+
+ if (binDir.find("CMakeScratch") != std::string::npos) {
+ cmSystemTools::RemoveADirectory(binDir);
+ }
}
void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index deefe57..b483f0f 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -67,14 +67,22 @@ public:
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.
+ * 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.
+ *
+ * This function requires at least two \p arguments and will crash if given
+ * fewer.
*/
bool TryCompileCode(Arguments& arguments,
cmStateEnums::TargetType targetType);
/**
+ * Returns \c true if \p path resides within a CMake temporary directory,
+ * otherwise returns \c false.
+ */
+ static bool IsTemporary(std::string const& path);
+
+ /**
* This deletes all the files created by TryCompileCode.
* This way we do not have to rely on the timing and
* dependencies of makefiles.
@@ -94,4 +102,10 @@ public:
std::string FindErrorMessage;
bool SrcFileSignature = false;
cmMakefile* Makefile;
+
+private:
+ Arguments ParseArgs(
+ const cmRange<std::vector<std::string>::const_iterator>& args,
+ const cmArgumentParser<Arguments>& parser,
+ std::vector<std::string>& unparsedArguments);
};
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 9b2b119..c792d4a 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2130,6 +2130,9 @@ int cmake::ActualConfigure()
this->UpdateConversionPathTable();
this->CleanupCommandsAndMacros();
+ cmSystemTools::RemoveADirectory(this->GetHomeOutputDirectory() +
+ "/CMakeFiles/CMakeScratch");
+
int res = this->DoPreConfigureChecks();
if (res < 0) {
return -2;