summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt4
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx111
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx7
-rw-r--r--Source/CPack/cmCPackGenerator.cxx3
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx4
-rw-r--r--Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx2
-rw-r--r--Source/CTest/cmCTestGenericHandler.cxx52
-rw-r--r--Source/CTest/cmCTestGenericHandler.h32
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx10
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.cxx4
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx23
-rw-r--r--Source/CTest/cmCTestScriptHandler.h12
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx6
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx109
-rw-r--r--Source/CTest/cmCTestTestHandler.h8
-rw-r--r--Source/QtDialog/QCMake.cxx4
-rw-r--r--Source/cmCMakePresetsFile.cxx1069
-rw-r--r--Source/cmCMakePresetsFile.h27
-rw-r--r--Source/cmCMakePresetsFileInternal.h112
-rw-r--r--Source/cmCMakePresetsFileReadJSON.cxx1022
-rw-r--r--Source/cmCTest.cxx42
-rw-r--r--Source/cmCTest.h2
-rw-r--r--Source/cmCommandLineArgument.h4
-rw-r--r--Source/cmComputeLinkInformation.cxx19
-rw-r--r--Source/cmComputeLinkInformation.h6
-rw-r--r--Source/cmCreateTestSourceList.cxx11
-rw-r--r--Source/cmCustomCommandGenerator.cxx21
-rw-r--r--Source/cmCustomCommandGenerator.h1
-rw-r--r--Source/cmExportFileGenerator.cxx4
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx3
-rw-r--r--Source/cmFileAPI.cxx2
-rw-r--r--Source/cmFileAPICodemodel.cxx468
-rw-r--r--Source/cmFileCommand.cxx146
-rw-r--r--Source/cmFindLibraryCommand.cxx2
-rw-r--r--Source/cmGeneratorExpressionNode.cxx55
-rw-r--r--Source/cmGeneratorTarget.cxx14
-rw-r--r--Source/cmGeneratorTarget.h5
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx65
-rw-r--r--Source/cmGlobalNinjaGenerator.h5
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx338
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h30
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx5
-rw-r--r--Source/cmInstallTargetGenerator.cxx1
-rw-r--r--Source/cmInstallTargetGenerator.h2
-rw-r--r--Source/cmJSONHelpers.h2
-rw-r--r--Source/cmListCommand.cxx68
-rw-r--r--Source/cmListFileCache.cxx12
-rw-r--r--Source/cmLocalGenerator.cxx25
-rw-r--r--Source/cmLocalGenerator.h30
-rw-r--r--Source/cmLocalNinjaGenerator.cxx13
-rw-r--r--Source/cmLocalNinjaGenerator.h6
-rw-r--r--Source/cmMakefile.cxx4
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx7
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx5
-rw-r--r--Source/cmMakefileTargetGenerator.cxx6
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx6
-rw-r--r--Source/cmNinjaTargetGenerator.cxx14
-rw-r--r--Source/cmOrderDirectories.cxx2
-rw-r--r--Source/cmPolicies.h9
-rw-r--r--Source/cmProjectCommand.cxx5
-rw-r--r--Source/cmQtAutoGenInitializer.cxx130
-rw-r--r--Source/cmQtAutoGenInitializer.h7
-rw-r--r--Source/cmQtAutoMocUic.cxx6
-rw-r--r--Source/cmSourceFile.h2
-rw-r--r--Source/cmStandardLevelResolver.cxx5
-rw-r--r--Source/cmStateSnapshot.cxx55
-rw-r--r--Source/cmStringCommand.cxx4
-rw-r--r--Source/cmSystemTools.cxx170
-rw-r--r--Source/cmSystemTools.h36
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx12
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.cxx143
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.h31
-rw-r--r--Source/cmake.cxx61
-rw-r--r--Source/cmake.h4
-rw-r--r--Source/cmcmd.cxx20
-rw-r--r--Source/ctest.cxx10
-rw-r--r--Source/kwsys/Directory.cxx30
-rw-r--r--Source/kwsys/Glob.hxx.in7
-rw-r--r--Source/kwsys/SystemTools.cxx19
-rw-r--r--Source/kwsys/SystemTools.hxx.in11
-rw-r--r--Source/kwsys/Terminal.c2
82 files changed, 3300 insertions, 1553 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 6adc9cf..938745c 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -198,6 +198,8 @@ set(SRCS
cmCMakePath.cxx
cmCMakePresetsFile.cxx
cmCMakePresetsFile.h
+ cmCMakePresetsFileInternal.h
+ cmCMakePresetsFileReadJSON.cxx
cmCommandArgumentParserHelper.cxx
cmCommonTargetGenerator.cxx
cmCommonTargetGenerator.h
@@ -785,8 +787,6 @@ if (WIN32)
cmVisualStudioGeneratorOptions.cxx
cmVisualStudio10TargetGenerator.h
cmVisualStudio10TargetGenerator.cxx
- cmVisualStudio10ToolsetOptions.h
- cmVisualStudio10ToolsetOptions.cxx
cmLocalVisualStudio10Generator.cxx
cmLocalVisualStudio10Generator.h
cmGlobalVisualStudio10Generator.h
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 8b9029f..8930a5f 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 20)
-set(CMake_VERSION_PATCH 1)
+set(CMake_VERSION_PATCH 20210414)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
index c4bd7f1..1429c46 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -7,6 +7,8 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
+
#include "cmCPackComponentGroup.h"
#include "cmCPackIFWCommon.h"
#include "cmCPackIFWGenerator.h"
@@ -30,44 +32,67 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default;
cmCPackIFWPackage::DependenceStruct::DependenceStruct(
const std::string& dependence)
{
- // Search compare section
- size_t pos = std::string::npos;
- if ((pos = dependence.find("<=")) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
- this->Compare.Value = dependence.substr(pos + 2);
- } else if ((pos = dependence.find(">=")) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
- this->Compare.Value = dependence.substr(pos + 2);
- } else if ((pos = dependence.find('<')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareLess;
- this->Compare.Value = dependence.substr(pos + 1);
- } else if ((pos = dependence.find('=')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareEqual;
- this->Compare.Value = dependence.substr(pos + 1);
- } else if ((pos = dependence.find('>')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareGreater;
- this->Compare.Value = dependence.substr(pos + 1);
- } else if ((pos = dependence.find('-')) != std::string::npos) {
- this->Compare.Type = cmCPackIFWPackage::CompareNone;
- this->Compare.Value = dependence.substr(pos + 1);
- }
- size_t dashPos = dependence.find('-');
- if (dashPos != std::string::npos) {
- pos = dashPos;
- }
- this->Name = dependence.substr(0, pos);
+ // Preferred format is name and version are separated by a colon (:), but
+ // note that this is only supported with QtIFW 3.1 or later. Backward
+ // compatibility allows a hyphen (-) as a separator instead, but names then
+ // cannot contain a hyphen.
+ size_t pos;
+ if ((pos = dependence.find(':')) == std::string::npos) {
+ pos = dependence.find('-');
+ }
+
+ if (pos != std::string::npos) {
+ this->Name = dependence.substr(0, pos);
+ ++pos;
+ if (pos == dependence.size()) {
+ // Nothing after the separator. Treat this as no version constraint.
+ return;
+ }
+
+ const auto versionPart =
+ cm::string_view(dependence.data() + pos, dependence.size() - pos);
+
+ if (cmHasLiteralPrefix(versionPart, "<=")) {
+ this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
+ this->Compare.Value = std::string(versionPart.substr(2));
+ } else if (cmHasLiteralPrefix(versionPart, ">=")) {
+ this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
+ this->Compare.Value = std::string(versionPart.substr(2));
+ } else if (cmHasPrefix(versionPart, '<')) {
+ this->Compare.Type = cmCPackIFWPackage::CompareLess;
+ this->Compare.Value = std::string(versionPart.substr(1));
+ } else if (cmHasPrefix(versionPart, '=')) {
+ this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+ this->Compare.Value = std::string(versionPart.substr(1));
+ } else if (cmHasPrefix(versionPart, '>')) {
+ this->Compare.Type = cmCPackIFWPackage::CompareGreater;
+ this->Compare.Value = std::string(versionPart.substr(1));
+ } else {
+ // We found no operator but a version specification is still expected to
+ // follow. The default behavior is to treat this the same as =. We
+ // explicitly record that as our type (it simplifies our logic a little
+ // and is also clearer).
+ this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+ this->Compare.Value = std::string(versionPart);
+ }
+ } else {
+ this->Name = dependence;
+ }
}
std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
{
- if (this->Compare.Type == cmCPackIFWPackage::CompareNone) {
- return this->Name;
- }
-
std::string result = this->Name;
-
- if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
- !this->Compare.Value.empty()) {
+ if (this->Name.find('-') != std::string::npos) {
+ // When a name contains a hyphen, we must use a colon after the name to
+ // prevent the hyphen from being parsed by QtIFW as the separator between
+ // the name and the version. Note that a colon is only supported with
+ // QtIFW 3.1 or later.
+ result += ":";
+ } else if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
+ !this->Compare.Value.empty()) {
+ // No hyphen in the name and we know a version part will follow. Use a
+ // hyphen as a separator since this works for all QtIFW versions.
result += "-";
}
@@ -609,6 +634,9 @@ void cmCPackIFWPackage::GeneratePackageFile()
}
// Dependencies
+ const bool hyphensInNamesUnsupported = this->Generator &&
+ !this->Generator->FrameworkVersion.empty() && this->IsVersionLess("3.1");
+ bool warnUnsupportedNames = false;
std::set<DependenceStruct> compDepSet;
for (DependenceStruct* ad : this->AlienDependencies) {
compDepSet.insert(*ad);
@@ -620,9 +648,13 @@ void cmCPackIFWPackage::GeneratePackageFile()
if (!compDepSet.empty()) {
std::ostringstream dependencies;
auto it = compDepSet.begin();
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << it->NameWithCompare();
++it;
while (it != compDepSet.end()) {
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << "," << it->NameWithCompare();
++it;
}
@@ -638,15 +670,28 @@ void cmCPackIFWPackage::GeneratePackageFile()
if (!compAutoDepSet.empty()) {
std::ostringstream dependencies;
auto it = compAutoDepSet.begin();
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << it->NameWithCompare();
++it;
while (it != compAutoDepSet.end()) {
+ warnUnsupportedNames |=
+ hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
dependencies << "," << it->NameWithCompare();
++it;
}
xout.Element("AutoDependOn", dependencies.str());
}
+ if (warnUnsupportedNames) {
+ cmCPackIFWLogger(
+ WARNING,
+ "The dependencies for component \""
+ << this->Name << "\" specify names that contain hyphens. "
+ << "This requires QtIFW 3.1 or later, but you are using version "
+ << this->Generator->FrameworkVersion << std::endl);
+ }
+
// Licenses (copy to meta dir)
std::vector<std::string> licenses = this->Licenses;
for (size_t i = 1; i < licenses.size(); i += 2) {
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index cefb906..0d56e5f 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -273,6 +273,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
? this->GetOption("CPACK_DMG_FORMAT")
: "UDZO";
+ const std::string cpack_dmg_filesystem =
+ this->GetOption("CPACK_DMG_FILESYSTEM")
+ ? this->GetOption("CPACK_DMG_FILESYSTEM")
+ : "HFS+";
+
// Get optional arguments ...
std::string cpack_license_file =
this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
@@ -418,7 +423,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
temp_image_command << " -ov";
temp_image_command << " -srcfolder \"" << staging.str() << "\"";
temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\"";
- temp_image_command << " -fs HFS+";
+ temp_image_command << " -fs \"" << cpack_dmg_filesystem << "\"";
temp_image_command << " -format " << temp_image_format;
temp_image_command << " \"" << temp_image << "\"";
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 3db4162..c512a36 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -384,7 +384,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
for (std::string const& gf : this->files) {
bool skip = false;
std::string inFile = gf;
- if (cmSystemTools::FileIsDirectory(gf)) {
+ if (cmSystemTools::FileIsDirectory(gf) &&
+ !cmSystemTools::FileIsSymlink(gf)) {
inFile += '/';
}
for (cmsys::RegularExpression& reg : ignoreFilesRegex) {
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index f1cc677..6bd0d1b 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -437,7 +437,9 @@ int cmCPackNSISGenerator::InitializeInternal()
}
#endif
- nsisPath = cmSystemTools::FindProgram("makensis", path, false);
+ this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLE", "makensis");
+ nsisPath = cmSystemTools::FindProgram(
+ this->GetOption("CPACK_NSIS_EXECUTABLE"), path, false);
if (nsisPath.empty()) {
cmCPackLogger(
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
index 051c117..af495bb 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
@@ -16,7 +16,7 @@ bool cmCTestEmptyBinaryDirectoryCommand::InitialPass(
return false;
}
- if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0].c_str())) {
+ if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0])) {
std::ostringstream ostr;
ostr << "problem removing the binary directory: " << args[0];
this->SetError(ostr.str());
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 91818bb..cc756d7 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -21,32 +21,47 @@ cmCTestGenericHandler::cmCTestGenericHandler()
cmCTestGenericHandler::~cmCTestGenericHandler() = default;
-void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
+/* Modify the given `map`, setting key `op` to `value` if `value`
+ * is non-null, otherwise removing key `op` (if it exists).
+ */
+static void SetMapValue(cmCTestGenericHandler::t_StringToString& map,
+ const std::string& op, const char* value)
{
if (!value) {
- auto remit = this->Options.find(op);
- if (remit != this->Options.end()) {
- this->Options.erase(remit);
- }
+ map.erase(op);
return;
}
- this->Options[op] = value;
+ map[op] = value;
+}
+
+void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
+{
+ SetMapValue(this->Options, op, value);
}
void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
const char* value)
{
this->SetOption(op, value);
- if (!value) {
- auto remit = this->PersistentOptions.find(op);
- if (remit != this->PersistentOptions.end()) {
- this->PersistentOptions.erase(remit);
- }
- return;
+ SetMapValue(this->PersistentOptions, op, value);
+}
+
+void cmCTestGenericHandler::AddMultiOption(const std::string& op,
+ const std::string& value)
+{
+ if (!value.empty()) {
+ this->MultiOptions[op].emplace_back(value);
}
+}
- this->PersistentOptions[op] = value;
+void cmCTestGenericHandler::AddPersistentMultiOption(const std::string& op,
+ const std::string& value)
+{
+ if (!value.empty()) {
+ this->MultiOptions[op].emplace_back(value);
+ this->PersistentMultiOptions[op].emplace_back(value);
+ }
}
void cmCTestGenericHandler::Initialize()
@@ -68,6 +83,17 @@ const char* cmCTestGenericHandler::GetOption(const std::string& op)
return remit->second.c_str();
}
+std::vector<std::string> cmCTestGenericHandler::GetMultiOption(
+ const std::string& optionName) const
+{
+ // Avoid inserting a key, which MultiOptions[op] would do.
+ auto remit = this->MultiOptions.find(optionName);
+ if (remit == this->MultiOptions.end()) {
+ return {};
+ }
+ return remit->second;
+}
+
bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part,
const char* name,
cmGeneratedFileStream& xofs)
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index 89d7596..6f44545 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -72,11 +72,41 @@ public:
virtual ~cmCTestGenericHandler();
using t_StringToString = std::map<std::string, std::string>;
+ using t_StringToMultiString =
+ std::map<std::string, std::vector<std::string>>;
+ /**
+ * Options collect a single value from flags; passing the
+ * flag multiple times on the command-line *overwrites* values,
+ * and only the last one specified counts. Set an option to
+ * nullptr to "unset" it.
+ *
+ * The value is stored as a string. The values set for single
+ * and multi-options (see below) live in different spaces,
+ * so calling a single-getter for a key that has only been set
+ * as a multi-value will return nullptr.
+ */
void SetPersistentOption(const std::string& op, const char* value);
void SetOption(const std::string& op, const char* value);
const char* GetOption(const std::string& op);
+ /**
+ * Multi-Options collect one or more values from flags; passing
+ * the flag multiple times on the command-line *adds* values,
+ * rather than overwriting the previous values.
+ *
+ * Adding an empty value does nothing.
+ *
+ * The value is stored as a vector of strings. The values set for single
+ * (see above) and multi-options live in different spaces,
+ * so calling a multi-getter for a key that has only been set
+ * as a single-value will return an empty vector.
+ */
+ void AddPersistentMultiOption(const std::string& optionName,
+ const std::string& value);
+ void AddMultiOption(const std::string& optionName, const std::string& value);
+ std::vector<std::string> GetMultiOption(const std::string& op) const;
+
void SetCommand(cmCTestCommand* command) { this->Command = command; }
void SetSubmitIndex(int idx) { this->SubmitIndex = idx; }
@@ -100,6 +130,8 @@ protected:
cmCTest* CTest;
t_StringToString Options;
t_StringToString PersistentOptions;
+ t_StringToMultiString MultiOptions;
+ t_StringToMultiString PersistentMultiOptions;
t_StringToString LogFileNames;
cmCTestCommand* Command;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 852f9d9..86a8e00 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -587,24 +587,24 @@ void cmCTestMultiProcessHandler::StartNextTests()
onlyRunSerialTestsLeft = false;
}
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, ");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "***** WAITING, ");
if (this->SerialTestRunning) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Waiting for RUN_SERIAL test to finish.");
} else if (onlyRunSerialTestsLeft) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Only RUN_SERIAL tests remain, awaiting available slot.");
} else {
/* clang-format off */
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"System Load: " << systemLoad << ", "
"Max Allowed Load: " << this->TestLoad << ", "
"Smallest test " << testWithMinProcessors <<
" requires " << minProcessorsRequired);
/* clang-format on */
}
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "*****" << std::endl);
// Wait between 1 and 5 seconds before trying again.
unsigned int milliseconds = (cmSystemTools::RandomSeed() % 5 + 1) * 1000;
diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx
index f59ca57..7661d4d 100644
--- a/Source/CTest/cmCTestRunScriptCommand.cxx
+++ b/Source/CTest/cmCTestRunScriptCommand.cxx
@@ -37,8 +37,8 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args,
++i;
} else {
int ret;
- cmCTestScriptHandler::RunScript(this->CTest, this->Makefile,
- args[i].c_str(), !np, &ret);
+ cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, args[i],
+ !np, &ret);
this->Makefile->AddDefinition(returnVariable, std::to_string(ret));
}
}
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 4808c36..ff0b179 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -4,7 +4,6 @@
#include <cstdio>
#include <cstdlib>
-#include <cstring>
#include <map>
#include <ratio>
#include <sstream>
@@ -91,7 +90,7 @@ void cmCTestScriptHandler::Initialize()
cmCTestScriptHandler::~cmCTestScriptHandler() = default;
// just adds an argument to the vector
-void cmCTestScriptHandler::AddConfigurationScript(const char* script,
+void cmCTestScriptHandler::AddConfigurationScript(const std::string& script,
bool pscope)
{
this->ConfigurationScripts.emplace_back(script);
@@ -676,7 +675,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
// clear the binary directory?
if (this->EmptyBinDir) {
- if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir.c_str())) {
+ if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Problem removing the binary directory" << std::endl);
}
@@ -724,8 +723,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
// put the initial cache into the bin dir
if (!this->InitialCache.empty()) {
- if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir.c_str(),
- this->InitialCache.c_str())) {
+ if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir,
+ this->InitialCache)) {
this->RestoreBackupDirectories();
return 9;
}
@@ -812,8 +811,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
return 0;
}
-bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
- const char* text)
+bool cmCTestScriptHandler::WriteInitialCache(const std::string& directory,
+ const std::string& text)
{
std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt");
cmGeneratedFileStream fout(cacheFile);
@@ -821,9 +820,7 @@ bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
return false;
}
- if (text != nullptr) {
- fout.write(text, strlen(text));
- }
+ fout.write(text.data(), text.size());
// Make sure the operating system has finished writing the file
// before closing it. This will ensure the file is finished before
@@ -852,7 +849,7 @@ void cmCTestScriptHandler::RestoreBackupDirectories()
}
bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf,
- const char* sname, bool InProcess,
+ const std::string& sname, bool InProcess,
int* returnValue)
{
auto sh = cm::make_unique<cmCTestScriptHandler>();
@@ -866,10 +863,10 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf,
return true;
}
-bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname)
+bool cmCTestScriptHandler::EmptyBinaryDirectory(const std::string& sname)
{
// try to avoid deleting root
- if (!sname || strlen(sname) < 2) {
+ if (sname.size() < 2) {
return false;
}
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index 8eb9658..b7764b2 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -62,7 +62,7 @@ public:
/**
* Add a script to run, and if is should run in the current process
*/
- void AddConfigurationScript(const char*, bool pscope);
+ void AddConfigurationScript(const std::string&, bool pscope);
/**
* Run a dashboard using a specified confiuration script
@@ -72,19 +72,21 @@ public:
/*
* Run a script
*/
- static bool RunScript(cmCTest* ctest, cmMakefile* mf, const char* script,
- bool InProcess, int* returnValue);
+ static bool RunScript(cmCTest* ctest, cmMakefile* mf,
+ const std::string& script, bool InProcess,
+ int* returnValue);
int RunCurrentScript();
/*
* Empty Binary Directory
*/
- static bool EmptyBinaryDirectory(const char* dir);
+ static bool EmptyBinaryDirectory(const std::string& dir);
/*
* Write an initial CMakeCache.txt from the given contents.
*/
- static bool WriteInitialCache(const char* directory, const char* text);
+ static bool WriteInitialCache(const std::string& directory,
+ const std::string& text);
/*
* Some elapsed time handling functions
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 4403733..886c263 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -73,11 +73,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
handler->SetOption("IncludeRegularExpression", this->Include.c_str());
}
if (!this->ExcludeLabel.empty()) {
- handler->SetOption("ExcludeLabelRegularExpression",
- this->ExcludeLabel.c_str());
+ handler->AddMultiOption("ExcludeLabelRegularExpression",
+ this->ExcludeLabel);
}
if (!this->IncludeLabel.empty()) {
- handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str());
+ handler->AddMultiOption("LabelRegularExpression", this->IncludeLabel);
}
if (!this->ExcludeFixture.empty()) {
handler->SetOption("ExcludeFixtureRegularExpression",
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 1cb5d00..742e78a 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -287,8 +287,6 @@ cmCTestTestHandler::cmCTestTestHandler()
{
this->UseUnion = false;
- this->UseIncludeLabelRegExpFlag = false;
- this->UseExcludeLabelRegExpFlag = false;
this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false;
@@ -327,13 +325,11 @@ void cmCTestTestHandler::Initialize()
this->TestsToRun.clear();
- this->UseIncludeLabelRegExpFlag = false;
- this->UseExcludeLabelRegExpFlag = false;
this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false;
- this->IncludeLabelRegularExpression = "";
- this->ExcludeLabelRegularExpression = "";
+ this->IncludeLabelRegularExpressions.clear();
+ this->ExcludeLabelRegularExpressions.clear();
this->IncludeRegExp.clear();
this->ExcludeRegExp.clear();
this->ExcludeFixtureRegExp.clear();
@@ -479,6 +475,22 @@ int cmCTestTestHandler::ProcessHandler()
return 0;
}
+/* Given a multi-option value `parts`, compile those parts into
+ * regular expressions in `expressions`. Skip empty values.
+ * Returns true if there were any expressions.
+ */
+static bool BuildLabelRE(const std::vector<std::string>& parts,
+ std::vector<cmsys::RegularExpression>& expressions)
+{
+ expressions.clear();
+ for (const auto& p : parts) {
+ if (!p.empty()) {
+ expressions.emplace_back(p);
+ }
+ }
+ return !expressions.empty();
+}
+
bool cmCTestTestHandler::ProcessOptions()
{
// Update internal data structure from generic one
@@ -519,18 +531,11 @@ bool cmCTestTestHandler::ProcessOptions()
this->CTest->SetStopOnFailure(true);
}
- const char* val;
- val = this->GetOption("LabelRegularExpression");
- if (val) {
- this->UseIncludeLabelRegExpFlag = true;
- this->IncludeLabelRegExp = val;
- }
- val = this->GetOption("ExcludeLabelRegularExpression");
- if (val) {
- this->UseExcludeLabelRegExpFlag = true;
- this->ExcludeLabelRegExp = val;
- }
- val = this->GetOption("IncludeRegularExpression");
+ BuildLabelRE(this->GetMultiOption("LabelRegularExpression"),
+ this->IncludeLabelRegularExpressions);
+ BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"),
+ this->ExcludeLabelRegularExpressions);
+ const char* val = this->GetOption("IncludeRegularExpression");
if (val) {
this->UseIncludeRegExp();
this->SetIncludeRegExp(val);
@@ -763,10 +768,40 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
}
+/**
+ * Check if the labels (from a test) match all the expressions.
+ *
+ * Each of the RE's must match at least one label
+ * (e.g. all of the REs must match **some** label,
+ * in order for the filter to apply to the test).
+ */
+static bool MatchLabelsAgainstFilterRE(
+ const std::vector<std::string>& labels,
+ const std::vector<cmsys::RegularExpression>& expressions)
+{
+ for (const auto& re : expressions) {
+ // check to see if the label regular expression matches
+ bool found = false; // assume it does not match
+ cmsys::RegularExpressionMatch match;
+ // loop over all labels and look for match
+ for (std::string const& l : labels) {
+ if (re.find(l.c_str(), match)) {
+ found = true;
+ break;
+ }
+ }
+ // if no match was found, exclude the test
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+}
+
void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
- if (!this->UseIncludeLabelRegExpFlag) {
+ if (this->IncludeLabelRegularExpressions.empty()) {
return;
}
// if there are no labels and we are filtering by labels
@@ -775,16 +810,9 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
it.IsInBasedOnREOptions = false;
return;
}
- // check to see if the label regular expression matches
- bool found = false; // assume it does not match
- // loop over all labels and look for match
- for (std::string const& l : it.Labels) {
- if (this->IncludeLabelRegularExpression.find(l)) {
- found = true;
- }
- }
// if no match was found, exclude the test
- if (!found) {
+ if (!MatchLabelsAgainstFilterRE(it.Labels,
+ this->IncludeLabelRegularExpressions)) {
it.IsInBasedOnREOptions = false;
}
}
@@ -792,7 +820,7 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
- if (!this->UseExcludeLabelRegExpFlag) {
+ if (this->ExcludeLabelRegularExpressions.empty()) {
return;
}
// if there are no labels and we are excluding by labels
@@ -800,16 +828,9 @@ void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
if (it.Labels.empty()) {
return;
}
- // check to see if the label regular expression matches
- bool found = false; // assume it does not match
- // loop over all labels and look for match
- for (std::string const& l : it.Labels) {
- if (this->ExcludeLabelRegularExpression.find(l)) {
- found = true;
- }
- }
// if match was found, exclude the test
- if (found) {
+ if (MatchLabelsAgainstFilterRE(it.Labels,
+ this->ExcludeLabelRegularExpressions)) {
it.IsInBasedOnREOptions = false;
}
}
@@ -1704,19 +1725,11 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty(
bool cmCTestTestHandler::GetListOfTests()
{
- if (!this->IncludeLabelRegExp.empty()) {
- this->IncludeLabelRegularExpression.compile(
- this->IncludeLabelRegExp.c_str());
- }
- if (!this->ExcludeLabelRegExp.empty()) {
- this->ExcludeLabelRegularExpression.compile(
- this->ExcludeLabelRegExp.c_str());
- }
if (!this->IncludeRegExp.empty()) {
- this->IncludeTestsRegularExpression.compile(this->IncludeRegExp.c_str());
+ this->IncludeTestsRegularExpression.compile(this->IncludeRegExp);
}
if (!this->ExcludeRegExp.empty()) {
- this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp.c_str());
+ this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp);
}
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Constructing a list of tests" << std::endl, this->Quiet);
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index aa29eeb..6fa18a9 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -320,20 +320,16 @@ private:
std::vector<int> TestsToRun;
- bool UseIncludeLabelRegExpFlag;
- bool UseExcludeLabelRegExpFlag;
bool UseIncludeRegExpFlag;
bool UseExcludeRegExpFlag;
bool UseExcludeRegExpFirst;
- std::string IncludeLabelRegExp;
- std::string ExcludeLabelRegExp;
std::string IncludeRegExp;
std::string ExcludeRegExp;
std::string ExcludeFixtureRegExp;
std::string ExcludeFixtureSetupRegExp;
std::string ExcludeFixtureCleanupRegExp;
- cmsys::RegularExpression IncludeLabelRegularExpression;
- cmsys::RegularExpression ExcludeLabelRegularExpression;
+ std::vector<cmsys::RegularExpression> IncludeLabelRegularExpressions;
+ std::vector<cmsys::RegularExpression> ExcludeLabelRegularExpressions;
cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression;
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index f593f83..6796e25 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -160,7 +160,7 @@ void QCMake::setPreset(const QString& name, bool setBinary)
auto const& expandedPreset =
this->CMakePresetsFile.ConfigurePresets[presetName].Expanded;
if (expandedPreset) {
- if (setBinary) {
+ if (setBinary && !expandedPreset->BinaryDir.empty()) {
QString binaryDir =
QString::fromLocal8Bit(expandedPreset->BinaryDir.data());
this->setBinaryDirectory(binaryDir);
@@ -557,7 +557,7 @@ void QCMake::loadPresets()
preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data()));
preset.setToolset = !p.ToolsetStrategy ||
p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
- preset.enabled = it.Expanded &&
+ preset.enabled = it.Expanded && it.Expanded->ConditionResult &&
std::find_if(this->AvailableGenerators.begin(),
this->AvailableGenerators.end(),
[&p](const cmake::GeneratorInfo& g) {
diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx
index dda3661..39cce98 100644
--- a/Source/cmCMakePresetsFile.cxx
+++ b/Source/cmCMakePresetsFile.cxx
@@ -9,28 +9,17 @@
#include <iterator>
#include <utility>
-#include <cmext/string_view>
+#include <cm/string_view>
-#include <cm3p/json/reader.h>
-#include <cm3p/json/value.h>
+#include "cmsys/RegularExpression.hxx"
-#include "cmsys/FStream.hxx"
-
-#include "cmJSONHelpers.h"
+#include "cmCMakePresetsFileInternal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmVersion.h"
-
-#define CHECK_OK(expr) \
- { \
- auto _result = expr; \
- if (_result != ReadFileResult::READ_OK) \
- return _result; \
- }
-#define CHECK_EXPAND(out, field, expanders) \
+#define CHECK_EXPAND(out, field, expanders, version) \
{ \
- switch (ExpandMacros(field, expanders)) { \
+ switch (ExpandMacros(field, expanders, version)) { \
case ExpandMacroResult::Error: \
return false; \
case ExpandMacroResult::Ignore: \
@@ -50,673 +39,11 @@ enum class CycleStatus
};
using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
-using CacheVariable = cmCMakePresetsFile::CacheVariable;
using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset;
using BuildPreset = cmCMakePresetsFile::BuildPreset;
using TestPreset = cmCMakePresetsFile::TestPreset;
-using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy;
-
-constexpr int MIN_VERSION = 1;
-constexpr int MAX_VERSION = 2;
-
-struct CMakeVersion
-{
- unsigned int Major = 0;
- unsigned int Minor = 0;
- unsigned int Patch = 0;
-};
-
-struct RootPresets
-{
- CMakeVersion CMakeMinimumRequired;
- std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets;
- std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets;
- std::vector<cmCMakePresetsFile::TestPreset> TestPresets;
-};
-
-cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
-{
- return [error](std::nullptr_t& /*out*/,
- const Json::Value* value) -> ReadFileResult {
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isObject()) {
- return error;
- }
-
- return ReadFileResult::READ_OK;
- };
-}
-
-auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
-
-auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
- ReadFileResult::NO_VERSION, VersionIntHelper);
-
-auto const RootVersionHelper =
- cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_ROOT)
- .Bind("version"_s, VersionHelper, false);
-
-auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
-
-ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
-{
- if (!value) {
- out.clear();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isBool()) {
- out = value->asBool() ? "TRUE" : "FALSE";
- return ReadFileResult::READ_OK;
- }
-
- return VariableStringHelper(out, value);
-}
-
-auto const VariableObjectHelper =
- cmJSONObjectHelper<CacheVariable, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
- .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
- .Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
-
-ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
- const Json::Value* value)
-{
- if (value->isBool()) {
- out = CacheVariable{
- /*Type=*/"BOOL",
- /*Value=*/value->asBool() ? "TRUE" : "FALSE",
- };
- return ReadFileResult::READ_OK;
- }
- if (value->isString()) {
- out = CacheVariable{
- /*Type=*/"",
- /*Value=*/value->asString(),
- };
- return ReadFileResult::READ_OK;
- }
- if (value->isObject()) {
- out.emplace();
- return VariableObjectHelper(*out, value);
- }
- if (value->isNull()) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
- return ReadFileResult::INVALID_VARIABLE;
-}
-
-auto const VariablesHelper =
- cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
-
-auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
- const Json::Value* value)
-{
- if (!value || value->isNull()) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
- if (value->isString()) {
- out = value->asString();
- return ReadFileResult::READ_OK;
- }
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const EnvironmentMapHelper =
- cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
- EnvironmentHelper);
-
-auto const PresetVectorStringHelper =
- cmJSONVectorHelper<std::string, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
- PresetStringHelper);
-
-ReadFileResult PresetInheritsHelper(std::vector<std::string>& out,
- const Json::Value* value)
-{
- out.clear();
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.push_back(value->asString());
- return ReadFileResult::READ_OK;
- }
-
- return PresetVectorStringHelper(out, value);
-}
-
-auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-auto const PresetOptionalBoolHelper =
- cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK,
- PresetBoolHelper);
-
-auto const PresetIntHelper = cmJSONIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-auto const PresetOptionalIntHelper = cmJSONOptionalHelper<int, ReadFileResult>(
- ReadFileResult::READ_OK, PresetIntHelper);
-
-auto const PresetVectorIntHelper = cmJSONVectorHelper<int, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
-
-auto const PresetWarningsHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
- PresetOptionalBoolHelper, false)
- .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
- PresetOptionalBoolHelper, false)
- .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
- PresetOptionalBoolHelper, false)
- .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
- PresetOptionalBoolHelper, false);
-
-auto const PresetErrorsHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
- PresetOptionalBoolHelper, false);
-
-auto const PresetDebugHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper,
- false)
- .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
- PresetOptionalBoolHelper, false)
- .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper,
- false);
-
-ReadFileResult ArchToolsetStrategyHelper(
- cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
-{
- if (!value) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "set") {
- out = ArchToolsetStrategy::Set;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "external") {
- out = ArchToolsetStrategy::External;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
-ArchToolsetHelper(
- std::string ConfigurePreset::*valueField,
- cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
-{
- auto const objectHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("value", valueField, PresetStringHelper, false)
- .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
- return [valueField, strategyField, objectHelper](
- ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
- if (!value) {
- (out.*valueField).clear();
- out.*strategyField = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.*valueField = value->asString();
- out.*strategyField = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isObject()) {
- return objectHelper(out, value);
- }
-
- return ReadFileResult::INVALID_PRESET;
- };
-}
-
-auto const ArchitectureHelper = ArchToolsetHelper(
- &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy);
-auto const ToolsetHelper = ArchToolsetHelper(
- &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
-
-auto const ConfigurePresetHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper,
- false)
- .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper,
- false)
- .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper,
- false)
- .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper,
- false)
- .Bind("architecture"_s, ArchitectureHelper, false)
- .Bind("toolset"_s, ToolsetHelper, false)
- .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper,
- false)
- .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
- .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables,
- VariablesHelper, false)
- .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("warnings"_s, PresetWarningsHelper, false)
- .Bind("errors"_s, PresetErrorsHelper, false)
- .Bind("debug"_s, PresetDebugHelper, false);
-
-auto const BuildPresetHelper =
- cmJSONObjectHelper<BuildPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &BuildPreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false)
- .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper,
- false)
- .Bind("description"_s, &BuildPreset::Description, PresetStringHelper,
- false)
- .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset,
- PresetStringHelper, false)
- .Bind("inheritConfigureEnvironment"_s,
- &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
- false)
- .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false)
- .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false)
- .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper,
- false)
- .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper,
- false)
- .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false)
- .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions,
- PresetVectorStringHelper, false);
-
-ReadFileResult TestPresetOutputVerbosityHelper(
- TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value)
-{
- if (!value) {
- out = TestPreset::OutputOptions::VerbosityEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "default") {
- out = TestPreset::OutputOptions::VerbosityEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "verbose") {
- out = TestPreset::OutputOptions::VerbosityEnum::Verbose;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "extra") {
- out = TestPreset::OutputOptions::VerbosityEnum::Extra;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalOutputVerbosityHelper =
- cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetOutputVerbosityHelper);
-
-auto const TestPresetOptionalOutputHelper =
- cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress,
- PresetOptionalBoolHelper, false)
- .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity,
- TestPresetOptionalOutputVerbosityHelper, false)
- .Bind("debug"_s, &TestPreset::OutputOptions::Debug,
- PresetOptionalBoolHelper, false)
- .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure,
- PresetOptionalBoolHelper, false)
- .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet,
- PresetOptionalBoolHelper, false)
- .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile,
- PresetStringHelper, false)
- .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary,
- PresetOptionalBoolHelper, false)
- .Bind("subprojectSummary"_s,
- &TestPreset::OutputOptions::SubprojectSummary,
- PresetOptionalBoolHelper, false)
- .Bind("maxPassedTestOutputSize"_s,
- &TestPreset::OutputOptions::MaxPassedTestOutputSize,
- PresetOptionalIntHelper, false)
- .Bind("maxFailedTestOutputSize"_s,
- &TestPreset::OutputOptions::MaxFailedTestOutputSize,
- PresetOptionalIntHelper, false)
- .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth,
- PresetOptionalIntHelper, false));
-
-auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
- cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start,
- PresetOptionalIntHelper, false)
- .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End,
- PresetOptionalIntHelper, false)
- .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride,
- PresetOptionalIntHelper, false)
- .Bind("specificTests"_s,
- &TestPreset::IncludeOptions::IndexOptions::SpecificTests,
- PresetVectorIntHelper, false));
-
-ReadFileResult TestPresetOptionalFilterIncludeIndexHelper(
- cm::optional<TestPreset::IncludeOptions::IndexOptions>& out,
- const Json::Value* value)
-{
- if (!value) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.emplace();
- out->IndexFile = value->asString();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isObject()) {
- return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value);
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalFilterIncludeHelper =
- cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper,
- false)
- .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper,
- false)
- .Bind("index"_s, &TestPreset::IncludeOptions::Index,
- TestPresetOptionalFilterIncludeIndexHelper, false)
- .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion,
- PresetOptionalBoolHelper, false));
-
-auto const TestPresetOptionalFilterExcludeFixturesHelper =
- cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any,
- PresetStringHelper, false)
- .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup,
- PresetStringHelper, false)
- .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup,
- PresetStringHelper, false));
-
-auto const TestPresetOptionalFilterExcludeHelper =
- cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper,
- false)
- .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper,
- false)
- .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures,
- TestPresetOptionalFilterExcludeFixturesHelper, false));
-
-ReadFileResult TestPresetExecutionShowOnlyHelper(
- TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value)
-{
- if (!value || !value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "human") {
- out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "json-v1") {
- out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionShowOnlyHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetExecutionShowOnlyHelper);
-
-ReadFileResult TestPresetExecutionModeHelper(
- TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out,
- const Json::Value* value)
-{
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "until-fail") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "until-pass") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "after-timeout") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionRepeatHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode,
- TestPresetExecutionModeHelper, true)
- .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count,
- PresetIntHelper, true));
-
-ReadFileResult TestPresetExecutionNoTestsActionHelper(
- TestPreset::ExecutionOptions::NoTestsActionEnum& out,
- const Json::Value* value)
-{
- if (!value) {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "default") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "error") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "ignore") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionNoTestsActionHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetExecutionNoTestsActionHelper);
-
-auto const TestPresetExecutionHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure,
- PresetOptionalBoolHelper, false)
- .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover,
- PresetOptionalBoolHelper, false)
- .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs,
- PresetOptionalIntHelper, false)
- .Bind("resourceSpecFile"_s,
- &TestPreset::ExecutionOptions::ResourceSpecFile,
- PresetStringHelper, false)
- .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad,
- PresetOptionalIntHelper, false)
- .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly,
- TestPresetOptionalExecutionShowOnlyHelper, false)
- .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat,
- TestPresetOptionalExecutionRepeatHelper, false)
- .Bind("interactiveDebugging"_s,
- &TestPreset::ExecutionOptions::InteractiveDebugging,
- PresetOptionalBoolHelper, false)
- .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom,
- PresetOptionalBoolHelper, false)
- .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout,
- PresetOptionalIntHelper, false)
- .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction,
- TestPresetOptionalExecutionNoTestsActionHelper, false));
-
-auto const TestPresetFilterHelper =
- cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("include"_s, &TestPreset::FilterOptions::Include,
- TestPresetOptionalFilterIncludeHelper, false)
- .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude,
- TestPresetOptionalFilterExcludeHelper, false));
-
-auto const TestPresetHelper =
- cmJSONObjectHelper<TestPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &TestPreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false)
- .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false)
- .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false)
- .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("configurePreset"_s, &TestPreset::ConfigurePreset,
- PresetStringHelper, false)
- .Bind("inheritConfigureEnvironment"_s,
- &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
- false)
- .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper,
- false)
- .Bind("overwriteConfigurationFile"_s,
- &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper,
- false)
- .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper,
- false)
- .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false)
- .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper,
- false);
-
-auto const ConfigurePresetsHelper =
- cmJSONVectorHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
- ConfigurePresetHelper);
-
-auto const BuildPresetsHelper =
- cmJSONVectorHelper<BuildPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
- BuildPresetHelper);
-
-auto const TestPresetsHelper = cmJSONVectorHelper<TestPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper);
-
-auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
-
-auto const CMakeVersionHelper =
- cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
- .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
- .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
- .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
-
-auto const RootPresetsHelper =
- cmJSONObjectHelper<RootPresets, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
- .Bind<int>("version"_s, nullptr, VersionHelper)
- .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
- ConfigurePresetsHelper, false)
- .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper,
- false)
- .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false)
- .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
- CMakeVersionHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_ROOT), false);
+using ExpandMacroResult = cmCMakePresetsFileInternal::ExpandMacroResult;
+using MacroExpander = cmCMakePresetsFileInternal::MacroExpander;
void InheritString(std::string& child, const std::string& parent)
{
@@ -751,7 +78,7 @@ void InheritVector(std::vector<T>& child, const std::vector<T>& parent)
template <class T>
ReadFileResult VisitPreset(
T& preset, std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets,
- std::map<std::string, CycleStatus> cycleStatus)
+ std::map<std::string, CycleStatus> cycleStatus, int version)
{
switch (cycleStatus[preset.Name]) {
case CycleStatus::InProgress:
@@ -781,7 +108,7 @@ ReadFileResult VisitPreset(
return ReadFileResult::USER_PRESET_INHERITANCE;
}
- auto result = VisitPreset(parentPreset, presets, cycleStatus);
+ auto result = VisitPreset(parentPreset, presets, cycleStatus, version);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -791,9 +118,17 @@ ReadFileResult VisitPreset(
for (auto const& v : parentPreset.Environment) {
preset.Environment.insert(v);
}
+
+ if (!preset.ConditionEvaluator) {
+ preset.ConditionEvaluator = parentPreset.ConditionEvaluator;
+ }
+ }
+
+ if (preset.ConditionEvaluator && preset.ConditionEvaluator->IsNull()) {
+ preset.ConditionEvaluator.reset();
}
- CHECK_OK(preset.VisitPresetAfterInherit())
+ CHECK_OK(preset.VisitPresetAfterInherit(version))
cycleStatus[preset.Name] = CycleStatus::Verified;
return ReadFileResult::READ_OK;
@@ -801,7 +136,8 @@ ReadFileResult VisitPreset(
template <class T>
ReadFileResult ComputePresetInheritance(
- std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets)
+ std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets,
+ const cmCMakePresetsFile& file)
{
std::map<std::string, CycleStatus> cycleStatus;
for (auto const& it : presets) {
@@ -809,7 +145,9 @@ ReadFileResult ComputePresetInheritance(
}
for (auto& it : presets) {
- auto result = VisitPreset<T>(it.second.Unexpanded, presets, cycleStatus);
+ auto& preset = it.second.Unexpanded;
+ auto result =
+ VisitPreset<T>(preset, presets, cycleStatus, file.GetVersion(preset));
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -839,24 +177,17 @@ bool IsValidMacroNamespace(const std::string& str)
[&str](const char* prefix) -> bool { return str == prefix; });
}
-enum class ExpandMacroResult
-{
- Ok,
- Ignore,
- Error,
-};
-
-using MacroExpander = std::function<ExpandMacroResult(
- const std::string&, const std::string&, std::string&)>;
-
ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
- const std::vector<MacroExpander>& macroExpanders);
+ const std::vector<MacroExpander>& macroExpanders,
+ int version);
ExpandMacroResult ExpandMacros(
- std::string& out, const std::vector<MacroExpander>& macroExpanders);
-ExpandMacroResult ExpandMacro(
- std::string& out, const std::string& macroNamespace,
- const std::string& macroName,
- const std::vector<MacroExpander>& macroExpanders);
+ std::string& out, const std::vector<MacroExpander>& macroExpanders,
+ int version);
+ExpandMacroResult ExpandMacro(std::string& out,
+ const std::string& macroNamespace,
+ const std::string& macroName,
+ const std::vector<MacroExpander>& macroExpanders,
+ int version);
bool ExpandMacros(const cmCMakePresetsFile& file,
const ConfigurePreset& preset,
@@ -864,7 +195,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
const std::vector<MacroExpander>& macroExpanders)
{
std::string binaryDir = preset.BinaryDir;
- CHECK_EXPAND(out, binaryDir, macroExpanders)
+ CHECK_EXPAND(out, binaryDir, macroExpanders, file.GetVersion(preset))
if (!cmSystemTools::FileIsFullPath(binaryDir)) {
binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
@@ -872,69 +203,89 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
+ if (!preset.InstallDir.empty()) {
+ std::string installDir = preset.InstallDir;
+ CHECK_EXPAND(out, installDir, macroExpanders, file.GetVersion(preset))
+
+ if (!cmSystemTools::FileIsFullPath(installDir)) {
+ installDir = cmStrCat(file.SourceDir, '/', installDir);
+ }
+ out->InstallDir = cmSystemTools::CollapseFullPath(installDir);
+ cmSystemTools::ConvertToUnixSlashes(out->InstallDir);
+ }
+
for (auto& variable : out->CacheVariables) {
if (variable.second) {
- CHECK_EXPAND(out, variable.second->Value, macroExpanders)
+ CHECK_EXPAND(out, variable.second->Value, macroExpanders,
+ file.GetVersion(preset))
}
}
return true;
}
-bool ExpandMacros(const cmCMakePresetsFile&, const BuildPreset&,
+bool ExpandMacros(const cmCMakePresetsFile& file, const BuildPreset& preset,
cm::optional<BuildPreset>& out,
const std::vector<MacroExpander>& macroExpanders)
{
for (auto& target : out->Targets) {
- CHECK_EXPAND(out, target, macroExpanders)
+ CHECK_EXPAND(out, target, macroExpanders, file.GetVersion(preset))
}
for (auto& nativeToolOption : out->NativeToolOptions) {
- CHECK_EXPAND(out, nativeToolOption, macroExpanders)
+ CHECK_EXPAND(out, nativeToolOption, macroExpanders,
+ file.GetVersion(preset))
}
return true;
}
-bool ExpandMacros(const cmCMakePresetsFile&, const TestPreset&,
+bool ExpandMacros(const cmCMakePresetsFile& file, const TestPreset& preset,
cm::optional<TestPreset>& out,
const std::vector<MacroExpander>& macroExpanders)
{
for (auto& overwrite : out->OverwriteConfigurationFile) {
- CHECK_EXPAND(out, overwrite, macroExpanders);
+ CHECK_EXPAND(out, overwrite, macroExpanders, file.GetVersion(preset));
}
if (out->Output) {
- CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders)
+ CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders,
+ file.GetVersion(preset))
}
if (out->Filter) {
if (out->Filter->Include) {
- CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders)
- CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders,
+ file.GetVersion(preset))
+ CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders,
+ file.GetVersion(preset))
if (out->Filter->Include->Index) {
CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile,
- macroExpanders);
+ macroExpanders, file.GetVersion(preset));
}
}
if (out->Filter->Exclude) {
- CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders)
- CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders,
+ file.GetVersion(preset))
+ CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders,
+ file.GetVersion(preset))
if (out->Filter->Exclude->Fixtures) {
- CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders,
+ file.GetVersion(preset))
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup,
- macroExpanders)
+ macroExpanders, file.GetVersion(preset))
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup,
- macroExpanders)
+ macroExpanders, file.GetVersion(preset))
}
}
}
if (out->Execution) {
- CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders)
+ CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders,
+ file.GetVersion(preset))
}
return true;
@@ -955,8 +306,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
MacroExpander defaultMacroExpander =
[&file, &preset](const std::string& macroNamespace,
- const std::string& macroName,
- std::string& macroOut) -> ExpandMacroResult {
+ const std::string& macroName, std::string& macroOut,
+ int version) -> ExpandMacroResult {
if (macroNamespace.empty()) {
if (macroName == "sourceDir") {
macroOut += file.SourceDir;
@@ -985,6 +336,13 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
macroOut += '$';
return ExpandMacroResult::Ok;
}
+ if (macroName == "hostSystemName") {
+ if (version < 3) {
+ return ExpandMacroResult::Error;
+ }
+ macroOut += cmSystemTools::GetSystemName();
+ return ExpandMacroResult::Ok;
+ }
}
return ExpandMacroResult::Ignore;
@@ -993,11 +351,12 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
MacroExpander environmentMacroExpander =
[&macroExpanders, &out, &envCycles](
const std::string& macroNamespace, const std::string& macroName,
- std::string& result) -> ExpandMacroResult {
+ std::string& result, int version) -> ExpandMacroResult {
if (macroNamespace == "env" && !macroName.empty() && out) {
auto v = out->Environment.find(macroName);
if (v != out->Environment.end() && v->second) {
- auto e = VisitEnv(*v->second, envCycles[macroName], macroExpanders);
+ auto e =
+ VisitEnv(*v->second, envCycles[macroName], macroExpanders, version);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -1025,7 +384,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
for (auto& v : out->Environment) {
if (v.second) {
- switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders)) {
+ switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders,
+ file.GetVersion(preset))) {
case ExpandMacroResult::Error:
return false;
case ExpandMacroResult::Ignore:
@@ -1037,11 +397,25 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
}
}
+ if (preset.ConditionEvaluator) {
+ cm::optional<bool> result;
+ if (!preset.ConditionEvaluator->Evaluate(
+ macroExpanders, file.GetVersion(preset), result)) {
+ return false;
+ }
+ if (!result) {
+ out.reset();
+ return true;
+ }
+ out->ConditionResult = *result;
+ }
+
return ExpandMacros(file, preset, out, macroExpanders);
}
ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
- const std::vector<MacroExpander>& macroExpanders)
+ const std::vector<MacroExpander>& macroExpanders,
+ int version)
{
if (status == CycleStatus::Verified) {
return ExpandMacroResult::Ok;
@@ -1051,7 +425,7 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
}
status = CycleStatus::InProgress;
- auto e = ExpandMacros(value, macroExpanders);
+ auto e = ExpandMacros(value, macroExpanders, version);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -1060,7 +434,8 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
}
ExpandMacroResult ExpandMacros(
- std::string& out, const std::vector<MacroExpander>& macroExpanders)
+ std::string& out, const std::vector<MacroExpander>& macroExpanders,
+ int version)
{
std::string result;
std::string macroNamespace;
@@ -1107,8 +482,8 @@ ExpandMacroResult ExpandMacros(
case State::MacroName:
if (c == '}') {
- auto e =
- ExpandMacro(result, macroNamespace, macroName, macroExpanders);
+ auto e = ExpandMacro(result, macroNamespace, macroName,
+ macroExpanders, version);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -1140,10 +515,11 @@ ExpandMacroResult ExpandMacros(
ExpandMacroResult ExpandMacro(std::string& out,
const std::string& macroNamespace,
const std::string& macroName,
- const std::vector<MacroExpander>& macroExpanders)
+ const std::vector<MacroExpander>& macroExpanders,
+ int version)
{
for (auto const& macroExpander : macroExpanders) {
- auto result = macroExpander(macroNamespace, macroName, out);
+ auto result = macroExpander(macroNamespace, macroName, out, version);
if (result != ExpandMacroResult::Ignore) {
return result;
}
@@ -1157,6 +533,98 @@ ExpandMacroResult ExpandMacro(std::string& out,
}
}
+bool cmCMakePresetsFileInternal::EqualsCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ std::string lhs = this->Lhs;
+ CHECK_EXPAND(out, lhs, expanders, version);
+
+ std::string rhs = this->Rhs;
+ CHECK_EXPAND(out, rhs, expanders, version);
+
+ out = (lhs == rhs);
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::InListCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ std::string str = this->String;
+ CHECK_EXPAND(out, str, expanders, version);
+
+ for (auto item : this->List) {
+ CHECK_EXPAND(out, item, expanders, version);
+ if (str == item) {
+ out = true;
+ return true;
+ }
+ }
+
+ out = false;
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::MatchesCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ std::string str = this->String;
+ CHECK_EXPAND(out, str, expanders, version);
+ std::string regexStr = this->Regex;
+ CHECK_EXPAND(out, regexStr, expanders, version);
+
+ cmsys::RegularExpression regex;
+ if (!regex.compile(regexStr)) {
+ return false;
+ }
+
+ out = regex.find(str);
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ for (auto const& condition : this->Conditions) {
+ cm::optional<bool> result;
+ if (!condition->Evaluate(expanders, version, result)) {
+ out.reset();
+ return false;
+ }
+
+ if (!result) {
+ out.reset();
+ return true;
+ }
+
+ if (result == this->StopValue) {
+ out = result;
+ return true;
+ }
+ }
+
+ out = !this->StopValue;
+ return true;
+}
+
+bool cmCMakePresetsFileInternal::NotCondition::Evaluate(
+ const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const
+{
+ out.reset();
+ if (!this->SubCondition->Evaluate(expanders, version, out)) {
+ out.reset();
+ return false;
+ }
+ if (out) {
+ *out = !*out;
+ }
+ return true;
+}
+
cmCMakePresetsFile::ReadFileResult
cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit(
const cmCMakePresetsFile::Preset& parentPreset)
@@ -1174,6 +642,7 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit(
preset.ToolsetStrategy = parent.ToolsetStrategy;
}
InheritString(preset.BinaryDir, parent.BinaryDir);
+ InheritString(preset.InstallDir, parent.InstallDir);
InheritOptionalValue(preset.WarnDev, parent.WarnDev);
InheritOptionalValue(preset.ErrorDev, parent.ErrorDev);
InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated);
@@ -1201,16 +670,19 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetBeforeInherit()
}
cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit()
+cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit(int version)
{
auto& preset = *this;
if (!preset.Hidden) {
- if (preset.Generator.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
- if (preset.BinaryDir.empty()) {
- return ReadFileResult::INVALID_PRESET;
+ if (version < 3) {
+ if (preset.Generator.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ if (preset.BinaryDir.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
}
+
if (preset.WarnDev == false && preset.ErrorDev == true) {
return ReadFileResult::INVALID_PRESET;
}
@@ -1246,7 +718,7 @@ cmCMakePresetsFile::BuildPreset::VisitPresetInherit(
}
cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit()
+cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit(int /* version */)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
@@ -1356,7 +828,7 @@ cmCMakePresetsFile::TestPreset::VisitPresetInherit(
}
cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit()
+cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit(int /* version */)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
@@ -1417,9 +889,9 @@ cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles)
: ReadFileResult::FILE_NOT_FOUND;
}
- CHECK_OK(ComputePresetInheritance(this->ConfigurePresets))
- CHECK_OK(ComputePresetInheritance(this->BuildPresets))
- CHECK_OK(ComputePresetInheritance(this->TestPresets))
+ CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this))
+ CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this))
+ CHECK_OK(ComputePresetInheritance(this->TestPresets, *this))
for (auto& it : this->ConfigurePresets) {
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
@@ -1510,111 +982,18 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result)
"support.";
case ReadFileResult::INVALID_CONFIGURE_PRESET:
return "Invalid \"configurePreset\" field";
+ case ReadFileResult::INSTALL_PREFIX_UNSUPPORTED:
+ return "File version must be 3 or higher for installDir preset "
+ "support.";
+ case ReadFileResult::INVALID_CONDITION:
+ return "Invalid preset condition";
+ case ReadFileResult::CONDITION_UNSUPPORTED:
+ return "File version must be 3 or higher for condition support";
}
return "Unknown error";
}
-cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
- const std::string& filename, bool user)
-{
- cmsys::ifstream fin(filename.c_str());
- if (!fin) {
- return ReadFileResult::FILE_NOT_FOUND;
- }
- // If there's a BOM, toss it.
- cmsys::FStream::ReadBOM(fin);
-
- Json::Value root;
- Json::CharReaderBuilder builder;
- Json::CharReaderBuilder::strictMode(&builder.settings_);
- if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
- return ReadFileResult::JSON_PARSE_ERROR;
- }
-
- int v = 0;
- auto result = RootVersionHelper(v, &root);
- if (result != ReadFileResult::READ_OK) {
- return result;
- }
- if (v < MIN_VERSION || v > MAX_VERSION) {
- return ReadFileResult::UNRECOGNIZED_VERSION;
- }
-
- // Support for build and test presets added in version 2.
- if (v < 2 &&
- (root.isMember("buildPresets") || root.isMember("testPresets"))) {
- return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
- }
-
- RootPresets presets;
- if ((result = RootPresetsHelper(presets, &root)) !=
- ReadFileResult::READ_OK) {
- return result;
- }
-
- unsigned int currentMajor = cmVersion::GetMajorVersion();
- unsigned int currentMinor = cmVersion::GetMinorVersion();
- unsigned int currentPatch = cmVersion::GetPatchVersion();
- auto const& required = presets.CMakeMinimumRequired;
- if (required.Major > currentMajor ||
- (required.Major == currentMajor &&
- (required.Minor > currentMinor ||
- (required.Minor == currentMinor &&
- (required.Patch > currentPatch))))) {
- return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
- }
-
- for (auto& preset : presets.ConfigurePresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<ConfigurePreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->ConfigurePresets
- .emplace(std::make_pair(preset.Name, presetPair))
- .second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
- this->ConfigurePresetOrder.push_back(preset.Name);
- }
-
- for (auto& preset : presets.BuildPresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<BuildPreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
- this->BuildPresetOrder.push_back(preset.Name);
- }
-
- for (auto& preset : presets.TestPresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<TestPreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
- this->TestPresetOrder.push_back(preset.Name);
- }
-
- return ReadFileResult::READ_OK;
-}
-
void cmCMakePresetsFile::ClearPresets()
{
this->ConfigurePresets.clear();
@@ -1666,7 +1045,7 @@ void cmCMakePresetsFile::PrintConfigurePresetList(
for (auto const& p : this->ConfigurePresetOrder) {
auto const& preset = this->ConfigurePresets.at(p);
if (!preset.Unexpanded.Hidden && preset.Expanded &&
- filter(preset.Unexpanded)) {
+ preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
presets.push_back(
static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
}
@@ -1683,7 +1062,8 @@ void cmCMakePresetsFile::PrintBuildPresetList() const
std::vector<const cmCMakePresetsFile::Preset*> presets;
for (auto const& p : this->BuildPresetOrder) {
auto const& preset = this->BuildPresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded) {
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult) {
presets.push_back(
static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
}
@@ -1700,7 +1080,8 @@ void cmCMakePresetsFile::PrintTestPresetList() const
std::vector<const cmCMakePresetsFile::Preset*> presets;
for (auto const& p : this->TestPresetOrder) {
auto const& preset = this->TestPresets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded) {
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult) {
presets.push_back(
static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
}
diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h
index 3067d5e..fc14830 100644
--- a/Source/cmCMakePresetsFile.h
+++ b/Source/cmCMakePresetsFile.h
@@ -2,8 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include <functional>
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -33,6 +36,9 @@ public:
INVALID_MACRO_EXPANSION,
BUILD_TEST_PRESETS_UNSUPPORTED,
INVALID_CONFIGURE_PRESET,
+ INSTALL_PREFIX_UNSUPPORTED,
+ INVALID_CONDITION,
+ CONDITION_UNSUPPORTED,
};
enum class ArchToolsetStrategy
@@ -48,6 +54,8 @@ public:
std::string Value;
};
+ class Condition;
+
class Preset
{
public:
@@ -70,6 +78,9 @@ public:
std::string DisplayName;
std::string Description;
+ std::shared_ptr<Condition> ConditionEvaluator;
+ bool ConditionResult = true;
+
std::map<std::string, cm::optional<std::string>> Environment;
virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0;
@@ -78,7 +89,7 @@ public:
return ReadFileResult::READ_OK;
}
- virtual ReadFileResult VisitPresetAfterInherit()
+ virtual ReadFileResult VisitPresetAfterInherit(int /* version */)
{
return ReadFileResult::READ_OK;
}
@@ -103,6 +114,7 @@ public:
std::string Toolset;
cm::optional<ArchToolsetStrategy> ToolsetStrategy;
std::string BinaryDir;
+ std::string InstallDir;
std::map<std::string, cm::optional<CacheVariable>> CacheVariables;
@@ -120,7 +132,7 @@ public:
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetBeforeInherit() override;
- ReadFileResult VisitPresetAfterInherit() override;
+ ReadFileResult VisitPresetAfterInherit(int version) override;
};
class BuildPreset : public Preset
@@ -146,7 +158,7 @@ public:
std::vector<std::string> NativeToolOptions;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
- ReadFileResult VisitPresetAfterInherit() override;
+ ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
class TestPreset : public Preset
@@ -273,7 +285,7 @@ public:
cm::optional<ExecutionOptions> Execution;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
- ReadFileResult VisitPresetAfterInherit() override;
+ ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
template <class T>
@@ -293,6 +305,13 @@ public:
std::vector<std::string> TestPresetOrder;
std::string SourceDir;
+ int Version;
+ int UserVersion;
+
+ int GetVersion(const Preset& preset) const
+ {
+ return preset.User ? this->UserVersion : this->Version;
+ }
static std::string GetFilename(const std::string& sourceDir);
static std::string GetUserFilename(const std::string& sourceDir);
diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h
new file mode 100644
index 0000000..3269276
--- /dev/null
+++ b/Source/cmCMakePresetsFileInternal.h
@@ -0,0 +1,112 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <memory>
+
+#include "cmCMakePresetsFile.h"
+
+#define CHECK_OK(expr) \
+ { \
+ auto _result = expr; \
+ if (_result != ReadFileResult::READ_OK) \
+ return _result; \
+ }
+
+namespace cmCMakePresetsFileInternal {
+enum class ExpandMacroResult
+{
+ Ok,
+ Ignore,
+ Error,
+};
+
+using MacroExpander = std::function<ExpandMacroResult(
+ const std::string&, const std::string&, std::string&, int version)>;
+}
+
+class cmCMakePresetsFile::Condition
+{
+public:
+ virtual ~Condition() = default;
+
+ virtual bool Evaluate(
+ const std::vector<cmCMakePresetsFileInternal::MacroExpander>& expanders,
+ int version, cm::optional<bool>& out) const = 0;
+ virtual bool IsNull() const { return false; }
+};
+
+namespace cmCMakePresetsFileInternal {
+
+class NullCondition : public cmCMakePresetsFile::Condition
+{
+ bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
+ int /*version*/, cm::optional<bool>& out) const override
+ {
+ out = true;
+ return true;
+ }
+
+ bool IsNull() const override { return true; }
+};
+
+class ConstCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
+ int /*version*/, cm::optional<bool>& out) const override
+ {
+ out = this->Value;
+ return true;
+ }
+
+ bool Value;
+};
+
+class EqualsCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string Lhs;
+ std::string Rhs;
+};
+
+class InListCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string String;
+ std::vector<std::string> List;
+};
+
+class MatchesCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string String;
+ std::string Regex;
+};
+
+class AnyAllOfCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::vector<std::unique_ptr<Condition>> Conditions;
+ bool StopValue;
+};
+
+class NotCondition : public cmCMakePresetsFile::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::unique_ptr<Condition> SubCondition;
+};
+}
diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx
new file mode 100644
index 0000000..403fac6
--- /dev/null
+++ b/Source/cmCMakePresetsFileReadJSON.cxx
@@ -0,0 +1,1022 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <functional>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/reader.h>
+#include <cm3p/json/value.h>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmCMakePresetsFile.h"
+#include "cmCMakePresetsFileInternal.h"
+#include "cmJSONHelpers.h"
+#include "cmVersion.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
+using CacheVariable = cmCMakePresetsFile::CacheVariable;
+using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset;
+using BuildPreset = cmCMakePresetsFile::BuildPreset;
+using TestPreset = cmCMakePresetsFile::TestPreset;
+using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy;
+
+constexpr int MIN_VERSION = 1;
+constexpr int MAX_VERSION = 3;
+
+struct CMakeVersion
+{
+ unsigned int Major = 0;
+ unsigned int Minor = 0;
+ unsigned int Patch = 0;
+};
+
+struct RootPresets
+{
+ CMakeVersion CMakeMinimumRequired;
+ std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets;
+ std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets;
+ std::vector<cmCMakePresetsFile::TestPreset> TestPresets;
+};
+
+std::unique_ptr<cmCMakePresetsFileInternal::NotCondition> InvertCondition(
+ std::unique_ptr<cmCMakePresetsFile::Condition> condition)
+{
+ auto retval = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>();
+ retval->SubCondition = std::move(condition);
+ return retval;
+}
+
+auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
+
+auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
+
+auto const ConditionStringListHelper =
+ cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
+ ConditionStringHelper);
+
+auto const ConstConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::ConstCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("value"_s, &cmCMakePresetsFileInternal::ConstCondition::Value,
+ ConditionBoolHelper, true);
+
+auto const EqualsConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::EqualsCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("lhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Lhs,
+ ConditionStringHelper, true)
+ .Bind("rhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Rhs,
+ ConditionStringHelper, true);
+
+auto const InListConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::InListCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("string"_s, &cmCMakePresetsFileInternal::InListCondition::String,
+ ConditionStringHelper, true)
+ .Bind("list"_s, &cmCMakePresetsFileInternal::InListCondition::List,
+ ConditionStringListHelper, true);
+
+auto const MatchesConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::MatchesCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("string"_s, &cmCMakePresetsFileInternal::MatchesCondition::String,
+ ConditionStringHelper, true)
+ .Bind("regex"_s, &cmCMakePresetsFileInternal::MatchesCondition::Regex,
+ ConditionStringHelper, true);
+
+ReadFileResult SubConditionHelper(
+ std::unique_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value);
+
+auto const ListConditionVectorHelper =
+ cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsFile::Condition>,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION,
+ SubConditionHelper);
+auto const AnyAllOfConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::AnyAllOfCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("conditions"_s,
+ &cmCMakePresetsFileInternal::AnyAllOfCondition::Conditions,
+ ListConditionVectorHelper);
+
+auto const NotConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsFileInternal::NotCondition, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("condition"_s,
+ &cmCMakePresetsFileInternal::NotCondition::SubCondition,
+ SubConditionHelper);
+
+ReadFileResult ConditionHelper(
+ std::unique_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out.reset();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isBool()) {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>();
+ c->Value = value->asBool();
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isNull()) {
+ out = cm::make_unique<cmCMakePresetsFileInternal::NullCondition>();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ if (!value->isMember("type")) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+
+ if (!(*value)["type"].isString()) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+ auto type = (*value)["type"].asString();
+
+ if (type == "const") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>();
+ CHECK_OK(ConstConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "equals" || type == "notEquals") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::EqualsCondition>();
+ CHECK_OK(EqualsConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notEquals") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "inList" || type == "notInList") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::InListCondition>();
+ CHECK_OK(InListConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notInList") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "matches" || type == "notMatches") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::MatchesCondition>();
+ CHECK_OK(MatchesConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notMatches") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "anyOf" || type == "allOf") {
+ auto c =
+ cm::make_unique<cmCMakePresetsFileInternal::AnyAllOfCondition>();
+ c->StopValue = (type == "anyOf");
+ CHECK_OK(AnyAllOfConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "not") {
+ auto c = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>();
+ CHECK_OK(NotConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+ }
+
+ return ReadFileResult::INVALID_CONDITION;
+}
+
+ReadFileResult PresetConditionHelper(
+ std::shared_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value)
+{
+ std::unique_ptr<cmCMakePresetsFile::Condition> ptr;
+ auto result = ConditionHelper(ptr, value);
+ out = std::move(ptr);
+ return result;
+}
+
+ReadFileResult SubConditionHelper(
+ std::unique_ptr<cmCMakePresetsFile::Condition>& out,
+ const Json::Value* value)
+{
+ std::unique_ptr<cmCMakePresetsFile::Condition> ptr;
+ auto result = ConditionHelper(ptr, value);
+ if (ptr && ptr->IsNull()) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+ out = std::move(ptr);
+ return result;
+}
+
+cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
+{
+ return [error](std::nullptr_t& /*out*/,
+ const Json::Value* value) -> ReadFileResult {
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isObject()) {
+ return error;
+ }
+
+ return ReadFileResult::READ_OK;
+ };
+}
+
+auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
+ ReadFileResult::NO_VERSION, VersionIntHelper);
+
+auto const RootVersionHelper =
+ cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_ROOT)
+ .Bind("version"_s, VersionHelper, false);
+
+auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
+
+ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
+{
+ if (!value) {
+ out.clear();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isBool()) {
+ out = value->asBool() ? "TRUE" : "FALSE";
+ return ReadFileResult::READ_OK;
+ }
+
+ return VariableStringHelper(out, value);
+}
+
+auto const VariableObjectHelper =
+ cmJSONObjectHelper<CacheVariable, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
+ .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
+ .Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
+
+ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
+ const Json::Value* value)
+{
+ if (value->isBool()) {
+ out = CacheVariable{
+ /*Type=*/"BOOL",
+ /*Value=*/value->asBool() ? "TRUE" : "FALSE",
+ };
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isString()) {
+ out = CacheVariable{
+ /*Type=*/"",
+ /*Value=*/value->asString(),
+ };
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isObject()) {
+ out.emplace();
+ return VariableObjectHelper(*out, value);
+ }
+ if (value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_VARIABLE;
+}
+
+auto const VariablesHelper =
+ cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
+
+auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
+ const Json::Value* value)
+{
+ if (!value || value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isString()) {
+ out = value->asString();
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const EnvironmentMapHelper =
+ cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ EnvironmentHelper);
+
+auto const PresetVectorStringHelper =
+ cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ PresetStringHelper);
+
+ReadFileResult PresetInheritsHelper(std::vector<std::string>& out,
+ const Json::Value* value)
+{
+ out.clear();
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.push_back(value->asString());
+ return ReadFileResult::READ_OK;
+ }
+
+ return PresetVectorStringHelper(out, value);
+}
+
+auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+auto const PresetOptionalBoolHelper =
+ cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK,
+ PresetBoolHelper);
+
+auto const PresetIntHelper = cmJSONIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+auto const PresetOptionalIntHelper = cmJSONOptionalHelper<int, ReadFileResult>(
+ ReadFileResult::READ_OK, PresetIntHelper);
+
+auto const PresetVectorIntHelper = cmJSONVectorHelper<int, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
+
+auto const PresetWarningsHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
+ PresetOptionalBoolHelper, false)
+ .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
+ PresetOptionalBoolHelper, false)
+ .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
+ PresetOptionalBoolHelper, false)
+ .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
+ PresetOptionalBoolHelper, false);
+
+auto const PresetErrorsHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
+ PresetOptionalBoolHelper, false);
+
+auto const PresetDebugHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper,
+ false)
+ .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
+ PresetOptionalBoolHelper, false)
+ .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper,
+ false);
+
+ReadFileResult ArchToolsetStrategyHelper(
+ cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "set") {
+ out = ArchToolsetStrategy::Set;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "external") {
+ out = ArchToolsetStrategy::External;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
+ArchToolsetHelper(
+ std::string ConfigurePreset::*valueField,
+ cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
+{
+ auto const objectHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("value", valueField, PresetStringHelper, false)
+ .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
+ return [valueField, strategyField, objectHelper](
+ ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
+ if (!value) {
+ (out.*valueField).clear();
+ out.*strategyField = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.*valueField = value->asString();
+ out.*strategyField = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ return objectHelper(out, value);
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+ };
+}
+
+auto const ArchitectureHelper = ArchToolsetHelper(
+ &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy);
+auto const ToolsetHelper = ArchToolsetHelper(
+ &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
+
+auto const ConfigurePresetHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper,
+ false)
+ .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_PRESET), false)
+ .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper,
+ false)
+ .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper,
+ false)
+ .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper,
+ false)
+ .Bind("architecture"_s, ArchitectureHelper, false)
+ .Bind("toolset"_s, ToolsetHelper, false)
+ .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper,
+ false)
+ .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper,
+ false)
+ .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
+ .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables,
+ VariablesHelper, false)
+ .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper,
+ false)
+ .Bind("warnings"_s, PresetWarningsHelper, false)
+ .Bind("errors"_s, PresetErrorsHelper, false)
+ .Bind("debug"_s, PresetDebugHelper, false)
+ .Bind("condition"_s, &ConfigurePreset::ConditionEvaluator,
+ PresetConditionHelper, false);
+
+auto const BuildPresetHelper =
+ cmJSONObjectHelper<BuildPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &BuildPreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false)
+ .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_PRESET), false)
+ .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper,
+ false)
+ .Bind("description"_s, &BuildPreset::Description, PresetStringHelper,
+ false)
+ .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper,
+ false)
+ .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset,
+ PresetStringHelper, false)
+ .Bind("inheritConfigureEnvironment"_s,
+ &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
+ false)
+ .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false)
+ .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false)
+ .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper,
+ false)
+ .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper,
+ false)
+ .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false)
+ .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions,
+ PresetVectorStringHelper, false)
+ .Bind("condition"_s, &BuildPreset::ConditionEvaluator,
+ PresetConditionHelper, false);
+
+ReadFileResult TestPresetOutputVerbosityHelper(
+ TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value)
+{
+ if (!value) {
+ out = TestPreset::OutputOptions::VerbosityEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "default") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "verbose") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Verbose;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "extra") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Extra;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalOutputVerbosityHelper =
+ cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetOutputVerbosityHelper);
+
+auto const TestPresetOptionalOutputHelper =
+ cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress,
+ PresetOptionalBoolHelper, false)
+ .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity,
+ TestPresetOptionalOutputVerbosityHelper, false)
+ .Bind("debug"_s, &TestPreset::OutputOptions::Debug,
+ PresetOptionalBoolHelper, false)
+ .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure,
+ PresetOptionalBoolHelper, false)
+ .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet,
+ PresetOptionalBoolHelper, false)
+ .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile,
+ PresetStringHelper, false)
+ .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary,
+ PresetOptionalBoolHelper, false)
+ .Bind("subprojectSummary"_s,
+ &TestPreset::OutputOptions::SubprojectSummary,
+ PresetOptionalBoolHelper, false)
+ .Bind("maxPassedTestOutputSize"_s,
+ &TestPreset::OutputOptions::MaxPassedTestOutputSize,
+ PresetOptionalIntHelper, false)
+ .Bind("maxFailedTestOutputSize"_s,
+ &TestPreset::OutputOptions::MaxFailedTestOutputSize,
+ PresetOptionalIntHelper, false)
+ .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth,
+ PresetOptionalIntHelper, false));
+
+auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
+ cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start,
+ PresetOptionalIntHelper, false)
+ .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End,
+ PresetOptionalIntHelper, false)
+ .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride,
+ PresetOptionalIntHelper, false)
+ .Bind("specificTests"_s,
+ &TestPreset::IncludeOptions::IndexOptions::SpecificTests,
+ PresetVectorIntHelper, false));
+
+ReadFileResult TestPresetOptionalFilterIncludeIndexHelper(
+ cm::optional<TestPreset::IncludeOptions::IndexOptions>& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.emplace();
+ out->IndexFile = value->asString();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value);
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalFilterIncludeHelper =
+ cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper,
+ false)
+ .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper,
+ false)
+ .Bind("index"_s, &TestPreset::IncludeOptions::Index,
+ TestPresetOptionalFilterIncludeIndexHelper, false)
+ .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion,
+ PresetOptionalBoolHelper, false));
+
+auto const TestPresetOptionalFilterExcludeFixturesHelper =
+ cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any,
+ PresetStringHelper, false)
+ .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup,
+ PresetStringHelper, false)
+ .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup,
+ PresetStringHelper, false));
+
+auto const TestPresetOptionalFilterExcludeHelper =
+ cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper,
+ false)
+ .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper,
+ false)
+ .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures,
+ TestPresetOptionalFilterExcludeFixturesHelper, false));
+
+ReadFileResult TestPresetExecutionShowOnlyHelper(
+ TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value)
+{
+ if (!value || !value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "human") {
+ out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "json-v1") {
+ out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionShowOnlyHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetExecutionShowOnlyHelper);
+
+ReadFileResult TestPresetExecutionModeHelper(
+ TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "until-fail") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "until-pass") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "after-timeout") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionRepeatHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode,
+ TestPresetExecutionModeHelper, true)
+ .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count,
+ PresetIntHelper, true));
+
+ReadFileResult TestPresetExecutionNoTestsActionHelper(
+ TestPreset::ExecutionOptions::NoTestsActionEnum& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "default") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "error") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "ignore") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionNoTestsActionHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetExecutionNoTestsActionHelper);
+
+auto const TestPresetExecutionHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure,
+ PresetOptionalBoolHelper, false)
+ .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover,
+ PresetOptionalBoolHelper, false)
+ .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs,
+ PresetOptionalIntHelper, false)
+ .Bind("resourceSpecFile"_s,
+ &TestPreset::ExecutionOptions::ResourceSpecFile,
+ PresetStringHelper, false)
+ .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad,
+ PresetOptionalIntHelper, false)
+ .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly,
+ TestPresetOptionalExecutionShowOnlyHelper, false)
+ .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat,
+ TestPresetOptionalExecutionRepeatHelper, false)
+ .Bind("interactiveDebugging"_s,
+ &TestPreset::ExecutionOptions::InteractiveDebugging,
+ PresetOptionalBoolHelper, false)
+ .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom,
+ PresetOptionalBoolHelper, false)
+ .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout,
+ PresetOptionalIntHelper, false)
+ .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction,
+ TestPresetOptionalExecutionNoTestsActionHelper, false));
+
+auto const TestPresetFilterHelper =
+ cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("include"_s, &TestPreset::FilterOptions::Include,
+ TestPresetOptionalFilterIncludeHelper, false)
+ .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude,
+ TestPresetOptionalFilterExcludeHelper, false));
+
+auto const TestPresetHelper =
+ cmJSONObjectHelper<TestPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &TestPreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false)
+ .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_PRESET), false)
+ .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false)
+ .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false)
+ .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper,
+ false)
+ .Bind("configurePreset"_s, &TestPreset::ConfigurePreset,
+ PresetStringHelper, false)
+ .Bind("inheritConfigureEnvironment"_s,
+ &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
+ false)
+ .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper,
+ false)
+ .Bind("overwriteConfigurationFile"_s,
+ &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper,
+ false)
+ .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper,
+ false)
+ .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false)
+ .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper,
+ false)
+ .Bind("condition"_s, &TestPreset::ConditionEvaluator,
+ PresetConditionHelper, false);
+
+auto const ConfigurePresetsHelper =
+ cmJSONVectorHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ ConfigurePresetHelper);
+
+auto const BuildPresetsHelper =
+ cmJSONVectorHelper<BuildPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ BuildPresetHelper);
+
+auto const TestPresetsHelper = cmJSONVectorHelper<TestPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper);
+
+auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const CMakeVersionHelper =
+ cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
+ .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
+ .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
+ .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
+
+auto const RootPresetsHelper =
+ cmJSONObjectHelper<RootPresets, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
+ .Bind<int>("version"_s, nullptr, VersionHelper)
+ .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
+ ConfigurePresetsHelper, false)
+ .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper,
+ false)
+ .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false)
+ .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
+ CMakeVersionHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_ROOT), false);
+}
+
+cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
+ const std::string& filename, bool user)
+{
+ cmsys::ifstream fin(filename.c_str());
+ if (!fin) {
+ return ReadFileResult::FILE_NOT_FOUND;
+ }
+ // If there's a BOM, toss it.
+ cmsys::FStream::ReadBOM(fin);
+
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ Json::CharReaderBuilder::strictMode(&builder.settings_);
+ if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
+ return ReadFileResult::JSON_PARSE_ERROR;
+ }
+
+ int v = 0;
+ auto result = RootVersionHelper(v, &root);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ if (v < MIN_VERSION || v > MAX_VERSION) {
+ return ReadFileResult::UNRECOGNIZED_VERSION;
+ }
+ if (user) {
+ this->UserVersion = v;
+ } else {
+ this->Version = v;
+ }
+
+ // Support for build and test presets added in version 2.
+ if (v < 2 &&
+ (root.isMember("buildPresets") || root.isMember("testPresets"))) {
+ return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
+ }
+
+ RootPresets presets;
+ if ((result = RootPresetsHelper(presets, &root)) !=
+ ReadFileResult::READ_OK) {
+ return result;
+ }
+
+ unsigned int currentMajor = cmVersion::GetMajorVersion();
+ unsigned int currentMinor = cmVersion::GetMinorVersion();
+ unsigned int currentPatch = cmVersion::GetPatchVersion();
+ auto const& required = presets.CMakeMinimumRequired;
+ if (required.Major > currentMajor ||
+ (required.Major == currentMajor &&
+ (required.Minor > currentMinor ||
+ (required.Minor == currentMinor &&
+ (required.Patch > currentPatch))))) {
+ return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
+ }
+
+ for (auto& preset : presets.ConfigurePresets) {
+ preset.User = user;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<ConfigurePreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->ConfigurePresets
+ .emplace(std::make_pair(preset.Name, presetPair))
+ .second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for installDir presets added in version 3.
+ if (v < 3 && !preset.InstallDir.empty()) {
+ return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ this->ConfigurePresetOrder.push_back(preset.Name);
+ }
+
+ for (auto& preset : presets.BuildPresets) {
+ preset.User = user;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<BuildPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ this->BuildPresetOrder.push_back(preset.Name);
+ }
+
+ for (auto& preset : presets.TestPresets) {
+ preset.User = user;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<TestPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ this->TestPresetOrder.push_back(preset.Name);
+ }
+
+ return ReadFileResult::READ_OK;
+}
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 620ba19..0dfd1bd 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -2108,17 +2108,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
} else if (this->CheckArgument(arg, "-L"_s, "--label-regex") &&
i < args.size() - 1) {
i++;
- this->GetTestHandler()->SetPersistentOption("LabelRegularExpression",
- args[i].c_str());
- this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression",
- args[i].c_str());
+ this->GetTestHandler()->AddPersistentMultiOption("LabelRegularExpression",
+ args[i]);
+ this->GetMemCheckHandler()->AddPersistentMultiOption(
+ "LabelRegularExpression", args[i]);
} else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") &&
i < args.size() - 1) {
i++;
- this->GetTestHandler()->SetPersistentOption(
- "ExcludeLabelRegularExpression", args[i].c_str());
- this->GetMemCheckHandler()->SetPersistentOption(
- "ExcludeLabelRegularExpression", args[i].c_str());
+ this->GetTestHandler()->AddPersistentMultiOption(
+ "ExcludeLabelRegularExpression", args[i]);
+ this->GetMemCheckHandler()->AddPersistentMultiOption(
+ "ExcludeLabelRegularExpression", args[i]);
}
else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") &&
@@ -2221,7 +2221,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
cmCTestScriptHandler* ch = this->GetScriptHandler();
// -SR is an internal argument, -SP should be ignored when it is passed
if (!SRArgumentSpecified) {
- ch->AddConfigurationScript(args[i].c_str(), false);
+ ch->AddConfigurationScript(args[i], false);
}
}
@@ -2231,7 +2231,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
this->Impl->RunConfigurationScript = true;
i++;
cmCTestScriptHandler* ch = this->GetScriptHandler();
- ch->AddConfigurationScript(args[i].c_str(), true);
+ ch->AddConfigurationScript(args[i], true);
}
if (this->CheckArgument(arg, "-S"_s, "--script") && i < args.size() - 1) {
@@ -2240,7 +2240,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
cmCTestScriptHandler* ch = this->GetScriptHandler();
// -SR is an internal argument, -S should be ignored when it is passed
if (!SRArgumentSpecified) {
- ch->AddConfigurationScript(args[i].c_str(), true);
+ ch->AddConfigurationScript(args[i], true);
}
}
}
@@ -2268,6 +2268,15 @@ void cmCTest::SetPersistentOptionIfNotEmpty(const std::string& value,
}
}
+void cmCTest::AddPersistentMultiOptionIfNotEmpty(const std::string& value,
+ const std::string& optionName)
+{
+ if (!value.empty()) {
+ this->GetTestHandler()->AddPersistentMultiOption(optionName, value);
+ this->GetMemCheckHandler()->AddPersistentMultiOption(optionName, value);
+ }
+}
+
bool cmCTest::SetArgsFromPreset(const std::string& presetName,
bool listPresets)
{
@@ -2310,6 +2319,13 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
return false;
}
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Cannot use disabled test preset in ",
+ workingDirectory, ": \"", presetName, '"'));
+ settingsFile.PrintTestPresetList();
+ return false;
+ }
+
auto configurePresetPair =
settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);
if (configurePresetPair == settingsFile.ConfigurePresets.end()) {
@@ -2412,7 +2428,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Filter->Include) {
this->SetPersistentOptionIfNotEmpty(
expandedPreset->Filter->Include->Name, "IncludeRegularExpression");
- this->SetPersistentOptionIfNotEmpty(
+ this->AddPersistentMultiOptionIfNotEmpty(
expandedPreset->Filter->Include->Label, "LabelRegularExpression");
if (expandedPreset->Filter->Include->Index) {
@@ -2445,7 +2461,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Filter->Exclude) {
this->SetPersistentOptionIfNotEmpty(
expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression");
- this->SetPersistentOptionIfNotEmpty(
+ this->AddPersistentMultiOptionIfNotEmpty(
expandedPreset->Filter->Exclude->Label,
"ExcludeLabelRegularExpression");
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 4669a1c..392eb1c 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -463,6 +463,8 @@ public:
private:
void SetPersistentOptionIfNotEmpty(const std::string& value,
const std::string& optionName);
+ void AddPersistentMultiOptionIfNotEmpty(const std::string& value,
+ const std::string& optionName);
int GenerateNotesFile(const std::string& files);
diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h
index 495dc69..b14cfc2 100644
--- a/Source/cmCommandLineArgument.h
+++ b/Source/cmCommandLineArgument.h
@@ -112,6 +112,10 @@ struct cmCommandLineArgument
}
}
if (parseState == ParseMode::Valid) {
+ if (possible_value[0] == ' ') {
+ possible_value.remove_prefix(1);
+ }
+
parseState = this->StoreCall(std::string(possible_value),
std::forward<CallState>(state)...)
? ParseMode::Valid
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 6225a4a..5473316 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -701,6 +701,10 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
this->AddTargetItem(lib, tgt);
this->AddLibraryRuntimeInfo(lib.Value, tgt);
+ if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ this->Target->IsDLLPlatform()) {
+ this->AddRuntimeDLL(tgt);
+ }
}
} else {
// This is not a CMake target. Use the name given.
@@ -728,6 +732,13 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item,
const cmGeneratorTarget* tgt)
{
+ // Record dependencies on DLLs.
+ if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ this->Target->IsDLLPlatform() &&
+ this->SharedDependencyMode != SharedDepModeLink) {
+ this->AddRuntimeDLL(tgt);
+ }
+
// If dropping shared library dependencies, ignore them.
if (this->SharedDependencyMode == SharedDepModeNone) {
return;
@@ -799,6 +810,14 @@ void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item,
}
}
+void cmComputeLinkInformation::AddRuntimeDLL(cmGeneratorTarget const* tgt)
+{
+ if (std::find(this->RuntimeDLLs.begin(), this->RuntimeDLLs.end(), tgt) ==
+ this->RuntimeDLLs.end()) {
+ this->RuntimeDLLs.emplace_back(tgt);
+ }
+}
+
void cmComputeLinkInformation::ComputeLinkTypeInfo()
{
// Check whether archives may actually be shared libraries.
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 9fec702..4acb99f 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -64,6 +64,10 @@ public:
std::string GetRPathString(bool for_install) const;
std::string GetChrpathString() const;
std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const;
+ std::vector<cmGeneratorTarget const*> const& GetRuntimeDLLs() const
+ {
+ return this->RuntimeDLLs;
+ }
std::string const& GetLibLinkFileFlag() const
{
@@ -81,6 +85,7 @@ private:
void AddItem(BT<std::string> const& item, const cmGeneratorTarget* tgt);
void AddSharedDepItem(BT<std::string> const& item,
cmGeneratorTarget const* tgt);
+ void AddRuntimeDLL(cmGeneratorTarget const* tgt);
// Output information.
ItemVector Items;
@@ -89,6 +94,7 @@ private:
std::vector<std::string> FrameworkPaths;
std::vector<std::string> RuntimeSearchPath;
std::set<cmGeneratorTarget const*> SharedLibrariesLinked;
+ std::vector<cmGeneratorTarget const*> RuntimeDLLs;
// Context information.
cmGeneratorTarget const* const Target;
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index 3001ae0..a2fac73 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -90,10 +90,15 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args,
std::replace(func_name.begin(), func_name.end(), ' ', '_');
std::replace(func_name.begin(), func_name.end(), '/', '_');
std::replace(func_name.begin(), func_name.end(), ':', '_');
+ bool already_declared =
+ std::find(tests_func_name.begin(), tests_func_name.end(), func_name) !=
+ tests_func_name.end();
tests_func_name.push_back(func_name);
- forwardDeclareCode += "int ";
- forwardDeclareCode += func_name;
- forwardDeclareCode += "(int, char*[]);\n";
+ if (!already_declared) {
+ forwardDeclareCode += "int ";
+ forwardDeclareCode += func_name;
+ forwardDeclareCode += "(int, char*[]);\n";
+ }
}
std::string functionMapCode;
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 4329caf..4705443 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -139,6 +139,14 @@ std::vector<std::string> EvaluateOutputs(std::vector<std::string> const& paths,
}
return outputs;
}
+
+std::string EvaluateDepfile(std::string const& path,
+ cmGeneratorExpression const& ge,
+ cmLocalGenerator* lg, std::string const& config)
+{
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(path);
+ return cge->Evaluate(lg, config);
+}
}
cmCustomCommandGenerator::cmCustomCommandGenerator(
@@ -381,9 +389,20 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
}
}
+std::string cmCustomCommandGenerator::GetDepfile() const
+{
+ const auto& depfile = this->CC->GetDepfile();
+ if (depfile.empty()) {
+ return "";
+ }
+
+ cmGeneratorExpression ge(this->CC->GetBacktrace());
+ return EvaluateDepfile(depfile, ge, this->LG, this->OutputConfig);
+}
+
std::string cmCustomCommandGenerator::GetFullDepfile() const
{
- std::string depfile = this->CC->GetDepfile();
+ std::string depfile = this->GetDepfile();
if (depfile.empty()) {
return "";
}
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 4be5b3f..53e5573 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -57,6 +57,7 @@ public:
std::vector<std::string> const& GetDepends() const;
std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
bool HasOnlyEmptyCommandLines() const;
+ std::string GetDepfile() const;
std::string GetFullDepfile() const;
std::string GetInternalDepfile() const;
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 7015a01..0409f97 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -924,13 +924,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
// Isolate the file policy level.
// Support CMake versions as far back as 2.6 but also support using NEW
- // policy settings for up to CMake 3.18 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.19 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
/* clang-format off */
os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.6...3.18)\n";
+ << "cmake_policy(VERSION 2.6...3.19)\n";
/* clang-format on */
}
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index a92f6e3..52965bb 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -435,7 +435,8 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes(
lg->GetIncludeDirectories(includes, target, language, config);
std::string includesString =
- lg->GetIncludeFlags(includes, target, language, true, false, config);
+ lg->GetIncludeFlags(includes, target, language, config, false,
+ cmLocalGenerator::IncludePathStyle::Absolute);
return includesString;
}
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index d2a9bec..d529f52 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -686,7 +686,7 @@ std::string cmFileAPI::NoSupportedVersion(
// The "codemodel" object kind.
-static unsigned int const CodeModelV2Minor = 2;
+static unsigned int const CodeModelV2Minor = 3;
void cmFileAPI::BuildClientRequestCodeModel(
ClientRequest& r, std::vector<RequestVersion> const& versions)
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 9061109..6b8757c 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -20,11 +20,16 @@
#include <cm3p/json/value.h>
#include "cmCryptoHash.h"
+#include "cmExportSet.h"
#include "cmFileAPI.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmInstallDirectoryGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
+#include "cmInstallScriptGenerator.h"
#include "cmInstallSubdirectoryGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h"
@@ -42,81 +47,13 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
+#include "cmTargetExport.h"
#include "cmake.h"
namespace {
-class Codemodel
-{
- cmFileAPI& FileAPI;
- unsigned long Version;
-
- Json::Value DumpPaths();
- Json::Value DumpConfigurations();
- Json::Value DumpConfiguration(std::string const& config);
-
-public:
- Codemodel(cmFileAPI& fileAPI, unsigned long version);
- Json::Value Dump();
-};
-
-class CodemodelConfig
-{
- cmFileAPI& FileAPI;
- unsigned long Version;
- std::string const& Config;
- std::string TopSource;
- std::string TopBuild;
-
- struct Directory
- {
- cmStateSnapshot Snapshot;
- cmLocalGenerator const* LocalGenerator = nullptr;
- Json::Value TargetIndexes = Json::arrayValue;
- Json::ArrayIndex ProjectIndex;
- bool HasInstallRule = false;
- };
- std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
- DirectoryMap;
- std::vector<Directory> Directories;
-
- struct Project
- {
- cmStateSnapshot Snapshot;
- static const Json::ArrayIndex NoParentIndex =
- static_cast<Json::ArrayIndex>(-1);
- Json::ArrayIndex ParentIndex = NoParentIndex;
- Json::Value ChildIndexes = Json::arrayValue;
- Json::Value DirectoryIndexes = Json::arrayValue;
- Json::Value TargetIndexes = Json::arrayValue;
- };
- std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
- ProjectMap;
- std::vector<Project> Projects;
-
- void ProcessDirectories();
-
- Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
- Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);
-
- Json::ArrayIndex AddProject(cmStateSnapshot s);
-
- Json::Value DumpTargets();
- Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);
-
- Json::Value DumpDirectories();
- Json::Value DumpDirectory(Directory& d);
-
- Json::Value DumpProjects();
- Json::Value DumpProject(Project& p);
-
- Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);
-
-public:
- CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
- std::string const& config);
- Json::Value Dump();
-};
+using TargetIndexMapType =
+ std::unordered_map<cmGeneratorTarget const*, Json::ArrayIndex>;
std::string RelativeIfUnder(std::string const& top, std::string const& in)
{
@@ -131,16 +68,6 @@ std::string RelativeIfUnder(std::string const& top, std::string const& in)
return out;
}
-std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
-{
- cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
- std::string path = RelativeIfUnder(
- topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
- std::string hash = hasher.HashString(path);
- hash.resize(20, '0');
- return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
-}
-
class JBTIndex
{
public:
@@ -290,6 +217,91 @@ Json::Value BacktraceData::Dump()
return backtraceGraph;
}
+class Codemodel
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+
+ Json::Value DumpPaths();
+ Json::Value DumpConfigurations();
+ Json::Value DumpConfiguration(std::string const& config);
+
+public:
+ Codemodel(cmFileAPI& fileAPI, unsigned long version);
+ Json::Value Dump();
+};
+
+class CodemodelConfig
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+ std::string const& Config;
+ std::string TopSource;
+ std::string TopBuild;
+
+ struct Directory
+ {
+ cmStateSnapshot Snapshot;
+ cmLocalGenerator const* LocalGenerator = nullptr;
+ Json::Value TargetIndexes = Json::arrayValue;
+ Json::ArrayIndex ProjectIndex;
+ bool HasInstallRule = false;
+ };
+ std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+ DirectoryMap;
+ std::vector<Directory> Directories;
+
+ struct Project
+ {
+ cmStateSnapshot Snapshot;
+ static const Json::ArrayIndex NoParentIndex =
+ static_cast<Json::ArrayIndex>(-1);
+ Json::ArrayIndex ParentIndex = NoParentIndex;
+ Json::Value ChildIndexes = Json::arrayValue;
+ Json::Value DirectoryIndexes = Json::arrayValue;
+ Json::Value TargetIndexes = Json::arrayValue;
+ };
+ std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+ ProjectMap;
+ std::vector<Project> Projects;
+
+ TargetIndexMapType TargetIndexMap;
+
+ void ProcessDirectories();
+
+ Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
+ Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);
+
+ Json::ArrayIndex AddProject(cmStateSnapshot s);
+
+ Json::Value DumpTargets();
+ Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);
+
+ Json::Value DumpDirectories();
+ Json::Value DumpDirectory(Directory& d);
+ Json::Value DumpDirectoryObject(Directory& d);
+
+ Json::Value DumpProjects();
+ Json::Value DumpProject(Project& p);
+
+ Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);
+
+public:
+ CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
+ std::string const& config);
+ Json::Value Dump();
+};
+
+std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
+{
+ cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
+ std::string path = RelativeIfUnder(
+ topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
+ std::string hash = hasher.HashString(path);
+ hash.resize(20, '0');
+ return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
+}
+
struct CompileData
{
struct IncludeEntry
@@ -367,6 +379,31 @@ struct hash<CompileData>
} // namespace std
namespace {
+class DirectoryObject
+{
+ cmLocalGenerator const* LG = nullptr;
+ std::string const& Config;
+ TargetIndexMapType& TargetIndexMap;
+ std::string TopSource;
+ std::string TopBuild;
+ BacktraceData Backtraces;
+
+ void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
+
+ Json::Value DumpPaths();
+ Json::Value DumpInstallers();
+ Json::Value DumpInstaller(cmInstallGenerator* gen);
+ Json::Value DumpInstallerExportTargets(cmExportSet* exp);
+ Json::Value DumpInstallerPath(std::string const& top,
+ std::string const& fromPathIn,
+ std::string const& toPath);
+
+public:
+ DirectoryObject(cmLocalGenerator const* lg, std::string const& config,
+ TargetIndexMapType& targetIndexMap);
+ Json::Value Dump();
+};
+
class Target
{
cmGeneratorTarget* GT;
@@ -663,6 +700,8 @@ Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt,
target["projectIndex"] = pi;
this->Projects[pi].TargetIndexes.append(ti);
+ this->TargetIndexMap[gt] = ti;
+
return target;
}
@@ -677,7 +716,7 @@ Json::Value CodemodelConfig::DumpDirectories()
Json::Value CodemodelConfig::DumpDirectory(Directory& d)
{
- Json::Value directory = Json::objectValue;
+ Json::Value directory = this->DumpDirectoryObject(d);
std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource();
directory["source"] = RelativeIfUnder(this->TopSource, sourceDir);
@@ -717,6 +756,31 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d)
return directory;
}
+Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d)
+{
+ std::string prefix = "directory";
+ std::string sourceDirRel = RelativeIfUnder(
+ this->TopSource, d.Snapshot.GetDirectory().GetCurrentSource());
+ std::string buildDirRel = RelativeIfUnder(
+ this->TopBuild, d.Snapshot.GetDirectory().GetCurrentBinary());
+ if (!cmSystemTools::FileIsFullPath(buildDirRel)) {
+ prefix = cmStrCat(prefix, '-', buildDirRel);
+ } else if (!cmSystemTools::FileIsFullPath(sourceDirRel)) {
+ prefix = cmStrCat(prefix, '-', sourceDirRel);
+ }
+ for (char& c : prefix) {
+ if (c == '/' || c == '\\') {
+ c = '.';
+ }
+ }
+ if (!this->Config.empty()) {
+ prefix += "-" + this->Config;
+ }
+
+ DirectoryObject dir(d.LocalGenerator, this->Config, this->TargetIndexMap);
+ return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix);
+}
+
Json::Value CodemodelConfig::DumpProjects()
{
Json::Value projects = Json::arrayValue;
@@ -760,6 +824,246 @@ Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
return minimumCMakeVersion;
}
+DirectoryObject::DirectoryObject(cmLocalGenerator const* lg,
+ std::string const& config,
+ TargetIndexMapType& targetIndexMap)
+ : LG(lg)
+ , Config(config)
+ , TargetIndexMap(targetIndexMap)
+ , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
+ , TopBuild(
+ lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
+ , Backtraces(this->TopSource)
+{
+}
+
+Json::Value DirectoryObject::Dump()
+{
+ Json::Value directoryObject = Json::objectValue;
+ directoryObject["paths"] = this->DumpPaths();
+ directoryObject["installers"] = this->DumpInstallers();
+ directoryObject["backtraceGraph"] = this->Backtraces.Dump();
+ return directoryObject;
+}
+
+void DirectoryObject::AddBacktrace(Json::Value& object,
+ cmListFileBacktrace const& bt)
+{
+ if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
+ object["backtrace"] = backtrace.Index;
+ }
+}
+
+Json::Value DirectoryObject::DumpPaths()
+{
+ Json::Value paths = Json::objectValue;
+
+ std::string const& sourceDir = this->LG->GetCurrentSourceDirectory();
+ paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);
+
+ std::string const& buildDir = this->LG->GetCurrentBinaryDirectory();
+ paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);
+
+ return paths;
+}
+
+Json::Value DirectoryObject::DumpInstallers()
+{
+ Json::Value installers = Json::arrayValue;
+ for (const auto& gen : this->LG->GetMakefile()->GetInstallGenerators()) {
+ Json::Value installer = this->DumpInstaller(gen.get());
+ if (!installer.empty()) {
+ installers.append(std::move(installer)); // NOLINT(*)
+ }
+ }
+ return installers;
+}
+
+Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
+{
+ Json::Value installer = Json::objectValue;
+
+ // Exclude subdirectory installers. They are implementation details.
+ if (dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) {
+ return installer;
+ }
+
+ // Exclude installers not used in this configuration.
+ if (!gen->InstallsForConfig(this->Config)) {
+ return installer;
+ }
+
+ // Add fields specific to each kind of install generator.
+ if (auto* installTarget = dynamic_cast<cmInstallTargetGenerator*>(gen)) {
+ cmInstallTargetGenerator::Files const& files =
+ installTarget->GetFiles(this->Config);
+ if (files.From.empty()) {
+ return installer;
+ }
+
+ installer["type"] = "target";
+ installer["destination"] = installTarget->GetDestination(this->Config);
+ installer["targetId"] =
+ TargetId(installTarget->GetTarget(), this->TopBuild);
+ installer["targetIndex"] =
+ this->TargetIndexMap[installTarget->GetTarget()];
+
+ std::string fromDir = files.FromDir;
+ if (!fromDir.empty()) {
+ fromDir.push_back('/');
+ }
+
+ std::string toDir = files.ToDir;
+ if (!toDir.empty()) {
+ toDir.push_back('/');
+ }
+
+ Json::Value paths = Json::arrayValue;
+ for (size_t i = 0; i < files.From.size(); ++i) {
+ std::string const& fromPath = cmStrCat(fromDir, files.From[i]);
+ std::string const& toPath = cmStrCat(toDir, files.To[i]);
+ paths.append(this->DumpInstallerPath(this->TopBuild, fromPath, toPath));
+ }
+ installer["paths"] = std::move(paths);
+
+ if (installTarget->GetOptional()) {
+ installer["isOptional"] = true;
+ }
+
+ if (installTarget->IsImportLibrary()) {
+ installer["targetIsImportLibrary"] = true;
+ }
+
+ switch (files.NamelinkMode) {
+ case cmInstallTargetGenerator::NamelinkModeNone:
+ break;
+ case cmInstallTargetGenerator::NamelinkModeOnly:
+ installer["targetInstallNamelink"] = "only";
+ break;
+ case cmInstallTargetGenerator::NamelinkModeSkip:
+ installer["targetInstallNamelink"] = "skip";
+ break;
+ }
+
+ // FIXME: Parse FilePermissions to provide structured information.
+ // FIXME: Thread EXPORT name through from install() call.
+ } else if (auto* installFiles =
+ dynamic_cast<cmInstallFilesGenerator*>(gen)) {
+ std::vector<std::string> const& files =
+ installFiles->GetFiles(this->Config);
+ if (files.empty()) {
+ return installer;
+ }
+
+ installer["type"] = "file";
+ installer["destination"] = installFiles->GetDestination(this->Config);
+ Json::Value paths = Json::arrayValue;
+ std::string const& rename = installFiles->GetRename(this->Config);
+ if (!rename.empty() && files.size() == 1) {
+ paths.append(this->DumpInstallerPath(this->TopSource, files[0], rename));
+ } else {
+ for (std::string const& file : installFiles->GetFiles(this->Config)) {
+ paths.append(RelativeIfUnder(this->TopSource, file));
+ }
+ }
+ installer["paths"] = std::move(paths);
+ if (installFiles->GetOptional()) {
+ installer["isOptional"] = true;
+ }
+ // FIXME: Parse FilePermissions to provide structured information.
+ } else if (auto* installDir =
+ dynamic_cast<cmInstallDirectoryGenerator*>(gen)) {
+ std::vector<std::string> const& dirs =
+ installDir->GetDirectories(this->Config);
+ if (dirs.empty()) {
+ return installer;
+ }
+
+ installer["type"] = "directory";
+ installer["destination"] = installDir->GetDestination(this->Config);
+ Json::Value paths = Json::arrayValue;
+ for (std::string const& dir : dirs) {
+ if (cmHasLiteralSuffix(dir, "/")) {
+ paths.append(this->DumpInstallerPath(
+ this->TopSource, dir.substr(0, dir.size() - 1), "."));
+ } else {
+ paths.append(this->DumpInstallerPath(
+ this->TopSource, dir, cmSystemTools::GetFilenameName(dir)));
+ }
+ }
+ installer["paths"] = std::move(paths);
+ if (installDir->GetOptional()) {
+ installer["isOptional"] = true;
+ }
+ // FIXME: Parse FilePermissions, DirPermissions, and LiteralArguments.
+ // to provide structured information.
+ } else if (auto* installExport =
+ dynamic_cast<cmInstallExportGenerator*>(gen)) {
+ installer["type"] = "export";
+ installer["destination"] = installExport->GetDestination();
+ cmExportSet* exportSet = installExport->GetExportSet();
+ installer["exportName"] = exportSet->GetName();
+ installer["exportTargets"] = this->DumpInstallerExportTargets(exportSet);
+ Json::Value paths = Json::arrayValue;
+ paths.append(
+ RelativeIfUnder(this->TopBuild, installExport->GetMainImportFile()));
+ installer["paths"] = std::move(paths);
+ } else if (auto* installScript =
+ dynamic_cast<cmInstallScriptGenerator*>(gen)) {
+ if (installScript->IsCode()) {
+ installer["type"] = "code";
+ } else {
+ installer["type"] = "script";
+ installer["scriptFile"] = RelativeIfUnder(
+ this->TopSource, installScript->GetScript(this->Config));
+ }
+ }
+
+ // Add fields common to all install generators.
+ installer["component"] = gen->GetComponent();
+ if (gen->GetExcludeFromAll()) {
+ installer["isExcludeFromAll"] = true;
+ }
+ this->AddBacktrace(installer, gen->GetBacktrace());
+
+ return installer;
+}
+
+Json::Value DirectoryObject::DumpInstallerExportTargets(cmExportSet* exp)
+{
+ Json::Value targets = Json::arrayValue;
+ for (auto const& targetExport : exp->GetTargetExports()) {
+ Json::Value target = Json::objectValue;
+ target["id"] = TargetId(targetExport->Target, this->TopBuild);
+ target["index"] = this->TargetIndexMap[targetExport->Target];
+ targets.append(std::move(target)); // NOLINT(*)
+ }
+ return targets;
+}
+
+Json::Value DirectoryObject::DumpInstallerPath(std::string const& top,
+ std::string const& fromPathIn,
+ std::string const& toPath)
+{
+ Json::Value installPath;
+
+ std::string fromPath = RelativeIfUnder(top, fromPathIn);
+
+ // If toPath is the last component of fromPath, use just fromPath.
+ if (toPath.find_first_of('/') == std::string::npos &&
+ cmHasSuffix(fromPath, toPath) &&
+ (fromPath.size() == toPath.size() ||
+ fromPath[fromPath.size() - toPath.size() - 1] == '/')) {
+ installPath = fromPath;
+ } else {
+ installPath = Json::objectValue;
+ installPath["from"] = fromPath;
+ installPath["to"] = toPath;
+ }
+
+ return installPath;
+}
+
Target::Target(cmGeneratorTarget* gt, std::string const& config)
: GT(gt)
, Config(config)
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 4a28238..a06ed48 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1313,8 +1313,9 @@ bool HandleRelativePathCommand(std::vector<std::string> const& args,
bool HandleRename(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- if (args.size() != 3) {
- status.SetError("RENAME given incorrect number of arguments.");
+ if (args.size() < 3) {
+ status.SetError("RENAME must be called with at least two additional "
+ "arguments");
return false;
}
@@ -1330,13 +1331,143 @@ bool HandleRename(std::vector<std::string> const& args,
cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
}
- if (!cmSystemTools::RenameFile(oldname, newname)) {
- std::string err = cmSystemTools::GetLastSystemError();
- status.SetError(cmStrCat("RENAME failed to rename\n ", oldname,
- "\nto\n ", newname, "\nbecause: ", err, "\n"));
+ struct Arguments
+ {
+ bool NoReplace = false;
+ std::string Result;
+ };
+
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("NO_REPLACE"_s, &Arguments::NoReplace)
+ .Bind("RESULT"_s, &Arguments::Result);
+
+ std::vector<std::string> unconsumedArgs;
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs);
+ if (!unconsumedArgs.empty()) {
+ status.SetError("RENAME unknown argument:\n " + unconsumedArgs.front());
return false;
}
- return true;
+
+ std::string err;
+ switch (cmSystemTools::RenameFile(oldname, newname,
+ arguments.NoReplace
+ ? cmSystemTools::Replace::No
+ : cmSystemTools::Replace::Yes,
+ &err)) {
+ case cmSystemTools::RenameResult::Success:
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, "0");
+ }
+ return true;
+ case cmSystemTools::RenameResult::NoReplace:
+ if (!arguments.Result.empty()) {
+ err = "NO_REPLACE";
+ } else {
+ err = "path not replaced";
+ }
+ CM_FALLTHROUGH;
+ case cmSystemTools::RenameResult::Failure:
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, err);
+ return true;
+ }
+ break;
+ }
+ status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, "\nto\n ",
+ newname, "\nbecause: ", err, "\n"));
+ return false;
+}
+
+bool HandleCopyFile(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3) {
+ status.SetError("COPY_FILE must be called with at least two additional "
+ "arguments");
+ return false;
+ }
+
+ // Compute full path for old and new names.
+ std::string oldname = args[1];
+ if (!cmsys::SystemTools::FileIsFullPath(oldname)) {
+ oldname =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
+ }
+ std::string newname = args[2];
+ if (!cmsys::SystemTools::FileIsFullPath(newname)) {
+ newname =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
+ }
+
+ struct Arguments
+ {
+ bool OnlyIfDifferent = false;
+ std::string Result;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("ONLY_IF_DIFFERENT"_s, &Arguments::OnlyIfDifferent)
+ .Bind("RESULT"_s, &Arguments::Result);
+
+ std::vector<std::string> unconsumedArgs;
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs);
+ if (!unconsumedArgs.empty()) {
+ status.SetError("COPY_FILE unknown argument:\n " +
+ unconsumedArgs.front());
+ return false;
+ }
+
+ bool result = true;
+ if (cmsys::SystemTools::FileIsDirectory(oldname)) {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result,
+ "cannot copy a directory");
+ } else {
+ status.SetError(
+ cmStrCat("COPY_FILE cannot copy a directory\n ", oldname));
+ result = false;
+ }
+ return result;
+ }
+ if (cmsys::SystemTools::FileIsDirectory(newname)) {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result,
+ "cannot copy to a directory");
+ } else {
+ status.SetError(
+ cmStrCat("COPY_FILE cannot copy to a directory\n ", newname));
+ result = false;
+ }
+ return result;
+ }
+
+ cmSystemTools::CopyWhen when;
+ if (arguments.OnlyIfDifferent) {
+ when = cmSystemTools::CopyWhen::OnlyIfDifferent;
+ } else {
+ when = cmSystemTools::CopyWhen::Always;
+ }
+
+ std::string err;
+ if (cmSystemTools::CopySingleFile(oldname, newname, when, &err) ==
+ cmSystemTools::CopyResult::Success) {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, "0");
+ }
+ } else {
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, err);
+ } else {
+ status.SetError(cmStrCat("COPY_FILE failed to copy\n ", oldname,
+ "\nto\n ", newname, "\nbecause: ", err, "\n"));
+ result = false;
+ }
+ }
+
+ return result;
}
bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse,
@@ -3569,6 +3700,7 @@ bool cmFileCommand(std::vector<std::string> const& args,
{ "GLOB_RECURSE"_s, HandleGlobRecurseCommand },
{ "MAKE_DIRECTORY"_s, HandleMakeDirectoryCommand },
{ "RENAME"_s, HandleRename },
+ { "COPY_FILE"_s, HandleCopyFile },
{ "REMOVE"_s, HandleRemove },
{ "REMOVE_RECURSE"_s, HandleRemoveRecurse },
{ "COPY"_s, HandleCopyCommand },
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 49b1bd7..d85ba8f 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -374,7 +374,7 @@ void cmFindLibraryHelper::AddName(std::string const& name)
regex += "(\\.[0-9]+\\.[0-9]+)?";
}
regex += "$";
- entry.Regex.compile(regex.c_str());
+ entry.Regex.compile(regex);
this->Names.push_back(std::move(entry));
}
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index e40316e..7125170 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -14,6 +14,7 @@
#include <utility>
#include <cm/iterator>
+#include <cm/optional>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
@@ -23,6 +24,7 @@
#include "cmsys/String.h"
#include "cmAlgorithms.h"
+#include "cmComputeLinkInformation.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
@@ -1627,8 +1629,8 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
type != cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "Objects of target \"" << tgtName
- << "\" referenced but is not an allowed library types (EXECUTABLE, "
- << "STATIC, SHARED, MODULE, OBJECT).";
+ << "\" referenced but is not one of the allowed target types "
+ << "(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT).";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
@@ -1687,6 +1689,54 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
}
} targetObjectsNode;
+static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode
+{
+ TargetRuntimeDllsNode() {} // NOLINT(modernize-use-equals-default)
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::string tgtName = parameters.front();
+ cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
+ if (!gt) {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but no such target exists.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ cmStateEnums::TargetType type = gt->GetType();
+ if (type != cmStateEnums::EXECUTABLE &&
+ type != cmStateEnums::SHARED_LIBRARY &&
+ type != cmStateEnums::MODULE_LIBRARY) {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but is not one of the allowed target types "
+ << "(EXECUTABLE, SHARED, MODULE).";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+
+ if (auto* cli = gt->GetLinkInformation(context->Config)) {
+ std::vector<std::string> dllPaths;
+ auto const& dlls = cli->GetRuntimeDLLs();
+
+ for (auto const& dll : dlls) {
+ if (auto loc = dll->MaybeGetLocation(context->Config)) {
+ dllPaths.emplace_back(*loc);
+ }
+ }
+
+ return cmJoin(dllPaths, ";");
+ }
+
+ return "";
+ }
+} targetRuntimeDllsNode;
+
static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
{
CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default)
@@ -2603,6 +2653,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "TARGET_EXISTS", &targetExistsNode },
{ "TARGET_NAME_IF_EXISTS", &targetNameIfExistsNode },
{ "TARGET_GENEX_EVAL", &targetGenexEvalNode },
+ { "TARGET_RUNTIME_DLLS", &targetRuntimeDllsNode },
{ "GENEX_EVAL", &genexEvalNode },
{ "BUILD_INTERFACE", &buildInterfaceNode },
{ "INSTALL_INTERFACE", &installInterfaceNode },
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index efac06a..365f8b8 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1062,6 +1062,20 @@ const std::string& cmGeneratorTarget::GetLocation(
return location;
}
+cm::optional<std::string> cmGeneratorTarget::MaybeGetLocation(
+ std::string const& config) const
+{
+ cm::optional<std::string> location;
+ if (cmGeneratorTarget::ImportInfo const* imp = this->GetImportInfo(config)) {
+ if (!imp->Location.empty()) {
+ location = imp->Location;
+ }
+ } else {
+ location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
+ }
+ return location;
+}
+
std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands()
const
{
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 8fe70ab..2935e0b 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -14,6 +14,8 @@
#include <utility>
#include <vector>
+#include <cm/optional>
+
#include "cmLinkItem.h"
#include "cmListFileCache.h"
#include "cmPolicies.h"
@@ -50,6 +52,9 @@ public:
bool CanCompileSources() const;
const std::string& GetLocation(const std::string& config) const;
+ /** Get the full path to the target's main artifact, if known. */
+ cm::optional<std::string> MaybeGetLocation(std::string const& config) const;
+
std::vector<cmCustomCommand> const& GetPreBuildCommands() const;
std::vector<cmCustomCommand> const& GetPreLinkCommands() const;
std::vector<cmCustomCommand> const& GetPostBuildCommands() const;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index c502fb8..6937639 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -9,6 +9,7 @@
#include <cm/iterator>
#include <cm/memory>
+#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/memory>
@@ -503,14 +504,7 @@ std::unique_ptr<cmLocalGenerator> cmGlobalNinjaGenerator::CreateLocalGenerator(
codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const
{
-#ifdef _WIN32
- // Ninja on Windows does not support non-ANSI characters.
- // https://github.com/ninja-build/ninja/issues/1195
- return codecvt::ANSI;
-#else
- // No encoding conversion needed on other platforms.
- return codecvt::None;
-#endif
+ return this->NinjaExpectedEncoding;
}
void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry)
@@ -732,6 +726,61 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures()
this->NinjaSupportsMetadataOnRegeneration = !cmSystemTools::VersionCompare(
cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
RequiredNinjaVersionForMetadataOnRegeneration().c_str());
+#ifdef _WIN32
+ this->NinjaSupportsCodePage = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ RequiredNinjaVersionForCodePage().c_str());
+ if (this->NinjaSupportsCodePage) {
+ this->CheckNinjaCodePage();
+ } else {
+ this->NinjaExpectedEncoding = codecvt::ANSI;
+ }
+#endif
+}
+
+void cmGlobalNinjaGenerator::CheckNinjaCodePage()
+{
+ std::vector<std::string> command{ this->NinjaCommand, "-t", "wincodepage" };
+ std::string output;
+ std::string error;
+ int result;
+ if (!cmSystemTools::RunSingleCommand(command, &output, &error, &result,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("Running\n '",
+ cmJoin(command, "' '"),
+ "'\n"
+ "failed with:\n ",
+ error));
+ cmSystemTools::SetFatalErrorOccured();
+ } else if (result == 0) {
+ std::istringstream outputStream(output);
+ std::string line;
+ bool found = false;
+ while (cmSystemTools::GetLineFromStream(outputStream, line)) {
+ if (cmHasLiteralPrefix(line, "Build file encoding: ")) {
+ cm::string_view lineView(line);
+ cm::string_view encoding =
+ lineView.substr(cmStrLen("Build file encoding: "));
+ if (encoding == "UTF-8") {
+ // Ninja expects UTF-8. We use that internally. No conversion needed.
+ this->NinjaExpectedEncoding = codecvt::None;
+ } else {
+ this->NinjaExpectedEncoding = codecvt::ANSI;
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::WARNING,
+ "Could not determine Ninja's code page, defaulting to UTF-8");
+ this->NinjaExpectedEncoding = codecvt::None;
+ }
+ } else {
+ this->NinjaExpectedEncoding = codecvt::ANSI;
+ }
}
bool cmGlobalNinjaGenerator::CheckLanguages(
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 0c919ef..9f31708 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -388,6 +388,7 @@ public:
{
return "1.10.2";
}
+ static std::string RequiredNinjaVersionForCodePage() { return "1.11"; }
bool SupportsConsolePool() const;
bool SupportsImplicitOuts() const;
bool SupportsManifestRestat() const;
@@ -474,6 +475,7 @@ private:
std::string GetEditCacheCommand() const override;
bool FindMakeProgram(cmMakefile* mf) override;
void CheckNinjaFeatures();
+ void CheckNinjaCodePage();
bool CheckLanguages(std::vector<std::string> const& languages,
cmMakefile* mf) const override;
bool CheckFortran(cmMakefile* mf) const;
@@ -568,6 +570,9 @@ private:
bool NinjaSupportsUnconditionalRecompactTool = false;
bool NinjaSupportsMultipleOutputs = false;
bool NinjaSupportsMetadataOnRegeneration = false;
+ bool NinjaSupportsCodePage = false;
+
+ codecvt::Encoding NinjaExpectedEncoding = codecvt::None;
bool DiagnosedCxxModuleSupport = false;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index badce2e..93fbe37 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -231,6 +231,23 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
return false;
}
+ if (!this->CustomFlagTableDir.empty() &&
+ !(cmSystemTools::FileIsFullPath(this->CustomFlagTableDir) &&
+ cmSystemTools::FileIsDirectory(this->CustomFlagTableDir))) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset\n"
+ " customFlagTableDir=" << this->CustomFlagTableDir << "\n"
+ "that is not an absolute path to an existing directory.";
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) {
// The GenerateDebugInformation link setting for the v140 toolset
// in VS 2015 was originally an enum with "No" and "Debug" values,
@@ -263,8 +280,8 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
bcDir = this->VCTargetsPath + "/BuildCustomizations";
} else {
bcDir = this->GetPlatformToolsetCudaCustomDirString() +
- "CUDAVisualStudioIntegration\\extras\\"
- "visual_studio_integration\\MSBuildExtensions";
+ this->GetPlatformToolsetCudaVSIntegrationSubdirString() +
+ "extras\\visual_studio_integration\\MSBuildExtensions";
cmSystemTools::ConvertToUnixSlashes(bcDir);
}
cmsys::Glob gl;
@@ -470,11 +487,27 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
if (this->GeneratorToolsetCudaCustomDir.back() != '\\') {
this->GeneratorToolsetCudaCustomDir.push_back('\\');
}
+ /* check for legacy toolkit folder structure */
+ if (cmsys::SystemTools::FileIsDirectory(
+ cmStrCat(this->GeneratorToolsetCudaCustomDir, "nvcc"))) {
+ this->GeneratorToolsetCudaNvccSubdir = "nvcc\\";
+ }
+ if (cmsys::SystemTools::FileIsDirectory(
+ cmStrCat(this->GeneratorToolsetCudaCustomDir,
+ "CUDAVisualStudioIntegration"))) {
+ this->GeneratorToolsetCudaVSIntegrationSubdir =
+ "CUDAVisualStudioIntegration\\";
+ }
} else {
this->GeneratorToolsetCuda = value;
}
return true;
}
+ if (key == "customFlagTableDir") {
+ this->CustomFlagTableDir = value;
+ cmSystemTools::ConvertToUnixSlashes(this->CustomFlagTableDir);
+ return true;
+ }
if (key == "version") {
this->GeneratorToolsetVersion = value;
return true;
@@ -787,6 +820,18 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const
return this->GeneratorToolsetCudaCustomDir;
}
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaNvccSubdirString() const
+{
+ return this->GeneratorToolsetCudaNvccSubdir;
+}
+
+std::string const& cmGlobalVisualStudio10Generator::
+ GetPlatformToolsetCudaVSIntegrationSubdirString() const
+{
+ return this->GeneratorToolsetCudaVSIntegrationSubdir;
+}
+
cmGlobalVisualStudio10Generator::AuxToolset
cmGlobalVisualStudio10Generator::FindAuxToolset(std::string&,
std::string&) const
@@ -1349,137 +1394,262 @@ static cmIDEFlagTable const* cmLoadFlagTableJson(
return ret;
}
-static std::string cmGetFlagTableName(std::string const& toolsetName,
- std::string const& table)
+cm::optional<std::string> cmGlobalVisualStudio10Generator::FindFlagTable(
+ cm::string_view toolsetName, cm::string_view table) const
{
- return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" +
- toolsetName + "_" + table + ".json";
+ if (!this->CustomFlagTableDir.empty()) {
+ std::string customFlagTableFile =
+ cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_',
+ toolsetName, '_', table, ".json");
+ if (cmSystemTools::FileExists(customFlagTableFile)) {
+ return customFlagTableFile;
+ }
+ customFlagTableFile =
+ cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_',
+ table, ".json");
+ if (cmSystemTools::FileExists(customFlagTableFile)) {
+ return customFlagTableFile;
+ }
+ }
+ std::string fullPath =
+ cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/MSBuild/FlagTables/",
+ toolsetName, '_', table, ".json");
+ if (cmSystemTools::FileExists(fullPath)) {
+ return fullPath;
+ }
+ return {};
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable(
- std::string const& optionsName, std::string const& toolsetName,
- std::string const& defaultName, std::string const& table) const
+ std::string const& toolSpecificName, std::string const& defaultName,
+ std::string const& table) const
{
- cmIDEFlagTable const* ret = nullptr;
+ cmMakefile* mf = this->GetCurrentMakefile();
std::string filename;
- if (!optionsName.empty()) {
- filename = cmGetFlagTableName(optionsName, table);
- ret = cmLoadFlagTableJson(filename);
+ if (!toolSpecificName.empty()) {
+ if (cm::optional<std::string> found =
+ this->FindFlagTable(toolSpecificName, table)) {
+ filename = std::move(*found);
+ } else {
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("JSON flag table for ", table,
+ " not found for toolset ", toolSpecificName));
+ return nullptr;
+ }
} else {
- filename = cmGetFlagTableName(toolsetName, table);
- if (cmSystemTools::FileExists(filename)) {
- ret = cmLoadFlagTableJson(filename);
+ std::string const& genericName =
+ this->CanonicalToolsetName(this->GetPlatformToolsetString());
+ cm::optional<std::string> found = this->FindFlagTable(genericName, table);
+ if (!found) {
+ found = this->FindFlagTable(defaultName, table);
+ }
+ if (found) {
+ filename = std::move(*found);
} else {
- filename = cmGetFlagTableName(defaultName, table);
- ret = cmLoadFlagTableJson(filename);
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("JSON flag table for ", table,
+ " not found for toolset ", genericName, " ",
+ defaultName));
+ return nullptr;
}
}
- if (!ret) {
- cmMakefile* mf = this->GetCurrentMakefile();
-
- std::ostringstream e;
- /* clang-format off */
- e << "JSON flag table \"" << filename <<
- "\" could not be loaded.\n";
- /* clang-format on */
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename)) {
+ return ret;
}
- return ret;
+
+ mf->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("JSON flag table could not be loaded:\n ", filename));
+ return nullptr;
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetClFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCLFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "CL");
+ return LoadFlagTable(this->GetClFlagTableName(),
+ this->DefaultCLFlagTableName, "CL");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable()
const
{
- std::string optionsName = this->ToolsetOptions.GetCSharpFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCSharpFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp");
+ return LoadFlagTable(this->GetCSharpFlagTableName(),
+ this->DefaultCSharpFlagTableName, "CSharp");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetRcFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultRCFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "RC");
+ return LoadFlagTable(this->GetRcFlagTableName(),
+ this->DefaultRCFlagTableName, "RC");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetLibFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultLibFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB");
+ return LoadFlagTable(this->GetLibFlagTableName(),
+ this->DefaultLibFlagTableName, "LIB");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetLinkFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultLinkFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "Link");
+ return LoadFlagTable(this->GetLinkFlagTableName(),
+ this->DefaultLinkFlagTableName, "Link");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const
{
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCudaFlagTableName);
- return LoadFlagTable("", toolsetName, defaultName, "Cuda");
+ return LoadFlagTable(std::string(), this->DefaultCudaFlagTableName, "Cuda");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable()
const
{
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultCudaHostFlagTableName);
- return LoadFlagTable("", toolsetName, defaultName, "CudaHost");
+ return LoadFlagTable(std::string(), this->DefaultCudaHostFlagTableName,
+ "CudaHost");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
{
- std::string optionsName = this->ToolsetOptions.GetMasmFlagTableName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultMasmFlagTableName);
- return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM");
+ return LoadFlagTable(this->GetMasmFlagTableName(),
+ this->DefaultMasmFlagTableName, "MASM");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
{
- std::string toolsetName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->GetPlatformToolsetString());
- std::string defaultName = this->ToolsetOptions.GetToolsetName(
- this->GetPlatformName(), this->DefaultNasmFlagTableName);
- return LoadFlagTable("", toolsetName, defaultName, "NASM");
+ return LoadFlagTable(std::string(), this->DefaultNasmFlagTableName, "NASM");
+}
+
+std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if (toolset == "v142") {
+ return "v142";
+ } else if (toolset == "v141") {
+ return "v141";
+ } else if (useToolset == "v140") {
+ return "v140";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if (useToolset == "v142") {
+ return "v142";
+ } else if (useToolset == "v141") {
+ return "v141";
+ } else if (useToolset == "v140") {
+ return "v140";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if (useToolset == "v142") {
+ return "v142";
+ } else if (useToolset == "v141") {
+ return "v141";
+ } else if (useToolset == "v140") {
+ return "v140";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName() const
+{
+ std::string const& toolset = this->GetPlatformToolsetString();
+ std::string const useToolset = this->CanonicalToolsetName(toolset);
+
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
+ } else if (useToolset == "v120") {
+ return "v12";
+ } else if (useToolset == "v110") {
+ return "v11";
+ } else if (useToolset == "v100") {
+ return "v10";
+ } else {
+ return "";
+ }
+}
+
+std::string cmGlobalVisualStudio10Generator::CanonicalToolsetName(
+ std::string const& toolset) const
+{
+ std::size_t length = toolset.length();
+
+ if (cmHasLiteralSuffix(toolset, "_xp")) {
+ length -= 3;
+ }
+
+ return toolset.substr(0, length);
}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 8d30ef8..2596720 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -5,8 +5,10 @@
#include <memory>
#include <set>
+#include <cm/optional>
+#include <cm/string_view>
+
#include "cmGlobalVisualStudio8Generator.h"
-#include "cmVisualStudio10ToolsetOptions.h"
/** \class cmGlobalVisualStudio10Generator
* \brief Write a Unix makefiles.
@@ -76,6 +78,13 @@ public:
const char* GetPlatformToolsetCudaCustomDir() const;
std::string const& GetPlatformToolsetCudaCustomDirString() const;
+ /** The nvcc subdirectory of a custom cuda install directory */
+ std::string const& GetPlatformToolsetCudaNvccSubdirString() const;
+
+ /** The visual studio integration subdirectory of a custom cuda install
+ * directory */
+ std::string const& GetPlatformToolsetCudaVSIntegrationSubdirString() const;
+
/** Return whether we need to use No/Debug instead of false/true
for GenerateDebugInformation. */
bool GetPlatformToolsetNeedsDebugEnum() const
@@ -176,8 +185,7 @@ protected:
std::string const& GetMSBuildCommand();
- cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName,
- std::string const& toolsetName,
+ cmIDEFlagTable const* LoadFlagTable(std::string const& toolSpecificName,
std::string const& defaultName,
std::string const& table) const;
@@ -187,6 +195,8 @@ protected:
std::string GeneratorToolsetCustomVCTargetsDir;
std::string GeneratorToolsetCuda;
std::string GeneratorToolsetCudaCustomDir;
+ std::string GeneratorToolsetCudaNvccSubdir;
+ std::string GeneratorToolsetCudaVSIntegrationSubdir;
std::string DefaultPlatformToolset;
std::string DefaultPlatformToolsetHostArchitecture;
std::string DefaultAndroidToolset;
@@ -230,7 +240,6 @@ private:
std::string MSBuildCommand;
bool MSBuildCommandInitialized;
- cmVisualStudio10ToolsetOptions ToolsetOptions;
std::set<std::string> AndroidExecutableWarnings;
virtual std::string FindMSBuildCommand();
std::string FindDevEnvCommand() override;
@@ -242,6 +251,19 @@ private:
bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
+ std::string GetClFlagTableName() const;
+ std::string GetCSharpFlagTableName() const;
+ std::string GetRcFlagTableName() const;
+ std::string GetLibFlagTableName() const;
+ std::string GetLinkFlagTableName() const;
+ std::string GetMasmFlagTableName() const;
+ std::string CanonicalToolsetName(std::string const& toolset) const;
+
+ cm::optional<std::string> FindFlagTable(cm::string_view toolsetName,
+ cm::string_view table) const;
+
+ std::string CustomFlagTableDir;
+
std::string CustomVCTargetsPath;
std::string VCTargetsPath;
bool FindVCTargetsPath(cmMakefile* mf);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index d6cc423..7dd1704 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -991,7 +991,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES),
*sf);
}
- lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true));
+ lg->AppendFlags(flags,
+ lg->GetIncludeFlags(includes, gtgt, lang, std::string()));
cmXCodeObject* buildFile =
this->CreateXCodeBuildFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf);
@@ -2695,7 +2696,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// GNU assembly files (#16449)
for (auto const& language : languages) {
std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags(
- includes, gtgt, language, true, false, configName);
+ includes, gtgt, language, configName);
if (!includeFlags.empty()) {
cflags[language] += " " + includeFlags;
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index bef785d..eb214fa 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -338,6 +338,7 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
// Add the names based on the current namelink mode.
if (haveNamelink) {
+ files.NamelinkMode = this->NamelinkMode;
// With a namelink we need to check the mode.
if (this->NamelinkMode == NamelinkModeOnly) {
// Install the namelink only.
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index 8c5d444..84fce42 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -39,7 +39,6 @@ public:
NamelinkModeSkip
};
void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; }
- NamelinkModeType GetNamelinkMode() const { return this->NamelinkMode; }
std::string GetInstallFilename(const std::string& config) const;
@@ -82,6 +81,7 @@ public:
// Prefix for all files in To.
std::string ToDir;
+ NamelinkModeType NamelinkMode = NamelinkModeNone;
bool NoTweak = false;
bool UseSourcePermissions = false;
cmInstallType Type = cmInstallType();
diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h
index a63347d..6690aef 100644
--- a/Source/cmJSONHelpers.h
+++ b/Source/cmJSONHelpers.h
@@ -239,7 +239,7 @@ cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail,
if (!filter(t)) {
continue;
}
- out.push_back(t);
+ out.push_back(std::move(t));
}
return success;
};
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index fdddb45..09cd88e 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -4,9 +4,7 @@
#include <algorithm>
#include <cassert>
-#include <cstddef>
#include <cstdio>
-#include <cstdlib> // required for atoi
#include <functional>
#include <iterator>
#include <set>
@@ -36,6 +34,42 @@
namespace {
+bool GetIndexArg(const std::string& arg, int* idx, cmMakefile& mf)
+{
+ long value;
+ if (!cmStrToLong(arg, &value)) {
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0121)) {
+ case cmPolicies::WARN: {
+ // Default is to warn and use old behavior OLD behavior is to allow
+ // compatibility, so issue a warning and use the previous behavior.
+ std::string warn =
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121),
+ " Invalid list index \"", arg, "\".");
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, warn);
+ break;
+ }
+ case cmPolicies::OLD:
+ // OLD behavior is to allow compatibility, so just ignore the
+ // situation.
+ break;
+ case cmPolicies::NEW:
+ return false;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ std::string msg =
+ cmStrCat(cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0121),
+ " Invalid list index \"", arg, "\".");
+ mf.IssueMessage(MessageType::FATAL_ERROR, msg);
+ break;
+ }
+ }
+
+ // Truncation is happening here, but it had always been happening here.
+ *idx = static_cast<int>(value);
+
+ return true;
+}
+
bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
std::string const& listName,
std::vector<std::string>& varArgsExpanded,
@@ -154,7 +188,11 @@ bool HandleGetCommand(std::vector<std::string> const& args,
const char* sep = "";
size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size() - 1; cc++) {
- int item = atoi(args[cc].c_str());
+ int item;
+ if (!GetIndexArg(args[cc], &item, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
+ return false;
+ }
value += sep;
sep = ";";
if (item < 0) {
@@ -362,7 +400,11 @@ bool HandleInsertCommand(std::vector<std::string> const& args,
const std::string& listName = args[1];
// expand the variable
- int item = atoi(args[2].c_str());
+ int item;
+ if (!GetIndexArg(args[2], &item, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
+ return false;
+ }
std::vector<std::string> varArgsExpanded;
if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
varArgsExpanded.empty()) &&
@@ -1282,8 +1324,16 @@ bool HandleSublistCommand(std::vector<std::string> const& args,
return true;
}
- const int start = atoi(args[2].c_str());
- const int length = atoi(args[3].c_str());
+ int start;
+ int length;
+ if (!GetIndexArg(args[2], &start, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
+ return false;
+ }
+ if (!GetIndexArg(args[3], &length, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[3], " is not a valid index"));
+ return false;
+ }
using size_type = decltype(varArgsExpanded)::size_type;
@@ -1338,7 +1388,11 @@ bool HandleRemoveAtCommand(std::vector<std::string> const& args,
std::vector<size_t> removed;
size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size(); ++cc) {
- int item = atoi(args[cc].c_str());
+ int item;
+ if (!GetIndexArg(args[cc], &item, status.GetMakefile())) {
+ status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
+ return false;
+ }
if (item < 0) {
item = static_cast<int>(nitem) + item;
}
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 1464a14..5c3a034 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -7,6 +7,10 @@
#include <sstream>
#include <utility>
+#ifdef _WIN32
+# include <cmsys/Encoding.hxx>
+#endif
+
#include "cmListFileLexer.h"
#include "cmMessageType.h"
#include "cmMessenger.h"
@@ -83,9 +87,15 @@ bool cmListFileParser::ParseFile(const char* filename)
{
this->FileName = filename;
+#ifdef _WIN32
+ std::string expandedFileName = cmsys::Encoding::ToNarrow(
+ cmSystemTools::ConvertToWindowsExtendedPath(filename));
+ filename = expandedFileName.c_str();
+#endif
+
// Open the file.
cmListFileLexer_BOM bom;
- if (!cmListFileLexer_SetFileName(this->Lexer, this->FileName, &bom)) {
+ if (!cmListFileLexer_SetFileName(this->Lexer, filename, &bom)) {
this->IssueFileOpenError("cmListFileCache: error can not open file.");
return false;
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 73b6fbc..b301c6e 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -838,16 +838,16 @@ cmProp cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
}
std::string cmLocalGenerator::ConvertToIncludeReference(
- std::string const& path, OutputFormat format, bool forceFullPaths)
+ std::string const& path, IncludePathStyle pathStyle, OutputFormat format)
{
- static_cast<void>(forceFullPaths);
+ static_cast<void>(pathStyle);
return this->ConvertToOutputForExisting(path, format);
}
std::string cmLocalGenerator::GetIncludeFlags(
- const std::vector<std::string>& includeDirs, cmGeneratorTarget* target,
- const std::string& lang, bool forceFullPaths, bool forResponseFile,
- const std::string& config)
+ std::vector<std::string> const& includeDirs, cmGeneratorTarget* target,
+ std::string const& lang, std::string const& config, bool forResponseFile,
+ IncludePathStyle pathStyle)
{
if (lang.empty()) {
return "";
@@ -923,7 +923,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
flagUsed = true;
}
std::string includePath =
- this->ConvertToIncludeReference(i, shellFormat, forceFullPaths);
+ this->ConvertToIncludeReference(i, pathStyle, shellFormat);
if (quotePaths && !includePath.empty() && includePath.front() != '\"') {
includeFlags << "\"";
}
@@ -1527,12 +1527,12 @@ void cmLocalGenerator::GetTargetFlags(
}
if (target->IsWin32Executable(config)) {
- exeFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
+ exeFlags += this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE"));
exeFlags += " ";
} else {
- exeFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
+ exeFlags += this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE"));
exeFlags += " ";
}
@@ -2701,8 +2701,9 @@ void cmLocalGenerator::CopyPchCompilePdb(
}
file << "foreach(retry RANGE 1 30)\n";
- file << " if (EXISTS \"" << from_file << "\" AND \"" << from_file
- << " \" IS_NEWER_THAN \"" << dest_file << "\")\n";
+ file << " if (EXISTS \"" << from_file << "\" AND (NOT EXISTS \""
+ << dest_file << "\" OR NOT \"" << dest_file << " \" IS_NEWER_THAN \""
+ << from_file << "\"))\n";
file << " execute_process(COMMAND ${CMAKE_COMMAND} -E copy";
file << " \"" << from_file << "\""
<< " \"" << to_dir << "\" RESULT_VARIABLE result "
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index e48849a..f597120 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -171,13 +171,19 @@ public:
cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
+
+ enum class IncludePathStyle
+ {
+ Default,
+ Absolute,
+ };
+
//! Get the include flags for the current makefile and language
- std::string GetIncludeFlags(const std::vector<std::string>& includes,
- cmGeneratorTarget* target,
- const std::string& lang,
- bool forceFullPaths = false,
- bool forResponseFile = false,
- const std::string& config = "");
+ std::string GetIncludeFlags(
+ std::vector<std::string> const& includes, cmGeneratorTarget* target,
+ std::string const& lang, std::string const& config,
+ bool forResponseFile = false,
+ IncludePathStyle pathStyle = IncludePathStyle::Default);
using GeneratorTargetVector =
std::vector<std::unique_ptr<cmGeneratorTarget>>;
@@ -256,11 +262,6 @@ public:
bool GetRealDependency(const std::string& name, const std::string& config,
std::string& dep);
- virtual std::string ConvertToIncludeReference(
- std::string const& path,
- cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL,
- bool forceFullPaths = false);
-
/** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {}
@@ -557,6 +558,13 @@ public:
cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop);
protected:
+ // The default implementation ignores the IncludePathStyle and always
+ // uses absolute paths. A generator may override this to use relative
+ // paths in some cases.
+ virtual std::string ConvertToIncludeReference(
+ std::string const& path, IncludePathStyle pathStyle,
+ cmOutputConverter::OutputFormat format);
+
//! put all the libraries for a target on into the given stream
void OutputLinkLibraries(cmComputeLinkInformation* pcli,
cmLinkLineComputer* linkLineComputer,
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 51ad993..c2a6410 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -97,9 +97,12 @@ void cmLocalNinjaGenerator::Generate()
// contains any non-ASCII characters and dependency checking will fail.
// As a workaround, leave the msvc_deps_prefix UTF-8 encoded even though
// the rest of the file is ANSI encoded.
- if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8) {
+ if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8 &&
+ this->GetGlobalGenerator()->GetMakefileEncoding() != codecvt::None) {
this->GetRulesFileStream().WriteRaw(showIncludesPrefix);
} else {
+ // Ninja 1.11 and above uses the UTF-8 code page if it's supported, so
+ // in that case we can write it normally without using raw bytes.
this->GetRulesFileStream() << showIncludesPrefix;
}
#else
@@ -202,10 +205,10 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
// Virtual protected methods.
std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
- std::string const& path, cmOutputConverter::OutputFormat format,
- bool forceFullPaths)
+ std::string const& path, IncludePathStyle pathStyle,
+ cmOutputConverter::OutputFormat format)
{
- if (forceFullPaths) {
+ if (pathStyle == IncludePathStyle::Absolute) {
return this->ConvertToOutputFormat(
cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()),
format);
@@ -667,7 +670,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
- std::string depfile = cc->GetDepfile();
+ std::string depfile = ccg.GetDepfile();
if (!depfile.empty()) {
switch (cc->GetCMP0116Status()) {
case cmPolicies::WARN:
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 5b850f3..8b6824f 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -12,6 +12,7 @@
#include "cmListFileCache.h"
#include "cmLocalCommonGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmNinjaTypes.h"
#include "cmOutputConverter.h"
@@ -91,9 +92,8 @@ public:
protected:
std::string ConvertToIncludeReference(
- std::string const& path,
- cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL,
- bool forceFullPaths = false) override;
+ std::string const& path, IncludePathStyle pathStyle,
+ cmOutputConverter::OutputFormat format) override;
private:
cmGeneratedFileStream& GetImplFileStream(const std::string& config) const;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 78cae0e..40a67a3 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1222,7 +1222,7 @@ void cmMakefile::AddCustomCommandOldStyle(
// Each output must get its own copy of this rule.
cmsys::RegularExpression sourceFiles(
- "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|cu|m|mm|"
+ "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|ixx|cppm|cu|m|mm|"
"rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
"hm|hpp|hxx|in|txx|inl)$");
@@ -4393,7 +4393,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
// Deprecate old policies, especially those that require a lot
// of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0075 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 1750e37..6783341 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -384,11 +384,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
if (this->GeneratorTarget->IsWin32Executable(
this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) {
this->LocalGenerator->AppendFlags(
- linkFlags, this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"));
+ linkFlags,
+ this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE")));
} else {
this->LocalGenerator->AppendFlags(
linkFlags,
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"));
+ this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE")));
}
// Add symbol export flags if necessary.
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index ce64e2c..5e4f03d 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -780,9 +780,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.Target = target.c_str();
vars.LinkLibraries = linkLibs.c_str();
vars.ObjectsQuoted = buildObjs.c_str();
+ std::string targetOutSOName;
if (this->GeneratorTarget->HasSOName(this->GetConfigName())) {
vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
- vars.TargetSOName = this->TargetNames.SharedObject.c_str();
+ targetOutSOName = this->LocalGenerator->ConvertToOutputFormat(
+ this->TargetNames.SharedObject.c_str(), cmOutputConverter::SHELL);
+ vars.TargetSOName = targetOutSOName.c_str();
}
vars.LinkFlags = linkFlags.c_str();
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 4918bf6..fa469ed 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -854,7 +854,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
vars.Defines = definesString.c_str();
std::string includesString = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, lang, true, false, config);
+ includes, this->GeneratorTarget, lang, config);
this->LocalGenerator->AppendFlags(includesString,
"$(" + lang + "_INCLUDES)");
vars.Includes = includesString.c_str();
@@ -2195,8 +2195,8 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
lang, this->GetConfigName());
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, lang, false, useResponseFile,
- this->GetConfigName());
+ includes, this->GeneratorTarget, lang, this->GetConfigName(),
+ useResponseFile);
if (includeFlags.empty()) {
return;
}
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 49e5e4c..1d511f2 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -868,7 +868,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
if (genTarget->HasSOName(config)) {
vars["SONAME_FLAG"] =
this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config));
- vars["SONAME"] = tgtNames.SharedObject;
+ vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject,
+ cmOutputConverter::SHELL);
if (genTarget->GetType() == cmStateEnums::SHARED_LIBRARY) {
std::string install_dir =
this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config);
@@ -1176,7 +1177,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
}
if (gt->HasSOName(config)) {
vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config));
- vars["SONAME"] = tgtNames.SharedObject;
+ vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject,
+ cmOutputConverter::SHELL);
if (targetType == cmStateEnums::SHARED_LIBRARY) {
std::string install_dir = gt->GetInstallNameDirForBuildTree(config);
if (!install_dir.empty()) {
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 672b579..2e0ffdb 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -263,9 +263,10 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
language, config);
// Add include directory flags.
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, language,
- language == "RC", // full include paths for RC needed by cmcldeps
- false, config);
+ includes, this->GeneratorTarget, language, config, false,
+ // full include paths for RC needed by cmcldeps
+ language == "RC" ? cmLocalGenerator::IncludePathStyle::Absolute
+ : cmLocalGenerator::IncludePathStyle::Default);
if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
}
@@ -324,7 +325,8 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
}
std::string includesString = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, language, true, false, config);
+ includes, this->GeneratorTarget, language, config, false,
+ cmLocalGenerator::IncludePathStyle::Absolute);
this->LocalGenerator->AppendFlags(includesString,
this->GetIncludes(language, config));
@@ -1379,8 +1381,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmSystemTools::GetParentDirectory(source->GetFullPath()));
std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags(
- sourceDirectory, this->GeneratorTarget, language, false, false,
- config);
+ sourceDirectory, this->GeneratorTarget, language, config, false,
+ cmLocalGenerator::IncludePathStyle::Default);
vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]);
}
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 0369af0..68f40a9 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -359,7 +359,7 @@ void cmOrderDirectories::SetLinkExtensionInfo(
std::string const& removeExtRegex)
{
this->LinkExtensions = linkExtensions;
- this->RemoveLibraryExtension.compile(removeExtRegex.c_str());
+ this->RemoveLibraryExtension.compile(removeExtRegex);
}
void cmOrderDirectories::CollectOriginalDirectories()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 2194b0f..d546b6e 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -359,7 +359,14 @@ class cmMakefile;
3, 20, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0120, \
"The WriteCompilerDetectionHeader module is removed.", 3, 20, 0, \
- cmPolicies::WARN)
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0121, \
+ "The list() command now validates parsing of index arguments.", 3, \
+ 21, 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0122, \
+ "UseSWIG use standard library name conventions for csharp language.", 3, \
+ 21, 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/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index ed32de9..acdb09f 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -59,6 +59,11 @@ bool cmProjectCommand(std::vector<std::string> const& args,
mf.AddDefinition("PROJECT_NAME", projectName);
+ mf.AddDefinitionBool("PROJECT_IS_TOP_LEVEL", mf.IsRootMakefile());
+ mf.AddCacheDefinition(projectName + "_IS_TOP_LEVEL",
+ mf.IsRootMakefile() ? "ON" : "OFF",
+ "Value Computed by CMake", cmStateEnums::STATIC);
+
// Set the CMAKE_PROJECT_NAME variable to be the highest-level
// project name in the tree. If there are two project commands
// in the same CMakeLists.txt file, and it is the top level
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index a1816f1..3adeb1a 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -294,6 +294,17 @@ bool InfoWriter::Save(std::string const& filename)
return fileStream.Close();
}
+void AddAutogenExecutableToDependencies(
+ cmQtAutoGenInitializer::GenVarsT const& genVars,
+ std::vector<std::string>& dependencies)
+{
+ if (genVars.ExecutableTarget != nullptr) {
+ dependencies.push_back(genVars.ExecutableTarget->Target->GetName());
+ } else if (!genVars.Executable.empty()) {
+ dependencies.push_back(genVars.Executable);
+ }
+}
+
} // End of unnamed namespace
cmQtAutoGenInitializer::cmQtAutoGenInitializer(
@@ -419,12 +430,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
// Include directory
- this->ConfigFileNames(this->Dir.Include,
- cmStrCat(this->Dir.Build, "/include"), "");
- this->Dir.IncludeGenExp = this->Dir.Include.Default;
- if (this->MultiConfig) {
- this->Dir.IncludeGenExp += "_$<CONFIG>";
- }
+ this->ConfigFileNamesAndGenex(this->Dir.Include, this->Dir.IncludeGenExp,
+ cmStrCat(this->Dir.Build, "/include"), "");
}
// Moc, Uic and _autogen target settings
@@ -575,15 +582,9 @@ bool cmQtAutoGenInitializer::InitMoc()
cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;
} else {
- this->ConfigFileNames(this->Moc.CompilationFile,
- cmStrCat(this->Dir.Build, "/mocs_compilation"),
- ".cpp");
- if (this->MultiConfig) {
- this->Moc.CompilationFileGenex =
- cmStrCat(this->Dir.Build, "/mocs_compilation_$<CONFIG>.cpp"_s);
- } else {
- this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;
- }
+ this->ConfigFileNamesAndGenex(
+ this->Moc.CompilationFile, this->Moc.CompilationFileGenex,
+ cmStrCat(this->Dir.Build, "/mocs_compilation"_s), ".cpp"_s);
}
// Moc predefs
@@ -935,9 +936,35 @@ bool cmQtAutoGenInitializer::InitScanFiles()
if (!skipUic) {
// Check if the .ui file has uic options
std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
- if (!uicOpts.empty()) {
- this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts));
+ if (uicOpts.empty()) {
+ this->Uic.UiFilesNoOptions.emplace_back(fullPath);
+ } else {
+ this->Uic.UiFilesWithOptions.emplace_back(fullPath,
+ cmExpandedList(uicOpts));
}
+
+ auto uiHeaderRelativePath = cmSystemTools::RelativePath(
+ this->LocalGen->GetCurrentSourceDirectory(),
+ cmSystemTools::GetFilenamePath(fullPath));
+
+ // Avoid creating a path containing adjacent slashes
+ if (!uiHeaderRelativePath.empty() &&
+ uiHeaderRelativePath.back() != '/') {
+ uiHeaderRelativePath += '/';
+ }
+
+ auto uiHeaderFilePath = cmStrCat(
+ '/', uiHeaderRelativePath, "ui_"_s,
+ cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s);
+
+ ConfigString uiHeader;
+ std::string uiHeaderGenex;
+ this->ConfigFileNamesAndGenex(
+ uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s),
+ uiHeaderFilePath);
+
+ this->Uic.UiHeaders.emplace_back(
+ std::make_pair(uiHeader, uiHeaderGenex));
} else {
// Register skipped .ui file
this->Uic.SkipUi.insert(fullPath);
@@ -1091,6 +1118,13 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
autogenByproducts.push_back(this->Moc.CompilationFileGenex);
}
+ if (this->Uic.Enabled) {
+ for (const auto& file : this->Uic.UiHeaders) {
+ this->AddGeneratedSource(file.first, this->Uic);
+ autogenByproducts.push_back(file.second);
+ }
+ }
+
// Compose target comment
std::string autogenComment;
{
@@ -1149,6 +1183,42 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
this->Makefile);
}
+ if (!this->Uic.UiFilesNoOptions.empty() ||
+ !this->Uic.UiFilesWithOptions.empty()) {
+ // Add a generated timestamp file
+ ConfigString timestampFile;
+ std::string timestampFileGenex;
+ ConfigFileNamesAndGenex(timestampFile, timestampFileGenex,
+ cmStrCat(this->Dir.Build, "/autouic"_s),
+ ".stamp"_s);
+ this->AddGeneratedSource(timestampFile, this->Uic);
+
+ // Add a step in the pre-build command to touch the timestamp file
+ commandLines.push_back(
+ cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "touch",
+ timestampFileGenex }));
+
+ // UIC needs to be re-run if any of the known UI files change or the
+ // executable itself has been updated
+ auto uicDependencies = this->Uic.UiFilesNoOptions;
+ for (auto const& uiFile : this->Uic.UiFilesWithOptions) {
+ uicDependencies.push_back(uiFile.first);
+ }
+ AddAutogenExecutableToDependencies(this->Uic, uicDependencies);
+
+ // Add a rule file to cause the target to build if a dependency has
+ // changed, which will trigger the pre-build command to run autogen
+ std::string no_main_dependency;
+ cmCustomCommandLines no_command_lines;
+ this->LocalGen->AddCustomCommandToOutput(
+ timestampFileGenex, uicDependencies, no_main_dependency,
+ no_command_lines, /*comment=*/"", this->Dir.Work.c_str(),
+ /*cmp0116=*/cmPolicies::NEW, /*replace=*/false,
+ /*escapeOldStyle=*/false, /*uses_terminal=*/false,
+ /*command_expand_lists=*/false, /*depfile=*/"", /*job_pool=*/"",
+ stdPipesUTF8);
+ }
+
// Add the pre-build command directly to bypass the OBJECT_LIBRARY
// rejection in cmMakefile::AddCustomCommandToTarget because we know
// PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
@@ -1241,16 +1311,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
dependencies.clear();
dependencies.push_back(timestampTargetName);
- if (this->Moc.ExecutableTarget != nullptr) {
- dependencies.push_back(this->Moc.ExecutableTarget->Target->GetName());
- } else if (!this->Moc.Executable.empty()) {
- dependencies.push_back(this->Moc.Executable);
- }
- if (this->Uic.ExecutableTarget != nullptr) {
- dependencies.push_back(this->Uic.ExecutableTarget->Target->GetName());
- } else if (!this->Uic.Executable.empty()) {
- dependencies.push_back(this->Uic.Executable);
- }
+ AddAutogenExecutableToDependencies(this->Moc, dependencies);
+ AddAutogenExecutableToDependencies(this->Uic, dependencies);
// Create the custom command that outputs the timestamp file.
const char timestampFileName[] = "timestamp";
@@ -1589,7 +1651,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());
info.SetArray("UIC_SKIP", uic_skip);
- info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFiles,
+ info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFilesWithOptions,
[](Json::Value& jval, UicT::UiFileT const& uiFile) {
jval.resize(2u);
jval[0u] = uiFile.first;
@@ -1749,6 +1811,18 @@ void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
}
}
+void cmQtAutoGenInitializer::ConfigFileNamesAndGenex(
+ ConfigString& configString, std::string& genex, cm::string_view const prefix,
+ cm::string_view const suffix)
+{
+ this->ConfigFileNames(configString, prefix, suffix);
+ if (this->MultiConfig) {
+ genex = cmStrCat(prefix, "_$<CONFIG>"_s, suffix);
+ } else {
+ genex = configString.Default;
+ }
+}
+
void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString)
{
this->AddCleanFile(configString.Default);
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index f7e126d..8a6d8f9 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -141,6 +141,8 @@ private:
void ConfigFileNames(ConfigString& configString, cm::string_view prefix,
cm::string_view suffix);
+ void ConfigFileNamesAndGenex(ConfigString& configString, std::string& genex,
+ cm::string_view prefix, cm::string_view suffix);
void ConfigFileClean(ConfigString& configString);
std::string GetMocBuildPath(MUFile const& muf);
@@ -236,9 +238,12 @@ private:
: GenVarsT(GenT::UIC){};
std::set<std::string> SkipUi;
- std::vector<UiFileT> UiFiles;
+ std::vector<std::string> UiFilesNoOptions;
+ std::vector<UiFileT> UiFilesWithOptions;
ConfigStrings<std::vector<std::string>> Options;
std::vector<std::string> SearchPaths;
+ std::vector<std::pair<ConfigString /*ui header*/, std::string /*genex*/>>
+ UiHeaders;
} Uic;
/** rcc variables. */
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 535f786..c32c965 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -1589,14 +1589,14 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
};
// Vicinity of the source
- if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) {
- return true;
- }
if (!includePrefix.empty()) {
if (findUi(cmStrCat(sourceDirPrefix, includePrefix, this->UiName))) {
return true;
}
}
+ if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) {
+ return true;
+ }
// Additional AUTOUIC search paths
auto const& searchPaths = this->UicConst().SearchPaths;
if (!searchPaths.empty()) {
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 76a5ded..32ed687 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -175,7 +175,7 @@ private:
#define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$"
#define CM_SOURCE_REGEX \
- "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \
+ "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|ixx|cppm|cu|f|f90|for|fpp|ftn|m|mm|" \
"rc|def|r|odl|idl|hpj|bat)$"
#define CM_PCH_REGEX "cmake_pch(_[^.]+)?\\.(h|hxx)$"
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index bf6925e..280e508 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -308,8 +308,9 @@ struct StanardLevelComputer
std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
{
{ "C",
- StanardLevelComputer{ "C", std::vector<int>{ 90, 99, 11 },
- std::vector<std::string>{ "90", "99", "11" } } },
+ StanardLevelComputer{
+ "C", std::vector<int>{ 90, 99, 11, 17, 23 },
+ std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "CXX",
StanardLevelComputer{
"CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index 1e20abb..fbf47ef 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -16,16 +16,9 @@
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStatePrivate.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
-#if !defined(_WIN32)
-# include <sys/utsname.h>
-#endif
-
-#if defined(__CYGWIN__)
-# include "cmSystemTools.h"
-#endif
-
cmStateSnapshot::cmStateSnapshot(cmState* state)
: State(state)
{
@@ -292,34 +285,26 @@ void InitializeContentFromParent(T& parentContent, T& thisContent,
void cmStateSnapshot::SetDefaultDefinitions()
{
-/* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
- With CMake must separate between target and host platform. In most cases
- the tests for WIN32, UNIX and APPLE will be for the target system, so an
- additional set of variables for the host system is required ->
- CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
- WIN32, UNIX and APPLE are now set in the platform files in
- Modules/Platforms/.
- To keep cmake scripts (-P) and custom language and compiler modules
- working, these variables are still also set here in this place, but they
- will be reset in CMakeSystemSpecificInformation.cmake before the platform
- files are executed. */
-#if defined(_WIN32)
- this->SetDefinition("WIN32", "1");
- this->SetDefinition("CMAKE_HOST_WIN32", "1");
- this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows");
-#else
- this->SetDefinition("UNIX", "1");
- this->SetDefinition("CMAKE_HOST_UNIX", "1");
-
-# if defined(__ANDROID__)
- this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Android");
-# else
- struct utsname uts_name;
- if (uname(&uts_name) >= 0) {
- this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname);
+ /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
+ With CMake must separate between target and host platform. In most cases
+ the tests for WIN32, UNIX and APPLE will be for the target system, so an
+ additional set of variables for the host system is required ->
+ CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
+ WIN32, UNIX and APPLE are now set in the platform files in
+ Modules/Platforms/.
+ To keep cmake scripts (-P) and custom language and compiler modules
+ working, these variables are still also set here in this place, but they
+ will be reset in CMakeSystemSpecificInformation.cmake before the platform
+ files are executed. */
+ cm::string_view hostSystemName = cmSystemTools::GetSystemName();
+ this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName);
+ if (hostSystemName == "Windows") {
+ this->SetDefinition("WIN32", "1");
+ this->SetDefinition("CMAKE_HOST_WIN32", "1");
+ } else {
+ this->SetDefinition("UNIX", "1");
+ this->SetDefinition("CMAKE_HOST_UNIX", "1");
}
-# endif
-#endif
#if defined(__CYGWIN__)
std::string legacy;
if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) &&
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 23fc3e0..5fa309d 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -241,7 +241,7 @@ bool RegexMatch(std::vector<std::string> const& args,
status.GetMakefile().ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
- if (!re.compile(regex.c_str())) {
+ if (!re.compile(regex)) {
std::string e =
"sub-command REGEX, mode MATCH failed to compile regex \"" + regex +
"\".";
@@ -283,7 +283,7 @@ bool RegexMatchAll(std::vector<std::string> const& args,
status.GetMakefile().ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
- if (!re.compile(regex.c_str())) {
+ if (!re.compile(regex)) {
std::string e =
"sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex +
"\".";
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index c1ce7ec..3a438fd 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -86,6 +86,7 @@
# include <unistd.h>
# include <sys/time.h>
+# include <sys/types.h>
#endif
#if defined(_WIN32) && \
@@ -101,6 +102,10 @@
# include <malloc.h> /* for malloc/free on QNX */
#endif
+#if !defined(_WIN32) && !defined(__ANDROID__)
+# include <sys/utsname.h>
+#endif
+
namespace {
cmSystemTools::InterruptCallback s_InterruptCallback;
@@ -148,6 +153,27 @@ static int cm_archive_read_open_file(struct archive* a, const char* file,
# define environ (*_NSGetEnviron())
#endif
+namespace {
+void ReportError(std::string* err)
+{
+ if (!err) {
+ return;
+ }
+#ifdef _WIN32
+ LPSTR message = NULL;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, NULL);
+ *err = std::string(message, size);
+ LocalFree(message);
+#else
+ *err = strerror(errno);
+#endif
+}
+}
+
bool cmSystemTools::s_RunCommandHideConsole = false;
bool cmSystemTools::s_DisableRunCommandOutput = false;
bool cmSystemTools::s_ErrorOccured = false;
@@ -951,21 +977,79 @@ void cmSystemTools::InitializeLibUV()
#ifdef _WIN32
namespace {
-bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname)
+bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname,
+ cmSystemTools::Replace replace)
{
// Not only ignore any previous error, but clear any memory of it.
SetLastError(0);
- // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file.
- return MoveFileExW(oldname.c_str(), newname.c_str(),
- MOVEFILE_REPLACE_EXISTING);
+ DWORD flags = 0;
+ if (replace == cmSystemTools::Replace::Yes) {
+ // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file.
+ flags = flags | MOVEFILE_REPLACE_EXISTING;
+ }
+
+ return MoveFileExW(oldname.c_str(), newname.c_str(), flags);
}
}
#endif
+bool cmSystemTools::CopySingleFile(const std::string& oldname,
+ const std::string& newname)
+{
+ return cmSystemTools::CopySingleFile(oldname, newname, CopyWhen::Always) ==
+ CopyResult::Success;
+}
+
+cmSystemTools::CopyResult cmSystemTools::CopySingleFile(
+ std::string const& oldname, std::string const& newname, CopyWhen when,
+ std::string* err)
+{
+ switch (when) {
+ case CopyWhen::Always:
+ break;
+ case CopyWhen::OnlyIfDifferent:
+ if (!FilesDiffer(oldname, newname)) {
+ return CopyResult::Success;
+ }
+ break;
+ }
+
+ mode_t perm = 0;
+ bool perms = SystemTools::GetPermissions(oldname, perm);
+
+ // If files are the same do not copy
+ if (SystemTools::SameFile(oldname, newname)) {
+ return CopyResult::Success;
+ }
+
+ if (!cmsys::SystemTools::CloneFileContent(oldname, newname)) {
+ // if cloning did not succeed, fall back to blockwise copy
+ if (!cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname)) {
+ ReportError(err);
+ return CopyResult::Failure;
+ }
+ }
+ if (perms) {
+ if (!SystemTools::SetPermissions(newname, perm)) {
+ ReportError(err);
+ return CopyResult::Failure;
+ }
+ }
+ return CopyResult::Success;
+}
+
bool cmSystemTools::RenameFile(const std::string& oldname,
const std::string& newname)
{
+ return cmSystemTools::RenameFile(oldname, newname, Replace::Yes) ==
+ RenameResult::Success;
+}
+
+cmSystemTools::RenameResult cmSystemTools::RenameFile(
+ std::string const& oldname, std::string const& newname, Replace replace,
+ std::string* err)
+{
#ifdef _WIN32
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
@@ -987,7 +1071,7 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
oldname_wstr, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
DWORD move_last_error = 0;
- while (!cmMoveFile(oldname_wstr, newname_wstr) && --retry.Count) {
+ while (!cmMoveFile(oldname_wstr, newname_wstr, replace) && --retry.Count) {
move_last_error = GetLastError();
// There was no error ==> the operation is not yet complete.
@@ -1003,7 +1087,11 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
// 3) Windows Explorer has an associated directory already opened.
if (move_last_error != ERROR_ACCESS_DENIED &&
move_last_error != ERROR_SHARING_VIOLATION) {
- return false;
+ if (replace == Replace::No && move_last_error == ERROR_ALREADY_EXISTS) {
+ return RenameResult::NoReplace;
+ }
+ ReportError(err);
+ return RenameResult::Failure;
}
DWORD const attrs = GetFileAttributesW(newname_wstr.c_str());
@@ -1027,10 +1115,31 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
save_restore_file_attributes.SetPath(newname_wstr);
}
SetLastError(move_last_error);
- return retry.Count > 0;
+ if (retry.Count > 0) {
+ return RenameResult::Success;
+ }
+ if (replace == Replace::No && GetLastError() == ERROR_ALREADY_EXISTS) {
+ return RenameResult::NoReplace;
+ }
+ ReportError(err);
+ return RenameResult::Failure;
#else
- /* On UNIX we have an OS-provided call to do this atomically. */
- return rename(oldname.c_str(), newname.c_str()) == 0;
+ // On UNIX we have OS-provided calls to create 'newname' atomically.
+ if (replace == Replace::No) {
+ if (link(oldname.c_str(), newname.c_str()) == 0) {
+ return RenameResult::Success;
+ }
+ if (errno == EEXIST) {
+ return RenameResult::NoReplace;
+ }
+ ReportError(err);
+ return RenameResult::Failure;
+ }
+ if (rename(oldname.c_str(), newname.c_str()) == 0) {
+ return RenameResult::Success;
+ }
+ ReportError(err);
+ return RenameResult::Failure;
#endif
}
@@ -3101,3 +3210,46 @@ bool cmSystemTools::CreateLink(const std::string& origName,
return true;
}
+
+cm::string_view cmSystemTools::GetSystemName()
+{
+#if defined(_WIN32)
+ return "Windows";
+#elif defined(__ANDROID__)
+ return "Android";
+#else
+ static struct utsname uts_name;
+ static bool initialized = false;
+ static cm::string_view systemName;
+ if (initialized) {
+ return systemName;
+ }
+ if (uname(&uts_name) >= 0) {
+ initialized = true;
+ systemName = uts_name.sysname;
+
+ if (cmIsOff(systemName)) {
+ systemName = "UnknownOS";
+ }
+
+ // fix for BSD/OS, remove the /
+ static const cmsys::RegularExpression bsdOsRegex("BSD.OS");
+ cmsys::RegularExpressionMatch match;
+ if (bsdOsRegex.find(uts_name.sysname, match)) {
+ systemName = "BSDOS";
+ }
+
+ // fix for GNU/kFreeBSD, remove the GNU/
+ if (systemName.find("kFreeBSD") != cm::string_view::npos) {
+ systemName = "kFreeBSD";
+ }
+
+ // fix for CYGWIN which has windows version in it
+ if (systemName.find("CYGWIN") != cm::string_view::npos) {
+ systemName = "CYGWIN";
+ }
+ return systemName;
+ }
+ return "";
+#endif
+}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 5bbbb0c..5620899 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -128,10 +128,43 @@ public:
static bool SimpleGlob(const std::string& glob,
std::vector<std::string>& files, int type = 0);
+ enum class CopyWhen
+ {
+ Always,
+ OnlyIfDifferent,
+ };
+ enum class CopyResult
+ {
+ Success,
+ Failure,
+ };
+
+ /** Copy a file. */
+ static bool CopySingleFile(const std::string& oldname,
+ const std::string& newname);
+ static CopyResult CopySingleFile(std::string const& oldname,
+ std::string const& newname, CopyWhen when,
+ std::string* err = nullptr);
+
+ enum class Replace
+ {
+ Yes,
+ No,
+ };
+ enum class RenameResult
+ {
+ Success,
+ NoReplace,
+ Failure,
+ };
+
/** Rename a file or directory within a single disk volume (atomic
if possible). */
static bool RenameFile(const std::string& oldname,
const std::string& newname);
+ static RenameResult RenameFile(std::string const& oldname,
+ std::string const& newname, Replace replace,
+ std::string* err = nullptr);
//! Rename a file if contents are different, delete the source otherwise
static void MoveFileIfDifferent(const std::string& source,
@@ -465,6 +498,9 @@ public:
const std::string& newName,
std::string* errorMessage = nullptr);
+ /** Get the system name. */
+ static cm::string_view GetSystemName();
+
private:
static bool s_ForceUnixPaths;
static bool s_RunCommandHideConsole;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 965ac3e..0255d60 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -545,7 +545,7 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element(
"CudaToolkitCustomDir",
this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() +
- "nvcc");
+ this->GlobalGenerator->GetPlatformToolsetCudaNvccSubdirString());
}
}
@@ -654,8 +654,9 @@ void cmVisualStudio10TargetGenerator::Generate()
std::string cudaPath = customDir.empty()
? "$(VCTargetsPath)\\BuildCustomizations\\"
: customDir +
- "CUDAVisualStudioIntegration\\extras\\"
- "visual_studio_integration\\MSBuildExtensions\\";
+ this->GlobalGenerator
+ ->GetPlatformToolsetCudaVSIntegrationSubdirString() +
+ "extras\\visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
std::move(cudaPath) + "CUDA " +
@@ -747,8 +748,9 @@ void cmVisualStudio10TargetGenerator::Generate()
std::string cudaPath = customDir.empty()
? "$(VCTargetsPath)\\BuildCustomizations\\"
: customDir +
- "CUDAVisualStudioIntegration\\extras\\"
- "visual_studio_integration\\MSBuildExtensions\\";
+ this->GlobalGenerator
+ ->GetPlatformToolsetCudaVSIntegrationSubdirString() +
+ "extras\\visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
std::move(cudaPath) + "CUDA " +
diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx
deleted file mode 100644
index 7fc33e6..0000000
--- a/Source/cmVisualStudio10ToolsetOptions.cxx
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmVisualStudio10ToolsetOptions.h"
-
-#include "cmAlgorithms.h"
-#include "cmIDEFlagTable.h"
-#include "cmVisualStudioGeneratorOptions.h"
-
-std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if (toolset == "v142") {
- return "v142";
- } else if (toolset == "v141") {
- return "v141";
- } else if (useToolset == "v140") {
- return "v140";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if (useToolset == "v142") {
- return "v142";
- } else if (useToolset == "v141") {
- return "v141";
- } else if (useToolset == "v140") {
- return "v140";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if ((useToolset == "v140") || (useToolset == "v141") ||
- (useToolset == "v142")) {
- return "v14";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if ((useToolset == "v140") || (useToolset == "v141") ||
- (useToolset == "v142")) {
- return "v14";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if (useToolset == "v142") {
- return "v142";
- } else if (useToolset == "v141") {
- return "v141";
- } else if (useToolset == "v140") {
- return "v140";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName(
- std::string const& name, std::string const& toolset) const
-{
- std::string const useToolset = this->GetToolsetName(name, toolset);
-
- if ((useToolset == "v140") || (useToolset == "v141") ||
- (useToolset == "v142")) {
- return "v14";
- } else if (useToolset == "v120") {
- return "v12";
- } else if (useToolset == "v110") {
- return "v11";
- } else if (useToolset == "v100") {
- return "v10";
- } else {
- return "";
- }
-}
-
-std::string cmVisualStudio10ToolsetOptions::GetToolsetName(
- std::string const& name, std::string const& toolset) const
-{
- static_cast<void>(name);
- std::size_t length = toolset.length();
-
- if (cmHasLiteralSuffix(toolset, "_xp")) {
- length -= 3;
- }
-
- return toolset.substr(0, length);
-}
diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h
deleted file mode 100644
index 85cc2b6..0000000
--- a/Source/cmVisualStudio10ToolsetOptions.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-
-/** \class cmVisualStudio10ToolsetOptions
- * \brief Retrieves toolset options for MSBuild.
- *
- * cmVisualStudio10ToolsetOptions manages toolsets within MSBuild
- */
-class cmVisualStudio10ToolsetOptions
-{
-public:
- std::string GetClFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetCSharpFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetRcFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetLibFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetLinkFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetMasmFlagTableName(std::string const& name,
- std::string const& toolset) const;
- std::string GetToolsetName(std::string const& name,
- std::string const& toolset) const;
-};
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 4b57395..1d4bbf4 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -28,6 +28,7 @@
#include "cm_sys_stat.h"
+#include "cmCMakePath.h"
#include "cmCMakePresetsFile.h"
#include "cmCommandLineArgument.h"
#include "cmCommands.h"
@@ -208,9 +209,9 @@ cmake::cmake(Role role, cmState::Mode mode)
};
// The "c" extension MUST precede the "C" extension.
- setupExts(
- this->CLikeSourceFileExtensions,
- { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M", "mm" });
+ setupExts(this->CLikeSourceFileExtensions,
+ { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M",
+ "mm", "ixx", "cppm" });
setupExts(this->HeaderFileExtensions,
{ "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" });
setupExts(this->CudaFileExtensions, { "cu" });
@@ -493,6 +494,21 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
return true;
};
+ auto PrefixLambda = [&](std::string const& path, cmake* state) -> bool {
+ const std::string var = "CMAKE_INSTALL_PREFIX";
+ cmStateEnums::CacheEntryType type = cmStateEnums::PATH;
+ cmCMakePath absolutePath(path);
+ if (absolutePath.IsAbsolute()) {
+#ifndef CMAKE_BOOTSTRAP
+ state->UnprocessedPresetVariables.erase(var);
+#endif
+ state->ProcessCacheArg(var, path, type);
+ return true;
+ }
+ cmSystemTools::Error("Absolute paths are required for --install-prefix");
+ return false;
+ };
+
std::vector<CommandArgument> arguments = {
CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
CommandArgument::Values::One, DefineLambda },
@@ -511,8 +527,12 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
state->ReadListFile(args, path);
return true;
} },
+
CommandArgument{ "-P", "-P must be followed by a file name.",
CommandArgument::Values::One, ScriptLambda },
+ CommandArgument{ "--install-prefix",
+ "No install directory specified for --install-prefix",
+ CommandArgument::Values::One, PrefixLambda },
CommandArgument{ "--find-package", CommandArgument::Values::Zero,
[&](std::string const&, cmake*) -> bool {
findPackageMode = true;
@@ -649,7 +669,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
this->GlobalGenerator->CreateGenerationObjects();
const auto& lg = this->GlobalGenerator->LocalGenerators[0];
std::string includeFlags =
- lg->GetIncludeFlags(includeDirs, nullptr, language);
+ lg->GetIncludeFlags(includeDirs, nullptr, language, std::string());
std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
@@ -815,6 +835,9 @@ void cmake::SetArgs(const std::vector<std::string>& args)
CommandArgument::Values::One, PlatformLambda },
CommandArgument{ "-T", "No toolset specified for -T",
CommandArgument::Values::One, ToolsetLamda },
+ CommandArgument{ "--install-prefix",
+ "No install directory specified for --install-prefix",
+ CommandArgument::Values::One, IgnoreAndTrueLambda },
CommandArgument{ "--check-build-system", CommandArgument::Values::Two,
[](std::string const& value, cmake* state) -> bool {
@@ -1194,11 +1217,17 @@ void cmake::SetArgs(const std::vector<std::string>& args)
"\": Invalid macro expansion"));
return;
}
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Could not use disabled preset \"",
+ preset->second.Unexpanded.Name, "\""));
+ return;
+ }
- if (!this->State->IsCacheLoaded() && !haveBArg) {
+ if (!this->State->IsCacheLoaded() && !haveBArg &&
+ !expandedPreset->BinaryDir.empty()) {
this->SetHomeOutputDirectory(expandedPreset->BinaryDir);
}
- if (!this->GlobalGenerator) {
+ if (!this->GlobalGenerator && !expandedPreset->Generator.empty()) {
if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator,
false)) {
return;
@@ -1207,6 +1236,14 @@ void cmake::SetArgs(const std::vector<std::string>& args)
this->UnprocessedPresetVariables = expandedPreset->CacheVariables;
this->UnprocessedPresetEnvironment = expandedPreset->Environment;
+ if (!expandedPreset->InstallDir.empty() &&
+ this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX") ==
+ nullptr) {
+ this->UnprocessedPresetVariables["CMAKE_INSTALL_PREFIX"] = {
+ "PATH", expandedPreset->InstallDir
+ };
+ }
+
if (!expandedPreset->ArchitectureStrategy ||
expandedPreset->ArchitectureStrategy ==
cmCMakePresetsFile::ArchToolsetStrategy::Set) {
@@ -3133,6 +3170,14 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
+ if (!expandedPreset->ConditionResult) {
+ cmSystemTools::Error(cmStrCat("Cannot use disabled build preset in ",
+ this->GetHomeDirectory(), ": \"",
+ presetName, '"'));
+ settingsFile.PrintBuildPresetList();
+ return 1;
+ }
+
auto configurePresetPair =
settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);
if (configurePresetPair == settingsFile.ConfigurePresets.end()) {
@@ -3159,7 +3204,9 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
- dir = expandedConfigurePreset->BinaryDir;
+ if (!expandedConfigurePreset->BinaryDir.empty()) {
+ dir = expandedConfigurePreset->BinaryDir;
+ }
this->UnprocessedPresetEnvironment = expandedPreset->Environment;
this->ProcessPresetEnvironment();
diff --git a/Source/cmake.h b/Source/cmake.h
index 82e028c..ab2ed21 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -712,6 +712,8 @@ private:
"Specify toolset name if supported by generator." }, \
{ "-A <platform-name>", \
"Specify platform name if supported by generator." }, \
+ { "--install-prefix <directory>", \
+ "Specify install directory [CMAKE_INSTALL_PREFIX]." }, \
{ "-Wdev", "Enable developer warnings." }, \
{ "-Wno-dev", "Suppress developer warnings." }, \
{ "-Werror=dev", "Make developer warnings errors." }, \
@@ -739,6 +741,8 @@ private:
F(c_std_90) \
F(c_std_99) \
F(c_std_11) \
+ F(c_std_17) \
+ F(c_std_23) \
FOR_EACH_C90_FEATURE(F) \
FOR_EACH_C99_FEATURE(F) \
FOR_EACH_C11_FEATURE(F)
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 6713cc3..9ba4b93 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -74,7 +74,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd);
namespace {
-void CMakeCommandUsage(const char* program)
+void CMakeCommandUsage(std::string const& program)
{
std::ostringstream errorStream;
@@ -704,7 +704,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
} else if (args[2] == "--ignore-eol") {
filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]);
} else {
- CMakeCommandUsage(args[0].c_str());
+ CMakeCommandUsage(args[0]);
return 2;
}
@@ -1085,7 +1085,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
std::string const& directory = args[2];
if (!cmSystemTools::FileExists(directory)) {
cmSystemTools::Error("Directory does not exist for chdir command: " +
- args[2]);
+ directory);
return 1;
}
@@ -1152,7 +1152,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
<< "\n";
return 1;
}
- if (!cmSystemTools::CreateSymlink(args[2], args[3])) {
+ if (!cmSystemTools::CreateSymlink(args[2], destinationFileName)) {
return 1;
}
return 0;
@@ -1161,12 +1161,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
// Command to create a hard link. Fails on platforms not
// supporting them.
if (args[1] == "create_hardlink" && args.size() == 4) {
- const char* SouceFileName = args[2].c_str();
- const char* destinationFileName = args[3].c_str();
+ std::string const& sourceFileName = args[2];
+ std::string const& destinationFileName = args[3];
- if (!cmSystemTools::FileExists(SouceFileName)) {
+ if (!cmSystemTools::FileExists(sourceFileName)) {
std::cerr << "failed to create hard link because source path '"
- << SouceFileName << "' does not exist \n";
+ << sourceFileName << "' does not exist \n";
return 1;
}
@@ -1180,7 +1180,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
return 1;
}
- if (!cmSystemTools::CreateLink(args[2], args[3])) {
+ if (!cmSystemTools::CreateLink(sourceFileName, destinationFileName)) {
return 1;
}
return 0;
@@ -1560,7 +1560,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
}
- CMakeCommandUsage(args[0].c_str());
+ CMakeCommandUsage(args[0]);
return 1;
}
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 3c331d3..a4b85ae 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -55,8 +55,9 @@ static const char* cmDocumentationOptions[][2] = {
"format of the test information and can be 'human' for the current text "
"format or 'json-v1' for json format. Defaults to 'human'." },
{ "-L <regex>, --label-regex <regex>",
- "Run tests with labels matching "
- "regular expression." },
+ "Run tests with labels matching regular expression. "
+ "With multiple -L, run tests where each "
+ "regular expression matches at least one label." },
{ "-R <regex>, --tests-regex <regex>",
"Run tests matching regular "
"expression." },
@@ -64,8 +65,9 @@ static const char* cmDocumentationOptions[][2] = {
"Exclude tests matching regular "
"expression." },
{ "-LE <regex>, --label-exclude <regex>",
- "Exclude tests with labels "
- "matching regular expression." },
+ "Exclude tests with labels matching regular expression. "
+ "With multiple -LE, exclude tests where each "
+ "regular expression matches at least one label." },
{ "-FA <regex>, --fixture-exclude-any <regex>",
"Do not automatically "
"add any tests for "
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 0c2190a..e70d4e8 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -121,7 +121,21 @@ bool Directory::Load(const std::string& name, std::string* errorMessage)
delete[] buf;
if (srchHandle == -1) {
- return 0;
+ if (errorMessage) {
+ if (unsigned int errorId = GetLastError()) {
+ LPSTR message = nullptr;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, nullptr);
+ *errorMessage = std::string(message, size);
+ LocalFree(message);
+ } else {
+ *errorMessage = "Unknown error.";
+ }
+ }
+ return false;
}
// Loop through names
@@ -152,6 +166,20 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
delete[] buf;
if (srchHandle == -1) {
+ if (errorMessage) {
+ if (unsigned int errorId = GetLastError()) {
+ LPSTR message = nullptr;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, nullptr);
+ *errorMessage = std::string(message, size);
+ LocalFree(message);
+ } else {
+ *errorMessage = "Unknown error.";
+ }
+ }
return 0;
}
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index e8474e2..fd39775 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -54,6 +54,9 @@ public:
Glob();
~Glob();
+ Glob(const Glob&) = delete;
+ void operator=(const Glob&) = delete;
+
//! Find all files that match the pattern.
bool FindFiles(const std::string& inexpr, GlobMessages* messages = nullptr);
@@ -124,10 +127,6 @@ protected:
std::vector<std::string> VisitedSymlinks;
bool ListDirs;
bool RecurseListDirs;
-
-private:
- Glob(const Glob&) = delete;
- void operator=(const Glob&) = delete;
};
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 6144d9c..4d974a8 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -244,7 +244,7 @@ inline int Chdir(const std::string& dir)
return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
}
inline void Realpath(const std::string& path, std::string& resolved_path,
- std::string* errorMessage = 0)
+ std::string* errorMessage = nullptr)
{
std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
wchar_t* ptemp;
@@ -2273,11 +2273,8 @@ bool SystemTools::TextFilesDiffer(const std::string& path1,
return false;
}
-/**
- * Blockwise copy source to destination file
- */
-static bool CopyFileContentBlockwise(const std::string& source,
- const std::string& destination)
+bool SystemTools::CopyFileContentBlockwise(const std::string& source,
+ const std::string& destination)
{
// Open files
kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
@@ -2341,8 +2338,8 @@ static bool CopyFileContentBlockwise(const std::string& source,
* - The underlying filesystem does not support file cloning
* - An unspecified error occurred
*/
-static bool CloneFileContent(const std::string& source,
- const std::string& destination)
+bool SystemTools::CloneFileContent(const std::string& source,
+ const std::string& destination)
{
#if defined(__linux) && defined(FICLONE)
int in = open(source.c_str(), O_RDONLY);
@@ -2410,9 +2407,9 @@ bool SystemTools::CopyFileAlways(const std::string& source,
SystemTools::MakeDirectory(destination_dir);
- if (!CloneFileContent(source, real_destination)) {
+ if (!SystemTools::CloneFileContent(source, real_destination)) {
// if cloning did not succeed, fall back to blockwise copy
- if (!CopyFileContentBlockwise(source, real_destination)) {
+ if (!SystemTools::CopyFileContentBlockwise(source, real_destination)) {
return false;
}
}
@@ -3929,7 +3926,7 @@ bool SystemTools::FileIsFullPath(const char* in_name)
bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len)
{
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
// On Windows, the name must be at least two characters long.
if (len < 2) {
return false;
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 74dc176..a7b1288 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -578,6 +578,17 @@ public:
const std::string& path2);
/**
+ * Blockwise copy source to destination file
+ */
+ static bool CopyFileContentBlockwise(const std::string& source,
+ const std::string& destination);
+ /**
+ * Clone the source file to the destination file
+ */
+ static bool CloneFileContent(const std::string& source,
+ const std::string& destination);
+
+ /**
* Return true if the two files are the same file
*/
static bool SameFile(const std::string& file1, const std::string& file2);
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index 4d1b46c..9409d1b 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -10,7 +10,7 @@
#endif
/* Configure support for this platform. */
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32)
# define KWSYS_TERMINAL_SUPPORT_CONSOLE
#endif
#if !defined(_WIN32)