소스 검색

cmCMakePresetsGraph: Add package presets

Kyle Edwards 3 년 전
부모
커밋
b699610df4

+ 1 - 0
Source/CMakeLists.txt

@@ -168,6 +168,7 @@ set(SRCS
   cmCMakePresetsGraphReadJSON.cxx
   cmCMakePresetsGraphReadJSONBuildPresets.cxx
   cmCMakePresetsGraphReadJSONConfigurePresets.cxx
+  cmCMakePresetsGraphReadJSONPackagePresets.cxx
   cmCMakePresetsGraphReadJSONTestPresets.cxx
   cmCommandArgumentParserHelper.cxx
   cmCommonTargetGenerator.cxx

+ 117 - 0
Source/cmCMakePresetsGraph.cxx

@@ -43,6 +43,7 @@ using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
 using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
 using BuildPreset = cmCMakePresetsGraph::BuildPreset;
 using TestPreset = cmCMakePresetsGraph::TestPreset;
+using PackagePreset = cmCMakePresetsGraph::PackagePreset;
 using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
 using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
 
@@ -301,6 +302,28 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset,
   return true;
 }
 
+bool ExpandMacros(const cmCMakePresetsGraph& graph,
+                  const PackagePreset& preset,
+                  cm::optional<PackagePreset>& out,
+                  const std::vector<MacroExpander>& macroExpanders)
+{
+  for (auto& variable : out->Variables) {
+    CHECK_EXPAND(out, variable.second, macroExpanders,
+                 graph.GetVersion(preset));
+  }
+
+  CHECK_EXPAND(out, out->ConfigFile, macroExpanders, graph.GetVersion(preset));
+  CHECK_EXPAND(out, out->PackageName, macroExpanders,
+               graph.GetVersion(preset));
+  CHECK_EXPAND(out, out->PackageVersion, macroExpanders,
+               graph.GetVersion(preset));
+  CHECK_EXPAND(out, out->PackageDirectory, macroExpanders,
+               graph.GetVersion(preset));
+  CHECK_EXPAND(out, out->VendorName, macroExpanders, graph.GetVersion(preset));
+
+  return true;
+}
+
 template <class T>
 bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset,
                   cm::optional<T>& out)
@@ -868,6 +891,44 @@ cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(int /* version */)
   return ReadFileResult::READ_OK;
 }
 
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
+  const cmCMakePresetsGraph::Preset& parentPreset)
+{
+  auto& preset = *this;
+  const PackagePreset& parent =
+    static_cast<const PackagePreset&>(parentPreset);
+
+  InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
+  InheritOptionalValue(preset.InheritConfigureEnvironment,
+                       parent.InheritConfigureEnvironment);
+  InheritVector(preset.Generators, parent.Generators);
+  InheritVector(preset.Configurations, parent.Configurations);
+
+  for (auto const& v : parent.Variables) {
+    preset.Variables.insert(v);
+  }
+
+  InheritOptionalValue(preset.DebugOutput, parent.DebugOutput);
+  InheritOptionalValue(preset.VerboseOutput, parent.VerboseOutput);
+  InheritString(preset.PackageName, parent.PackageName);
+  InheritString(preset.PackageVersion, parent.PackageVersion);
+  InheritString(preset.PackageDirectory, parent.PackageDirectory);
+  InheritString(preset.VendorName, parent.VendorName);
+
+  return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(int /* version */)
+{
+  auto& preset = *this;
+  if (!preset.Hidden && preset.ConfigurePreset.empty()) {
+    return ReadFileResult::INVALID_PRESET;
+  }
+  return ReadFileResult::READ_OK;
+}
+
 std::string cmCMakePresetsGraph::GetFilename(const std::string& sourceDir)
 {
   return cmStrCat(sourceDir, "/CMakePresets.json");
@@ -930,6 +991,7 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
   CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this));
   CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this));
   CHECK_OK(ComputePresetInheritance(this->TestPresets, *this));
+  CHECK_OK(ComputePresetInheritance(this->PackagePresets, *this));
 
   for (auto& it : this->ConfigurePresets) {
     if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
@@ -985,6 +1047,30 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
     }
   }
 
