Merge topic 'FindGTest-config-mode'

2327b4330c FindGTest: Added support for CONFIG mode
6d45f951ed FindGTest: Minor whitespace change, moved an include upwards
98d5f033ed FindGTest: Ensure target names follow upstream GTest
585cc7c930 ci: install gmock in the Fedora 31 image

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5404
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index 93e1151..62c4b7c 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -130,34 +130,34 @@
       the ``architecture`` field instead.
 
     ``architecture``
-
-      An optional string representing the platform name to use for generators
-      that support platforms.
-
     ``toolset``
 
-      An optional string representing the toolset name to use for generators
-      that support toolsets.
+      Optional fields representing the platform and toolset, respectively, for
+      generators that support them. Each may be either a string or an object
+      with the following fields:
 
-    ``cmakeGeneratorConfig``
+      ``value``
 
-      An optional string telling CMake how to handle the ``architecture`` and
-      ``toolset`` fields. Valid values are:
+        An optional string representing the value.
 
-      ``"default"``
+      ``strategy``
 
-        Set the platform and toolset using the ``architecture`` and ``toolset``
-        fields respectively. On non-Visual Studio generators, this will result
-        in an error if ``architecture`` or ``toolset`` are set.
+        An optional string telling CMake how to handle the ``architecture`` or
+        ``toolset`` field. Valid values are:
 
-      ``"ignore"``
+        ``"set"``
 
-        Do not set the platform or toolset at all, even on Visual Studio
-        generators. This is useful if, for example, a preset uses the Ninja
-        generator, and an IDE knows how to set up the Visual C++ environment
-        from the ``architecture`` and ``toolset`` fields. In that case, CMake
-        will ignore ``architecture`` and ``toolset``, but the IDE can use them
-        to set up the environment before invoking CMake.
+          Set the respective value. This will result in an error for generators
+          that do not support the respective field.
+
+        ``"external"``
+
+          Do not set the value, even if the generator supports it. This is
+          useful if, for example, a preset uses the Ninja generator, and an IDE
+          knows how to set up the Visual C++ environment from the
+          ``architecture`` and ``toolset`` fields. In that case, CMake will
+          ignore the field, but the IDE can use them to set up the environment
+          before invoking CMake.
 
     ``binaryDir``
 
@@ -176,9 +176,10 @@
     ``cacheVariables``
 
       An optional map of cache variables. The key is the variable name (which
-      may not be an empty string), and the value is either ``null``, a string
-      representing the value of the variable (which supports macro expansion),
-      or an object with the following fields:
+      may not be an empty string), and the value is either ``null``, a boolean
+      (which is equivalent to a value of ``"TRUE"`` or ``"FALSE"`` and a type
+      of ``BOOL``), a string representing the value of the variable (which
+      supports macro expansion), or an object with the following fields:
 
       ``type``
 
@@ -186,7 +187,8 @@
 
       ``value``
 
-        A required string representing the value of the variable. This field
+        A required string or boolean representing the value of the variable.
+        A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``. This field
         supports macro expansion.
 
       Cache variables are inherited through the ``inherits`` field, and the
@@ -306,6 +308,11 @@
 
     Path to the project source directory's parent directory.
 
+  ``${sourceDirName}``
+
+    The last filename component of ``${sourceDir}``. For example, if
+    ``${sourceDir}`` is ``/path/to/source``, this would be ``source``.
+
   ``${presetName}``
 
     Name specified in the preset's ``name`` field.
diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json
index 564c94c..57b063e 100644
--- a/Help/manual/presets/schema.json
+++ b/Help/manual/presets/schema.json
@@ -85,19 +85,57 @@
             "description": "An optional string representing the generator to use for the preset. If generator is not specified, it must be inherited from the inherits preset (unless this preset is hidden). Note that for Visual Studio generators, unlike in the command line -G argument, you cannot include the platform name in the generator name. Use the architecture field instead."
           },
           "architecture": {
-            "type": "string",
-            "description": "An optional string representing the platform name to use for Visual Studio generators."
+            "anyOf": [
+              {
+                "type": "string",
+                "description": "An optional string representing the platform for generators that support it."
+              },
+              {
+                "type": "object",
+                "description": "An optional object representing the platform for generators that support it.",
+                "properties": {
+                  "value": {
+                    "type": "string",
+                    "description": "An optional string representing the value."
+                  },
+                  "strategy": {
+                    "type": "string",
+                    "description": "An optional string telling CMake how to handle the field. Valid values are: \"set\" Set the respective value. This will result in an error for generators that do not support the respective field. \"external\" Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore the field, but the IDE can use them to set up the environment before invoking CMake.",
+                    "enum": [
+                      "set",
+                      "external"
+                    ]
+                  }
+                },
+                "additionalProperties": false
+              }
+            ]
           },
           "toolset": {
-            "type": "string",
-            "description": "An optional string representing the toolset name to use for Visual Studio generators."
-          },
-          "cmakeGeneratorConfig": {
-            "type": "string",
-            "description": "An optional string telling CMake how to handle the architecture and toolset fields. Valid values are: \"default\": Set the platform and toolset using the architecture and toolset fields respectively. On non-Visual Studio generators, this will result in an error if architecture or toolset are set. \"ignore\": Do not set the platform or toolset at all, even on Visual Studio generators. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore architecture and toolset, but the IDE can use them to set up the environment before invoking CMake.",
-            "enum": [
-              "default",
-              "ignore"
+            "anyOf": [
+              {
+                "type": "string",
+                "description": "An optional string representing the toolset for generators that support it."
+              },
+              {
+                "type": "object",
+                "description": "An optional object representing the toolset for generators that support it.",
+                "properties": {
+                  "value": {
+                    "type": "string",
+                    "description": "An optional string representing the value."
+                  },
+                  "strategy": {
+                    "type": "string",
+                    "description": "An optional string telling CMake how to handle the field. Valid values are: \"set\" Set the respective value. This will result in an error for generators that do not support the respective field. \"external\" Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the architecture and toolset fields. In that case, CMake will ignore the field, but the IDE can use them to set up the environment before invoking CMake.",
+                    "enum": [
+                      "set",
+                      "external"
+                    ]
+                  }
+                },
+                "additionalProperties": false
+              }
             ]
           },
           "binaryDir": {
@@ -119,6 +157,10 @@
                   "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
                 },
                 {
+                  "type": "boolean",
+                  "description": "A boolean representing the value of the variable. Equivalent to \"TRUE\" or \"FALSE\"."
+                },
+                {
                   "type": "string",
                   "description": "A string representing the value of the variable (which supports macro expansion)."
                 },
@@ -131,8 +173,16 @@
                       "description": "An optional string representing the type of the variable. It should be BOOL, FILEPATH, PATH, STRING, or INTERNAL."
                     },
                     "value": {
-                      "type": "string",
-                      "description": "A required string representing the value of the variable. This field supports macro expansion."
+                      "anyOf": [
+                        {
+                          "type": "boolean",
+                          "description": "A required boolean representing the value of the variable. Equivalent to \"TRUE\" or \"FALSE\"."
+                        },
+                        {
+                          "type": "string",
+                          "description": "A required string representing the value of the variable. This field supports macro expansion."
+                        }
+                      ]
                     }
                   },
                   "required": [
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 8148eac..48ea3f6 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 19)
-set(CMake_VERSION_PATCH 20201021)
+set(CMake_VERSION_PATCH 20201023)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 4d1a589..84bb791 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -122,7 +122,7 @@
       readit = status.GetMakefile().ReadDependentFile(fname);
     }
     if (!readit) {
-      status.SetError(cmStrCat("Could not find include file: ", fname));
+      status.SetError(cmStrCat("Could not load include file: ", fname));
       return false;
     }
   }
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 7a04daa..a15614d 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -859,8 +859,10 @@
   if (presetData.isValid()) {
     auto preset = presetData.value<QCMakePreset>();
     dialog.setCurrentGenerator(preset.generator);
-    if (preset.setGenConfig) {
+    if (preset.setArchitecture) {
       dialog.setPlatform(preset.architecture);
+    }
+    if (preset.setToolset) {
       dialog.setToolset(preset.toolset);
     }
     dialog.setCompilerOption(CompilerOption::DefaultNative);
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index 9017a63..2f41f70 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -157,8 +157,8 @@
 
     if (!name.isNull()) {
       std::string presetName(name.toLocal8Bit());
-      auto const& preset = this->CMakePresetsFile.Presets[presetName];
-      auto expandedPreset = this->CMakePresetsFile.ExpandMacros(preset);
+      auto const& expandedPreset =
+        this->CMakePresetsFile.Presets[presetName].Expanded;
       if (expandedPreset) {
         if (setBinary) {
           QString binaryDir =
@@ -420,8 +420,7 @@
 
   if (!this->PresetName.isNull()) {
     std::string presetName(this->PresetName.toLocal8Bit());
-    auto p = this->CMakePresetsFile.ExpandMacros(
-      this->CMakePresetsFile.Presets.at(presetName));
+    auto const& p = this->CMakePresetsFile.Presets.at(presetName).Expanded;
     if (p) {
       for (auto const& v : p->CacheVariables) {
         if (!v.second) {
@@ -537,7 +536,8 @@
 
   QVector<QCMakePreset> presets;
   for (auto const& name : this->CMakePresetsFile.PresetOrder) {
-    auto const& p = this->CMakePresetsFile.Presets[name];
+    auto const& it = this->CMakePresetsFile.Presets[name];
+    auto const& p = it.Unexpanded;
     if (p.Hidden) {
       continue;
     }
@@ -551,15 +551,17 @@
     preset.generator = std::move(QString::fromLocal8Bit(p.Generator.data()));
     preset.architecture =
       std::move(QString::fromLocal8Bit(p.Architecture.data()));
+    preset.setArchitecture = !p.ArchitectureStrategy ||
+      p.ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
     preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data()));
-    preset.setGenConfig = !p.GeneratorConfig ||
-      p.GeneratorConfig == cmCMakePresetsFile::CMakeGeneratorConfig::Default;
-    preset.enabled = std::find_if(this->AvailableGenerators.begin(),
-                                  this->AvailableGenerators.end(),
-                                  [&p](const cmake::GeneratorInfo& g) {
-                                    return g.name == p.Generator;
-                                  }) != this->AvailableGenerators.end() &&
-      this->CMakePresetsFile.ExpandMacros(p);
+    preset.setToolset = !p.ToolsetStrategy ||
+      p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
+    preset.enabled = it.Expanded &&
+      std::find_if(this->AvailableGenerators.begin(),
+                   this->AvailableGenerators.end(),
+                   [&p](const cmake::GeneratorInfo& g) {
+                     return g.name == p.Generator;
+                   }) != this->AvailableGenerators.end();
     presets.push_back(preset);
   }
   emit this->presetsChanged(presets);
diff --git a/Source/QtDialog/QCMakePreset.cxx b/Source/QtDialog/QCMakePreset.cxx
index b10cf07..176f532 100644
--- a/Source/QtDialog/QCMakePreset.cxx
+++ b/Source/QtDialog/QCMakePreset.cxx
@@ -6,8 +6,9 @@
 {
   return lhs.name == rhs.name && lhs.displayName == rhs.displayName &&
     lhs.description == rhs.description && lhs.generator == rhs.generator &&
-    lhs.architecture == rhs.architecture && lhs.toolset == rhs.toolset &&
-    lhs.setGenConfig == rhs.setGenConfig && lhs.enabled == rhs.enabled;
+    lhs.architecture == rhs.architecture &&
+    lhs.setArchitecture == rhs.setArchitecture && lhs.toolset == rhs.toolset &&
+    lhs.setToolset == rhs.setToolset && lhs.enabled == rhs.enabled;
 }
 
 bool operator!=(const QCMakePreset& lhs, const QCMakePreset& rhs)
@@ -27,11 +28,13 @@
           (lhs.generator == rhs.generator &&
            (lhs.architecture < rhs.architecture ||
             (lhs.architecture == rhs.architecture &&
-             (lhs.toolset < rhs.toolset ||
-              (lhs.toolset == rhs.toolset &&
-               (lhs.setGenConfig < rhs.setGenConfig ||
-                (lhs.setGenConfig == rhs.setGenConfig &&
-                 (lhs.enabled < rhs.enabled))))))))))))));
+             (lhs.setArchitecture < rhs.setArchitecture ||
+              (lhs.setArchitecture == rhs.setArchitecture &&
+               (lhs.toolset < rhs.toolset ||
+                (lhs.toolset == rhs.toolset &&
+                 (lhs.setToolset < rhs.setToolset ||
+                  (lhs.setToolset == rhs.setToolset &&
+                   (lhs.enabled < rhs.enabled))))))))))))))));
 }
 
 bool operator<=(const QCMakePreset& lhs, const QCMakePreset& rhs)
