Browse Source

CMake: Add presets functionality

Kyle Edwards 5 years ago
parent
commit
8617479061
100 changed files with 1380 additions and 46 deletions
  1. 2 2
      Source/cmCMakePresetsFile.cxx
  2. 4 4
      Source/cmCMakePresetsFile.h
  3. 306 33
      Source/cmake.cxx
  4. 48 6
      Source/cmake.h
  5. 6 1
      Source/cmakemain.cxx
  6. 1 0
      Tests/RunCMake/CMakeLists.txt
  7. 1 0
      Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt
  8. 11 0
      Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt
  9. 0 0
      Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
  10. 1 0
      Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
  11. 11 0
      Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt
  12. 4 0
      Tests/RunCMake/CMakePresets/CMakeLists.txt.in
  13. 481 0
      Tests/RunCMake/CMakePresets/CMakePresets.json.in
  14. 2 0
      Tests/RunCMake/CMakePresets/CacheOverride.cmake
  15. 1 0
      Tests/RunCMake/CMakePresets/CyclicInheritance0-result.txt
  16. 2 0
      Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt
  17. 13 0
      Tests/RunCMake/CMakePresets/CyclicInheritance0.json.in
  18. 1 0
      Tests/RunCMake/CMakePresets/CyclicInheritance1-result.txt
  19. 2 0
      Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt
  20. 21 0
      Tests/RunCMake/CMakePresets/CyclicInheritance1.json.in
  21. 1 0
      Tests/RunCMake/CMakePresets/CyclicInheritance2-result.txt
  22. 2 0
      Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt
  23. 29 0
      Tests/RunCMake/CMakePresets/CyclicInheritance2.json.in
  24. 1 0
      Tests/RunCMake/CMakePresets/Debug-stderr.txt
  25. 4 0
      Tests/RunCMake/CMakePresets/Debug-stdout.txt
  26. 4 0
      Tests/RunCMake/CMakePresets/Debug.cmake
  27. 19 0
      Tests/RunCMake/CMakePresets/Debug.json.in
  28. 3 0
      Tests/RunCMake/CMakePresets/DebugBase.cmake
  29. 1 0
      Tests/RunCMake/CMakePresets/DisableWarningFlags.cmake
  30. 1 0
      Tests/RunCMake/CMakePresets/DuplicatePresets-result.txt
  31. 2 0
      Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt
  32. 15 0
      Tests/RunCMake/CMakePresets/DuplicatePresets.json.in
  33. 1 0
      Tests/RunCMake/CMakePresets/EmptyPresetName-result.txt
  34. 2 0
      Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt
  35. 10 0
      Tests/RunCMake/CMakePresets/EmptyPresetName.json.in
  36. 1 0
      Tests/RunCMake/CMakePresets/EnvCycle-result.txt
  37. 1 0
      Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt
  38. 1 0
      Tests/RunCMake/CMakePresets/ErrorDeprecated-result.txt
  39. 7 0
      Tests/RunCMake/CMakePresets/ErrorDeprecated-stderr.txt
  40. 1 0
      Tests/RunCMake/CMakePresets/ErrorDeprecated.cmake
  41. 1 0
      Tests/RunCMake/CMakePresets/ErrorDev-result.txt
  42. 8 0
      Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt
  43. 1 0
      Tests/RunCMake/CMakePresets/ErrorDev.cmake
  44. 1 0
      Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-result.txt
  45. 2 0
      Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt
  46. 16 0
      Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated.json.in
  47. 1 0
      Tests/RunCMake/CMakePresets/ErrorNoWarningDev-result.txt
  48. 2 0
      Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt
  49. 16 0
      Tests/RunCMake/CMakePresets/ErrorNoWarningDev.json.in
  50. 1 0
      Tests/RunCMake/CMakePresets/ExtraPresetField-result.txt
  51. 2 0
      Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt
  52. 11 0
      Tests/RunCMake/CMakePresets/ExtraPresetField.json.in
  53. 1 0
      Tests/RunCMake/CMakePresets/ExtraRootField-result.txt
  54. 2 0
      Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt
  55. 11 0
      Tests/RunCMake/CMakePresets/ExtraRootField.json.in
  56. 1 0
      Tests/RunCMake/CMakePresets/ExtraVariableField-result.txt
  57. 2 0
      Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt
  58. 16 0
      Tests/RunCMake/CMakePresets/ExtraVariableField.json.in
  59. 46 0
      Tests/RunCMake/CMakePresets/Good-stdout.txt
  60. 45 0
      Tests/RunCMake/CMakePresets/Good.cmake
  61. 0 0
      Tests/RunCMake/CMakePresets/GoodBOM.cmake
  62. 10 0
      Tests/RunCMake/CMakePresets/GoodBOM.json.in
  63. 4 0
      Tests/RunCMake/CMakePresets/GoodBinaryCmdLine.cmake
  64. 3 0
      Tests/RunCMake/CMakePresets/GoodBinaryRelative.cmake
  65. 4 0
      Tests/RunCMake/CMakePresets/GoodBinaryUp.cmake
  66. 3 0
      Tests/RunCMake/CMakePresets/GoodGeneratorCmdLine.cmake
  67. 6 0
      Tests/RunCMake/CMakePresets/GoodInheritanceChild.cmake
  68. 3 0
      Tests/RunCMake/CMakePresets/GoodInheritanceMacro.cmake
  69. 10 0
      Tests/RunCMake/CMakePresets/GoodInheritanceMulti.cmake
  70. 3 0
      Tests/RunCMake/CMakePresets/GoodInheritanceMultiSecond.cmake
  71. 18 0
      Tests/RunCMake/CMakePresets/GoodInheritanceOverride.cmake
  72. 6 0
      Tests/RunCMake/CMakePresets/GoodInheritanceParent.cmake
  73. 0 0
      Tests/RunCMake/CMakePresets/GoodNoArgs.cmake
  74. 4 0
      Tests/RunCMake/CMakePresets/GoodNoS.cmake
  75. 0 0
      Tests/RunCMake/CMakePresets/GoodSpaces.cmake
  76. 0 0
      Tests/RunCMake/CMakePresets/GoodUserFromMain.cmake
  77. 10 0
      Tests/RunCMake/CMakePresets/GoodUserFromMain.json.in
  78. 4 0
      Tests/RunCMake/CMakePresets/GoodUserFromMainUser.json.in
  79. 0 0
      Tests/RunCMake/CMakePresets/GoodUserFromUser.cmake
  80. 4 0
      Tests/RunCMake/CMakePresets/GoodUserFromUser.json.in
  81. 10 0
      Tests/RunCMake/CMakePresets/GoodUserFromUserUser.json.in
  82. 0 0
      Tests/RunCMake/CMakePresets/GoodUserOnly.cmake
  83. 10 0
      Tests/RunCMake/CMakePresets/GoodUserOnlyUser.json.in
  84. 0 0
      Tests/RunCMake/CMakePresets/GoodWindowsBackslash.cmake
  85. 1 0
      Tests/RunCMake/CMakePresets/HighVersion-result.txt
  86. 2 0
      Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
  87. 4 0
      Tests/RunCMake/CMakePresets/HighVersion.json.in
  88. 1 0
      Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt
  89. 2 0
      Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt
  90. 11 0
      Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
  91. 1 0
      Tests/RunCMake/CMakePresets/InvalidGenerator-result.txt
  92. 3 0
      Tests/RunCMake/CMakePresets/InvalidGenerator-stderr.txt
  93. 1 0
      Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-result.txt
  94. 3 0
      Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-stderr.txt
  95. 1 0
      Tests/RunCMake/CMakePresets/InvalidInheritance-result.txt
  96. 2 0
      Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt
  97. 13 0
      Tests/RunCMake/CMakePresets/InvalidInheritance.json.in
  98. 1 0
      Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-result.txt
  99. 2 0
      Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt
  100. 10 0
      Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir.json.in

