Merge topic 'feature/preset-resolve-extract'

e99fbf4100 Presets: Extract ResolvePreset utility for preset resolution

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !11957
This commit is contained in:
Brad King
2026-04-23 13:26:21 +00:00
committed by Kitware Robot
14 changed files with 271 additions and 165 deletions

View File

@@ -136,6 +136,7 @@ add_library(
cmCMakePresetsGraphReadJSONPackagePresets.cxx
cmCMakePresetsGraphReadJSONTestPresets.cxx
cmCMakePresetsGraphReadJSONWorkflowPresets.cxx
cmCMakePresetsGraphResolve.cxx
cmCMakeString.hxx
cmCMakeString.cxx
cmCommandLineArgument.h

View File

@@ -276,41 +276,20 @@ int main(int argc, char const* const* argv)
return 0;
}
auto presetPair = presetsGraph.PackagePresets.find(preset);
if (presetPair == presetsGraph.PackagePresets.end()) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"No such package preset in " << workingDirectory << ": \""
<< preset << "\"\n");
auto resolveResult =
presetsGraph.ResolvePreset(preset, presetsGraph.PackagePresets);
auto resolveError = cmCMakePresetsGraph::FormatPresetError<
cmCMakePresetsGraph::PackagePreset>(resolveResult.StatusCode,
resolveResult.ErrorPresetName,
workingDirectory);
if (resolveError) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR, *resolveError << "\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
auto const* expandedPreset = resolveResult.Preset;
if (presetPair->second.Unexpanded.Hidden) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot use hidden package preset in "
<< workingDirectory << ": \"" << preset << "\"\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
auto const& expandedPreset = presetPair->second.Expanded;
if (!expandedPreset) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Could not evaluate package preset \""
<< preset << "\": Invalid macro expansion\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
if (!expandedPreset->ConditionResult) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot use disabled package preset in "
<< workingDirectory << ": \"" << preset << "\"\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
if (!presetGeneratorsPresent(presetPair->second.Unexpanded)) {
if (!presetGeneratorsPresent(*expandedPreset)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot use preset");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;

View File

@@ -4,10 +4,8 @@
#include <chrono>
#include <cstdlib>
#include <map>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <cm/memory>
@@ -36,48 +34,6 @@ using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
namespace {
cm::optional<ConfigurePreset> LoadPreset(cmExecutionStatus& status,
std::string sourceDirectory,
std::string presetName)
{
// Load a configure preset after verifying its existence and validity.
cmCMakePresetsGraph presetsGraph;
if (!presetsGraph.ReadProjectPresets(sourceDirectory)) {
status.SetError(
cmStrCat("Could not read presets from \"", sourceDirectory,
"\": ", presetsGraph.parseState.GetErrorMessage()));
return cm::nullopt;
}
auto preset = presetsGraph.ConfigurePresets.find(presetName);
if (preset == presetsGraph.ConfigurePresets.end()) {
status.SetError(cmStrCat("No such preset in ", sourceDirectory, ": \"",
presetName, '"'));
return cm::nullopt;
}
if (preset->second.Unexpanded.Hidden) {
status.SetError(cmStrCat("Cannot use hidden preset in ", sourceDirectory,
": \"", presetName, '"'));
return cm::nullopt;
}
auto const& expandedPreset = preset->second.Expanded;
if (!expandedPreset) {
status.SetError(cmStrCat("Could not evaluate preset \"", presetName,
"\": Invalid macro expansion."));
return cm::nullopt;
}
if (!expandedPreset->ConditionResult) {
status.SetError(
cmStrCat("Cannot use disabled preset \"", presetName, "\"."));
return cm::nullopt;
}
return expandedPreset;
}
bool ConstructConfigureCommand(cmExecutionStatus& status, cmMakefile& mf,
std::string const sourceDirectory,
std::string const buildDirectory,
@@ -107,11 +63,27 @@ bool ConstructConfigureCommand(cmExecutionStatus& status, cmMakefile& mf,
bool presetProvidesGenerator = false;
if (!presetName.empty()) {
auto expandedPreset = LoadPreset(status, sourceDirectory, presetName);
if (!expandedPreset) {
cmCMakePresetsGraph presetsGraph;
if (!presetsGraph.ReadProjectPresets(sourceDirectory)) {
status.SetError(
cmStrCat("Could not read presets from \"", sourceDirectory,
"\": ", presetsGraph.parseState.GetErrorMessage()));
return false;
}
auto resolveResult =
presetsGraph.ResolvePreset(presetName, presetsGraph.ConfigurePresets);
auto resolveError =
cmCMakePresetsGraph::FormatPresetError<ConfigurePreset>(
resolveResult.StatusCode, resolveResult.ErrorPresetName,
sourceDirectory);
if (resolveError) {
status.SetError(*resolveError);
return false;
}
auto const* expandedPreset = resolveResult.Preset;
configureCommand += " \"--preset\"";
configureCommand += " \"";
configureCommand += presetName;

View File

@@ -401,6 +401,38 @@ public:
cm::optional<T> Expanded;
};
enum class PresetResolveStatus
{
Success,
NotFound,
Hidden,
InvalidMacroExpansion,
Disabled,
};
// Result type for preset resolution
template <class T>
struct PresetResolveResult
{
using Status = PresetResolveStatus;
Status StatusCode = Status::Success;
std::string ErrorPresetName;
T const* Preset = nullptr;
};
template <class T>
PresetResolveResult<T> ResolvePreset(
std::string const& presetName,
std::map<std::string, PresetPair<T>> const& presets) const;
// Returns an error message for a preset resolve status,
// or cm::nullopt on Success.
template <class T>
static cm::optional<std::string> FormatPresetError(
PresetResolveStatus status, std::string const& errorPresetName,
std::string const& directory);
std::map<std::string, PresetPair<ConfigurePreset>> ConfigurePresets;
std::map<std::string, PresetPair<BuildPreset>> BuildPresets;
std::map<std::string, PresetPair<TestPreset>> TestPresets;
@@ -459,3 +491,57 @@ private:
static std::string GetFilename(std::string const& sourceDir);
static std::string GetUserFilename(std::string const& sourceDir);
};
extern template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::ConfigurePreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<std::string,
cmCMakePresetsGraph::PresetPair<
cmCMakePresetsGraph::ConfigurePreset>> const&) const;
extern template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::BuildPreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<
std::string,
cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::BuildPreset>> const&)
const;
extern template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::TestPreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<
std::string,
cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::TestPreset>> const&)
const;
extern template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::PackagePreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<std::string,
cmCMakePresetsGraph::PresetPair<
cmCMakePresetsGraph::PackagePreset>> const&) const;
extern template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::ConfigurePreset>(
cmCMakePresetsGraph::PresetResolveStatus, std::string const&,
std::string const&);
extern template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::BuildPreset>(
cmCMakePresetsGraph::PresetResolveStatus, std::string const&,
std::string const&);
extern template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::TestPreset>(
cmCMakePresetsGraph::PresetResolveStatus, std::string const&,
std::string const&);
extern template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::PackagePreset>(
cmCMakePresetsGraph::PresetResolveStatus, std::string const&,
std::string const&);

View File

@@ -0,0 +1,116 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include <cassert>
#include <map>
#include <string>
#include <cm/optional>
#include "cmCMakePresetsGraph.h"
#include "cmStringAlgorithms.h"
template <class T>
cmCMakePresetsGraph::PresetResolveResult<T> cmCMakePresetsGraph::ResolvePreset(
std::string const& presetName,
std::map<std::string, PresetPair<T>> const& presets) const
{
using Result = PresetResolveResult<T>;
Result result;
auto presetPair = presets.find(presetName);
if (presetPair == presets.end()) {
result.StatusCode = Result::Status::NotFound;
result.ErrorPresetName = presetName;
return result;
}
if (presetPair->second.Unexpanded.Hidden) {
result.StatusCode = Result::Status::Hidden;
result.ErrorPresetName = presetName;
return result;
}
if (!presetPair->second.Expanded) {
result.StatusCode = Result::Status::InvalidMacroExpansion;
result.ErrorPresetName = presetName;
return result;
}
if (!presetPair->second.Expanded->ConditionResult) {
result.StatusCode = Result::Status::Disabled;
result.ErrorPresetName = presetName;
return result;
}
result.Preset = &*presetPair->second.Expanded;
return result;
}
// Explicit template instantiations
template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::ConfigurePreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<std::string,
PresetPair<cmCMakePresetsGraph::ConfigurePreset>> const&) const;
template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::BuildPreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<std::string, PresetPair<cmCMakePresetsGraph::BuildPreset>> const&)
const;
template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::TestPreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<std::string, PresetPair<cmCMakePresetsGraph::TestPreset>> const&)
const;
template cmCMakePresetsGraph::PresetResolveResult<
cmCMakePresetsGraph::PackagePreset>
cmCMakePresetsGraph::ResolvePreset(
std::string const&,
std::map<std::string, PresetPair<cmCMakePresetsGraph::PackagePreset>> const&)
const;
template <class T>
cm::optional<std::string> cmCMakePresetsGraph::FormatPresetError(
PresetResolveStatus status, std::string const& errorPresetName,
std::string const& directory)
{
using Status = PresetResolveStatus;
switch (status) {
case Status::NotFound:
return cmStrCat("No such ", T::kind(), " preset in ", directory, ": \"",
errorPresetName, '"');
case Status::Hidden:
return cmStrCat("Cannot use hidden ", T::kind(), " preset in ",
directory, ": \"", errorPresetName, '"');
case Status::InvalidMacroExpansion:
return cmStrCat("Could not evaluate ", T::kind(), " preset \"",
errorPresetName, "\": Invalid macro expansion");
case Status::Disabled:
return cmStrCat("Cannot use disabled ", T::kind(), " preset in ",
directory, ": \"", errorPresetName, '"');
case Status::Success:
return cm::nullopt;
}
assert(false && "Unreachable.");
return cm::nullopt;
}
// Explicit template instantiations for FormatPresetError
template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::ConfigurePreset>(
PresetResolveStatus, std::string const&, std::string const&);
template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::BuildPreset>(
PresetResolveStatus, std::string const&, std::string const&);
template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::TestPreset>(
PresetResolveStatus, std::string const&, std::string const&);
template cm::optional<std::string>
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::PackagePreset>(
PresetResolveStatus, std::string const&, std::string const&);

