From e3168128841485a0a579ad3b9125fdae5e12eec8 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 8 Sep 2022 18:24:28 -0400 Subject: CMakePresets.json: Add workflow presets to schema --- Source/CMakeLists.txt | 1 + Source/cmCMakePresetsGraph.cxx | 139 +++++++++++++++++++++ Source/cmCMakePresetsGraph.h | 45 ++++++- Source/cmCMakePresetsGraphInternal.h | 4 + Source/cmCMakePresetsGraphReadJSON.cxx | 37 +++++- .../cmCMakePresetsGraphReadJSONWorkflowPresets.cxx | 95 ++++++++++++++ 6 files changed, 316 insertions(+), 5 deletions(-) create mode 100644 Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 32bd341..8f2a5cb 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 7fbcdab..fb3d042 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 +using PresetPair = cmCMakePresetsGraph::PresetPair; 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& /*out*/, + const std::vector& /*macroExpanders*/) +{ + return true; +} + template bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset, cm::optional& out) @@ -579,6 +590,42 @@ ExpandMacroResult ExpandMacro(std::string& out, return ExpandMacroResult::Error; } + +template +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( + const ConfigurePreset& preset, const ConfigurePreset*& configurePreset) +{ + configurePreset = &preset; + return ReadFileResult::READ_OK; +} + +template +ReadFileResult TryReachPresetFromWorkflow( + const WorkflowPreset& origin, + const std::map>& 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(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 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(&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 806a36d..5b3e812 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 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 Steps; + + ReadFileResult VisitPresetInherit(const Preset& parent) override; + ReadFileResult VisitPresetAfterInherit(int /* version */) override; + }; + template class PresetPair { @@ -375,11 +415,13 @@ public: std::map> BuildPresets; std::map> TestPresets; std::map> PackagePresets; + std::map> WorkflowPresets; std::vector ConfigurePresetOrder; std::vector BuildPresetOrder; std::vector TestPresetOrder; std::vector PackagePresetOrder; + std::vector WorkflowPresetOrder; std::string SourceDir; std::vector> Files; @@ -442,6 +484,7 @@ public: void PrintPackagePresetList( const std::function& 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 40af356..9e47a69 100644 --- a/Source/cmCMakePresetsGraphInternal.h +++ b/Source/cmCMakePresetsGraphInternal.h @@ -151,6 +151,10 @@ cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper( std::vector& out, const Json::Value* value); +cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper( + std::vector& out, + const Json::Value* value); + cmJSONHelper VendorHelper( cmCMakePresetsGraph::ReadFileResult error); diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index 4fba7d9..5aa4284 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; @@ -46,10 +48,11 @@ struct CMakeVersion struct RootPresets { CMakeVersion CMakeMinimumRequired; - std::vector ConfigurePresets; - std::vector BuildPresets; - std::vector TestPresets; - std::vector PackagePresets; + std::vector ConfigurePresets; + std::vector BuildPresets; + std::vector TestPresets; + std::vector PackagePresets; + std::vector WorkflowPresets; std::vector 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 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 0000000..33680a1 --- /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 +#include +#include +#include + +#include + +#include + +#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::Object( + 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::Vector( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + WorkflowStepHelper); + +auto const WorkflowPresetHelper = + cmJSONHelperBuilder::Object( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &WorkflowPreset::Name, + cmCMakePresetsGraphInternal::PresetStringHelper) + .Bind("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& out, + const Json::Value* value) +{ + static auto const helper = + cmJSONHelperBuilder::Vector( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + WorkflowPresetHelper); + + return helper(out, value); +} +} -- cgit v0.12 From 374d82bbcd461a5ee8d1d9d3a94abd8a26759c37 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 16 Sep 2022 15:17:27 -0400 Subject: cmake: Add --workflow mode Fixes: #23118 --- Help/manual/cmake-presets.7.rst | 56 +++++- Help/manual/cmake.1.rst | 22 +++ Help/manual/presets/example.json | 23 +++ Help/manual/presets/schema.json | 85 ++++++++- Help/release/dev/cmake-presets-workflow.rst | 4 + Source/cmake.cxx | 209 +++++++++++++++++++++ Source/cmake.h | 14 ++ Source/cmakemain.cxx | 65 +++++++ Tests/RunCMake/CMakeLists.txt | 4 + .../DocumentationExampleListAllPresets-stdout.txt | 4 + .../CMakePresetsWorkflow/BadExitCode-result.txt | 1 + .../CMakePresetsWorkflow/BadExitCode-stderr.txt | 4 + .../CMakePresetsWorkflow/BadExitCode-stdout.txt | 17 ++ .../CMakePresetsWorkflow/BadExitCode.cmake | 8 + .../CMakePresetsWorkflow/BadExitCodeTest.cmake | 1 + .../CMakePresetsWorkflow/CMakeLists.txt.in | 3 + .../ConfigureStepMismatch-result.txt | 1 + .../ConfigureStepMismatch-stderr.txt | 2 + .../ConfigureStepMismatch.json.in | 32 ++++ .../FirstStepNotConfigure-result.txt | 0 .../FirstStepNotConfigure-stderr.txt | 2 + .../FirstStepNotConfigure.json.in | 27 +++ .../RunCMake/CMakePresetsWorkflow/Good-stdout.txt | 19 ++ Tests/RunCMake/CMakePresetsWorkflow/Good.cmake | 8 + Tests/RunCMake/CMakePresetsWorkflow/Good.json.in | 87 +++++++++ .../CMakePresetsWorkflow/GoodUser-stdout.txt | 2 + Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake | 1 + .../RunCMake/CMakePresetsWorkflow/GoodUser.json.in | 14 ++ .../CMakePresetsWorkflow/ListPresets-stdout.txt | 4 + .../CMakePresetsWorkflow/ListPresets.json.in | 30 +++ .../NoWorkflowSteps-result.txt | 1 + .../NoWorkflowSteps-stderr.txt | 2 + .../CMakePresetsWorkflow/NoWorkflowSteps.json.in | 9 + .../NonexistentStep-result.txt | 1 + .../NonexistentStep-stderr.txt | 2 + .../CMakePresetsWorkflow/NonexistentStep.json.in | 14 ++ .../CMakePresetsWorkflow/RunCMakeTest.cmake | 79 ++++++++ .../SecondStepConfigure-result.txt | 1 + .../SecondStepConfigure-stderr.txt | 2 + .../SecondStepConfigure.json.in | 25 +++ .../UnreachableStep-result.txt | 1 + .../UnreachableStep-stderr.txt | 2 + .../CMakePresetsWorkflow/UnreachableStep.json.in | 14 ++ .../UnreachableStepUser.json.in | 8 + .../UnsupportedVersion-result.txt | 1 + .../UnsupportedVersion-stderr.txt | 2 + .../UnsupportedVersion.json.in | 4 + .../WorkflowStepDisabled-result.txt | 1 + .../WorkflowStepDisabled-stderr.txt | 2 + .../WorkflowStepDisabled.json.in | 23 +++ .../WorkflowStepHidden-result.txt | 1 + .../WorkflowStepHidden-stderr.txt | 2 + .../WorkflowStepHidden.json.in | 20 ++ .../WorkflowStepInvalidMacro-result.txt | 1 + .../WorkflowStepInvalidMacro-stderr.txt | 1 + .../WorkflowStepInvalidMacro.json.in | 20 ++ Tests/RunCMake/CMakePresetsWorkflow/check.cmake | 3 + .../CMakePresetsWorkflow/cpack_staging.cmake.in | 1 + 58 files changed, 981 insertions(+), 11 deletions(-) create mode 100644 Help/release/dev/cmake-presets-workflow.rst create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/Good.cmake create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/Good.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/check.cmake create mode 100644 Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index d5319f2..93f929e 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -106,6 +106,10 @@ The root object recognizes the following fields: An optional array of `Package Preset`_ objects. This is allowed in preset files specifying version ``6`` or above. +``workflowPresets`` + An optional array of `Workflow Preset`_ objects. + This is allowed in preset files specifying version ``6`` or above. + Includes ^^^^^^^^ @@ -137,8 +141,8 @@ that may contain the following fields: This identifier is used in the :ref:`cmake --preset ` option. There must not be two configure presets in the union of ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same directory with the same name. - However, a configure preset may have the same name as a build, test, or - package preset. + However, a configure preset may have the same name as a build, test, + package, or workflow preset. ``hidden`` An optional boolean specifying whether or not a preset should be hidden. @@ -364,8 +368,8 @@ that may contain the following fields: :ref:`cmake --build --preset ` option. There must not be two build presets in the union of ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same directory with the same name. - However, a build preset may have the same name as a configure, test, or - package preset. + However, a build preset may have the same name as a configure, test, + package, or workflow preset. ``hidden`` An optional boolean specifying whether or not a preset should be hidden. @@ -525,8 +529,8 @@ that may contain the following fields: This identifier is used in the :option:`ctest --preset` option. There must not be two test presets in the union of ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same directory with the same name. - However, a test preset may have the same name as a configure, build, or - package preset. + However, a test preset may have the same name as a configure, build, + package, or workflow preset. ``hidden`` An optional boolean specifying whether or not a preset should be hidden. @@ -861,8 +865,8 @@ fields: This identifier is used in the :option:`cpack --preset` option. There must not be two package presets in the union of ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same directory with the same name. - However, a package preset may have the same name as a configure, build, or - test preset. + However, a package preset may have the same name as a configure, build, + test, or workflow preset. ``hidden`` An optional boolean specifying whether or not a preset should be hidden. @@ -977,6 +981,42 @@ fields: ``vendorName`` An optional string representing the vendor name. +Workflow Preset +^^^^^^^^^^^^^^^ + +Workflow presets may be used in schema version ``6`` or above. Each entry of +the ``workflowPresets`` array is a JSON object that may contain the following +fields: + +``name`` + A required string representing the machine-friendly name of the preset. + This identifier is used in the + :ref:`cmake --workflow --preset ` option. There must not be + two workflow presets in the union of ``CMakePresets.json`` and + ``CMakeUserPresets.json`` in the same directory with the same name. However, + a workflow preset may have the same name as a configure, build, test, or + package preset. + +``displayName`` + An optional string with a human-friendly name of the preset. + +``description`` + An optional string with a human-friendly description of the preset. + +``steps`` + A required array of objects describing the steps of the workflow. The first + step must be a configure preset, and all subsequent steps must be non- + configure presets whose ``configurePreset`` field matches the starting + configure preset. Each object may contain the following fields: + + ``type`` + A required string. The first step must be ``configure``. Subsequent steps + must be either ``build``, ``test``, or ``package``. + + ``name`` + A required string representing the name of the configure, build, test, or + package preset to run as this workflow step. + Condition ^^^^^^^^^ diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 98655e5..c05f3c8 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -30,6 +30,9 @@ Synopsis `Run the Find-Package Tool`_ cmake --find-package [] + `Run a Workflow Preset`_ + cmake --workflow [] + `View Help`_ cmake --help[-] @@ -1177,6 +1180,25 @@ autoconf-based projects (via ``share/aclocal/cmake.m4``). This mode is not well-supported due to some technical limitations. It is kept for compatibility but should not be used in new projects. +.. _`Workflow Mode`: + +Run a Workflow Preset +===================== + +:manual:`CMake Presets ` provides a way to execute multiple +build steps in order: + +.. option:: --preset , --preset= + + Use a workflow preset to specify a workflow. The project binary directory + is inferred from the initial configure preset. The current working directory + must contain CMake preset files. + See :manual:`preset ` for more details. + +.. option:: --list-presets + + Lists the available workflow presets. The current working directory must + contain CMake preset files. View Help ========= diff --git a/Help/manual/presets/example.json b/Help/manual/presets/example.json index 06a1112..696ab47 100644 --- a/Help/manual/presets/example.json +++ b/Help/manual/presets/example.json @@ -75,6 +75,29 @@ ] } ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + }, + { + "type": "package", + "name": "default" + } + ] + } + ], "vendor": { "example.com/ExampleIDE/1.0": { "autoFormat": false diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index f3a7532..b4db700 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -85,6 +85,7 @@ "buildPresets": { "$ref": "#/definitions/buildPresetsV4"}, "testPresets": { "$ref": "#/definitions/testPresetsV5"}, "packagePresets": { "$ref": "#/definitions/packagePresetsV6"}, + "workflowPresets": { "$ref": "#/definitions/workflowPresetsV6" }, "include": { "$ref": "#/definitions/include"} }, "additionalProperties": false @@ -492,7 +493,7 @@ "properties": { "name": { "type": "string", - "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, or package) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", "minLength": 1 }, "hidden": { @@ -744,7 +745,7 @@ "properties": { "name": { "type": "string", - "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, or package) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", "minLength": 1 }, "hidden": { @@ -1153,7 +1154,7 @@ "properties": { "name": { "type": "string", - "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, or package) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", "minLength": 1 }, "hidden": { @@ -1321,6 +1322,84 @@ "additionalProperties": false } }, + "workflowPresetsItemsV6": { + "type": "array", + "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 6 and higher.", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "minLength": 1 + }, + "vendor": { + "type": "object", + "description": "An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the root-level vendor field.", + "properties": {} + }, + "displayName": { + "type": "string", + "description": "An optional string with a human-friendly name of the preset." + }, + "description": { + "type": "string", + "description": "An optional string with a human-friendly description of the preset." + }, + "steps": { + "type": "array", + "description": "A required array of objects describing the steps of the workflow. The first step must be a configure preset, and all subsequent steps must be non-configure presets whose configurePreset field matches the starting configure preset.", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string. The first step must be configure. Subsequent steps must be either build, test, or package.", + "enum": ["configure", "build", "test", "package"] + }, + "name": { + "type": "string", + "description": "A required string representing the name of the configure, build, test, or package preset to run as this workflow step.", + "minLength": 1 + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + } + } + }, + "required": [ + "name", + "steps" + ], + "additionalProperties": false + } + }, + "workflowPresetsV6": { + "type": "array", + "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 6 and higher.", + "allOf": [ + { "$ref": "#/definitions/workflowPresetsItemsV6" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "steps": {} + }, + "required": [ + "name", + "steps" + ], + "additionalProperties": false + } + }, "condition": { "anyOf": [ { diff --git a/Help/release/dev/cmake-presets-workflow.rst b/Help/release/dev/cmake-presets-workflow.rst new file mode 100644 index 0000000..db93d72 --- /dev/null +++ b/Help/release/dev/cmake-presets-workflow.rst @@ -0,0 +1,4 @@ +cmake-presets-workflow +---------------------- + +* The :manual:`cmake-presets(7)` format now supports a ``workflowPresets`` field. diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 3b105e3..7f30bb4 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -23,6 +23,10 @@ #include #include +#if !defined(CMAKE_BOOTSTRAP) && !defined(_WIN32) +# include +#endif + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" @@ -56,6 +60,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" +#include "cmUVProcessChain.h" #include "cmUtils.hxx" #include "cmVersionConfig.h" #include "cmWorkingDirectory.h" @@ -3665,6 +3670,210 @@ bool cmake::Open(const std::string& dir, bool dryRun) return gen->Open(dir, *cachedProjectName, dryRun); } +#if !defined(CMAKE_BOOTSTRAP) +template +const T* cmake::FindPresetForWorkflow( + cm::static_string_view type, + const std::map>& presets, + const cmCMakePresetsGraph::WorkflowPreset::WorkflowStep& step) +{ + auto it = presets.find(step.PresetName); + if (it == presets.end()) { + cmSystemTools::Error(cmStrCat("No such ", type, " preset in ", + this->GetHomeDirectory(), ": \"", + step.PresetName, '"')); + return nullptr; + } + + if (it->second.Unexpanded.Hidden) { + cmSystemTools::Error(cmStrCat("Cannot use hidden ", type, " preset in ", + this->GetHomeDirectory(), ": \"", + step.PresetName, '"')); + return nullptr; + } + + if (!it->second.Expanded) { + cmSystemTools::Error(cmStrCat("Could not evaluate ", type, " preset \"", + step.PresetName, + "\": Invalid macro expansion")); + return nullptr; + } + + if (!it->second.Expanded->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled ", type, " preset in ", + this->GetHomeDirectory(), ": \"", + step.PresetName, '"')); + return nullptr; + } + + return &*it->second.Expanded; +} + +std::function cmake::BuildWorkflowStep( + const std::vector& args) +{ + cmUVProcessChainBuilder builder; + builder + .AddCommand(args) +# ifdef _WIN32 + .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, _fileno(stdout)) + .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, _fileno(stderr)); +# else + .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, STDOUT_FILENO) + .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, STDERR_FILENO); +# endif + return [builder]() -> int { + auto chain = builder.Start(); + chain.Wait(); + return static_cast(chain.GetStatus().front()->ExitStatus); + }; +} +#endif + +int cmake::Workflow(const std::string& presetName, bool listPresets) +{ +#ifndef CMAKE_BOOTSTRAP + this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); + this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); + + cmCMakePresetsGraph settingsFile; + auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory()); + if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) { + cmSystemTools::Error( + cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ": ", + cmCMakePresetsGraph::ResultToString(result))); + return 1; + } + + if (listPresets) { + settingsFile.PrintWorkflowPresetList(); + return 0; + } + + auto presetPair = settingsFile.WorkflowPresets.find(presetName); + if (presetPair == settingsFile.WorkflowPresets.end()) { + cmSystemTools::Error(cmStrCat("No such workflow preset in ", + this->GetHomeDirectory(), ": \"", presetName, + '"')); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + if (presetPair->second.Unexpanded.Hidden) { + cmSystemTools::Error(cmStrCat("Cannot use hidden workflow preset in ", + this->GetHomeDirectory(), ": \"", presetName, + '"')); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + auto const& expandedPreset = presetPair->second.Expanded; + if (!expandedPreset) { + cmSystemTools::Error(cmStrCat("Could not evaluate workflow preset \"", + presetName, "\": Invalid macro expansion")); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + if (!expandedPreset->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled workflow preset in ", + this->GetHomeDirectory(), ": \"", presetName, + '"')); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + struct CalculatedStep + { + int StepNumber; + cm::static_string_view Type; + std::string Name; + std::function Action; + + CalculatedStep(int stepNumber, cm::static_string_view type, + std::string name, std::function action) + : StepNumber(stepNumber) + , Type(type) + , Name(std::move(name)) + , Action(std::move(action)) + { + } + }; + + std::vector steps; + steps.reserve(expandedPreset->Steps.size()); + int stepNumber = 1; + for (auto const& step : expandedPreset->Steps) { + switch (step.PresetType) { + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type:: + Configure: { + auto const* configurePreset = this->FindPresetForWorkflow( + "configure"_s, settingsFile.ConfigurePresets, step); + if (!configurePreset) { + return 1; + } + steps.emplace_back( + stepNumber, "configure"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCMakeCommand(), + "--preset", step.PresetName })); + } break; + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Build: { + auto const* buildPreset = this->FindPresetForWorkflow( + "build"_s, settingsFile.BuildPresets, step); + if (!buildPreset) { + return 1; + } + steps.emplace_back( + stepNumber, "build"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCMakeCommand(), + "--build", "--preset", step.PresetName })); + } break; + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Test: { + auto const* testPreset = this->FindPresetForWorkflow( + "test"_s, settingsFile.TestPresets, step); + if (!testPreset) { + return 1; + } + steps.emplace_back( + stepNumber, "test"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCTestCommand(), + "--preset", step.PresetName })); + } break; + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Package: { + auto const* packagePreset = this->FindPresetForWorkflow( + "package"_s, settingsFile.PackagePresets, step); + if (!packagePreset) { + return 1; + } + steps.emplace_back( + stepNumber, "package"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCPackCommand(), + "--preset", step.PresetName })); + } break; + } + stepNumber++; + } + + int stepResult; + bool first = true; + for (auto const& step : steps) { + if (!first) { + std::cout << "\n"; + } + std::cout << "Executing workflow step " << step.StepNumber << " of " + << steps.size() << ": " << step.Type << " preset \"" << step.Name + << "\"\n\n" + << std::flush; + if ((stepResult = step.Action()) != 0) { + return stepResult; + } + first = false; + } +#endif + + return 0; +} + void cmake::WatchUnusedCli(const std::string& var) { #ifndef CMAKE_BOOTSTRAP diff --git a/Source/cmake.h b/Source/cmake.h index 8c0fece..54d0bb5 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -16,6 +16,7 @@ #include #include +#include #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" @@ -600,6 +601,9 @@ public: //! run the --open option bool Open(const std::string& dir, bool dryRun); + //! run the --workflow option + int Workflow(const std::string& presetName, bool listPresets); + void UnwatchUnusedCli(const std::string& var); void WatchUnusedCli(const std::string& var); @@ -740,6 +744,16 @@ private: void AppendExtraGeneratorsDocumentation(std::vector&); #if !defined(CMAKE_BOOTSTRAP) + template + const T* FindPresetForWorkflow( + cm::static_string_view type, + const std::map>& presets, + const cmCMakePresetsGraph::WorkflowPreset::WorkflowStep& step); + + std::function BuildWorkflowStep(const std::vector& args); +#endif + +#if !defined(CMAKE_BOOTSTRAP) std::unique_ptr ProfilingOutput; #endif }; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 6f3d0eb..b754b72 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -911,6 +911,68 @@ int do_install(int ac, char const* const* av) #endif } +int do_workflow(int ac, char const* const* av) +{ +#ifdef CMAKE_BOOTSTRAP + std::cerr << "This cmake does not support --workflow\n"; + return -1; +#else + std::string presetName; + bool listPresets = false; + + using CommandArgument = + cmCommandLineArgument; + + std::vector arguments = { + CommandArgument{ "--preset", CommandArgument::Values::One, + CommandArgument::setToValue(presetName) }, + CommandArgument{ "--list-presets", CommandArgument::Values::Zero, + CommandArgument::setToTrue(listPresets) } + }; + + std::vector inputArgs; + + inputArgs.reserve(ac - 2); + cm::append(inputArgs, av + 2, av + ac); + + decltype(inputArgs.size()) i = 0; + for (; i < inputArgs.size(); ++i) { + std::string const& arg = inputArgs[i]; + bool matched = false; + bool parsed = false; + for (auto const& m : arguments) { + matched = m.matches(arg); + if (matched) { + parsed = m.parse(arg, i, inputArgs); + break; + } + } + if (!(matched && parsed)) { + if (!matched) { + std::cerr << "Unknown argument " << arg << std::endl; + } + break; + } + } + + if (presetName.empty() && !listPresets) { + std::cerr << "TODO: Usage\n"; + return 1; + } + + cmake cm(cmake::RoleInternal, cmState::Project); + cmSystemTools::SetMessageCallback( + [&cm](const std::string& msg, const cmMessageMetadata& md) { + cmakemainMessageCallback(msg, md, &cm); + }); + cm.SetProgressCallback([&cm](const std::string& msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); + + return cm.Workflow(presetName, listPresets); +#endif +} + int do_open(int ac, char const* const* av) { #ifdef CMAKE_BOOTSTRAP @@ -980,6 +1042,9 @@ int main(int ac, char const* const* av) if (strcmp(av[1], "--open") == 0) { return do_open(ac, av); } + if (strcmp(av[1], "--workflow") == 0) { + return do_workflow(ac, av); + } if (strcmp(av[1], "-E") == 0) { return do_command(ac, av, std::move(consoleBuf)); } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 2f5bc87..4a42bda 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -1008,6 +1008,10 @@ add_RunCMake_test(CMakePresetsPackage -DPython_EXECUTABLE=${Python_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} ) +add_RunCMake_test(CMakePresetsWorkflow + -DPython_EXECUTABLE=${Python_EXECUTABLE} + -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} + ) add_RunCMake_test(VerifyHeaderSets) diff --git a/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt index b1fcc28..57b714d 100644 --- a/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt +++ b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt @@ -15,4 +15,8 @@ Available test presets: Available package presets: + "default" + +Available workflow presets: + "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt @@ -0,0 +1 @@ +8 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt new file mode 100644 index 0000000..0690c69 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt @@ -0,0 +1,4 @@ +^Errors while running CTest +Output from these tests are in: [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build/Testing/Temporary/LastTest\.log +Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely\.$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt new file mode 100644 index 0000000..2f23f88 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt @@ -0,0 +1,17 @@ +^Executing workflow step 1 of 4: configure preset "default" + +.*Testing the configure step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build.* + +Executing workflow step 2 of 4: build preset "default" + +.*Testing the build step at [^ +]*[\\/]Tests[\\/]RunCMake[\\/]CMakePresetsWorkflow[\\/]BadExitCode[\\/]build.* + +Executing workflow step 3 of 4: test preset "default" + +.*Testing the test step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build.* + +The following tests FAILED: +.* +1 - EchoTest \(Failed\)$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake new file mode 100644 index 0000000..10b46e3 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake @@ -0,0 +1,8 @@ +message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}") + +add_custom_target(echo_test ALL COMMAND ${CMAKE_COMMAND} -E echo "Testing the build step at ${CMAKE_BINARY_DIR}") + +enable_testing() +add_test(NAME EchoTest COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/BadExitCodeTest.cmake") + +include(CPack) diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake new file mode 100644 index 0000000..59f683e --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR " Testing the test step at ${CMAKE_BINARY_DIR}") diff --git a/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in b/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in new file mode 100644 index 0000000..129184a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project("@CASE_NAME@" NONE) +include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake") diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt new file mode 100644 index 0000000..22ca94d --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in new file mode 100644 index 0000000..0864149 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in @@ -0,0 +1,32 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default" + }, + { + "name": "mismatch" + } + ], + "buildPresets": [ + { + "name": "mismatch", + "configurePreset": "mismatch" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "mismatch" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt new file mode 100644 index 0000000..cbfee5a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in new file mode 100644 index 0000000..2c121a8 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in @@ -0,0 +1,27 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "build", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt new file mode 100644 index 0000000..a04d7ea --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt @@ -0,0 +1,19 @@ +^Executing workflow step 1 of 4: configure preset "default" + +.*Testing the configure step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.* + +Executing workflow step 2 of 4: build preset "default" + +.*Testing the build step at [^ +]*[\\/]Tests[\\/]RunCMake[\\/]CMakePresetsWorkflow[\\/]Good[\\/]build.* + +Executing workflow step 3 of 4: test preset "default" + +.*Testing the test step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.* + +Executing workflow step 4 of 4: package preset "default" + +.*Testing the package step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.* diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake b/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake new file mode 100644 index 0000000..31ce7ff --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake @@ -0,0 +1,8 @@ +message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}") + +add_custom_target(echo_test ALL COMMAND ${CMAKE_COMMAND} -E echo "Testing the build step at ${CMAKE_BINARY_DIR}") + +enable_testing() +add_test(NAME EchoTest COMMAND ${CMAKE_COMMAND} -E echo "Testing the test step at ${CMAKE_BINARY_DIR}") + +include(CPack) diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in b/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in new file mode 100644 index 0000000..87e2936 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in @@ -0,0 +1,87 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default", + "configuration": "Debug" + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default", + "output": { + "verbosity": "verbose" + }, + "configuration": "Debug" + } + ], + "packagePresets": [ + { + "name": "default", + "configurePreset": "default", + "generators": [ + "External" + ], + "variables": { + "CPACK_EXTERNAL_PACKAGE_SCRIPT": "${sourceDir}/cpack_staging.cmake" + }, + "configurations": ["Debug"] + } + ], + "workflowPresets": [ + { + "name": "Good", + "displayName": "Good Workflow Preset", + "description": "This workflow preset works properly.", + "vendor": {}, + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + }, + { + "type": "package", + "name": "default" + } + ] + }, + { + "name": "BadExitCode", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + }, + { + "type": "package", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt new file mode 100644 index 0000000..1014915 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt @@ -0,0 +1,2 @@ +-- Testing the configure step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/GoodUser/build diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake new file mode 100644 index 0000000..9143e00 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake @@ -0,0 +1 @@ +message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}") diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in new file mode 100644 index 0000000..e71b4ea --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in @@ -0,0 +1,14 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "GoodUser", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt new file mode 100644 index 0000000..57f30a4 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt @@ -0,0 +1,4 @@ +^Available workflow presets: + + "default" + "with-description" - With Description$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in new file mode 100644 index 0000000..9a7d5a6 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in @@ -0,0 +1,30 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + }, + { + "name": "with-description", + "displayName": "With Description", + "description": "This preset has a description.", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt new file mode 100644 index 0000000..049ed6b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in new file mode 100644 index 0000000..2757197 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in @@ -0,0 +1,9 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "default", + "steps": [] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt new file mode 100644 index 0000000..c522b84 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in new file mode 100644 index 0000000..235398b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in @@ -0,0 +1,14 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake new file mode 100644 index 0000000..b89a11a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake @@ -0,0 +1,79 @@ +include(RunCMake) + +# Presets do not support legacy VS generator name architecture suffix. +if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ") + set(RunCMake_GENERATOR "${CMAKE_MATCH_1}") +endif() + +function(run_cmake_workflow_presets name) + set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}") + set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build") + set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") + + set(RunCMake_TEST_NO_CLEAN TRUE) + + file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") + + set(CASE_NAME "${name}") + set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}") + configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY) + + if(NOT CMakePresets_FILE) + set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in") + endif() + if(EXISTS "${CMakePresets_FILE}") + configure_file("${CMakePresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY) + endif() + + if(NOT CMakeUserPresets_FILE) + set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in") + endif() + if(EXISTS "${CMakeUserPresets_FILE}") + configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY) + endif() + + foreach(ASSET ${CMakePresets_ASSETS}) + configure_file("${RunCMake_SOURCE_DIR}/${ASSET}.in" "${RunCMake_TEST_SOURCE_DIR}/${ASSET}" @ONLY) + endforeach() + + if(EXISTS "${RunCMake_SOURCE_DIR}/${name}-check.cmake") + set(RunCMake-check-file "${name}-check.cmake") + else() + set(RunCMake-check-file "check.cmake") + endif() + + if(eq) + set(eq 0 PARENT_SCOPE) + set(preset_arg "--preset=${name}") + else() + set(eq 1 PARENT_SCOPE) + set(preset_arg "--preset" "${name}") + endif() + run_cmake_command("${name}" "${CMAKE_COMMAND}" "--workflow" ${preset_arg} ${ARGN}) +endfunction() + +set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) +run_cmake_workflow_presets(UnsupportedVersion) +set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) +run_cmake_workflow_presets(NoWorkflowSteps) +run_cmake_workflow_presets(FirstStepNotConfigure) +run_cmake_workflow_presets(SecondStepConfigure) +run_cmake_workflow_presets(NonexistentStep) +run_cmake_workflow_presets(UnreachableStep) +run_cmake_workflow_presets(WorkflowStepHidden) +run_cmake_workflow_presets(WorkflowStepDisabled) +run_cmake_workflow_presets(WorkflowStepInvalidMacro) +run_cmake_workflow_presets(ConfigureStepMismatch) + +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Good.json.in") +set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/GoodUser.json.in") +set(CMakePresets_ASSETS cpack_staging.cmake) +run_cmake_workflow_presets(Good) +run_cmake_workflow_presets(GoodUser) +run_cmake_workflow_presets(BadExitCode) +unset(CMakePresets_FILE) +unset(CMakeUserPresets_FILE) +unset(CMakePresets_ASSETS) + +run_cmake_workflow_presets(ListPresets --list-presets) diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt new file mode 100644 index 0000000..b0ad7d5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in new file mode 100644 index 0000000..44e1582 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in @@ -0,0 +1,25 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt new file mode 100644 index 0000000..425e719 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep: Workflow step is unreachable from preset's file$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in new file mode 100644 index 0000000..235398b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in @@ -0,0 +1,14 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in new file mode 100644 index 0000000..39b6835 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in @@ -0,0 +1,8 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default" + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt new file mode 100644 index 0000000..5cf01aa --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion: File version must be 6 or higher for workflow preset support$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in new file mode 100644 index 0000000..4ebaa8e --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in @@ -0,0 +1,4 @@ +{ + "version": 5, + "workflowPresets": [] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt new file mode 100644 index 0000000..b598b27 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Cannot use disabled configure preset in [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled: "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in new file mode 100644 index 0000000..a3b6783 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in @@ -0,0 +1,23 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "condition": { + "type": "const", + "value": false + } + } + ], + "workflowPresets": [ + { + "name": "WorkflowStepDisabled", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt new file mode 100644 index 0000000..838ded5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Cannot use hidden configure preset in [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden: "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in new file mode 100644 index 0000000..07c4105 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in @@ -0,0 +1,20 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "hidden": true + } + ], + "workflowPresets": [ + { + "name": "WorkflowStepHidden", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt new file mode 100644 index 0000000..f132a93 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Could not evaluate configure preset "default": Invalid macro expansion$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in new file mode 100644 index 0000000..6aec0e3 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in @@ -0,0 +1,20 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "$vendor{invalidMacro}" + } + ], + "workflowPresets": [ + { + "name": "WorkflowStepInvalidMacro", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/check.cmake b/Tests/RunCMake/CMakePresetsWorkflow/check.cmake new file mode 100644 index 0000000..e79c4f1 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/check.cmake @@ -0,0 +1,3 @@ +set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.py") +include("${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.cmake") +include("${RunCMake_SOURCE_DIR}/../CMakePresets/check.cmake") diff --git a/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in b/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in new file mode 100644 index 0000000..4030dfb --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in @@ -0,0 +1 @@ +message(STATUS "Testing the package step at @RunCMake_TEST_BINARY_DIR@") -- cgit v0.12