+ 2 - 2
Source/cmCMakePresetsFile.cxx

@@ -94,7 +94,7 @@ ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
     return ReadFileResult::READ_OK;
   }
   if (value->isObject()) {
-    out = CacheVariable{};
+    out.emplace();
     return VariableObjectHelper(*out, value);
   }
   if (value->isNull()) {
@@ -701,7 +701,7 @@ cmCMakePresetsFile::ExpandMacros(const UnexpandedPreset& preset) const
     }
   }
 
-  return retval;
+  return cm::make_optional(retval);
 }
 
 cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(

+ 4 - 4
Source/cmCMakePresetsFile.h

@@ -30,16 +30,16 @@ public:
   public:
 #if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
     Preset() = default;
-    Preset(const Preset& other) = default;
-    Preset(Preset&& other) = default;
+    Preset(const Preset& /*other*/) = default;
+    Preset(Preset&& /*other*/) = default;
 
-    Preset& operator=(const Preset& other) = default;
+    Preset& operator=(const Preset& /*other*/) = default;
 
     // 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. Disable the
     // move assignment operator until C++17 is enabled.
-    Preset& operator=(Preset&& other) = delete;
+    Preset& operator=(Preset&& /*other*/) = delete;
 #endif
 
     std::string Name;

+ 306 - 33
Source/cmake.cxx

@@ -13,6 +13,7 @@
 #include <utility>
 
 #include <cm/memory>
+#include <cm/optional>
 #include <cm/string_view>
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
 #  include <cm/iterator>
@@ -27,6 +28,7 @@
 
 #include "cm_sys_stat.h"
 
+#include "cmCMakePresetsFile.h"
 #include "cmCommands.h"
 #include "cmDocumentation.h"
 #include "cmDocumentationEntry.h"
@@ -286,6 +288,97 @@ void cmake::CleanupCommandsAndMacros()
   this->CurrentSnapshot.SetDefaultDefinitions();
 }
 
+#ifndef CMAKE_BOOTSTRAP
+void cmake::SetWarningFromPreset(const std::string& name,
+                                 const cm::optional<bool>& warning,
+                                 const cm::optional<bool>& error)
+{
+  if (warning) {
+    if (*warning) {
+      this->DiagLevels[name] = std::max(this->DiagLevels[name], DIAG_WARN);
+    } else {
+      this->DiagLevels[name] = DIAG_IGNORE;
+    }
+  }
+  if (error) {
+    if (*error) {
+      this->DiagLevels[name] = DIAG_ERROR;
+    } else {
+      this->DiagLevels[name] = std::min(this->DiagLevels[name], DIAG_WARN);
+    }
+  }
+}
+
+void cmake::ProcessPresetVariables()
+{
+  for (auto const& var : this->UnprocessedPresetVariables) {
+    if (!var.second) {
+      continue;
+    }
+    cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
+    if (!var.second->Type.empty()) {
+      type = cmState::StringToCacheEntryType(var.second->Type);
+    }
+    this->ProcessCacheArg(var.first, var.second->Value, type);
+  }
+}
+
+void cmake::PrintPresetVariables()
+{
+  bool first = true;
+  for (auto const& var : this->UnprocessedPresetVariables) {
+    if (!var.second) {
+      continue;
+    }
+    cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
+    if (!var.second->Type.empty()) {
+      type = cmState::StringToCacheEntryType(var.second->Type);
+    }
+    if (first) {
+      std::cout << "Preset CMake variables:\n\n";
+      first = false;
+    }
+    std::cout << "  " << var.first;
+    if (type != cmStateEnums::UNINITIALIZED) {
+      std::cout << ':' << cmState::CacheEntryTypeToString(type);
+    }
+    std::cout << "=\"" << var.second->Value << "\"\n";
+  }
+  if (!first) {
+    std::cout << '\n';
+  }
+  this->UnprocessedPresetVariables.clear();
+}
+
+void cmake::ProcessPresetEnvironment()
+{
+  for (auto const& var : this->UnprocessedPresetEnvironment) {
+    if (var.second) {
+      cmSystemTools::PutEnv(cmStrCat(var.first, '=', *var.second));
+    }
+  }
+}
+
+void cmake::PrintPresetEnvironment()
+{
+  bool first = true;
+  for (auto const& var : this->UnprocessedPresetEnvironment) {
+    if (!var.second) {
+      continue;
+    }
+    if (first) {
+      std::cout << "Preset environment variables:\n\n";
+      first = false;
+    }
+    std::cout << "  " << var.first << "=\"" << *var.second << "\"\n";
+  }
+  if (!first) {
+    std::cout << '\n';
+  }
+  this->UnprocessedPresetEnvironment.clear();
+}
+#endif
+
 // Parse the args
 bool cmake::SetCacheArgs(const std::vector<std::string>& args)
 {
@@ -308,28 +401,10 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
       std::string value;
       cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
       if (cmState::ParseCacheEntry(entry, var, value, type)) {
-        // The value is transformed if it is a filepath for example, so
-        // we can't compare whether the value is already in the cache until
-        // after we call AddCacheEntry.
-        bool haveValue = false;
-        std::string cachedValue;
-        if (this->WarnUnusedCli) {
-          if (cmProp v = this->State->GetInitializedCacheValue(var)) {
-            haveValue = true;
-            cachedValue = *v;
-          }
-        }
-
-        this->AddCacheEntry(var, value.c_str(),
-                            "No help, variable specified on the command line.",
-                            type);
-
-        if (this->WarnUnusedCli) {
-          if (!haveValue ||
-              cachedValue != *this->State->GetInitializedCacheValue(var)) {
-            this->WatchUnusedCli(var);
-          }
-        }
+#ifndef CMAKE_BOOTSTRAP
+        this->UnprocessedPresetVariables.erase(var);
+#endif
+        this->ProcessCacheArg(var, value, type);
       } else {
         cmSystemTools::Error("Parse error in command line argument: " + arg +
                              "\n" + "Should be: VAR:type=value\n");
@@ -409,6 +484,9 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
 
       // now remove them from the cache
       for (std::string const& currentEntry : entriesToDelete) {
+#ifndef CMAKE_BOOTSTRAP
+        this->UnprocessedPresetVariables.erase(currentEntry);
+#endif
         this->State->RemoveCacheEntry(currentEntry);
       }
     } else if (cmHasLiteralPrefix(arg, "-C")) {
@@ -462,6 +540,33 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
   return true;
 }
 
+void cmake::ProcessCacheArg(const std::string& var, const std::string& value,
+                            cmStateEnums::CacheEntryType type)
+{
+  // The value is transformed if it is a filepath for example, so
+  // we can't compare whether the value is already in the cache until
+  // after we call AddCacheEntry.
+  bool haveValue = false;
+  std::string cachedValue;
+  if (this->WarnUnusedCli) {
+    if (cmProp v = this->State->GetInitializedCacheValue(var)) {
+      haveValue = true;
+      cachedValue = *v;
+    }
+  }
+
+  this->AddCacheEntry(var, value.c_str(),
+                      "No help, variable specified on the command line.",
+                      type);
+
+  if (this->WarnUnusedCli) {
+    if (!haveValue ||
+        cachedValue != *this->State->GetInitializedCacheValue(var)) {
+      this->WatchUnusedCli(var);
+    }
+  }
+}
+
 void cmake::ReadListFile(const std::vector<std::string>& args,
                          const std::string& path)
 {
@@ -625,6 +730,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
 #if !defined(CMAKE_BOOTSTRAP)
   std::string profilingFormat;
   std::string profilingOutput;
+  std::string presetName;
+  bool listPresets = false;
 #endif
   for (unsigned int i = 1; i < args.size(); ++i) {
     std::string const& arg = args[i];
@@ -830,19 +937,9 @@ void cmake::SetArgs(const std::vector<std::string>& args)
         }
         value = args[i];
       }
-      auto gen = this->CreateGlobalGenerator(value);
-      if (!gen) {
-        std::string kdevError;
-        if (value.find("KDevelop3", 0) != std::string::npos) {
-          kdevError = "\nThe KDevelop3 generator is not supported anymore.";
-        }
-
-        cmSystemTools::Error(
-          cmStrCat("Could not create named generator ", value, kdevError));
-        this->PrintGeneratorList();
+      if (!this->CreateAndSetGlobalGenerator(value, true)) {
         return;
       }
-      this->SetGlobalGenerator(std::move(gen));
 #if !defined(CMAKE_BOOTSTRAP)
     } else if (cmHasLiteralPrefix(arg, "--profiling-format")) {
       profilingFormat = arg.substr(strlen("--profiling-format="));
@@ -856,6 +953,13 @@ void cmake::SetArgs(const std::vector<std::string>& args)
       if (profilingOutput.empty()) {
         cmSystemTools::Error("No path specified for --profiling-output");
       }
+    } else if (cmHasLiteralPrefix(arg, "--preset")) {
+      presetName = arg.substr(strlen("--preset="));
+      if (presetName.empty()) {
+        cmSystemTools::Error("No preset specified for --preset");
+      }
+    } else if (cmHasLiteralPrefix(arg, "--list-presets")) {
+      listPresets = true;
 #endif
     }
     // no option assume it is the path to the source or an existing build
@@ -915,6 +1019,91 @@ void cmake::SetArgs(const std::vector<std::string>& args)
   if (!haveBinaryDir) {
     this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
   }
+
+#if !defined(CMAKE_BOOTSTRAP)
+  if (listPresets || !presetName.empty()) {
+    cmCMakePresetsFile settingsFile;
+    auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
+    if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+      cmSystemTools::Error(
+        cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
+                 ": ", cmCMakePresetsFile::ResultToString(result)));
+      return;
+    }
+    if (listPresets) {
+      this->PrintPresetList(settingsFile);
+      return;
+    }
+    auto preset = settingsFile.Presets.find(presetName);
+    if (preset == settingsFile.Presets.end()) {
+      cmSystemTools::Error(cmStrCat("No such preset in ",
+                                    this->GetHomeDirectory(), ": \"",
+                                    presetName, '"'));
+      this->PrintPresetList(settingsFile);
+      return;
+    }
+    if (preset->second.Hidden) {
+      cmSystemTools::Error(cmStrCat("Cannot use hidden preset in ",
+                                    this->GetHomeDirectory(), ": \"",
+                                    presetName, '"'));
+      this->PrintPresetList(settingsFile);
+      return;
+    }
+    auto expandedPreset = settingsFile.ExpandMacros(preset->second);
+    if (!expandedPreset) {
+      cmSystemTools::Error(cmStrCat("Could not evaluate preset \"",
+                                    preset->second.Name,
+                                    "\": Invalid macro expansion"));
+      return;
+    }
+
+    if (!haveBinaryDir) {
+      this->SetHomeOutputDirectory(expandedPreset->BinaryDir);
+    }
+    if (!this->GlobalGenerator) {
+      if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator,
+                                             false)) {
+        return;
+      }
+    }
+    this->UnprocessedPresetVariables = expandedPreset->CacheVariables;
+    this->UnprocessedPresetEnvironment = expandedPreset->Environment;
+
+    if (!expandedPreset->GeneratorConfig ||
+        expandedPreset->GeneratorConfig ==
+          cmCMakePresetsFile::CMakeGeneratorConfig::Default) {
+      if (!this->GeneratorPlatformSet) {
+        this->SetGeneratorPlatform(expandedPreset->Architecture);
+      }
+      if (!this->GeneratorToolsetSet) {
+        this->SetGeneratorToolset(expandedPreset->Toolset);
+      }
+    }
+
+    this->SetWarningFromPreset("dev", expandedPreset->WarnDev,
+                               expandedPreset->ErrorDev);
+    this->SetWarningFromPreset("deprecated", expandedPreset->WarnDeprecated,
+                               expandedPreset->ErrorDeprecated);
+    if (expandedPreset->WarnUninitialized == true) {
+      this->SetWarnUninitialized(true);
+    }
+    if (expandedPreset->WarnUnusedCli == false) {
+      this->SetWarnUnusedCli(false);
+    }
+    if (expandedPreset->WarnSystemVars == true) {
+      this->SetCheckSystemVars(true);
+    }
+    if (expandedPreset->DebugOutput == true) {
+      this->SetDebugOutputOn(true);
+    }
+    if (expandedPreset->DebugTryCompile == true) {
+      this->DebugTryCompileOn();
+    }
+    if (expandedPreset->DebugFind == true) {
+      this->SetDebugFindOutputOn(true);
+    }
+  }
+#endif
 }
 
 cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