View File

@@ -1520,35 +1520,18 @@ bool cmCTest::SetArgsFromPreset(std::string const& presetName,
return true;
}
auto presetPair = settingsFile.TestPresets.find(presetName);
if (presetPair == settingsFile.TestPresets.end()) {
cmSystemTools::Error(cmStrCat("No such test preset in ", workingDirectory,
": \"", presetName, '"'));
settingsFile.PrintTestPresetList();
return false;
}
if (presetPair->second.Unexpanded.Hidden) {
cmSystemTools::Error(cmStrCat("Cannot use hidden test preset in ",
workingDirectory, ": \"", presetName, '"'));
settingsFile.PrintTestPresetList();
return false;
}
auto const& expandedPreset = presetPair->second.Expanded;
if (!expandedPreset) {
cmSystemTools::Error(cmStrCat("Could not evaluate test preset \"",
presetName, "\": Invalid macro expansion"));
settingsFile.PrintTestPresetList();
return false;
}
if (!expandedPreset->ConditionResult) {
cmSystemTools::Error(cmStrCat("Cannot use disabled test preset in ",
workingDirectory, ": \"", presetName, '"'));
auto resolveResult =
settingsFile.ResolvePreset(presetName, settingsFile.TestPresets);
auto resolveError =
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::TestPreset>(
resolveResult.StatusCode, resolveResult.ErrorPresetName,
workingDirectory);
if (resolveError) {
cmSystemTools::Error(*resolveError);
settingsFile.PrintTestPresetList();
return false;
}
auto const* expandedPreset = resolveResult.Preset;
auto configurePresetPair =
settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);