+  for (auto& it : this->PackagePresets) {
+    if (!it.second.Unexpanded.Hidden) {
+      const auto configurePreset =
+        this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
+      if (configurePreset == this->ConfigurePresets.end()) {
+        return ReadFileResult::INVALID_CONFIGURE_PRESET;
+      }
+      if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
+            configurePreset->second.Unexpanded.OriginFile)) {
+        return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE;
+      }
+
+      if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
+        it.second.Unexpanded.Environment.insert(
+          configurePreset->second.Unexpanded.Environment.begin(),
+          configurePreset->second.Unexpanded.Environment.end());
+      }
+    }
+
+    if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+      return ReadFileResult::INVALID_MACRO_EXPANSION;
+    }
+  }
+
   return ReadFileResult::READ_OK;
 }
 
@@ -1028,6 +1114,8 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result)
     case ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED:
       return "File version must be 2 or higher for build and test preset "
              "support.";
+    case ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED:
+      return "File version must be 5 or higher for package preset support";
     case ReadFileResult::INCLUDE_UNSUPPORTED:
       return "File version must be 4 or higher for include support";
     case ReadFileResult::INVALID_INCLUDE:
@@ -1173,10 +1261,39 @@ void cmCMakePresetsGraph::PrintTestPresetList(
   }
 }
 
+void cmCMakePresetsGraph::PrintPackagePresetList(
+  PrintPrecedingNewline* newline) const
+{
+  this->PrintPackagePresetList([](const PackagePreset&) { return true; },
+                               newline);
+}
+
+void cmCMakePresetsGraph::PrintPackagePresetList(
+  const std::function<bool(const PackagePreset&)>& filter,
+  PrintPrecedingNewline* newline) const
+{
+  std::vector<const cmCMakePresetsGraph::Preset*> presets;
+  for (auto const& p : this->PackagePresetOrder) {
+    auto const& preset = this->PackagePresets.at(p);
+    if (!preset.Unexpanded.Hidden && preset.Expanded &&
+        preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
+      presets.push_back(
+        static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded));
+    }
+  }
+
+  if (!presets.empty()) {
+    printPrecedingNewline(newline);
+    std::cout << "Available package presets:\n\n";
+    cmCMakePresetsGraph::PrintPresets(presets);
+  }
+}
+
 void cmCMakePresetsGraph::PrintAllPresets() const
 {
   PrintPrecedingNewline newline = PrintPrecedingNewline::False;
   this->PrintConfigurePresetList(&newline);
   this->PrintBuildPresetList(&newline);
   this->PrintTestPresetList(&newline);
+  this->PrintPackagePresetList(&newline);
 }

+ 43 - 0
Source/cmCMakePresetsGraph.h

@@ -41,6 +41,7 @@ public:
     CONFIGURE_PRESET_UNREACHABLE_FROM_FILE,
     INVALID_MACRO_EXPANSION,
     BUILD_TEST_PRESETS_UNSUPPORTED,
+    PACKAGE_PRESETS_UNSUPPORTED,
     INCLUDE_UNSUPPORTED,
     INVALID_INCLUDE,
     INVALID_CONFIGURE_PRESET,
@@ -326,6 +327,42 @@ public:
     ReadFileResult VisitPresetAfterInherit(int /* version */) override;
   };
 