diff --git a/Source/QtDialog/QCMakePreset.h b/Source/QtDialog/QCMakePreset.h
index 93d70d8..1609fcb 100644
--- a/Source/QtDialog/QCMakePreset.h
+++ b/Source/QtDialog/QCMakePreset.h
@@ -15,8 +15,9 @@
   QString description;
   QString generator;
   QString architecture;
+  bool setArchitecture;
   QString toolset;
-  bool setGenConfig;
+  bool setToolset;
   bool enabled;
 };
 
diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx
index 90a0faa..cf5db6e 100644
--- a/Source/cmCMakePresetsFile.cxx
+++ b/Source/cmCMakePresetsFile.cxx
@@ -29,7 +29,8 @@
 using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
 using CacheVariable = cmCMakePresetsFile::CacheVariable;
 using UnexpandedPreset = cmCMakePresetsFile::UnexpandedPreset;
-using CMakeGeneratorConfig = cmCMakePresetsFile::CMakeGeneratorConfig;
+using ExpandedPreset = cmCMakePresetsFile::ExpandedPreset;
+using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy;
 
 constexpr int MIN_VERSION = 1;
 constexpr int MAX_VERSION = 1;
@@ -77,15 +78,37 @@
 auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
   ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
 
+ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
+{
+  if (!value) {
+    out.clear();
+    return ReadFileResult::READ_OK;
+  }
+
+  if (value->isBool()) {
+    out = value->asBool() ? "TRUE" : "FALSE";
+    return ReadFileResult::READ_OK;
+  }
+
+  return VariableStringHelper(out, value);
+}
+
 auto const VariableObjectHelper =
   cmJSONObjectHelper<CacheVariable, ReadFileResult>(
     ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
     .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
-    .Bind("value"_s, &CacheVariable::Value, VariableStringHelper);
+    .Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
 
 ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
                               const Json::Value* value)
 {
+  if (value->isBool()) {
+    out = CacheVariable{
+      /*Type=*/"BOOL",
+      /*Value=*/value->asBool() ? "TRUE" : "FALSE",
+    };
+    return ReadFileResult::READ_OK;
+  }
   if (value->isString()) {
     out = CacheVariable{
       /*Type=*/"",
@@ -189,8 +212,8 @@
     .Bind("find"_s, &UnexpandedPreset::DebugFind, PresetOptionalBoolHelper,
           false);
 
-ReadFileResult CMakeGeneratorConfigHelper(
-  cm::optional<CMakeGeneratorConfig>& out, const Json::Value* value)
+ReadFileResult ArchToolsetStrategyHelper(
+  cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
 {
   if (!value) {
     out = cm::nullopt;
@@ -201,19 +224,56 @@
     return ReadFileResult::INVALID_PRESET;
   }
 
-  if (value->asString() == "default") {
-    out = CMakeGeneratorConfig::Default;
+  if (value->asString() == "set") {
+    out = ArchToolsetStrategy::Set;
     return ReadFileResult::READ_OK;
   }
 
-  if (value->asString() == "ignore") {
-    out = CMakeGeneratorConfig::Ignore;
+  if (value->asString() == "external") {
+    out = ArchToolsetStrategy::External;
     return ReadFileResult::READ_OK;
   }
 
   return ReadFileResult::INVALID_PRESET;
 }
 
+std::function<ReadFileResult(UnexpandedPreset&, const Json::Value*)>
+ArchToolsetHelper(
+  std::string UnexpandedPreset::*valueField,
+  cm::optional<ArchToolsetStrategy> UnexpandedPreset::*strategyField)
+{
+  auto const objectHelper =
+    cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+      ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+      .Bind("value", valueField, PresetStringHelper, false)
+      .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
+  return [valueField, strategyField, objectHelper](
+           UnexpandedPreset& out, const Json::Value* value) -> ReadFileResult {
+    if (!value) {
+      (out.*valueField).clear();
+      out.*strategyField = cm::nullopt;
+      return ReadFileResult::READ_OK;
+    }
+
+    if (value->isString()) {
+      out.*valueField = value->asString();
+      out.*strategyField = cm::nullopt;
+      return ReadFileResult::READ_OK;
+    }
+
+    if (value->isObject()) {
+      return objectHelper(out, value);
+    }
+
+    return ReadFileResult::INVALID_PRESET;
+  };
+}
+
+auto const ArchitectureHelper = ArchToolsetHelper(
+  &UnexpandedPreset::Architecture, &UnexpandedPreset::ArchitectureStrategy);
+auto const ToolsetHelper = ArchToolsetHelper(
+  &UnexpandedPreset::Toolset, &UnexpandedPreset::ToolsetStrategy);
+
 auto const PresetHelper =
   cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
     ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
@@ -229,11 +289,8 @@
           false)
     .Bind("generator"_s, &UnexpandedPreset::Generator, PresetStringHelper,
           false)
-    .Bind("architecture"_s, &UnexpandedPreset::Architecture,
-          PresetStringHelper, false)
-    .Bind("toolset"_s, &UnexpandedPreset::Toolset, PresetStringHelper, false)
-    .Bind("cmakeGeneratorConfig"_s, &UnexpandedPreset::GeneratorConfig,
-          CMakeGeneratorConfigHelper, false)
+    .Bind("architecture"_s, ArchitectureHelper, false)
+    .Bind("toolset"_s, ToolsetHelper, false)
     .Bind("binaryDir"_s, &UnexpandedPreset::BinaryDir, PresetStringHelper,
           false)
     .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
@@ -290,9 +347,9 @@
  * that each preset has the required fields, either directly or through
  * inheritance.
  */
-ReadFileResult VisitPreset(std::map<std::string, UnexpandedPreset>& presets,
-                           UnexpandedPreset& preset,
-                           std::map<std::string, CycleStatus> cycleStatus)
+ReadFileResult VisitPreset(
+  std::map<std::string, cmCMakePresetsFile::PresetPair>& presets,
+  UnexpandedPreset& preset, std::map<std::string, CycleStatus> cycleStatus)
 {
   switch (cycleStatus[preset.Name]) {
     case CycleStatus::InProgress:
@@ -318,35 +375,42 @@
       return ReadFileResult::INVALID_PRESET;
     }
 
-    if (!preset.User && parent->second.User) {
+    if (!preset.User && parent->second.Unexpanded.User) {
       return ReadFileResult::USER_PRESET_INHERITANCE;
     }
 
-    auto result = VisitPreset(presets, parent->second, cycleStatus);
+    auto result = VisitPreset(presets, parent->second.Unexpanded, cycleStatus);
     if (result != ReadFileResult::READ_OK) {
       return result;
     }
 
-    InheritString(preset.Generator, parent->second.Generator);
-    InheritString(preset.Architecture, parent->second.Architecture);
-    InheritString(preset.Toolset, parent->second.Toolset);
-    if (!preset.GeneratorConfig) {
-      preset.GeneratorConfig = parent->second.GeneratorConfig;
+    InheritString(preset.Generator, parent->second.Unexpanded.Generator);
+    InheritString(preset.Architecture, parent->second.Unexpanded.Architecture);
+    InheritString(preset.Toolset, parent->second.Unexpanded.Toolset);
+    if (!preset.ArchitectureStrategy) {
+      preset.ArchitectureStrategy =
+        parent->second.Unexpanded.ArchitectureStrategy;
     }
-    InheritString(preset.BinaryDir, parent->second.BinaryDir);
-    InheritOptionalBool(preset.WarnDev, parent->second.WarnDev);
-    InheritOptionalBool(preset.ErrorDev, parent->second.ErrorDev);
-    InheritOptionalBool(preset.WarnDeprecated, parent->second.WarnDeprecated);
+    if (!preset.ToolsetStrategy) {
+      preset.ToolsetStrategy = parent->second.Unexpanded.ToolsetStrategy;
+    }
+    InheritString(preset.BinaryDir, parent->second.Unexpanded.BinaryDir);
+    InheritOptionalBool(preset.WarnDev, parent->second.Unexpanded.WarnDev);
+    InheritOptionalBool(preset.ErrorDev, parent->second.Unexpanded.ErrorDev);
+    InheritOptionalBool(preset.WarnDeprecated,
+                        parent->second.Unexpanded.WarnDeprecated);
     InheritOptionalBool(preset.ErrorDeprecated,
-                        parent->second.ErrorDeprecated);
+                        parent->second.Unexpanded.ErrorDeprecated);
     InheritOptionalBool(preset.WarnUninitialized,
-                        parent->second.WarnUninitialized);
-    InheritOptionalBool(preset.WarnUnusedCli, parent->second.WarnUnusedCli);
-    InheritOptionalBool(preset.WarnSystemVars, parent->second.WarnSystemVars);
-    for (auto const& v : parent->second.CacheVariables) {
+                        parent->second.Unexpanded.WarnUninitialized);
+    InheritOptionalBool(preset.WarnUnusedCli,
+                        parent->second.Unexpanded.WarnUnusedCli);
+    InheritOptionalBool(preset.WarnSystemVars,
+                        parent->second.Unexpanded.WarnSystemVars);
+    for (auto const& v : parent->second.Unexpanded.CacheVariables) {
       preset.CacheVariables.insert(v);
     }
-    for (auto const& v : parent->second.Environment) {
+    for (auto const& v : parent->second.Unexpanded.Environment) {
       preset.Environment.insert(v);
     }
   }
@@ -371,7 +435,7 @@
 }
 
 ReadFileResult ComputePresetInheritance(
-  std::map<std::string, UnexpandedPreset>& presets)
+  std::map<std::string, cmCMakePresetsFile::PresetPair>& presets)
 {
   std::map<std::string, CycleStatus> cycleStatus;
   for (auto const& it : presets) {
@@ -379,7 +443,7 @@
   }
 
   for (auto& it : presets) {
-    auto result = VisitPreset(presets, it.second, cycleStatus);
+    auto result = VisitPreset(presets, it.second.Unexpanded, cycleStatus);
     if (result != ReadFileResult::READ_OK) {
       return result;
     }
@@ -415,44 +479,111 @@
   return false;
 }
 
-bool VisitEnv(const cmCMakePresetsFile& file,
-              cmCMakePresetsFile::ExpandedPreset& preset,
-              std::map<std::string, CycleStatus>& envCycles,
-              std::string& value, CycleStatus& status);
-bool ExpandMacros(const cmCMakePresetsFile& file,
-                  cmCMakePresetsFile::ExpandedPreset& preset,
-                  std::map<std::string, CycleStatus>& envCycles,
-                  std::string& out);
-bool ExpandMacro(const cmCMakePresetsFile& file,
-                 cmCMakePresetsFile::ExpandedPreset& preset,
-                 std::map<std::string, CycleStatus>& envCycles,
-                 std::string& out, const std::string& macroNamespace,
-                 const std::string& macroName);
-
-bool VisitEnv(const cmCMakePresetsFile& file,
-              cmCMakePresetsFile::ExpandedPreset& preset,
-              std::map<std::string, CycleStatus>& envCycles,
-              std::string& value, CycleStatus& status)
+enum class ExpandMacroResult
 {
-  if (status == CycleStatus::Verified) {
-    return true;
-  }
-  if (status == CycleStatus::InProgress) {
-    return false;
+  Ok,
+  Ignore,
+  Error,
+};
+
+ExpandMacroResult VisitEnv(const cmCMakePresetsFile& file,
+                           cmCMakePresetsFile::ExpandedPreset& preset,
+                           std::map<std::string, CycleStatus>& envCycles,
+                           std::string& value, CycleStatus& status);
+ExpandMacroResult ExpandMacros(const cmCMakePresetsFile& file,
+                               cmCMakePresetsFile::ExpandedPreset& preset,
+                               std::map<std::string, CycleStatus>& envCycles,
+                               std::string& out);
+ExpandMacroResult ExpandMacro(const cmCMakePresetsFile& file,
+                              cmCMakePresetsFile::ExpandedPreset& preset,
+                              std::map<std::string, CycleStatus>& envCycles,
+                              std::string& out,
+                              const std::string& macroNamespace,
+                              const std::string& macroName);
+
+bool ExpandMacros(const cmCMakePresetsFile& file,
+                  const UnexpandedPreset& preset,
+                  cm::optional<ExpandedPreset>& out)
+{
+  out = preset;
+
+  std::map<std::string, CycleStatus> envCycles;
+  for (auto const& v : out->Environment) {
+    envCycles[v.first] = CycleStatus::Unvisited;
   }
 
-  status = CycleStatus::InProgress;
-  if (!ExpandMacros(file, preset, envCycles, value)) {
-    return false;
+  for (auto& v : out->Environment) {
+    if (v.second) {
+      switch (VisitEnv(file, *out, envCycles, *v.second, envCycles[v.first])) {
+        case ExpandMacroResult::Error:
+          return false;
+        case ExpandMacroResult::Ignore:
+          out.reset();
+          return true;
+        case ExpandMacroResult::Ok:
+          break;
+      }
+    }
   }
-  status = CycleStatus::Verified;
+
+  std::string binaryDir = preset.BinaryDir;
+  switch (ExpandMacros(file, *out, envCycles, binaryDir)) {
+    case ExpandMacroResult::Error:
+      return false;
+    case ExpandMacroResult::Ignore:
+      out.reset();
+      return true;
+    case ExpandMacroResult::Ok:
+      break;
+  }
+  if (!cmSystemTools::FileIsFullPath(binaryDir)) {
+    binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
+  }
+  out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
+  cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
+
+  for (auto& variable : out->CacheVariables) {
+    if (variable.second) {
+      switch (ExpandMacros(file, *out, envCycles, variable.second->Value)) {
+        case ExpandMacroResult::Error:
+          return false;
+        case ExpandMacroResult::Ignore:
+          out.reset();
+          return true;
+        case ExpandMacroResult::Ok:
+          break;
+      }
+    }
+  }
+
   return true;
 }
 
-bool ExpandMacros(const cmCMakePresetsFile& file,
-                  cmCMakePresetsFile::ExpandedPreset& preset,
-                  std::map<std::string, CycleStatus>& envCycles,
-                  std::string& out)
+ExpandMacroResult VisitEnv(const cmCMakePresetsFile& file,
+                           cmCMakePresetsFile::ExpandedPreset& preset,
+                           std::map<std::string, CycleStatus>& envCycles,
+                           std::string& value, CycleStatus& status)
+{
+  if (status == CycleStatus::Verified) {
+    return ExpandMacroResult::Ok;
+  }
+  if (status == CycleStatus::InProgress) {
+    return ExpandMacroResult::Error;
+  }
+
+  status = CycleStatus::InProgress;
+  auto e = ExpandMacros(file, preset, envCycles, value);
+  if (e != ExpandMacroResult::Ok) {
+    return e;
+  }
+  status = CycleStatus::Verified;
+  return ExpandMacroResult::Ok;
+}
+
+ExpandMacroResult ExpandMacros(const cmCMakePresetsFile& file,
+                               cmCMakePresetsFile::ExpandedPreset& preset,
+                               std::map<std::string, CycleStatus>& envCycles,
+                               std::string& out)
 {
   std::string result;
   std::string macroNamespace;
@@ -499,9 +630,10 @@
 
       case State::MacroName:
         if (c == '}') {
-          if (!ExpandMacro(file, preset, envCycles, result, macroNamespace,
-                           macroName)) {
-            return false;
+          auto e = ExpandMacro(file, preset, envCycles, result, macroNamespace,
+                               macroName);
+          if (e != ExpandMacroResult::Ok) {
+            return e;
           }
           macroNamespace.clear();
           macroName.clear();
@@ -521,67 +653,76 @@
       result += macroNamespace;
       break;
     case State::MacroName:
-      return false;
+      return ExpandMacroResult::Error;
   }
 
   out = std::move(result);
-  return true;
+  return ExpandMacroResult::Ok;
 }
 
-bool ExpandMacro(const cmCMakePresetsFile& file,
-                 cmCMakePresetsFile::ExpandedPreset& preset,
-                 std::map<std::string, CycleStatus>& envCycles,
-                 std::string& out, const std::string& macroNamespace,
-                 const std::string& macroName)
+ExpandMacroResult ExpandMacro(const cmCMakePresetsFile& file,
+                              cmCMakePresetsFile::ExpandedPreset& preset,
+                              std::map<std::string, CycleStatus>& envCycles,
+                              std::string& out,
+                              const std::string& macroNamespace,
+                              const std::string& macroName)
 {
   if (macroNamespace.empty()) {
     if (macroName == "sourceDir") {
       out += file.SourceDir;
-      return true;
+      return ExpandMacroResult::Ok;
     }
     if (macroName == "sourceParentDir") {
       out += cmSystemTools::GetParentDirectory(file.SourceDir);
-      return true;
+      return ExpandMacroResult::Ok;
+    }
+    if (macroName == "sourceDirName") {
+      out += cmSystemTools::GetFilenameName(file.SourceDir);
+      return ExpandMacroResult::Ok;
     }
     if (macroName == "presetName") {
       out += preset.Name;
-      return true;
+      return ExpandMacroResult::Ok;
     }
     if (macroName == "generator") {
       out += preset.Generator;
-      return true;
+      return ExpandMacroResult::Ok;
     }
     if (macroName == "dollar") {
       out += '$';
-      return true;
+      return ExpandMacroResult::Ok;
     }
   }
 
   if (macroNamespace == "env" && !macroName.empty()) {
     auto v = preset.Environment.find(macroName);
     if (v != preset.Environment.end() && v->second) {
-      if (!VisitEnv(file, preset, envCycles, *v->second,
-                    envCycles[macroName])) {
-        return false;
+      auto e =
+        VisitEnv(file, preset, envCycles, *v->second, envCycles[macroName]);
+      if (e != ExpandMacroResult::Ok) {
+        return e;
       }
       out += *v->second;
-      return true;
+      return ExpandMacroResult::Ok;
     }
   }
 
   if (macroNamespace == "env" || macroNamespace == "penv") {
     if (macroName.empty()) {
-      return false;
+      return ExpandMacroResult::Error;
     }
     const char* value = std::getenv(macroName.c_str());
     if (value) {
       out += value;
     }
-    return true;
+    return ExpandMacroResult::Ok;
   }
 
-  // "vendor" falls through to here
-  return false;
+  if (macroNamespace == "vendor") {
+    return ExpandMacroResult::Ignore;
+  }
+
+  return ExpandMacroResult::Error;
 }
 }
 
@@ -604,7 +745,7 @@
   this->PresetOrder.clear();
 
   std::vector<std::string> presetOrder;
-  std::map<std::string, UnexpandedPreset> presetMap;
+  std::map<std::string, PresetPair> presetMap;
 
   std::string filename = GetUserFilename(this->SourceDir);
   if (cmSystemTools::FileExists(filename)) {
@@ -634,6 +775,12 @@
     return result;
   }
 
+  for (auto& it : presetMap) {
+    if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+      return ReadFileResult::INVALID_MACRO_EXPANSION;
+    }
+  }
+
   this->PresetOrder = std::move(presetOrder);
   this->Presets = std::move(presetMap);
   return ReadFileResult::READ_OK;
@@ -672,51 +819,16 @@
       return "Cyclic preset inheritance";
     case ReadFileResult::USER_PRESET_INHERITANCE:
       return "Project preset inherits from user preset";
-    default:
-      return "Unknown error";
-  }
-}
-
-cm::optional<cmCMakePresetsFile::ExpandedPreset>
-cmCMakePresetsFile::ExpandMacros(const UnexpandedPreset& preset) const
-{
-  ExpandedPreset retval{ preset };
-
-  std::map<std::string, CycleStatus> envCycles;
-  for (auto const& v : retval.Environment) {
-    envCycles[v.first] = CycleStatus::Unvisited;
+    case ReadFileResult::INVALID_MACRO_EXPANSION:
+      return "Invalid macro expansion";
   }
 
-  for (auto& v : retval.Environment) {
-    if (v.second &&
-        !VisitEnv(*this, retval, envCycles, *v.second, envCycles[v.first])) {
-      return cm::nullopt;
-    }
-  }
-
-  std::string binaryDir = preset.BinaryDir;
-  if (!::ExpandMacros(*this, retval, envCycles, binaryDir)) {
-    return cm::nullopt;
-  }
-  if (!cmSystemTools::FileIsFullPath(binaryDir)) {
-    binaryDir = cmStrCat(this->SourceDir, '/', binaryDir);
-  }
-  retval.BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
-  cmSystemTools::ConvertToUnixSlashes(retval.BinaryDir);
-
-  for (auto& variable : retval.CacheVariables) {
-    if (variable.second &&
-        !::ExpandMacros(*this, retval, envCycles, variable.second->Value)) {
-      return cm::nullopt;
-    }
-  }
-
-  return cm::make_optional(retval);
+  return "Unknown error";
 }
 
 cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
   const std::string& filename, std::vector<std::string>& presetOrder,
-  std::map<std::string, UnexpandedPreset>& presetMap, bool user)
+  std::map<std::string, PresetPair>& presetMap, bool user)
 {
   cmsys::ifstream fin(filename.c_str());
   if (!fin) {
@@ -763,7 +875,7 @@
     if (preset.Name.empty()) {
       return ReadFileResult::INVALID_PRESET;
     }
-    if (!presetMap.insert({ preset.Name, preset }).second) {
+    if (!presetMap.insert({ preset.Name, { preset, cm::nullopt } }).second) {
       return ReadFileResult::DUPLICATE_PRESETS;
     }
     presetOrder.push_back(preset.Name);
diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h
index 70ec4c5..f6b159a 100644
--- a/Source/cmCMakePresetsFile.h
+++ b/Source/cmCMakePresetsFile.h
@@ -12,10 +12,10 @@
 class cmCMakePresetsFile
 {
 public:
-  enum class CMakeGeneratorConfig
+  enum class ArchToolsetStrategy
   {
-    Default,
-    Ignore,
+    Set,
+    External,
   };
 
   class CacheVariable
@@ -50,8 +50,9 @@
     std::string Description;
     std::string Generator;
     std::string Architecture;
+    cm::optional<ArchToolsetStrategy> ArchitectureStrategy;
     std::string Toolset;
-    cm::optional<CMakeGeneratorConfig> GeneratorConfig;
+    cm::optional<ArchToolsetStrategy> ToolsetStrategy;
     std::string BinaryDir;
 
     std::map<std::string, cm::optional<CacheVariable>> CacheVariables;
@@ -102,8 +103,15 @@
     }
   };
 
+  class PresetPair
+  {
+  public:
+    UnexpandedPreset Unexpanded;
+    cm::optional<ExpandedPreset> Expanded;
+  };
+
   std::string SourceDir;
-  std::map<std::string, UnexpandedPreset> Presets;
+  std::map<std::string, PresetPair> Presets;
   std::vector<std::string> PresetOrder;
 
   enum class ReadFileResult
@@ -123,6 +131,7 @@
     DUPLICATE_PRESETS,
     CYCLIC_PRESET_INHERITANCE,
     USER_PRESET_INHERITANCE,
+    INVALID_MACRO_EXPANSION,
   };
 
   static std::string GetFilename(const std::string& sourceDir);
@@ -131,11 +140,9 @@
                                     bool allowNoFiles = false);
   static const char* ResultToString(ReadFileResult result);
 
-  cm::optional<ExpandedPreset> ExpandMacros(
-    const UnexpandedPreset& preset) const;
-
 private:
-  ReadFileResult ReadJSONFile(
-    const std::string& filename, std::vector<std::string>& presetOrder,
-    std::map<std::string, UnexpandedPreset>& presetMap, bool user);
+  ReadFileResult ReadJSONFile(const std::string& filename,
+                              std::vector<std::string>& presetOrder,
+                              std::map<std::string, PresetPair>& presetMap,
+                              bool user);
 };
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index ae801bb..5e3aec5 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -146,11 +146,24 @@
 
   std::string listFile = cmSystemTools::CollapseFullPath(
     fname, status.GetMakefile().GetCurrentSourceDirectory());
-  if (optional && !cmSystemTools::FileExists(listFile)) {
+
+  const bool fileDoesnotExist = !cmSystemTools::FileExists(listFile);
+  const bool fileIsDirectory = cmSystemTools::FileIsDirectory(listFile);
+  if (fileDoesnotExist || fileIsDirectory) {
     if (!resultVarName.empty()) {
       status.GetMakefile().AddDefinition(resultVarName, "NOTFOUND");
     }
-    return true;
+    if (optional) {
+      return true;
+    }
+    if (fileDoesnotExist) {
+      status.SetError(cmStrCat("could not find requested file:\n  ", fname));
+      return false;
+    }
+    if (fileIsDirectory) {
+      status.SetError(cmStrCat("requested file is a directory:\n  ", fname));
+      return false;
+    }
   }
 
   bool readit =
@@ -163,9 +176,7 @@
   }
 
   if (!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) {
-    std::string m = cmStrCat("could not find load file:\n"
-                             "  ",
-                             fname);
+    std::string m = cmStrCat("could not load requested file:\n  ", fname);
     status.SetError(m);
     return false;
   }
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index fdf8307..d2cdb99 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -275,10 +275,9 @@
   { "SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0 },
   { "SourceFileFormat", "fixed", "Use Fixed Format", "fileFormatFixed", 0 },
   { "SourceFileFormat", "free", "Use Free Format", "fileFormatFree", 0 },
-  { "DebugInformationFormat", "Zi", "full debug", "debugEnabled", 0 },
   { "DebugInformationFormat", "debug:full", "full debug", "debugEnabled", 0 },
-  { "DebugInformationFormat", "Z7", "c7 compat", "debugOldStyleInfo", 0 },
-  { "DebugInformationFormat", "Zd", "line numbers", "debugLineInfoOnly", 0 },
+  { "DebugInformationFormat", "debug:minimal", "line numbers",
+    "debugLineInfoOnly", 0 },
   { "Optimization", "Od", "disable optimization", "optimizeDisabled", 0 },
   { "Optimization", "O1", "min space", "optimizeMinSpace", 0 },
   { "Optimization", "O3", "full optimize", "optimizeFull", 0 },
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 0cfba63..ed32de9 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -358,6 +358,17 @@
     return true;
   }
 
+  std::string includeFile =
+    cmSystemTools::CollapseFullPath(*include, mf.GetCurrentSourceDirectory());
+  if (!cmSystemTools::FileExists(includeFile)) {
+    status.SetError(cmStrCat("could not find requested file:\n  ", *include));
+    return false;
+  }
+  if (cmSystemTools::FileIsDirectory(includeFile)) {
+    status.SetError(cmStrCat("requested file is a directory:\n  ", *include));
+    return false;
+  }
+
   const bool readit = mf.ReadDependentFile(*include);
   if (readit) {
     return true;
@@ -367,7 +378,7 @@
     return true;
   }
 
-  status.SetError(cmStrCat("could not find file:\n  ", *include));
+  status.SetError(cmStrCat("could not load requested file:\n  ", *include));
   return false;
 }
 
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 0becee2..1ca7de8 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2402,27 +2402,28 @@
       configDefines += *ccdefs;
     }
 
-    // Add precompile headers compile options.
-    std::string customAndPchOptions = options;
+    // We have pch state in the following situation:
+    // 1. We have SKIP_PRECOMPILE_HEADERS == true
+    // 2. We are creating the pre-compiled header
+    // 3. We are a different language than the linker language AND pch is
+    // enabled
     const std::string pchSource =
       this->GeneratorTarget->GetPchSource(config, lang);
-    if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
-      std::string pchOptions;
-      if (sf.GetFullPath() == pchSource) {
-        pchOptions =
-          this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
-      } else {
-        pchOptions =
-          this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
-      }
-      customAndPchOptions = cmStrCat(customAndPchOptions, ';', pchOptions);
-    }
+    const bool skipPCH =
+      pchSource.empty() || sf.GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS");
+    const bool makePCH = (sf.GetFullPath() == pchSource);
+    const bool useSharedPCH =
+      !skipPCH && (lang == this->GeneratorTarget->GetLinkerLanguage(config));
+    const bool useDifferentLangPCH =
+      !skipPCH && (lang != this->GeneratorTarget->GetLinkerLanguage(config));
+    const bool needsPCHFlags =
+      (makePCH || useSharedPCH || useDifferentLangPCH);
 
     // if we have flags or defines for this config then
     // use them
     if (!flags.empty() || !options.empty() || !configDefines.empty() ||
-        !includes.empty() || compileAs || noWinRT ||
-        !customAndPchOptions.empty()) {
+        !includes.empty() || compileAs || noWinRT || !options.empty() ||
+        needsPCHFlags) {
       cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
       cmIDEFlagTable const* flagtable = nullptr;
       const std::string& srclang = source->GetLanguage();
@@ -2455,15 +2456,35 @@
       } else {
         clOptions.Parse(flags);
       }
