/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file LICENSE.rst or https://cmake.org/licensing for details. */ #pragma once #include #include #include #include #include #include #include #include #include "cmCMakePresetsErrors.h" #include "cmCMakePresetsGraph.h" #include "cmJSONHelpers.h" #include "cmSystemTools.h" #define CHECK_OK(expr) \ do { \ auto _result = expr; \ if (_result != true) \ return _result; \ } while (false) namespace cmCMakePresetsGraphInternal { enum class ExpandMacroResult { Ok, Ignore, Defer, Error, }; class MacroExpander { public: virtual ExpandMacroResult operator()(std::string const& macroNamespace, std::string const& macroName, std::string& macroOut, int version) const = 0; virtual ~MacroExpander() = default; }; using MacroExpanderVector = std::vector>; ExpandMacroResult ExpandMacros(std::string& out, MacroExpanderVector const& macroExpanders, int version); ExpandMacroResult ExpandMacro(std::string& out, std::string const& macroNamespace, std::string const& macroName, MacroExpanderVector const& macroExpanders, int version); } class cmCMakePresetsGraph::Condition { public: virtual ~Condition() = default; std::string ConditionJson; virtual bool Evaluate( cmCMakePresetsGraphInternal::MacroExpanderVector const& 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(cmCMakePresetsGraph const& graph) : Graph(graph) { } BaseMacroExpander(cmCMakePresetsGraph const& graph, std::string const& file) : Graph(graph) , File(file) { } ExpandMacroResult operator()(std::string const& macroNamespace, std::string const& macroName, std::string& macroOut, int version) const override; }; template std::string const* GetConfigurePresetName(T const& /*preset*/) { return nullptr; } inline std::string const* GetConfigurePresetName( cmCMakePresetsGraph::ConfigurePreset const& preset) { return &preset.Name; } inline std::string const* GetConfigurePresetName( cmCMakePresetsGraph::BuildPreset const& preset) { return &preset.ConfigurePreset; } inline std::string const* GetConfigurePresetName( cmCMakePresetsGraph::TestPreset const& preset) { return &preset.ConfigurePreset; } inline std::string const* GetConfigurePresetName( cmCMakePresetsGraph::PackagePreset const& preset) { return &preset.ConfigurePreset; } template class PresetMacroExpander : public MacroExpander { cmCMakePresetsGraph const& Graph; T const& Preset; public: PresetMacroExpander(cmCMakePresetsGraph const& graph, T const& preset) : Graph(graph) , Preset(preset) { } ExpandMacroResult operator()(std::string const& macroNamespace, std::string const& macroName, std::string& macroOut, int version) const override { if (macroNamespace.empty()) { if (macroName == "presetName") { macroOut += Preset.Name; return ExpandMacroResult::Ok; } if (macroName == "configurePresetName") { if (version < 13) { return ExpandMacroResult::Error; } if (auto const* configurePresetName = GetConfigurePresetName(Preset)) { macroOut += *configurePresetName; return ExpandMacroResult::Ok; } return ExpandMacroResult::Error; } 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; } }; template class ImmediateMacroExpander : public MacroExpander { T const& Preset; public: ImmediateMacroExpander(T const& preset) : Preset(preset) { } ExpandMacroResult operator()(std::string const& macroNamespace, std::string const& macroName, std::string& macroOut, int version) const override { if (macroNamespace.empty()) { if (macroName == "fileDir") { if (version < 12) { return ExpandMacroResult::Defer; } macroOut += cmSystemTools::GetParentDirectory(Preset.OriginFile->Filename); return ExpandMacroResult::Ok; } } return ExpandMacroResult::Defer; } }; template bool ExpandImmediateMacros(T& preset); extern template bool ExpandImmediateMacros< cmCMakePresetsGraph::ConfigurePreset>(cmCMakePresetsGraph::ConfigurePreset&); extern template bool ExpandImmediateMacros( cmCMakePresetsGraph::BuildPreset&); extern template bool ExpandImmediateMacros( cmCMakePresetsGraph::TestPreset&); extern template bool ExpandImmediateMacros( cmCMakePresetsGraph::PackagePreset&); extern template bool ExpandImmediateMacros< cmCMakePresetsGraph::WorkflowPreset>(cmCMakePresetsGraph::WorkflowPreset&); class NullCondition : public cmCMakePresetsGraph::Condition { bool Evaluate(MacroExpanderVector const& /*expanders*/, int /*version*/, cm::optional& out) const override { out = true; return true; } bool IsNull() const override { return true; } }; class ConstCondition : public cmCMakePresetsGraph::Condition { public: bool Evaluate(MacroExpanderVector const& /*expanders*/, int /*version*/, cm::optional& out) const override { out = this->Value; return true; } bool Value; }; class EqualsCondition : public cmCMakePresetsGraph::Condition { public: bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::string Lhs; std::string Rhs; }; class InListCondition : public cmCMakePresetsGraph::Condition { public: bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::string String; std::vector List; }; class MatchesCondition : public cmCMakePresetsGraph::Condition { public: bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::string String; std::string Regex; }; class AnyAllOfCondition : public cmCMakePresetsGraph::Condition { public: bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::vector> Conditions; bool StopValue; }; class NotCondition : public cmCMakePresetsGraph::Condition { public: bool Evaluate(MacroExpanderVector const& expanders, int version, cm::optional& out) const override; std::unique_ptr SubCondition; }; bool PresetStringHelper(std::string& out, Json::Value const* value, cmJSONState* state); bool PresetNameHelper(std::string& out, Json::Value const* value, cmJSONState* state); bool PresetVectorStringHelper(std::vector& out, Json::Value const* value, cmJSONState* state); bool PresetBoolHelper(bool& out, Json::Value const* value, cmJSONState* state); bool PresetOptionalBoolHelper(cm::optional& out, Json::Value const* value, cmJSONState* state); template bool PresetMapToBoolHelper(std::map& out, Json::Value const* value, K key, cmJSONState* state) { cm::optional temp; if (!PresetOptionalBoolHelper(temp, value, state)) { return false; } if (temp) { out[key] = *temp; } return true; } bool PresetIntHelper(int& out, Json::Value const* value, cmJSONState* state); bool PresetOptionalIntHelper(cm::optional& out, Json::Value const* value, cmJSONState* state); bool PresetUIntHelper(unsigned int& out, Json::Value const* value, cmJSONState* state); bool PresetOptionalUIntHelper(cm::optional& out, Json::Value const* value, cmJSONState* state); bool PresetVectorIntHelper(std::vector& out, Json::Value const* value, cmJSONState* state); bool ConfigurePresetsHelper( std::vector& out, Json::Value const* value, cmJSONState* state); bool BuildPresetsHelper(std::vector& out, Json::Value const* value, cmJSONState* state); bool TestPresetsHelper(std::vector& out, Json::Value const* value, cmJSONState* state); bool PackagePresetsHelper(std::vector& out, Json::Value const* value, cmJSONState* state); bool WorkflowPresetsHelper( std::vector& out, Json::Value const* value, cmJSONState* state); cm::string_view GetDiagnosticJSONName(cmDiagnosticCategory category); cmJSONHelper VendorHelper(ErrorGenerator const& error); bool PresetConditionHelper( std::shared_ptr& out, Json::Value const* value, cmJSONState* state); bool PresetVectorOneOrMoreStringHelper(std::vector& out, Json::Value const* value, cmJSONState* state); bool EnvironmentMapHelper( std::map>& out, Json::Value const* value, cmJSONState* state); cmJSONHelper SchemaHelper(); bool CheckDiagnostics(cmJSONState* state, int version, cmCMakePresetsGraph::ConfigurePreset& preset); // Binds the fields common to every preset kind. template cmJSONHelperBuilder::Object BindPresetIdentityFields( cmJSONHelperBuilder::Object obj) { obj.Bind("name"_s, &cmCMakePresetsGraph::Preset::Name, PresetNameHelper) .Bind("inherits"_s, &cmCMakePresetsGraph::Preset::Inherits, PresetVectorOneOrMoreStringHelper, false) .Bind("hidden"_s, &cmCMakePresetsGraph::Preset::Hidden, PresetBoolHelper, false) .template Bind( "vendor"_s, nullptr, VendorHelper(cmCMakePresetsErrors::INVALID_PRESET), false) .Bind("displayName"_s, &cmCMakePresetsGraph::Preset::DisplayName, PresetStringHelper, false) .Bind("description"_s, &cmCMakePresetsGraph::Preset::Description, PresetStringHelper, false) .Bind("condition"_s, &cmCMakePresetsGraph::Preset::ConditionEvaluator, PresetConditionHelper, false); return obj; } // Binds the fields shared by build, test, and package presets, which resolve // against a configure preset. template cmJSONHelperBuilder::Object BindDependentPresetFields( cmJSONHelperBuilder::Object obj) { obj .Bind("environment"_s, &cmCMakePresetsGraph::Preset::Environment, EnvironmentMapHelper, false) .Bind("configurePreset"_s, &T::ConfigurePreset, PresetStringHelper, false) .Bind("inheritConfigureEnvironment"_s, &T::InheritConfigureEnvironment, PresetOptionalBoolHelper, false); return obj; } }