+  class PackagePreset : public Preset
+  {
+  public:
+    PackagePreset() = default;
+    PackagePreset(PackagePreset&& /*other*/) = default;
+    PackagePreset(const PackagePreset& /*other*/) = default;
+    PackagePreset& operator=(const PackagePreset& /*other*/) = default;
+    ~PackagePreset() override = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+    PackagePreset& operator=(PackagePreset&& /*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.
+    PackagePreset& operator=(PackagePreset&& /*other*/) = delete;
+#endif
+
+    std::string ConfigurePreset;
+    cm::optional<bool> InheritConfigureEnvironment;
+    std::vector<std::string> Generators;
+    std::vector<std::string> Configurations;
+    std::map<std::string, std::string> Variables;
+    std::string ConfigFile;
+
+    cm::optional<bool> DebugOutput;
+    cm::optional<bool> VerboseOutput;
+
+    std::string PackageName;
+    std::string PackageVersion;
+    std::string PackageDirectory;
+    std::string VendorName;
+
+    ReadFileResult VisitPresetInherit(const Preset& parent) override;
+    ReadFileResult VisitPresetAfterInherit(int /* version */) override;
+  };
+
   template <class T>
   class PresetPair
   {
@@ -337,10 +374,12 @@ public:
   std::map<std::string, PresetPair<ConfigurePreset>> ConfigurePresets;
   std::map<std::string, PresetPair<BuildPreset>> BuildPresets;
   std::map<std::string, PresetPair<TestPreset>> TestPresets;
+  std::map<std::string, PresetPair<PackagePreset>> PackagePresets;
 
   std::vector<std::string> ConfigurePresetOrder;
   std::vector<std::string> BuildPresetOrder;
   std::vector<std::string> TestPresetOrder;
+  std::vector<std::string> PackagePresetOrder;
 
   std::string SourceDir;
   std::vector<std::unique_ptr<File>> Files;
@@ -399,6 +438,10 @@ public:
     PrintPrecedingNewline* newline = nullptr) const;
   void PrintBuildPresetList(PrintPrecedingNewline* newline = nullptr) const;
   void PrintTestPresetList(PrintPrecedingNewline* newline = nullptr) const;
+  void PrintPackagePresetList(PrintPrecedingNewline* newline = nullptr) const;
+  void PrintPackagePresetList(
+    const std::function<bool(const PackagePreset&)>& filter,
+    PrintPrecedingNewline* newline = nullptr) const;
   void PrintAllPresets() const;
 
 private:

+ 4 - 0
Source/cmCMakePresetsGraphInternal.h

@@ -147,6 +147,10 @@ cmCMakePresetsGraph::ReadFileResult BuildPresetsHelper(
 cmCMakePresetsGraph::ReadFileResult TestPresetsHelper(
   std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value);
 
+cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper(
+  std::vector<cmCMakePresetsGraph::PackagePreset>& out,
+  const Json::Value* value);
+
 cmJSONHelper<std::nullptr_t, cmCMakePresetsGraph::ReadFileResult> VendorHelper(
   cmCMakePresetsGraph::ReadFileResult error);
 

+ 28 - 1
Source/cmCMakePresetsGraphReadJSON.cxx

@@ -34,7 +34,7 @@ using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
 using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>;
 
 constexpr int MIN_VERSION = 1;
-constexpr int MAX_VERSION = 5;
+constexpr int MAX_VERSION = 6;
 
 struct CMakeVersion
 {
@@ -49,6 +49,7 @@ struct RootPresets
   std::vector<cmCMakePresetsGraph::ConfigurePreset> ConfigurePresets;
   std::vector<cmCMakePresetsGraph::BuildPreset> BuildPresets;
   std::vector<cmCMakePresetsGraph::TestPreset> TestPresets;
+  std::vector<cmCMakePresetsGraph::PackagePreset> PackagePresets;
   std::vector<std::string> Include;
 };
 
@@ -281,6 +282,8 @@ auto const RootPresetsHelper =
           cmCMakePresetsGraphInternal::BuildPresetsHelper, false)
     .Bind("testPresets"_s, &RootPresets::TestPresets,
           cmCMakePresetsGraphInternal::TestPresetsHelper, false)
+    .Bind("packagePresets"_s, &RootPresets::PackagePresets,
+          cmCMakePresetsGraphInternal::PackagePresetsHelper, false)
     .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
           CMakeVersionHelper, false)
     .Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
@@ -458,6 +461,11 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
     return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
   }
 
+  // Support for package presets added in version 6.
+  if (v < 6 && root.isMember("packagePresets")) {
+    return ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED;
+  }
+
   // Support for include added in version 4.
   if (v < 4 && root.isMember("include")) {
     return ReadFileResult::INCLUDE_UNSUPPORTED;
@@ -573,6 +581,25 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
     this->TestPresetOrder.push_back(preset.Name);
   }
 
