From 741a2077179a06640f40fb1aa2425dbe7036d8f2 Mon Sep 17 00:00:00 2001 From: Cristian Le Date: Wed, 27 Dec 2023 19:11:14 +0100 Subject: presets: Refactor macro expander implementation Change the macro expander to use vtable dispatch. Signed-off-by: Cristian Le --- Source/cmCMakePresetsGraph.cxx | 234 +++++++++++++++++---------------- Source/cmCMakePresetsGraphInternal.h | 103 ++++++++++++--- Source/cmCMakePresetsGraphReadJSON.cxx | 45 ++++--- 3 files changed, 237 insertions(+), 145 deletions(-) diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx index d37c8a4..008f2dd 100644 --- a/Source/cmCMakePresetsGraph.cxx +++ b/Source/cmCMakePresetsGraph.cxx @@ -10,6 +10,7 @@ #include #include +#include #include #include "cmsys/RegularExpression.hxx" @@ -49,6 +50,11 @@ template using PresetPair = cmCMakePresetsGraph::PresetPair; using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult; using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander; +using MacroExpanderVector = cmCMakePresetsGraphInternal::MacroExpanderVector; +using BaseMacroExpander = cmCMakePresetsGraphInternal::BaseMacroExpander; +template +using PresetMacroExpander = + cmCMakePresetsGraphInternal::PresetMacroExpander; using cmCMakePresetsGraphInternal::ExpandMacros; void InheritString(std::string& child, const std::string& parent) @@ -203,13 +209,61 @@ bool IsValidMacroNamespace(const std::string& str) } ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, - const std::vector& macroExpanders, + MacroExpanderVector const& macroExpanders, int version); +template +class EnvironmentMacroExpander : public MacroExpander +{ + std::map& EnvCycles; + cm::optional& Out; + MacroExpanderVector& MacroExpanders; + +public: + EnvironmentMacroExpander(MacroExpanderVector& macroExpanders, + cm::optional& out, + std::map& envCycles) + : EnvCycles(envCycles) + , Out(out) + , MacroExpanders(macroExpanders) + { + } + ExpandMacroResult operator()(const std::string& macroNamespace, + const std::string& macroName, + std::string& macroOut, + int version) const override + { + if (macroNamespace == "env" && !macroName.empty() && Out) { + auto v = Out->Environment.find(macroName); + if (v != Out->Environment.end() && v->second) { + auto e = + VisitEnv(*v->second, EnvCycles[macroName], MacroExpanders, version); + if (e != ExpandMacroResult::Ok) { + return e; + } + macroOut += *v->second; + return ExpandMacroResult::Ok; + } + } + + if (macroNamespace == "env" || macroNamespace == "penv") { + if (macroName.empty()) { + return ExpandMacroResult::Error; + } + if (cm::optional value = + cmSystemTools::GetEnvVar(macroName)) { + macroOut += *value; + } + return ExpandMacroResult::Ok; + } + + return ExpandMacroResult::Ignore; + } +}; bool ExpandMacros(const cmCMakePresetsGraph& graph, const ConfigurePreset& preset, cm::optional& out, - const std::vector& macroExpanders) + MacroExpanderVector const& macroExpanders) { std::string binaryDir = preset.BinaryDir; CHECK_EXPAND(out, binaryDir, macroExpanders, graph.GetVersion(preset)); @@ -251,7 +305,7 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, bool ExpandMacros(const cmCMakePresetsGraph& graph, const BuildPreset& preset, cm::optional& out, - const std::vector& macroExpanders) + MacroExpanderVector const& macroExpanders) { for (auto& target : out->Targets) { CHECK_EXPAND(out, target, macroExpanders, graph.GetVersion(preset)); @@ -267,7 +321,7 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const BuildPreset& preset, bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset, cm::optional& out, - const std::vector& macroExpanders) + MacroExpanderVector const& macroExpanders) { for (auto& overwrite : out->OverwriteConfigurationFile) { CHECK_EXPAND(out, overwrite, macroExpanders, graph.GetVersion(preset)); @@ -321,7 +375,7 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset, bool ExpandMacros(const cmCMakePresetsGraph& graph, const PackagePreset& preset, cm::optional& out, - const std::vector& macroExpanders) + MacroExpanderVector const& macroExpanders) { for (auto& variable : out->Variables) { CHECK_EXPAND(out, variable.second, macroExpanders, @@ -343,7 +397,7 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, bool ExpandMacros(const cmCMakePresetsGraph& /*graph*/, const WorkflowPreset& /*preset*/, cm::optional& /*out*/, - const std::vector& /*macroExpanders*/) + MacroExpanderVector const& /*macroExpanders*/) { return true; } @@ -359,100 +413,13 @@ bool ExpandMacros(cmCMakePresetsGraph& graph, const T& preset, envCycles[v.first] = CycleStatus::Unvisited; } - std::vector macroExpanders; + MacroExpanderVector macroExpanders{}; - MacroExpander defaultMacroExpander = - [&graph, &preset](const std::string& macroNamespace, - const std::string& macroName, std::string& macroOut, - int version) -> ExpandMacroResult { - if (macroNamespace.empty()) { - if (macroName == "sourceDir") { - macroOut += graph.SourceDir; - return ExpandMacroResult::Ok; - } - if (macroName == "sourceParentDir") { - macroOut += cmSystemTools::GetParentDirectory(graph.SourceDir); - return ExpandMacroResult::Ok; - } - if (macroName == "sourceDirName") { - macroOut += cmSystemTools::GetFilenameName(graph.SourceDir); - return ExpandMacroResult::Ok; - } - if (macroName == "presetName") { - macroOut += preset.Name; - return ExpandMacroResult::Ok; - } - if (macroName == "generator") { - // Generator only makes sense if preset is not hidden. - if (!preset.Hidden) { - macroOut += graph.GetGeneratorForPreset(preset.Name); - } - return ExpandMacroResult::Ok; - } - if (macroName == "dollar") { - macroOut += '$'; - return ExpandMacroResult::Ok; - } - if (macroName == "hostSystemName") { - if (version < 3) { - return ExpandMacroResult::Error; - } - macroOut += cmSystemTools::GetSystemName(); - return ExpandMacroResult::Ok; - } - if (macroName == "fileDir") { - if (version < 4) { - return ExpandMacroResult::Error; - } - macroOut += - cmSystemTools::GetParentDirectory(preset.OriginFile->Filename); - return ExpandMacroResult::Ok; - } - if (macroName == "pathListSep") { - if (version < 5) { - return ExpandMacroResult::Error; - } - macroOut += cmSystemTools::GetSystemPathlistSeparator(); - return ExpandMacroResult::Ok; - } - } - - return ExpandMacroResult::Ignore; - }; - - MacroExpander environmentMacroExpander = - [¯oExpanders, &out, &envCycles]( - const std::string& macroNamespace, const std::string& macroName, - std::string& result, int version) -> ExpandMacroResult { - if (macroNamespace == "env" && !macroName.empty() && out) { - auto v = out->Environment.find(macroName); - if (v != out->Environment.end() && v->second) { - auto e = - VisitEnv(*v->second, envCycles[macroName], macroExpanders, version); - if (e != ExpandMacroResult::Ok) { - return e; - } - result += *v->second; - return ExpandMacroResult::Ok; - } - } - - if (macroNamespace == "env" || macroNamespace == "penv") { - if (macroName.empty()) { - return ExpandMacroResult::Error; - } - if (cm::optional value = - cmSystemTools::GetEnvVar(macroName)) { - result += *value; - } - return ExpandMacroResult::Ok; - } - - return ExpandMacroResult::Ignore; - }; - - macroExpanders.push_back(defaultMacroExpander); - macroExpanders.push_back(environmentMacroExpander); + macroExpanders.push_back(cm::make_unique(graph)); + macroExpanders.push_back( + cm::make_unique>(graph, preset)); + macroExpanders.push_back(cm::make_unique>( + macroExpanders, out, envCycles)); for (auto& v : out->Environment) { if (v.second) { @@ -490,7 +457,7 @@ bool ExpandMacros(cmCMakePresetsGraph& graph, const T& preset, } ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, - const std::vector& macroExpanders, + MacroExpanderVector const& macroExpanders, int version) { if (status == CycleStatus::Verified) { @@ -511,8 +478,7 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, } ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacros( - std::string& out, const std::vector& macroExpanders, - int version) + std::string& out, MacroExpanderVector const& macroExpanders, int version) { std::string result; std::string macroNamespace; @@ -591,11 +557,11 @@ ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacros( ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacro( std::string& out, const std::string& macroNamespace, - const std::string& macroName, - const std::vector& macroExpanders, int version) + const std::string& macroName, MacroExpanderVector const& macroExpanders, + int version) { for (auto const& macroExpander : macroExpanders) { - auto result = macroExpander(macroNamespace, macroName, out, version); + auto result = (*macroExpander)(macroNamespace, macroName, out, version); if (result != ExpandMacroResult::Ignore) { return result; } @@ -651,8 +617,56 @@ bool TryReachPresetFromWorkflow( } } +ExpandMacroResult BaseMacroExpander::operator()( + const std::string& macroNamespace, const std::string& macroName, + std::string& macroOut, int version) const +{ + if (macroNamespace.empty()) { + if (macroName == "sourceDir") { + macroOut += Graph.SourceDir; + return ExpandMacroResult::Ok; + } + if (macroName == "sourceParentDir") { + macroOut += cmSystemTools::GetParentDirectory(Graph.SourceDir); + return ExpandMacroResult::Ok; + } + if (macroName == "sourceDirName") { + macroOut += cmSystemTools::GetFilenameName(Graph.SourceDir); + return ExpandMacroResult::Ok; + } + if (macroName == "dollar") { + macroOut += '$'; + return ExpandMacroResult::Ok; + } + if (macroName == "hostSystemName") { + if (version < 3) { + return ExpandMacroResult::Error; + } + macroOut += cmSystemTools::GetSystemName(); + return ExpandMacroResult::Ok; + } + // Enable fileDir macro expansion for non-preset expanders + if (macroName == "fileDir" && File) { + if (version < 4) { + return ExpandMacroResult::Error; + } + macroOut += cmSystemTools::GetParentDirectory(File.value()); + return ExpandMacroResult::Ok; + } + if (macroName == "pathListSep") { + if (version < 5) { + return ExpandMacroResult::Error; + } + macroOut += cmSystemTools::GetSystemPathlistSeparator(); + return ExpandMacroResult::Ok; + } + } + + return ExpandMacroResult::Ignore; +} + bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate( - const std::vector& expanders, int version, + MacroExpanderVector const& expanders, int version, cm::optional& out) const { std::string lhs = this->Lhs; @@ -666,7 +680,7 @@ bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate( } bool cmCMakePresetsGraphInternal::InListCondition::Evaluate( - const std::vector& expanders, int version, + MacroExpanderVector const& expanders, int version, cm::optional& out) const { std::string str = this->String; @@ -685,7 +699,7 @@ bool cmCMakePresetsGraphInternal::InListCondition::Evaluate( } bool cmCMakePresetsGraphInternal::MatchesCondition::Evaluate( - const std::vector& expanders, int version, + MacroExpanderVector const& expanders, int version, cm::optional& out) const { std::string str = this->String; @@ -703,7 +717,7 @@ bool cmCMakePresetsGraphInternal::MatchesCondition::Evaluate( } bool cmCMakePresetsGraphInternal::AnyAllOfCondition::Evaluate( - const std::vector& expanders, int version, + MacroExpanderVector const& expanders, int version, cm::optional& out) const { for (auto const& condition : this->Conditions) { @@ -729,7 +743,7 @@ bool cmCMakePresetsGraphInternal::AnyAllOfCondition::Evaluate( } bool cmCMakePresetsGraphInternal::NotCondition::Evaluate( - const std::vector& expanders, int version, + MacroExpanderVector const& expanders, int version, cm::optional& out) const { out.reset(); diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h index 5c76e0e..a67be21 100644 --- a/Source/cmCMakePresetsGraphInternal.h +++ b/Source/cmCMakePresetsGraphInternal.h @@ -11,6 +11,7 @@ #include "cmCMakePresetsGraph.h" #include "cmJSONHelpers.h" +#include "cmSystemTools.h" #define CHECK_OK(expr) \ do { \ @@ -27,17 +28,25 @@ enum class ExpandMacroResult Error, }; -using MacroExpander = std::function; +class MacroExpander +{ +public: + virtual ExpandMacroResult operator()(const std::string& macroNamespace, + const std::string& macroName, + std::string& macroOut, + int version) const = 0; + virtual ~MacroExpander() = default; +}; +using MacroExpanderVector = std::vector>; -ExpandMacroResult ExpandMacros( - std::string& out, const std::vector& macroExpanders, - int version); +ExpandMacroResult ExpandMacros(std::string& out, + MacroExpanderVector const& macroExpanders, + int version); ExpandMacroResult ExpandMacro(std::string& out, const std::string& macroNamespace, const std::string& macroName, - const std::vector& macroExpanders, + MacroExpanderVector const& macroExpanders, int version); } @@ -47,17 +56,79 @@ public: virtual ~Condition() = default; virtual bool Evaluate( - const std::vector& expanders, + const cmCMakePresetsGraphInternal::MacroExpanderVector& expanders, int version, cm::optional& out) const = 0; virtual bool IsNull() const { return false; } }; namespace cmCMakePresetsGraphInternal { +class BaseMacroExpander : public MacroExpander +{ + cmCMakePresetsGraph const& Graph; + cm::optional File; + +public: + BaseMacroExpander(const cmCMakePresetsGraph& graph) + : Graph(graph) + { + } + BaseMacroExpander(const cmCMakePresetsGraph& graph, const std::string& file) + : Graph(graph) + , File(file) + { + } + ExpandMacroResult operator()(const std::string& macroNamespace, + const std::string& macroName, + std::string& macroOut, + int version) const override; +}; + +template +class PresetMacroExpander : public MacroExpander +{ + cmCMakePresetsGraph const& Graph; + T const& Preset; + +public: + PresetMacroExpander(const cmCMakePresetsGraph& graph, const T& preset) + : Graph(graph) + , Preset(preset) + { + } + ExpandMacroResult operator()(const std::string& macroNamespace, + const std::string& macroName, + std::string& macroOut, + int version) const override + { + if (macroNamespace.empty()) { + if (macroName == "presetName") { + macroOut += Preset.Name; + return ExpandMacroResult::Ok; + } + if (macroName == "generator") { + // Generator only makes sense if preset is not hidden. + if (!Preset.Hidden) { + macroOut += Graph.GetGeneratorForPreset(Preset.Name); + } + return ExpandMacroResult::Ok; + } + if (macroName == "fileDir") { + if (version < 4) { + return ExpandMacroResult::Error; + } + macroOut += + cmSystemTools::GetParentDirectory(Preset.OriginFile->Filename); + return ExpandMacroResult::Ok; + } + } + return ExpandMacroResult::Ignore; + } +}; class NullCondition : public cmCMakePresetsGraph::Condition { - bool Evaluate(const std::vector& /*expanders*/, - int /*version*/, cm::optional& out) const override + bool Evaluate(MacroExpanderVector const& /*expanders*/, int /*version*/, + cm::optional& out) const override { out = true; return true; @@ -69,8 +140,8 @@ class NullCondition : public cmCMakePresetsGraph::Condition class ConstCondition : public cmCMakePresetsGraph::Condition { public: - bool Evaluate(const std::vector& /*expanders*/, - int /*version*/, cm::optional& out) const override + bool Evaluate(MacroExpanderVector const& /*expanders*/, int /*version*/, + cm::optional& out) const override { out = this->Value; return true; @@ -82,7 +153,7 @@ public: class EqualsCondition : public cmCMakePresetsGraph::Condition { public: - bool Evaluate(const std::vector& expanders, int version, + bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::string Lhs; @@ -92,7 +163,7 @@ public: class InListCondition : public cmCMakePresetsGraph::Condition { public: - bool Evaluate(const std::vector& expanders, int version, + bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::string String; @@ -102,7 +173,7 @@ public: class MatchesCondition : public cmCMakePresetsGraph::Condition { public: - bool Evaluate(const std::vector& expanders, int version, + bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::string String; @@ -112,7 +183,7 @@ public: class AnyAllOfCondition : public cmCMakePresetsGraph::Condition { public: - bool Evaluate(const std::vector& expanders, int version, + bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::vector> Conditions; @@ -122,7 +193,7 @@ public: class NotCondition : public cmCMakePresetsGraph::Condition { public: - bool Evaluate(const std::vector& expanders, int version, + bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::unique_ptr SubCondition; diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index 0d8ec63..47a3514 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -35,6 +35,7 @@ using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; using JSONHelperBuilder = cmJSONHelperBuilder; using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult; using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander; +using MacroExpanderVector = cmCMakePresetsGraphInternal::MacroExpanderVector; using cmCMakePresetsGraphInternal::ExpandMacros; constexpr int MIN_VERSION = 1; @@ -297,6 +298,29 @@ auto const RootPresetsHelper = false) .Bind("$schema"_s, nullptr, cmCMakePresetsGraphInternal::SchemaHelper(), false); + +class EnvironmentMacroExpander : public MacroExpander +{ +public: + ExpandMacroResult operator()(const std::string& macroNamespace, + const std::string& macroName, + std::string& macroOut, + int /*version*/) const override + { + if (macroNamespace == "penv") { + if (macroName.empty()) { + return ExpandMacroResult::Error; + } + if (cm::optional value = + cmSystemTools::GetEnvVar(macroName)) { + macroOut += *value; + } + return ExpandMacroResult::Ok; + } + + return ExpandMacroResult::Ignore; + } +}; } namespace cmCMakePresetsGraphInternal { @@ -706,26 +730,9 @@ bool cmCMakePresetsGraph::ReadJSONFile(const std::string& filename, return true; }; - std::vector macroExpanders; - - MacroExpander environmentMacroExpander = - [](const std::string& macroNamespace, const std::string& macroName, - std::string& expanded, int /*version*/) -> ExpandMacroResult { - if (macroNamespace == "penv") { - if (macroName.empty()) { - return ExpandMacroResult::Error; - } - if (cm::optional value = - cmSystemTools::GetEnvVar(macroName)) { - expanded += *value; - } - return ExpandMacroResult::Ok; - } - - return ExpandMacroResult::Ignore; - }; + MacroExpanderVector macroExpanders{}; - macroExpanders.push_back(environmentMacroExpander); + macroExpanders.push_back(cm::make_unique()); for (Json::ArrayIndex i = 0; i < presets.Include.size(); ++i) { auto include = presets.Include[i]; -- cgit v0.12