@@ -1240,6 +1429,79 @@ std::unique_ptr<cmGlobalGenerator> cmake::CreateGlobalGenerator(
   return generator;
 }
 
+bool cmake::CreateAndSetGlobalGenerator(const std::string& name,
+                                        bool allowArch)
+{
+  auto gen = this->CreateGlobalGenerator(name, allowArch);
+  if (!gen) {
+    std::string kdevError;
+    std::string vsError;
+    if (name.find("KDevelop3", 0) != std::string::npos) {
+      kdevError = "\nThe KDevelop3 generator is not supported anymore.";
+    }
+    if (!allowArch && cmHasLiteralPrefix(name, "Visual Studio ") &&
+        name.length() >= cmStrLen("Visual Studio xx xxxx ")) {
+      vsError = "\nUsing platforms in Visual Studio generator names is not "
+                "supported in CMakePresets.json.";
+    }
+
+    cmSystemTools::Error(
+      cmStrCat("Could not create named generator ", name, kdevError, vsError));
+    this->PrintGeneratorList();
+    return false;
+  }
+
+  this->SetGlobalGenerator(std::move(gen));
+  return true;
+}
+
+#ifndef CMAKE_BOOTSTRAP
+void cmake::PrintPresetList(const cmCMakePresetsFile& file) const
+{
+  std::vector<GeneratorInfo> generators;
+  this->GetRegisteredGenerators(generators, false);
+
+  std::vector<cmCMakePresetsFile::UnexpandedPreset> presets;
+  for (auto const& p : file.PresetOrder) {
+    auto const& preset = file.Presets.at(p);
+    if (!preset.Hidden &&
+        std::find_if(generators.begin(), generators.end(),
+                     [&preset](const GeneratorInfo& info) {
+                       return info.name == preset.Generator;
+                     }) != generators.end() &&
+        file.ExpandMacros(preset)) {
+      presets.push_back(preset);
+    }
+  }
+
+  if (presets.empty()) {
+    return;
+  }
+
+  std::cout << "Available presets:\n\n";
+
+  auto longestPresetName =
+    std::max_element(presets.begin(), presets.end(),
+                     [](const cmCMakePresetsFile::UnexpandedPreset& a,
+                        const cmCMakePresetsFile::UnexpandedPreset& b) {
+                       return a.Name.length() < b.Name.length();
+                     });
+  auto longestLength = longestPresetName->Name.length();
+
+  for (auto const& preset : presets) {
+    std::cout << "  \"" << preset.Name << '"';
+    auto const& description = preset.DisplayName;
+    if (!description.empty()) {
+      for (std::size_t i = 0; i < longestLength - preset.Name.length(); ++i) {
+        std::cout << ' ';
+      }
+      std::cout << " - " << description;
+    }
+    std::cout << '\n';
+  }
+}
+#endif
+
 void cmake::SetHomeDirectory(const std::string& dir)
 {
   this->State->SetSourceDirectory(dir);
@@ -1801,6 +2063,9 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
   if (cmSystemTools::GetErrorOccuredFlag()) {
     return -1;
   }
+  if (this->GetWorkingMode() == HELP_MODE) {
+    return 0;
+  }
 
   // Log the trace format version to the desired output
   if (this->GetTrace()) {
@@ -1829,11 +2094,19 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
     this->AddCMakePaths();
   }
 
+#ifndef CMAKE_BOOTSTRAP
+  this->ProcessPresetVariables();
+  this->ProcessPresetEnvironment();
+#endif
   // Add any cache args
   if (!this->SetCacheArgs(args)) {
     cmSystemTools::Error("Problem processing arguments. Aborting.\n");
     return -1;
   }
+#ifndef CMAKE_BOOTSTRAP
+  this->PrintPresetVariables();
+  this->PrintPresetEnvironment();
+#endif
 
   // In script mode we terminate after running the script.
   if (this->GetWorkingMode() != NORMAL_MODE) {

+ 48 - 6
Source/cmake.h

@@ -27,7 +27,11 @@
 #include "cmStateTypes.h"
 
 #if !defined(CMAKE_BOOTSTRAP)
+#  include <cm/optional>
+
 #  include <cm3p/json/value.h>
+
+#  include "cmCMakePresetsFile.h"
 #endif
 
 class cmExternalMakefileProjectGeneratorFactory;
@@ -88,13 +92,22 @@ public:
   enum WorkingMode
   {
     NORMAL_MODE, ///< Cmake runs to create project files
-                 /** \brief Script mode (started by using -P).
-                  *
-                  * In script mode there is no generator and no cache. Also,
-                  * languages are not enabled, so add_executable and things do
-                  * nothing.
-                  */
+
+    /** \brief Script mode (started by using -P).
+     *
+     * In script mode there is no generator and no cache. Also,
+     * languages are not enabled, so add_executable and things do
+     * nothing.
+     */
     SCRIPT_MODE,
+
+    /** \brief Help mode
+     *
+     * Used to print help for things that can only be determined after finding
+     * the source directory, for example, the list of presets.
+     */
+    HELP_MODE,
+
     /** \brief A pkg-config like mode
      *
      * In this mode cmake just searches for a package and prints the results to
@@ -221,6 +234,14 @@ public:
   std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
     const std::string& name, bool allowArch = true);
 
+  //! Create a GlobalGenerator and set it as our own
+  bool CreateAndSetGlobalGenerator(const std::string& name, bool allowArch);
+
+#ifndef CMAKE_BOOTSTRAP
+  //! Print list of presets
+  void PrintPresetList(const cmCMakePresetsFile& file) const;
+#endif
+
   //! Return the global generator assigned to this instance of cmake
   cmGlobalGenerator* GetGlobalGenerator()
   {
@@ -329,9 +350,22 @@ public:
   bool GetIsInTryCompile() const;
   void SetIsInTryCompile(bool b);
 
+#ifndef CMAKE_BOOTSTRAP
+  void SetWarningFromPreset(const std::string& name,
+                            const cm::optional<bool>& warning,
+                            const cm::optional<bool>& error);
+  void ProcessPresetVariables();
+  void PrintPresetVariables();
+  void ProcessPresetEnvironment();
+  void PrintPresetEnvironment();
+#endif
+
   //! Parse command line arguments that might set cache values
   bool SetCacheArgs(const std::vector<std::string>&);
 
+  void ProcessCacheArg(const std::string& var, const std::string& value,
+                       cmStateEnums::CacheEntryType type);
+
   using ProgressCallbackType = std::function<void(const std::string&, float)>;
   /**
    *  Set the function used by GUIs to receive progress updates
@@ -625,6 +659,12 @@ private:
   std::unique_ptr<cmFileTimeCache> FileTimeCache;
   std::string GraphVizFile;
   InstalledFilesMap InstalledFiles;
+#ifndef CMAKE_BOOTSTRAP
+  std::map<std::string, cm::optional<cmCMakePresetsFile::CacheVariable>>
+    UnprocessedPresetVariables;
+  std::map<std::string, cm::optional<std::string>>
+    UnprocessedPresetEnvironment;
+#endif
 
 #if !defined(CMAKE_BOOTSTRAP)
   std::unique_ptr<cmVariableWatch> VariableWatch;
@@ -664,6 +704,8 @@ private:
 #define CMAKE_STANDARD_OPTIONS_TABLE                                          \
   { "-S <path-to-source>", "Explicitly specify a source directory." },        \
     { "-B <path-to-build>", "Explicitly specify a build directory." },        \
+    { "--preset=<preset-name>", "Explicitly specify a preset." },             \
+    { "--list-presets", "List available presets." },                          \
     { "-C <initial-cache>", "Pre-load a script to populate the cache." },     \
     { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
     { "-U <globbing_expr>", "Remove matching entries from CMake cache." },    \

+ 6 - 1
Source/cmakemain.cxx

@@ -49,7 +49,8 @@ const char* cmDocumentationUsage[][2] = {
   { nullptr,
     "  cmake [options] <path-to-source>\n"
     "  cmake [options] <path-to-existing-build>\n"
-    "  cmake [options] -S <path-to-source> -B <path-to-build>" },
+    "  cmake [options] -S <path-to-source> -B <path-to-build>\n"
+    "  cmake [options] -S <path-to-source> --preset=<preset-name>" },
   { nullptr,
     "Specify a source directory to (re-)generate a build system for "
     "it in the current working directory.  Specify an existing build "
@@ -253,6 +254,9 @@ int do_cmake(int ac, char const* const* av)
     } else if (cmHasLiteralPrefix(av[i], "--find-package")) {
       workingMode = cmake::FIND_PACKAGE_MODE;
       args.emplace_back(av[i]);
+    } else if (strcmp(av[i], "--list-presets") == 0) {
+      workingMode = cmake::HELP_MODE;
+      args.emplace_back(av[i]);
     } else {
       args.emplace_back(av[i]);
     }
@@ -269,6 +273,7 @@ int do_cmake(int ac, char const* const* av)
   cmState::Mode mode = cmState::Unknown;
   switch (workingMode) {
     case cmake::NORMAL_MODE:
+    case cmake::HELP_MODE:
       mode = cmState::Project;
       break;
     case cmake::SCRIPT_MODE:

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -757,6 +757,7 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
   -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION})
 
 add_RunCMake_test("UnityBuild")
+add_RunCMake_test(CMakePresets)
 
 if(WIN32)
   add_RunCMake_test(Win32GenEx)

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

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

+ 11 - 0
Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt

@@ -0,0 +1,11 @@
+^CMake Error at CMakeLists\.txt:[0-9]+ \(project\):
+  Generator
+
+    [^
+]*
+
+  does not support platform specification, but platform
+
+    a
+
+  was specified\.$

+ 0 - 0
Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake


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

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

+ 11 - 0
Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt

@@ -0,0 +1,11 @@
+^CMake Error at CMakeLists\.txt:[0-9]+ \(project\):
+  Generator
+
+    [^
+]*
+
+  does not support platform specification, but platform
+
+    a
+
+  was specified\.$

+ 4 - 0
Tests/RunCMake/CMakePresets/CMakeLists.txt.in

@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+set(RunCMake_SOURCE_DIR [==[@RunCMake_SOURCE_DIR@]==])
+include("${RunCMake_SOURCE_DIR}/${RunCMake_TEST}.cmake")

+ 481 - 0
Tests/RunCMake/CMakePresets/CMakePresets.json.in

@@ -0,0 +1,481 @@
+/*
+ * Block comment
+ */
+{
+  // Inline comment
+  "version": 1,
+  "cmakeMinimumRequired": {
+    "major": 3,
+    "minor": 18,
+    "patch": 0
+  },
+  "vendor": {
+    "example.com/ExampleIDE/1.0": true
+  },
+  "configurePresets": [
+    {
+      "name": "Good",
+      "displayName": "Good Preset",
+      "description": "This preset is meant to test most of the fields when set correctly.",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "cmakeExecutable": "/path/does/not/exist/cmake",
+      "vendor": {
+        "example.com/ExampleIDE/1.0": {
+          "transmogrify": true
+        }
+      },
+      "cacheVariables": {
+        "TEST_SOURCE_DIR": {
+          "type": "PATH",
+          "value": "${sourceDir}"
+        },
+        "TEST_SOURCE_PARENT_DIR": {
+          "type": "PATH",
+          "value": "${sourceParentDir}"
+        },
+        "TEST_SOURCE_LIST": {
+          "type": "FILEPATH",
+          "value": "${sourceDir}/CMakeLists.txt"
+        },
+        "TEST_TRUE": {
+          "type": "BOOL",
+          "value": "TRUE"
+        },
+        "TEST_OFF": {
+          "type": "BOOL",
+          "value": "OFF"
+        },
+        "TEST_PRESET_NAME": {
+          "type": "STRING",
+          "value": "x${presetName}x"
+        },
+        "TEST_GENERATOR": {
+          "value": "x${generator}x"
+        },
+        "TEST_DOLLAR": {
+          "value": "${dollar}"
+        },
+        "TEST_ENV_REF": "$env{TEST_ENV_REF}",
+        "TEST_ENV": "$env{TEST_ENV}",
+        "TEST_D_ENV_REF": "$env{TEST_D_ENV_REF}",
+        "TEST_ENV_OVERRIDE": "$env{TEST_ENV_OVERRIDE}",
+        "TEST_PENV": "$env{TEST_PENV}",
+        "TEST_ENV_REF_PENV": "$env{TEST_ENV_REF_PENV}",
+        "TEST_ENV_REF_P": "$penv{TEST_ENV_REF}",
+        "TEST_ENV_P": "$penv{TEST_ENV}",
+        "TEST_D_ENV_REF_P": "$penv{TEST_D_ENV_REF}",
+        "TEST_ENV_OVERRIDE_P": "$penv{TEST_ENV_OVERRIDE}",
+        "TEST_PENV_P": "$penv{TEST_PENV}",
+        "TEST_ENV_REF_PENV_P": "$penv{TEST_ENV_REF_PENV}",
+        "TEST_MULTIPLE_MACROS": "${presetName} ${generator}",
+        "TEST_EXPANSION": "\\${presetName} ${dollar}{dollar} $unknown{namespace} $en{NOT_ENV} $enve{NOT_ENV} $ \\$ $a",
+        "TEST_TRAILING_DOLLAR": "a $",
+        "TEST_TRAILING_BACKSLASH": "a \\",
+        "TEST_TRAILING_UNKNOWN_NAMESPACE": "$unknown{namespace",
+        "TEST_OVERRIDE_1": {
+          "type": "STRING",
+          "value": "Default value"
+        },
+        "TEST_OVERRIDE_2": "Default value",
+        "TEST_OVERRIDE_3": {
+          "type": "STRING",
+          "value": "Default value"
+        },
+        "TEST_OVERRIDE_4": {
+          "type": "STRING",
+          "value": "Default value"
+        },
+        "TEST_UNDEF": "undef"
+      },
+      "environment": {
+        "TEST_ENV_REF": "$env{TEST_ENV}",
+        "TEST_ENV": "Environment variable",
+        "TEST_D_ENV_REF": "x$env{TEST_ENV_REF}x",
+        "TEST_ENV_OVERRIDE": "Overridden environment variable",
+        "TEST_ENV_REF_PENV": "prefix+$penv{TEST_ENV_REF_PENV}",
+        "TEST_PENV": null
+      }
+    },
+    {
+      "name": "GoodNoArgs",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "GoodBinaryUp",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/../GoodBinaryUp-build"
+    },
+    {
+      "name": "GoodBinaryRelative",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "build"
+    },
+    {
+      "name": "Good Spaces",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "GoodWindowsBackslash",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}\\build"
+    },
+    {
+      "name": "GoodBinaryCmdLine",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "GoodGeneratorCmdLine",
+      "generator": "Invalid Generator",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "InvalidGeneratorCmdLine",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "GoodNoS",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "GoodInheritanceParentBase",
+      "hidden": true,
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "cacheVariables": {
+        "TEST_VARIABLE": {
+          "type": "STRING",
+          "value": "Some string"
+        }
+      },
+      "environment": {
+        "TEST_ENV": "Some environment variable"
+      }
+    },
+    {
+      "name": "GoodInheritanceParent",
+      "inherits": "GoodInheritanceParentBase"
+    },
+    {
+      "name": "GoodInheritanceChildBase",
+      "hidden": true
+    },
+    {
+      "name": "GoodInheritanceChild",
+      "inherits": "GoodInheritanceChildBase",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "cacheVariables": {
+        "TEST_VARIABLE": {
+          "type": "STRING",
+          "value": "Some string"
+        }
+      },
+      "environment": {
+        "TEST_ENV": "Some environment variable"
+      }
+    },
+    {
+      "name": "GoodInheritanceOverrideBase",
+      "hidden": true,
+      "generator": "Invalid Generator",
+      "binaryDir": "${sourceDir}/../GoodInheritanceBase-build",
+      "cacheVariables": {
+        "PARENT_VARIABLE": {
+          "type": "STRING",
+          "value": "Parent variable"
+        },
+        "OVERRIDDEN_VARIABLE": {
+          "type": "BOOL",
+          "value": "ON"
+        },
+        "DELETED_VARIABLE": "This variable will be deleted"
+      },
+      "environment": {
+        "PARENT_ENV": "Parent environment variable",
+        "OVERRIDDEN_ENV": "This environment variable will be overridden",
+        "DELETED_ENV": "This environment variable will be deleted"
+      }
+    },
+    {
+      "name": "GoodInheritanceOverride",
+      "inherits": "GoodInheritanceOverrideBase",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "cacheVariables": {
+        "OVERRIDDEN_VARIABLE": {
+          "type": "STRING",
+          "value": "Overridden variable"
+        },
+        "CHILD_VARIABLE": {
+          "type": "STRING",
+          "value": "Child variable"
+        },
+        "DELETED_VARIABLE": null
+      },
+      "environment": {
+        "OVERRIDDEN_ENV": "Overridden environment variable",
+        "CHILD_ENV": "Child environment variable",
+        "DELETED_ENV": null
+      }
+    },
+    {
+      "name": "GoodInheritanceOverrideDummy",
+      "inherits": "GoodInheritanceOverride"
+    },
+    {
+      "name": "GoodInheritanceMulti1",
+      "hidden": true,
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "cacheVariables": {
+        "FIRST_VARIABLE": {
+          "type": "STRING",
+          "value": "First variable"
+        },
+        "OVERRIDDEN_VARIABLE": {
+          "type": "STRING",
+          "value": "Overridden variable"
+        }
+      },
+      "environment": {
+        "FIRST_ENV": "First environment variable",
+        "OVERRIDDEN_ENV": "Overridden environment variable"
+      }
+    },
+    {
+      "name": "GoodInheritanceMulti2",
+      "hidden": true,
+      "generator": "Invalid Generator",
+      "binaryDir": "${sourceDir}/../GoodInheritanceMulti2-build",
+      "cacheVariables": {
+        "SECOND_VARIABLE": {
+          "type": "STRING",
+          "value": "Second variable"
+        },
+        "OVERRIDDEN_VARIABLE": {
+          "type": "BOOL",
+          "value": "ON"
+        }
+      },
+      "environment": {
+        "SECOND_ENV": "Second environment variable",
+        "OVERRIDDEN_ENV": "This will be overridden"
+      }
+    },
+    {
+      "name": "GoodInheritanceMulti",
+      "inherits": [
+        "GoodInheritanceMulti1",
+        "GoodInheritanceMulti2"
+      ]
+    },
+    {
+      "name": "GoodInheritanceMultiSecond1",
+      "hidden": true
+    },
+    {
+      "name": "GoodInheritanceMultiSecond2",
+      "hidden": true,
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "GoodInheritanceMultiSecond",
+      "inherits": [
+        "GoodInheritanceMultiSecond1",
+        "GoodInheritanceMultiSecond2"
+      ]
+    },
+    {
+      "name": "GoodInheritanceMacroBase",
+      "hidden": true,
+      "cacheVariables": {
+        "PRESET_NAME": "${presetName}"
+      }
+    },
+    {
+      "name": "GoodInheritanceMacro",
+      "inherits": "GoodInheritanceMacroBase",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "UnclosedMacro",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir"
+    },
+    {
+      "name": "NoSuchMacro",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${noexist}"
+    },
+    {
+      "name": "VendorMacro",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "$vendor{unknown.unknownMacro}"
+    },
+    {
+      "name": "InvalidGenerator",
+      "generator": "Invalid Generator",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "EnvCycle",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "environment": {
+        "ENV_1": "$env{ENV_2}",
+        "ENV_2": "$env{ENV_1}"
+      }
+    },
+    {
+      "name": "UseHiddenPreset",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "hidden": true
+    },
+    {
+      "name": "VisualStudioGeneratorArch",
+      "generator": "@RunCMake_GENERATOR@ Win64",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "VisualStudioWin32",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": "Win32"
+    },
+    {
+      "name": "VisualStudioWin64",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": "x64"
+    },
+    {
+      "name": "VisualStudioWin32Override",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": "Win32"
+    },
+    {
+      "name": "VisualStudioToolset",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "toolset": "Test Toolset"
+    },
+    {
+      "name": "VisualStudioToolsetOverride",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "toolset": "Invalid Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceParentBase",
+      "hidden": true,
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": "Test Platform",
+      "toolset": "Test Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceParent",
+      "inherits": "VisualStudioInheritanceParentBase"
+    },
+    {
+      "name": "VisualStudioInheritanceChildBase",
+      "hidden": true
+    },
+    {
+      "name": "VisualStudioInheritanceChild",
+      "inherits": "VisualStudioInheritanceChildBase",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": "Test Platform",
+      "toolset": "Test Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceOverrideBase",
+      "hidden": true,
+      "architecture": "Invalid Platform",
+      "toolset": "Invalid Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceOverride",
+      "inherits": "VisualStudioInheritanceOverrideBase",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": "Test Platform",
+      "toolset": "Test Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceMulti1",
+      "hidden": true,
+      "architecture": "Test Platform",
+      "toolset": "Test Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceMulti2",
+      "hidden": true,
+      "architecture": "Invalid Platform",
+      "toolset": "Invalid Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceMulti",
+      "inherits": [
+        "VisualStudioInheritanceMulti1",
+        "VisualStudioInheritanceMulti2"
+      ],
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "VisualStudioInheritanceMultiSecond1",
+      "hidden": true
+    },
+    {
+      "name": "VisualStudioInheritanceMultiSecond2",
+      "hidden": true,
+      "architecture": "Test Platform",
+      "toolset": "Test Toolset"
+    },
+    {
+      "name": "VisualStudioInheritanceMultiSecond",
+      "inherits": [
+        "VisualStudioInheritanceMultiSecond1",
+        "VisualStudioInheritanceMultiSecond2"
+      ],
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "CMakeGeneratorConfigNone",
+      "generator": "@RunCMake_GENERATOR@",
+      "architecture": "a",
+      "toolset": "a",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "CMakeGeneratorConfigBase",
+      "generator": "@RunCMake_GENERATOR@",
+      "architecture": "a",
+      "toolset": "a",
+      "cmakeGeneratorConfig": "ignore",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "CMakeGeneratorConfigDefault",
+      "inherits": "CMakeGeneratorConfigBase",
+      "cmakeGeneratorConfig": "default"
+    },
+    {
+      "name": "CMakeGeneratorConfigIgnore",
+      "inherits": "CMakeGeneratorConfigBase"
+    }
+  ]
+}

+ 2 - 0
Tests/RunCMake/CMakePresets/CacheOverride.cmake

@@ -0,0 +1,2 @@
+set(TEST_OVERRIDE_3 "Overridden value" CACHE STRING "")
+set(TEST_OVERRIDE_4 "Overridden value" CACHE INTERNAL "")

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/CyclicInheritance0: Cyclic preset inheritance$

+ 13 - 0
Tests/RunCMake/CMakePresets/CyclicInheritance0.json.in

@@ -0,0 +1,13 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "CyclicInheritance0",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "inherits": [
+        "CyclicInheritance0"
+      ]
+    }
+  ]
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/CyclicInheritance1: Cyclic preset inheritance$