-      if (!customAndPchOptions.empty()) {
+
+      if (needsPCHFlags) {
+        // Add precompile headers compile options.
+        std::string expandedOptions;
+        std::string pchOptions;
+        if (makePCH) {
+          pchOptions =
+            this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
+        } else if (useSharedPCH) {
+          std::string pchHeader =
+            this->GeneratorTarget->GetPchHeader(config, lang);
+          clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
+        } else if (useDifferentLangPCH) {
+          pchOptions =
+            this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
+        }
+        this->LocalGenerator->AppendCompileOptions(expandedOptions,
+                                                   pchOptions);
+        clOptions.Parse(expandedOptions);
+      }
+
+      if (!options.empty()) {
         std::string expandedOptions;
         if (configDependentOptions) {
           this->LocalGenerator->AppendCompileOptions(
             expandedOptions,
-            genexInterpreter.Evaluate(customAndPchOptions, "COMPILE_OPTIONS"));
+            genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
         } else {
-          this->LocalGenerator->AppendCompileOptions(expandedOptions,
-                                                     customAndPchOptions);
+          this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
         }
         clOptions.Parse(expandedOptions);
       }
@@ -2786,6 +2807,13 @@
     this->GeneratorTarget->GetPchHeader(configName, linkLanguage);
   if (this->MSTools && vcxproj == this->ProjectType && pchHeader.empty()) {
     clOptions.AddFlag("PrecompiledHeader", "NotUsing");
+  } else if (this->MSTools && vcxproj == this->ProjectType &&
+             !pchHeader.empty()) {
+    clOptions.AddFlag("PrecompiledHeader", "Use");
+    clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
+    std::string pchFile =
+      this->GeneratorTarget->GetPchFile(configName, linkLanguage);
+    clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
   }
 
   // Get preprocessor definitions for this directory.
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 80a6edc..1771f0a 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1042,17 +1042,17 @@
       this->PrintPresetList(settingsFile);
       return;
     }