View File

@@ -2035,33 +2035,22 @@ bool cmake::SetArgsFromPreset(std::string const& presetName,
return false;
}
auto preset = presetsGraph.ConfigurePresets.find(presetName);
if (preset == presetsGraph.ConfigurePresets.end()) {
cmSystemTools::Error(cmStrCat("No such preset in ",
this->GetHomeDirectory(), ": \"", presetName,
'"'));
this->PrintPresetList(presetsGraph);
return false;
}
if (preset->second.Unexpanded.Hidden) {
cmSystemTools::Error(cmStrCat("Cannot use hidden preset in ",
this->GetHomeDirectory(), ": \"", presetName,
'"'));
this->PrintPresetList(presetsGraph);
return false;
}
auto const& expandedPreset = preset->second.Expanded;
if (!expandedPreset) {
cmSystemTools::Error(cmStrCat("Could not evaluate preset \"",
preset->second.Unexpanded.Name,
"\": Invalid macro expansion"));
return false;
}
if (!expandedPreset->ConditionResult) {
cmSystemTools::Error(cmStrCat("Could not use disabled preset \"",
preset->second.Unexpanded.Name, '"'));
auto resolveResult =
presetsGraph.ResolvePreset(presetName, presetsGraph.ConfigurePresets);
using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
using S = cmCMakePresetsGraph::PresetResolveStatus;
auto resolveError = cmCMakePresetsGraph::FormatPresetError<ConfigurePreset>(
resolveResult.StatusCode, resolveResult.ErrorPresetName,
this->GetHomeDirectory());
if (resolveError) {
cmSystemTools::Error(*resolveError);
if (resolveResult.StatusCode == S::NotFound ||
resolveResult.StatusCode == S::Hidden) {
this->PrintPresetList(presetsGraph);
}
return false;
}
auto const* expandedPreset = resolveResult.Preset;
if (!this->State->IsCacheLoaded() && !haveBinaryDirArg &&
!expandedPreset->BinaryDir.empty()) {
@@ -3926,39 +3915,18 @@ int cmake::Build(cmBuildArgs buildArgs, std::vector<std::string> targets,
return 0;
}
auto presetPair = settingsFile.BuildPresets.find(presetName);
if (presetPair == settingsFile.BuildPresets.end()) {
cmSystemTools::Error(cmStrCat("No such build preset in ",
this->GetHomeDirectory(), ": \"",
presetName, '"'));
settingsFile.PrintBuildPresetList();
return 1;
}
if (presetPair->second.Unexpanded.Hidden) {
cmSystemTools::Error(cmStrCat("Cannot use hidden build preset in ",
this->GetHomeDirectory(), ": \"",
presetName, '"'));
settingsFile.PrintBuildPresetList();
return 1;
}
auto const& expandedPreset = presetPair->second.Expanded;
if (!expandedPreset) {
cmSystemTools::Error(cmStrCat("Could not evaluate build preset \"",
presetName,
"\": Invalid macro expansion"));
settingsFile.PrintBuildPresetList();
return 1;
}
if (!expandedPreset->ConditionResult) {
cmSystemTools::Error(cmStrCat("Cannot use disabled build preset in ",
this->GetHomeDirectory(), ": \"",
presetName, '"'));
auto resolveResult =
settingsFile.ResolvePreset(presetName, settingsFile.BuildPresets);
auto resolveError =
cmCMakePresetsGraph::FormatPresetError<cmCMakePresetsGraph::BuildPreset>(
resolveResult.StatusCode, resolveResult.ErrorPresetName,
this->GetHomeDirectory());
if (resolveError) {
cmSystemTools::Error(*resolveError);
settingsFile.PrintBuildPresetList();
return 1;
}
auto const* expandedPreset = resolveResult.Preset;
auto configurePresetPair =
settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);

View File

@@ -1,2 +1,2 @@
^CMake Error: Cannot use hidden preset in [^
^CMake Error: Cannot use hidden configure preset in [^
]*/Tests/RunCMake/CMakePresets/ListPresetsHidden: "ListPresetsHidden"$

View File

@@ -1,2 +1,2 @@
^CMake Error: No such preset in [^
^CMake Error: No such configure preset in [^
]*/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset: "ListPresetsNoSuchPreset"$

View File

@@ -1,2 +1,2 @@
^CMake Error: No such preset in [^
^CMake Error: No such configure preset in [^
]*/Tests/RunCMake/CMakePresets/NoPresets: "NoPresets"$

View File

@@ -1,2 +1,2 @@
^CMake Error: No such preset in [^
^CMake Error: No such configure preset in [^
]*/Tests/RunCMake/CMakePresets/NoSuchPreset: "NoSuchPreset"$

View File

@@ -1 +1,2 @@
^CMake Error: Could not use disabled preset "SimpleFalse"$
^CMake Error: Cannot use disabled configure preset in [^
]*/Tests/RunCMake/CMakePresets/SimpleFalse: "SimpleFalse"$

View File

@@ -1,2 +1,2 @@
^CMake Error: Cannot use hidden preset in [^
^CMake Error: Cannot use hidden configure preset in [^
]*/Tests/RunCMake/CMakePresets/UseHiddenPreset: "UseHiddenPreset"$

View File

@@ -1 +1 @@
^CMake Error: Could not evaluate preset "VendorMacro": Invalid macro expansion$
^CMake Error: Could not evaluate configure preset "VendorMacro": Invalid macro expansion$