+ 21 - 0
Tests/RunCMake/CMakePresets/CyclicInheritance1.json.in

@@ -0,0 +1,21 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "CyclicInheritance0",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "inherits": [
+        "CyclicInheritance1"
+      ]
+    },
+    {
+      "name": "CyclicInheritance1",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "inherits": [
+        "CyclicInheritance0"
+      ]
+    }
+  ]
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/CyclicInheritance2: Cyclic preset inheritance$

+ 29 - 0
Tests/RunCMake/CMakePresets/CyclicInheritance2.json.in

@@ -0,0 +1,29 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "CyclicInheritance0",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "inherits": [
+        "CyclicInheritance1"
+      ]
+    },
+    {
+      "name": "CyclicInheritance1",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "inherits": [
+        "CyclicInheritance2"
+      ]
+    },
+    {
+      "name": "CyclicInheritance2",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "inherits": [
+        "CyclicInheritance0"
+      ]
+    }
+  ]
+}

+ 1 - 0
Tests/RunCMake/CMakePresets/Debug-stderr.txt

@@ -0,0 +1 @@
+  find_package considered the following locations for the Config module:

+ 4 - 0
Tests/RunCMake/CMakePresets/Debug-stdout.txt

@@ -0,0 +1,4 @@
+-- Generating [^
+]*/Tests/RunCMake/CMakePresets/Debug/build
+   Called from: \[1\][^
+]*/Tests/RunCMake/CMakePresets/Debug/CMakeLists\.txt

