summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/cmCMakePresetsGraph.cxx139
-rw-r--r--Source/cmCMakePresetsGraph.h45
-rw-r--r--Source/cmCMakePresetsGraphInternal.h4
-rw-r--r--Source/cmCMakePresetsGraphReadJSON.cxx37
-rw-r--r--Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx95
6 files changed, 316 insertions, 5 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 32bd3417af..8f2a5cb654 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -148,6 +148,7 @@ add_library(
cmCMakePresetsGraphReadJSONConfigurePresets.cxx
cmCMakePresetsGraphReadJSONPackagePresets.cxx
cmCMakePresetsGraphReadJSONTestPresets.cxx
+ cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
cmCommandArgumentParserHelper.cxx
cmCommonTargetGenerator.cxx
cmCommonTargetGenerator.h
diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx
index 7fbcdab68c..fb3d04217d 100644
--- a/Source/cmCMakePresetsGraph.cxx
+++ b/Source/cmCMakePresetsGraph.cxx
@@ -44,6 +44,9 @@ using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
using PackagePreset = cmCMakePresetsGraph::PackagePreset;
+using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
+template <typename T>
+using PresetPair = cmCMakePresetsGraph::PresetPair<T>;
using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
@@ -324,6 +327,14 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph,
return true;
}
+bool ExpandMacros(const cmCMakePresetsGraph& /*graph*/,
+ const WorkflowPreset& /*preset*/,
+ cm::optional<WorkflowPreset>& /*out*/,
+ const std::vector<MacroExpander>& /*macroExpanders*/)
+{
+ return true;
+}
+
template <class T>
bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset,
cm::optional<T>& out)
@@ -579,6 +590,42 @@ ExpandMacroResult ExpandMacro(std::string& out,
return ExpandMacroResult::Error;
}
+
+template <typename T>
+ReadFileResult SetupWorkflowConfigurePreset(
+ const T& preset, const ConfigurePreset*& configurePreset)
+{
+ if (preset.ConfigurePreset != configurePreset->Name) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+ return ReadFileResult::READ_OK;
+}
+
+template <>
+ReadFileResult SetupWorkflowConfigurePreset<ConfigurePreset>(
+ const ConfigurePreset& preset, const ConfigurePreset*& configurePreset)
+{
+ configurePreset = &preset;
+ return ReadFileResult::READ_OK;
+}
+
+template <typename T>
+ReadFileResult TryReachPresetFromWorkflow(
+ const WorkflowPreset& origin,
+ const std::map<std::string, PresetPair<T>>& presets, const std::string& name,
+ const ConfigurePreset*& configurePreset)
+{
+ auto it = presets.find(name);
+ if (it == presets.end()) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+ if (!origin.OriginFile->ReachableFiles.count(
+ it->second.Unexpanded.OriginFile)) {
+ return ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE;
+ }
+ return SetupWorkflowConfigurePreset<T>(it->second.Unexpanded,
+ configurePreset);
+}
}
bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate(
@@ -929,6 +976,19 @@ cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(int /* version */)
return ReadFileResult::READ_OK;
}
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit(
+ const cmCMakePresetsGraph::Preset& /*parentPreset*/)
+{
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::WorkflowPreset::VisitPresetAfterInherit(int /* version */)
+{
+ return ReadFileResult::READ_OK;
+}
+
std::string cmCMakePresetsGraph::GetFilename(const std::string& sourceDir)
{
return cmStrCat(sourceDir, "/CMakePresets.json");
@@ -992,6 +1052,7 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this));
CHECK_OK(ComputePresetInheritance(this->TestPresets, *this));
CHECK_OK(ComputePresetInheritance(this->PackagePresets, *this));
+ CHECK_OK(ComputePresetInheritance(this->WorkflowPresets, *this));
for (auto& it : this->ConfigurePresets) {
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
@@ -1071,6 +1132,55 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
}
}
+ for (auto& it : this->WorkflowPresets) {
+ using Type = WorkflowPreset::WorkflowStep::Type;
+
+ const ConfigurePreset* configurePreset = nullptr;
+ for (auto const& step : it.second.Unexpanded.Steps) {
+ if (configurePreset == nullptr && step.PresetType != Type::Configure) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+ if (configurePreset != nullptr && step.PresetType == Type::Configure) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+
+ ReadFileResult result;
+ switch (step.PresetType) {
+ case Type::Configure:
+ result = TryReachPresetFromWorkflow(
+ it.second.Unexpanded, this->ConfigurePresets, step.PresetName,
+ configurePreset);
+ break;
+ case Type::Build:
+ result = TryReachPresetFromWorkflow(
+ it.second.Unexpanded, this->BuildPresets, step.PresetName,
+ configurePreset);
+ break;
+ case Type::Test:
+ result =
+ TryReachPresetFromWorkflow(it.second.Unexpanded, this->TestPresets,
+ step.PresetName, configurePreset);
+ break;
+ case Type::Package:
+ result = TryReachPresetFromWorkflow(
+ it.second.Unexpanded, this->PackagePresets, step.PresetName,
+ configurePreset);
+ break;
+ }
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ }
+
+ if (configurePreset == nullptr) {
+ return ReadFileResult::INVALID_WORKFLOW_STEPS;
+ }
+
+ if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ return ReadFileResult::INVALID_MACRO_EXPANSION;
+ }
+ }
+
return ReadFileResult::READ_OK;
}
@@ -1116,6 +1226,8 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result)
"support.";
case ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED:
return "File version must be 6 or higher for package preset support";
+ case ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED:
+ return "File version must be 6 or higher for workflow preset support";
case ReadFileResult::INCLUDE_UNSUPPORTED:
return "File version must be 4 or higher for include support";
case ReadFileResult::INVALID_INCLUDE:
@@ -1137,6 +1249,10 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result)
case ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED:
return "File version must be 5 or higher for testOutputTruncation "
"preset support.";
+ case ReadFileResult::INVALID_WORKFLOW_STEPS:
+ return "Invalid workflow steps";
+ case ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE:
+ return "Workflow step is unreachable from preset's file";
}
return "Unknown error";
@@ -1148,11 +1264,13 @@ void cmCMakePresetsGraph::ClearPresets()
this->BuildPresets.clear();
this->TestPresets.clear();
this->PackagePresets.clear();
+ this->WorkflowPresets.clear();
this->ConfigurePresetOrder.clear();
this->BuildPresetOrder.clear();
this->TestPresetOrder.clear();
this->PackagePresetOrder.clear();
+ this->WorkflowPresetOrder.clear();
this->Files.clear();
}
@@ -1291,6 +1409,26 @@ void cmCMakePresetsGraph::PrintPackagePresetList(
}
}
+void cmCMakePresetsGraph::PrintWorkflowPresetList(
+ PrintPrecedingNewline* newline) const
+{
+ std::vector<const cmCMakePresetsGraph::Preset*> presets;
+ for (auto const& p : this->WorkflowPresetOrder) {
+ auto const& preset = this->WorkflowPresets.at(p);
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ preset.Expanded->ConditionResult) {
+ presets.push_back(
+ static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded));
+ }
+ }
+
+ if (!presets.empty()) {
+ printPrecedingNewline(newline);
+ std::cout << "Available workflow presets:\n\n";
+ cmCMakePresetsGraph::PrintPresets(presets);
+ }
+}
+
void cmCMakePresetsGraph::PrintAllPresets() const
{
PrintPrecedingNewline newline = PrintPrecedingNewline::False;
@@ -1298,4 +1436,5 @@ void cmCMakePresetsGraph::PrintAllPresets() const
this->PrintBuildPresetList(&newline);
this->PrintTestPresetList(&newline);
this->PrintPackagePresetList(&newline);
+ this->PrintWorkflowPresetList(&newline);
}
diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h
index 806a36da31..5b3e812e11 100644
--- a/Source/cmCMakePresetsGraph.h
+++ b/Source/cmCMakePresetsGraph.h
@@ -42,6 +42,7 @@ public:
INVALID_MACRO_EXPANSION,
BUILD_TEST_PRESETS_UNSUPPORTED,
PACKAGE_PRESETS_UNSUPPORTED,
+ WORKFLOW_PRESETS_UNSUPPORTED,
INCLUDE_UNSUPPORTED,
INVALID_INCLUDE,
INVALID_CONFIGURE_PRESET,
@@ -51,6 +52,8 @@ public:
TOOLCHAIN_FILE_UNSUPPORTED,
CYCLIC_INCLUDE,
TEST_OUTPUT_TRUNCATION_UNSUPPORTED,
+ INVALID_WORKFLOW_STEPS,
+ WORKFLOW_STEP_UNREACHABLE_FROM_FILE,
};
std::string errors;
@@ -97,7 +100,7 @@ public:
std::string Name;
std::vector<std::string> Inherits;
- bool Hidden;
+ bool Hidden = false;
File* OriginFile;
std::string DisplayName;
std::string Description;
@@ -363,6 +366,43 @@ public:
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
+ class WorkflowPreset : public Preset
+ {
+ public:
+ WorkflowPreset() = default;
+ WorkflowPreset(WorkflowPreset&& /*other*/) = default;
+ WorkflowPreset(const WorkflowPreset& /*other*/) = default;
+ WorkflowPreset& operator=(const WorkflowPreset& /*other*/) = default;
+ ~WorkflowPreset() override = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ WorkflowPreset& operator=(WorkflowPreset&& /*other*/) = default;
+#else
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't.
+ WorkflowPreset& operator=(WorkflowPreset&& /*other*/) = delete;
+#endif
+
+ class WorkflowStep
+ {
+ public:
+ enum class Type
+ {
+ Configure,
+ Build,
+ Test,
+ Package,
+ };
+ Type PresetType;
+ std::string PresetName;
+ };
+
+ std::vector<WorkflowStep> Steps;
+
+ ReadFileResult VisitPresetInherit(const Preset& parent) override;
+ ReadFileResult VisitPresetAfterInherit(int /* version */) override;
+ };
+
template <class T>
class PresetPair
{
@@ -375,11 +415,13 @@ public:
std::map<std::string, PresetPair<BuildPreset>> BuildPresets;
std::map<std::string, PresetPair<TestPreset>> TestPresets;
std::map<std::string, PresetPair<PackagePreset>> PackagePresets;
+ std::map<std::string, PresetPair<WorkflowPreset>> WorkflowPresets;
std::vector<std::string> ConfigurePresetOrder;
std::vector<std::string> BuildPresetOrder;
std::vector<std::string> TestPresetOrder;
std::vector<std::string> PackagePresetOrder;
+ std::vector<std::string> WorkflowPresetOrder;
std::string SourceDir;
std::vector<std::unique_ptr<File>> Files;
@@ -442,6 +484,7 @@ public:
void PrintPackagePresetList(
const std::function<bool(const PackagePreset&)>& filter,
PrintPrecedingNewline* newline = nullptr) const;
+ void PrintWorkflowPresetList(PrintPrecedingNewline* newline = nullptr) const;
void PrintAllPresets() const;
private:
diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h
index 40af356176..9e47a6988f 100644
--- a/Source/cmCMakePresetsGraphInternal.h
+++ b/Source/cmCMakePresetsGraphInternal.h
@@ -151,6 +151,10 @@ cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper(
std::vector<cmCMakePresetsGraph::PackagePreset>& out,
const Json::Value* value);
+cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper(
+ std::vector<cmCMakePresetsGraph::WorkflowPreset>& out,
+ const Json::Value* value);
+
cmJSONHelper<std::nullptr_t, cmCMakePresetsGraph::ReadFileResult> VendorHelper(
cmCMakePresetsGraph::ReadFileResult error);
diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx
index 4fba7d94a3..5aa4284d75 100644
--- a/Source/cmCMakePresetsGraphReadJSON.cxx
+++ b/Source/cmCMakePresetsGraphReadJSON.cxx
@@ -30,6 +30,8 @@ using CacheVariable = cmCMakePresetsGraph::CacheVariable;
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
using TestPreset = cmCMakePresetsGraph::TestPreset;
+using PackagePreset = cmCMakePresetsGraph::PackagePreset;
+using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>;
@@ -46,10 +48,11 @@ struct CMakeVersion
struct RootPresets
{
CMakeVersion CMakeMinimumRequired;
- std::vector<cmCMakePresetsGraph::ConfigurePreset> ConfigurePresets;
- std::vector<cmCMakePresetsGraph::BuildPreset> BuildPresets;
- std::vector<cmCMakePresetsGraph::TestPreset> TestPresets;
- std::vector<cmCMakePresetsGraph::PackagePreset> PackagePresets;
+ std::vector<ConfigurePreset> ConfigurePresets;
+ std::vector<BuildPreset> BuildPresets;
+ std::vector<TestPreset> TestPresets;
+ std::vector<PackagePreset> PackagePresets;
+ std::vector<WorkflowPreset> WorkflowPresets;
std::vector<std::string> Include;
};
@@ -284,6 +287,8 @@ auto const RootPresetsHelper =
cmCMakePresetsGraphInternal::TestPresetsHelper, false)
.Bind("packagePresets"_s, &RootPresets::PackagePresets,
cmCMakePresetsGraphInternal::PackagePresetsHelper, false)
+ .Bind("workflowPresets"_s, &RootPresets::WorkflowPresets,
+ cmCMakePresetsGraphInternal::WorkflowPresetsHelper, false)
.Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
CMakeVersionHelper, false)
.Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
@@ -466,6 +471,11 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
return ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED;
}
+ // Support for workflow presets added in version 6.
+ if (v < 6 && root.isMember("workflowPresets")) {
+ return ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED;
+ }
+
// Support for include added in version 4.
if (v < 4 && root.isMember("include")) {
return ReadFileResult::INCLUDE_UNSUPPORTED;
@@ -600,6 +610,25 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
this->PackagePresetOrder.push_back(preset.Name);
}
+ for (auto& preset : presets.WorkflowPresets) {
+ preset.OriginFile = file;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<WorkflowPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->WorkflowPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3, but this requires version 6
+ // already, so no action needed.
+
+ this->WorkflowPresetOrder.push_back(preset.Name);
+ }
+
auto const includeFile = [this, &inProgressFiles, file](
const std::string& include, RootType rootType2,
ReadReason readReason2,
diff --git a/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
new file mode 100644
index 0000000000..33680a1829
--- /dev/null
+++ b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
@@ -0,0 +1,95 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <cstddef>
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <cmext/string_view>
+
+#include <cm3p/json/value.h>
+
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
+
+ReadFileResult WorkflowStepTypeHelper(WorkflowPreset::WorkflowStep::Type& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "configure") {
+ out = WorkflowPreset::WorkflowStep::Type::Configure;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "build") {
+ out = WorkflowPreset::WorkflowStep::Type::Build;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "test") {
+ out = WorkflowPreset::WorkflowStep::Type::Test;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "package") {
+ out = WorkflowPreset::WorkflowStep::Type::Package;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const WorkflowStepHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset::WorkflowStep>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("type"_s, &WorkflowPreset::WorkflowStep::PresetType,
+ WorkflowStepTypeHelper)
+ .Bind("name"_s, &WorkflowPreset::WorkflowStep::PresetName,
+ cmCMakePresetsGraphInternal::PresetStringHelper);
+
+auto const WorkflowStepsHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset::WorkflowStep>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ WorkflowStepHelper);
+
+auto const WorkflowPresetHelper =
+ cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &WorkflowPreset::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ cmCMakePresetsGraphInternal::VendorHelper(
+ ReadFileResult::INVALID_PRESET),
+ false)
+ .Bind("displayName"_s, &WorkflowPreset::DisplayName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("description"_s, &WorkflowPreset::Description,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("steps"_s, &WorkflowPreset::Steps, WorkflowStepsHelper);
+}
+
+namespace cmCMakePresetsGraphInternal {
+cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper(
+ std::vector<cmCMakePresetsGraph::WorkflowPreset>& out,
+ const Json::Value* value)
+{
+ static auto const helper =
+ cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ WorkflowPresetHelper);
+
+ return helper(out, value);
+}
+}