-    if (preset->second.Hidden) {
+    if (preset->second.Unexpanded.Hidden) {
       cmSystemTools::Error(cmStrCat("Cannot use hidden preset in ",
                                     this->GetHomeDirectory(), ": \"",
                                     presetName, '"'));
       this->PrintPresetList(settingsFile);
       return;
     }
-    auto expandedPreset = settingsFile.ExpandMacros(preset->second);
+    auto const& expandedPreset = preset->second.Expanded;
     if (!expandedPreset) {
       cmSystemTools::Error(cmStrCat("Could not evaluate preset \"",
-                                    preset->second.Name,
+                                    preset->second.Unexpanded.Name,
                                     "\": Invalid macro expansion"));
       return;
     }
@@ -1069,12 +1069,16 @@
     this->UnprocessedPresetVariables = expandedPreset->CacheVariables;
     this->UnprocessedPresetEnvironment = expandedPreset->Environment;
 
-    if (!expandedPreset->GeneratorConfig ||
-        expandedPreset->GeneratorConfig ==
-          cmCMakePresetsFile::CMakeGeneratorConfig::Default) {
+    if (!expandedPreset->ArchitectureStrategy ||
+        expandedPreset->ArchitectureStrategy ==
+          cmCMakePresetsFile::ArchToolsetStrategy::Set) {
       if (!this->GeneratorPlatformSet) {
         this->SetGeneratorPlatform(expandedPreset->Architecture);
       }
+    }
+    if (!expandedPreset->ToolsetStrategy ||
+        expandedPreset->ToolsetStrategy ==
+          cmCMakePresetsFile::ArchToolsetStrategy::Set) {
       if (!this->GeneratorToolsetSet) {
         this->SetGeneratorToolset(expandedPreset->Toolset);
       }
@@ -1464,13 +1468,12 @@
   std::vector<cmCMakePresetsFile::UnexpandedPreset> presets;
   for (auto const& p : file.PresetOrder) {
     auto const& preset = file.Presets.at(p);
-    if (!preset.Hidden &&
+    if (!preset.Unexpanded.Hidden && preset.Expanded &&
         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);
+                       return info.name == preset.Unexpanded.Generator;
+                     }) != generators.end()) {
+      presets.push_back(preset.Unexpanded);
     }
   }
 
diff --git a/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx b/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx
index 6ee55c3..a95d008 100644
--- a/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx
+++ b/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx
@@ -24,8 +24,9 @@
       /*description=*/"",
       /*generator=*/"Ninja",
       /*architecture=*/"",
+      /*setArchitecture=*/true,
       /*toolset=*/"",
-      /*setGenConfig=*/true,
+      /*setToolset=*/true,
       /*enabled=*/true,
     },
   });