+ 4 - 0
Tests/RunCMake/CMakePresets/Debug.cmake

@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/DebugBase.cmake)
+if(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/CMakeLists.txt")
+  message(SEND_ERROR "Debugging try_compile() did not work")
+endif()

+ 19 - 0
Tests/RunCMake/CMakePresets/Debug.json.in

@@ -0,0 +1,19 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "NoDebug",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "Debug",
+      "inherits": "NoDebug",
+      "debug": {
+        "output": true,
+        "find": true,
+        "tryCompile": true
+      }
+    }
+  ]
+}

+ 3 - 0
Tests/RunCMake/CMakePresets/DebugBase.cmake

@@ -0,0 +1,3 @@
+enable_language(C)
+try_compile(_result ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/main.c)
+find_package(ThisPackageHopefullyDoesNotExist CONFIG)

+ 1 - 0
Tests/RunCMake/CMakePresets/DisableWarningFlags.cmake

@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/DuplicatePresets: Duplicate presets$

+ 15 - 0
Tests/RunCMake/CMakePresets/DuplicatePresets.json.in

@@ -0,0 +1,15 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "DuplicatePresets",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    },
+    {
+      "name": "DuplicatePresets",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ]
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/EmptyPresetName: Invalid preset$

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

@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ]
+}

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

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

