Przeglądaj źródła

Merge topic 'preset-includes-macro-expansion'

f552ba6e6d presets: add support for macro expansion to includes
1df24df01f presets: Fix encoding of env/penv macro expansion on Windows

Acked-by: Kitware Robot <[email protected]>
Merge-request: !8255
Brad King 2 lat temu
rodzic
commit
d5095028ea

+ 3 - 0
Help/manual/cmake-presets.7.rst

@@ -133,6 +133,9 @@ Files directly or indirectly included from ``CMakePresets.json`` should be
 guaranteed to be provided by the project. ``CMakeUserPresets.json`` may
 include files from anywhere.
 
+Starting from version ``7``, the ``include`` field supports
+`macro expansion`_, but only ``$penv{}`` macro expansion.
+
 Configure Preset
 ^^^^^^^^^^^^^^^^
 

+ 7 - 0
Help/release/dev/preset-includes-macro-expansion.rst

@@ -0,0 +1,7 @@
+preset-includes-macro-expansion
+-------------------------------
+
+* :manual:`cmake-presets(7)` files now support schema version ``7``.
+
+* :manual:`cmake-presets(7)` now supports ``$penv{}`` macro expansion
+  in ``include`` fields.

+ 11 - 18
Source/cmCMakePresetsGraph.cxx

@@ -4,7 +4,6 @@
 
 #include <algorithm>
 #include <cassert>
-#include <cstdlib>
 #include <functional>
 #include <iostream>
 #include <iterator>
@@ -49,6 +48,7 @@ template <typename T>
 using PresetPair = cmCMakePresetsGraph::PresetPair<T>;
 using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
 using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
+using cmCMakePresetsGraphInternal::ExpandMacros;
 
 void InheritString(std::string& child, const std::string& parent)
 {
@@ -204,14 +204,6 @@ bool IsValidMacroNamespace(const std::string& str)
 ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
                            const std::vector<MacroExpander>& macroExpanders,
                            int version);
-ExpandMacroResult ExpandMacros(
-  std::string& out, const std::vector<MacroExpander>& macroExpanders,
-  int version);
-ExpandMacroResult ExpandMacro(std::string& out,
-                              const std::string& macroNamespace,
-                              const std::string& macroName,
-                              const std::vector<MacroExpander>& macroExpanders,
-                              int version);
 
 bool ExpandMacros(const cmCMakePresetsGraph& graph,
                   const ConfigurePreset& preset,
@@ -448,9 +440,9 @@ bool ExpandMacros(cmCMakePresetsGraph& graph, const T& preset,
       if (macroName.empty()) {
         return ExpandMacroResult::Error;
       }
-      const char* value = std::getenv(macroName.c_str());
-      if (value) {
-        result += value;
+      if (cm::optional<std::string> value =
+            cmSystemTools::GetEnvVar(macroName)) {
+        result += *value;
       }
       return ExpandMacroResult::Ok;
     }
@@ -515,8 +507,9 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
   status = CycleStatus::Verified;
   return ExpandMacroResult::Ok;
 }
+}
 
