Presets: Clarify workflow step error messages

Report both the workflow step type and preset name when workflow
preset validation or execution fails.  This disambiguates workflows
where configure, build, test, and package steps share the same preset
name.

Update the workflow preset RunCMake expectations.
This commit is contained in:
Richard
2026-07-31 10:44:57 -06:00
parent 8e7b683c67
commit b1f15344c9
12 changed files with 104 additions and 53 deletions
+27 -12
View File
@@ -235,10 +235,19 @@ void TEST_OUTPUT_TRUNCATION_UNSUPPORTED(cmJSONState* state)
"preset support");
}
void INVALID_WORKFLOW_STEPS(std::string const& workflowStep,
cmJSONState* state)
namespace {
std::string WorkflowStepLabel(cm::string_view stepType,
std::string const& stepName)
{
state->AddError(cmStrCat("Invalid workflow step \"", workflowStep, '"'));
return cmStrCat("of type \"", stepType, "\" named \"", stepName, '"');
}
}
void INVALID_WORKFLOW_STEPS(cm::string_view stepType,
std::string const& stepName, cmJSONState* state)
{
state->AddError(
cmStrCat("Invalid workflow step ", WorkflowStepLabel(stepType, stepName)));
}
void WORKFLOW_STEP_CONFIGURE_PRESET_MISMATCH(
@@ -266,25 +275,31 @@ void NO_WORKFLOW_STEPS(std::string const& presetName, cmJSONState* state)
cmStrCat("No workflow steps specified for \"", presetName, '"'));
}
void FIRST_WORKFLOW_STEP_NOT_CONFIGURE(std::string const& stepName,
void FIRST_WORKFLOW_STEP_NOT_CONFIGURE(cm::string_view stepType,
std::string const& stepName,
cmJSONState* state)
{
state->AddError(cmStrCat("First workflow step \"", stepName,
"\" must be a configure step"));
state->AddError(cmStrCat("First workflow step ",
WorkflowStepLabel(stepType, stepName),
" must be a configure step"));
}
void CONFIGURE_WORKFLOW_STEP_NOT_FIRST(std::string const& stepName,
void CONFIGURE_WORKFLOW_STEP_NOT_FIRST(cm::string_view stepType,
std::string const& stepName,
cmJSONState* state)
{
state->AddError(cmStrCat("Configure workflow step \"", stepName,
"\" must be the first step"));
state->AddError(cmStrCat("Workflow step ",
WorkflowStepLabel(stepType, stepName),
" must be the first step"));
}
void WORKFLOW_STEP_UNREACHABLE_FROM_FILE(std::string const& workflowStep,
void WORKFLOW_STEP_UNREACHABLE_FROM_FILE(cm::string_view stepType,
std::string const& stepName,
cmJSONState* state)
{
state->AddError(cmStrCat("Workflow step \"", workflowStep,
"\" is unreachable from preset's file"));
state->AddError(cmStrCat("Workflow step ",
WorkflowStepLabel(stepType, stepName),
" is unreachable from preset's file"));
}
void CTEST_JUNIT_UNSUPPORTED(cmJSONState* state)
+8 -5
View File
@@ -90,8 +90,8 @@ void CYCLIC_INCLUDE(std::string const& file, cmJSONState* state);
void TEST_OUTPUT_TRUNCATION_UNSUPPORTED(cmJSONState* state);
void INVALID_WORKFLOW_STEPS(std::string const& workflowStep,
cmJSONState* state);
void INVALID_WORKFLOW_STEPS(cm::string_view stepType,
std::string const& stepName, cmJSONState* state);
void WORKFLOW_STEP_CONFIGURE_PRESET_MISMATCH(
std::string const& kind, std::string const& workflowStep,
@@ -103,13 +103,16 @@ void INVALID_TEST_FILTER_INCLUDE_INDEX(Json::Value const* value,
void NO_WORKFLOW_STEPS(std::string const& presetName, cmJSONState* state);
void FIRST_WORKFLOW_STEP_NOT_CONFIGURE(std::string const& stepName,
void FIRST_WORKFLOW_STEP_NOT_CONFIGURE(cm::string_view stepType,
std::string const& stepName,
cmJSONState* state);
void CONFIGURE_WORKFLOW_STEP_NOT_FIRST(std::string const& stepName,
void CONFIGURE_WORKFLOW_STEP_NOT_FIRST(cm::string_view stepType,
std::string const& stepName,
cmJSONState* state);
void WORKFLOW_STEP_UNREACHABLE_FROM_FILE(std::string const& workflowStep,
void WORKFLOW_STEP_UNREACHABLE_FROM_FILE(cm::string_view stepType,
std::string const& stepName,
cmJSONState* state);
void CTEST_JUNIT_UNSUPPORTED(cmJSONState* state);
+32 -12
View File
@@ -64,6 +64,21 @@ using cmCMakePresetsGraphInternal::ExpandMacros;
bool gSkipNewLine = true;
char const* WorkflowStepTypeToString(WorkflowPreset::WorkflowStep::Type type)
{
switch (type) {
case WorkflowPreset::WorkflowStep::Type::Configure:
return "configure";
case WorkflowPreset::WorkflowStep::Type::Build:
return "build";
case WorkflowPreset::WorkflowStep::Type::Test:
return "test";
case WorkflowPreset::WorkflowStep::Type::Package:
return "package";
}
return "";
}
void InheritString(std::string& child, std::string const& parent)
{
if (child.empty()) {
@@ -701,6 +716,7 @@ namespace {
template <typename T>
bool SetupWorkflowConfigurePreset(T const& preset,
ConfigurePreset const*& configurePreset,
char const*, std::string const&,
cmJSONState* state)
{
if (preset.ConfigurePreset != configurePreset->Name) {
@@ -715,7 +731,7 @@ bool SetupWorkflowConfigurePreset(T const& preset,
template <>
bool SetupWorkflowConfigurePreset<ConfigurePreset>(
ConfigurePreset const& preset, ConfigurePreset const*& configurePreset,
cmJSONState*)
char const*, std::string const&, cmJSONState*)
{
configurePreset = &preset;
return true;
@@ -725,20 +741,23 @@ template <typename T>
bool TryReachPresetFromWorkflow(
WorkflowPreset const& origin,
std::map<std::string, PresetPair<T>> const& presets, std::string const& name,
ConfigurePreset const*& configurePreset, cmJSONState* state)
char const* workflowStepType, ConfigurePreset const*& configurePreset,
cmJSONState* state)
{
auto it = presets.find(name);
if (it == presets.end()) {
cmCMakePresetsErrors::INVALID_WORKFLOW_STEPS(name, state);
cmCMakePresetsErrors::INVALID_WORKFLOW_STEPS(workflowStepType, name,
state);
return false;
}
if (!origin.OriginFile->ReachableFiles.count(
it->second.Unexpanded.OriginFile)) {
cmCMakePresetsErrors::WORKFLOW_STEP_UNREACHABLE_FROM_FILE(name, state);
cmCMakePresetsErrors::WORKFLOW_STEP_UNREACHABLE_FROM_FILE(workflowStepType,
name, state);
return false;
}
return SetupWorkflowConfigurePreset<T>(it->second.Unexpanded,
configurePreset, state);
return SetupWorkflowConfigurePreset<T>(
it->second.Unexpanded, configurePreset, workflowStepType, name, state);
}
}
@@ -1382,14 +1401,15 @@ bool cmCMakePresetsGraph::ReadProjectPresetsInternal(
ConfigurePreset const* configurePreset = nullptr;
for (auto const& step : it.second.Unexpanded.Steps) {
char const* const stepType = WorkflowStepTypeToString(step.PresetType);
if (!configurePreset && step.PresetType != Type::Configure) {
cmCMakePresetsErrors::FIRST_WORKFLOW_STEP_NOT_CONFIGURE(
step.PresetName, &this->parseState);
stepType, step.PresetName, &this->parseState);
return false;
}
if (configurePreset && step.PresetType == Type::Configure) {
cmCMakePresetsErrors::CONFIGURE_WORKFLOW_STEP_NOT_FIRST(
step.PresetName, &this->parseState);
stepType, step.PresetName, &this->parseState);
return false;
}
@@ -1397,22 +1417,22 @@ bool cmCMakePresetsGraph::ReadProjectPresetsInternal(
case Type::Configure:
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->ConfigurePresets, step.PresetName,
configurePreset, &this->parseState);
stepType, configurePreset, &this->parseState);
break;
case Type::Build:
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->BuildPresets, step.PresetName,
configurePreset, &this->parseState);
stepType, configurePreset, &this->parseState);
break;
case Type::Test:
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->TestPresets, step.PresetName,
it.second.Unexpanded, this->TestPresets, step.PresetName, stepType,
configurePreset, &this->parseState);
break;
case Type::Package:
result = TryReachPresetFromWorkflow(
it.second.Unexpanded, this->PackagePresets, step.PresetName,
configurePreset, &this->parseState);
stepType, configurePreset, &this->parseState);
break;
}
if (!result) {
+26 -14
View File
@@ -4228,38 +4228,46 @@ bool cmake::Open(std::string const& dir, DryRun dryRun)
}
#if !defined(CMAKE_BOOTSTRAP)
namespace {
std::string WorkflowStepLabel(cm::static_string_view type,
std::string const& name)
{
return cmStrCat("of type \"", type, "\" named \"", name, '"');
}
}
template <typename T>
T const* cmake::FindPresetForWorkflow(
cm::static_string_view type,
std::map<std::string, cmCMakePresetsGraph::PresetPair<T>> const& presets,
cmCMakePresetsGraph::WorkflowPreset::WorkflowStep const& step)
{
std::string const stepLabel = WorkflowStepLabel(type, step.PresetName);
auto it = presets.find(step.PresetName);
if (it == presets.end()) {
cmSystemTools::Error(cmStrCat("No such ", type, " preset in ",
this->GetHomeDirectory(), ": \"",
step.PresetName, '"'));
cmSystemTools::Error(cmStrCat("No such preset for workflow step ",
stepLabel, " in ",
this->GetHomeDirectory()));
return nullptr;
}
if (it->second.Unexpanded.Hidden) {
cmSystemTools::Error(cmStrCat("Cannot use hidden ", type, " preset in ",
this->GetHomeDirectory(), ": \"",
step.PresetName, '"'));
cmSystemTools::Error(
cmStrCat("Cannot use hidden preset for workflow step ", stepLabel,
" in ", this->GetHomeDirectory()));
return nullptr;
}
if (!it->second.Expanded) {
cmSystemTools::Error(cmStrCat("Could not evaluate ", type, " preset \"",
step.PresetName,
"\": Invalid macro expansion"));
cmSystemTools::Error(cmStrCat("Could not evaluate workflow step ",
stepLabel, ": Invalid macro expansion"));
return nullptr;
}
if (!it->second.Expanded->ConditionResult) {
cmSystemTools::Error(cmStrCat("Cannot use disabled ", type, " preset in ",
this->GetHomeDirectory(), ": \"",
step.PresetName, '"'));
cmSystemTools::Error(
cmStrCat("Cannot use disabled preset for workflow step ", stepLabel,
" in ", this->GetHomeDirectory()));
return nullptr;
}
@@ -4437,13 +4445,17 @@ int cmake::Workflow(cmCMakePresetsWorkflowArgs const& args)
<< std::flush;
cmUVProcessChain::Status const status = step.Action();
if (status.ExitStatus != 0) {
cmSystemTools::Error(
cmStrCat("Workflow step ", WorkflowStepLabel(step.Type, step.Name),
" failed with exit code ", status.ExitStatus));
exitStatus = static_cast<int>(status.ExitStatus);
break;
}
auto const codeReasonPair = status.GetException();
if (codeReasonPair.first != cmUVProcessChain::ExceptionCode::None) {
std::cout << "Step command ended abnormally: " << codeReasonPair.second
<< std::endl;
cmSystemTools::Error(
cmStrCat("Workflow step ", WorkflowStepLabel(step.Type, step.Name),
" command ended abnormally: ", codeReasonPair.second));
exitStatus =
status.SpawnResult != 0 ? status.SpawnResult : status.TermSignal;
break;
@@ -1,4 +1,5 @@
^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\.$
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely\.
CMake Error: Workflow step of type "test" named "default" failed with exit code 8$
@@ -1,3 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure:
First workflow step "default" must be a configure step$
First workflow step of type "build" named "default" must be a configure step$
@@ -1,3 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep:
Invalid workflow step "default"$
Invalid workflow step of type "configure" named "default"$
@@ -1,3 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure:
Configure workflow step "default" must be the first step
Workflow step of type "configure" named "default" must be the first step
@@ -1,3 +1,3 @@
^CMake Error: Could not read presets from [^
]*/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep:
Workflow step "default" is unreachable from preset's file$
Workflow step of type "configure" named "default" is unreachable from preset's file$
@@ -1,2 +1,2 @@
^CMake Error: Cannot use disabled configure preset in [^
]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled: "default"$
^CMake Error: Cannot use disabled preset for workflow step of type "configure" named "default" in [^
]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled$
@@ -1,2 +1,2 @@
^CMake Error: Cannot use hidden configure preset in [^
]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden: "default"$
^CMake Error: Cannot use hidden preset for workflow step of type "configure" named "default" in [^
]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden$
@@ -1 +1 @@
^CMake Error: Could not evaluate configure preset "default": Invalid macro expansion$
^CMake Error: Could not evaluate workflow step of type "configure" named "default": Invalid macro expansion$