@@ -48,8 +49,9 @@
       /*description=*/"",
       /*generator=*/"Ninja Multi-Config",
       /*architecture=*/"",
+      /*setArchitecture=*/true,
       /*toolset=*/"",
-      /*setGenConfig=*/true,
+      /*setToolset=*/true,
       /*enabled=*/true,
     },
   });
diff --git a/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx b/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx
index ee45d39..97dbb30 100644
--- a/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx
+++ b/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx
@@ -32,8 +32,9 @@
       /*description=*/"",
       /*generator=*/"",
       /*architecture=*/"",
+      /*setArchitecture=*/true,
       /*toolset=*/"",
-      /*setGenConfig=*/true,
+      /*setToolset=*/true,
       /*enabled=*/true,
     },
     QCMakePreset{
@@ -42,8 +43,9 @@
       /*description=*/"",
       /*generator=*/"",
       /*architecture=*/"",
+      /*setArchitecture=*/true,
       /*toolset=*/"",
-      /*setGenConfig=*/true,
+      /*setToolset=*/true,
       /*enabled=*/true,
     },
     QCMakePreset{
@@ -52,8 +54,9 @@
       /*description=*/"Long Description",
       /*generator=*/"",
       /*architecture=*/"",
+      /*setArchitecture=*/true,
       /*toolset=*/"",
-      /*setGenConfig=*/true,
+      /*setToolset=*/true,
       /*enabled=*/true,
     },
     QCMakePreset{
@@ -62,8 +65,9 @@
       /*description=*/"",
       /*generator=*/"",
       /*architecture=*/"",
+      /*setArchitecture=*/true,
       /*toolset=*/"",
-      /*setGenConfig=*/true,
+      /*setToolset=*/true,
       /*enabled=*/false,
     },
   };