+  for (auto& preset : presets.PackagePresets) {
+    preset.OriginFile = file;
+    if (preset.Name.empty()) {
+      return ReadFileResult::INVALID_PRESET;
+    }
+
+    PresetPair<PackagePreset> presetPair;
+    presetPair.Unexpanded = preset;
+    presetPair.Expanded = cm::nullopt;
+    if (!this->PackagePresets.emplace(preset.Name, presetPair).second) {
+      return ReadFileResult::DUPLICATE_PRESETS;
+    }
+
+    // Support for conditions added in version 3, but this requires version 5
+    // already, so no action needed.
+
+    this->PackagePresetOrder.push_back(preset.Name);
+  }
+
   auto const includeFile = [this, &inProgressFiles, file](
                              const std::string& include, RootType rootType2,
                              ReadReason readReason2,

+ 95 - 0
Source/cmCMakePresetsGraphReadJSONPackagePresets.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 <cstddef>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/value.h>
+
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using PackagePreset = cmCMakePresetsGraph::PackagePreset;
+
+auto const OutputHelper =
+  cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>(
+    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+    .Bind("debug"_s, &PackagePreset::DebugOutput,
+          cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+    .Bind("verbose"_s, &PackagePreset::VerboseOutput,
+          cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
+
+auto const VariableHelper = cmJSONHelperBuilder<ReadFileResult>::String(
+  ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
+
+auto const VariablesHelper =
+  cmJSONHelperBuilder<ReadFileResult>::Map<std::string>(
+    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
+
+auto const PackagePresetHelper =
+  cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>(
+    ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+    .Bind("name"_s, &PackagePreset::Name,
+          cmCMakePresetsGraphInternal::PresetStringHelper)
+    .Bind("inherits"_s, &PackagePreset::Inherits,
+          cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
+          false)
+    .Bind("hidden"_s, &PackagePreset::Hidden,
+          cmCMakePresetsGraphInternal::PresetBoolHelper, false)
+    .Bind<std::nullptr_t>("vendor"_s, nullptr,
+                          cmCMakePresetsGraphInternal::VendorHelper(
+                            ReadFileResult::INVALID_PRESET),
+                          false)
+    .Bind("displayName"_s, &PackagePreset::DisplayName,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("description"_s, &PackagePreset::Description,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("environment"_s, &PackagePreset::Environment,
+          cmCMakePresetsGraphInternal::EnvironmentMapHelper, false)
+    .Bind("configurePreset"_s, &PackagePreset::ConfigurePreset,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("inheritConfigureEnvironment"_s,
+          &PackagePreset::InheritConfigureEnvironment,
+          cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+    .Bind("generators"_s, &PackagePreset::Generators,
+          cmCMakePresetsGraphInternal::PresetVectorStringHelper, false)
+    .Bind("configurations"_s, &PackagePreset::Configurations,
+          cmCMakePresetsGraphInternal::PresetVectorStringHelper, false)
+    .Bind("variables"_s, &PackagePreset::Variables, VariablesHelper, false)
+    .Bind("configFile"_s, &PackagePreset::ConfigFile,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("output"_s, OutputHelper, false)
+    .Bind("packageName"_s, &PackagePreset::PackageName,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("packageVersion"_s, &PackagePreset::PackageVersion,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("packageDirectory"_s, &PackagePreset::PackageDirectory,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("vendorName"_s, &PackagePreset::VendorName,
+          cmCMakePresetsGraphInternal::PresetStringHelper, false)
+    .Bind("condition"_s, &PackagePreset::ConditionEvaluator,
+          cmCMakePresetsGraphInternal::PresetConditionHelper, false);
+}
+
+namespace cmCMakePresetsGraphInternal {
+cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper(
+  std::vector<cmCMakePresetsGraph::PackagePreset>& out,
+  const Json::Value* value)
+{
+  static auto const helper =
+    cmJSONHelperBuilder<ReadFileResult>::Vector<PackagePreset>(
+      ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+      PackagePresetHelper);
+
+  return helper(out, value);
+}
+}