-ExpandMacroResult ExpandMacros(
+ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacros(
   std::string& out, const std::vector<MacroExpander>& macroExpanders,
   int version)
 {
@@ -595,11 +588,10 @@ ExpandMacroResult ExpandMacros(
   return ExpandMacroResult::Ok;
 }
 
-ExpandMacroResult ExpandMacro(std::string& out,
-                              const std::string& macroNamespace,
-                              const std::string& macroName,
-                              const std::vector<MacroExpander>& macroExpanders,
-                              int version)
+ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacro(
+  std::string& out, const std::string& macroNamespace,
+  const std::string& macroName,
+  const std::vector<MacroExpander>& macroExpanders, int version)
 {
   for (auto const& macroExpander : macroExpanders) {
     auto result = macroExpander(macroNamespace, macroName, out, version);
@@ -615,6 +607,7 @@ ExpandMacroResult ExpandMacro(std::string& out,
   return ExpandMacroResult::Error;
 }
 
+namespace {
 template <typename T>
 bool SetupWorkflowConfigurePreset(const T& preset,
                                   const ConfigurePreset*& configurePreset,

+ 10 - 0
Source/cmCMakePresetsGraphInternal.h

@@ -28,6 +28,16 @@ enum class ExpandMacroResult
 
 using MacroExpander = std::function<ExpandMacroResult(
   const std::string&, const std::string&, std::string&, int version)>;
+
+ExpandMacroResult ExpandMacros(
+  std::string& out, const std::vector<MacroExpander>& macroExpanders,
+  int version);
+
+ExpandMacroResult ExpandMacro(std::string& out,
+                              const std::string& macroNamespace,
+                              const std::string& macroName,
+                              const std::vector<MacroExpander>& macroExpanders,
+                              int version);
 }
 
 class cmCMakePresetsGraph::Condition

+ 36 - 1
Source/cmCMakePresetsGraphReadJSON.cxx

@@ -33,6 +33,9 @@ using PackagePreset = cmCMakePresetsGraph::PackagePreset;
 using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
 using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
 using JSONHelperBuilder = cmJSONHelperBuilder;
+using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
+using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
+using cmCMakePresetsGraphInternal::ExpandMacros;
 
 constexpr int MIN_VERSION = 1;
 constexpr int MAX_VERSION = 7;
@@ -688,7 +691,39 @@ bool cmCMakePresetsGraph::ReadJSONFile(const std::string& filename,
     return true;
   };
 
-  for (auto include : presets.Include) {
+  std::vector<MacroExpander> 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<std::string> value =
+            cmSystemTools::GetEnvVar(macroName)) {
+        expanded += *value;
+      }
+      return ExpandMacroResult::Ok;
+    }
+
+    return ExpandMacroResult::Ignore;
+  };
+
+  macroExpanders.push_back(environmentMacroExpander);
+
+  for (Json::ArrayIndex i = 0; i < presets.Include.size(); ++i) {
+    auto include = presets.Include[i];
+
+    // Support for macro expansion in includes added in version 7
+    if (v >= 7) {
+      if (ExpandMacros(include, macroExpanders, v) != ExpandMacroResult::Ok) {
+        cmCMakePresetErrors::INVALID_INCLUDE(&root["include"][i],
+                                             &this->parseState);
+        return false;
+      }
+    }
+
     if (!cmSystemTools::FileIsFullPath(include)) {
       auto directory = cmSystemTools::GetFilenamePath(filename);
       include = cmStrCat(directory, '/', include);

+ 1 - 0
Tests/RunCMake/CMakePresets/EmptyPenvInInclude-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/CMakePresets/EmptyPenvInInclude-stderr.txt

@@ -0,0 +1,5 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/EmptyPenvInInclude:
+Error: @3,15: Invalid "include" field
+  "include": \["\$penv\{\}"\],
+              \^$

+ 11 - 0
Tests/RunCMake/CMakePresets/EmptyPenvInInclude.json.in

@@ -0,0 +1,11 @@
+{
+  "version": 7,
+  "include": ["$penv{}"],
+  "configurePresets": [
+    {
+      "name": "EmptyPenvInInclude",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ]
+}

+ 5 - 0
Tests/RunCMake/CMakePresets/IncludeExpansion-stdout.txt

@@ -0,0 +1,5 @@
+^Not searching for unused variables given on the command line\.
+Available configure presets:
+
+  "Include"
+  "IncludeCommon"$

+ 10 - 0
Tests/RunCMake/CMakePresets/IncludeExpansion.json.in

@@ -0,0 +1,10 @@
+{
+  "version": 7,
+  "include": ["$penv{TEST_ENV_INCLUDE_DIR}/IncludeCommon.json"],
+  "configurePresets": [
+    {
+      "name": "Include",
+      "inherits": ["IncludeCommon"]
+    }
+  ]
+}

+ 7 - 0
Tests/RunCMake/CMakePresets/RunCMakeTest.cmake

@@ -146,6 +146,7 @@ run_cmake_presets(NoSuchMacro)
 run_cmake_presets(EnvCycle)
 run_cmake_presets(EmptyEnv)
 run_cmake_presets(EmptyPenv)
+run_cmake_presets(EmptyPenvInInclude)
 run_cmake_presets(InvalidRegex)
 set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
 run_cmake_presets(ConditionFuture)
@@ -393,6 +394,12 @@ set(CMakePresets_EXTRA_FILES
   "${RunCMake_SOURCE_DIR}/subdir/CMakePresets.json.in"
   )
 run_cmake_presets(Include --list-presets)
+set(CMakePresets_EXTRA_FILES
+  "${RunCMake_SOURCE_DIR}/IncludeCommon.json.in"
+  )
+set(ENV{TEST_ENV_INCLUDE_DIR} ${RunCMake_BINARY_DIR}/IncludeExpansion)
+run_cmake_presets(IncludeExpansion --list-presets)
+unset(ENV{TEST_ENV_INCLUDE_DIR})
 unset(CMakePresets_EXTRA_FILES)
 run_cmake_presets(IncludeNotFound)
 run_cmake_presets(IncludeCycle)