diff --git a/Tests/CMakeGUI/QCMakePresetTest.cxx b/Tests/CMakeGUI/QCMakePresetTest.cxx
index 8fd07e7..2081055 100644
--- a/Tests/CMakeGUI/QCMakePresetTest.cxx
+++ b/Tests/CMakeGUI/QCMakePresetTest.cxx
@@ -16,8 +16,9 @@
     /*description=*/"description",
     /*generator=*/"generator",
     /*architecture=*/"architecture",
+    /*setArchitecture=*/true,
     /*toolset=*/"toolset",
-    /*setGenConfig=*/true,
+    /*setToolset=*/true,
     /*enabled=*/true,
   };
 }
@@ -69,12 +70,14 @@
   QTest::newRow("architecture")
     << makePreset(&QCMakePreset::architecture, "other-architecture") << false
     << true << false;
+  QTest::newRow("setArchitecture")
+    << makePreset(&QCMakePreset::setArchitecture, false) << false << false
+    << true;
   QTest::newRow("toolset") << makePreset(&QCMakePreset::toolset,
                                          "other-toolset")
                            << false << false << true;
-  QTest::newRow("setGenConfig")
-    << makePreset(&QCMakePreset::setGenConfig, false) << false << false
-    << true;
+  QTest::newRow("setToolset")
+    << makePreset(&QCMakePreset::setToolset, false) << false << false << true;
   QTest::newRow("enabled") << makePreset(&QCMakePreset::enabled, false)
                            << false << false << true;
 }
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt b/Tests/RunCMake/CMakePresets/ArchToolsetStrategyDefault-result.txt
similarity index 100%
rename from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt
rename to Tests/RunCMake/CMakePresets/ArchToolsetStrategyDefault-result.txt
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt b/Tests/RunCMake/CMakePresets/ArchToolsetStrategyDefault-stderr.txt
similarity index 100%
rename from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt
rename to Tests/RunCMake/CMakePresets/ArchToolsetStrategyDefault-stderr.txt
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/RunCMake/CMakePresets/ArchToolsetStrategyIgnore.cmake
similarity index 100%
rename from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
rename to Tests/RunCMake/CMakePresets/ArchToolsetStrategyIgnore.cmake
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt b/Tests/RunCMake/CMakePresets/ArchToolsetStrategyNone-result.txt
similarity index 100%
rename from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
rename to Tests/RunCMake/CMakePresets/ArchToolsetStrategyNone-result.txt
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt b/Tests/RunCMake/CMakePresets/ArchToolsetStrategyNone-stderr.txt
similarity index 100%
rename from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt
rename to Tests/RunCMake/CMakePresets/ArchToolsetStrategyNone-stderr.txt
diff --git a/Tests/RunCMake/CMakePresets/CMakePresets.json.in b/Tests/RunCMake/CMakePresets/CMakePresets.json.in
index 8bfc602..a8f89ff 100644
--- a/Tests/RunCMake/CMakePresets/CMakePresets.json.in
+++ b/Tests/RunCMake/CMakePresets/CMakePresets.json.in
@@ -46,6 +46,22 @@
           "type": "BOOL",
           "value": "OFF"
         },