+ 1 - 0
Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt

@@ -0,0 +1 @@
+^CMake Error: Could not evaluate preset "EnvCycle": Invalid macro expansion$

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

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

+ 7 - 0
Tests/RunCMake/CMakePresets/ErrorDeprecated-stderr.txt

@@ -0,0 +1,7 @@
+^CMake Deprecation Error at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+  Deprecation warning
+Call Stack \(most recent call first\):
+  [^
+]*/Tests/RunCMake/CMakePresets/ErrorDeprecated\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)$

+ 1 - 0
Tests/RunCMake/CMakePresets/ErrorDeprecated.cmake

@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)

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

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

+ 8 - 0
Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt

@@ -0,0 +1,8 @@
+^CMake Error \(dev\) at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+  Dev warning
+Call Stack \(most recent call first\):
+  [^
+]*/Tests/RunCMake/CMakePresets/ErrorDev\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+This error is for project developers\. Use -Wno-error=dev to suppress it\.$

+ 1 - 0
Tests/RunCMake/CMakePresets/ErrorDev.cmake

@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated: Invalid preset$

+ 16 - 0
Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated.json.in

@@ -0,0 +1,16 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "ErrorNoWarningDeprecated",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "warnings": {
+        "deprecated": false
+      },
+      "errors": {
+        "deprecated": true
+      }
+    }
+  ]
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDev: Invalid preset$