+        "TEST_BOOL_TRUE": true,
+        "TEST_BOOL_FALSE": false,
+        "TEST_TYPED_BOOL_TRUE": {
+          "type": "STRING",
+          "value": true
+        },
+        "TEST_TYPED_BOOL_FALSE": {
+          "type": "STRING",
+          "value": false
+        },
+        "TEST_UNTYPED_BOOL_TRUE": {
+          "value": true
+        },
+        "TEST_UNTYPED_BOOL_FALSE": {
+          "value": false
+        },
         "TEST_PRESET_NAME": {
           "type": "STRING",
           "value": "x${presetName}x"
@@ -56,6 +72,7 @@
         "TEST_DOLLAR": {
           "value": "${dollar}"
         },
+        "TEST_SOURCE_DIR_NAME": "${sourceDirName}",
         "TEST_ENV_REF": "$env{TEST_ENV_REF}",
         "TEST_ENV": "$env{TEST_ENV}",
         "TEST_D_ENV_REF": "$env{TEST_D_ENV_REF}",
@@ -306,16 +323,6 @@
       "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}"
@@ -326,31 +333,6 @@
       "binaryDir": "${sourceDir}/build"
     },
     {
-      "name": "EnvCycle",
-      "generator": "@RunCMake_GENERATOR@",
-      "binaryDir": "${sourceDir}/build",
-      "environment": {
-        "ENV_1": "$env{ENV_2}",
-        "ENV_2": "$env{ENV_1}"
-      }
-    },
-    {
-      "name": "EmptyEnv",
-      "generator": "@RunCMake_GENERATOR@",
-      "binaryDir": "${sourceDir}/build",
-      "cacheVariables": {
-        "MY_VAR": "$env{}"
-      }
-    },
-    {
-      "name": "EmptyPenv",
-      "generator": "@RunCMake_GENERATOR@",
-      "binaryDir": "${sourceDir}/build",
-      "cacheVariables": {
-        "MY_VAR": "$penv{}"
-      }
-    },
-    {
       "name": "UseHiddenPreset",
       "generator": "@RunCMake_GENERATOR@",
       "binaryDir": "${sourceDir}/build",
@@ -470,28 +452,38 @@
       "binaryDir": "${sourceDir}/build"
     },
     {
-      "name": "CMakeGeneratorConfigNone",
+      "name": "ArchToolsetStrategyNone",
       "generator": "@RunCMake_GENERATOR@",
       "architecture": "a",
       "toolset": "a",
       "binaryDir": "${sourceDir}/build"
     },
     {
-      "name": "CMakeGeneratorConfigBase",
+      "name": "ArchToolsetStrategyBase",
       "generator": "@RunCMake_GENERATOR@",
-      "architecture": "a",
-      "toolset": "a",
-      "cmakeGeneratorConfig": "ignore",
+      "architecture": {
+        "value": "a",
+        "strategy": "external"
+      },
+      "toolset": {
+        "value": "a",
+        "strategy": "external"
+      },
       "binaryDir": "${sourceDir}/build"
     },
     {
-      "name": "CMakeGeneratorConfigDefault",
-      "inherits": "CMakeGeneratorConfigBase",
-      "cmakeGeneratorConfig": "default"
+      "name": "ArchToolsetStrategyDefault",
+      "inherits": "ArchToolsetStrategyBase",
+      "architecture": {
+        "strategy": "set"
+      },
+      "toolset": {
+        "strategy": "set"
+      }
     },
     {
-      "name": "CMakeGeneratorConfigIgnore",
-      "inherits": "CMakeGeneratorConfigBase"
+      "name": "ArchToolsetStrategyIgnore",
+      "inherits": "ArchToolsetStrategyBase"
     }
   ]
 }
diff --git a/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt
index 9c9c025..723ac21 100644
--- a/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/EmptyEnv-stderr.txt
@@ -1 +1,2 @@
-^CMake Error: Could not evaluate preset "EmptyEnv": Invalid macro expansion$
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/EmptyEnv: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/EmptyEnv.json.in
similarity index 62%
rename from Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
rename to Tests/RunCMake/CMakePresets/EmptyEnv.json.in
index 900c6df..ef0d575 100644
--- a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
+++ b/Tests/RunCMake/CMakePresets/EmptyEnv.json.in
@@ -2,10 +2,12 @@
   "version": 1,
   "configurePresets": [
     {
-      "name": "UnknownCMakeGeneratorConfig",
+      "name": "EmptyEnv",
       "generator": "@RunCMake_GENERATOR@",
       "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": "unknown"
+      "cacheVariables": {
+        "MY_VAR": "$env{}"
+      }
     }
   ]
 }
diff --git a/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt
index 395c7b4..880cee6 100644
--- a/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/EmptyPenv-stderr.txt
@@ -1 +1,2 @@
-^CMake Error: Could not evaluate preset "EmptyPenv": Invalid macro expansion$
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/EmptyPenv: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/EmptyPenv.json.in
similarity index 61%
copy from Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
copy to Tests/RunCMake/CMakePresets/EmptyPenv.json.in
index 900c6df..9081fe5 100644
--- a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
+++ b/Tests/RunCMake/CMakePresets/EmptyPenv.json.in
@@ -2,10 +2,12 @@
   "version": 1,
   "configurePresets": [
     {
-      "name": "UnknownCMakeGeneratorConfig",
+      "name": "EmptyPenv",
       "generator": "@RunCMake_GENERATOR@",
       "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": "unknown"
+      "cacheVariables": {
+        "MY_VAR": "$penv{}"
+      }
     }
   ]
 }
diff --git a/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt b/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt
index c8568f1..1d22b87 100644
--- a/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt
@@ -1 +1,2 @@
-^CMake Error: Could not evaluate preset "EnvCycle": Invalid macro expansion$
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/EnvCycle: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/EnvCycle.json.in b/Tests/RunCMake/CMakePresets/EnvCycle.json.in
new file mode 100644
index 0000000..25a1349
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/EnvCycle.json.in
@@ -0,0 +1,14 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "EnvCycle",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "environment": {
+        "ENV_1": "$env{ENV_2}",
+        "ENV_2": "$env{ENV_1}"
+      }
+    }
+  ]
+}
diff --git a/Tests/RunCMake/CMakePresets/Good-stdout.txt b/Tests/RunCMake/CMakePresets/Good-stdout.txt
index ce6189e..75003c7 100644
--- a/Tests/RunCMake/CMakePresets/Good-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/Good-stdout.txt
@@ -1,5 +1,7 @@
 Preset CMake variables:
 
+  TEST_BOOL_FALSE:BOOL="FALSE"
+  TEST_BOOL_TRUE:BOOL="TRUE"
   TEST_DOLLAR="\$"
   TEST_D_ENV_REF="xEnvironment variablex"
   TEST_D_ENV_REF_P=""
@@ -24,6 +26,7 @@
   TEST_PRESET_NAME:STRING="xGoodx"
   TEST_SOURCE_DIR:PATH="[^
 ]*/Tests/RunCMake/CMakePresets/Good"
+  TEST_SOURCE_DIR_NAME="Good"
   TEST_SOURCE_LIST:FILEPATH="[^
 ]*/Tests/RunCMake/CMakePresets/Good/CMakeLists\.txt"
   TEST_SOURCE_PARENT_DIR:PATH="[^
@@ -32,6 +35,10 @@
   TEST_TRAILING_DOLLAR="a \$"
   TEST_TRAILING_UNKNOWN_NAMESPACE="\$unknown{namespace"
   TEST_TRUE:BOOL="TRUE"
+  TEST_TYPED_BOOL_FALSE:STRING="FALSE"
+  TEST_TYPED_BOOL_TRUE:STRING="TRUE"
+  TEST_UNTYPED_BOOL_FALSE="FALSE"
+  TEST_UNTYPED_BOOL_TRUE="TRUE"
 
 Preset environment variables:
 
diff --git a/Tests/RunCMake/CMakePresets/Good.cmake b/Tests/RunCMake/CMakePresets/Good.cmake
index d8e3e2d..73a618d 100644
--- a/Tests/RunCMake/CMakePresets/Good.cmake
+++ b/Tests/RunCMake/CMakePresets/Good.cmake
@@ -8,9 +8,16 @@
 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_BOOL_TRUE "BOOL" "TRUE")
+test_variable(TEST_BOOL_FALSE "BOOL" "FALSE")
+test_variable(TEST_TYPED_BOOL_TRUE "STRING" "TRUE")
+test_variable(TEST_TYPED_BOOL_FALSE "STRING" "FALSE")
+test_variable(TEST_UNTYPED_BOOL_TRUE "UNINITIALIZED" "TRUE")
+test_variable(TEST_UNTYPED_BOOL_FALSE "UNINITIALIZED" "FALSE")
 test_variable(TEST_PRESET_NAME "STRING" "xGoodx")
 test_variable(TEST_GENERATOR "UNINITIALIZED" "x${CMAKE_GENERATOR}x")
 test_variable(TEST_DOLLAR "UNINITIALIZED" "$")
+test_variable(TEST_SOURCE_DIR_NAME "UNINITIALIZED" "Good")
 test_variable(TEST_ENV_REF "UNINITIALIZED" "Environment variable")
 test_variable(TEST_ENV "UNINITIALIZED" "Environment variable")
 test_variable(TEST_D_ENV_REF "UNINITIALIZED" "xEnvironment variablex")
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt b/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-result.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt
copy to Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-result.txt
diff --git a/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-stderr.txt
new file mode 100644
index 0000000..4a4d4ce
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy.json.in b/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy.json.in
new file mode 100644
index 0000000..9ec2cee
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidArchitectureStrategy.json.in
@@ -0,0 +1,13 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "InvalidArchitectureStrategy",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": {
+        "strategy": {}
+      }
+    }
+  ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt
deleted file mode 100644
index 72a20d5..0000000
--- a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-^CMake Error: Could not read presets from [^
-]*/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
deleted file mode 100644
index 1479c66..0000000
--- a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "version": 1,
-  "configurePresets": [
-    {
-      "name": "InvalidCMakeGeneratorConfig",
-      "generator": "@RunCMake_GENERATOR@",
-      "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": {}
-    }
-  ]
-}
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-result.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
copy to Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-result.txt
diff --git a/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-stderr.txt
new file mode 100644
index 0000000..fab3766
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy.json.in
similarity index 61%
copy from Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
copy to Tests/RunCMake/CMakePresets/InvalidToolsetStrategy.json.in
index 900c6df..7d2ab1f 100644
--- a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
+++ b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy.json.in
@@ -2,10 +2,12 @@
   "version": 1,
   "configurePresets": [
     {
-      "name": "UnknownCMakeGeneratorConfig",
+      "name": "InvalidToolsetStrategy",
       "generator": "@RunCMake_GENERATOR@",
       "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": "unknown"
+      "toolset": {
+        "strategy": {}
+      }
     }
   ]
 }
diff --git a/Tests/RunCMake/CMakePresets/ListPresets.json.in b/Tests/RunCMake/CMakePresets/ListPresets.json.in
index c7646c6..2ef3797 100644
--- a/Tests/RunCMake/CMakePresets/ListPresets.json.in
+++ b/Tests/RunCMake/CMakePresets/ListPresets.json.in
@@ -26,7 +26,7 @@
     {
       "name": "invalid-macro",
       "generator": "@RunCMake_GENERATOR@",
-      "binaryDir": "${noexist}"
+      "binaryDir": "$vendor{noexist}"
     },
     {
       "name": "ListPresetsHidden",
diff --git a/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt b/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt
index 08fa87b..7dafe62 100644
--- a/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt
@@ -1 +1,2 @@
-^CMake Error: Could not evaluate preset "NoSuchMacro": Invalid macro expansion$
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/NoSuchMacro: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/NoSuchMacro.json.in b/Tests/RunCMake/CMakePresets/NoSuchMacro.json.in
new file mode 100644
index 0000000..94d0b76
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoSuchMacro.json.in
@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "NoSuchMacro",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${noexist}"
+    }
+  ]
+}
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
index e0e54f4..bd84510 100644
--- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -117,10 +117,19 @@
 run_cmake_presets(ErrorNoWarningDev)
 run_cmake_presets(ErrorNoWarningDeprecated)
 set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
-run_cmake_presets(InvalidCMakeGeneratorConfig)
-run_cmake_presets(UnknownCMakeGeneratorConfig)
+run_cmake_presets(InvalidArchitectureStrategy)
+run_cmake_presets(UnknownArchitectureStrategy)
+run_cmake_presets(InvalidToolsetStrategy)
+run_cmake_presets(UnknownToolsetStrategy)
 run_cmake_presets(EmptyCacheKey)
 run_cmake_presets(EmptyEnvKey)
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
+run_cmake_presets(UnclosedMacro)
+run_cmake_presets(NoSuchMacro)
+run_cmake_presets(EnvCycle)
+run_cmake_presets(EmptyEnv)
+run_cmake_presets(EmptyPenv)
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
 
 # Test cmakeMinimumRequired field
 run_cmake_presets(MinimumRequiredInvalid)
@@ -170,13 +179,8 @@
 run_cmake_presets(GoodInheritanceMacro)
 
 # Test bad preset arguments
-run_cmake_presets(UnclosedMacro)
-run_cmake_presets(NoSuchMacro)
 run_cmake_presets(VendorMacro)
 run_cmake_presets(InvalidGenerator)
-run_cmake_presets(EnvCycle)
-run_cmake_presets(EmptyEnv)
-run_cmake_presets(EmptyPenv)
 
 # Test Visual Studio-specific stuff
 if(RunCMake_GENERATOR MATCHES "^Visual Studio ")
@@ -194,9 +198,9 @@
     run_cmake_presets(VisualStudioInheritanceMultiSecond)
   endif()
 else()
-  run_cmake_presets(CMakeGeneratorConfigNone)
-  run_cmake_presets(CMakeGeneratorConfigDefault)
-  run_cmake_presets(CMakeGeneratorConfigIgnore)
+  run_cmake_presets(ArchToolsetStrategyNone)
+  run_cmake_presets(ArchToolsetStrategyDefault)
+  run_cmake_presets(ArchToolsetStrategyIgnore)
 endif()
 
 # Test bad command line arguments
diff --git a/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt b/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt
index 248510d..f9481f0 100644
--- a/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt
@@ -1 +1,2 @@
-^CMake Error: Could not evaluate preset "UnclosedMacro": Invalid macro expansion$
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/UnclosedMacro: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/UnclosedMacro.json.in b/Tests/RunCMake/CMakePresets/UnclosedMacro.json.in
new file mode 100644
index 0000000..ad6cf7d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnclosedMacro.json.in
@@ -0,0 +1,10 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "UnclosedMacro",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir"
+    }
+  ]
+}
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt b/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-result.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt
copy to Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-result.txt
diff --git a/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-stderr.txt
new file mode 100644
index 0000000..cf17881
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy.json.in b/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy.json.in
new file mode 100644
index 0000000..a3bf7c8
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnknownArchitectureStrategy.json.in
@@ -0,0 +1,13 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "UnknownArchitectureStrategy",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "architecture": {
+        "strategy": "unknown"
+      }
+    }
+  ]
+}
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-result.txt b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-stderr.txt b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-stderr.txt
deleted file mode 100644
index b1759b0..0000000
--- a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-stderr.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-^CMake Error: Could not read presets from [^
-]*/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt b/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-result.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
copy to Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-result.txt
diff --git a/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-stderr.txt b/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-stderr.txt
new file mode 100644
index 0000000..8f9be29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy.json.in b/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy.json.in
new file mode 100644
index 0000000..1668700
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnknownToolsetStrategy.json.in
@@ -0,0 +1,13 @@
+{
+  "version": 1,
+  "configurePresets": [
+    {
+      "name": "UnknownToolsetStrategy",
+      "generator": "@RunCMake_GENERATOR@",
+      "binaryDir": "${sourceDir}/build",
+      "toolset": {
+        "strategy": "unknown"
+      }
+    }
+  ]
+}
diff --git a/Tests/RunCMake/include/ExportExportInclude-stderr.txt b/Tests/RunCMake/include/ExportExportInclude-stderr.txt
index 70d013c..6d5c02f 100644
--- a/Tests/RunCMake/include/ExportExportInclude-stderr.txt
+++ b/Tests/RunCMake/include/ExportExportInclude-stderr.txt
@@ -1,5 +1,5 @@
 CMake Error at ExportExportInclude.cmake:6 \(include\):
-  include could not find load file:
+  include could not find requested file:
 
     .*/Tests/RunCMake/include/ExportExportInclude-build/theTargets.cmake
 Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt b/Tests/RunCMake/include/IncludeIsDirectory-result.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
copy to Tests/RunCMake/include/IncludeIsDirectory-result.txt
diff --git a/Tests/RunCMake/include/IncludeIsDirectory-stderr.txt b/Tests/RunCMake/include/IncludeIsDirectory-stderr.txt
new file mode 100644
index 0000000..5735c29
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeIsDirectory-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at IncludeIsDirectory.cmake:1 \(include\):
+  include requested file is a directory:
+
+    .*/Tests/RunCMake/include/IncludeIsDirectory-build
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/include/IncludeIsDirectory.cmake b/Tests/RunCMake/include/IncludeIsDirectory.cmake
new file mode 100644
index 0000000..74189e3
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeIsDirectory.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_BINARY_DIR}")
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt b/Tests/RunCMake/include/IncludeMalformed-result.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
copy to Tests/RunCMake/include/IncludeMalformed-result.txt
diff --git a/Tests/RunCMake/include/IncludeMalformed-stderr.txt b/Tests/RunCMake/include/IncludeMalformed-stderr.txt
new file mode 100644
index 0000000..fc75549
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeMalformed-stderr.txt
@@ -0,0 +1,13 @@
+CMake Error at malformedInclude.cmake:1:
+  Parse error.  Function missing ending "\)".  End of file reached.
+Call Stack \(most recent call first\):
+  IncludeMalformed.cmake:1 \(include\)
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at IncludeMalformed.cmake:1 \(include\):
+  include could not load requested file:
+
+    malformedInclude.cmake
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/include/IncludeMalformed.cmake b/Tests/RunCMake/include/IncludeMalformed.cmake
new file mode 100644
index 0000000..9560142
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeMalformed.cmake
@@ -0,0 +1 @@
+include("malformedInclude.cmake")
diff --git a/Tests/RunCMake/include/RunCMakeTest.cmake b/Tests/RunCMake/include/RunCMakeTest.cmake
index bea7d5c..8fb7201 100644
--- a/Tests/RunCMake/include/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include/RunCMakeTest.cmake
@@ -5,3 +5,5 @@
 run_cmake(CMP0024-WARN)
 run_cmake(CMP0024-NEW)
 run_cmake(ExportExportInclude)
+run_cmake(IncludeIsDirectory)
+run_cmake(IncludeMalformed)
diff --git a/Tests/RunCMake/include/malformedInclude.cmake b/Tests/RunCMake/include/malformedInclude.cmake
new file mode 100644
index 0000000..3cec3ad
--- /dev/null
+++ b/Tests/RunCMake/include/malformedInclude.cmake
@@ -0,0 +1 @@
+if(