+ 16 - 0
Tests/RunCMake/CMakePresets/ErrorNoWarningDev.json.in

@@ -0,0 +1,16 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "ErrorNoWarningDev",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "warnings": {
+        "dev": false
+      },
+      "errors": {
+        "dev": true
+      }
+    }
+  ]
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ExtraPresetField: Invalid preset$

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

@@ -0,0 +1,11 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "ExtraPresetField",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "invalid": true
+    }
+  ]
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ExtraRootField: Invalid root object$

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

@@ -0,0 +1,11 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "ExtraRootField",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ],
+  "invalid": true
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ExtraVariableField: Invalid CMake variable definition$

+ 16 - 0
Tests/RunCMake/CMakePresets/ExtraVariableField.json.in

@@ -0,0 +1,16 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "ExtraVariableField",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "cacheVariables": {
+        "EXTRA": {
+          "value": "",
+          "invalid": true
+        }
+      }
+    }
+  ]
+}

+ 46 - 0
Tests/RunCMake/CMakePresets/Good-stdout.txt

@@ -0,0 +1,46 @@
+Preset CMake variables:
+
+  TEST_DOLLAR="\$"
+  TEST_D_ENV_REF="xEnvironment variablex"
+  TEST_D_ENV_REF_P=""
+  TEST_ENV="Environment variable"
+  TEST_ENV_OVERRIDE="Overridden environment variable"
+  TEST_ENV_OVERRIDE_P="This environment variable will be overridden"
+  TEST_ENV_P=""
+  TEST_ENV_REF="Environment variable"
+  TEST_ENV_REF_P=""
+  TEST_ENV_REF_PENV="prefix\+suffix"
+  TEST_ENV_REF_PENV_P="suffix"
+  TEST_EXPANSION="\\Good \${dollar} \$unknown{namespace} \$en{NOT_ENV} \$enve{NOT_ENV} \$ \\\$ \$a"
+  TEST_GENERATOR="x[^
+]*x"
+  TEST_MULTIPLE_MACROS="Good [^
+]*"
+  TEST_OFF:BOOL="OFF"
+  TEST_OVERRIDE_3:STRING="Default value"
+  TEST_OVERRIDE_4:STRING="Default value"
+  TEST_PENV="Process environment variable"
+  TEST_PENV_P="Process environment variable"
+  TEST_PRESET_NAME:STRING="xGoodx"
+  TEST_SOURCE_DIR:PATH="[^
+]*/Tests/RunCMake/CMakePresets/Good"
+  TEST_SOURCE_LIST:FILEPATH="[^
+]*/Tests/RunCMake/CMakePresets/Good/CMakeLists\.txt"
+  TEST_SOURCE_PARENT_DIR:PATH="[^
+]*/Tests/RunCMake/CMakePresets"
+  TEST_TRAILING_BACKSLASH="a \\"
+  TEST_TRAILING_DOLLAR="a \$"
+  TEST_TRAILING_UNKNOWN_NAMESPACE="\$unknown{namespace"
+  TEST_TRUE:BOOL="TRUE"
+
+Preset environment variables:
+
+  TEST_D_ENV_REF="xEnvironment variablex"
+  TEST_ENV="Environment variable"
+  TEST_ENV_OVERRIDE="Overridden environment variable"
+  TEST_ENV_REF="Environment variable"
+  TEST_ENV_REF_PENV="prefix\+suffix"
+
+(-- Selecting Windows SDK version [^
+]*
+)?-- Configuring done

+ 45 - 0
Tests/RunCMake/CMakePresets/Good.cmake

@@ -0,0 +1,45 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent_dir "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(CMAKE_GENERATOR "" "${RunCMake_GENERATOR}")
+test_variable(TEST_SOURCE_DIR "PATH" "${CMAKE_SOURCE_DIR}")
+test_variable(TEST_SOURCE_PARENT_DIR "PATH" "${_parent_dir}")
+test_variable(TEST_SOURCE_LIST "FILEPATH" "${CMAKE_SOURCE_DIR}/CMakeLists.txt")
+test_variable(TEST_TRUE "BOOL" "TRUE")
+test_variable(TEST_OFF "BOOL" "OFF")
+test_variable(TEST_PRESET_NAME "STRING" "xGoodx")
+test_variable(TEST_GENERATOR "UNINITIALIZED" "x${CMAKE_GENERATOR}x")
+test_variable(TEST_DOLLAR "UNINITIALIZED" "$")
+test_variable(TEST_ENV_REF "UNINITIALIZED" "Environment variable")
+test_variable(TEST_ENV "UNINITIALIZED" "Environment variable")
+test_variable(TEST_D_ENV_REF "UNINITIALIZED" "xEnvironment variablex")
+test_variable(TEST_ENV_OVERRIDE "UNINITIALIZED" "Overridden environment variable")
+test_variable(TEST_PENV "UNINITIALIZED" "Process environment variable")
+test_variable(TEST_ENV_REF_PENV "UNINITIALIZED" "prefix+suffix")
+test_variable(TEST_ENV_REF_P "UNINITIALIZED" "")
+test_variable(TEST_ENV_P "UNINITIALIZED" "")
+test_variable(TEST_D_ENV_REF_P "UNINITIALIZED" "")
+test_variable(TEST_ENV_OVERRIDE_P "UNINITIALIZED" "This environment variable will be overridden")
+test_variable(TEST_PENV_P "UNINITIALIZED" "Process environment variable")
+test_variable(TEST_ENV_REF_PENV_P "UNINITIALIZED" "suffix")
+test_variable(TEST_MULTIPLE_MACROS "UNINITIALIZED" "Good ${CMAKE_GENERATOR}")
+test_variable(TEST_EXPANSION "UNINITIALIZED" "\\Good \${dollar} \$unknown{namespace} \$en{NOT_ENV} \$enve{NOT_ENV} $ \\$ $a")
+test_variable(TEST_TRAILING_DOLLAR "UNINITIALIZED" "a $")
+test_variable(TEST_TRAILING_BACKSLASH "UNINITIALIZED" "a \\")
+test_variable(TEST_TRAILING_UNKNOWN_NAMESPACE "UNINITIALIZED" "\$unknown{namespace")
+test_variable(TEST_OVERRIDE_1 "UNINITIALIZED" "Overridden value")
+test_variable(TEST_OVERRIDE_2 "STRING" "Overridden value")
+test_variable(TEST_OVERRIDE_3 "STRING" "Default value")
+test_variable(TEST_OVERRIDE_4 "INTERNAL" "Overridden value")
+
+if(DEFINED TEST_UNDEF OR DEFINED CACHE{TEST_UNDEF})
+  message(SEND_ERROR "TEST_UNDEF should not be defined")
+endif()
+
+test_environment_variable(TEST_ENV_REF "Environment variable")
+test_environment_variable(TEST_ENV "Environment variable")
+test_environment_variable(TEST_D_ENV_REF "xEnvironment variablex")
+test_environment_variable(TEST_ENV_OVERRIDE "Overridden environment variable")
+test_environment_variable(TEST_PENV "Process environment variable")
+test_environment_variable(TEST_ENV_REF_PENV "prefix+suffix")

+ 0 - 0
Tests/RunCMake/CMakePresets/GoodBOM.cmake


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

@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "GoodBOM",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ]
+}

+ 4 - 0
Tests/RunCMake/CMakePresets/GoodBinaryCmdLine.cmake

@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodBinaryCmdLine-build")

+ 3 - 0
Tests/RunCMake/CMakePresets/GoodBinaryRelative.cmake

@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")

+ 4 - 0
Tests/RunCMake/CMakePresets/GoodBinaryUp.cmake

@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodBinaryUp-build")

+ 3 - 0
Tests/RunCMake/CMakePresets/GoodGeneratorCmdLine.cmake

@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_GENERATOR "" "${RunCMake_GENERATOR}")

+ 6 - 0
Tests/RunCMake/CMakePresets/GoodInheritanceChild.cmake

@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(TEST_VARIABLE "STRING" "Some string")
+
+test_environment_variable(TEST_ENV "Some environment variable")

+ 3 - 0
Tests/RunCMake/CMakePresets/GoodInheritanceMacro.cmake

@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(PRESET_NAME "UNINITIALIZED" "GoodInheritanceMacro")

+ 10 - 0
Tests/RunCMake/CMakePresets/GoodInheritanceMulti.cmake

@@ -0,0 +1,10 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(FIRST_VARIABLE "STRING" "First variable")
+test_variable(SECOND_VARIABLE "STRING" "Second variable")
+test_variable(OVERRIDDEN_VARIABLE "STRING" "Overridden variable")
+
+test_environment_variable(FIRST_ENV "First environment variable")
+test_environment_variable(SECOND_ENV "Second environment variable")
+test_environment_variable(OVERRIDDEN_ENV "Overridden environment variable")

+ 3 - 0
Tests/RunCMake/CMakePresets/GoodInheritanceMultiSecond.cmake

@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")

+ 18 - 0
Tests/RunCMake/CMakePresets/GoodInheritanceOverride.cmake

@@ -0,0 +1,18 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(PARENT_VARIABLE "STRING" "Parent variable")
+test_variable(OVERRIDDEN_VARIABLE "STRING" "Overridden variable")
+test_variable(CHILD_VARIABLE "STRING" "Child variable")
+
+if(DEFINED DELETED_VARIABLE OR DEFINED CACHE{DELETED_VARIABLE})
+  message(SEND_ERROR "DELETED_VARIABLE should not be defined")
+endif()
+
+test_environment_variable(PARENT_ENV "Parent environment variable")
+test_environment_variable(CHILD_ENV "Child environment variable")
+test_environment_variable(OVERRIDDEN_ENV "Overridden environment variable")
+
+if(DEFINED ENV{DELETED_ENV})
+  message(SEND_ERROR "DELETED_ENV should not be defined")
+endif()

+ 6 - 0
Tests/RunCMake/CMakePresets/GoodInheritanceParent.cmake

@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(TEST_VARIABLE "STRING" "Some string")
+
+test_environment_variable(TEST_ENV "Some environment variable")

+ 0 - 0
Tests/RunCMake/CMakePresets/GoodNoArgs.cmake


+ 4 - 0
Tests/RunCMake/CMakePresets/GoodNoS.cmake

@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodNoS-build")

+ 0 - 0
Tests/RunCMake/CMakePresets/GoodSpaces.cmake


+ 0 - 0
Tests/RunCMake/CMakePresets/GoodUserFromMain.cmake


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

@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "GoodUserFromMain",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ]
+}

+ 4 - 0
Tests/RunCMake/CMakePresets/GoodUserFromMainUser.json.in

@@ -0,0 +1,4 @@
+{
+  "version": 1,
+  "configurePresets": []
+}

+ 0 - 0
Tests/RunCMake/CMakePresets/GoodUserFromUser.cmake


+ 4 - 0
Tests/RunCMake/CMakePresets/GoodUserFromUser.json.in

@@ -0,0 +1,4 @@
+{
+  "version": 1,
+  "configurePresets": []
+}

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

@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "GoodUserFromUser",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ]
+}

+ 0 - 0
Tests/RunCMake/CMakePresets/GoodUserOnly.cmake


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

@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "GoodUserOnly",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build"
+    }
+  ]
+}

+ 0 - 0
Tests/RunCMake/CMakePresets/GoodWindowsBackslash.cmake


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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/HighVersion-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/HighVersion: Unrecognized "version" field$

+ 4 - 0
Tests/RunCMake/CMakePresets/HighVersion.json.in

@@ -0,0 +1,4 @@
+{
+  "version": 1000,
+  "configurePresets": []
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig: Invalid preset$

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

@@ -0,0 +1,11 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "InvalidCMakeGeneratorConfig",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "cmakeGeneratorConfig": {}
+    }
+  ]
+}

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

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

+ 3 - 0
Tests/RunCMake/CMakePresets/InvalidGenerator-stderr.txt

@@ -0,0 +1,3 @@
+^CMake Error: Could not create named generator Invalid Generator
+
+Generators

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

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

+ 3 - 0
Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-stderr.txt

@@ -0,0 +1,3 @@
+^CMake Error: Could not create named generator Invalid Generator
+
+Generators

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidInheritance: Invalid preset$

+ 13 - 0
Tests/RunCMake/CMakePresets/InvalidInheritance.json.in

@@ -0,0 +1,13 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "InvalidInheritance",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "inherits": [
+        "NoExist"
+      ]
+    }
+  ]
+}

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

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

+ 2 - 0
Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt

@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir: Invalid preset$

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

@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "InvalidPresetBinaryDir",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": []
+    }
+  ]
+}

Some files were not shown because too many files changed in this diff