Merge topic 'vs-fortran-debugging-flags'

8ad6fabfc5 VS: Remove flag table entries for Fortran /Z* flags

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5406
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index eda96ae..1a94a3d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -52,7 +52,7 @@
         - .cmake_doc_artifacts
         - .run_only_for_package
 
-.upload:source-package:
+upload:source-package:
     extends:
         - .rsync_upload
         - .run_only_for_package
@@ -175,7 +175,7 @@
     needs:
         - prep:doc-package
 
-.upload:linux-x86_64-package:
+upload:linux-x86_64-package:
     extends:
         - .rsync_upload
         - .run_only_for_package
@@ -250,7 +250,7 @@
     needs:
         - prep:doc-package
 
-.upload:macos-package:
+upload:macos-package:
     extends:
         - .rsync_upload
         - .run_only_for_package
diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake
index 2340543..90556bf 100644
--- a/.gitlab/ci/configure_debian10_ninja.cmake
+++ b/.gitlab/ci/configure_debian10_ninja.cmake
@@ -19,6 +19,7 @@
 set(CMake_TEST_FindGTest "ON" CACHE BOOL "")
 set(CMake_TEST_FindGTK2 "ON" CACHE BOOL "")
 set(CMake_TEST_FindIconv "ON" CACHE BOOL "")
+set(CMake_TEST_FindIntl "ON" CACHE BOOL "")
 set(CMake_TEST_FindJPEG "ON" CACHE BOOL "")
 set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "")
 set(CMake_TEST_FindLAPACK "ON" CACHE BOOL "")
diff --git a/.gitlab/ci/configure_fedora31_makefiles.cmake b/.gitlab/ci/configure_fedora31_makefiles.cmake
index 8d2454f..db2d005 100644
--- a/.gitlab/ci/configure_fedora31_makefiles.cmake
+++ b/.gitlab/ci/configure_fedora31_makefiles.cmake
@@ -19,6 +19,7 @@
 set(CMake_TEST_FindGTest "ON" CACHE BOOL "")
 set(CMake_TEST_FindGTK2 "ON" CACHE BOOL "")
 set(CMake_TEST_FindIconv "ON" CACHE BOOL "")
+set(CMake_TEST_FindIntl "ON" CACHE BOOL "")
 set(CMake_TEST_FindJPEG "ON" CACHE BOOL "")
 set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "")
 set(CMake_TEST_FindLAPACK "ON" CACHE BOOL "")
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 9438676..315552b 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -52,7 +52,7 @@
     image: "kitware/cmake:ci-fedora31-x86_64-2020-10-20"
 
     variables:
-        GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
+        GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes"
 
 #### Lint builds
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2d860d4..a2fcf2e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 # file Copyright.txt or https://cmake.org/licensing for details.
 
-cmake_minimum_required(VERSION 3.1...3.15 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.1...3.18 FATAL_ERROR)
 set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideC.cmake)
 set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideCXX.cmake)
 project(CMake)
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index 231f9da..a28b0b1 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -239,6 +239,11 @@
   command itself.
   Using ``DEPFILE`` with other generators than Ninja is an error.
 
+  If the ``DEPFILE`` argument is relative, it should be relative to
+  :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the
+  ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`
+  (see policy :policy:`CMP0116`.)
+
 Build Events
 ^^^^^^^^^^^^
 
diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst
index 75d685c..664b7a4 100644
--- a/Help/dev/maint.rst
+++ b/Help/dev/maint.rst
@@ -357,3 +357,13 @@
   The files generatd by `install(EXPORT)` and `export()` commands
   are known to work with policies as of CMake $prev, so enable them
   in sufficiently new CMake versions.
+
+Update the ``cmake_minimum_required`` version range in CMake itself:
+
+* ``CMakeLists.txt``
+* ``Utilities/Doxygen/CMakeLists.txt``
+* ``Utilities/Sphinx/CMakeLists.txt``
+
+to end in the previous release.  Commit with a message such as::
+
+  Configure CMake itself with policies through CMake $prev
diff --git a/Help/guide/ide-integration/index.rst b/Help/guide/ide-integration/index.rst
index 8ea31a0..addf932 100644
--- a/Help/guide/ide-integration/index.rst
+++ b/Help/guide/ide-integration/index.rst
@@ -82,8 +82,8 @@
 artifacts. Such information can be obtained by using the
 :manual:`File API <cmake-file-api(7)>`. The manual page for the File API
 contains more information about the API and how to invoke it.
-:manual:`Server mode <cmake-server(7)>` is deprecated and should not be
-used on CMake 3.14 or later.
+:manual:`Server mode <cmake-server(7)>` was removed as of CMake 3.20 and
+should not be used on CMake 3.14 or later.
 
 IDEs should avoid creating more build trees than necessary, and only create
 multiple build trees if the user wishes to switch to a different compiler,
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index fa10f66..0116674 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,15 @@
 to determine whether to report an error on use of deprecated macros or
 functions.
 
+Policies Introduced by CMake 3.20
+=================================
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0116: Ninja generators transform DEPFILEs from add_custom_command(). </policy/CMP0116>
+   CMP0115: Source file extensions must be explicit. </policy/CMP0115>
+
 Policies Introduced by CMake 3.19
 =================================
 
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/cmake-server.7.rst b/Help/manual/cmake-server.7.rst
index 8f10b9f..6c8d0f4 100644
--- a/Help/manual/cmake-server.7.rst
+++ b/Help/manual/cmake-server.7.rst
@@ -3,742 +3,5 @@
 cmake-server(7)
 ***************
 
-.. only:: html
-
-   .. contents::
-
-.. deprecated:: 3.15
-
-  This will be removed from a future version of CMake.
-  Clients should use the :manual:`cmake-file-api(7)` instead.
-
-Introduction
-============
-
-:manual:`cmake(1)` is capable of providing semantic information about
-CMake code it executes to generate a buildsystem.  If executed with
-the ``-E server`` command line options, it starts in a long running mode
-and allows a client to request the available information via a JSON protocol.
-
-The protocol is designed to be useful to IDEs, refactoring tools, and
-other tools which have a need to understand the buildsystem in entirety.
-
-A single :manual:`cmake-buildsystem(7)` may describe buildsystem contents
-and build properties which differ based on
-:manual:`generation-time context <cmake-generator-expressions(7)>`
-including:
-
-* The Platform (eg, Windows, APPLE, Linux).
-* The build configuration (eg, Debug, Release, Coverage).
-* The Compiler (eg, MSVC, GCC, Clang) and compiler version.
-* The language of the source files compiled.
-* Available compile features (eg CXX variadic templates).
-* CMake policies.
-
-The protocol aims to provide information to tooling to satisfy several
-needs:
-
-#. Provide a complete and easily parsed source of all information relevant
-   to the tooling as it relates to the source code.  There should be no need
-   for tooling to parse generated buildsystems to access include directories
-   or compile definitions for example.
-#. Semantic information about the CMake buildsystem itself.
-#. Provide a stable interface for reading the information in the CMake cache.
-#. Information for determining when cmake needs to be re-run as a result of
-   file changes.
-
-
-Operation
-=========
-
-Start :manual:`cmake(1)` in the server command mode, supplying the path to
-the build directory to process::
-
-  cmake -E server (--debug|--pipe=<NAMED_PIPE>)
-
-The server will communicate using stdin/stdout (with the ``--debug`` parameter)
-or using a named pipe (with the ``--pipe=<NAMED_PIPE>`` parameter).  Note
-that "named pipe" refers to a local domain socket on Unix and to a named pipe
-on Windows.
-
-When connecting to the server (via named pipe or by starting it in ``--debug``
-mode), the server will reply with a hello message::
-
-  [== "CMake Server" ==[
-  {"supportedProtocolVersions":[{"major":1,"minor":0}],"type":"hello"}
-  ]== "CMake Server" ==]
-
-Messages sent to and from the process are wrapped in magic strings::
-
-  [== "CMake Server" ==[
-  {
-    ... some JSON message ...
-  }
-  ]== "CMake Server" ==]
-
-The server is now ready to accept further requests via the named pipe
-or stdin.
-
-
-Debugging
-=========
-
-CMake server mode can be asked to provide statistics on execution times, etc.
-or to dump a copy of the response into a file. This is done passing a "debug"
-JSON object as a child of the request.
-
-The debug object supports the "showStats" key, which takes a boolean and makes
-the server mode return a "zzzDebug" object with stats as part of its response.
-"dumpToFile" takes a string value and will cause the cmake server to copy
-the response into the given filename.
-
-This is a response from the cmake server with "showStats" set to true::
-
-  [== "CMake Server" ==[
-  {
-    "cookie":"",
-    "errorMessage":"Waiting for type \"handshake\".",
-    "inReplyTo":"unknown",
-   "type":"error",
-    "zzzDebug": {
-      "dumpFile":"/tmp/error.txt",
-      "jsonSerialization":0.011016,
-      "size":111,
-      "totalTime":0.025995
-    }
-  }
-  ]== "CMake Server" ==]
-
-The server has made a copy of this response into the file /tmp/error.txt and
-took 0.011 seconds to turn the JSON response into a string, and it took 0.025
-seconds to process the request in total. The reply has a size of 111 bytes.
-
-
-Protocol API
-============
-
-
-General Message Layout
-----------------------
-
-All messages need to have a "type" value, which identifies the type of
-message that is passed back or forth. E.g. the initial message sent by the
-server is of type "hello". Messages without a type will generate an response
-of type "error".
-
-All requests sent to the server may contain a "cookie" value. This value
-will he handed back unchanged in all responses triggered by the request.
-
-All responses will contain a value "inReplyTo", which may be empty in
-case of parse errors, but will contain the type of the request message
-in all other cases.
-
-
-Type "reply"
-^^^^^^^^^^^^
-
-This type is used by the server to reply to requests.
-
-The message may -- depending on the type of the original request --
-contain values.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"cookie":"zimtstern","inReplyTo":"handshake","type":"reply"}
-  ]== "CMake Server" ==]
-
-
-Type "error"
-^^^^^^^^^^^^
-
-This type is used to return an error condition to the client. It will
-contain an "errorMessage".
-
-Example::
-
-  [== "CMake Server" ==[
-  {"cookie":"","errorMessage":"Protocol version not supported.","inReplyTo":"handshake","type":"error"}
-  ]== "CMake Server" ==]
-
-
-Type "progress"
-^^^^^^^^^^^^^^^
-
-When the server is busy for a long time, it is polite to send back replies of
-type "progress" to the client. These will contain a "progressMessage" with a
-string describing the action currently taking place as well as
-"progressMinimum", "progressMaximum" and "progressCurrent" with integer values
-describing the range of progress.
-
-Messages of type "progress" will be followed by more "progress" messages or with
-a message of type "reply" or "error" that complete the request.
-
-"progress" messages may not be emitted after the "reply" or "error" message for
-the request that triggered the responses was delivered.
-
-
-Type "message"
-^^^^^^^^^^^^^^
-
-A message is triggered when the server processes a request and produces some
-form of output that should be displayed to the user. A Message has a "message"
-with the actual text to display as well as a "title" with a suggested dialog
-box title.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"cookie":"","message":"Something happened.","title":"Title Text","inReplyTo":"handshake","type":"message"}
-  ]== "CMake Server" ==]
-
-
-Type "signal"
-^^^^^^^^^^^^^
-
-The server can send signals when it detects changes in the system state. Signals
-are of type "signal", have an empty "cookie" and "inReplyTo" field and always
-have a "name" set to show which signal was sent.
-
-
-Specific Signals
-----------------
-
-The cmake server may sent signals with the following names:
-
-"dirty" Signal
-^^^^^^^^^^^^^^
-
-The "dirty" signal is sent whenever the server determines that the configuration
-of the project is no longer up-to-date. This happens when any of the files that have
-an influence on the build system is changed.
-
-The "dirty" signal may look like this::
-
-  [== "CMake Server" ==[
-  {
-    "cookie":"",
-    "inReplyTo":"",
-    "name":"dirty",
-    "type":"signal"}
-  ]== "CMake Server" ==]
-
-
-"fileChange" Signal
-^^^^^^^^^^^^^^^^^^^
-
-The "fileChange" signal is sent whenever a watched file is changed. It contains
-the "path" that has changed and a list of "properties" with the kind of change
-that was detected. Possible changes are "change" and "rename".
-
-The "fileChange" signal looks like this::
-
-  [== "CMake Server" ==[
-  {
-    "cookie":"",
-    "inReplyTo":"",
-    "name":"fileChange",
-    "path":"/absolute/CMakeLists.txt",
-    "properties":["change"],
-    "type":"signal"}
-  ]== "CMake Server" ==]
-
-
-Specific Message Types
-----------------------
-
-
-Type "hello"
-^^^^^^^^^^^^
-
-The initial message send by the cmake server on startup is of type "hello".
-This is the only message ever sent by the server that is not of type "reply",
-"progress" or "error".
-
-It will contain "supportedProtocolVersions" with an array of server protocol
-versions supported by the cmake server. These are JSON objects with "major" and
-"minor" keys containing non-negative integer values. Some versions may be marked
-as experimental. These will contain the "isExperimental" key set to true. Enabling
-these requires a special command line argument when starting the cmake server mode.
-
-Within a "major" version all "minor" versions are fully backwards compatible.
-New "minor" versions may introduce functionality in such a way that existing
-clients of the same "major" version will continue to work, provided they
-ignore keys in the output that they do not know about.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"supportedProtocolVersions":[{"major":0,"minor":1}],"type":"hello"}
-  ]== "CMake Server" ==]
-
-
-Type "handshake"
-^^^^^^^^^^^^^^^^
-
-The first request that the client may send to the server is of type "handshake".
-
-This request needs to pass one of the "supportedProtocolVersions" of the "hello"
-type response received earlier back to the server in the "protocolVersion" field.
-Giving the "major" version of the requested protocol version will make the server
-use the latest minor version of that protocol. Use this if you do not explicitly
-need to depend on a specific minor version.
-
-Protocol version 1.0 requires the following attributes to be set:
-
-  * "sourceDirectory" with a path to the sources
-  * "buildDirectory" with a path to the build directory
-  * "generator" with the generator name
-  * "extraGenerator" (optional!) with the extra generator to be used
-  * "platform" with the generator platform (if supported by the generator)
-  * "toolset" with the generator toolset (if supported by the generator)
-
-Protocol version 1.2 makes all but the build directory optional, provided
-there is a valid cache in the build directory that contains all the other
-information already.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"cookie":"zimtstern","type":"handshake","protocolVersion":{"major":0},
-   "sourceDirectory":"/home/code/cmake", "buildDirectory":"/tmp/testbuild",
-   "generator":"Ninja"}
-  ]== "CMake Server" ==]
-
-which will result in a response type "reply"::
-
-  [== "CMake Server" ==[
-  {"cookie":"zimtstern","inReplyTo":"handshake","type":"reply"}
-  ]== "CMake Server" ==]
-
-indicating that the server is ready for action.
-
-
-Type "globalSettings"
-^^^^^^^^^^^^^^^^^^^^^
-
-This request can be sent after the initial handshake. It will return a
-JSON structure with information on cmake state.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"globalSettings"}
-  ]== "CMake Server" ==]
-
-which will result in a response type "reply"::
-
-  [== "CMake Server" ==[
-  {
-    "buildDirectory": "/tmp/test-build",
-    "capabilities": {
-      "generators": [
-        {
-          "extraGenerators": [],
-          "name": "Watcom WMake",
-          "platformSupport": false,
-          "toolsetSupport": false
-        },
-        <...>
-      ],
-      "serverMode": false,
-      "version": {
-        "isDirty": false,
-        "major": 3,
-        "minor": 6,
-        "patch": 20160830,
-        "string": "3.6.20160830-gd6abad",
-        "suffix": "gd6abad"
-      }
-    },
-    "checkSystemVars": false,
-    "cookie": "",
-    "extraGenerator": "",
-    "generator": "Ninja",
-    "debugOutput": false,
-    "inReplyTo": "globalSettings",
-    "sourceDirectory": "/home/code/cmake",
-    "trace": false,
-    "traceExpand": false,
-    "type": "reply",
-    "warnUninitialized": false,
-    "warnUnused": false,
-    "warnUnusedCli": true
-  }
-  ]== "CMake Server" ==]
-
-
-Type "setGlobalSettings"
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-This request can be sent to change the global settings attributes. Unknown
-attributes are going to be ignored. Read-only attributes reported by
-"globalSettings" are all capabilities, buildDirectory, generator,
-extraGenerator and sourceDirectory. Any attempt to set these will be ignored,
-too.
-
-All other settings will be changed.
-
-The server will respond with an empty reply message or an error.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"setGlobalSettings","debugOutput":true}
-  ]== "CMake Server" ==]
-
-CMake will reply to this with::
-
-  [== "CMake Server" ==[
-  {"inReplyTo":"setGlobalSettings","type":"reply"}
-  ]== "CMake Server" ==]
-
-
-Type "configure"
-^^^^^^^^^^^^^^^^
-
-This request will configure a project for build.
-
-To configure a build directory already containing cmake files, it is enough to
-set "buildDirectory" via "setGlobalSettings". To create a fresh build directory
-you also need to set "currentGenerator" and "sourceDirectory" via "setGlobalSettings"
-in addition to "buildDirectory".
-
-You may a list of strings to "configure" via the "cacheArguments" key. These
-strings will be interpreted similar to command line arguments related to
-cache handling that are passed to the cmake command line client.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"configure", "cacheArguments":["-Dsomething=else"]}
-  ]== "CMake Server" ==]
-
-CMake will reply like this (after reporting progress for some time)::
-
-  [== "CMake Server" ==[
-  {"cookie":"","inReplyTo":"configure","type":"reply"}
-  ]== "CMake Server" ==]
-
-
-Type "compute"
-^^^^^^^^^^^^^^
-
-This request will generate build system files in the build directory and
-is only available after a project was successfully "configure"d.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"compute"}
-  ]== "CMake Server" ==]
-
-CMake will reply (after reporting progress information)::
-
-  [== "CMake Server" ==[
-  {"cookie":"","inReplyTo":"compute","type":"reply"}
-  ]== "CMake Server" ==]
-
-
-Type "codemodel"
-^^^^^^^^^^^^^^^^
-
-The "codemodel" request can be used after a project was "compute"d successfully.
-
-It will list the complete project structure as it is known to cmake.
-
-The reply will contain a key "configurations", which will contain a list of
-configuration objects. Configuration objects are used to destinquish between
-different configurations the build directory might have enabled. While most
-generators only support one configuration, others might support several.
-
-Each configuration object can have the following keys:
-
-"name"
-  contains the name of the configuration. The name may be empty.
-"projects"
-  contains a list of project objects, one for each build project.
-
-Project objects define one (sub-)project defined in the cmake build system.
-
-Each project object can have the following keys:
-
-"name"
-  contains the (sub-)projects name.
-"minimumCMakeVersion"
-  contains the minimum cmake version allowed for this project, null if the
-  project doesn't specify one.
-"hasInstallRule"
-  true if the project contains any install rules, false otherwise.
-"sourceDirectory"
-  contains the current source directory
-"buildDirectory"
-  contains the current build directory.
-"targets"
-  contains a list of build system target objects.
-
-Target objects define individual build targets for a certain configuration.
-
-Each target object can have the following keys:
-
-"name"
-  contains the name of the target.
-"type"
-  defines the type of build of the target. Possible values are
-  "STATIC_LIBRARY", "MODULE_LIBRARY", "SHARED_LIBRARY", "OBJECT_LIBRARY",
-  "EXECUTABLE", "UTILITY" and "INTERFACE_LIBRARY".
-"fullName"
-  contains the full name of the build result (incl. extensions, etc.).
-"sourceDirectory"
-  contains the current source directory.
-"buildDirectory"
-  contains the current build directory.
-"isGeneratorProvided"
-  true if the target is auto-created by a generator, false otherwise
-"hasInstallRule"
-  true if the target contains any install rules, false otherwise.
-"installPaths"
-  full path to the destination directories defined by target install rules.
-"artifacts"
-  with a list of build artifacts. The list is sorted with the most
-  important artifacts first (e.g. a .DLL file is listed before a
-  .PDB file on windows).
-"linkerLanguage"
-  contains the language of the linker used to produce the artifact.
-"linkLibraries"
-  with a list of libraries to link to. This value is encoded in the
-  system's native shell format.
-"linkFlags"
-  with a list of flags to pass to the linker. This value is encoded in
-  the system's native shell format.
-"linkLanguageFlags"
-  with the flags for a compiler using the linkerLanguage. This value is
-  encoded in the system's native shell format.
-"frameworkPath"
-  with the framework path (on Apple computers). This value is encoded
-  in the system's native shell format.
-"linkPath"
-  with the link path. This value is encoded in the system's native shell
-  format.
-"sysroot"
-  with the sysroot path.
-"fileGroups"
-  contains the source files making up the target.
-
-FileGroups are used to group sources using similar settings together.
-
-Each fileGroup object may contain the following keys:
-
-"language"
-  contains the programming language used by all files in the group.
-"compileFlags"
-  with a string containing all the flags passed to the compiler
-  when building any of the files in this group. This value is encoded in
-  the system's native shell format.
-"includePath"
-  with a list of include paths. Each include path is an object
-  containing a "path" with the actual include path and "isSystem" with a bool
-  value informing whether this is a normal include or a system include. This
-  value is encoded in the system's native shell format.
-"defines"
-  with a list of defines in the form "SOMEVALUE" or "SOMEVALUE=42". This
-  value is encoded in the system's native shell format.
-"sources"
-  with a list of source files.
-
-All file paths in the fileGroup are either absolute or relative to the
-sourceDirectory of the target.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"codemodel"}
-  ]== "CMake Server" ==]
-
-CMake will reply::
-
-  [== "CMake Server" ==[
-  {
-    "configurations": [
-      {
-        "name": "",
-        "projects": [
-          {
-            "buildDirectory": "/tmp/build/Source/CursesDialog/form",
-            "name": "CMAKE_FORM",
-            "sourceDirectory": "/home/code/src/cmake/Source/CursesDialog/form",
-            "targets": [
-              {
-                "artifacts": [ "/tmp/build/Source/CursesDialog/form/libcmForm.a" ],
-                "buildDirectory": "/tmp/build/Source/CursesDialog/form",
-                "fileGroups": [
-                  {
-                    "compileFlags": "  -std=gnu11",
-                    "defines": [ "CURL_STATICLIB", "LIBARCHIVE_STATIC" ],
-                    "includePath": [ { "path": "/tmp/build/Utilities" }, <...> ],
-                    "isGenerated": false,
-                    "language": "C",
-                    "sources": [ "fld_arg.c", <...> ]
-                  }
-                ],
-                "fullName": "libcmForm.a",
-                "linkerLanguage": "C",
-                "name": "cmForm",
-                "sourceDirectory": "/home/code/src/cmake/Source/CursesDialog/form",
-                "type": "STATIC_LIBRARY"
-              }
-            ]
-          },
-          <...>
-        ]
-      }
-    ],
-    "cookie": "",
-    "inReplyTo": "codemodel",
-    "type": "reply"
-  }
-  ]== "CMake Server" ==]
-
-
-Type "ctestInfo"
-^^^^^^^^^^^^^^^^
-
-The "ctestInfo" request can be used after a project was "compute"d successfully.
-
-It will list the complete project test structure as it is known to cmake.
-
-The reply will contain a key "configurations", which will contain a list of
-configuration objects. Configuration objects are used to destinquish between
-different configurations the build directory might have enabled. While most
-generators only support one configuration, others might support several.
-
-Each configuration object can have the following keys:
-
-"name"
-  contains the name of the configuration. The name may be empty.
-"projects"
-  contains a list of project objects, one for each build project.
-
-Project objects define one (sub-)project defined in the cmake build system.
-
-Each project object can have the following keys:
-
-"name"
-  contains the (sub-)projects name.
-"ctestInfo"
-  contains a list of test objects.
-
-Each test object can have the following keys:
-
-"ctestName"
-  contains the name of the test.
-"ctestCommand"
-  contains the test command.
-"properties"
-  contains a list of test property objects.
-
-Each test property object can have the following keys:
-
-"key"
-  contains the test property key.
-"value"
-  contains the test property value.
-
-
-Type "cmakeInputs"
-^^^^^^^^^^^^^^^^^^
-
-The "cmakeInputs" requests will report files used by CMake as part
-of the build system itself.
-
-This request is only available after a project was successfully
-"configure"d.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"cmakeInputs"}
-  ]== "CMake Server" ==]
-
-CMake will reply with the following information::
-
-  [== "CMake Server" ==[
-  {"buildFiles":
-    [
-      {"isCMake":true,"isTemporary":false,"sources":["/usr/lib/cmake/...", ... ]},
-      {"isCMake":false,"isTemporary":false,"sources":["CMakeLists.txt", ...]},
-      {"isCMake":false,"isTemporary":true,"sources":["/tmp/build/CMakeFiles/...", ...]}
-    ],
-    "cmakeRootDirectory":"/usr/lib/cmake",
-    "sourceDirectory":"/home/code/src/cmake",
-    "cookie":"",
-    "inReplyTo":"cmakeInputs",
-    "type":"reply"
-  }
-  ]== "CMake Server" ==]
-
-All file names are either relative to the top level source directory or
-absolute.
-
-The list of files which "isCMake" set to true are part of the cmake installation.
-
-The list of files witch "isTemporary" set to true are part of the build directory
-and will not survive the build directory getting cleaned out.
-
-
-Type "cache"
-^^^^^^^^^^^^
-
-The "cache" request will list the cached configuration values.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"cache"}
-  ]== "CMake Server" ==]
-
-CMake will respond with the following output::
-
-  [== "CMake Server" ==[
-  {
-    "cookie":"","inReplyTo":"cache","type":"reply",
-    "cache":
-    [
-      {
-        "key":"SOMEVALUE",
-        "properties":
-        {
-          "ADVANCED":"1",
-          "HELPSTRING":"This is not helpful"
-        }
-        "type":"STRING",
-        "value":"TEST"}
-    ]
-  }
-  ]== "CMake Server" ==]
-
-The output can be limited to a list of keys by passing an array of key names
-to the "keys" optional field of the "cache" request.
-
-
-Type "fileSystemWatchers"
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The server can watch the filesystem for changes. The "fileSystemWatchers"
-command will report on the files and directories watched.
-
-Example::
-
-  [== "CMake Server" ==[
-  {"type":"fileSystemWatchers"}
-  ]== "CMake Server" ==]
-
-CMake will respond with the following output::
-
-  [== "CMake Server" ==[
-  {
-    "cookie":"","inReplyTo":"fileSystemWatchers","type":"reply",
-    "watchedFiles": [ "/absolute/path" ],
-    "watchedDirectories": [ "/absolute" ]
-  }
-  ]== "CMake Server" ==]
+The :manual:`cmake(1)` server mode has been removed since CMake 3.20.
+Clients should use the :manual:`cmake-file-api(7)` instead.
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 5452c79..b581e48 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -582,6 +582,7 @@
 
   ``serverMode``
     ``true`` if cmake supports server-mode and ``false`` otherwise.
+    Always false since CMake 3.20.
 
 ``cat <files>...``
   Concatenate files and print on the standard output.
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/Help/policy/CMP0115.rst b/Help/policy/CMP0115.rst
new file mode 100644
index 0000000..7f82c43
--- /dev/null
+++ b/Help/policy/CMP0115.rst
@@ -0,0 +1,34 @@
+CMP0115
+-------
+
+.. versionadded:: 3.20
+
+Source file extensions must be explicit.
+
+In CMake 3.19 and below, if a source file could not be found by the name
+specified, it would append a list of known extensions to the name to see if
+the file with the extension could be found. For example, this would allow the
+user to run:
+
+.. code-block:: cmake
+
+  add_executable(exe main)
+
+and put ``main.c`` in the executable without specifying the extension.
+
+Starting in CMake 3.20, CMake prefers all source files to have their extensions
+explicitly listed:
+
+.. code-block:: cmake
+
+  add_executable(exe main.c)
+
+The ``OLD`` behavior for this policy is to implicitly append known extensions
+to source files if they can't be found. The ``NEW`` behavior of this policy is
+to not append known extensions and require them to be explicit.
+
+This policy was introduced in CMake version 3.20.  CMake version |release|
+warns when the policy is not set and uses ``OLD`` behavior. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0116.rst b/Help/policy/CMP0116.rst
new file mode 100644
index 0000000..25a14c4
--- /dev/null
+++ b/Help/policy/CMP0116.rst
@@ -0,0 +1,38 @@
+CMP0116
+-------
+
+.. versionadded:: 3.20
+
+Ninja generators transform ``DEPFILE`` s from :command:`add_custom_command`.
+
+In CMake 3.19 and below, files given to the ``DEPFILE`` argument of
+:command:`add_custom_command` were passed directly to Ninja's ``depfile``
+variable without any path resolution. This meant that if
+:command:`add_custom_command` was called from a subdirectory (created by
+:command:`add_subdirectory`), the ``DEPFILE`` argument would have to be either
+an absolute path or a path relative to :variable:`CMAKE_BINARY_DIR`, rather
+than :variable:`CMAKE_CURRENT_BINARY_DIR`. In addition, no transformation was
+done on the file listed in ``DEPFILE``, which meant that the paths within the
+``DEPFILE`` had the same restrictions.
+
+Starting with CMake 3.20, the ``DEPFILE`` argument is relative to
+:variable:`CMAKE_CURRENT_BINARY_DIR` (unless it is absolute), and the paths in
+the ``DEPFILE`` are also relative to :variable:`CMAKE_CURRENT_BINARY_DIR`.
+CMake automatically transforms the paths in the ``DEPFILE`` (unless they are
+absolute) after the custom command is run. The file listed in ``DEPFILE`` is
+not modified in any way. Instead, CMake writes the transformation to its own
+internal file, and passes this internal file to Ninja's ``depfile`` variable.
+This transformation happens regardless of whether or not ``DEPFILE`` is
+relative, and regardless of whether or not :command:`add_custom_command` is
+called from a subdirectory.
+
+The ``OLD`` behavior for this policy is to pass the ``DEPFILE`` to Ninja
+unaltered. The ``NEW`` behavior for this policy is to transform the ``DEPFILE``
+after running the custom command.
+
+This policy was introduced in CMake version 3.20.  Unlike most policies,
+CMake version |release| does *not* warn by default when this policy is not set
+(unless ``DEPFILE`` is used in a subdirectory) and simply uses ``OLD``
+behavior.  See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0116 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+  Developers should add similar notes for each topic branch
+  making a noteworthy change.  Each document should be named
+  and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/FindIntl-imported-target.rst b/Help/release/dev/FindIntl-imported-target.rst
new file mode 100644
index 0000000..5770f21
--- /dev/null
+++ b/Help/release/dev/FindIntl-imported-target.rst
@@ -0,0 +1,4 @@
+FindIntl-imported-target
+------------------------
+
+* The :module:`FindIntl` module now provides an imported target.
diff --git a/Help/release/dev/cpack-nsis-utf-8-bom.rst b/Help/release/dev/cpack-nsis-utf-8-bom.rst
new file mode 100644
index 0000000..b2a20ce
--- /dev/null
+++ b/Help/release/dev/cpack-nsis-utf-8-bom.rst
@@ -0,0 +1,6 @@
+cpack-nsis-utf8-bom
+-------------------
+
+* The :cpack_gen:`CPack NSIS Generator` now handles correctly Unicode characters.
+  If you want to have a ``CPACK_RESOURCE_FILE_LICENSE`` with UTF-8 characters
+  it needs to be encoded in UTF-8 BOM.
diff --git a/Help/release/dev/explicit-source-extensions.rst b/Help/release/dev/explicit-source-extensions.rst
new file mode 100644
index 0000000..ccd9339
--- /dev/null
+++ b/Help/release/dev/explicit-source-extensions.rst
@@ -0,0 +1,5 @@
+explicit-source-extensions
+--------------------------
+
+* Source file extensions must now be explicit. See policy :policy:`CMP0115` for
+  details.
diff --git a/Help/release/dev/ninja-depfile-transformation.rst b/Help/release/dev/ninja-depfile-transformation.rst
new file mode 100644
index 0000000..edf7f58
--- /dev/null
+++ b/Help/release/dev/ninja-depfile-transformation.rst
@@ -0,0 +1,5 @@
+ninja-depfile-transformation
+----------------------------
+
+* Ninja generators now transform ``DEPFILE`` s from
+  :command:`add_custom_command`. See policy :policy:`CMP0116` for details.
diff --git a/Help/release/dev/remove-server-mode.rst b/Help/release/dev/remove-server-mode.rst
new file mode 100644
index 0000000..7c986b1
--- /dev/null
+++ b/Help/release/dev/remove-server-mode.rst
@@ -0,0 +1,5 @@
+remove-server-mode
+------------------
+
+* The :manual:`cmake-server(7)` mode has been removed.
+  Clients should use the :manual:`cmake-file-api(7)` instead.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 6fb0f1a..a8329a6 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -7,6 +7,8 @@
   This file should include the adjacent "dev.txt" file
   in development versions but not in release versions.
 
+.. include:: dev.txt
+
 Releases
 ========
 
diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index d35595a..9f68741 100644
--- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
+++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
@@ -27,6 +27,8 @@
   policy :policy:`CMP0102`.
 * ``CMAKE_POLICY_WARNING_CMP0112`` controls the warning for
   policy :policy:`CMP0112`.
+* ``CMAKE_POLICY_WARNING_CMP0116`` controls the warning for
+  policy :policy:`CMP0116`.
 
 This variable should not be set by a project in CMake code.  Project
 developers running CMake may set this variable in their cache to
diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake
index 44387d4..928881c 100644
--- a/Modules/CheckLanguage.cmake
+++ b/Modules/CheckLanguage.cmake
@@ -68,6 +68,11 @@
     else()
       set(_D_CMAKE_MAKE_PROGRAM "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
     endif()
+    if(CMAKE_TOOLCHAIN_FILE)
+      set(_D_CMAKE_TOOLCHAIN_FILE "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE}")
+    else()
+      set(_D_CMAKE_TOOLCHAIN_FILE "")
+    endif()
     execute_process(
       WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
       COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
@@ -75,6 +80,7 @@
                                  -T "${CMAKE_GENERATOR_TOOLSET}"
                                  ${_D_CMAKE_GENERATOR_INSTANCE}
                                  ${_D_CMAKE_MAKE_PROGRAM}
+                                 ${_D_CMAKE_TOOLCHAIN_FILE}
       OUTPUT_VARIABLE _cl_output
       ERROR_VARIABLE _cl_output
       RESULT_VARIABLE _cl_result
diff --git a/Modules/FindIntl.cmake b/Modules/FindIntl.cmake
index 1a09a60..d29f554 100644
--- a/Modules/FindIntl.cmake
+++ b/Modules/FindIntl.cmake
@@ -15,11 +15,16 @@
   Intl_FOUND - true if the libintl headers and libraries were found
   Intl_INCLUDE_DIRS - the directory containing the libintl headers
   Intl_LIBRARIES - libintl libraries to be linked
+  Intl::Intl - imported target for Intl
 
 The following cache variables may also be set::
 
   Intl_INCLUDE_DIR - the directory containing the libintl headers
   Intl_LIBRARY - the libintl library (if any)
+  Intl_HAVE_GETTEXT_BUILTIN - check if gettext is in the C library
+  Intl_HAVE_DCGETTEXT_BUILTIN - check if dcgettext is in the C library
+  Intl_IS_BUILTIN - whether intl is a part of the C library determined
+      from the result of Intl_HAVE_GETTEXT_BUILTIN and Intl_HAVE_DCGETTEXT_BUILTIN
 
 .. note::
   On some platforms, such as Linux with GNU libc, the gettext
@@ -35,6 +40,22 @@
 
 # Written by Roger Leigh <rleigh@codelibre.net>
 
+include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/CheckSymbolExists.cmake)
+
+# Check if we have libintl is a part of libc
+cmake_push_check_state(RESET)
+set(CMAKE_REQUIRED_QUIET TRUE)
+check_symbol_exists(gettext libintl.h Intl_HAVE_GETTEXT_BUILTIN)
+check_symbol_exists(dcgettext libintl.h Intl_HAVE_DCGETTEXT_BUILTIN) # redundant check
+cmake_pop_check_state()
+
+if(Intl_HAVE_GETTEXT_BUILTIN AND Intl_HAVE_DCGETTEXT_BUILTIN)
+  set(Intl_IS_BUILTIN TRUE)
+else()
+  set(Intl_IS_BUILTIN FALSE)
+endif()
+
 # Find include directory
 find_path(Intl_INCLUDE_DIR
           NAMES "libintl.h"
@@ -42,21 +63,28 @@
 mark_as_advanced(Intl_INCLUDE_DIR)
 
 # Find all Intl libraries
-find_library(Intl_LIBRARY "intl" NAMES_PER_DIR
-  DOC "libintl libraries (if not in the C library)")
-mark_as_advanced(Intl_LIBRARY)
+set(Intl_REQUIRED_VARS)
+if(NOT Intl_IS_BUILTIN)
+  find_library(Intl_LIBRARY "intl" "libintl" NAMES_PER_DIR
+    DOC "libintl libraries (if not in the C library)")
+  mark_as_advanced(Intl_LIBRARY)
+  list(APPEND Intl_REQUIRED_VARS Intl_LIBRARY)
+endif()
 
 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl
                                   FOUND_VAR Intl_FOUND
-                                  REQUIRED_VARS Intl_INCLUDE_DIR
+                                  REQUIRED_VARS Intl_INCLUDE_DIR ${Intl_REQUIRED_VARS}
                                   FAIL_MESSAGE "Failed to find Gettext libintl")
+unset(Intl_REQUIRED_VARS)
 
 if(Intl_FOUND)
   set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}")
-  if(Intl_LIBRARY)
-    set(Intl_LIBRARIES "${Intl_LIBRARY}")
-  else()
-    unset(Intl_LIBRARIES)
+  set(Intl_LIBRARIES "${Intl_LIBRARY}")
+  if(NOT TARGET Intl::Intl)
+    add_library(Intl::Intl INTERFACE IMPORTED)
+    set_target_properties(Intl::Intl PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${Intl_INCLUDE_DIRS}"
+      INTERFACE_LINK_LIBRARIES "${Intl_LIBRARIES}")
   endif()
 endif()
diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in
index 6009ce0..b448c76 100644
--- a/Modules/Internal/CPack/NSIS.template.in
+++ b/Modules/Internal/CPack/NSIS.template.in
@@ -1,4 +1,4 @@
-; CPack install script designed for a nmake build
+; CPack install script designed for a nmake build
 
 ;--------------------------------
 ; You must define these values
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 1194318..cb954e5 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -441,6 +441,8 @@
   cmTest.h
   cmTestGenerator.cxx
   cmTestGenerator.h
+  cmTransformDepfile.cxx
+  cmTransformDepfile.h
   cmUuid.cxx
   cmUVHandlePtr.cxx
   cmUVHandlePtr.h
@@ -1156,20 +1158,6 @@
 list(APPEND _tools cmake)
 target_link_libraries(cmake CMakeLib)
 
-add_library(CMakeServerLib
-  cmConnection.h cmConnection.cxx
-  cmFileMonitor.cxx cmFileMonitor.h
-  cmJsonObjectDictionary.h
-  cmJsonObjects.h
-  cmJsonObjects.cxx
-  cmPipeConnection.cxx cmPipeConnection.h
-  cmServer.cxx cmServer.h
-  cmServerConnection.cxx cmServerConnection.h
-  cmServerProtocol.cxx cmServerProtocol.h
-  )
-target_link_libraries(CMakeServerLib CMakeLib)
-target_link_libraries(cmake CMakeServerLib)
-
 # Build CTest executable
 add_executable(ctest ctest.cxx ${MANIFEST_FILE})
 list(APPEND _tools ctest)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 30b9512..48ea3f6 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,8 +1,8 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 19)
-set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 1)
+set(CMake_VERSION_PATCH 20201023)
+#set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
 # Start with the full version number used in tags.  It has no dev info.
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/LexerParser/cmGccDepfileLexer.cxx b/Source/LexerParser/cmGccDepfileLexer.cxx
index a98969d..3630f4e 100644
--- a/Source/LexerParser/cmGccDepfileLexer.cxx
+++ b/Source/LexerParser/cmGccDepfileLexer.cxx
@@ -994,7 +994,7 @@
 YY_RULE_SETUP
 {
                          // A line continuation ends the current file name.
-                         yyextra->newDependency();
+                         yyextra->newRuleOrDependency();
                        }
 	YY_BREAK
 case 6:
diff --git a/Source/LexerParser/cmGccDepfileLexer.in.l b/Source/LexerParser/cmGccDepfileLexer.in.l
index 08f8577..c83cb75 100644
--- a/Source/LexerParser/cmGccDepfileLexer.in.l
+++ b/Source/LexerParser/cmGccDepfileLexer.in.l
@@ -42,7 +42,7 @@
                        }
 {WSPACE}*\\{NEWLINE}   {
                          // A line continuation ends the current file name.
-                         yyextra->newDependency();
+                         yyextra->newRuleOrDependency();
                        }
 {NEWLINE}              {
                          // A newline ends the current file name and the current rule.
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/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 231a2d6..bea89c0 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -314,16 +314,9 @@
 
   // Check for an append request.
   if (append) {
-    if (mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends,
-                                       commandLines)) {
-      return true;
-    }
-
-    // No command for this output exists.
-    status.SetError(
-      cmStrCat("given APPEND option with output\n  ", output[0],
-               "\nwhich is not already a custom command output."));
-    return false;
+    mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends,
+                                   commandLines);
+    return true;
   }
 
   if (uses_terminal && !job_pool.empty()) {
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/cmConnection.cxx b/Source/cmConnection.cxx
deleted file mode 100644
index e4d0cf1..0000000
--- a/Source/cmConnection.cxx
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmConnection.h"
-
-#include <cassert>
-#include <cstring>
-
-#include <cm3p/uv.h>
-
-#include "cmServer.h"
-
-struct write_req_t
-{
-  uv_write_t req;
-  uv_buf_t buf;
-};
-
-void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle,
-                                             size_t suggested_size,
-                                             uv_buf_t* buf)
-{
-  (void)(handle);
-#ifndef __clang_analyzer__
-  char* rawBuffer = new char[suggested_size];
-  *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
-#else
-  (void)(suggested_size);
-  (void)(buf);
-#endif /* __clang_analyzer__ */
-}
-
-void cmEventBasedConnection::on_read(uv_stream_t* stream, ssize_t nread,
-                                     const uv_buf_t* buf)
-{
-  auto conn = static_cast<cmEventBasedConnection*>(stream->data);
-  if (conn) {
-    if (nread >= 0) {
-      conn->ReadData(std::string(buf->base, buf->base + nread));
-    } else {
-      conn->OnDisconnect(static_cast<int>(nread));
-    }
-  }
-
-  delete[](buf->base);
-}
-
-void cmEventBasedConnection::on_close(uv_handle_t* /*handle*/)
-{
-}
-
-void cmEventBasedConnection::on_write(uv_write_t* req, int status)
-{
-  (void)(status);
-
-  // Free req and buffer
-  write_req_t* wr = reinterpret_cast<write_req_t*>(req);
-  delete[](wr->buf.base);
-  delete wr;
-}
-
-void cmEventBasedConnection::on_new_connection(uv_stream_t* stream, int status)
-{
-  (void)(status);
-  auto conn = static_cast<cmEventBasedConnection*>(stream->data);
-
-  if (conn) {
-    conn->Connect(stream);
-  }
-}
-
-bool cmEventBasedConnection::IsOpen() const
-{
-  return this->WriteStream != nullptr;
-}
-
-void cmEventBasedConnection::WriteData(const std::string& _data)
-{
-#ifndef NDEBUG
-  auto curr_thread_id = uv_thread_self();
-  assert(this->Server);
-  assert(uv_thread_equal(&curr_thread_id, &this->Server->ServeThreadId));
-#endif
-
-#ifndef __clang_analyzer__
-  auto data = _data;
-  assert(this->WriteStream.get());
-  if (BufferStrategy) {
-    data = BufferStrategy->BufferOutMessage(data);
-  }
-
-  auto ds = data.size();
-
-  write_req_t* req = new write_req_t;
-  req->req.data = this;
-  req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds));
-  memcpy(req->buf.base, data.c_str(), ds);
-  uv_write(reinterpret_cast<uv_write_t*>(req), this->WriteStream, &req->buf, 1,
-           on_write);
-#else
-  (void)(_data);
-#endif /* __clang_analyzer__ */
-}
-
-void cmEventBasedConnection::ReadData(const std::string& data)
-{
-  this->RawReadBuffer += data;
-  if (BufferStrategy) {
-    std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
-    while (!packet.empty()) {
-      ProcessRequest(packet);
-      packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
-    }
-  } else {
-    ProcessRequest(this->RawReadBuffer);
-    this->RawReadBuffer.clear();
-  }
-}
-
-cmEventBasedConnection::cmEventBasedConnection(
-  cmConnectionBufferStrategy* bufferStrategy)
-  : BufferStrategy(bufferStrategy)
-{
-}
-
-void cmEventBasedConnection::Connect(uv_stream_t* server)
-{
-  (void)server;
-  Server->OnConnected(nullptr);
-}
-
-void cmEventBasedConnection::OnDisconnect(int onerror)
-{
-  (void)onerror;
-  this->OnConnectionShuttingDown();
-  if (this->Server) {
-    this->Server->OnDisconnect(this);
-  }
-}
-
-cmConnection::~cmConnection() = default;
-
-bool cmConnection::OnConnectionShuttingDown()
-{
-  this->Server = nullptr;
-  return true;
-}
-
-void cmConnection::SetServer(cmServerBase* s)
-{
-  Server = s;
-}
-
-void cmConnection::ProcessRequest(const std::string& request)
-{
-  Server->ProcessRequest(this, request);
-}
-
-bool cmConnection::OnServeStart(std::string* errString)
-{
-  (void)errString;
-  return true;
-}
-
-bool cmEventBasedConnection::OnConnectionShuttingDown()
-{
-  if (this->WriteStream.get()) {
-    this->WriteStream->data = nullptr;
-  }
-
-  WriteStream.reset();
-
-  return true;
-}
diff --git a/Source/cmConnection.h b/Source/cmConnection.h
deleted file mode 100644
index 5335a7f..0000000
--- a/Source/cmConnection.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <cstddef>
-#include <memory>
-#include <string>
-
-#include <cm3p/uv.h>
-
-#include "cmUVHandlePtr.h"
-
-class cmServerBase;
-
-/***
- * Given a sequence of bytes with any kind of buffering, instances of this
- * class arrange logical chunks according to whatever the use case is for
- * the connection.
- */
-class cmConnectionBufferStrategy
-{
-public:
-  virtual ~cmConnectionBufferStrategy();
-
-  /***
-   * Called whenever with an active raw buffer. If a logical chunk
-   * becomes available, that chunk is returned and that portion is
-   * removed from the rawBuffer
-   *
-   * @param rawBuffer in/out parameter. Receive buffer; the buffer strategy is
-   * free to manipulate this buffer anyway it needs to.
-   *
-   * @return Next chunk from the stream. Returns the empty string if a chunk
-   * isn't ready yet. Users of this interface should repeatedly call this
-   * function until an empty string is returned since its entirely possible
-   * multiple chunks come in a single raw buffer.
-   */
-  virtual std::string BufferMessage(std::string& rawBuffer) = 0;
-
-  /***
-   * Called to properly buffer an outgoing message.
-   *
-   * @param rawBuffer Message to format in the correct way
-   *
-   * @return Formatted message
-   */
-  virtual std::string BufferOutMessage(const std::string& rawBuffer) const
-  {
-    return rawBuffer;
-  };
-  /***
-   * Resets the internal state of the buffering
-   */
-  virtual void clear();
-
-  // TODO: There should be a callback / flag set for errors
-};
-
-class cmConnection
-{
-public:
-  cmConnection() = default;
-
-  cmConnection(cmConnection const&) = delete;
-  cmConnection& operator=(cmConnection const&) = delete;
-
-  virtual void WriteData(const std::string& data) = 0;
-
-  virtual ~cmConnection();
-
-  virtual bool OnConnectionShuttingDown();
-
-  virtual bool IsOpen() const = 0;
-
-  virtual void SetServer(cmServerBase* s);
-
-  virtual void ProcessRequest(const std::string& request);
-
-  virtual bool OnServeStart(std::string* pString);
-
-protected:
-  cmServerBase* Server = nullptr;
-};
-
-/***
- * Abstraction of a connection; ties in event callbacks from libuv and notifies
- * the server when appropriate
- */
-class cmEventBasedConnection : public cmConnection
-{
-
-public:
-  /***
-   * @param bufferStrategy If no strategy is given, it will process the raw
-   * chunks as they come in. The connection
-   * owns the pointer given.
-   */
-  cmEventBasedConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr);
-
-  virtual void Connect(uv_stream_t* server);
-
-  virtual void ReadData(const std::string& data);
-
-  bool IsOpen() const override;
-
-  void WriteData(const std::string& data) override;
-  bool OnConnectionShuttingDown() override;
-
-  virtual void OnDisconnect(int errorCode);
-
-  static void on_close(uv_handle_t* handle);
-
-  template <typename T>
-  static void on_close_delete(uv_handle_t* handle)
-  {
-    delete reinterpret_cast<T*>(handle);
-  }
-
-protected:
-  cm::uv_stream_ptr WriteStream;
-
-  std::string RawReadBuffer;
-
-  std::unique_ptr<cmConnectionBufferStrategy> BufferStrategy;
-
-  static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
-
-  static void on_write(uv_write_t* req, int status);
-
-  static void on_new_connection(uv_stream_t* stream, int status);
-
-  static void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size,
-                              uv_buf_t* buf);
-};
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 60504ba..d8307f6 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -6,18 +6,22 @@
 #include <memory>
 #include <utility>
 
+#include <cm/optional>
 #include <cmext/algorithm>
 
+#include "cmCryptoHash.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmProperty.h"
 #include "cmStateTypes.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
+#include "cmTransformDepfile.h"
 
 namespace {
 void AppendPaths(const std::vector<std::string>& inputs,
@@ -42,7 +46,8 @@
 
 cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
                                                    std::string config,
-                                                   cmLocalGenerator* lg)
+                                                   cmLocalGenerator* lg,
+                                                   bool transformDepfile)
   : CC(cc)
   , Config(std::move(config))
   , LG(lg)
@@ -75,6 +80,36 @@
     this->CommandLines.push_back(std::move(argv));
   }
 
+  if (transformDepfile && !this->CommandLines.empty() &&
+      !cc.GetDepfile().empty() &&
+      this->LG->GetGlobalGenerator()->DepfileFormat()) {
+    cmCustomCommandLine argv;
+    argv.push_back(cmSystemTools::GetCMakeCommand());
+    argv.emplace_back("-E");
+    argv.emplace_back("cmake_transform_depfile");
+    switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
+      case cmDepfileFormat::GccDepfile:
+        argv.emplace_back("gccdepfile");
+        break;
+      case cmDepfileFormat::VsTlog:
+        argv.emplace_back("vstlog");
+        break;
+    }
+    if (this->LG->GetCurrentBinaryDirectory() ==
+        this->LG->GetBinaryDirectory()) {
+      argv.emplace_back("./");
+    } else {
+      argv.push_back(cmStrCat(this->LG->MaybeConvertToRelativePath(
+                                this->LG->GetBinaryDirectory(),
+                                this->LG->GetCurrentBinaryDirectory()),
+                              '/'));
+    }
+    argv.push_back(this->GetFullDepfile());
+    argv.push_back(this->GetInternalDepfile());
+
+    this->CommandLines.push_back(std::move(argv));
+  }
+
   AppendPaths(cc.GetByproducts(), ge, this->LG, this->Config,
               this->Byproducts);
   AppendPaths(cc.GetDepends(), ge, this->LG, this->Config, this->Depends);
@@ -97,7 +132,7 @@
 
 unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
 {
-  return static_cast<unsigned int>(this->CC.GetCommandLines().size());
+  return static_cast<unsigned int>(this->CommandLines.size());
 }
 
 void cmCustomCommandGenerator::FillEmulatorsWithArguments()
@@ -234,6 +269,40 @@
   }
 }
 
+std::string cmCustomCommandGenerator::GetFullDepfile() const
+{
+  std::string depfile = this->CC.GetDepfile();
+  if (depfile.empty()) {
+    return "";
+  }
+
+  if (!cmSystemTools::FileIsFullPath(depfile)) {
+    depfile = cmStrCat(this->LG->GetCurrentBinaryDirectory(), '/', depfile);
+  }
+  return cmSystemTools::CollapseFullPath(depfile);
+}
+
+std::string cmCustomCommandGenerator::GetInternalDepfile() const
+{
+  std::string depfile = this->GetFullDepfile();
+  if (depfile.empty()) {
+    return "";
+  }
+
+  cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+  std::string extension;
+  switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
+    case cmDepfileFormat::GccDepfile:
+      extension = ".d";
+      break;
+    case cmDepfileFormat::VsTlog:
+      extension = ".tlog";
+      break;
+  }
+  return cmStrCat(this->LG->GetBinaryDirectory(), "/CMakeFiles/d/",
+                  hash.HashString(depfile), extension);
+}
+
 const char* cmCustomCommandGenerator::GetComment() const
 {
   return this->CC.GetComment();
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 412eba8..8b5259d 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -31,7 +31,7 @@
 
 public:
   cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config,
-                           cmLocalGenerator* lg);
+                           cmLocalGenerator* lg, bool transformDepfile = true);
   cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete;
   cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) =
     delete;
@@ -45,4 +45,6 @@
   std::vector<std::string> const& GetByproducts() const;
   std::vector<std::string> const& GetDepends() const;
   bool HasOnlyEmptyCommandLines() const;
+  std::string GetFullDepfile() const;
+  std::string GetInternalDepfile() const;
 };
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index cbae4e5..a853bb1 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -924,13 +924,13 @@
 
   // Isolate the file policy level.
   // Support CMake versions as far back as 2.6 but also support using NEW
-  // policy settings for up to CMake 3.17 (this upper limit may be reviewed
+  // policy settings for up to CMake 3.18 (this upper limit may be reviewed
   // and increased from time to time). This reduces the opportunity for CMake
   // warnings when an older export file is later used with newer CMake
   // versions.
   /* clang-format off */
   os << "cmake_policy(PUSH)\n"
-     << "cmake_policy(VERSION 2.6...3.17)\n";
+     << "cmake_policy(VERSION 2.6...3.18)\n";
   /* clang-format on */
 }
 
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 8a3aad2..cd440ad 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -15,6 +15,7 @@
 #include <vector>
 
 #include <cm/memory>
+#include <cm/string_view>
 #include <cmext/algorithm>
 #include <cmext/string_view>
 
@@ -2314,49 +2315,92 @@
     status.SetError("Incorrect arguments to GENERATE subcommand.");
     return false;
   }
-  if (args[1] != "OUTPUT") {
+
+  struct Arguments
+  {
+    std::string Output;
+    std::string Input;
+    std::string Content;
+    std::string Condition;
+    std::string Target;
+  };
+
+  static auto const parser = cmArgumentParser<Arguments>{}
+                               .Bind("OUTPUT"_s, &Arguments::Output)
+                               .Bind("INPUT"_s, &Arguments::Input)
+                               .Bind("CONTENT"_s, &Arguments::Content)
+                               .Bind("CONDITION"_s, &Arguments::Condition)
+                               .Bind("TARGET"_s, &Arguments::Target);
+
+  std::vector<std::string> unparsedArguments;
+  std::vector<std::string> keywordsMissingValues;
+  std::vector<std::string> parsedKeywords;
+  Arguments const arguments =
+    parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments,
+                 &keywordsMissingValues, &parsedKeywords);
+
+  if (!keywordsMissingValues.empty()) {
     status.SetError("Incorrect arguments to GENERATE subcommand.");
     return false;
   }
 
-  std::string condition;
-  std::string target;
-
-  for (std::size_t i = 5; i < args.size();) {
-    const std::string& arg = args[i++];
-
-    if (args.size() - i == 0) {
-      status.SetError("Incorrect arguments to GENERATE subcommand.");
-      return false;
-    }
-
-    const std::string& value = args[i++];
-
-    if (value.empty()) {
-      status.SetError(
-        arg + " of sub-command GENERATE must not be empty if specified.");
-      return false;
-    }
-
-    if (arg == "CONDITION") {
-      condition = value;
-    } else if (arg == "TARGET") {
-      target = value;
-    } else {
-      status.SetError("Unknown argument to GENERATE subcommand.");
-      return false;
-    }
+  if (!unparsedArguments.empty()) {
+    status.SetError("Unknown argument to GENERATE subcommand.");
+    return false;
   }
 
-  std::string output = args[2];
-  const bool inputIsContent = args[3] != "INPUT";
-  if (inputIsContent && args[3] != "CONTENT") {
+  bool mandatoryOptionsSpecified = false;
+  if (parsedKeywords.size() > 1) {
+    const bool outputOprionSpecified = parsedKeywords[0] == "OUTPUT"_s;
+    const bool inputOrContentSpecified =
+      parsedKeywords[1] == "INPUT"_s || parsedKeywords[1] == "CONTENT"_s;
+    if (outputOprionSpecified && inputOrContentSpecified) {
+      mandatoryOptionsSpecified = true;
+    }
+  }
+  if (!mandatoryOptionsSpecified) {
     status.SetError("Incorrect arguments to GENERATE subcommand.");
     return false;
   }
-  std::string input = args[4];
 
-  AddEvaluationFile(input, target, output, condition, inputIsContent, status);
+  const bool conditionOptionSpecified =
+    std::find(parsedKeywords.begin(), parsedKeywords.end(), "CONDITION"_s) !=
+    parsedKeywords.end();
+  if (conditionOptionSpecified && arguments.Condition.empty()) {
+    status.SetError("CONDITION of sub-command GENERATE must not be empty "
+                    "if specified.");
+    return false;
+  }
+
+  const bool targetOptionSpecified =
+    std::find(parsedKeywords.begin(), parsedKeywords.end(), "TARGET"_s) !=
+    parsedKeywords.end();
+  if (targetOptionSpecified && arguments.Target.empty()) {
+    status.SetError("TARGET of sub-command GENERATE must not be empty "
+                    "if specified.");
+    return false;
+  }
+
+  const bool outputOptionSpecified =
+    std::find(parsedKeywords.begin(), parsedKeywords.end(), "OUTPUT"_s) !=
+    parsedKeywords.end();
+  if (outputOptionSpecified && parsedKeywords[0] != "OUTPUT"_s) {
+    status.SetError("Incorrect arguments to GENERATE subcommand.");
+    return false;
+  }
+
+  const bool inputIsContent = parsedKeywords[1] != "INPUT"_s;
+  if (inputIsContent && parsedKeywords[1] != "CONTENT") {
+    status.SetError("Unknown argument to GENERATE subcommand.");
+  }
+
+  std::string input = arguments.Input;
+  if (inputIsContent) {
+    input = arguments.Content;
+  }
+
+  AddEvaluationFile(input, arguments.Target, arguments.Output,
+                    arguments.Condition, inputIsContent, status);
   return true;
 }
 
diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx
deleted file mode 100644
index 8cfdb2d..0000000
--- a/Source/cmFileMonitor.cxx
+++ /dev/null
@@ -1,383 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmFileMonitor.h"
-
-#include <cassert>
-#include <cstddef>
-#include <unordered_map>
-#include <utility>
-
-#include <cm/memory>
-
-#include "cmsys/SystemTools.hxx"
-
-namespace {
-void on_directory_change(uv_fs_event_t* handle, const char* filename,
-                         int events, int status);
-void on_fs_close(uv_handle_t* handle);
-} // namespace
-
-class cmIBaseWatcher
-{
-public:
-  virtual ~cmIBaseWatcher() = default;
-
-  virtual void Trigger(const std::string& pathSegment, int events,
-                       int status) const = 0;
-  virtual std::string Path() const = 0;
-  virtual uv_loop_t* Loop() const = 0;
-
-  virtual void StartWatching() = 0;
-  virtual void StopWatching() = 0;
-
-  virtual std::vector<std::string> WatchedFiles() const = 0;
-  virtual std::vector<std::string> WatchedDirectories() const = 0;
-};
-
-class cmVirtualDirectoryWatcher : public cmIBaseWatcher
-{
-public:
-  ~cmVirtualDirectoryWatcher() override = default;
-
-  cmIBaseWatcher* Find(const std::string& ps)
-  {
-    const auto i = this->Children.find(ps);
-    return (i == this->Children.end()) ? nullptr : i->second.get();
-  }
-
-  void Trigger(const std::string& pathSegment, int events,
-               int status) const final
-  {
-    if (pathSegment.empty()) {
-      for (auto const& child : this->Children) {
-        child.second->Trigger(std::string(), events, status);
-      }
-    } else {
-      const auto i = this->Children.find(pathSegment);
-      if (i != this->Children.end()) {
-        i->second->Trigger(std::string(), events, status);
-      }
-    }
-  }
-
-  void StartWatching() override
-  {
-    for (auto const& child : this->Children) {
-      child.second->StartWatching();
-    }
-  }
-
-  void StopWatching() override
-  {
-    for (auto const& child : this->Children) {
-      child.second->StopWatching();
-    }
-  }
-
-  std::vector<std::string> WatchedFiles() const final
-  {
-    std::vector<std::string> result;
-    for (auto const& child : this->Children) {
-      for (std::string const& f : child.second->WatchedFiles()) {
-        result.push_back(f);
-      }
-    }
-    return result;
-  }
-
-  std::vector<std::string> WatchedDirectories() const override
-  {
-    std::vector<std::string> result;
-    for (auto const& child : this->Children) {
-      for (std::string const& dir : child.second->WatchedDirectories()) {
-        result.push_back(dir);
-      }
-    }
-    return result;
-  }
-
-  void Reset() { this->Children.clear(); }
-
-  void AddChildWatcher(const std::string& ps, cmIBaseWatcher* watcher)
-  {
-    assert(!ps.empty());
-    assert(this->Children.find(ps) == this->Children.end());
-    assert(watcher);
-
-    this->Children.emplace(ps, std::unique_ptr<cmIBaseWatcher>(watcher));
-  }
-
-private:
-  std::unordered_map<std::string, std::unique_ptr<cmIBaseWatcher>>
-    Children; // owned!
-};
-
-// Root of all the different (on windows!) root directories:
-class cmRootWatcher : public cmVirtualDirectoryWatcher
-{
-public:
-  cmRootWatcher(uv_loop_t* loop)
-    : mLoop(loop)
-  {
-    assert(loop);
-  }
-
-  std::string Path() const final
-  {
-    assert(false);
-    return std::string();
-  }
-  uv_loop_t* Loop() const final { return this->mLoop; }
-
-private:
-  uv_loop_t* const mLoop; // no ownership!
-};
-
-// Real directories:
-class cmRealDirectoryWatcher : public cmVirtualDirectoryWatcher
-{
-public:
-  cmRealDirectoryWatcher(cmVirtualDirectoryWatcher* p, const std::string& ps)
-    : Parent(p)
-    , PathSegment(ps)
-  {
-    assert(p);
-    assert(!ps.empty());
-
-    p->AddChildWatcher(ps, this);
-  }
-
-  void StartWatching() final
-  {
-    if (!this->Handle) {
-      this->Handle = new uv_fs_event_t;
-
-      uv_fs_event_init(this->Loop(), this->Handle);
-      this->Handle->data = this;
-      uv_fs_event_start(this->Handle, &on_directory_change, Path().c_str(), 0);
-    }
-    cmVirtualDirectoryWatcher::StartWatching();
-  }
-
-  void StopWatching() final
-  {
-    if (this->Handle) {
-      uv_fs_event_stop(this->Handle);
-      if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(this->Handle))) {
-        uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
-      }
-      this->Handle = nullptr;
-    }
-    cmVirtualDirectoryWatcher::StopWatching();
-  }
-
-  uv_loop_t* Loop() const final { return this->Parent->Loop(); }
-
-  std::vector<std::string> WatchedDirectories() const override
-  {
-    std::vector<std::string> result = { Path() };
-    for (std::string const& dir :
-         cmVirtualDirectoryWatcher::WatchedDirectories()) {
-      result.push_back(dir);
-    }
-    return result;
-  }
-
-protected:
-  cmVirtualDirectoryWatcher* const Parent;
-  const std::string PathSegment;
-
-private:
-  uv_fs_event_t* Handle = nullptr; // owner!
-};
-
-// Root directories:
-class cmRootDirectoryWatcher : public cmRealDirectoryWatcher
-{
-public:
-  cmRootDirectoryWatcher(cmRootWatcher* p, const std::string& ps)
-    : cmRealDirectoryWatcher(p, ps)
-  {
-  }
-
-  std::string Path() const final { return this->PathSegment; }
-};
-
-// Normal directories below root:
-class cmDirectoryWatcher : public cmRealDirectoryWatcher
-{
-public:
-  cmDirectoryWatcher(cmRealDirectoryWatcher* p, const std::string& ps)
-    : cmRealDirectoryWatcher(p, ps)
-  {
-  }
-
-  std::string Path() const final
-  {
-    return this->Parent->Path() + this->PathSegment + "/";
-  }
-};
-
-class cmFileWatcher : public cmIBaseWatcher
-{
-public:
-  cmFileWatcher(cmRealDirectoryWatcher* p, const std::string& ps,
-                cmFileMonitor::Callback cb)
-    : Parent(p)
-    , PathSegment(ps)
-    , CbList({ std::move(cb) })
-  {
-    assert(p);
-    assert(!ps.empty());
-    p->AddChildWatcher(ps, this);
-  }
-
-  void StartWatching() final {}
-
-  void StopWatching() final {}
-
-  void AppendCallback(cmFileMonitor::Callback const& cb)
-  {
-    this->CbList.push_back(cb);
-  }
-
-  std::string Path() const final
-  {
-    return this->Parent->Path() + this->PathSegment;
-  }
-
-  std::vector<std::string> WatchedDirectories() const final { return {}; }
-
-  std::vector<std::string> WatchedFiles() const final
-  {
-    return { this->Path() };
-  }
-
-  void Trigger(const std::string& ps, int events, int status) const final
-  {
-    assert(ps.empty());
-    assert(status == 0);
-    static_cast<void>(ps);
-
-    const std::string path = this->Path();
-    for (cmFileMonitor::Callback const& cb : this->CbList) {
-      cb(path, events, status);
-    }
-  }
-
-  uv_loop_t* Loop() const final { return this->Parent->Loop(); }
-
-private:
-  cmRealDirectoryWatcher* Parent;
-  const std::string PathSegment;
-  std::vector<cmFileMonitor::Callback> CbList;
-};
-
-namespace {
-
-void on_directory_change(uv_fs_event_t* handle, const char* filename,
-                         int events, int status)
-{
-  const cmIBaseWatcher* const watcher =
-    static_cast<const cmIBaseWatcher*>(handle->data);
-  const std::string pathSegment(filename ? filename : "");
-  watcher->Trigger(pathSegment, events, status);
-}
-
-void on_fs_close(uv_handle_t* handle)
-{
-  delete reinterpret_cast<uv_fs_event_t*>(handle);
-}
-
-} // namespace
-
-cmFileMonitor::cmFileMonitor(uv_loop_t* l)
-  : Root(cm::make_unique<cmRootWatcher>(l))
-{
-}
-
-cmFileMonitor::~cmFileMonitor() = default;
-
-void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths,
-                                 Callback const& cb)
-{
-  for (std::string const& p : paths) {
-    std::vector<std::string> pathSegments;
-    cmsys::SystemTools::SplitPath(p, pathSegments, true);
-    const bool pathIsFile = !cmsys::SystemTools::FileIsDirectory(p);
-
-    const size_t segmentCount = pathSegments.size();
-    if (segmentCount < 2) { // Expect at least rootdir and filename
-      continue;
-    }
-    cmVirtualDirectoryWatcher* currentWatcher = this->Root.get();
-    for (size_t i = 0; i < segmentCount; ++i) {
-      assert(currentWatcher);
-
-      const bool fileSegment = (i == segmentCount - 1 && pathIsFile);
-      const bool rootSegment = (i == 0);
-      assert(
-        !(fileSegment &&
-          rootSegment)); // Can not be both filename and root part of the path!
-
-      const std::string& currentSegment = pathSegments[i];
-      if (currentSegment.empty()) {
-        continue;
-      }
-
-      cmIBaseWatcher* nextWatcher = currentWatcher->Find(currentSegment);
-      if (!nextWatcher) {
-        if (rootSegment) { // Root part
-          assert(currentWatcher == this->Root.get());
-          nextWatcher =
-            new cmRootDirectoryWatcher(this->Root.get(), currentSegment);
-          assert(currentWatcher->Find(currentSegment) == nextWatcher);
-        } else if (fileSegment) { // File part
-          assert(currentWatcher != this->Root.get());
-          nextWatcher = new cmFileWatcher(
-            dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
-            currentSegment, cb);
-          assert(currentWatcher->Find(currentSegment) == nextWatcher);
-        } else { // Any normal directory in between
-          nextWatcher = new cmDirectoryWatcher(
-            dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
-            currentSegment);
-          assert(currentWatcher->Find(currentSegment) == nextWatcher);
-        }
-      } else {
-        if (fileSegment) {
-          auto filePtr = dynamic_cast<cmFileWatcher*>(nextWatcher);
-          assert(filePtr);
-          filePtr->AppendCallback(cb);
-          continue;
-        }
-      }
-      currentWatcher = dynamic_cast<cmVirtualDirectoryWatcher*>(nextWatcher);
-    }
-  }
-  this->Root->StartWatching();
-}
-
-void cmFileMonitor::StopMonitoring()
-{
-  this->Root->StopWatching();
-  this->Root->Reset();
-}
-
-std::vector<std::string> cmFileMonitor::WatchedFiles() const
-{
-  std::vector<std::string> result;
-  if (this->Root) {
-    result = this->Root->WatchedFiles();
-  }
-  return result;
-}
-
-std::vector<std::string> cmFileMonitor::WatchedDirectories() const
-{
-  std::vector<std::string> result;
-  if (this->Root) {
-    result = this->Root->WatchedDirectories();
-  }
-  return result;
-}
diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h
deleted file mode 100644
index fc75b0c..0000000
--- a/Source/cmFileMonitor.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <cm3p/uv.h>
-
-class cmRootWatcher;
-
-class cmFileMonitor
-{
-
-public:
-  cmFileMonitor(uv_loop_t* l);
-  ~cmFileMonitor();
-
-  cmFileMonitor(cmFileMonitor const&) = delete;
-  cmFileMonitor& operator=(cmFileMonitor const&) = delete;
-
-  using Callback = std::function<void(const std::string&, int, int)>;
-  void MonitorPaths(const std::vector<std::string>& paths, Callback const& cb);
-  void StopMonitoring();
-
-  std::vector<std::string> WatchedFiles() const;
-  std::vector<std::string> WatchedDirectories() const;
-
-private:
-  std::unique_ptr<cmRootWatcher> Root;
-};
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index dee91d7..7952336 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -182,7 +182,7 @@
       { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" } }
   };
 
-  for (auto& path : search_paths) {
+  for (auto const& path : search_paths) {
     cmProp def = this->Makefile->GetDefinition(path.second);
     if (def) {
       path.first = !cmIsOn(*def);
diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx
index 957896f..c782bcd 100644
--- a/Source/cmGccDepfileLexerHelper.cxx
+++ b/Source/cmGccDepfileLexerHelper.cxx
@@ -27,23 +27,30 @@
   if (!file) {
     return false;
   }
-  newEntry();
+  this->newEntry();
   yyscan_t scanner;
   cmGccDepfile_yylex_init(&scanner);
   cmGccDepfile_yyset_extra(this, scanner);
   cmGccDepfile_yyrestart(file, scanner);
   cmGccDepfile_yylex(scanner);
   cmGccDepfile_yylex_destroy(scanner);
-  sanitizeContent();
+  this->sanitizeContent();
   fclose(file);
-  return true;
+  return this->HelperState != State::Failed;
 }
 
 void cmGccDepfileLexerHelper::newEntry()
 {
+  if (this->HelperState == State::Rule && !this->Content.empty()) {
+    if (!this->Content.back().rules.empty() &&
+        !this->Content.back().rules.back().empty()) {
+      this->HelperState = State::Failed;
+    }
+    return;
+  }
   this->HelperState = State::Rule;
   this->Content.emplace_back();
-  newRule();
+  this->newRule();
 }
 
 void cmGccDepfileLexerHelper::newRule()
@@ -56,20 +63,22 @@
 
 void cmGccDepfileLexerHelper::newDependency()
 {
-  // printf("NEW DEP\n");
+  if (this->HelperState == State::Failed) {
+    return;
+  }
   this->HelperState = State::Dependency;
-  if (this->Content.back().paths.empty() ||
-      !this->Content.back().paths.back().empty()) {
-    this->Content.back().paths.emplace_back();
+  auto& entry = this->Content.back();
+  if (entry.paths.empty() || !entry.paths.back().empty()) {
+    entry.paths.emplace_back();
   }
 }
 
 void cmGccDepfileLexerHelper::newRuleOrDependency()
 {
   if (this->HelperState == State::Rule) {
-    newRule();
-  } else {
-    newDependency();
+    this->newRule();
+  } else if (this->HelperState == State::Dependency) {
+    this->newDependency();
   }
 }
 
@@ -93,6 +102,8 @@
       }
       dst = &dep->paths.back();
     } break;
+    case State::Failed:
+      return;
   }
   dst->append(s);
 }
diff --git a/Source/cmGccDepfileLexerHelper.h b/Source/cmGccDepfileLexerHelper.h
index 07ca61d..91132f5 100644
--- a/Source/cmGccDepfileLexerHelper.h
+++ b/Source/cmGccDepfileLexerHelper.h
@@ -29,7 +29,8 @@
   enum class State
   {
     Rule,
-    Dependency
+    Dependency,
+    Failed,
   };
   State HelperState = State::Rule;
 };
diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx
index 9d70ede..eb3511a 100644
--- a/Source/cmGccDepfileReader.cxx
+++ b/Source/cmGccDepfileReader.cxx
@@ -5,14 +5,15 @@
 #include <type_traits>
 #include <utility>
 
+#include <cm/optional>
+
 #include "cmGccDepfileLexerHelper.h"
 
-cmGccDepfileContent cmReadGccDepfile(const char* filePath)
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath)
 {
-  cmGccDepfileContent result;
   cmGccDepfileLexerHelper helper;
   if (helper.readFile(filePath)) {
-    result = std::move(helper).extractContent();
+    return cm::make_optional(std::move(helper).extractContent());
   }
-  return result;
+  return cm::nullopt;
 }
diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h
index 395dd77..59ed7fd 100644
--- a/Source/cmGccDepfileReader.h
+++ b/Source/cmGccDepfileReader.h
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
+#include <cm/optional>
+
 #include "cmGccDepfileReaderTypes.h"
 
-cmGccDepfileContent cmReadGccDepfile(const char* filePath);
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath);
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 3e7737e..af2afd6 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -60,7 +60,7 @@
 
   void Extend(size_t length) { this->Length += length; }
 
-  size_t GetLength() { return this->Length; }
+  size_t GetLength() const { return this->Length; }
 
 private:
   const char* Content;
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 4ca7405..e40316e 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -677,7 +677,7 @@
     }
     static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
 
-    for (auto& param : parameters) {
+    for (auto const& param : parameters) {
 
       if (!compilerIdValidator.find(param)) {
         reportError(context, content->GetOriginalExpression(),
@@ -805,7 +805,7 @@
       return parameters.front().empty() ? "1" : "0";
     }
 
-    for (auto& param : parameters) {
+    for (auto const& param : parameters) {
       if (param == platformId) {
         return "1";
       }
@@ -901,7 +901,7 @@
       return std::string();
     }
     context->HadContextSensitiveCondition = true;
-    for (auto& param : parameters) {
+    for (auto const& param : parameters) {
       if (context->Config.empty()) {
         if (param.empty()) {
           return "1";
@@ -927,7 +927,7 @@
         if (cmProp mapValue = context->CurrentTarget->GetProperty(mapProp)) {
           cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs);
 
-          for (auto& param : parameters) {
+          for (auto const& param : parameters) {
             if (cm::contains(mappedConfigs, cmSystemTools::UpperCase(param))) {
               return "1";
             }
@@ -995,7 +995,7 @@
       return context->Language;
     }
 
-    for (auto& param : parameters) {
+    for (auto const& param : parameters) {
       if (context->Language == param) {
         return "1";
       }
@@ -1101,7 +1101,7 @@
       return context->Language;
     }
 
-    for (auto& param : parameters) {
+    for (auto const& param : parameters) {
       if (context->Language == param) {
         return "1";
       }
@@ -1129,7 +1129,7 @@
     }
     static cmsys::RegularExpression linkerIdValidator("^[A-Za-z0-9_]*$");
 
-    for (auto& param : parameters) {
+    for (auto const& param : parameters) {
       if (!linkerIdValidator.find(param)) {
         reportError(context, content->GetOriginalExpression(),
                     "Expression syntax not recognized.");
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index bdea9fa..1ed82fd 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -254,7 +254,7 @@
 {
   EvaluatedTargetPropertyEntries out;
   out.Entries.reserve(in.size());
-  for (auto& entry : in) {
+  for (auto const& entry : in) {
     out.Entries.emplace_back(EvaluateTargetPropertyEntry(
       thisTarget, config, lang, dagChecker, *entry));
   }
@@ -332,7 +332,7 @@
 const std::string& cmGeneratorTarget::GetSourcesProperty() const
 {
   std::vector<std::string> values;
-  for (auto& se : this->SourceEntries) {
+  for (auto const& se : this->SourceEntries) {
     values.push_back(se->GetInput());
   }
   static std::string value;
@@ -1539,10 +1539,14 @@
     for (std::string& src : entry.Values) {
       cmSourceFile* sf = mf->GetOrCreateSource(src);
       std::string e;
-      std::string fullPath = sf->ResolveFullPath(&e);
+      std::string w;
+      std::string fullPath = sf->ResolveFullPath(&e, &w);
+      cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
+      if (!w.empty()) {
+        cm->IssueMessage(MessageType::AUTHOR_WARNING, w, tgt->GetBacktrace());
+      }
       if (fullPath.empty()) {
         if (!e.empty()) {
-          cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
           cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace());
         }
         return contextDependent;
@@ -2500,7 +2504,7 @@
     }
   }
 
-  bool GetHadLinkLanguageSensitiveCondition()
+  bool GetHadLinkLanguageSensitiveCondition() const
   {
     return HadLinkLanguageSensitiveCondition;
   }
@@ -2986,7 +2990,8 @@
   auto i = this->NameMap.lower_bound(name);
   if (i == this->NameMap.end() || i->first != name) {
     // Check if we know how to generate this file.
-    cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name);
+    cmSourcesWithOutput sources =
+      this->LocalGenerator->GetSourcesWithOutput(name);
     // If we failed to find a target or source and we have a relative path, it
     // might be a valid source if made relative to the current binary
     // directory.
@@ -2996,7 +3001,7 @@
         cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', name);
       fullname = cmSystemTools::CollapseFullPath(
         fullname, this->Makefile->GetHomeOutputDirectory());
-      sources = this->Makefile->GetSourcesWithOutput(fullname);
+      sources = this->LocalGenerator->GetSourcesWithOutput(fullname);
     }
     i = this->NameMap.emplace_hint(i, name, sources);
   }
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index a8f8f57..ed50067 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -763,9 +763,9 @@
     /* set temporary mark; check if revisit*/
     if (temp.insert(si).second) {
       for (auto& di : si->GetCustomCommand()->GetDepends()) {
-        cmSourceFile const* sf = this->GeneratorTarget->GetLocalGenerator()
-                                   ->GetMakefile()
-                                   ->GetSourceFileWithOutput(di);
+        cmSourceFile const* sf =
+          this->GeneratorTarget->GetLocalGenerator()->GetSourceFileWithOutput(
+            di);
         /* if sf exists then visit */
         if (sf && this->VisitCustomCommand(temp, perm, order, sf)) {
           return true;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 1197db6..52f1d52 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2601,7 +2601,7 @@
 }
 
 void cmGlobalGenerator::AddGlobalTarget_EditCache(
-  std::vector<GlobalTargetInfo>& targets)
+  std::vector<GlobalTargetInfo>& targets) const
 {
   const char* editCacheTargetName = this->GetEditCacheTargetName();
   if (!editCacheTargetName) {
@@ -2635,7 +2635,7 @@
 }
 
 void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
-  std::vector<GlobalTargetInfo>& targets)
+  std::vector<GlobalTargetInfo>& targets) const
 {
   const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
   if (!rebuildCacheTargetName) {
@@ -2758,7 +2758,7 @@
   }
 }
 
-std::string cmGlobalGenerator::GetPredefinedTargetsFolder()
+std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const
 {
   cmProp prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
     "PREDEFINED_TARGETS_FOLDER");
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index b532a43..afafba9 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -14,6 +14,7 @@
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
 #include <cmext/algorithm>
 
 #include "cm_codecvt.hxx"
@@ -26,6 +27,7 @@
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetDepend.h"
+#include "cmTransformDepfile.h"
 
 #if !defined(CMAKE_BOOTSTRAP)
 #  include <cm3p/json/value.h>
@@ -452,6 +454,10 @@
   virtual bool ShouldStripResourcePath(cmMakefile*) const;
 
   virtual bool SupportsCustomCommandDepfile() const { return false; }
+  virtual cm::optional<cmDepfileFormat> DepfileFormat() const
+  {
+    return cm::nullopt;
+  }
 
   std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
 
@@ -568,8 +574,9 @@
   void AddGlobalTarget_Package(std::vector<GlobalTargetInfo>& targets);
   void AddGlobalTarget_PackageSource(std::vector<GlobalTargetInfo>& targets);
   void AddGlobalTarget_Test(std::vector<GlobalTargetInfo>& targets);
-  void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets);
-  void AddGlobalTarget_RebuildCache(std::vector<GlobalTargetInfo>& targets);
+  void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets) const;
+  void AddGlobalTarget_RebuildCache(
+    std::vector<GlobalTargetInfo>& targets) const;
   void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
   cmTarget CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
 
@@ -595,7 +602,7 @@
 
   cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;
 
-  std::string GetPredefinedTargetsFolder();
+  std::string GetPredefinedTargetsFolder() const;
 
 private:
   using TargetMap = std::unordered_map<std::string, cmTarget*>;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index c08c9cf..33bf830 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -704,7 +704,7 @@
   std::set<cmGeneratorTarget const*> temp;
   std::set<cmGeneratorTarget const*> perm;
 
-  for (auto ti : tgt) {
+  for (auto const ti : tgt) {
     bool r = VisitTarget(temp, perm, build, ti);
     if (r) {
       return r;
@@ -726,7 +726,7 @@
        * in the same order */
       OrderedTargetDependSet sortedTargets(this->GetTargetDirectDepends(ti),
                                            "");
-      for (auto& di : sortedTargets) {
+      for (auto const& di : sortedTargets) {
         if (this->VisitTarget(temp, perm, order, di)) {
           return true;
         }
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 985f430..9b27bc5 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1057,7 +1057,7 @@
   }
 }
 
-void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
+void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os) const
 {
   os << "# CMAKE generated file: DO NOT EDIT!\n"
      << "# Generated by \"" << this->GetName() << "\""
@@ -1088,7 +1088,7 @@
 
 void cmGlobalNinjaGenerator::AppendTargetOutputs(
   cmGeneratorTarget const* target, cmNinjaDeps& outputs,
-  const std::string& config, cmNinjaTargetDepends depends)
+  const std::string& config, cmNinjaTargetDepends depends) const
 {
   // for frameworks, we want the real name, not smple name
   // frameworks always appear versioned, and the build.ninja
@@ -2650,30 +2650,17 @@
 
 bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables()
 {
-  this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_DEFAULT_BUILD_TYPE");
-  this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_CROSS_CONFIGS");
-  this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_DEFAULT_CONFIGS");
-  return this->ReadCacheEntriesForBuild(*this->Makefiles.front()->GetState());
-}
-
-std::string cmGlobalNinjaMultiGenerator::GetDefaultBuildConfig() const
-{
-  return "";
-}
-
-bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
-  const cmState& state)
-{
   std::vector<std::string> configsVec;
-  cmExpandList(state.GetSafeCacheEntryValue("CMAKE_CONFIGURATION_TYPES"),
-               configsVec);
+  cmExpandList(
+    this->Makefiles.front()->GetSafeDefinition("CMAKE_CONFIGURATION_TYPES"),
+    configsVec);
   if (configsVec.empty()) {
     configsVec.emplace_back();
   }
   std::set<std::string> configs(configsVec.cbegin(), configsVec.cend());
 
   this->DefaultFileConfig =
-    state.GetSafeCacheEntryValue("CMAKE_DEFAULT_BUILD_TYPE");
+    this->Makefiles.front()->GetSafeDefinition("CMAKE_DEFAULT_BUILD_TYPE");
   if (this->DefaultFileConfig.empty()) {
     this->DefaultFileConfig = configsVec.front();
   }
@@ -2688,8 +2675,9 @@
   }
 
   std::vector<std::string> crossConfigsVec;
-  cmExpandList(state.GetSafeCacheEntryValue("CMAKE_CROSS_CONFIGS"),
-               crossConfigsVec);
+  cmExpandList(
+    this->Makefiles.front()->GetSafeDefinition("CMAKE_CROSS_CONFIGS"),
+    crossConfigsVec);
   auto crossConfigs = ListSubsetWithAll(configs, configs, crossConfigsVec);
   if (!crossConfigs) {
     std::ostringstream msg;
@@ -2702,7 +2690,7 @@
   this->CrossConfigs = *crossConfigs;
 
   auto defaultConfigsString =
-    state.GetSafeCacheEntryValue("CMAKE_DEFAULT_CONFIGS");
+    this->Makefiles.front()->GetSafeDefinition("CMAKE_DEFAULT_CONFIGS");
   if (defaultConfigsString.empty()) {
     defaultConfigsString = this->DefaultFileConfig;
   }
@@ -2736,6 +2724,11 @@
   return true;
 }
 
+std::string cmGlobalNinjaMultiGenerator::GetDefaultBuildConfig() const
+{
+  return "";
+}
+
 std::string cmGlobalNinjaMultiGenerator::OrderDependsTargetForTarget(
   cmGeneratorTarget const* target, const std::string& config) const
 {
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 884a711..94abb40 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -24,6 +24,7 @@
 #include "cmNinjaTypes.h"
 #include "cmPolicies.h"
 #include "cmStringAlgorithms.h"
+#include "cmTransformDepfile.h"
 
 class cmCustomCommand;
 class cmGeneratorTarget;
@@ -31,7 +32,6 @@
 class cmLocalGenerator;
 class cmMakefile;
 class cmOutputConverter;
-class cmState;
 class cmStateDirectory;
 class cmake;
 struct cmDocumentationEntry;
@@ -211,6 +211,10 @@
   const char* GetCleanTargetName() const override { return "clean"; }
 
   bool SupportsCustomCommandDepfile() const override { return true; }
+  cm::optional<cmDepfileFormat> DepfileFormat() const override
+  {
+    return cmDepfileFormat::GccDepfile;
+  }
 
   virtual cmGeneratedFileStream* GetImplFileStream(
     const std::string& /*config*/) const
@@ -248,7 +252,7 @@
       : GG(gg)
     {
     }
-    std::string operator()(std::string const& path)
+    std::string operator()(std::string const& path) const
     {
       return this->GG->ConvertToNinjaPath(path);
     }
@@ -319,7 +323,7 @@
 
   void AppendTargetOutputs(cmGeneratorTarget const* target,
                            cmNinjaDeps& outputs, const std::string& config,
-                           cmNinjaTargetDepends depends);
+                           cmNinjaTargetDepends depends) const;
   void AppendTargetDepends(cmGeneratorTarget const* target,
                            cmNinjaDeps& outputs, const std::string& config,
                            const std::string& fileConfig,
@@ -459,7 +463,7 @@
   void CleanMetaData();
 
   /// Write the common disclaimer text at the top of each build file.
-  void WriteDisclaimer(std::ostream& os);
+  void WriteDisclaimer(std::ostream& os) const;
 
   void WriteAssumedSourceDependencies();
 
@@ -647,8 +651,6 @@
 
   std::string GetDefaultBuildConfig() const override;
 
-  bool ReadCacheEntriesForBuild(const cmState& state) override;
-
   bool SupportsDefaultBuildType() const override { return true; }
   bool SupportsCrossConfigs() const override { return true; }
   bool SupportsDefaultConfigs() const override { return true; }
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/cmJsonObjectDictionary.h b/Source/cmJsonObjectDictionary.h
deleted file mode 100644
index 8a2b529..0000000
--- a/Source/cmJsonObjectDictionary.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include <string>
-
-// Vocabulary:
-
-static const std::string kARTIFACTS_KEY = "artifacts";
-static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
-static const std::string kCOMPILE_FLAGS_KEY = "compileFlags";
-static const std::string kCONFIGURATIONS_KEY = "configurations";
-static const std::string kDEFINES_KEY = "defines";
-static const std::string kFILE_GROUPS_KEY = "fileGroups";
-static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath";
-static const std::string kFULL_NAME_KEY = "fullName";
-static const std::string kINCLUDE_PATH_KEY = "includePath";
-static const std::string kIS_CMAKE_KEY = "isCMake";
-static const std::string kIS_GENERATED_KEY = "isGenerated";
-static const std::string kIS_SYSTEM_KEY = "isSystem";
-static const std::string kIS_TEMPORARY_KEY = "isTemporary";
-static const std::string kKEY_KEY = "key";
-static const std::string kLANGUAGE_KEY = "language";
-static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage";
-static const std::string kLINK_FLAGS_KEY = "linkFlags";
-static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags";
-static const std::string kLINK_LIBRARIES_KEY = "linkLibraries";
-static const std::string kLINK_PATH_KEY = "linkPath";
-static const std::string kNAME_KEY = "name";
-static const std::string kPATH_KEY = "path";
-static const std::string kPROJECTS_KEY = "projects";
-static const std::string kPROPERTIES_KEY = "properties";
-static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
-static const std::string kSOURCES_KEY = "sources";
-static const std::string kSYSROOT_KEY = "sysroot";
-static const std::string kTARGETS_KEY = "targets";
-static const std::string kTYPE_KEY = "type";
-static const std::string kVALUE_KEY = "value";
-static const std::string kHAS_INSTALL_RULE = "hasInstallRule";
-static const std::string kINSTALL_PATHS = "installPaths";
-static const std::string kCTEST_NAME = "ctestName";
-static const std::string kCTEST_COMMAND = "ctestCommand";
-static const std::string kCTEST_INFO = "ctestInfo";
-static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion";
-static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided";
diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx
deleted file mode 100644
index 3a7ae0c..0000000
--- a/Source/cmJsonObjects.cxx
+++ /dev/null
@@ -1,692 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmJsonObjects.h" // IWYU pragma: keep
-
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <functional>
-#include <limits>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <cmext/algorithm>
-
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
-#include "cmInstallGenerator.h"
-#include "cmInstallSubdirectoryGenerator.h"
-#include "cmInstallTargetGenerator.h"
-#include "cmJsonObjectDictionary.h"
-#include "cmJsonObjects.h"
-#include "cmLinkLineComputer.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmProperty.h"
-#include "cmPropertyMap.h"
-#include "cmSourceFile.h"
-#include "cmState.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
-#include "cmStateTypes.h"
-#include "cmStringAlgorithms.h"
-#include "cmSystemTools.h"
-#include "cmTarget.h"
-#include "cmTest.h"
-#include "cmake.h"
-
-namespace {
-
-std::vector<std::string> getConfigurations(const cmake* cm)
-{
-  std::vector<std::string> configurations;
-  const auto& makefiles = cm->GetGlobalGenerator()->GetMakefiles();
-  if (makefiles.empty()) {
-    return configurations;
-  }
-
-  return makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
-}
-
-bool hasString(const Json::Value& v, const std::string& s)
-{
-  return !v.isNull() &&
-    std::any_of(v.begin(), v.end(),
-                [s](const Json::Value& i) { return i.asString() == s; });
-}
-
-template <class T>
-Json::Value fromStringList(const T& in)
-{
-  Json::Value result = Json::arrayValue;
-  for (std::string const& i : in) {
-    result.append(i);
-  }
-  return result;
-}
-
-} // namespace
-
-void cmGetCMakeInputs(const cmGlobalGenerator* gg,
-                      const std::string& sourceDir,
-                      const std::string& buildDir,
-                      std::vector<std::string>* internalFiles,
-                      std::vector<std::string>* explicitFiles,
-                      std::vector<std::string>* tmpFiles)
-{
-  const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/';
-  auto const& makefiles = gg->GetMakefiles();
-  for (const auto& mf : makefiles) {
-    for (std::string const& lf : mf->GetListFiles()) {
-
-      const std::string startOfFile = lf.substr(0, cmakeRootDir.size());
-      const bool isInternal = (startOfFile == cmakeRootDir);
-      const bool isTemporary =
-        !isInternal && (cmHasPrefix(lf, buildDir + '/'));
-
-      std::string toAdd = lf;
-      if (!sourceDir.empty()) {
-        const std::string& relative =
-          cmSystemTools::RelativePath(sourceDir, lf);
-        if (toAdd.size() > relative.size()) {
-          toAdd = relative;
-        }
-      }
-
-      if (isInternal) {
-        if (internalFiles) {
-          internalFiles->push_back(std::move(toAdd));
-        }
-      } else {
-        if (isTemporary) {
-          if (tmpFiles) {
-            tmpFiles->push_back(std::move(toAdd));
-          }
-        } else {
-          if (explicitFiles) {
-            explicitFiles->push_back(std::move(toAdd));
-          }
-        }
-      }
-    }
-  }
-}
-
-Json::Value cmDumpCMakeInputs(const cmake* cm)
-{
-  const cmGlobalGenerator* gg = cm->GetGlobalGenerator();
-  const std::string& buildDir = cm->GetHomeOutputDirectory();
-  const std::string& sourceDir = cm->GetHomeDirectory();
-
-  std::vector<std::string> internalFiles;
-  std::vector<std::string> explicitFiles;
-  std::vector<std::string> tmpFiles;
-  cmGetCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles,
-                   &tmpFiles);
-
-  Json::Value array = Json::arrayValue;
-
-  Json::Value tmp = Json::objectValue;
-  tmp[kIS_CMAKE_KEY] = true;
-  tmp[kIS_TEMPORARY_KEY] = false;
-  tmp[kSOURCES_KEY] = fromStringList(internalFiles);
-  array.append(tmp);
-
-  tmp = Json::objectValue;
-  tmp[kIS_CMAKE_KEY] = false;
-  tmp[kIS_TEMPORARY_KEY] = false;
-  tmp[kSOURCES_KEY] = fromStringList(explicitFiles);
-  array.append(tmp);
-
-  tmp = Json::objectValue;
-  tmp[kIS_CMAKE_KEY] = false;
-  tmp[kIS_TEMPORARY_KEY] = true;
-  tmp[kSOURCES_KEY] = fromStringList(tmpFiles);
-  array.append(tmp);
-
-  return array;
-}
-
-class LanguageData
-{
-public:
-  bool operator==(const LanguageData& other) const;
-
-  void SetDefines(const std::set<std::string>& defines);
-
-  bool IsGenerated = false;
-  std::string Language;
-  std::string Flags;
-  std::vector<std::string> Defines;
-  std::vector<std::pair<std::string, bool>> IncludePathList;
-};
-
-bool LanguageData::operator==(const LanguageData& other) const
-{
-  return Language == other.Language && Defines == other.Defines &&
-    Flags == other.Flags && IncludePathList == other.IncludePathList &&
-    IsGenerated == other.IsGenerated;
-}
-
-void LanguageData::SetDefines(const std::set<std::string>& defines)
-{
-  std::vector<std::string> result;
-  result.reserve(defines.size());
-  for (std::string const& i : defines) {
-    result.push_back(i);
-  }
-  std::sort(result.begin(), result.end());
-  Defines = std::move(result);
-}
-
-namespace std {
-
-template <>
-struct hash<LanguageData>
-{
-  std::size_t operator()(const LanguageData& in) const
-  {
-    using std::hash;
-    size_t result =
-      hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
-    for (auto const& i : in.IncludePathList) {
-      result = result ^
-        (hash<std::string>()(i.first) ^
-         (i.second ? std::numeric_limits<size_t>::max() : 0));
-    }
-    for (auto const& i : in.Defines) {
-      result = result ^ hash<std::string>()(i);
-    }
-    result =
-      result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0);
-    return result;
-  }
-};
-
-} // namespace std
-
-static Json::Value DumpSourceFileGroup(const LanguageData& data,
-                                       const std::vector<std::string>& files,
-                                       const std::string& baseDir)
-{
-  Json::Value result = Json::objectValue;
-
-  if (!data.Language.empty()) {
-    result[kLANGUAGE_KEY] = data.Language;
-    if (!data.Flags.empty()) {
-      result[kCOMPILE_FLAGS_KEY] = data.Flags;
-    }
-    if (!data.IncludePathList.empty()) {
-      Json::Value includes = Json::arrayValue;
-      for (auto const& i : data.IncludePathList) {
-        Json::Value tmp = Json::objectValue;
-        tmp[kPATH_KEY] = i.first;
-        if (i.second) {
-          tmp[kIS_SYSTEM_KEY] = i.second;
-        }
-        includes.append(tmp);
-      }
-      result[kINCLUDE_PATH_KEY] = includes;
-    }
-    if (!data.Defines.empty()) {
-      result[kDEFINES_KEY] = fromStringList(data.Defines);
-    }
-  }
-
-  result[kIS_GENERATED_KEY] = data.IsGenerated;
-
-  Json::Value sourcesValue = Json::arrayValue;
-  for (auto const& i : files) {
-    const std::string relPath = cmSystemTools::RelativePath(baseDir, i);
-    sourcesValue.append(relPath.size() < i.size() ? relPath : i);
-  }
-
-  result[kSOURCES_KEY] = sourcesValue;
-  return result;
-}
-
-static Json::Value DumpSourceFilesList(
-  cmGeneratorTarget* target, const std::string& config,
-  const std::map<std::string, LanguageData>& languageDataMap)
-{
-  // Collect sourcefile groups:
-
-  std::vector<cmSourceFile*> files;
-  target->GetSourceFiles(files, config);
-
-  std::unordered_map<LanguageData, std::vector<std::string>> fileGroups;
-  for (cmSourceFile* file : files) {
-    LanguageData fileData;
-    fileData.Language = file->GetOrDetermineLanguage();
-    if (!fileData.Language.empty()) {
-      const LanguageData& ld = languageDataMap.at(fileData.Language);
-      cmLocalGenerator* lg = target->GetLocalGenerator();
-      cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
-                                                        fileData.Language);
-
-      std::string compileFlags = ld.Flags;
-      const std::string COMPILE_FLAGS("COMPILE_FLAGS");
-      if (cmProp cflags = file->GetProperty(COMPILE_FLAGS)) {
-        lg->AppendFlags(compileFlags,
-                        genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
-      }
-      const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
-      if (cmProp coptions = file->GetProperty(COMPILE_OPTIONS)) {
-        lg->AppendCompileOptions(
-          compileFlags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
-      }
-      fileData.Flags = compileFlags;
-
-      // Add include directories from source file properties.
-      std::vector<std::string> includes;
-
-      const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
-      if (cmProp cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) {
-        const std::string& evaluatedIncludes =
-          genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES);
-        lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file);
-
-        for (const auto& include : includes) {
-          fileData.IncludePathList.emplace_back(
-            include,
-            target->IsSystemIncludeDirectory(include, config,
-                                             fileData.Language));
-        }
-      }
-
-      fileData.IncludePathList.insert(fileData.IncludePathList.end(),
-                                      ld.IncludePathList.begin(),
-                                      ld.IncludePathList.end());
-
-      const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
-      std::set<std::string> defines;
-      if (cmProp defs = file->GetProperty(COMPILE_DEFINITIONS)) {
-        lg->AppendDefines(
-          defines, genexInterpreter.Evaluate(*defs, COMPILE_DEFINITIONS));
-      }
-
-      const std::string defPropName =
-        "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
-      if (cmProp config_defs = file->GetProperty(defPropName)) {
-        lg->AppendDefines(
-          defines,
-          genexInterpreter.Evaluate(*config_defs, COMPILE_DEFINITIONS));
-      }
-
-      defines.insert(ld.Defines.begin(), ld.Defines.end());
-
-      fileData.SetDefines(defines);
-    }
-
-    fileData.IsGenerated = file->GetIsGenerated();
-    std::vector<std::string>& groupFileList = fileGroups[fileData];
-    groupFileList.push_back(file->ResolveFullPath());
-  }
-
-  const std::string& baseDir = target->Makefile->GetCurrentSourceDirectory();
-  Json::Value result = Json::arrayValue;
-  for (auto const& it : fileGroups) {
-    Json::Value group = DumpSourceFileGroup(it.first, it.second, baseDir);
-    if (!group.isNull()) {
-      result.append(group);
-    }
-  }
-
-  return result;
-}
-
-static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo,
-                                 const std::string& config)
-{
-  Json::Value result = Json::objectValue;
-  result[kCTEST_NAME] = testInfo->GetName();
-
-  // Concat command entries together. After the first should be the arguments
-  // for the command
-  std::string command;
-  for (auto const& cmd : testInfo->GetCommand()) {
-    command.append(cmd);
-    command.append(" ");
-  }
-
-  // Remove any config specific variables from the output.
-  result[kCTEST_COMMAND] =
-    cmGeneratorExpression::Evaluate(command, lg, config);
-
-  // Build up the list of properties that may have been specified
-  Json::Value properties = Json::arrayValue;
-  for (auto& prop : testInfo->GetProperties().GetList()) {
-    Json::Value entry = Json::objectValue;
-    entry[kKEY_KEY] = prop.first;
-
-    // Remove config variables from the value too.
-    entry[kVALUE_KEY] =
-      cmGeneratorExpression::Evaluate(prop.second, lg, config);
-    properties.append(entry);
-  }
-  result[kPROPERTIES_KEY] = properties;
-
-  return result;
-}
-
-static void DumpMakefileTests(cmLocalGenerator* lg, const std::string& config,
-                              Json::Value* result)
-{
-  auto mf = lg->GetMakefile();
-  std::vector<cmTest*> tests;
-  mf->GetTests(config, tests);
-  for (auto test : tests) {
-    Json::Value tmp = DumpCTestInfo(lg, test, config);
-    if (!tmp.isNull()) {
-      result->append(tmp);
-    }
-  }
-}
-
-static Json::Value DumpCTestProjectList(const cmake* cm,
-                                        std::string const& config)
-{
-  Json::Value result = Json::arrayValue;
-
-  auto globalGen = cm->GetGlobalGenerator();
-
-  for (const auto& projectIt : globalGen->GetProjectMap()) {
-    Json::Value pObj = Json::objectValue;
-    pObj[kNAME_KEY] = projectIt.first;
-
-    Json::Value tests = Json::arrayValue;
-
-    // Gather tests for every generator
-    for (const auto& lg : projectIt.second) {
-      // Make sure they're generated.
-      lg->GenerateTestFiles();
-      DumpMakefileTests(lg, config, &tests);
-    }
-
-    pObj[kCTEST_INFO] = tests;
-
-    result.append(pObj);
-  }
-
-  return result;
-}
-
-static Json::Value DumpCTestConfiguration(const cmake* cm,
-                                          const std::string& config)
-{
-  Json::Value result = Json::objectValue;
-  result[kNAME_KEY] = config;
-
-  result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config);
-
-  return result;
-}
-
-static Json::Value DumpCTestConfigurationsList(const cmake* cm)
-{
-  Json::Value result = Json::arrayValue;
-
-  for (const std::string& c : getConfigurations(cm)) {
-    result.append(DumpCTestConfiguration(cm, c));
-  }
-
-  return result;
-}
-
-Json::Value cmDumpCTestInfo(const cmake* cm)
-{
-  Json::Value result = Json::objectValue;
-  result[kCONFIGURATIONS_KEY] = DumpCTestConfigurationsList(cm);
-  return result;
-}
-
-static Json::Value DumpTarget(cmGeneratorTarget* target,
-                              const std::string& config)
-{
-  cmLocalGenerator* lg = target->GetLocalGenerator();
-
-  const cmStateEnums::TargetType type = target->GetType();
-  const std::string typeName = cmState::GetTargetTypeName(type);
-
-  Json::Value ttl = Json::arrayValue;
-  ttl.append("EXECUTABLE");
-  ttl.append("STATIC_LIBRARY");
-  ttl.append("SHARED_LIBRARY");
-  ttl.append("MODULE_LIBRARY");
-  ttl.append("OBJECT_LIBRARY");
-  ttl.append("UTILITY");
-  ttl.append("INTERFACE_LIBRARY");
-
-  if (!hasString(ttl, typeName) || target->IsImported()) {
-    return Json::Value();
-  }
-
-  Json::Value result = Json::objectValue;
-  result[kNAME_KEY] = target->GetName();
-  result[kIS_GENERATOR_PROVIDED_KEY] =
-    target->Target->GetIsGeneratorProvided();
-  result[kTYPE_KEY] = typeName;
-  result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory();
-  result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory();
-
-  if (type == cmStateEnums::INTERFACE_LIBRARY) {
-    return result;
-  }
-
-  result[kFULL_NAME_KEY] = target->GetFullName(config);
-
-  if (target->Target->GetHaveInstallRule()) {
-    result[kHAS_INSTALL_RULE] = true;
-
-    Json::Value installPaths = Json::arrayValue;
-    for (const auto& installGenerator :
-         target->Makefile->GetInstallGenerators()) {
-      auto installTargetGenerator =
-        dynamic_cast<cmInstallTargetGenerator*>(installGenerator.get());
-      if (installTargetGenerator != nullptr &&
-          installTargetGenerator->GetTarget()->Target == target->Target) {
-        auto dest = installTargetGenerator->GetDestination(config);
-
-        std::string installPath;
-        if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) {
-          installPath = dest;
-        } else {
-          installPath = cmStrCat(
-            target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"), '/',
-            dest);
-        }
-
-        installPaths.append(installPath);
-      }
-    }
-
-    result[kINSTALL_PATHS] = installPaths;
-  }
-
-  if (target->HaveWellDefinedOutputFiles()) {
-    Json::Value artifacts = Json::arrayValue;
-    artifacts.append(
-      target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
-    if (target->HasImportLibrary(config)) {
-      artifacts.append(
-        target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
-    }
-    if (target->IsDLLPlatform()) {
-      const cmGeneratorTarget::OutputInfo* output =
-        target->GetOutputInfo(config);
-      if (output && !output->PdbDir.empty()) {
-        artifacts.append(output->PdbDir + '/' + target->GetPDBName(config));
-      }
-    }
-    result[kARTIFACTS_KEY] = artifacts;
-
-    result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config);
-
-    std::string linkLibs;
-    std::string linkFlags;
-    std::string linkLanguageFlags;
-    std::string frameworkPath;
-    std::string linkPath;
-    cmLinkLineComputer linkLineComputer(lg,
-                                        lg->GetStateSnapshot().GetDirectory());
-    lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
-                       linkFlags, frameworkPath, linkPath, target);
-
-    linkLibs = cmTrimWhitespace(linkLibs);
-    linkFlags = cmTrimWhitespace(linkFlags);
-    linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
-    frameworkPath = cmTrimWhitespace(frameworkPath);
-    linkPath = cmTrimWhitespace(linkPath);
-
-    if (!cmTrimWhitespace(linkLibs).empty()) {
-      result[kLINK_LIBRARIES_KEY] = linkLibs;
-    }
-    if (!cmTrimWhitespace(linkFlags).empty()) {
-      result[kLINK_FLAGS_KEY] = linkFlags;
-    }
-    if (!cmTrimWhitespace(linkLanguageFlags).empty()) {
-      result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
-    }
-    if (!frameworkPath.empty()) {
-      result[kFRAMEWORK_PATH_KEY] = frameworkPath;
-    }
-    if (!linkPath.empty()) {
-      result[kLINK_PATH_KEY] = linkPath;
-    }
-    const std::string sysroot =
-      lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT");
-    if (!sysroot.empty()) {
-      result[kSYSROOT_KEY] = sysroot;
-    }
-  }
-
-  std::set<std::string> languages;
-  target->GetLanguages(languages, config);
-  std::map<std::string, LanguageData> languageDataMap;
-
-  for (std::string const& lang : languages) {
-    LanguageData& ld = languageDataMap[lang];
-    ld.Language = lang;
-    lg->GetTargetCompileFlags(target, config, lang, ld.Flags);
-    std::set<std::string> defines;
-    lg->GetTargetDefines(target, config, lang, defines);
-    ld.SetDefines(defines);
-    std::vector<std::string> includePathList;
-    lg->GetIncludeDirectories(includePathList, target, lang, config);
-    for (std::string const& i : includePathList) {
-      ld.IncludePathList.emplace_back(
-        i, target->IsSystemIncludeDirectory(i, config, lang));
-    }
-  }
-
-  Json::Value sourceGroupsValue =
-    DumpSourceFilesList(target, config, languageDataMap);
-  if (!sourceGroupsValue.empty()) {
-    result[kFILE_GROUPS_KEY] = sourceGroupsValue;
-  }
-
-  return result;
-}
-
-static Json::Value DumpTargetsList(
-  const std::vector<cmLocalGenerator*>& generators, const std::string& config)
-{
-  Json::Value result = Json::arrayValue;
-
-  std::vector<cmGeneratorTarget*> targetList;
-  for (auto const& lgIt : generators) {
-    cm::append(targetList, lgIt->GetGeneratorTargets());
-  }
-  std::sort(targetList.begin(), targetList.end());
-
-  for (cmGeneratorTarget* target : targetList) {
-    Json::Value tmp = DumpTarget(target, config);
-    if (!tmp.isNull()) {
-      result.append(tmp);
-    }
-  }
-
-  return result;
-}
-
-static Json::Value DumpProjectList(const cmake* cm, std::string const& config)
-{
-  Json::Value result = Json::arrayValue;
-
-  auto globalGen = cm->GetGlobalGenerator();
-
-  for (auto const& projectIt : globalGen->GetProjectMap()) {
-    Json::Value pObj = Json::objectValue;
-    pObj[kNAME_KEY] = projectIt.first;
-
-    // All Projects must have at least one local generator
-    assert(!projectIt.second.empty());
-    const cmLocalGenerator* lg = projectIt.second.at(0);
-
-    // Project structure information:
-    const cmMakefile* mf = lg->GetMakefile();
-    auto minVersion = mf->GetSafeDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
-    pObj[kMINIMUM_CMAKE_VERSION] = minVersion;
-    pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
-    pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
-    pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
-
-    // For a project-level install rule it might be defined in any of its
-    // associated generators.
-    bool hasInstallRule = false;
-    for (const auto generator : projectIt.second) {
-      for (const auto& installGen :
-           generator->GetMakefile()->GetInstallGenerators()) {
-        if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen.get())) {
-          hasInstallRule = true;
-          break;
-        }
-      }
-
-      if (hasInstallRule) {
-        break;
-      }
-    }
-
-    pObj[kHAS_INSTALL_RULE] = hasInstallRule;
-
-    result.append(pObj);
-  }
-
-  return result;
-}
-
-static Json::Value DumpConfiguration(const cmake* cm,
-                                     const std::string& config)
-{
-  Json::Value result = Json::objectValue;
-  result[kNAME_KEY] = config;
-
-  result[kPROJECTS_KEY] = DumpProjectList(cm, config);
-
-  return result;
-}
-
-static Json::Value DumpConfigurationsList(const cmake* cm)
-{
-  Json::Value result = Json::arrayValue;
-
-  for (std::string const& c : getConfigurations(cm)) {
-    result.append(DumpConfiguration(cm, c));
-  }
-
-  return result;
-}
-
-Json::Value cmDumpCodeModel(const cmake* cm)
-{
-  Json::Value result = Json::objectValue;
-  result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(cm);
-  return result;
-}
diff --git a/Source/cmJsonObjects.h b/Source/cmJsonObjects.h
deleted file mode 100644
index 80a4834..0000000
--- a/Source/cmJsonObjects.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-#include <vector>
-
-#include <cm3p/json/value.h>
-
-class cmake;
-class cmGlobalGenerator;
-
-extern void cmGetCMakeInputs(const cmGlobalGenerator* gg,
-                             const std::string& sourceDir,
-                             const std::string& buildDir,
-                             std::vector<std::string>* internalFiles,
-                             std::vector<std::string>* explicitFiles,
-                             std::vector<std::string>* tmpFiles);
-
-extern Json::Value cmDumpCodeModel(const cmake* cm);
-extern Json::Value cmDumpCTestInfo(const cmake* cm);
-extern Json::Value cmDumpCMakeInputs(const cmake* cm);
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4e6010c..47e10e0 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -279,7 +279,7 @@
                    });
 }
 
-void cmLocalGenerator::TraceDependencies()
+void cmLocalGenerator::TraceDependencies() const
 {
   // Generate the rule files for each target.
   const auto& targets = this->GetGeneratorTargets();
@@ -3210,7 +3210,7 @@
 }
 
 std::string cmLocalGenerator::ConstructComment(
-  cmCustomCommandGenerator const& ccg, const char* default_comment)
+  cmCustomCommandGenerator const& ccg, const char* default_comment) const
 {
   // Check for a comment provided with the command.
   if (ccg.GetComment()) {
@@ -3918,10 +3918,35 @@
     cc->SetJobPool(job_pool);
     file->SetCustomCommand(std::move(cc));
 
-    mf->AddSourceOutputs(file, outputs, byproducts);
+    lg.AddSourceOutputs(file, outputs, byproducts);
   }
   return file;
 }
+
+bool AnyOutputMatches(const std::string& name,
+                      const std::vector<std::string>& outputs)
+{
+  for (std::string const& output : outputs) {
+    std::string::size_type pos = output.rfind(name);
+    // If the output matches exactly
+    if (pos != std::string::npos && pos == output.size() - name.size() &&
+        (pos == 0 || output[pos - 1] == '/')) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool AnyTargetCommandOutputMatches(
+  const std::string& name, const std::vector<cmCustomCommand>& commands)
+{
+  for (cmCustomCommand const& command : commands) {
+    if (AnyOutputMatches(name, command.GetByproducts())) {
+      return true;
+    }
+  }
+  return false;
+}
 }
 
 namespace detail {
@@ -3937,8 +3962,6 @@
                               const std::string& job_pool,
                               bool command_expand_lists, bool stdPipesUTF8)
 {
-  cmMakefile* mf = lg.GetMakefile();
-
   // Always create the byproduct sources and mark them generated.
   CreateGeneratedSources(lg, byproducts, origin, lfbt);
 
@@ -3964,7 +3987,7 @@
       break;
   }
 
-  mf->AddTargetByproducts(target, byproducts);
+  lg.AddTargetByproducts(target, byproducts);
 }
 
 cmSourceFile* AddCustomCommandToOutput(
@@ -3996,7 +4019,7 @@
                                  const cmCustomCommandLines& commandLines)
 {
   // Lookup an existing command.
-  if (cmSourceFile* sf = lg.GetMakefile()->GetSourceFileWithOutput(output)) {
+  if (cmSourceFile* sf = lg.GetSourceFileWithOutput(output)) {
     if (cmCustomCommand* cc = sf->GetCustomCommand()) {
       cc->AppendCommands(commandLines);
       cc->AppendDepends(depends);
@@ -4008,7 +4031,7 @@
   // No existing command found.
   lg.GetCMakeInstance()->IssueMessage(
     MessageType::FATAL_ERROR,
-    cmStrCat("Attempt to append to output\n  ", output,
+    cmStrCat("Attempt to APPEND to custom command with output\n  ", output,
              "\nwhich is not already a custom command output."),
     lfbt);
 }
@@ -4040,7 +4063,7 @@
     /*replace=*/false, escapeOldStyle, uses_terminal, command_expand_lists,
     /*depfile=*/"", job_pool, stdPipesUTF8);
   if (rule) {
-    lg.GetMakefile()->AddTargetByproducts(target, byproducts);
+    lg.AddTargetByproducts(target, byproducts);
   }
 
   if (!force.NameCMP0049.empty()) {
@@ -4088,3 +4111,166 @@
   return computedObjects;
 }
 }
+
+cmSourcesWithOutput cmLocalGenerator::GetSourcesWithOutput(
+  const std::string& name) const
+{
+  // Linear search?  Also see GetSourceFileWithOutput for detail.
+  if (!cmSystemTools::FileIsFullPath(name)) {
+    cmSourcesWithOutput sources;
+    sources.Target = this->LinearGetTargetWithOutput(name);
+    sources.Source = this->LinearGetSourceFileWithOutput(
+      name, cmSourceOutputKind::OutputOrByproduct, sources.SourceIsByproduct);
+    return sources;
+  }
+  // Otherwise we use an efficient lookup map.
+  auto o = this->OutputToSource.find(name);
+  if (o != this->OutputToSource.end()) {
+    return o->second.Sources;
+  }
+  return {};
+}
+
+cmSourceFile* cmLocalGenerator::GetSourceFileWithOutput(
+  const std::string& name, cmSourceOutputKind kind) const
+{
+  // If the queried path is not absolute we use the backward compatible
+  // linear-time search for an output with a matching suffix.
+  if (!cmSystemTools::FileIsFullPath(name)) {
+    bool byproduct = false;
+    return this->LinearGetSourceFileWithOutput(name, kind, byproduct);
+  }
+  // Otherwise we use an efficient lookup map.
+  auto o = this->OutputToSource.find(name);
+  if (o != this->OutputToSource.end() &&
+      (!o->second.Sources.SourceIsByproduct ||
+       kind == cmSourceOutputKind::OutputOrByproduct)) {
+    // Source file could also be null pointer for example if we found the
+    // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD
+    // command of a target, or a not yet created custom command.
+    return o->second.Sources.Source;
+  }
+  return nullptr;
+}
+
+void cmLocalGenerator::AddTargetByproducts(
+  cmTarget* target, const std::vector<std::string>& byproducts)
+{
+  for (std::string const& o : byproducts) {
+    this->UpdateOutputToSourceMap(o, target);
+  }
+}
+
+void cmLocalGenerator::AddSourceOutputs(
+  cmSourceFile* source, const std::vector<std::string>& outputs,
+  const std::vector<std::string>& byproducts)
+{
+  for (std::string const& o : outputs) {
+    this->UpdateOutputToSourceMap(o, source, false);
+  }
+  for (std::string const& o : byproducts) {
+    this->UpdateOutputToSourceMap(o, source, true);
+  }
+}
+
+void cmLocalGenerator::UpdateOutputToSourceMap(std::string const& byproduct,
+                                               cmTarget* target)
+{
+  SourceEntry entry;
+  entry.Sources.Target = target;
+
+  auto pr = this->OutputToSource.emplace(byproduct, entry);
+  if (!pr.second) {
+    SourceEntry& current = pr.first->second;
+    // Has the target already been set?
+    if (!current.Sources.Target) {
+      current.Sources.Target = target;
+    } else {
+      // Multiple custom commands/targets produce the same output (source file
+      // or target).  See also comment in other UpdateOutputToSourceMap
+      // overload.
+      //
+      // TODO: Warn the user about this case.
+    }
+  }
+}
+
+void cmLocalGenerator::UpdateOutputToSourceMap(std::string const& output,
+                                               cmSourceFile* source,
+                                               bool byproduct)
+{
+  SourceEntry entry;
+  entry.Sources.Source = source;
+  entry.Sources.SourceIsByproduct = byproduct;
+
+  auto pr = this->OutputToSource.emplace(output, entry);
+  if (!pr.second) {
+    SourceEntry& current = pr.first->second;
+    // Outputs take precedence over byproducts
+    if (!current.Sources.Source ||
+        (current.Sources.SourceIsByproduct && !byproduct)) {
+      current.Sources.Source = source;
+      current.Sources.SourceIsByproduct = false;
+    } else {
+      // Multiple custom commands produce the same output but may
+      // be attached to a different source file (MAIN_DEPENDENCY).
+      // LinearGetSourceFileWithOutput would return the first one,
+      // so keep the mapping for the first one.
+      //
+      // TODO: Warn the user about this case.  However, the VS 8 generator
+      // triggers it for separate generate.stamp rules in ZERO_CHECK and
+      // individual targets.
+    }
+  }
+}
+
+cmTarget* cmLocalGenerator::LinearGetTargetWithOutput(
+  const std::string& name) const
+{
+  // We go through the ordered vector of targets to get reproducible results
+  // should multiple names match.
+  for (cmTarget* t : this->Makefile->GetOrderedTargets()) {
+    // Does the output of any command match the source file name?
+    if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
+      return t;
+    }
+    if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
+      return t;
+    }
+    if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
+      return t;
+    }
+  }
+  return nullptr;
+}
+
+cmSourceFile* cmLocalGenerator::LinearGetSourceFileWithOutput(
+  const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
+{
+  // Outputs take precedence over byproducts.
+  byproduct = false;
+  cmSourceFile* fallback = nullptr;
+
+  // Look through all the source files that have custom commands and see if the
+  // custom command has the passed source file as an output.
+  for (const auto& src : this->Makefile->GetSourceFiles()) {
+    // Does this source file have a custom command?
+    if (src->GetCustomCommand()) {
+      // Does the output of the custom command match the source file name?
+      if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
+        // Return the first matching output.
+        return src.get();
+      }
+      if (kind == cmSourceOutputKind::OutputOrByproduct) {
+        if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
+          // Do not return the source yet as there might be a matching output.
+          fallback = src.get();
+        }
+      }
+    }
+  }
+
+  // Did we find a byproduct?
+  byproduct = fallback != nullptr;
+  return fallback;
+}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 22d3599..b8bd3bc 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -36,6 +36,24 @@
 class cmTarget;
 class cmake;
 
+/** Flag if byproducts shall also be considered.  */
+enum class cmSourceOutputKind
+{
+  OutputOnly,
+  OutputOrByproduct
+};
+
+/** Target and source file which have a specific output.  */
+struct cmSourcesWithOutput
+{
+  /** Target with byproduct.  */
+  cmTarget* Target = nullptr;
+
+  /** Source file with output or byproduct.  */
+  cmSourceFile* Source = nullptr;
+  bool SourceIsByproduct = false;
+};
+
 /** \class cmLocalGenerator
  * \brief Create required build files for a directory.
  *
@@ -59,7 +77,7 @@
   /**
    * Calls TraceVSDependencies() on all targets of this generator.
    */
-  void TraceDependencies();
+  void TraceDependencies() const;
 
   virtual void AddHelperCommands() {}
 
@@ -337,6 +355,34 @@
     bool command_expand_lists = false, const std::string& job_pool = "",
     bool stdPipesUTF8 = false);
 
+  /**
+   * Add target byproducts.
+   */
+  void AddTargetByproducts(cmTarget* target,
+                           const std::vector<std::string>& byproducts);
+
+  /**
+   * Add source file outputs.
+   */
+  void AddSourceOutputs(cmSourceFile* source,
+                        const std::vector<std::string>& outputs,
+                        const std::vector<std::string>& byproducts);
+
+  /**
+   * Return the target if the provided source name is a byproduct of a utility
+   * target or a PRE_BUILD, PRE_LINK, or POST_BUILD command.
+   * Return the source file which has the provided source name as output.
+   */
+  cmSourcesWithOutput GetSourcesWithOutput(const std::string& name) const;
+
+  /**
+   * Is there a source file that has the provided source name as an output?
+   * If so then return it.
+   */
+  cmSourceFile* GetSourceFileWithOutput(
+    const std::string& name,
+    cmSourceOutputKind kind = cmSourceOutputKind::OutputOnly) const;
+
   std::string GetProjectName() const;
 
   /** Compute the language used to compile the given source file.  */
@@ -405,7 +451,7 @@
                                   const std::string& fname);
   /** Construct a comment for a custom command.  */
   std::string ConstructComment(cmCustomCommandGenerator const& ccg,
-                               const char* default_comment = "");
+                               const char* default_comment = "") const;
   // Compute object file names.
   std::string GetObjectFileNameWithoutTarget(
     const cmSourceFile& source, std::string const& dir_max,
@@ -532,6 +578,33 @@
   bool BackwardsCompatibilityFinal;
 
 private:
+  /**
+   * See LinearGetSourceFileWithOutput for background information
+   */
+  cmTarget* LinearGetTargetWithOutput(const std::string& name) const;
+
+  /**
+   * Generalized old version of GetSourceFileWithOutput kept for
+   * backward-compatibility. It implements a linear search and supports
+   * relative file paths. It is used as a fall back by GetSourceFileWithOutput
+   * and GetSourcesWithOutput.
+   */
+  cmSourceFile* LinearGetSourceFileWithOutput(const std::string& name,
+                                              cmSourceOutputKind kind,
+                                              bool& byproduct) const;
+  struct SourceEntry
+  {
+    cmSourcesWithOutput Sources;
+  };
+
+  // A map for fast output to input look up.
+  using OutputToSourceMap = std::unordered_map<std::string, SourceEntry>;
+  OutputToSourceMap OutputToSource;
+
+  void UpdateOutputToSourceMap(std::string const& byproduct, cmTarget* target);
+  void UpdateOutputToSourceMap(std::string const& output, cmSourceFile* source,
+                               bool byproduct);
+
   void AddSharedFlags(std::string& flags, const std::string& lang,
                       bool shared);
   bool GetShouldUseOldFlags(bool shared, const std::string& lang) const;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index ad782ee..ce85320 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -22,7 +22,9 @@
 #include "cmGlobalNinjaGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmMessageType.h"
 #include "cmNinjaTargetGenerator.h"
+#include "cmPolicies.h"
 #include "cmProperty.h"
 #include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
@@ -573,7 +575,20 @@
     return;
   }
 
-  cmCustomCommandGenerator ccg(*cc, config, this);
+  bool transformDepfile = false;
+  auto cmp0116 = this->GetPolicyStatus(cmPolicies::CMP0116);
+  switch (cmp0116) {
+    case cmPolicies::OLD:
+    case cmPolicies::WARN:
+      break;
+    case cmPolicies::REQUIRED_IF_USED:
+    case cmPolicies::REQUIRED_ALWAYS:
+    case cmPolicies::NEW:
+      transformDepfile = true;
+      break;
+  }
+
+  cmCustomCommandGenerator ccg(*cc, config, this, transformDepfile);
 
   const std::vector<std::string>& outputs = ccg.GetOutputs();
   const std::vector<std::string>& byproducts = ccg.GetByproducts();
@@ -623,10 +638,36 @@
     cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
     customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
 
+    std::string depfile = cc->GetDepfile();
+    if (!depfile.empty()) {
+      switch (cmp0116) {
+        case cmPolicies::WARN:
+          if (this->GetCurrentBinaryDirectory() !=
+                this->GetBinaryDirectory() ||
+              this->Makefile->PolicyOptionalWarningEnabled(
+                "CMAKE_POLICY_WARNING_CMP0116")) {
+            this->GetCMakeInstance()->IssueMessage(
+              MessageType::AUTHOR_WARNING,
+              cmPolicies::GetPolicyWarning(cmPolicies::CMP0116),
+              cc->GetBacktrace());
+          }
+          CM_FALLTHROUGH;
+        case cmPolicies::OLD:
+          break;
+        case cmPolicies::REQUIRED_IF_USED:
+        case cmPolicies::REQUIRED_ALWAYS:
+        case cmPolicies::NEW:
+          cmSystemTools::MakeDirectory(
+            cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles/d"));
+          depfile = ccg.GetInternalDepfile();
+          break;
+      }
+    }
+
     gg->WriteCustomCommandBuild(
       this->BuildCommandLine(cmdLines, customStep),
       this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
-      cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(),
+      depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
       /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config,
       ninjaDeps, orderOnlyDeps);
   }
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 8286d67..5edca2a 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -178,11 +178,11 @@
   /** Get whether to create rules to generate preprocessed and
       assembly sources.  This could be converted to a variable lookup
       later.  */
-  bool GetCreatePreprocessedSourceRules()
+  bool GetCreatePreprocessedSourceRules() const
   {
     return !this->SkipPreprocessedSourceRules;
   }
-  bool GetCreateAssemblySourceRules()
+  bool GetCreateAssemblySourceRules() const
   {
     return !this->SkipAssemblySourceRules;
   }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 0e4f888..6d1868c 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -939,8 +939,6 @@
     action.Value(lg, action.Backtrace);
   }
   this->GeneratorActionsInvoked = true;
-  this->DelayedOutputFiles.clear();
-  this->DelayedOutputFilesHaveGenex = false;
 
   // go through all configured files and see which ones still exist.
   // we don't want cmake to re-run if a configured file is created and deleted
@@ -1104,7 +1102,7 @@
   }
 
   // Always create the byproduct sources and mark them generated.
-  this->CreateGeneratedByproducts(byproducts);
+  this->CreateGeneratedOutputs(byproducts);
 
   // Strings could be moved into the callback function with C++14.
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -1163,7 +1161,7 @@
 
   // Always create the output sources and mark them generated.
   this->CreateGeneratedOutputs(outputs);
-  this->CreateGeneratedByproducts(byproducts);
+  this->CreateGeneratedOutputs(byproducts);
 
   // Strings could be moved into the callback function with C++14.
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -1247,16 +1245,11 @@
   }
 }
 
-bool cmMakefile::AppendCustomCommandToOutput(
+void cmMakefile::AppendCustomCommandToOutput(
   const std::string& output, const std::vector<std::string>& depends,
   const cmImplicitDependsList& implicit_depends,
   const cmCustomCommandLines& commandLines)
 {
-  // Check as good as we can if there will be a command for this output.
-  if (!this->MightHaveCustomCommand(output)) {
-    return false;
-  }
-
   // Validate custom commands.
   if (this->ValidateCustomCommand(commandLines)) {
     // Dispatch command creation to allow generator expressions in outputs.
@@ -1267,8 +1260,6 @@
                                             implicit_depends, commandLines);
       });
   }
-
-  return true;
 }
 
 cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target)
@@ -1313,7 +1304,7 @@
   this->GetOrCreateGeneratedSource(force.Name);
 
   // Always create the byproduct sources and mark them generated.
-  this->CreateGeneratedByproducts(byproducts);
+  this->CreateGeneratedOutputs(byproducts);
 
   // Strings could be moved into the callback function with C++14.
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -2038,7 +2029,7 @@
 #endif
 }
 
-void cmMakefile::RemoveCacheDefinition(const std::string& name)
+void cmMakefile::RemoveCacheDefinition(const std::string& name) const
 {
   this->GetState()->RemoveCacheEntry(name);
 }
@@ -2154,213 +2145,6 @@
 }
 
 namespace {
-bool AnyOutputMatches(const std::string& name,
-                      const std::vector<std::string>& outputs)
-{
-  for (std::string const& output : outputs) {
-    std::string::size_type pos = output.rfind(name);
-    // If the output matches exactly
-    if (pos != std::string::npos && pos == output.size() - name.size() &&
-        (pos == 0 || output[pos - 1] == '/')) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool AnyTargetCommandOutputMatches(
-  const std::string& name, const std::vector<cmCustomCommand>& commands)
-{
-  for (cmCustomCommand const& command : commands) {
-    if (AnyOutputMatches(name, command.GetByproducts())) {
-      return true;
-    }
-  }
-  return false;
-}
-}
-
-cmTarget* cmMakefile::LinearGetTargetWithOutput(const std::string& name) const
-{
-  // We go through the ordered vector of targets to get reproducible results
-  // should multiple names match.
-  for (cmTarget* t : this->OrderedTargets) {
-    // Does the output of any command match the source file name?
-    if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
-      return t;
-    }
-    if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
-      return t;
-    }
-    if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
-      return t;
-    }
-  }
-  return nullptr;
-}
-
-cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput(
-  const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
-{
-  // Outputs take precedence over byproducts.
-  byproduct = false;
-  cmSourceFile* fallback = nullptr;
-
-  // Look through all the source files that have custom commands and see if the
-  // custom command has the passed source file as an output.
-  for (const auto& src : this->SourceFiles) {
-    // Does this source file have a custom command?
-    if (src->GetCustomCommand()) {
-      // Does the output of the custom command match the source file name?
-      if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
-        // Return the first matching output.
-        return src.get();
-      }
-      if (kind == cmSourceOutputKind::OutputOrByproduct) {
-        if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
-          // Do not return the source yet as there might be a matching output.
-          fallback = src.get();
-        }
-      }
-    }
-  }
-
-  // Did we find a byproduct?
-  byproduct = fallback != nullptr;
-  return fallback;
-}
-
-cmSourcesWithOutput cmMakefile::GetSourcesWithOutput(
-  const std::string& name) const
-{
-  // Linear search?  Also see GetSourceFileWithOutput for detail.
-  if (!cmSystemTools::FileIsFullPath(name)) {
-    cmSourcesWithOutput sources;
-    sources.Target = this->LinearGetTargetWithOutput(name);
-    sources.Source = this->LinearGetSourceFileWithOutput(
-      name, cmSourceOutputKind::OutputOrByproduct, sources.SourceIsByproduct);
-    return sources;
-  }
-  // Otherwise we use an efficient lookup map.
-  auto o = this->OutputToSource.find(name);
-  if (o != this->OutputToSource.end()) {
-    return o->second.Sources;
-  }
-  return {};
-}
-
-cmSourceFile* cmMakefile::GetSourceFileWithOutput(
-  const std::string& name, cmSourceOutputKind kind) const
-{
-  // If the queried path is not absolute we use the backward compatible
-  // linear-time search for an output with a matching suffix.
-  if (!cmSystemTools::FileIsFullPath(name)) {
-    bool byproduct = false;
-    return this->LinearGetSourceFileWithOutput(name, kind, byproduct);
-  }
-  // Otherwise we use an efficient lookup map.
-  auto o = this->OutputToSource.find(name);
-  if (o != this->OutputToSource.end() &&
-      (!o->second.Sources.SourceIsByproduct ||
-       kind == cmSourceOutputKind::OutputOrByproduct)) {
-    // Source file could also be null pointer for example if we found the
-    // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD
-    // command of a target, or a not yet created custom command.
-    return o->second.Sources.Source;
-  }
-  return nullptr;
-}
-
-bool cmMakefile::MightHaveCustomCommand(const std::string& name) const
-{
-  if (this->DelayedOutputFilesHaveGenex ||
-      cmGeneratorExpression::Find(name) != std::string::npos) {
-    // Could be more restrictive, but for now we assume that there could always
-    // be a match when generator expressions are involved.
-    return true;
-  }
-  // Also see LinearGetSourceFileWithOutput.
-  if (!cmSystemTools::FileIsFullPath(name)) {
-    return AnyOutputMatches(name, this->DelayedOutputFiles);
-  }
-  // Otherwise we use an efficient lookup map.
-  auto o = this->OutputToSource.find(name);
-  if (o != this->OutputToSource.end()) {
-    return o->second.SourceMightBeOutput;
-  }
-  return false;
-}
-
-void cmMakefile::AddTargetByproducts(
-  cmTarget* target, const std::vector<std::string>& byproducts)
-{
-  for (std::string const& o : byproducts) {
-    this->UpdateOutputToSourceMap(o, target);
-  }
-}
-
-void cmMakefile::AddSourceOutputs(cmSourceFile* source,
-                                  const std::vector<std::string>& outputs,
-                                  const std::vector<std::string>& byproducts)
-{
-  for (std::string const& o : outputs) {
-    this->UpdateOutputToSourceMap(o, source, false);
-  }
-  for (std::string const& o : byproducts) {
-    this->UpdateOutputToSourceMap(o, source, true);
-  }
-}
-
-void cmMakefile::UpdateOutputToSourceMap(std::string const& byproduct,
-                                         cmTarget* target)
-{
-  SourceEntry entry;
-  entry.Sources.Target = target;
-
-  auto pr = this->OutputToSource.emplace(byproduct, entry);
-  if (!pr.second) {
-    SourceEntry& current = pr.first->second;
-    // Has the target already been set?
-    if (!current.Sources.Target) {
-      current.Sources.Target = target;
-    } else {
-      // Multiple custom commands/targets produce the same output (source file
-      // or target).  See also comment in other UpdateOutputToSourceMap
-      // overload.
-      //
-      // TODO: Warn the user about this case.
-    }
-  }
-}
-
-void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
-                                         cmSourceFile* source, bool byproduct)
-{
-  SourceEntry entry;
-  entry.Sources.Source = source;
-  entry.Sources.SourceIsByproduct = byproduct;
-  entry.SourceMightBeOutput = !byproduct;
-
-  auto pr = this->OutputToSource.emplace(output, entry);
-  if (!pr.second) {
-    SourceEntry& current = pr.first->second;
-    // Outputs take precedence over byproducts
-    if (!current.Sources.Source ||
-        (current.Sources.SourceIsByproduct && !byproduct)) {
-      current.Sources.Source = source;
-      current.Sources.SourceIsByproduct = false;
-      current.SourceMightBeOutput = true;
-    } else {
-      // Multiple custom commands produce the same output but may
-      // be attached to a different source file (MAIN_DEPENDENCY).
-      // LinearGetSourceFileWithOutput would return the first one,
-      // so keep the mapping for the first one.
-      //
-      // TODO: Warn the user about this case.  However, the VS 8 generator
-      // triggers it for separate generate.stamp rules in ZERO_CHECK and
-      // individual targets.
-    }
-  }
 }
 
 #if !defined(CMAKE_BOOTSTRAP)
@@ -3055,7 +2839,7 @@
   this->RecursionDepth = recursionDepth;
 }
 
-std::string cmMakefile::NewDeferId()
+std::string cmMakefile::NewDeferId() const
 {
   return this->GetGlobalGenerator()->NewDeferId();
 }
@@ -3675,38 +3459,10 @@
   for (std::string const& o : outputs) {
     if (cmGeneratorExpression::Find(o) == std::string::npos) {
       this->GetOrCreateGeneratedSource(o);
-      this->AddDelayedOutput(o);
-    } else {
-      this->DelayedOutputFilesHaveGenex = true;
     }
   }
 }
 
-void cmMakefile::CreateGeneratedByproducts(
-  const std::vector<std::string>& byproducts)
-{
-  for (std::string const& o : byproducts) {
-    if (cmGeneratorExpression::Find(o) == std::string::npos) {
-      this->GetOrCreateGeneratedSource(o);
-    }
-  }
-}
-
-void cmMakefile::AddDelayedOutput(std::string const& output)
-{
-  // Note that this vector might contain the output names in a different order
-  // than in source file iteration order.
-  this->DelayedOutputFiles.push_back(output);
-
-  SourceEntry entry;
-  entry.SourceMightBeOutput = true;
-
-  auto pr = this->OutputToSource.emplace(output, entry);
-  if (!pr.second) {
-    pr.first->second.SourceMightBeOutput = true;
-  }
-}
-
 void cmMakefile::AddTargetObject(std::string const& tgtName,
                                  std::string const& objFile)
 {
@@ -4283,7 +4039,7 @@
 }
 
 void cmMakefile::GetTests(const std::string& config,
-                          std::vector<cmTest*>& tests)
+                          std::vector<cmTest*>& tests) const
 {
   for (const auto& generator : this->GetTestGenerators()) {
     if (generator->TestsForConfig(config)) {
@@ -4633,7 +4389,7 @@
   return this->StateSnapshot.GetPolicy(id, parent_scope);
 }
 
-bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var)
+bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var) const
 {
   // Check for an explicit CMAKE_POLICY_WARNING_CMP<NNNN> setting.
   if (cmProp val = this->GetDefinition(var)) {
@@ -4670,7 +4426,7 @@
 
   // Deprecate old policies, especially those that require a lot
   // of code to maintain the old behavior.
-  if (status == cmPolicies::OLD && id <= cmPolicies::CMP0072 &&
+  if (status == cmPolicies::OLD && id <= cmPolicies::CMP0075 &&
       !(this->GetCMakeInstance()->GetIsInTryCompile() &&
         (
           // Policies set by cmCoreTryCompile::TryCompileCode.
@@ -4738,7 +4494,7 @@
   return !this->CMP0054ReportedIds.insert(context).second;
 }
 
-void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
+void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) const
 {
   /* Record the setting of every policy.  */
   using PolicyID = cmPolicies::PolicyID;
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index c7940fb..26ed737 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -59,24 +59,6 @@
 class cmVariableWatch;
 class cmake;
 
-/** Flag if byproducts shall also be considered.  */
-enum class cmSourceOutputKind
-{
-  OutputOnly,
-  OutputOrByproduct
-};
-
-/** Target and source file which have a specific output.  */
-struct cmSourcesWithOutput
-{
-  /** Target with byproduct.  */
-  cmTarget* Target = nullptr;
-
-  /** Source file with output or byproduct.  */
-  cmSourceFile* Source = nullptr;
-  bool SourceIsByproduct = false;
-};
-
 /** A type-safe wrapper for a string representing a directory id.  */
 class cmDirectoryId
 {
@@ -225,25 +207,12 @@
                                 const std::string& source,
                                 const cmCustomCommandLines& commandLines,
                                 const char* comment);
-  bool AppendCustomCommandToOutput(
+  void AppendCustomCommandToOutput(
     const std::string& output, const std::vector<std::string>& depends,
     const cmImplicitDependsList& implicit_depends,
     const cmCustomCommandLines& commandLines);
 
   /**
-   * Add target byproducts.
-   */
-  void AddTargetByproducts(cmTarget* target,
-                           const std::vector<std::string>& byproducts);
-
-  /**
-   * Add source file outputs.
-   */
-  void AddSourceOutputs(cmSourceFile* source,
-                        const std::vector<std::string>& outputs,
-                        const std::vector<std::string>& byproducts);
-
-  /**
    * Add a define flag to the build.
    */
   void AddDefineFlag(std::string const& definition);
@@ -335,7 +304,7 @@
    */
   void RemoveDefinition(const std::string& name);
   //! Remove a definition from the cache.
-  void RemoveCacheDefinition(const std::string& name);
+  void RemoveCacheDefinition(const std::string& name) const;
 
   /**
    * Specify the name of the project for this build.
@@ -376,7 +345,7 @@
                                            bool parent_scope = false) const;
   bool SetPolicyVersion(std::string const& version_min,
                         std::string const& version_max);
-  void RecordPolicies(cmPolicies::PolicyMap& pm);
+  void RecordPolicies(cmPolicies::PolicyMap& pm) const;
   //@}
 
   /** Helper class to push and pop policies automatically.  */
@@ -753,20 +722,10 @@
     return this->SourceFiles;
   }
 
-  /**
-   * Return the target if the provided source name is a byproduct of a utility
-   * target or a PRE_BUILD, PRE_LINK, or POST_BUILD command.
-   * Return the source file which has the provided source name as output.
-   */
-  cmSourcesWithOutput GetSourcesWithOutput(const std::string& name) const;
-
-  /**
-   * Is there a source file that has the provided source name as an output?
-   * If so then return it.
-   */
-  cmSourceFile* GetSourceFileWithOutput(
-    const std::string& name,
-    cmSourceOutputKind kind = cmSourceOutputKind::OutputOnly) const;
+  std::vector<cmTarget*> const& GetOrderedTargets() const
+  {
+    return this->OrderedTargets;
+  }
 
   //! Add a new cmTest to the list of tests for this makefile.
   cmTest* CreateTest(const std::string& testName);
@@ -779,7 +738,7 @@
   /**
    * Get all tests that run under the given configuration.
    */
-  void GetTests(const std::string& config, std::vector<cmTest*>& tests);
+  void GetTests(const std::string& config, std::vector<cmTest*>& tests) const;
 
   /**
    * Return a location of a file in cmake or custom modules directory
@@ -926,7 +885,7 @@
     return this->SystemIncludeDirectories;
   }
 
-  bool PolicyOptionalWarningEnabled(std::string const& var);
+  bool PolicyOptionalWarningEnabled(std::string const& var) const;
 
   void PushLoopBlock();
   void PopLoopBlock();
@@ -967,7 +926,7 @@
   int GetRecursionDepth() const;
   void SetRecursionDepth(int recursionDepth);
 
-  std::string NewDeferId();
+  std::string NewDeferId() const;
   bool DeferCall(std::string id, std::string fileName, cmListFileFunction lff);
   bool DeferCancelCall(std::string const& id);
   cm::optional<std::string> DeferGetCallIds() const;
@@ -983,8 +942,7 @@
   mutable cmTargetMap Targets;
   std::map<std::string, std::string> AliasTargets;
 
-  using TargetsVec = std::vector<cmTarget*>;
-  TargetsVec OrderedTargets;
+  std::vector<cmTarget*> OrderedTargets;
 
   std::vector<std::unique_ptr<cmSourceFile>> SourceFiles;
 
@@ -1129,48 +1087,9 @@
   bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
 
   void CreateGeneratedOutputs(const std::vector<std::string>& outputs);
-  void CreateGeneratedByproducts(const std::vector<std::string>& byproducts);
 
   std::vector<BT<GeneratorAction>> GeneratorActions;
   bool GeneratorActionsInvoked = false;
-  bool DelayedOutputFilesHaveGenex = false;
-  std::vector<std::string> DelayedOutputFiles;
-
-  void AddDelayedOutput(std::string const& output);
-
-  /**
-   * See LinearGetSourceFileWithOutput for background information
-   */
-  cmTarget* LinearGetTargetWithOutput(const std::string& name) const;
-
-  /**
-   * Generalized old version of GetSourceFileWithOutput kept for
-   * backward-compatibility. It implements a linear search and supports
-   * relative file paths. It is used as a fall back by GetSourceFileWithOutput
-   * and GetSourcesWithOutput.
-   */
-  cmSourceFile* LinearGetSourceFileWithOutput(const std::string& name,
-                                              cmSourceOutputKind kind,
-                                              bool& byproduct) const;
-
-  struct SourceEntry
-  {
-    cmSourcesWithOutput Sources;
-    bool SourceMightBeOutput = false;
-  };
-
-  // A map for fast output to input look up.
-  using OutputToSourceMap = std::unordered_map<std::string, SourceEntry>;
-  OutputToSourceMap OutputToSource;
-
-  void UpdateOutputToSourceMap(std::string const& byproduct, cmTarget* target);
-  void UpdateOutputToSourceMap(std::string const& output, cmSourceFile* source,
-                               bool byproduct);
-
-  /**
-   * Return if the provided source file might have a custom command.
-   */
-  bool MightHaveCustomCommand(const std::string& name) const;
 
   bool CheckSystemVars;
   bool CheckCMP0000;
diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx
deleted file mode 100644
index 1eede13..0000000
--- a/Source/cmPipeConnection.cxx
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmPipeConnection.h"
-
-#include <utility>
-
-#include "cmServer.h"
-
-cmPipeConnection::cmPipeConnection(std::string name,
-                                   cmConnectionBufferStrategy* bufferStrategy)
-  : cmEventBasedConnection(bufferStrategy)
-  , PipeName(std::move(name))
-{
-}
-
-void cmPipeConnection::Connect(uv_stream_t* server)
-{
-  if (this->WriteStream.get()) {
-    // Accept and close all pipes but the first:
-    cm::uv_pipe_ptr rejectPipe;
-
-    rejectPipe.init(*this->Server->GetLoop(), 0);
-    uv_accept(server, rejectPipe);
-
-    return;
-  }
-
-  cm::uv_pipe_ptr ClientPipe;
-  ClientPipe.init(*this->Server->GetLoop(), 0,
-                  static_cast<cmEventBasedConnection*>(this));
-
-  if (uv_accept(server, ClientPipe) != 0) {
-    return;
-  }
-
-  uv_read_start(ClientPipe, on_alloc_buffer, on_read);
-  WriteStream = std::move(ClientPipe);
-  Server->OnConnected(this);
-}
-
-bool cmPipeConnection::OnServeStart(std::string* errorMessage)
-{
-  this->ServerPipe.init(*this->Server->GetLoop(), 0,
-                        static_cast<cmEventBasedConnection*>(this));
-
-  int r;
-  if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
-    *errorMessage = std::string("Internal Error with ") + this->PipeName +
-      ": " + uv_err_name(r);
-    return false;
-  }
-
-  if ((r = uv_listen(this->ServerPipe, 1, on_new_connection)) != 0) {
-    *errorMessage = std::string("Internal Error listening on ") +
-      this->PipeName + ": " + uv_err_name(r);
-    return false;
-  }
-
-  return cmConnection::OnServeStart(errorMessage);
-}
-
-bool cmPipeConnection::OnConnectionShuttingDown()
-{
-  if (this->WriteStream.get()) {
-    this->WriteStream->data = nullptr;
-  }
-
-  this->ServerPipe.reset();
-
-  return cmEventBasedConnection::OnConnectionShuttingDown();
-}
diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h
deleted file mode 100644
index 1215716..0000000
--- a/Source/cmPipeConnection.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-
-#include <cm3p/uv.h>
-
-#include "cmConnection.h"
-#include "cmUVHandlePtr.h"
-
-class cmPipeConnection : public cmEventBasedConnection
-{
-public:
-  cmPipeConnection(std::string name,
-                   cmConnectionBufferStrategy* bufferStrategy = nullptr);
-
-  bool OnServeStart(std::string* pString) override;
-
-  bool OnConnectionShuttingDown() override;
-
-  void Connect(uv_stream_t* server) override;
-
-private:
-  const std::string PipeName;
-  cm::uv_pipe_ptr ServerPipe;
-};
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 18ce9c3..5ef0ff7 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -340,7 +340,12 @@
          3, 19, 0, cmPolicies::WARN)                                          \
   SELECT(POLICY, CMP0114,                                                     \
          "ExternalProject step targets fully adopt their steps.", 3, 19, 0,   \
-         cmPolicies::WARN)
+         cmPolicies::WARN)                                                    \
+  SELECT(POLICY, CMP0115, "Source file extensions must be explicit.", 3, 20,  \
+         0, cmPolicies::WARN)                                                 \
+  SELECT(POLICY, CMP0116,                                                     \
+         "Ninja generators transform DEPFILEs from add_custom_command().", 3, \
+         20, 0, cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
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/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index cf90417..2db1b84 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -29,13 +29,13 @@
     {
     }
 
-    bool operator>(IntegerVersion const version)
+    bool operator>(IntegerVersion const version) const
     {
       return (this->Major > version.Major) ||
         ((this->Major == version.Major) && (this->Minor > version.Minor));
     }
 
-    bool operator>=(IntegerVersion const version)
+    bool operator>=(IntegerVersion const version) const
     {
       return (this->Major > version.Major) ||
         ((this->Major == version.Major) && (this->Minor >= version.Minor));
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 9cb172b..b27bb88 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -15,6 +15,7 @@
 #include <vector>
 
 #include <cm/memory>
+#include <cm/optional>
 #include <cm/string_view>
 #include <cmext/algorithm>
 
@@ -26,7 +27,6 @@
 #include "cmCryptoHash.h"
 #include "cmFileTime.h"
 #include "cmGccDepfileReader.h"
-#include "cmGccDepfileReaderTypes.h"
 #include "cmGeneratedFileStream.h"
 #include "cmQtAutoGen.h"
 #include "cmQtAutoGenerator.h"
@@ -2841,14 +2841,14 @@
 std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
   const char* filePath)
 {
-  cmGccDepfileContent content = cmReadGccDepfile(filePath);
-  if (content.empty()) {
+  auto const content = cmReadGccDepfile(filePath);
+  if (!content || content->empty()) {
     return {};
   }
 
   // Moc outputs a depfile with exactly one rule.
   // Discard the rule and return the dependencies.
-  return content.front().paths;
+  return content->front().paths;
 }
 
 void cmQtAutoMocUicT::Abort(bool error)
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
deleted file mode 100644
index 7f97406..0000000
--- a/Source/cmServer.cxx
+++ /dev/null
@@ -1,570 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmServer.h"
-
-#include <algorithm>
-#include <cassert>
-#include <csignal>
-#include <cstdint>
-#include <iostream>
-#include <mutex>
-#include <utility>
-
-#include <cm/memory>
-#include <cm/shared_mutex>
-
-#include <cm3p/json/reader.h>
-#include <cm3p/json/writer.h>
-
-#include "cmsys/FStream.hxx"
-
-#include "cmConnection.h"
-#include "cmFileMonitor.h"
-#include "cmJsonObjectDictionary.h"
-#include "cmServerDictionary.h"
-#include "cmServerProtocol.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
-
-void on_signal(uv_signal_t* signal, int signum)
-{
-  auto conn = static_cast<cmServerBase*>(signal->data);
-  conn->OnSignal(signum);
-}
-
-static void on_walk_to_shutdown(uv_handle_t* handle, void* arg)
-{
-  (void)arg;
-  assert(uv_is_closing(handle));
-  if (!uv_is_closing(handle)) {
-    uv_close(handle, &cmEventBasedConnection::on_close);
-  }
-}
-
-class cmServer::DebugInfo
-{
-public:
-  DebugInfo()
-    : StartTime(uv_hrtime())
-  {
-  }
-
-  bool PrintStatistics = false;
-
-  std::string OutputFile;
-  uint64_t StartTime;
-};
-
-cmServer::cmServer(cmConnection* conn, bool supportExperimental)
-  : cmServerBase(conn)
-  , SupportExperimental(supportExperimental)
-{
-  // Register supported protocols:
-  this->RegisterProtocol(cm::make_unique<cmServerProtocol1>());
-}
-
-cmServer::~cmServer()
-{
-  Close();
-}
-
-void cmServer::ProcessRequest(cmConnection* connection,
-                              const std::string& input)
-{
-  Json::Reader reader;
-  Json::Value value;
-  if (!reader.parse(input, value)) {
-    this->WriteParseError(connection, "Failed to parse JSON input.");
-    return;
-  }
-
-  std::unique_ptr<DebugInfo> debug;
-  Json::Value debugValue = value["debug"];
-  if (!debugValue.isNull()) {
-    debug = cm::make_unique<DebugInfo>();
-    debug->OutputFile = debugValue["dumpToFile"].asString();
-    debug->PrintStatistics = debugValue["showStats"].asBool();
-  }
-
-  const cmServerRequest request(this, connection, value[kTYPE_KEY].asString(),
-                                value[kCOOKIE_KEY].asString(), value);
-
-  if (request.Type.empty()) {
-    cmServerResponse response(request);
-    response.SetError("No type given in request.");
-    this->WriteResponse(connection, response, nullptr);
-    return;
-  }
-
-  cmSystemTools::SetMessageCallback(
-    [&request](const std::string& msg, const char* title) {
-      reportMessage(msg, title, request);
-    });
-
-  if (this->Protocol) {
-    this->Protocol->CMakeInstance()->SetProgressCallback(
-      [&request](const std::string& msg, float prog) {
-        reportProgress(msg, prog, request);
-      });
-    this->WriteResponse(connection, this->Protocol->Process(request),
-                        debug.get());
-  } else {
-    this->WriteResponse(connection, this->SetProtocolVersion(request),
-                        debug.get());
-  }
-}
-
-void cmServer::RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol)
-{
-  if (protocol->IsExperimental() && !this->SupportExperimental) {
-    protocol.reset();
-    return;
-  }
-  auto version = protocol->ProtocolVersion();
-  assert(version.first >= 0);
-  assert(version.second >= 0);
-  auto it = std::find_if(
-    this->SupportedProtocols.begin(), this->SupportedProtocols.end(),
-    [version](const std::unique_ptr<cmServerProtocol>& p) {
-      return p->ProtocolVersion() == version;
-    });
-  if (it == this->SupportedProtocols.end()) {
-    this->SupportedProtocols.push_back(std::move(protocol));
-  }
-}
-
-void cmServer::PrintHello(cmConnection* connection) const
-{
-  Json::Value hello = Json::objectValue;
-  hello[kTYPE_KEY] = "hello";
-
-  Json::Value& protocolVersions = hello[kSUPPORTED_PROTOCOL_VERSIONS] =
-    Json::arrayValue;
-
-  for (auto const& proto : this->SupportedProtocols) {
-    auto version = proto->ProtocolVersion();
-    Json::Value tmp = Json::objectValue;
-    tmp[kMAJOR_KEY] = version.first;
-    tmp[kMINOR_KEY] = version.second;
-    if (proto->IsExperimental()) {
-      tmp[kIS_EXPERIMENTAL_KEY] = true;
-    }
-    protocolVersions.append(tmp);
-  }
-
-  this->WriteJsonObject(connection, hello, nullptr);
-}
-
-void cmServer::reportProgress(const std::string& msg, float progress,
-                              const cmServerRequest& request)
-{
-  if (progress < 0.0f || progress > 1.0f) {
-    request.ReportMessage(msg, "");
-  } else {
-    request.ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
-  }
-}
-
-void cmServer::reportMessage(const std::string& msg, const char* title,
-                             const cmServerRequest& request)
-{
-  std::string titleString;
-  if (title) {
-    titleString = title;
-  }
-  request.ReportMessage(msg, titleString);
-}
-
-cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
-{
-  if (request.Type != kHANDSHAKE_TYPE) {
-    return request.ReportError("Waiting for type \"" + kHANDSHAKE_TYPE +
-                               "\".");
-  }
-
-  Json::Value requestedProtocolVersion = request.Data[kPROTOCOL_VERSION_KEY];
-  if (requestedProtocolVersion.isNull()) {
-    return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
-                               "\" is required for \"" + kHANDSHAKE_TYPE +
-                               "\".");
-  }
-
-  if (!requestedProtocolVersion.isObject()) {
-    return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
-                               "\" must be a JSON object.");
-  }
-
-  Json::Value majorValue = requestedProtocolVersion[kMAJOR_KEY];
-  if (!majorValue.isInt()) {
-    return request.ReportError("\"" + kMAJOR_KEY +
-                               "\" must be set and an integer.");
-  }
-
-  Json::Value minorValue = requestedProtocolVersion[kMINOR_KEY];
-  if (!minorValue.isNull() && !minorValue.isInt()) {
-    return request.ReportError("\"" + kMINOR_KEY +
-                               "\" must be unset or an integer.");
-  }
-
-  const int major = majorValue.asInt();
-  const int minor = minorValue.isNull() ? -1 : minorValue.asInt();
-  if (major < 0) {
-    return request.ReportError("\"" + kMAJOR_KEY + "\" must be >= 0.");
-  }
-  if (!minorValue.isNull() && minor < 0) {
-    return request.ReportError("\"" + kMINOR_KEY +
-                               "\" must be >= 0 when set.");
-  }
-
-  this->Protocol =
-    cmServer::FindMatchingProtocol(this->SupportedProtocols, major, minor);
-  if (!this->Protocol) {
-    return request.ReportError("Protocol version not supported.");
-  }
-
-  std::string errorMessage;
-  if (!this->Protocol->Activate(this, request, &errorMessage)) {
-    this->Protocol = nullptr;
-    return request.ReportError("Failed to activate protocol version: " +
-                               errorMessage);
-  }
-  return request.Reply(Json::objectValue);
-}
-
-bool cmServer::Serve(std::string* errorMessage)
-{
-  if (this->SupportedProtocols.empty()) {
-    *errorMessage =
-      "No protocol versions defined. Maybe you need --experimental?";
-    return false;
-  }
-  assert(!this->Protocol);
-
-  return cmServerBase::Serve(errorMessage);
-}
-
-cmFileMonitor* cmServer::FileMonitor() const
-{
-  return fileMonitor.get();
-}
-
-void cmServer::WriteJsonObject(const Json::Value& jsonValue,
-                               const DebugInfo* debug) const
-{
-  cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
-  for (auto& connection : this->Connections) {
-    WriteJsonObject(connection.get(), jsonValue, debug);
-  }
-}
-
-void cmServer::WriteJsonObject(cmConnection* connection,
-                               const Json::Value& jsonValue,
-                               const DebugInfo* debug) const
-{
-  Json::FastWriter writer;
-
-  auto beforeJson = uv_hrtime();
-  std::string result = writer.write(jsonValue);
-
-  if (debug) {
-    Json::Value copy = jsonValue;
-    if (debug->PrintStatistics) {
-      Json::Value stats = Json::objectValue;
-      auto endTime = uv_hrtime();
-
-      stats["jsonSerialization"] = double(endTime - beforeJson) / 1000000.0;
-      stats["totalTime"] = double(endTime - debug->StartTime) / 1000000.0;
-      stats["size"] = static_cast<int>(result.size());
-      if (!debug->OutputFile.empty()) {
-        stats["dumpFile"] = debug->OutputFile;
-      }
-
-      copy["zzzDebug"] = stats;
-
-      result = writer.write(copy); // Update result to include debug info
-    }
-
-    if (!debug->OutputFile.empty()) {
-      cmsys::ofstream myfile(debug->OutputFile.c_str());
-      myfile << result;
-    }
-  }
-
-  connection->WriteData(result);
-}
-
-cmServerProtocol* cmServer::FindMatchingProtocol(
-  const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major,
-  int minor)
-{
-  cmServerProtocol* bestMatch = nullptr;
-  for (const auto& protocol : protocols) {
-    auto version = protocol->ProtocolVersion();
-    if (major != version.first) {
-      continue;
-    }
-    if (minor == version.second) {
-      return protocol.get();
-    }
-    if (!bestMatch || bestMatch->ProtocolVersion().second < version.second) {
-      bestMatch = protocol.get();
-    }
-  }
-  return minor < 0 ? bestMatch : nullptr;
-}
-
-void cmServer::WriteProgress(const cmServerRequest& request, int min,
-                             int current, int max,
-                             const std::string& message) const
-{
-  assert(min <= current && current <= max);
-  assert(message.length() != 0);
-
-  Json::Value obj = Json::objectValue;
-  obj[kTYPE_KEY] = kPROGRESS_TYPE;
-  obj[kREPLY_TO_KEY] = request.Type;
-  obj[kCOOKIE_KEY] = request.Cookie;
-  obj[kPROGRESS_MESSAGE_KEY] = message;
-  obj[kPROGRESS_MINIMUM_KEY] = min;
-  obj[kPROGRESS_MAXIMUM_KEY] = max;
-  obj[kPROGRESS_CURRENT_KEY] = current;
-
-  this->WriteJsonObject(request.Connection, obj, nullptr);
-}
-
-void cmServer::WriteMessage(const cmServerRequest& request,
-                            const std::string& message,
-                            const std::string& title) const
-{
-  if (message.empty()) {
-    return;
-  }
-
-  Json::Value obj = Json::objectValue;
-  obj[kTYPE_KEY] = kMESSAGE_TYPE;
-  obj[kREPLY_TO_KEY] = request.Type;
-  obj[kCOOKIE_KEY] = request.Cookie;
-  obj[kMESSAGE_KEY] = message;
-  if (!title.empty()) {
-    obj[kTITLE_KEY] = title;
-  }
-
-  WriteJsonObject(request.Connection, obj, nullptr);
-}
-
-void cmServer::WriteParseError(cmConnection* connection,
-                               const std::string& message) const
-{
-  Json::Value obj = Json::objectValue;
-  obj[kTYPE_KEY] = kERROR_TYPE;
-  obj[kERROR_MESSAGE_KEY] = message;
-  obj[kREPLY_TO_KEY] = "";
-  obj[kCOOKIE_KEY] = "";
-
-  this->WriteJsonObject(connection, obj, nullptr);
-}
-
-void cmServer::WriteSignal(const std::string& name,
-                           const Json::Value& data) const
-{
-  assert(data.isObject());
-  Json::Value obj = data;
-  obj[kTYPE_KEY] = kSIGNAL_TYPE;
-  obj[kREPLY_TO_KEY] = "";
-  obj[kCOOKIE_KEY] = "";
-  obj[kNAME_KEY] = name;
-
-  WriteJsonObject(obj, nullptr);
-}
-
-void cmServer::WriteResponse(cmConnection* connection,
-                             const cmServerResponse& response,
-                             const DebugInfo* debug) const
-{
-  assert(response.IsComplete());
-
-  Json::Value obj = response.Data();
-  obj[kCOOKIE_KEY] = response.Cookie;
-  obj[kTYPE_KEY] = response.IsError() ? kERROR_TYPE : kREPLY_TYPE;
-  obj[kREPLY_TO_KEY] = response.Type;
-  if (response.IsError()) {
-    obj[kERROR_MESSAGE_KEY] = response.ErrorMessage();
-  }
-
-  this->WriteJsonObject(connection, obj, debug);
-}
-
-void cmServer::OnConnected(cmConnection* connection)
-{
-  PrintHello(connection);
-}
-
-void cmServer::OnServeStart()
-{
-  cmServerBase::OnServeStart();
-  fileMonitor = std::make_shared<cmFileMonitor>(GetLoop());
-}
-
-void cmServer::StartShutDown()
-{
-  if (fileMonitor) {
-    fileMonitor->StopMonitoring();
-    fileMonitor.reset();
-  }
-  cmServerBase::StartShutDown();
-}
-
-static void __start_thread(void* arg)
-{
-  auto server = static_cast<cmServerBase*>(arg);
-  std::string error;
-  bool success = server->Serve(&error);
-  if (!success || !error.empty()) {
-    std::cerr << "Error during serve: " << error << std::endl;
-  }
-}
-
-bool cmServerBase::StartServeThread()
-{
-  ServeThreadRunning = true;
-  uv_thread_create(&ServeThread, __start_thread, this);
-  return true;
-}
-
-static void __shutdownThread(uv_async_t* arg)
-{
-  auto server = static_cast<cmServerBase*>(arg->data);
-  server->StartShutDown();
-}
-
-bool cmServerBase::Serve(std::string* errorMessage)
-{
-#ifndef NDEBUG
-  uv_thread_t blank_thread_t = {};
-  assert(uv_thread_equal(&blank_thread_t, &ServeThreadId));
-  ServeThreadId = uv_thread_self();
-#endif
-
-  errorMessage->clear();
-
-  ShutdownSignal.init(Loop, __shutdownThread, this);
-
-  SIGINTHandler.init(Loop, this);
-  SIGHUPHandler.init(Loop, this);
-
-  SIGINTHandler.start(&on_signal, SIGINT);
-  SIGHUPHandler.start(&on_signal, SIGHUP);
-
-  OnServeStart();
-
-  {
-    cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
-    for (auto& connection : Connections) {
-      if (!connection->OnServeStart(errorMessage)) {
-        return false;
-      }
-    }
-  }
-
-  if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
-    // It is important we don't ever let the event loop exit with open handles
-    // at best this is a memory leak, but it can also introduce race conditions
-    // which can hang the program.
-    assert(false && "Event loop stopped in unclean state.");
-
-    *errorMessage = "Internal Error: Event loop stopped in unclean state.";
-    return false;
-  }
-
-  return true;
-}
-
-void cmServerBase::OnConnected(cmConnection*)
-{
-}
-
-void cmServerBase::OnServeStart()
-{
-}
-
-void cmServerBase::StartShutDown()
-{
-  ShutdownSignal.reset();
-  SIGINTHandler.reset();
-  SIGHUPHandler.reset();
-
-  {
-    std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
-    for (auto& connection : Connections) {
-      connection->OnConnectionShuttingDown();
-    }
-    Connections.clear();
-  }
-
-  uv_walk(&Loop, on_walk_to_shutdown, nullptr);
-}
-
-bool cmServerBase::OnSignal(int signum)
-{
-  (void)signum;
-  StartShutDown();
-  return true;
-}
-
-cmServerBase::cmServerBase(cmConnection* connection)
-{
-  auto err = uv_loop_init(&Loop);
-  (void)err;
-  Loop.data = this;
-  assert(err == 0);
-
-  AddNewConnection(connection);
-}
-
-void cmServerBase::Close()
-{
-  if (Loop.data) {
-    if (ServeThreadRunning) {
-      this->ShutdownSignal.send();
-      uv_thread_join(&ServeThread);
-    }
-
-    uv_loop_close(&Loop);
-    Loop.data = nullptr;
-  }
-}
-cmServerBase::~cmServerBase()
-{
-  Close();
-}
-
-void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
-{
-  {
-    std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
-    Connections.emplace_back(ownedConnection);
-  }
-  ownedConnection->SetServer(this);
-}
-
-uv_loop_t* cmServerBase::GetLoop()
-{
-  return &Loop;
-}
-
-void cmServerBase::OnDisconnect(cmConnection* pConnection)
-{
-  auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
-    return m.get() == pConnection;
-  };
-  {
-    std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
-    Connections.erase(
-      std::remove_if(Connections.begin(), Connections.end(), pred),
-      Connections.end());
-  }
-
-  if (Connections.empty()) {
-    this->ShutdownSignal.send();
-  }
-}
diff --git a/Source/cmServer.h b/Source/cmServer.h
deleted file mode 100644
index 9543329..0000000
--- a/Source/cmServer.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <cm/shared_mutex>
-
-#include <cm3p/json/value.h>
-#include <cm3p/uv.h>
-
-#include "cmUVHandlePtr.h"
-
-class cmConnection;
-class cmFileMonitor;
-class cmServerProtocol;
-class cmServerRequest;
-class cmServerResponse;
-
-/***
- * This essentially hold and manages a libuv event queue and responds to
- * messages
- * on any of its connections.
- */
-class cmServerBase
-{
-public:
-  cmServerBase(cmConnection* connection);
-  virtual ~cmServerBase();
-
-  virtual void AddNewConnection(cmConnection* ownedConnection);
-
-  /***
-   * The main override responsible for tailoring behavior towards
-   * whatever the given server is supposed to do
-   *
-   * This should almost always be called by the given connections
-   * directly.
-   *
-   * @param connection The connection the request was received on
-   * @param request The actual request
-   */
-  virtual void ProcessRequest(cmConnection* connection,
-                              const std::string& request) = 0;
-  virtual void OnConnected(cmConnection* connection);
-
-  /***
-   * Start a dedicated thread. If this is used to start the server, it will
-   * join on the
-   * servers dtor.
-   */
-  virtual bool StartServeThread();
-  virtual bool Serve(std::string* errorMessage);
-
-  virtual void OnServeStart();
-  virtual void StartShutDown();
-
-  virtual bool OnSignal(int signum);
-  uv_loop_t* GetLoop();
-  void Close();
-  void OnDisconnect(cmConnection* pConnection);
-
-protected:
-  mutable cm::shared_mutex ConnectionsMutex;
-  std::vector<std::unique_ptr<cmConnection>> Connections;
-
-  bool ServeThreadRunning = false;
-  uv_thread_t ServeThread;
-  cm::uv_async_ptr ShutdownSignal;
-#ifndef NDEBUG
-public:
-  // When the server starts it will mark down it's current thread ID,
-  // which is useful in other contexts to just assert that operations
-  // are performed on that same thread.
-  uv_thread_t ServeThreadId = {};
-
-protected:
-#endif
-
-  uv_loop_t Loop;
-
-  cm::uv_signal_ptr SIGINTHandler;
-  cm::uv_signal_ptr SIGHUPHandler;
-};
-
-class cmServer : public cmServerBase
-{
-public:
-  class DebugInfo;
-
-  cmServer(cmConnection* conn, bool supportExperimental);
-  ~cmServer() override;
-
-  cmServer(cmServer const&) = delete;
-  cmServer& operator=(cmServer const&) = delete;
-
-  bool Serve(std::string* errorMessage) override;
-
-  cmFileMonitor* FileMonitor() const;
-
-private:
-  void RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol);
-
-  // Callbacks from cmServerConnection:
-
-  void ProcessRequest(cmConnection* connection,
-                      const std::string& request) override;
-  std::shared_ptr<cmFileMonitor> fileMonitor;
-
-public:
-  void OnServeStart() override;
-
-  void StartShutDown() override;
-
-public:
-  void OnConnected(cmConnection* connection) override;
-
-private:
-  static void reportProgress(const std::string& msg, float progress,
-                             const cmServerRequest& request);
-  static void reportMessage(const std::string& msg, const char* title,
-                            const cmServerRequest& request);
-
-  // Handle requests:
-  cmServerResponse SetProtocolVersion(const cmServerRequest& request);
-
-  void PrintHello(cmConnection* connection) const;
-
-  // Write responses:
-  void WriteProgress(const cmServerRequest& request, int min, int current,
-                     int max, const std::string& message) const;
-  void WriteMessage(const cmServerRequest& request, const std::string& message,
-                    const std::string& title) const;
-  void WriteResponse(cmConnection* connection,
-                     const cmServerResponse& response,
-                     const DebugInfo* debug) const;
-  void WriteParseError(cmConnection* connection,
-                       const std::string& message) const;
-  void WriteSignal(const std::string& name, const Json::Value& obj) const;
-
-  void WriteJsonObject(Json::Value const& jsonValue,
-                       const DebugInfo* debug) const;
-
-  void WriteJsonObject(cmConnection* connection, Json::Value const& jsonValue,
-                       const DebugInfo* debug) const;
-
-  static cmServerProtocol* FindMatchingProtocol(
-    const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major,
-    int minor);
-
-  const bool SupportExperimental;
-
-  cmServerProtocol* Protocol = nullptr;
-  std::vector<std::unique_ptr<cmServerProtocol>> SupportedProtocols;
-
-  friend class cmServerProtocol;
-  friend class cmServerRequest;
-};
diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx
deleted file mode 100644
index b4f41a0..0000000
--- a/Source/cmServerConnection.cxx
+++ /dev/null
@@ -1,165 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmConfigure.h"
-
-#include "cmServerConnection.h"
-
-#include <cm3p/uv.h>
-
-#include "cmServer.h"
-#include "cmServerDictionary.h"
-
-#ifdef _WIN32
-#  include "io.h"
-#else
-#  include <unistd.h>
-#endif
-#include <cassert>
-#include <utility>
-
-cmStdIoConnection::cmStdIoConnection(
-  cmConnectionBufferStrategy* bufferStrategy)
-  : cmEventBasedConnection(bufferStrategy)
-{
-}
-
-cm::uv_stream_ptr cmStdIoConnection::SetupStream(int file_id)
-{
-  switch (uv_guess_handle(file_id)) {
-    case UV_TTY: {
-      cm::uv_tty_ptr tty;
-      tty.init(*this->Server->GetLoop(), file_id, file_id == 0,
-               static_cast<cmEventBasedConnection*>(this));
-      uv_tty_set_mode(tty, UV_TTY_MODE_NORMAL);
-      return { std::move(tty) };
-    }
-    case UV_FILE:
-      if (file_id == 0) {
-        return nullptr;
-      }
-      // Intentional fallthrough; stdin can _not_ be treated as a named
-      // pipe, however stdout can be.
-      CM_FALLTHROUGH;
-    case UV_NAMED_PIPE: {
-      cm::uv_pipe_ptr pipe;
-      pipe.init(*this->Server->GetLoop(), 0,
-                static_cast<cmEventBasedConnection*>(this));
-      uv_pipe_open(pipe, file_id);
-      return { std::move(pipe) };
-    }
-    default:
-      assert(false && "Unable to determine stream type");
-      return nullptr;
-  }
-}
-
-void cmStdIoConnection::SetServer(cmServerBase* s)
-{
-  cmConnection::SetServer(s);
-  if (!s) {
-    return;
-  }
-
-  this->ReadStream = SetupStream(0);
-  this->WriteStream = SetupStream(1);
-}
-
-void shutdown_connection(uv_prepare_t* prepare)
-{
-  cmStdIoConnection* connection =
-    static_cast<cmStdIoConnection*>(prepare->data);
-
-  if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(prepare))) {
-    uv_close(reinterpret_cast<uv_handle_t*>(prepare),
-             &cmEventBasedConnection::on_close_delete<uv_prepare_t>);
-  }
-  connection->OnDisconnect(0);
-}
-
-bool cmStdIoConnection::OnServeStart(std::string* pString)
-{
-  Server->OnConnected(this);
-  if (this->ReadStream.get()) {
-    uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
-  } else if (uv_guess_handle(0) == UV_FILE) {
-    char buffer[1024];
-    while (auto len = read(0, buffer, sizeof(buffer))) {
-      ReadData(std::string(buffer, buffer + len));
-    }
-
-    // We can't start the disconnect from here, add a prepare hook to do that
-    // for us
-    auto prepare = new uv_prepare_t();
-    prepare->data = this;
-    uv_prepare_init(Server->GetLoop(), prepare);
-    uv_prepare_start(prepare, shutdown_connection);
-  }
-  return cmConnection::OnServeStart(pString);
-}
-
-bool cmStdIoConnection::OnConnectionShuttingDown()
-{
-  if (ReadStream.get()) {
-    uv_read_stop(ReadStream);
-    ReadStream->data = nullptr;
-  }
-
-  this->ReadStream.reset();
-
-  cmEventBasedConnection::OnConnectionShuttingDown();
-
-  return true;
-}
-
-cmServerPipeConnection::cmServerPipeConnection(const std::string& name)
-  : cmPipeConnection(name, new cmServerBufferStrategy)
-{
-}
-
-cmServerStdIoConnection::cmServerStdIoConnection()
-  : cmStdIoConnection(new cmServerBufferStrategy)
-{
-}
-
-cmConnectionBufferStrategy::~cmConnectionBufferStrategy() = default;
-
-void cmConnectionBufferStrategy::clear()
-{
-}
-
-std::string cmServerBufferStrategy::BufferOutMessage(
-  const std::string& rawBuffer) const
-{
-  return std::string("\n") + kSTART_MAGIC + std::string("\n") + rawBuffer +
-    kEND_MAGIC + std::string("\n");
-}
-
-std::string cmServerBufferStrategy::BufferMessage(std::string& RawReadBuffer)
-{
-  for (;;) {
-    auto needle = RawReadBuffer.find('\n');
-
-    if (needle == std::string::npos) {
-      return "";
-    }
-    std::string line = RawReadBuffer.substr(0, needle);
-    const auto ls = line.size();
-    if (ls > 1 && line.at(ls - 1) == '\r') {
-      line.erase(ls - 1, 1);
-    }
-    RawReadBuffer.erase(RawReadBuffer.begin(),
-                        RawReadBuffer.begin() + static_cast<long>(needle) + 1);
-    if (line == kSTART_MAGIC) {
-      RequestBuffer.clear();
-      continue;
-    }
-    if (line == kEND_MAGIC) {
-      std::string rtn;
-      rtn.swap(this->RequestBuffer);
-      return rtn;
-    }
-
-    this->RequestBuffer += line;
-    this->RequestBuffer += "\n";
-  }
-}
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
deleted file mode 100644
index a70edb4..0000000
--- a/Source/cmServerConnection.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-
-#include "cmConnection.h"
-#include "cmPipeConnection.h"
-#include "cmUVHandlePtr.h"
-
-class cmServerBase;
-
-/***
- * This connection buffer strategy accepts messages in the form of
- * [== "CMake Server" ==[
-{
-  ... some JSON message ...
-}
-]== "CMake Server" ==]
- * and only passes on the core json; it discards the envelope.
- */
-class cmServerBufferStrategy : public cmConnectionBufferStrategy
-{
-public:
-  std::string BufferMessage(std::string& rawBuffer) override;
-  std::string BufferOutMessage(const std::string& rawBuffer) const override;
-
-private:
-  std::string RequestBuffer;
-};
-
-/***
- * Generic connection over std io interfaces -- tty
- */
-class cmStdIoConnection : public cmEventBasedConnection
-{
-public:
-  cmStdIoConnection(cmConnectionBufferStrategy* bufferStrategy);
-
-  void SetServer(cmServerBase* s) override;
-
-  bool OnConnectionShuttingDown() override;
-
-  bool OnServeStart(std::string* pString) override;
-
-private:
-  cm::uv_stream_ptr SetupStream(int file_id);
-  cm::uv_stream_ptr ReadStream;
-};
-
-/***
- * These specific connections use the cmake server
- * buffering strategy.
- */
-class cmServerStdIoConnection : public cmStdIoConnection
-{
-public:
-  cmServerStdIoConnection();
-};
-
-class cmServerPipeConnection : public cmPipeConnection
-{
-public:
-  cmServerPipeConnection(const std::string& name);
-};
diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h
deleted file mode 100644
index 961e4b7..0000000
--- a/Source/cmServerDictionary.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include <string>
-
-// Vocabulary:
-
-static const std::string kDIRTY_SIGNAL = "dirty";
-static const std::string kFILE_CHANGE_SIGNAL = "fileChange";
-
-static const std::string kCACHE_TYPE = "cache";
-static const std::string kCMAKE_INPUTS_TYPE = "cmakeInputs";
-static const std::string kCODE_MODEL_TYPE = "codemodel";
-static const std::string kCOMPUTE_TYPE = "compute";
-static const std::string kCONFIGURE_TYPE = "configure";
-static const std::string kERROR_TYPE = "error";
-static const std::string kFILESYSTEM_WATCHERS_TYPE = "fileSystemWatchers";
-static const std::string kGLOBAL_SETTINGS_TYPE = "globalSettings";
-static const std::string kHANDSHAKE_TYPE = "handshake";
-static const std::string kMESSAGE_TYPE = "message";
-static const std::string kPROGRESS_TYPE = "progress";
-static const std::string kREPLY_TYPE = "reply";
-static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings";
-static const std::string kSIGNAL_TYPE = "signal";
-static const std::string kCTEST_INFO_TYPE = "ctestInfo";
-
-static const std::string kBUILD_FILES_KEY = "buildFiles";
-static const std::string kCACHE_ARGUMENTS_KEY = "cacheArguments";
-static const std::string kCACHE_KEY = "cache";
-static const std::string kCAPABILITIES_KEY = "capabilities";
-static const std::string kCHECK_SYSTEM_VARS_KEY = "checkSystemVars";
-static const std::string kCMAKE_ROOT_DIRECTORY_KEY = "cmakeRootDirectory";
-static const std::string kCOOKIE_KEY = "cookie";
-static const std::string kDEBUG_OUTPUT_KEY = "debugOutput";
-static const std::string kERROR_MESSAGE_KEY = "errorMessage";
-static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator";
-static const std::string kGENERATOR_KEY = "generator";
-static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental";
-static const std::string kKEYS_KEY = "keys";
-static const std::string kMAJOR_KEY = "major";
-static const std::string kMESSAGE_KEY = "message";
-static const std::string kMINOR_KEY = "minor";
-static const std::string kPLATFORM_KEY = "platform";
-static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent";
-static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum";
-static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage";
-static const std::string kPROGRESS_MINIMUM_KEY = "progressMinimum";
-static const std::string kPROTOCOL_VERSION_KEY = "protocolVersion";
-static const std::string kREPLY_TO_KEY = "inReplyTo";
-static const std::string kSUPPORTED_PROTOCOL_VERSIONS =
-  "supportedProtocolVersions";
-static const std::string kTITLE_KEY = "title";
-static const std::string kTOOLSET_KEY = "toolset";
-static const std::string kTRACE_EXPAND_KEY = "traceExpand";
-static const std::string kTRACE_KEY = "trace";
-static const std::string kWARN_UNINITIALIZED_KEY = "warnUninitialized";
-static const std::string kWARN_UNUSED_CLI_KEY = "warnUnusedCli";
-static const std::string kWARN_UNUSED_KEY = "warnUnused";
-static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
-static const std::string kWATCHED_FILES_KEY = "watchedFiles";
-
-static const std::string kSTART_MAGIC = "[== \"CMake Server\" ==[";
-static const std::string kEND_MAGIC = "]== \"CMake Server\" ==]";
-
-static const std::string kRENAME_PROPERTY_VALUE = "rename";
-static const std::string kCHANGE_PROPERTY_VALUE = "change";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
deleted file mode 100644
index e586fd9..0000000
--- a/Source/cmServerProtocol.cxx
+++ /dev/null
@@ -1,760 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmServerProtocol.h"
-
-#include <algorithm>
-#include <cassert>
-#include <functional>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <cm/memory>
-#include <cmext/algorithm>
-
-#include <cm3p/uv.h>
-
-#include "cmExternalMakefileProjectGenerator.h"
-#include "cmFileMonitor.h"
-#include "cmGlobalGenerator.h"
-#include "cmJsonObjectDictionary.h"
-#include "cmJsonObjects.h"
-#include "cmMessageType.h"
-#include "cmProperty.h"
-#include "cmServer.h"
-#include "cmServerDictionary.h"
-#include "cmState.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
-
-// Get rid of some windows macros:
-#undef max
-
-namespace {
-
-std::vector<std::string> toStringList(const Json::Value& in)
-{
-  std::vector<std::string> result;
-  for (auto const& it : in) {
-    result.push_back(it.asString());
-  }
-  return result;
-}
-
-} // namespace
-
-cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection,
-                                 std::string t, std::string c, Json::Value d)
-  : Type(std::move(t))
-  , Cookie(std::move(c))
-  , Data(std::move(d))
-  , Connection(connection)
-  , m_Server(server)
-{
-}
-
-void cmServerRequest::ReportProgress(int min, int current, int max,
-                                     const std::string& message) const
-{
-  this->m_Server->WriteProgress(*this, min, current, max, message);
-}
-
-void cmServerRequest::ReportMessage(const std::string& message,
-                                    const std::string& title) const
-{
-  m_Server->WriteMessage(*this, message, title);
-}
-
-cmServerResponse cmServerRequest::Reply(const Json::Value& data) const
-{
-  cmServerResponse response(*this);
-  response.SetData(data);
-  return response;
-}
-
-cmServerResponse cmServerRequest::ReportError(const std::string& message) const
-{
-  cmServerResponse response(*this);
-  response.SetError(message);
-  return response;
-}
-
-cmServerResponse::cmServerResponse(const cmServerRequest& request)
-  : Type(request.Type)
-  , Cookie(request.Cookie)
-{
-}
-
-void cmServerResponse::SetData(const Json::Value& data)
-{
-  assert(this->m_Payload == PAYLOAD_UNKNOWN);
-  if (!data[kCOOKIE_KEY].isNull() || !data[kTYPE_KEY].isNull()) {
-    this->SetError("Response contains cookie or type field.");
-    return;
-  }
-  this->m_Payload = PAYLOAD_DATA;
-  this->m_Data = data;
-}
-
-void cmServerResponse::SetError(const std::string& message)
-{
-  assert(this->m_Payload == PAYLOAD_UNKNOWN);
-  this->m_Payload = PAYLOAD_ERROR;
-  this->m_ErrorMessage = message;
-}
-
-bool cmServerResponse::IsComplete() const
-{
-  return this->m_Payload != PAYLOAD_UNKNOWN;
-}
-
-bool cmServerResponse::IsError() const
-{
-  assert(this->m_Payload != PAYLOAD_UNKNOWN);
-  return this->m_Payload == PAYLOAD_ERROR;
-}
-
-std::string cmServerResponse::ErrorMessage() const
-{
-  if (this->m_Payload == PAYLOAD_ERROR) {
-    return this->m_ErrorMessage;
-  }
-  return std::string();
-}
-
-Json::Value cmServerResponse::Data() const
-{
-  assert(this->m_Payload != PAYLOAD_UNKNOWN);
-  return this->m_Data;
-}
-
-bool cmServerProtocol::Activate(cmServer* server,
-                                const cmServerRequest& request,
-                                std::string* errorMessage)
-{
-  assert(server);
-  this->m_Server = server;
-  this->m_CMakeInstance =
-    cm::make_unique<cmake>(cmake::RoleProject, cmState::Project);
-  this->m_WarnUnused = false;
-  const bool result = this->DoActivate(request, errorMessage);
-  if (!result) {
-    this->m_CMakeInstance = nullptr;
-  }
-  return result;
-}
-
-cmFileMonitor* cmServerProtocol::FileMonitor() const
-{
-  return this->m_Server ? this->m_Server->FileMonitor() : nullptr;
-}
-
-void cmServerProtocol::SendSignal(const std::string& name,
-                                  const Json::Value& data) const
-{
-  if (this->m_Server) {
-    this->m_Server->WriteSignal(name, data);
-  }
-}
-
-cmake* cmServerProtocol::CMakeInstance() const
-{
-  return this->m_CMakeInstance.get();
-}
-
-bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
-                                  std::string* /*errorMessage*/)
-{
-  return true;
-}
-
-std::pair<int, int> cmServerProtocol1::ProtocolVersion() const
-{
-  return { 1, 2 };
-}
-
-static void setErrorMessage(std::string* errorMessage, const std::string& text)
-{
-  if (errorMessage) {
-    *errorMessage = text;
-  }
-}
-
-static bool getOrTestHomeDirectory(cmState* state, std::string& value,
-                                   std::string* errorMessage)
-{
-  const std::string cachedValue =
-    *state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
-  if (value.empty()) {
-    value = cachedValue;
-    return true;
-  }
-  const std::string suffix = "/CMakeLists.txt";
-  const std::string cachedValueCML = cachedValue + suffix;
-  const std::string valueCML = value + suffix;
-  if (!cmSystemTools::SameFile(valueCML, cachedValueCML)) {
-    setErrorMessage(errorMessage,
-                    std::string("\"CMAKE_HOME_DIRECTORY\" is set but "
-                                "incompatible with configured "
-                                "source directory value."));
-    return false;
-  }
-  return true;
-}
-
-static bool getOrTestValue(cmState* state, const std::string& key,
-                           std::string& value,
-                           const std::string& keyDescription,
-                           std::string* errorMessage)
-{
-  const std::string cachedValue = state->GetSafeCacheEntryValue(key);
-  if (value.empty()) {
-    value = cachedValue;
-  }
-  if (!cachedValue.empty() && cachedValue != value) {
-    setErrorMessage(errorMessage,
-                    std::string("\"") + key +
-                      "\" is set but incompatible with configured " +
-                      keyDescription + " value.");
-    return false;
-  }
-  return true;
-}
-
-bool cmServerProtocol1::DoActivate(const cmServerRequest& request,
-                                   std::string* errorMessage)
-{
-  std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString();
-  std::string buildDirectory = request.Data[kBUILD_DIRECTORY_KEY].asString();
-  std::string generator = request.Data[kGENERATOR_KEY].asString();
-  std::string extraGenerator = request.Data[kEXTRA_GENERATOR_KEY].asString();
-  std::string toolset = request.Data[kTOOLSET_KEY].asString();
-  std::string platform = request.Data[kPLATFORM_KEY].asString();
-
-  // normalize source and build directory
-  if (!sourceDirectory.empty()) {
-    sourceDirectory = cmSystemTools::CollapseFullPath(sourceDirectory);
-    cmSystemTools::ConvertToUnixSlashes(sourceDirectory);
-  }
-  if (!buildDirectory.empty()) {
-    buildDirectory = cmSystemTools::CollapseFullPath(buildDirectory);
-    cmSystemTools::ConvertToUnixSlashes(buildDirectory);
-  }
-
-  if (buildDirectory.empty()) {
-    setErrorMessage(errorMessage,
-                    std::string("\"") + kBUILD_DIRECTORY_KEY +
-                      "\" is missing.");
-    return false;
-  }
-
-  cmake* cm = CMakeInstance();
-  if (cmSystemTools::PathExists(buildDirectory)) {
-    if (!cmSystemTools::FileIsDirectory(buildDirectory)) {
-      setErrorMessage(errorMessage,
-                      std::string("\"") + kBUILD_DIRECTORY_KEY +
-                        "\" exists but is not a directory.");
-      return false;
-    }
-
-    const std::string cachePath = cmake::FindCacheFile(buildDirectory);
-    if (cm->LoadCache(cachePath)) {
-      cmState* state = cm->GetState();
-
-      // Check generator:
-      if (!getOrTestValue(state, "CMAKE_GENERATOR", generator, "generator",
-                          errorMessage)) {
-        return false;
-      }
-
-      // check extra generator:
-      if (!getOrTestValue(state, "CMAKE_EXTRA_GENERATOR", extraGenerator,
-                          "extra generator", errorMessage)) {
-        return false;
-      }
-
-      // check sourcedir:
-      if (!getOrTestHomeDirectory(state, sourceDirectory, errorMessage)) {
-        return false;
-      }
-
-      // check toolset:
-      if (!getOrTestValue(state, "CMAKE_GENERATOR_TOOLSET", toolset, "toolset",
-                          errorMessage)) {
-        return false;
-      }
-
-      // check platform:
-      if (!getOrTestValue(state, "CMAKE_GENERATOR_PLATFORM", platform,
-                          "platform", errorMessage)) {
-        return false;
-      }
-    }
-  }
-
-  if (sourceDirectory.empty()) {
-    setErrorMessage(errorMessage,
-                    std::string("\"") + kSOURCE_DIRECTORY_KEY +
-                      "\" is unset but required.");
-    return false;
-  }
-  if (!cmSystemTools::FileIsDirectory(sourceDirectory)) {
-    setErrorMessage(errorMessage,
-                    std::string("\"") + kSOURCE_DIRECTORY_KEY +
-                      "\" is not a directory.");
-    return false;
-  }
-  if (generator.empty()) {
-    setErrorMessage(errorMessage,
-                    std::string("\"") + kGENERATOR_KEY +
-                      "\" is unset but required.");
-    return false;
-  }
-
-  std::vector<cmake::GeneratorInfo> generators;
-  cm->GetRegisteredGenerators(generators);
-  auto baseIt = std::find_if(generators.begin(), generators.end(),
-                             [&generator](const cmake::GeneratorInfo& info) {
-                               return info.name == generator;
-                             });
-  if (baseIt == generators.end()) {
-    setErrorMessage(errorMessage,
-                    std::string("Generator \"") + generator +
-                      "\" not supported.");
-    return false;
-  }
-  auto extraIt = std::find_if(
-    generators.begin(), generators.end(),
-    [&generator, &extraGenerator](const cmake::GeneratorInfo& info) {
-      return info.baseName == generator && info.extraName == extraGenerator;
-    });
-  if (extraIt == generators.end()) {
-    setErrorMessage(errorMessage,
-                    std::string("The combination of generator \"" + generator +
-                                "\" and extra generator \"" + extraGenerator +
-                                "\" is not supported."));
-    return false;
-  }
-  if (!extraIt->supportsToolset && !toolset.empty()) {
-    setErrorMessage(errorMessage,
-                    std::string("Toolset was provided but is not supported by "
-                                "the requested generator."));
-    return false;
-  }
-  if (!extraIt->supportsPlatform && !platform.empty()) {
-    setErrorMessage(errorMessage,
-                    std::string("Platform was provided but is not supported "
-                                "by the requested generator."));
-    return false;
-  }
-
-  this->GeneratorInfo =
-    GeneratorInformation(generator, extraGenerator, toolset, platform,
-                         sourceDirectory, buildDirectory);
-
-  this->m_State = STATE_ACTIVE;
-  return true;
-}
-
-void cmServerProtocol1::HandleCMakeFileChanges(const std::string& path,
-                                               int event, int status)
-{
-  assert(status == 0);
-  static_cast<void>(status);
-
-  if (!m_isDirty) {
-    m_isDirty = true;
-    SendSignal(kDIRTY_SIGNAL, Json::objectValue);
-  }
-  Json::Value obj = Json::objectValue;
-  obj[kPATH_KEY] = path;
-  Json::Value properties = Json::arrayValue;
-  if (event & UV_RENAME) {
-    properties.append(kRENAME_PROPERTY_VALUE);
-  }
-  if (event & UV_CHANGE) {
-    properties.append(kCHANGE_PROPERTY_VALUE);
-  }
-
-  obj[kPROPERTIES_KEY] = properties;
-  SendSignal(kFILE_CHANGE_SIGNAL, obj);
-}
-
-cmServerResponse cmServerProtocol1::Process(const cmServerRequest& request)
-{
-  assert(this->m_State >= STATE_ACTIVE);
-
-  if (request.Type == kCACHE_TYPE) {
-    return this->ProcessCache(request);
-  }
-  if (request.Type == kCMAKE_INPUTS_TYPE) {
-    return this->ProcessCMakeInputs(request);
-  }
-  if (request.Type == kCODE_MODEL_TYPE) {
-    return this->ProcessCodeModel(request);
-  }
-  if (request.Type == kCOMPUTE_TYPE) {
-    return this->ProcessCompute(request);
-  }
-  if (request.Type == kCONFIGURE_TYPE) {
-    return this->ProcessConfigure(request);
-  }
-  if (request.Type == kFILESYSTEM_WATCHERS_TYPE) {
-    return this->ProcessFileSystemWatchers(request);
-  }
-  if (request.Type == kGLOBAL_SETTINGS_TYPE) {
-    return this->ProcessGlobalSettings(request);
-  }
-  if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) {
-    return this->ProcessSetGlobalSettings(request);
-  }
-  if (request.Type == kCTEST_INFO_TYPE) {
-    return this->ProcessCTests(request);
-  }
-
-  return request.ReportError("Unknown command!");
-}
-
-bool cmServerProtocol1::IsExperimental() const
-{
-  return true;
-}
-
-cmServerResponse cmServerProtocol1::ProcessCache(
-  const cmServerRequest& request)
-{
-  cmState* state = this->CMakeInstance()->GetState();
-
-  Json::Value result = Json::objectValue;
-
-  std::vector<std::string> allKeys = state->GetCacheEntryKeys();
-
-  Json::Value list = Json::arrayValue;
-  std::vector<std::string> keys = toStringList(request.Data[kKEYS_KEY]);
-  if (keys.empty()) {
-    keys = allKeys;
-  } else {
-    for (auto const& i : keys) {
-      if (!cm::contains(allKeys, i)) {
-        return request.ReportError("Key \"" + i + "\" not found in cache.");
-      }
-    }
-  }
-  std::sort(keys.begin(), keys.end());
-  for (auto const& key : keys) {
-    Json::Value entry = Json::objectValue;
-    entry[kKEY_KEY] = key;
-    entry[kTYPE_KEY] =
-      cmState::CacheEntryTypeToString(state->GetCacheEntryType(key));
-    entry[kVALUE_KEY] = *state->GetCacheEntryValue(key);
-
-    Json::Value props = Json::objectValue;
-    bool haveProperties = false;
-    for (auto const& prop : state->GetCacheEntryPropertyList(key)) {
-      haveProperties = true;
-      props[prop] = *state->GetCacheEntryProperty(key, prop);
-    }
-    if (haveProperties) {
-      entry[kPROPERTIES_KEY] = props;
-    }
-
-    list.append(entry);
-  }
-
-  result[kCACHE_KEY] = list;
-  return request.Reply(result);
-}
-
-cmServerResponse cmServerProtocol1::ProcessCMakeInputs(
-  const cmServerRequest& request)
-{
-  if (this->m_State < STATE_CONFIGURED) {
-    return request.ReportError("This instance was not yet configured.");
-  }
-
-  const cmake* cm = this->CMakeInstance();
-  const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot();
-  const std::string& sourceDir = cm->GetHomeDirectory();
-
-  Json::Value result = Json::objectValue;
-  result[kSOURCE_DIRECTORY_KEY] = sourceDir;
-  result[kCMAKE_ROOT_DIRECTORY_KEY] = cmakeRootDir;
-  result[kBUILD_FILES_KEY] = cmDumpCMakeInputs(cm);
-  return request.Reply(result);
-}
-
-cmServerResponse cmServerProtocol1::ProcessCodeModel(
-  const cmServerRequest& request)
-{
-  if (this->m_State != STATE_COMPUTED) {
-    return request.ReportError("No build system was generated yet.");
-  }
-
-  return request.Reply(cmDumpCodeModel(this->CMakeInstance()));
-}
-
-cmServerResponse cmServerProtocol1::ProcessCompute(
-  const cmServerRequest& request)
-{
-  if (this->m_State > STATE_CONFIGURED) {
-    return request.ReportError("This build system was already generated.");
-  }
-  if (this->m_State < STATE_CONFIGURED) {
-    return request.ReportError("This project was not configured yet.");
-  }
-
-  cmake* cm = this->CMakeInstance();
-  int ret = cm->Generate();
-
-  if (ret < 0) {
-    return request.ReportError("Failed to compute build system.");
-  }
-  m_State = STATE_COMPUTED;
-  return request.Reply(Json::Value());
-}
-
-cmServerResponse cmServerProtocol1::ProcessConfigure(
-  const cmServerRequest& request)
-{
-  if (this->m_State == STATE_INACTIVE) {
-    return request.ReportError("This instance is inactive.");
-  }
-
-  FileMonitor()->StopMonitoring();
-
-  std::string errorMessage;
-  cmake* cm = this->CMakeInstance();
-  this->GeneratorInfo.SetupGenerator(cm, &errorMessage);
-  if (!errorMessage.empty()) {
-    return request.ReportError(errorMessage);
-  }
-
-  // Make sure the types of cacheArguments matches (if given):
-  std::vector<std::string> cacheArgs = { "unused" };
-  bool cacheArgumentsError = false;
-  const Json::Value passedArgs = request.Data[kCACHE_ARGUMENTS_KEY];
-  if (!passedArgs.isNull()) {
-    if (passedArgs.isString()) {
-      cacheArgs.push_back(passedArgs.asString());
-    } else if (passedArgs.isArray()) {
-      for (auto const& arg : passedArgs) {
-        if (!arg.isString()) {
-          cacheArgumentsError = true;
-          break;
-        }
-        cacheArgs.push_back(arg.asString());
-      }
-    } else {
-      cacheArgumentsError = true;
-    }
-  }
-  if (cacheArgumentsError) {
-    request.ReportError(
-      "cacheArguments must be unset, a string or an array of strings.");
-  }
-
-  std::string sourceDir = cm->GetHomeDirectory();
-  const std::string buildDir = cm->GetHomeOutputDirectory();
-
-  cmGlobalGenerator* gg = cm->GetGlobalGenerator();
-
-  if (buildDir.empty()) {
-    return request.ReportError("No build directory set via Handshake.");
-  }
-
-  if (cm->LoadCache(buildDir)) {
-    // build directory has been set up before
-    cmProp cachedSourceDir =
-      cm->GetState()->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
-    if (!cachedSourceDir) {
-      return request.ReportError("No CMAKE_HOME_DIRECTORY found in cache.");
-    }
-    if (sourceDir.empty()) {
-      sourceDir = *cachedSourceDir;
-      cm->SetHomeDirectory(sourceDir);
-    }
-
-    cmProp cachedGenerator =
-      cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR");
-    if (cachedGenerator) {
-      if (gg && gg->GetName() != *cachedGenerator) {
-        return request.ReportError("Configured generator does not match with "
-                                   "CMAKE_GENERATOR found in cache.");
-      }
-    }
-  } else {
-    // build directory has not been set up before
-    if (sourceDir.empty()) {
-      return request.ReportError("No sourceDirectory set via "
-                                 "setGlobalSettings and no cache found in "
-                                 "buildDirectory.");
-    }
-  }
-
-  cmSystemTools::ResetErrorOccuredFlag(); // Reset error state
-
-  if (cm->AddCMakePaths() != 1) {
-    return request.ReportError("Failed to set CMake paths.");
-  }
-
-  if (!cm->SetCacheArgs(cacheArgs)) {
-    return request.ReportError("cacheArguments could not be set.");
-  }
-
-  int ret = cm->Configure();
-  cm->IssueMessage(
-    MessageType::DEPRECATION_WARNING,
-    "The 'cmake-server(7)' is deprecated.  "
-    "Please port clients to use the 'cmake-file-api(7)' instead.");
-  if (ret < 0) {
-    return request.ReportError("Configuration failed.");
-  }
-
-  std::vector<std::string> toWatchList;
-  cmGetCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList,
-                   nullptr);
-
-  FileMonitor()->MonitorPaths(toWatchList,
-                              [this](const std::string& p, int e, int s) {
-                                this->HandleCMakeFileChanges(p, e, s);
-                              });
-
-  m_State = STATE_CONFIGURED;
-  m_isDirty = false;
-  return request.Reply(Json::Value());
-}
-
-cmServerResponse cmServerProtocol1::ProcessGlobalSettings(
-  const cmServerRequest& request)
-{
-  cmake* cm = this->CMakeInstance();
-  Json::Value obj = Json::objectValue;
-
-  // Capabilities information:
-  obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson();
-
-  obj[kDEBUG_OUTPUT_KEY] = cm->GetDebugOutput();
-  obj[kTRACE_KEY] = cm->GetTrace();
-  obj[kTRACE_EXPAND_KEY] = cm->GetTraceExpand();
-  obj[kWARN_UNINITIALIZED_KEY] = cm->GetWarnUninitialized();
-  obj[kWARN_UNUSED_KEY] = m_WarnUnused;
-  obj[kWARN_UNUSED_CLI_KEY] = cm->GetWarnUnusedCli();
-  obj[kCHECK_SYSTEM_VARS_KEY] = cm->GetCheckSystemVars();
-
-  obj[kSOURCE_DIRECTORY_KEY] = this->GeneratorInfo.SourceDirectory;
-  obj[kBUILD_DIRECTORY_KEY] = this->GeneratorInfo.BuildDirectory;
-
-  // Currently used generator:
-  obj[kGENERATOR_KEY] = this->GeneratorInfo.GeneratorName;
-  obj[kEXTRA_GENERATOR_KEY] = this->GeneratorInfo.ExtraGeneratorName;
-
-  return request.Reply(obj);
-}
-
-static void setBool(const cmServerRequest& request, const std::string& key,
-                    std::function<void(bool)> const& setter)
-{
-  if (request.Data[key].isNull()) {
-    return;
-  }
-  setter(request.Data[key].asBool());
-}
-
-cmServerResponse cmServerProtocol1::ProcessSetGlobalSettings(
-  const cmServerRequest& request)
-{
-  const std::vector<std::string> boolValues = {
-    kDEBUG_OUTPUT_KEY,       kTRACE_KEY,       kTRACE_EXPAND_KEY,
-    kWARN_UNINITIALIZED_KEY, kWARN_UNUSED_KEY, kWARN_UNUSED_CLI_KEY,
-    kCHECK_SYSTEM_VARS_KEY
-  };
-  for (std::string const& i : boolValues) {
-    if (!request.Data[i].isNull() && !request.Data[i].isBool()) {
-      return request.ReportError("\"" + i +
-                                 "\" must be unset or a bool value.");
-    }
-  }
-
-  cmake* cm = this->CMakeInstance();
-
-  setBool(request, kDEBUG_OUTPUT_KEY,
-          [cm](bool e) { cm->SetDebugOutputOn(e); });
-  setBool(request, kTRACE_KEY, [cm](bool e) { cm->SetTrace(e); });
-  setBool(request, kTRACE_EXPAND_KEY, [cm](bool e) { cm->SetTraceExpand(e); });
-  setBool(request, kWARN_UNINITIALIZED_KEY,
-          [cm](bool e) { cm->SetWarnUninitialized(e); });
-  setBool(request, kWARN_UNUSED_KEY, [this](bool e) { m_WarnUnused = e; });
-  setBool(request, kWARN_UNUSED_CLI_KEY,
-          [cm](bool e) { cm->SetWarnUnusedCli(e); });
-  setBool(request, kCHECK_SYSTEM_VARS_KEY,
-          [cm](bool e) { cm->SetCheckSystemVars(e); });
-
-  return request.Reply(Json::Value());
-}
-
-cmServerResponse cmServerProtocol1::ProcessFileSystemWatchers(
-  const cmServerRequest& request)
-{
-  const cmFileMonitor* const fm = FileMonitor();
-  Json::Value result = Json::objectValue;
-  Json::Value files = Json::arrayValue;
-  for (auto const& f : fm->WatchedFiles()) {
-    files.append(f);
-  }
-  Json::Value directories = Json::arrayValue;
-  for (auto const& d : fm->WatchedDirectories()) {
-    directories.append(d);
-  }
-  result[kWATCHED_FILES_KEY] = files;
-  result[kWATCHED_DIRECTORIES_KEY] = directories;
-
-  return request.Reply(result);
-}
-
-cmServerResponse cmServerProtocol1::ProcessCTests(
-  const cmServerRequest& request)
-{
-  if (this->m_State < STATE_COMPUTED) {
-    return request.ReportError("This instance was not yet computed.");
-  }
-
-  return request.Reply(cmDumpCTestInfo(this->CMakeInstance()));
-}
-
-cmServerProtocol1::GeneratorInformation::GeneratorInformation(
-  std::string generatorName, std::string extraGeneratorName,
-  std::string toolset, std::string platform, std::string sourceDirectory,
-  std::string buildDirectory)
-  : GeneratorName(std::move(generatorName))
-  , ExtraGeneratorName(std::move(extraGeneratorName))
-  , Toolset(std::move(toolset))
-  , Platform(std::move(platform))
-  , SourceDirectory(std::move(sourceDirectory))
-  , BuildDirectory(std::move(buildDirectory))
-{
-}
-
-void cmServerProtocol1::GeneratorInformation::SetupGenerator(
-  cmake* cm, std::string* errorMessage)
-{
-  const std::string fullGeneratorName =
-    cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
-      GeneratorName, ExtraGeneratorName);
-
-  cm->SetHomeDirectory(SourceDirectory);
-  cm->SetHomeOutputDirectory(BuildDirectory);
-
-  auto gg = cm->CreateGlobalGenerator(fullGeneratorName);
-  if (!gg) {
-    setErrorMessage(
-      errorMessage,
-      std::string("Could not set up the requested combination of \"") +
-        kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\"");
-    return;
-  }
-
-  cm->SetGlobalGenerator(std::move(gg));
-
-  cm->SetGeneratorToolset(Toolset);
-  cm->SetGeneratorPlatform(Platform);
-}
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
deleted file mode 100644
index 6009e23..0000000
--- a/Source/cmServerProtocol.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include <cm3p/json/value.h>
-
-#include "cmake.h"
-
-class cmConnection;
-class cmFileMonitor;
-class cmServer;
-class cmServerRequest;
-
-class cmServerResponse
-{
-public:
-  explicit cmServerResponse(const cmServerRequest& request);
-
-  void SetData(const Json::Value& data);
-  void SetError(const std::string& message);
-
-  bool IsComplete() const;
-  bool IsError() const;
-  std::string ErrorMessage() const;
-  Json::Value Data() const;
-
-  const std::string Type;
-  const std::string Cookie;
-
-private:
-  enum PayLoad
-  {
-    PAYLOAD_UNKNOWN,
-    PAYLOAD_ERROR,
-    PAYLOAD_DATA
-  };
-  PayLoad m_Payload = PAYLOAD_UNKNOWN;
-  std::string m_ErrorMessage;
-  Json::Value m_Data;
-};
-
-class cmServerRequest
-{
-public:
-  cmServerResponse Reply(const Json::Value& data) const;
-  cmServerResponse ReportError(const std::string& message) const;
-
-  const std::string Type;
-  const std::string Cookie;
-  const Json::Value Data;
-  cmConnection* Connection;
-
-private:
-  cmServerRequest(cmServer* server, cmConnection* connection, std::string t,
-                  std::string c, Json::Value d);
-
-  void ReportProgress(int min, int current, int max,
-                      const std::string& message) const;
-  void ReportMessage(const std::string& message,
-                     const std::string& title) const;
-
-  cmServer* m_Server;
-
-  friend class cmServer;
-};
-
-class cmServerProtocol
-{
-public:
-  cmServerProtocol() = default;
-  virtual ~cmServerProtocol() = default;
-
-  cmServerProtocol(cmServerProtocol const&) = delete;
-  cmServerProtocol& operator=(cmServerProtocol const&) = delete;
-
-  virtual std::pair<int, int> ProtocolVersion() const = 0;
-  virtual bool IsExperimental() const = 0;
-  virtual cmServerResponse Process(const cmServerRequest& request) = 0;
-
-  bool Activate(cmServer* server, const cmServerRequest& request,
-                std::string* errorMessage);
-
-  cmFileMonitor* FileMonitor() const;
-  void SendSignal(const std::string& name, const Json::Value& data) const;
-
-protected:
-  cmake* CMakeInstance() const;
-  // Implement protocol specific activation tasks here. Called from Activate().
-  virtual bool DoActivate(const cmServerRequest& request,
-                          std::string* errorMessage);
-  bool m_WarnUnused = false; // storage for legacy option
-
-private:
-  std::unique_ptr<cmake> m_CMakeInstance;
-  cmServer* m_Server = nullptr; // not owned!
-
-  friend class cmServer;
-};
-
-class cmServerProtocol1 : public cmServerProtocol
-{
-public:
-  std::pair<int, int> ProtocolVersion() const override;
-  bool IsExperimental() const override;
-  cmServerResponse Process(const cmServerRequest& request) override;
-
-private:
-  bool DoActivate(const cmServerRequest& request,
-                  std::string* errorMessage) override;
-
-  void HandleCMakeFileChanges(const std::string& path, int event, int status);
-
-  // Handle requests:
-  cmServerResponse ProcessCache(const cmServerRequest& request);
-  cmServerResponse ProcessCMakeInputs(const cmServerRequest& request);
-  cmServerResponse ProcessCodeModel(const cmServerRequest& request);
-  cmServerResponse ProcessCompute(const cmServerRequest& request);
-  cmServerResponse ProcessConfigure(const cmServerRequest& request);
-  cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
-  cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
-  cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request);
-  cmServerResponse ProcessCTests(const cmServerRequest& request);
-
-  enum State
-  {
-    STATE_INACTIVE,
-    STATE_ACTIVE,
-    STATE_CONFIGURED,
-    STATE_COMPUTED
-  };
-  State m_State = STATE_INACTIVE;
-
-  bool m_isDirty = false;
-
-  struct GeneratorInformation
-  {
-  public:
-    GeneratorInformation() = default;
-    GeneratorInformation(std::string generatorName,
-                         std::string extraGeneratorName, std::string toolset,
-                         std::string platform, std::string sourceDirectory,
-                         std::string buildDirectory);
-
-    void SetupGenerator(cmake* cm, std::string* errorMessage);
-
-    std::string GeneratorName;
-    std::string ExtraGeneratorName;
-    std::string Toolset;
-    std::string Platform;
-
-    std::string SourceDirectory;
-    std::string BuildDirectory;
-  };
-
-  GeneratorInformation GeneratorInfo;
-};
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index ef44a57..61f48e9 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -8,6 +8,7 @@
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmPolicies.h"
 #include "cmProperty.h"
 #include "cmState.h"
 #include "cmStringAlgorithms.h"
@@ -93,10 +94,11 @@
   return this->Location;
 }
 
-std::string const& cmSourceFile::ResolveFullPath(std::string* error)
+std::string const& cmSourceFile::ResolveFullPath(std::string* error,
+                                                 std::string* cmp0115Warning)
 {
   if (this->FullPath.empty()) {
-    if (this->FindFullPath(error)) {
+    if (this->FindFullPath(error, cmp0115Warning)) {
       this->CheckExtension();
     }
   }
@@ -108,7 +110,8 @@
   return this->FullPath;
 }
 
-bool cmSourceFile::FindFullPath(std::string* error)
+bool cmSourceFile::FindFullPath(std::string* error,
+                                std::string* cmp0115Warning)
 {
   // If the file is generated compute the location without checking on disk.
   if (this->GetIsGenerated()) {
@@ -131,9 +134,11 @@
   // List of extension lists
   std::vector<std::string> exts =
     makefile->GetCMakeInstance()->GetAllExtensions();
+  auto cmp0115 = makefile->GetPolicyStatus(cmPolicies::CMP0115);
 
   // Tries to find the file in a given directory
-  auto findInDir = [this, &exts, &lPath](std::string const& dir) -> bool {
+  auto findInDir = [this, &exts, &lPath, cmp0115, cmp0115Warning,
+                    makefile](std::string const& dir) -> bool {
     // Compute full path
     std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir);
     // Try full path
@@ -141,13 +146,29 @@
       this->FullPath = fullPath;
       return true;
     }
-    // Try full path with extension
-    for (std::string const& ext : exts) {
-      if (!ext.empty()) {
-        std::string extPath = cmStrCat(fullPath, '.', ext);
-        if (cmSystemTools::FileExists(extPath)) {
-          this->FullPath = extPath;
-          return true;
+    // This has to be an if statement due to a bug in Oracle Developer Studio.
+    // See https://community.oracle.com/tech/developers/discussion/4476246/
+    // for details.
+    if (cmp0115 == cmPolicies::OLD || cmp0115 == cmPolicies::WARN) {
+      // Try full path with extension
+      for (std::string const& ext : exts) {
+        if (!ext.empty()) {
+          std::string extPath = cmStrCat(fullPath, '.', ext);
+          if (cmSystemTools::FileExists(extPath)) {
+            this->FullPath = extPath;
+            if (cmp0115 == cmPolicies::WARN) {
+              std::string warning =
+                cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0115),
+                         "\nFile:\n  ", extPath);
+              if (cmp0115Warning) {
+                *cmp0115Warning = std::move(warning);
+              } else {
+                makefile->GetCMakeInstance()->IssueMessage(
+                  MessageType::AUTHOR_WARNING, warning);
+              }
+            }
+            return true;
+          }
         }
       }
     }
@@ -168,11 +189,19 @@
   }
 
   // Compose error
-  std::string err =
-    cmStrCat("Cannot find source file:\n  ", lPath, "\nTried extensions");
-  for (std::string const& ext : exts) {
-    err += " .";
-    err += ext;
+  std::string err = cmStrCat("Cannot find source file:\n  ", lPath);
+  switch (cmp0115) {
+    case cmPolicies::OLD:
+    case cmPolicies::WARN:
+      err = cmStrCat(err, "\nTried extensions");
+      for (auto const& ext : exts) {
+        err = cmStrCat(err, " .", ext);
+      }
+      break;
+    case cmPolicies::REQUIRED_IF_USED:
+    case cmPolicies::REQUIRED_ALWAYS:
+    case cmPolicies::NEW:
+      break;
   }
   if (error != nullptr) {
     *error = std::move(err);
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 39ea8e3..3196b3f 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -77,7 +77,8 @@
    * Resolves the full path to the file.  Attempts to locate the file on disk
    * and finalizes its location.
    */
-  std::string const& ResolveFullPath(std::string* error = nullptr);
+  std::string const& ResolveFullPath(std::string* error = nullptr,
+                                     std::string* cmp0115Warning = nullptr);
 
   /**
    * The resolved full path to the file.  The returned file name might be empty
@@ -138,7 +139,7 @@
   bool FindFullPathFailed = false;
   bool IsGenerated = false;
 
-  bool FindFullPath(std::string* error);
+  bool FindFullPath(std::string* error, std::string* cmp0115Warning);
   void CheckExtension();
   void CheckLanguage(std::string const& ext);
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index e076d1e..4eebec6 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -213,7 +213,7 @@
   bool CheckImportedLibName(std::string const& prop,
                             std::string const& value) const;
 
-  std::string ProcessSourceItemCMP0049(const std::string& s);
+  std::string ProcessSourceItemCMP0049(const std::string& s) const;
 };
 
 namespace {
@@ -740,7 +740,8 @@
   }
 }
 
-std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
+std::string cmTargetInternals::ProcessSourceItemCMP0049(
+  const std::string& s) const
 {
   std::string src = s;
 
@@ -791,7 +792,7 @@
   {
   }
 
-  cmSourceFileLocation operator()(const std::string& filename)
+  cmSourceFileLocation operator()(const std::string& filename) const
   {
     return cmSourceFileLocation(this->Makefile, filename);
   }
@@ -857,7 +858,7 @@
                                            cmSourceFileLocationKind::Known);
 }
 
-void cmTarget::ClearDependencyInformation(cmMakefile& mf)
+void cmTarget::ClearDependencyInformation(cmMakefile& mf) const
 {
   std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS");
   mf.RemoveCacheDefinition(depname);
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index d8f66bc..c2a4d86 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -114,7 +114,7 @@
   LinkLibraryVectorType const& GetOriginalLinkLibraries() const;
 
   //! Clear the dependency information recorded for this target, if any.
-  void ClearDependencyInformation(cmMakefile& mf);
+  void ClearDependencyInformation(cmMakefile& mf) const;
 
   void AddLinkLibrary(cmMakefile& mf, std::string const& lib,
                       cmTargetLinkLibraryType llt);
diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx
new file mode 100644
index 0000000..e1f8753
--- /dev/null
+++ b/Source/cmTransformDepfile.cxx
@@ -0,0 +1,114 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmTransformDepfile.h"
+
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include <cm/optional>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmGccDepfileReader.h"
+#include "cmGccDepfileReaderTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+namespace {
+void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
+{
+  for (auto c : filename) {
+    switch (c) {
+      case ' ':
+        fout << "\\ ";
+        break;
+      case '\\':
+        fout << "\\\\";
+        break;
+      default:
+        fout << c;
+        break;
+    }
+  }
+}
+
+void WriteGccDepfile(cmsys::ofstream& fout, const cmGccDepfileContent& content)
+{
+  for (auto const& dep : content) {
+    bool first = true;
+    for (auto const& rule : dep.rules) {
+      if (!first) {
+        fout << " \\\n  ";
+      }
+      first = false;
+      WriteFilenameGcc(fout, rule);
+    }
+    fout << ':';
+    for (auto const& path : dep.paths) {
+      fout << " \\\n  " << path;
+    }
+    fout << '\n';
+  }
+}
+
+void WriteVsTlog(cmsys::ofstream& fout, const cmGccDepfileContent& content)
+{
+  for (auto const& dep : content) {
+    fout << '^';
+    bool first = true;
+    for (auto const& rule : dep.rules) {
+      if (!first) {
+        fout << '|';
+      }
+      first = false;
+      fout << cmSystemTools::ConvertToOutputPath(rule);
+    }
+    fout << "\r\n";
+    for (auto const& path : dep.paths) {
+      fout << cmSystemTools::ConvertToOutputPath(path) << "\r\n";
+    }
+  }
+}
+}
+
+bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
+                        const std::string& infile, const std::string& outfile)
+{
+  cmGccDepfileContent content;
+  if (cmSystemTools::FileExists(infile)) {
+    auto result = cmReadGccDepfile(infile.c_str());
+    if (!result) {
+      return false;
+    }
+    content = *std::move(result);
+  }
+
+  for (auto& dep : content) {
+    for (auto& rule : dep.rules) {
+      if (!cmSystemTools::FileIsFullPath(rule)) {
+        rule = cmStrCat(prefix, rule);
+      }
+    }
+    for (auto& path : dep.paths) {
+      if (!cmSystemTools::FileIsFullPath(path)) {
+        path = cmStrCat(prefix, path);
+      }
+    }
+  }
+
+  cmsys::ofstream fout(outfile.c_str());
+  if (!fout) {
+    return false;
+  }
+  switch (format) {
+    case cmDepfileFormat::GccDepfile:
+      WriteGccDepfile(fout, content);
+      break;
+    case cmDepfileFormat::VsTlog:
+      WriteVsTlog(fout, content);
+      break;
+  }
+  return true;
+}
diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h
new file mode 100644
index 0000000..792c1aa
--- /dev/null
+++ b/Source/cmTransformDepfile.h
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#pragma once
+
+#include <string>
+
+enum class cmDepfileFormat
+{
+  GccDepfile,
+  VsTlog,
+};
+
+bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
+                        const std::string& infile, const std::string& outfile);
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 2a14b03..1771f0a 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -263,7 +263,7 @@
   }
   obj["generators"] = generators;
   obj["fileApi"] = cmFileAPI::ReportCapabilities();
-  obj["serverMode"] = true;
+  obj["serverMode"] = false;
 
   return obj;
 }
@@ -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);
     }
   }
 
@@ -1938,7 +1941,7 @@
     }
   }
 
-  auto& mf = this->GlobalGenerator->GetMakefiles()[0];
+  const auto& mf = this->GlobalGenerator->GetMakefiles()[0];
   if (mf->IsOn("CTEST_USE_LAUNCHERS") &&
       !this->State->GetGlobalProperty("RULE_LAUNCH_COMPILE")) {
     cmSystemTools::Error(
@@ -2280,12 +2283,12 @@
   return this->State->GetInitializedCacheValue(name);
 }
 
-void cmake::AddScriptingCommands()
+void cmake::AddScriptingCommands() const
 {
   GetScriptingCommands(this->GetState());
 }
 
-void cmake::AddProjectCommands()
+void cmake::AddProjectCommands() const
 {
   GetProjectCommands(this->GetState());
 }
diff --git a/Source/cmake.h b/Source/cmake.h
index 262d673..f70fd14 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -411,7 +411,7 @@
   WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; }
 
   //! Debug the try compile stuff by not deleting the files
-  bool GetDebugTryCompile() { return this->DebugTryCompile; }
+  bool GetDebugTryCompile() const { return this->DebugTryCompile; }
   void DebugTryCompileOn() { this->DebugTryCompile = true; }
 
   /**
@@ -456,11 +456,11 @@
   void SetShowLogContext(bool b) { this->LogContext = b; }
 
   //! Do we want debug output during the cmake run.
-  bool GetDebugOutput() { return this->DebugOutput; }
+  bool GetDebugOutput() const { return this->DebugOutput; }
   void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
 
   //! Do we want debug output from the find commands during the cmake run.
-  bool GetDebugFindOutput() { return this->DebugFindOutput; }
+  bool GetDebugFindOutput() const { return this->DebugFindOutput; }
   void SetDebugFindOutputOn(bool b) { this->DebugFindOutput = b; }
 
   //! Do we want trace output during the cmake run.
@@ -482,11 +482,11 @@
   void SetTraceFile(std::string const& file);
   void PrintTraceFormatVersion();
 
-  bool GetWarnUninitialized() { return this->WarnUninitialized; }
+  bool GetWarnUninitialized() const { return this->WarnUninitialized; }
   void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
-  bool GetWarnUnusedCli() { return this->WarnUnusedCli; }
+  bool GetWarnUnusedCli() const { return this->WarnUnusedCli; }
   void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; }
-  bool GetCheckSystemVars() { return this->CheckSystemVars; }
+  bool GetCheckSystemVars() const { return this->CheckSystemVars; }
   void SetCheckSystemVars(bool b) { this->CheckSystemVars = b; }
 
   void MarkCliAsUsed(const std::string& variable);
@@ -591,8 +591,8 @@
   using RegisteredExtraGeneratorsVector =
     std::vector<cmExternalMakefileProjectGeneratorFactory*>;
   RegisteredExtraGeneratorsVector ExtraGenerators;
-  void AddScriptingCommands();
-  void AddProjectCommands();
+  void AddScriptingCommands() const;
+  void AddProjectCommands() const;
   void AddDefaultGenerators();
   void AddDefaultExtraGenerators();
 
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index e2ff8b7..ea1f968 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -20,6 +20,7 @@
 #include "cmStateSnapshot.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
+#include "cmTransformDepfile.h"
 #include "cmUVProcessChain.h"
 #include "cmUtils.hxx"
 #include "cmVersion.h"
@@ -28,8 +29,6 @@
 #if !defined(CMAKE_BOOTSTRAP)
 #  include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
 #  include "cmFileTime.h"
-#  include "cmServer.h"
-#  include "cmServerConnection.h"
 
 #  include "bindexplib.h"
 #endif
@@ -61,8 +60,6 @@
 #include "cmsys/Process.h"
 #include "cmsys/Terminal.h"
 
-class cmConnection;
-
 int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
                               std::vector<std::string>::const_iterator argEnd);
 int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
@@ -121,7 +118,6 @@
        "(on one volume)\n"
     << "  rm [-rRf] <file/dir>...    - remove files or directories, use -f to "
        "force it, r or R to remove directories and their contents recursively\n"
-    << "  server                    - start cmake in server mode\n"
     << "  sleep <number>...         - sleep for given number of seconds\n"
     << "  tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n"
     << "                            - create or extract a tar or zip archive\n"
@@ -1359,47 +1355,8 @@
     }
 
     if (args[1] == "server") {
-      const std::string pipePrefix = "--pipe=";
-      bool supportExperimental = false;
-      bool isDebug = false;
-      std::string pipe;
-
-      for (auto const& arg : cmMakeRange(args).advance(2)) {
-        if (arg == "--experimental") {
-          supportExperimental = true;
-        } else if (arg == "--debug") {
-          pipe.clear();
-          isDebug = true;
-        } else if (cmHasPrefix(arg, pipePrefix)) {
-          isDebug = false;
-          pipe = arg.substr(pipePrefix.size());
-          if (pipe.empty()) {
-            cmSystemTools::Error("No pipe given after --pipe=");
-            return 2;
-          }
-        } else {
-          cmSystemTools::Error("Unknown argument for server mode");
-          return 1;
-        }
-      }
-#if !defined(CMAKE_BOOTSTRAP)
-      cmConnection* conn;
-      if (isDebug) {
-        conn = new cmServerStdIoConnection;
-      } else {
-        conn = new cmServerPipeConnection(pipe);
-      }
-      cmServer server(conn, supportExperimental);
-      std::string errorMessage;
-      if (server.Serve(&errorMessage)) {
-        return 0;
-      }
-      cmSystemTools::Error(errorMessage);
-#else
-      static_cast<void>(supportExperimental);
-      static_cast<void>(isDebug);
-      cmSystemTools::Error("CMake was not built with server mode enabled");
-#endif
+      cmSystemTools::Error(
+        "CMake server mode has been removed in favor of the file-api.");
       return 1;
     }
 
@@ -1435,6 +1392,23 @@
       return cmcmd::WindowsCEEnvironment("9.0", args[2]);
     }
 #endif
+
+    // Internal depfile transformation
+    if (args[1] == "cmake_transform_depfile" && args.size() == 6) {
+      auto format = cmDepfileFormat::GccDepfile;
+      if (args[2] == "gccdepfile") {
+        format = cmDepfileFormat::GccDepfile;
+      } else if (args[2] == "vstlog") {
+        format = cmDepfileFormat::VsTlog;
+      } else {
+        return 1;
+      }
+      std::string prefix = args[3];
+      if (prefix == "./") {
+        prefix.clear();
+      }
+      return cmTransformDepfile(format, prefix, args[4], args[5]) ? 0 : 1;
+    }
   }
 
   ::CMakeCommandUsage(args[0].c_str());
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/CMakeLib/testGccDepfileReader.cxx b/Tests/CMakeLib/testGccDepfileReader.cxx
index e79f047..d46e8f3 100644
--- a/Tests/CMakeLib/testGccDepfileReader.cxx
+++ b/Tests/CMakeLib/testGccDepfileReader.cxx
@@ -5,6 +5,8 @@
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
+
 #include "cmsys/FStream.hxx"
 
 #include "cmGccDepfileReader.h"
@@ -112,17 +114,26 @@
 
   std::string dataDirPath = argv[1];
   dataDirPath += "/testGccDepfileReader_data";
-  const int numberOfTestFiles = 3;
+  const int numberOfTestFiles = 7; // 6th file doesn't exist
   for (int i = 1; i <= numberOfTestFiles; ++i) {
     const std::string base = dataDirPath + "/deps" + std::to_string(i);
     const std::string depfile = base + ".d";
     const std::string plainDepfile = base + ".txt";
     std::cout << "Comparing " << base << " with " << plainDepfile << std::endl;
     const auto actual = cmReadGccDepfile(depfile.c_str());
-    const auto expected = readPlainDepfile(plainDepfile.c_str());
-    if (!compare(actual, expected)) {
-      dump("actual", actual);
-      dump("expected", expected);
+    if (cmSystemTools::FileExists(plainDepfile)) {
+      if (!actual) {
+        std::cerr << "Reading " << depfile << " should have succeeded\n";
+        return 1;
+      }
+      const auto expected = readPlainDepfile(plainDepfile.c_str());
+      if (!compare(*actual, expected)) {
+        dump("actual", *actual);
+        dump("expected", expected);
+        return 1;
+      }
+    } else if (actual) {
+      std::cerr << "Reading " << depfile << " should have failed\n";
       return 1;
     }
   }
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps4.d b/Tests/CMakeLib/testGccDepfileReader_data/deps4.d
new file mode 100644
index 0000000..9977a28
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps4.d
@@ -0,0 +1 @@
+invalid
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/CMakeLib/testGccDepfileReader_data/deps5.d
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
copy to Tests/CMakeLib/testGccDepfileReader_data/deps5.d
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps5.txt b/Tests/CMakeLib/testGccDepfileReader_data/deps5.txt
new file mode 100644
index 0000000..6c4a75b
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps5.txt
@@ -0,0 +1,2 @@
+--RULES--
+--DEPENDENCIES--
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps7.d b/Tests/CMakeLib/testGccDepfileReader_data/deps7.d
new file mode 100644
index 0000000..92280cf
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps7.d
@@ -0,0 +1,6 @@
+out1 \
+  out2: \
+  in1 \
+  in2
+
+out3: in3
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps7.txt b/Tests/CMakeLib/testGccDepfileReader_data/deps7.txt
new file mode 100644
index 0000000..86b6600
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps7.txt
@@ -0,0 +1,10 @@
+--RULES--
+out1
+out2
+--DEPENDENCIES--
+in1
+in2
+--RULES--
+out3
+--DEPENDENCIES--
+in3
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 9aa401d..328ab7f 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -240,8 +240,6 @@
 
   if(NOT CMake_TEST_EXTERNAL_CMAKE)
     add_subdirectory(CMakeLib)
-
-    add_subdirectory(CMakeServerLib)
   endif()
   add_subdirectory(CMakeOnly)
   add_subdirectory(RunCMake)
@@ -1422,6 +1420,7 @@
             GTK2
             Iconv
             ICU
+            Intl
             JPEG
             JsonCpp
             LAPACK
@@ -2910,13 +2909,6 @@
   ADD_TEST_MACRO(CMakeCommands.link_directories)
   ADD_TEST_MACRO(CMakeCommands.target_link_directories)
 
-  # The cmake server-mode test requires python for a simple client.
-  find_package(PythonInterp QUIET)
-  if(PYTHON_EXECUTABLE)
-    set(Server_BUILD_OPTIONS -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE})
-    ADD_TEST_MACRO(Server Server)
-  endif()
-
   configure_file(
     "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"
     "${CMake_BINARY_DIR}/Tests/CTestTestCrash/test.cmake"
diff --git a/Tests/CMakeServerLib/CMakeLists.txt b/Tests/CMakeServerLib/CMakeLists.txt
deleted file mode 100644
index 2c23c2d..0000000
--- a/Tests/CMakeServerLib/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-include_directories(
-  ${CMAKE_CURRENT_BINARY_DIR}
-  ${CMake_BINARY_DIR}/Source
-  ${CMake_SOURCE_DIR}/Source
-  )
-
-set(CMakeServerLib_TESTS
-  testServerBuffering.cpp
-  )
-
-create_test_sourcelist(CMakeLib_TEST_SRCS CMakeServerLibTests.cxx ${CMakeServerLib_TESTS})
-add_executable(CMakeServerLibTests ${CMakeLib_TEST_SRCS})
-target_link_libraries(CMakeServerLibTests CMakeLib CMakeServerLib)
-
-SET_PROPERTY(TARGET CMakeServerLibTests PROPERTY C_CLANG_TIDY "")
-SET_PROPERTY(TARGET CMakeServerLibTests PROPERTY CXX_CLANG_TIDY "")
-
-foreach(testfile ${CMakeServerLib_TESTS})
-  get_filename_component(test "${testfile}" NAME_WE)
-  add_test(CMakeServerLib.${test} CMakeServerLibTests ${test} ${${test}_ARGS})
-endforeach()
diff --git a/Tests/CMakeServerLib/testServerBuffering.cpp b/Tests/CMakeServerLib/testServerBuffering.cpp
deleted file mode 100644
index 6f22940..0000000
--- a/Tests/CMakeServerLib/testServerBuffering.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include <iostream>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "cmConnection.h"
-#include "cmServerConnection.h"
-
-void print_error(const std::vector<std::string>& input,
-                 const std::vector<std::string>& output)
-{
-  std::cerr << "Responses don't equal input messages input." << std::endl;
-  std::cerr << "Responses: " << std::endl;
-
-  for (auto& msg : output) {
-    std::cerr << "'" << msg << "'" << std::endl;
-  }
-
-  std::cerr << "Input messages" << std::endl;
-  for (auto& msg : input) {
-    std::cerr << "'" << msg << "'" << std::endl;
-  }
-}
-
-std::string trim_newline(const std::string& _buffer)
-{
-  auto buffer = _buffer;
-  while (!buffer.empty() && (buffer.back() == '\n' || buffer.back() == '\r')) {
-    buffer.pop_back();
-  }
-  return buffer;
-}
-
-int testServerBuffering(int, char** const)
-{
-  std::vector<std::string> messages = {
-    "{ \"test\": 10}", "{ \"test\": { \"test2\": false} }",
-    "{ \"test\": [1, 2, 3] }",
-    "{ \"a\": { \"1\": {}, \n\n\n \"2\":[] \t\t\t\t}}"
-  };
-
-  std::string fullMessage;
-  for (auto& msg : messages) {
-    fullMessage += "[== \"CMake Server\" ==[\n";
-    fullMessage += msg;
-    fullMessage += "\n]== \"CMake Server\" ==]\n";
-  }
-
-  // The buffering strategy should cope with any fragmentation, including
-  // just getting the characters one at a time.
-  auto bufferingStrategy =
-    std::unique_ptr<cmConnectionBufferStrategy>(new cmServerBufferStrategy);
-  std::vector<std::string> response;
-  std::string rawBuffer;
-  for (auto& messageChar : fullMessage) {
-    rawBuffer += messageChar;
-    std::string packet = bufferingStrategy->BufferMessage(rawBuffer);
-    do {
-      if (!packet.empty() && packet != "\r\n") {
-        response.push_back(trim_newline(packet));
-      }
-      packet = bufferingStrategy->BufferMessage(rawBuffer);
-    } while (!packet.empty());
-  }
-
-  if (response != messages) {
-    print_error(messages, response);
-    return 1;
-  }
-
-  // We should also be able to deal with getting a bunch at once
-  response.clear();
-  std::string packet = bufferingStrategy->BufferMessage(fullMessage);
-  do {
-    if (!packet.empty() && packet != "\r\n") {
-      response.push_back(trim_newline(packet));
-    }
-    packet = bufferingStrategy->BufferMessage(fullMessage);
-  } while (!packet.empty());
-
-  if (response != messages) {
-    print_error(messages, response);
-    return 1;
-  }
-
-  return 0;
-}
diff --git a/Tests/FindIntl/CMakeLists.txt b/Tests/FindIntl/CMakeLists.txt
new file mode 100644
index 0000000..0906ede
--- /dev/null
+++ b/Tests/FindIntl/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindIntl.Test COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindIntl/Test"
+  "${CMake_BINARY_DIR}/Tests/FindIntl/Test"
+  ${build_generator_args}
+  --build-project TestFindIntl
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
diff --git a/Tests/FindIntl/Test/CMakeLists.txt b/Tests/FindIntl/Test/CMakeLists.txt
new file mode 100644
index 0000000..5140406
--- /dev/null
+++ b/Tests/FindIntl/Test/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.10)
+project(TestFindIntl CXX)
+include(CTest)
+
+find_package(Intl REQUIRED)
+
+add_executable(test_intl_tgt main.cxx)
+target_link_libraries(test_intl_tgt Intl::Intl)
+add_test(NAME test_intl_tgt COMMAND test_intl_tgt)
+
+add_executable(test_intl_var main.cxx)
+target_include_directories(test_intl_var PRIVATE ${Intl_INCLUDE_DIRS})
+target_link_libraries(test_intl_var PRIVATE ${Intl_LIBRARIES})
+add_test(NAME test_intl_var COMMAND test_intl_var)
diff --git a/Tests/FindIntl/Test/main.cxx b/Tests/FindIntl/Test/main.cxx
new file mode 100644
index 0000000..d90c095
--- /dev/null
+++ b/Tests/FindIntl/Test/main.cxx
@@ -0,0 +1,11 @@
+extern "C" {
+#include <libintl.h>
+}
+
+int main()
+{
+  // Check if we include the directory correctly and have no link errors
+  bindtextdomain("", "");
+  gettext("");
+  return 0;
+}
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/E_server-arg-result.txt
copy to Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt
new file mode 100644
index 0000000..b63c53d
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt
@@ -0,0 +1,17 @@
+^CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+  Cannot find source file:
+
+    main
+Call Stack \(most recent call first\):
+  CMP0115-NEW\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+  No SOURCES given to target: exe
+Call Stack \(most recent call first\):
+  CMP0115-NEW\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Generate step failed\.  Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake b/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake
new file mode 100644
index 0000000..ddf5071
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake
@@ -0,0 +1 @@
+include(CMP0115.cmake)
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/E_server-arg-result.txt
copy to Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt
diff --git a/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt
new file mode 100644
index 0000000..8b90311
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt
@@ -0,0 +1,22 @@
+^CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+  Cannot find source file:
+
+    noexist
+
+  Tried extensions [^
+]*
+  [^
+]*
+Call Stack \(most recent call first\):
+  CMP0115-OLD\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+  No SOURCES given to target: exe
+Call Stack \(most recent call first\):
+  CMP0115-OLD\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Generate step failed\.  Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake b/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake
new file mode 100644
index 0000000..ddf5071
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake
@@ -0,0 +1 @@
+include(CMP0115.cmake)
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/E_server-arg-result.txt
copy to Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt
diff --git a/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt
new file mode 100644
index 0000000..7b100b6
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt
@@ -0,0 +1,36 @@
+^CMake Warning \(dev\) at CMP0115\.cmake:[0-9]+ \(add_executable\):
+  Policy CMP0115 is not set: Source file extensions must be explicit\.  Run
+  "cmake --help-policy CMP0115" for policy details\.  Use the cmake_policy
+  command to set the policy and suppress this warning\.
+
+  File:
+
+    [^
+]*/Tests/RunCMake/CMP0115/main\.c
+Call Stack \(most recent call first\):
+  CMP0115-WARN\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+  Cannot find source file:
+
+    noexist
+
+  Tried extensions [^
+]*
+  [^
+]*
+Call Stack \(most recent call first\):
+  CMP0115-WARN\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+  No SOURCES given to target: exe
+Call Stack \(most recent call first\):
+  CMP0115-WARN\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Generate step failed\.  Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake b/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake
new file mode 100644
index 0000000..ddf5071
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake
@@ -0,0 +1 @@
+include(CMP0115.cmake)
diff --git a/Tests/RunCMake/CMP0115/CMP0115.cmake b/Tests/RunCMake/CMP0115/CMP0115.cmake
new file mode 100644
index 0000000..be910a4
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+
+add_executable(exe main noexist)
diff --git a/Tests/RunCMake/CMP0115/CMakeLists.txt b/Tests/RunCMake/CMP0115/CMakeLists.txt
new file mode 100644
index 0000000..b646c4a
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0115/RunCMakeTest.cmake b/Tests/RunCMake/CMP0115/RunCMakeTest.cmake
new file mode 100644
index 0000000..58182ac
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/RunCMakeTest.cmake
@@ -0,0 +1,12 @@
+include(RunCMake)
+
+function(run_cmp0115 status)
+  if(NOT status STREQUAL "WARN")
+    set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0115=${status})
+  endif()
+  run_cmake(CMP0115-${status})
+endfunction()
+
+run_cmp0115(OLD)
+run_cmp0115(WARN)
+run_cmp0115(NEW)
diff --git a/Tests/RunCMake/CMP0115/main.c b/Tests/RunCMake/CMP0115/main.c
new file mode 100644
index 0000000..8488f4e
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/CMP0116/CMP0116-NEW-NOWARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-NEW-NOWARN.cmake
new file mode 100644
index 0000000..f92fac6
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-NEW-NOWARN.cmake
@@ -0,0 +1,3 @@
+set(depdir)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-NEW-WARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-NEW-WARN.cmake
new file mode 100644
index 0000000..f92fac6
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-NEW-WARN.cmake
@@ -0,0 +1,3 @@
+set(depdir)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-OLD-NOWARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-OLD-NOWARN.cmake
new file mode 100644
index 0000000..665f485
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-OLD-NOWARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-OLD-WARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-OLD-WARN.cmake
new file mode 100644
index 0000000..665f485
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-OLD-WARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN-stderr.txt b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN-stderr.txt
new file mode 100644
index 0000000..843ff1c
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN-stderr.txt
@@ -0,0 +1,7 @@
+^(CMake Warning \(dev\) at Subdirectory/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+  Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+  add_custom_command\(\)\.  Run "cmake --help-policy CMP0116" for policy
+  details\.  Use the cmake_policy command to set the policy and suppress this
+  warning\.
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+*)+$
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN.cmake
new file mode 100644
index 0000000..665f485
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN-stderr.txt b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN-stderr.txt
new file mode 100644
index 0000000..e29af91
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN-stderr.txt
@@ -0,0 +1,16 @@
+^(CMake Warning \(dev\) at Common\.cmake:[0-9]+ \(add_custom_command\):
+  Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+  add_custom_command\(\)\.  Run "cmake --help-policy CMP0116" for policy
+  details\.  Use the cmake_policy command to set the policy and suppress this
+  warning\.
+Call Stack \(most recent call first\):
+  CMP0116-WARN-WARN\.cmake:[0-9]+ \(include\)
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
++)+(CMake Warning \(dev\) at Subdirectory/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+  Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+  add_custom_command\(\)\.  Run "cmake --help-policy CMP0116" for policy
+  details\.  Use the cmake_policy command to set the policy and suppress this
+  warning\.
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+*)+$
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN.cmake
new file mode 100644
index 0000000..665f485
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMakeLists.txt b/Tests/RunCMake/CMP0116/CMakeLists.txt
new file mode 100644
index 0000000..b646c4a
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0116/Common.cmake b/Tests/RunCMake/CMP0116/Common.cmake
new file mode 100644
index 0000000..472b162
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/Common.cmake
@@ -0,0 +1,8 @@
+add_custom_command(
+  OUTPUT top.txt
+  COMMAND ${CMAKE_COMMAND} -DOUTFILE=top.txt -DINFILE=topdep.txt -DDEPFILE=top.txt.d -DSTAMPFILE=topstamp.txt -DDEPDIR= -P ${CMAKE_SOURCE_DIR}/WriteDepfile.cmake
+  DEPFILE top.txt.d
+  )
+add_custom_target(top ALL DEPENDS top.txt)
+
+add_subdirectory(Subdirectory)
diff --git a/Tests/RunCMake/CMP0116/RunCMakeTest.cmake b/Tests/RunCMake/CMP0116/RunCMakeTest.cmake
new file mode 100644
index 0000000..8a83cc1
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/RunCMakeTest.cmake
@@ -0,0 +1,49 @@
+include(RunCMake)
+
+function(run_cmp0116 status warn)
+  if(warn)
+    set(name CMP0116-${status}-WARN)
+  else()
+    set(name CMP0116-${status}-NOWARN)
+  endif()
+  set(RunCMake_TEST_OPTIONS
+    -DCMAKE_POLICY_WARNING_CMP0116:BOOL=${warn}
+    )
+  if(NOT status STREQUAL "WARN")
+    list(APPEND RunCMake_TEST_OPTIONS
+      -DCMAKE_POLICY_DEFAULT_CMP0116:STRING=${status}
+      )
+  endif()
+
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+  run_cmake(${name})
+  unset(RunCMake_TEST_OPTIONS)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake-check-file check.cmake)
+
+  file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topdep.txt")
+  file(TOUCH "${RunCMake_TEST_BINARY_DIR}/Subdirectory/subdep.txt")
+  set(cmp0116_step 1)
+  run_cmake_command(${name}-build1 ${CMAKE_COMMAND} --build . --config Debug)
+  file(REMOVE "${RunCMake_TEST_BINARY_DIR}/topstamp.txt")
+  file(REMOVE "${RunCMake_TEST_BINARY_DIR}/Subdirectory/substamp.txt")
+  execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1.25)
+
+  file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topdep.txt")
+  file(TOUCH "${RunCMake_TEST_BINARY_DIR}/Subdirectory/subdep.txt")
+  set(cmp0116_step 2)
+  run_cmake_command(${name}-build2 ${CMAKE_COMMAND} --build . --config Debug)
+  file(REMOVE "${RunCMake_TEST_BINARY_DIR}/topstamp.txt")
+  file(REMOVE "${RunCMake_TEST_BINARY_DIR}/Subdirectory/substamp.txt")
+  execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1.25)
+
+  set(cmp0116_step 3)
+  run_cmake_command(${name}-build3 ${CMAKE_COMMAND} --build . --config Debug)
+endfunction()
+
+run_cmp0116(WARN OFF)
+run_cmp0116(OLD OFF)
+run_cmp0116(NEW OFF)
+run_cmp0116(WARN ON)
+run_cmp0116(OLD ON)
+run_cmp0116(NEW ON)
diff --git a/Tests/RunCMake/CMP0116/Subdirectory/CMakeLists.txt b/Tests/RunCMake/CMP0116/Subdirectory/CMakeLists.txt
new file mode 100644
index 0000000..f0f60b2
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/Subdirectory/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_custom_command(
+  OUTPUT sub.txt
+  COMMAND ${CMAKE_COMMAND} -DOUTFILE=sub.txt -DINFILE=subdep.txt -DDEPFILE=sub.txt.d -DSTAMPFILE=substamp.txt -DDEPDIR=${depdir} -P ${CMAKE_SOURCE_DIR}/WriteDepfile.cmake
+  DEPFILE ${depdir}sub.txt.d
+  )
+add_custom_target(sub ALL DEPENDS sub.txt)
diff --git a/Tests/RunCMake/CMP0116/WriteDepfile.cmake b/Tests/RunCMake/CMP0116/WriteDepfile.cmake
new file mode 100644
index 0000000..1a74d2a
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/WriteDepfile.cmake
@@ -0,0 +1,3 @@
+file(TOUCH "${OUTFILE}")
+file(TOUCH "${STAMPFILE}")
+file(WRITE "${DEPFILE}" "${DEPDIR}${OUTFILE}: ${DEPDIR}${INFILE}\n")
diff --git a/Tests/RunCMake/CMP0116/check.cmake b/Tests/RunCMake/CMP0116/check.cmake
new file mode 100644
index 0000000..1b16748
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/check.cmake
@@ -0,0 +1,18 @@
+function(check_exists file)
+  if(NOT EXISTS "${file}")
+    string(APPEND RunCMake_TEST_FAILED "${file} does not exist\n")
+  endif()
+  set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
+
+function(check_not_exists file)
+  if(EXISTS "${file}")
+    string(APPEND RunCMake_TEST_FAILED "${file} exists\n")
+  endif()
+  set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
+
+if(cmp0116_step EQUAL 3)
+  check_not_exists("${RunCMake_TEST_BINARY_DIR}/topstamp.txt")
+  check_not_exists("${RunCMake_TEST_BINARY_DIR}/Subdirectory/substamp.txt")
+endif()
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 7b85061..38ab553 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -125,6 +125,10 @@
 endif()
 add_RunCMake_test(CMP0106)
 add_RunCMake_test(CMP0111)
+add_RunCMake_test(CMP0115)
+if(CMAKE_GENERATOR MATCHES "Ninja")
+  add_RunCMake_test(CMP0116)
+endif()
 
 # The test for Policy 65 requires the use of the
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
@@ -770,6 +774,7 @@
 
 add_RunCMake_test("UnityBuild")
 add_RunCMake_test(CMakePresets -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA})
+add_RunCMake_test(TransformDepfile)
 
 if(WIN32)
   add_RunCMake_test(Win32GenEx)
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/InvalidCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/EmptyEnv.json.in
similarity index 62%
rename from Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
rename to Tests/RunCMake/CMakePresets/EmptyEnv.json.in
index 1479c66..ef0d575 100644
--- a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
+++ b/Tests/RunCMake/CMakePresets/EmptyEnv.json.in
@@ -2,10 +2,12 @@
   "version": 1,
   "configurePresets": [
     {
-      "name": "InvalidCMakeGeneratorConfig",
+      "name": "EmptyEnv",
       "generator": "@RunCMake_GENERATOR@",
       "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": {}
+      "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/InvalidCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/EmptyPenv.json.in
similarity index 61%
copy from Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
copy to Tests/RunCMake/CMakePresets/EmptyPenv.json.in
index 1479c66..9081fe5 100644
--- a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
+++ b/Tests/RunCMake/CMakePresets/EmptyPenv.json.in
@@ -2,10 +2,12 @@
   "version": 1,
   "configurePresets": [
     {
-      "name": "InvalidCMakeGeneratorConfig",
+      "name": "EmptyPenv",
       "generator": "@RunCMake_GENERATOR@",
       "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": {}
+      "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/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/InvalidCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy.json.in
similarity index 61%
copy from Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
copy to Tests/RunCMake/CMakePresets/InvalidToolsetStrategy.json.in
index 1479c66..7d2ab1f 100644
--- a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
+++ b/Tests/RunCMake/CMakePresets/InvalidToolsetStrategy.json.in
@@ -2,10 +2,12 @@
   "version": 1,
   "configurePresets": [
     {
-      "name": "InvalidCMakeGeneratorConfig",
+      "name": "InvalidToolsetStrategy",
       "generator": "@RunCMake_GENERATOR@",
       "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": {}
+      "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/UnknownCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
deleted file mode 100644
index 900c6df..0000000
--- a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "version": 1,
-  "configurePresets": [
-    {
-      "name": "UnknownCMakeGeneratorConfig",
-      "generator": "@RunCMake_GENERATOR@",
-      "binaryDir": "${sourceDir}/build",
-      "cmakeGeneratorConfig": "unknown"
-    }
-  ]
-}
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/CheckModules/CMP0075-stderr.txt b/Tests/RunCMake/CheckModules/CMP0075-stderr.txt
index 960fe94..97833f5 100644
--- a/Tests/RunCMake/CheckModules/CMP0075-stderr.txt
+++ b/Tests/RunCMake/CheckModules/CMP0075-stderr.txt
@@ -47,4 +47,15 @@
 Call Stack \(most recent call first\):
   CMP0075.cmake:41 \(check_include_files\)
   CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers.  Use -Wno-dev to suppress it.$
+This warning is for project developers.  Use -Wno-dev to suppress it.
++
+CMake Deprecation Warning at CMP0075.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0075 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
index e24e131..a8b6584 100644
--- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
+++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
@@ -1 +1 @@
-^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":2}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$
+^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":2}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"version":{.*}}$
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-stderr.txt b/Tests/RunCMake/CommandLine/E_server-arg-stderr.txt
deleted file mode 100644
index 4dcbab9..0000000
--- a/Tests/RunCMake/CommandLine/E_server-arg-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^CMake Error: Unknown argument for server mode$
diff --git a/Tests/RunCMake/CommandLine/E_server-pipe-result.txt b/Tests/RunCMake/CommandLine/E_server-pipe-result.txt
deleted file mode 100644
index 0cfbf08..0000000
--- a/Tests/RunCMake/CommandLine/E_server-pipe-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-2
diff --git a/Tests/RunCMake/CommandLine/E_server-pipe-stderr.txt b/Tests/RunCMake/CommandLine/E_server-pipe-stderr.txt
deleted file mode 100644
index 7193ba6..0000000
--- a/Tests/RunCMake/CommandLine/E_server-pipe-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^CMake Error: No pipe given after --pipe=$
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/CommandLine/E_server-result.txt
similarity index 100%
rename from Tests/RunCMake/CommandLine/E_server-arg-result.txt
rename to Tests/RunCMake/CommandLine/E_server-result.txt
diff --git a/Tests/RunCMake/CommandLine/E_server-stderr.txt b/Tests/RunCMake/CommandLine/E_server-stderr.txt
new file mode 100644
index 0000000..0cd0e56
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_server-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: CMake server mode has been removed in favor of the file-api\.$
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index b23c8c2..76ca898 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -25,8 +25,7 @@
 run_cmake_command(E_compare_files-invalid-arguments ${CMAKE_COMMAND} -E compare_files file1.txt file2.txt file3.txt)
 run_cmake_command(E_echo_append ${CMAKE_COMMAND} -E echo_append)
 run_cmake_command(E_rename-no-arg ${CMAKE_COMMAND} -E rename)
-run_cmake_command(E_server-arg ${CMAKE_COMMAND} -E server --extra-arg)
-run_cmake_command(E_server-pipe ${CMAKE_COMMAND} -E server --pipe=)
+run_cmake_command(E_server ${CMAKE_COMMAND} -E server)
 run_cmake_command(E_true ${CMAKE_COMMAND} -E true)
 run_cmake_command(E_true-extraargs ${CMAKE_COMMAND} -E true ignored)
 run_cmake_command(E_false ${CMAKE_COMMAND} -E false)
diff --git a/Tests/RunCMake/ToolchainFile/CheckLanguage-stdout.txt b/Tests/RunCMake/ToolchainFile/CheckLanguage-stdout.txt
new file mode 100644
index 0000000..b96eee6
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/CheckLanguage-stdout.txt
@@ -0,0 +1 @@
+-- Looking for a C compiler - NOTFOUND
diff --git a/Tests/RunCMake/ToolchainFile/CheckLanguage-toolchain.cmake b/Tests/RunCMake/ToolchainFile/CheckLanguage-toolchain.cmake
new file mode 100644
index 0000000..081f905
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/CheckLanguage-toolchain.cmake
@@ -0,0 +1,4 @@
+get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE)
+if(in_try_compile)
+  message(FATAL_ERROR "Toolchain file included")
+endif()
diff --git a/Tests/RunCMake/ToolchainFile/CheckLanguage.cmake b/Tests/RunCMake/ToolchainFile/CheckLanguage.cmake
new file mode 100644
index 0000000..854b3d4
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/CheckLanguage.cmake
@@ -0,0 +1,2 @@
+include(CheckLanguage)
+check_language(C)
diff --git a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
index 7eb4485..659523c 100644
--- a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
@@ -7,6 +7,7 @@
 
 run_cmake_toolchain(CallEnableLanguage)
 run_cmake_toolchain(CallProject)
+run_cmake_toolchain(CheckLanguage)
 run_cmake_toolchain(FlagsInit)
 run_cmake_toolchain(LinkFlagsInit)
 
diff --git a/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake
new file mode 100644
index 0000000..cb75eb0
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake
@@ -0,0 +1,21 @@
+include(RunCMake)
+
+function(run_transform_depfile name)
+  set(RunCMake-check-file gccdepfile.cmake)
+  run_cmake_command(${name}-gcc
+    ${CMAKE_COMMAND} -E cmake_transform_depfile gccdepfile ../ ${CMAKE_CURRENT_LIST_DIR}/${name}.d out.d
+    )
+  set(RunCMake-check-file vstlog.cmake)
+  run_cmake_command(${name}-tlog
+    ${CMAKE_COMMAND} -E cmake_transform_depfile vstlog ../ ${CMAKE_CURRENT_LIST_DIR}/${name}.d out.tlog
+    )
+endfunction()
+
+if(WIN32)
+  run_transform_depfile(deps-windows)
+else()
+  run_transform_depfile(deps-unix)
+endif()
+run_transform_depfile(noexist)
+run_transform_depfile(empty)
+run_transform_depfile(invalid)
diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.d b/Tests/RunCMake/TransformDepfile/deps-unix.d
new file mode 100644
index 0000000..5da5be8
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-unix.d
@@ -0,0 +1,6 @@
+out1 /home/build/out2: in1 /home/build/in2
+
+out3 \
+  /home/build/out4: \
+  in3 \
+  /home/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.d.txt b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt
new file mode 100644
index 0000000..58770f2
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt
@@ -0,0 +1,8 @@
+../out1 \
+  /home/build/out2: \
+  ../in1 \
+  /home/build/in2
+../out3 \
+  /home/build/out4: \
+  ../in3 \
+  /home/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt
new file mode 100644
index 0000000..2a26edf
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt
@@ -0,0 +1,6 @@
+^../out1|/home/build/out2
+../in1
+/home/build/in2
+^../out3|/home/build/out4
+../in3
+/home/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.d b/Tests/RunCMake/TransformDepfile/deps-windows.d
new file mode 100644
index 0000000..c926670
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-windows.d
@@ -0,0 +1,6 @@
+out1 C:/build/out2: in1 C:/build/in2
+
+out3 \
+  C:/build/out4: \
+  in3 \
+  C:/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.d.txt b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt
new file mode 100644
index 0000000..47b3ebf
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt
@@ -0,0 +1,8 @@
+../out1 \
+  C:/build/out2: \
+  ../in1 \
+  C:/build/in2
+../out3 \
+  C:/build/out4: \
+  ../in3 \
+  C:/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt
new file mode 100644
index 0000000..1e6024d
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt
@@ -0,0 +1,6 @@
+^..\out1|C:\build\out2
+..\in1
+C:\build\in2
+^..\out3|C:\build\out4
+..\in3
+C:\build\in4
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/RunCMake/TransformDepfile/empty.d
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
copy to Tests/RunCMake/TransformDepfile/empty.d
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/RunCMake/TransformDepfile/empty.d.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
copy to Tests/RunCMake/TransformDepfile/empty.d.txt
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/RunCMake/TransformDepfile/empty.tlog.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
copy to Tests/RunCMake/TransformDepfile/empty.tlog.txt
diff --git a/Tests/RunCMake/TransformDepfile/gccdepfile.cmake b/Tests/RunCMake/TransformDepfile/gccdepfile.cmake
new file mode 100644
index 0000000..be1e210
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/gccdepfile.cmake
@@ -0,0 +1,16 @@
+if(EXISTS "${RunCMake_SOURCE_DIR}/${name}.d.txt")
+  file(READ "${RunCMake_SOURCE_DIR}/${name}.d.txt" expected_contents)
+
+  if(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.d")
+    file(READ "${RunCMake_TEST_BINARY_DIR}/out.d" actual_contents)
+    if(NOT actual_contents STREQUAL expected_contents)
+      string(REPLACE "\n" "\n  " p_expected_contents "${expected_contents}")
+      string(REPLACE "\n" "\n  " p_actual_contents "${actual_contents}")
+      string(APPEND RunCMake_TEST_FAILED "Expected contents of ${RunCMake_TEST_BINARY_DIR}/out.d:\n  ${p_expected_contents}\nActual contents:\n  ${p_actual_contents}")
+    endif()
+  else()
+    string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.d should exist\n")
+  endif()
+elseif(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.d")
+  string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.d should not exist\n")
+endif()
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/E_server-arg-result.txt
copy to Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/E_server-arg-result.txt
copy to Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt
diff --git a/Tests/RunCMake/TransformDepfile/invalid.d b/Tests/RunCMake/TransformDepfile/invalid.d
new file mode 100644
index 0000000..9977a28
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/invalid.d
@@ -0,0 +1 @@
+invalid
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/RunCMake/TransformDepfile/noexist.d.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
copy to Tests/RunCMake/TransformDepfile/noexist.d.txt
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/RunCMake/TransformDepfile/noexist.tlog.txt
similarity index 100%
copy from Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
copy to Tests/RunCMake/TransformDepfile/noexist.tlog.txt
diff --git a/Tests/RunCMake/TransformDepfile/vstlog.cmake b/Tests/RunCMake/TransformDepfile/vstlog.cmake
new file mode 100644
index 0000000..afa78d0
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/vstlog.cmake
@@ -0,0 +1,16 @@
+if(EXISTS "${RunCMake_SOURCE_DIR}/${name}.tlog.txt")
+  file(READ "${RunCMake_SOURCE_DIR}/${name}.tlog.txt" expected_contents)
+
+  if(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog")
+    file(READ "${RunCMake_TEST_BINARY_DIR}/out.tlog" actual_contents)
+    if(NOT actual_contents STREQUAL expected_contents)
+      string(REPLACE "\n" "\n  " p_expected_contents "${expected_contents}")
+      string(REPLACE "\n" "\n  " p_actual_contents "${actual_contents}")
+      string(APPEND RunCMake_TEST_FAILED "Expected contents of ${RunCMake_TEST_BINARY_DIR}/out.tlog:\n  ${p_expected_contents}\nActual contents:\n  ${p_actual_contents}")
+    endif()
+  else()
+    string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should exist\n")
+  endif()
+elseif(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog")
+  string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should not exist\n")
+endif()
diff --git a/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt b/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
index b7ee23a..9324302 100644
--- a/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
+++ b/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
@@ -1,5 +1,5 @@
 CMake Error at AppendNotOutput.cmake:1 \(add_custom_command\):
-  add_custom_command given APPEND option with output
+  Attempt to APPEND to custom command with output
 
     .*RunCMake/add_custom_command/AppendNotOutput-build/out
 
diff --git a/Tests/RunCMake/add_library/CMP0073-stderr.txt b/Tests/RunCMake/add_library/CMP0073-stderr.txt
new file mode 100644
index 0000000..7f43fd7
--- /dev/null
+++ b/Tests/RunCMake/add_library/CMP0073-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0073.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0073 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
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/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/include/IncludeIsDirectory-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/E_server-arg-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/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/include/IncludeMalformed-result.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/E_server-arg-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(
diff --git a/Tests/Server/CMakeLists.txt b/Tests/Server/CMakeLists.txt
deleted file mode 100644
index 8321edb..0000000
--- a/Tests/Server/CMakeLists.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-cmake_minimum_required(VERSION 3.4)
-project(Server CXX)
-
-find_package(Python REQUIRED)
-
-macro(do_test bsname file type)
-  execute_process(COMMAND ${Python_EXECUTABLE}
-    -B # no .pyc files
-    "${CMAKE_SOURCE_DIR}/${type}-test.py"
-    "${CMAKE_COMMAND}"
-    "${CMAKE_SOURCE_DIR}/${file}"
-    "${CMAKE_SOURCE_DIR}"
-    "${CMAKE_BINARY_DIR}"
-    "${CMAKE_GENERATOR}"
-    RESULT_VARIABLE test_result
-    )
-
-  if (NOT test_result EQUAL 0)
-    message(SEND_ERROR "TEST FAILED: ${test_result}")
-  endif()
-endmacro()
-
-do_test("test_cache" "tc_cache.json" "server")
-do_test("test_handshake" "tc_handshake.json" "server")
-do_test("test_globalSettings" "tc_globalSettings.json" "server")
-do_test("test_buildsystem1" "tc_buildsystem1.json" "server")
-
-add_executable(Server empty.cpp)
diff --git a/Tests/Server/buildsystem1/CMakeLists.txt b/Tests/Server/buildsystem1/CMakeLists.txt
deleted file mode 100644
index d690472..0000000
--- a/Tests/Server/buildsystem1/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-cmake_minimum_required(VERSION 3.4)
-
-project(buildsystem2)
-
-set(var1 123)
-
-set(var2 345)
-
-add_executable(main main.cpp)
-
-add_executable(m_other main.cpp)
-
-add_library(foo foo.cpp)
-
-function(f1)
-endfunction()
-
-set(var3 345)
-
-add_library(someImportedLib UNKNOWN IMPORTED)
-
-add_subdirectory(subdir)
diff --git a/Tests/Server/buildsystem1/foo.cpp b/Tests/Server/buildsystem1/foo.cpp
deleted file mode 100644
index 7f39d71..0000000
--- a/Tests/Server/buildsystem1/foo.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int foo()
-{
-  return 0;
-}
diff --git a/Tests/Server/buildsystem1/main.cpp b/Tests/Server/buildsystem1/main.cpp
deleted file mode 100644
index 766b775..0000000
--- a/Tests/Server/buildsystem1/main.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int main()
-{
-  return 0;
-}
diff --git a/Tests/Server/buildsystem1/subdir/CMakeLists.txt b/Tests/Server/buildsystem1/subdir/CMakeLists.txt
deleted file mode 100644
index 9157312..0000000
--- a/Tests/Server/buildsystem1/subdir/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-set(bar4 something)
-
-set(bar5 more)
-
-add_executable(ooo empty.cpp)
diff --git a/Tests/Server/buildsystem1/subdir/empty.cpp b/Tests/Server/buildsystem1/subdir/empty.cpp
deleted file mode 100644
index 7f39d71..0000000
--- a/Tests/Server/buildsystem1/subdir/empty.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int foo()
-{
-  return 0;
-}
diff --git a/Tests/Server/cmakelib.py b/Tests/Server/cmakelib.py
deleted file mode 100644
index 546ae4c..0000000
--- a/Tests/Server/cmakelib.py
+++ /dev/null
@@ -1,380 +0,0 @@
-from __future__ import print_function
-import sys, subprocess, json, os, select, shutil, time, socket
-
-termwidth = 150
-
-print_communication = True
-
-def ordered(obj):
-  if isinstance(obj, dict):
-    return sorted((k, ordered(v)) for k, v in obj.items())
-  if isinstance(obj, list):
-    return sorted(ordered(x) for x in obj)
-  else:
-    return obj
-
-def col_print(title, array):
-  print()
-  print()
-  print(title)
-
-  indentwidth = 4
-  indent = " " * indentwidth
-
-  if not array:
-    print(indent + "<None>")
-    return
-
-  padwidth = 2
-
-  maxitemwidth = len(max(array, key=len))
-
-  numCols = max(1, int((termwidth - indentwidth + padwidth) / (maxitemwidth + padwidth)))
-
-  numRows = len(array) // numCols + 1
-
-  pad = " " * padwidth
-
-  for index in range(numRows):
-    print(indent + pad.join(item.ljust(maxitemwidth) for item in array[index::numRows]))
-
-filterPacket = lambda x: x
-
-STDIN = 0
-PIPE = 1
-
-communicationMethods = [STDIN]
-
-if hasattr(socket, 'AF_UNIX'):
-  communicationMethods.append(PIPE)
-
-def defaultExitWithError(proc):
-  data = ""
-  try:
-    while select.select([proc.outPipe], [], [], 3.)[0]:
-      data = data + proc.outPipe.read(1)
-    if len(data):
-      print("Rest of raw buffer from server:")
-      printServer(data)
-  except:
-    pass
-  proc.outPipe.close()
-  proc.inPipe.close()
-  proc.kill()
-  sys.exit(1)
-
-exitWithError = lambda proc: defaultExitWithError(proc)
-
-serverTag = "SERVER"
-
-def printServer(*args):
-    print(serverTag + ">", *args)
-    print()
-    sys.stdout.flush()
-
-def printClient(*args):
-    print("CLIENT>", *args)
-    print()
-    sys.stdout.flush()
-
-def waitForRawMessage(cmakeCommand):
-  stdoutdata = ""
-  payload = ""
-  while not cmakeCommand.poll():
-    stdoutdataLine = cmakeCommand.outPipe.readline()
-    if stdoutdataLine:
-      stdoutdata += stdoutdataLine.decode('utf-8')
-    else:
-      break
-    begin = stdoutdata.find('[== "CMake Server" ==[\n')
-    end = stdoutdata.find(']== "CMake Server" ==]')
-
-    if begin != -1 and end != -1:
-      begin += len('[== "CMake Server" ==[\n')
-      payload = stdoutdata[begin:end]
-      jsonPayload = json.loads(payload)
-      filteredPayload = filterPacket(jsonPayload)
-      if print_communication and filteredPayload:
-        printServer(filteredPayload)
-      if filteredPayload is not None or jsonPayload is None:
-          return jsonPayload
-      stdoutdata = stdoutdata[(end+len(']== "CMake Server" ==]')):]
-
-# Python2 has no problem writing the output of encodes directly,
-# but Python3 returns only 'int's for encode and so must be turned
-# into bytes. We use the existence of 'to_bytes' on an int to
-# determine which behavior is appropriate. It might be more clear
-# to do this in the code which uses the flag, but introducing
-# this lookup cost at every byte sent isn't ideal.
-has_to_bytes = "to_bytes" in dir(10)
-
-def writeRawData(cmakeCommand, content):
-  writeRawData.counter += 1
-  payload = """
-[== "CMake Server" ==[
-%s
-]== "CMake Server" ==]
-""" % content
-
-  rn = ( writeRawData.counter % 2 ) == 0
-
-  if rn:
-    payload = payload.replace('\n', '\r\n')
-
-  if print_communication:
-    printClient(content, "(Use \\r\\n:", rn, ")")
-
-  # To stress test how cmake deals with fragmentation in the
-  # communication channel, we send only one byte at a time.
-  # Certain communication methods / platforms might still buffer
-  # it all into one message since its so close together, but in
-  # general this will catch places where we assume full buffers
-  # come in all at once.
-  encoded_payload = payload.encode('utf-8')
-
-  # Python version 3+ can't write ints directly; but 'to_bytes'
-  # for int was only added in python 3.2. If this is a 3+ version
-  # of python without that conversion function; just write the whole
-  # thing out at once.
-  if sys.version_info[0] > 2 and not has_to_bytes:
-    cmakeCommand.write(encoded_payload)
-  else:
-    for c in encoded_payload:
-      if has_to_bytes:
-        c = c.to_bytes(1, byteorder='big')
-      cmakeCommand.write(c)
-
-writeRawData.counter = 0
-
-def writePayload(cmakeCommand, obj):
-  writeRawData(cmakeCommand, json.dumps(obj))
-
-def getPipeName():
-  return "/tmp/server-test-socket"
-
-def attachPipe(cmakeCommand, pipeName):
-  time.sleep(1)
-  sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-  sock.connect(pipeName)
-  global serverTag
-  serverTag = "SERVER(PIPE)"
-  cmakeCommand.outPipe = sock.makefile()
-  cmakeCommand.inPipe = sock
-  cmakeCommand.write = cmakeCommand.inPipe.sendall
-
-def writeAndFlush(pipe, val):
-  pipe.write(val)
-  pipe.flush()
-
-def initServerProc(cmakeCommand, comm):
-  if comm == PIPE:
-    pipeName = getPipeName()
-    cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--pipe=" + pipeName])
-    attachPipe(cmakeCommand, pipeName)
-  else:
-    cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--debug"],
-                                    stdin=subprocess.PIPE,
-                                    stdout=subprocess.PIPE)
-    cmakeCommand.outPipe = cmakeCommand.stdout
-    cmakeCommand.inPipe = cmakeCommand.stdin
-    cmakeCommand.write = lambda val: writeAndFlush(cmakeCommand.inPipe, val)
-
-  packet = waitForRawMessage(cmakeCommand)
-  if packet == None:
-    print("Not in server mode")
-    sys.exit(2)
-
-  if packet['type'] != 'hello':
-    print("No hello message")
-    sys.exit(3)
-
-  return cmakeCommand
-
-def exitProc(cmakeCommand):
-  # Tell the server to exit.
-  cmakeCommand.stdin.close()
-  cmakeCommand.stdout.close()
-
-  # Wait for the server to exit.
-  # If this version of python supports it, terminate the server after a timeout.
-  try:
-    cmakeCommand.wait(timeout=5)
-  except TypeError:
-    cmakeCommand.wait()
-  except:
-    cmakeCommand.terminate()
-    raise
-
-def waitForMessage(cmakeCommand, expected):
-  data = ordered(expected)
-  packet = ordered(waitForRawMessage(cmakeCommand))
-
-  if packet != data:
-    print ("Received unexpected message; test failed")
-    exitWithError(cmakeCommand)
-  return packet
-
-def waitForReply(cmakeCommand, originalType, cookie, skipProgress):
-  gotResult = False
-  while True:
-    packet = waitForRawMessage(cmakeCommand)
-    t = packet['type']
-    if packet['cookie'] != cookie or packet['inReplyTo'] != originalType:
-      print("cookie or inReplyTo mismatch")
-      sys.exit(4)
-    if t == 'message' or t == 'progress':
-      if skipProgress:
-        continue
-    if t == 'reply':
-        break
-    print("Unrecognized message", packet)
-    sys.exit(5)
-
-  return packet
-
-def waitForError(cmakeCommand, originalType, cookie, message):
-  packet = waitForRawMessage(cmakeCommand)
-  if packet['cookie'] != cookie or packet['type'] != 'error' or packet['inReplyTo'] != originalType or packet['errorMessage'] != message:
-    sys.exit(6)
-
-def waitForProgress(cmakeCommand, originalType, cookie, current, message):
-  packet = waitForRawMessage(cmakeCommand)
-  if packet['cookie'] != cookie or packet['type'] != 'progress' or packet['inReplyTo'] != originalType or packet['progressCurrent'] != current or packet['progressMessage'] != message:
-    sys.exit(7)
-
-def handshake(cmakeCommand, major, minor, source, build, generator, extraGenerator):
-  version = { 'major': major }
-  if minor >= 0:
-    version['minor'] = minor
-
-  writePayload(cmakeCommand, { 'type': 'handshake', 'protocolVersion': version,
-    'cookie': 'TEST_HANDSHAKE', 'sourceDirectory': source, 'buildDirectory': build,
-    'generator': generator, 'extraGenerator': extraGenerator })
-  waitForReply(cmakeCommand, 'handshake', 'TEST_HANDSHAKE', False)
-
-def validateGlobalSettings(cmakeCommand, cmakeCommandPath, data):
-  packet = waitForReply(cmakeCommand, 'globalSettings', '', False)
-
-  capabilities = packet['capabilities']
-
-  # validate version:
-  cmakeoutput = subprocess.check_output([ cmakeCommandPath, "--version" ], universal_newlines=True)
-  cmakeVersion = cmakeoutput.splitlines()[0][14:]
-
-  version = capabilities['version']
-  versionString = version['string']
-  vs = str(version['major']) + '.' + str(version['minor']) + '.' + str(version['patch'])
-  if (versionString != vs and not versionString.startswith(vs + '-')):
-    sys.exit(8)
-  if (versionString != cmakeVersion):
-    sys.exit(9)
-
-  # validate generators:
-  generatorObjects = capabilities['generators']
-
-  cmakeoutput = subprocess.check_output([ cmakeCommandPath, "--help" ], universal_newlines=True)
-  index = cmakeoutput.index('\nGenerators\n\n')
-  cmakeGenerators = []
-  for line in cmakeoutput[index + 12:].splitlines():
-    if not line:
-      continue
-    if line[0] == '*': # default generator marker
-      line = ' ' + line[1:]
-    if not line.startswith('  '):
-      continue
-    if line.startswith('    '):
-      continue
-    equalPos = line.find('=')
-    tmp = ''
-    if (equalPos > 0):
-      tmp = line[2:equalPos].strip()
-    else:
-      tmp = line.strip()
-    if tmp.endswith(" [arch]"):
-      tmp = tmp[0:len(tmp) - 7]
-    if (len(tmp) > 0) and (" - " not in tmp):
-      cmakeGenerators.append(tmp)
-
-  generators = []
-  for genObj in generatorObjects:
-    generators.append(genObj['name'])
-
-  generators.sort()
-  cmakeGenerators.sort()
-
-  for gen in cmakeGenerators:
-    if (not gen in generators):
-        sys.exit(10)
-
-  gen = packet['generator']
-  if (gen != '' and not (gen in generators)):
-    sys.exit(11)
-
-  for i in data:
-    print("Validating", i)
-    if (packet[i] != data[i]):
-      sys.exit(12)
-
-def validateCache(cmakeCommand, data):
-  packet = waitForReply(cmakeCommand, 'cache', '', False)
-
-  cache = packet['cache']
-
-  if (data['isEmpty']):
-    if (cache != []):
-      print('Expected empty cache, but got data.\n')
-      sys.exit(1)
-    return;
-
-  if (cache == []):
-    print('Expected cache contents, but got none.\n')
-    sys.exit(1)
-
-  hadHomeDir = False
-  for value in cache:
-    if (value['key'] == 'CMAKE_HOME_DIRECTORY'):
-      hadHomeDir = True
-
-  if (not hadHomeDir):
-    print('No CMAKE_HOME_DIRECTORY found in cache.')
-    sys.exit(1)
-
-def handleBasicMessage(proc, obj, debug):
-  if 'sendRaw' in obj:
-    data = obj['sendRaw']
-    if debug: print("Sending raw:", data)
-    writeRawData(proc, data)
-    return True
-  elif 'send' in obj:
-    data = obj['send']
-    if debug: print("Sending:", json.dumps(data))
-    writePayload(proc, data)
-    return True
-  elif 'recv' in obj:
-    data = obj['recv']
-    if debug: print("Waiting for:", json.dumps(data))
-    waitForMessage(proc, data)
-    return True
-  elif 'message' in obj:
-    print("MESSAGE:", obj["message"])
-    sys.stdout.flush()
-    return True
-  return False
-
-def shutdownProc(proc):
-  # Tell the server to exit.
-  proc.inPipe.close()
-  proc.outPipe.close()
-
-  # Wait for the server to exit.
-  # If this version of python supports it, terminate the server after a timeout.
-  try:
-    proc.wait(timeout=5)
-  except TypeError:
-    proc.wait()
-  except:
-    proc.terminate()
-    raise
-
-  print('cmake-server exited: %d' % proc.returncode)
-  sys.exit(proc.returncode)
diff --git a/Tests/Server/empty.cpp b/Tests/Server/empty.cpp
deleted file mode 100644
index 766b775..0000000
--- a/Tests/Server/empty.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int main()
-{
-  return 0;
-}
diff --git a/Tests/Server/server-test.py b/Tests/Server/server-test.py
deleted file mode 100644
index 701c6e9..0000000
--- a/Tests/Server/server-test.py
+++ /dev/null
@@ -1,105 +0,0 @@
-from __future__ import print_function
-import sys, cmakelib, json, os, shutil
-
-debug = True
-
-cmakeCommand = sys.argv[1]
-testFile = sys.argv[2]
-sourceDir = sys.argv[3]
-buildDir = sys.argv[4] + "/" + os.path.splitext(os.path.basename(testFile))[0]
-cmakeGenerator = sys.argv[5]
-
-print("Server Test:", testFile,
-      "\n-- SourceDir:", sourceDir,
-      "\n-- BuildDir:", buildDir,
-      "\n-- Generator:", cmakeGenerator)
-
-if os.path.exists(buildDir):
-    shutil.rmtree(buildDir)
-
-cmakelib.filterBase = sourceDir
-
-with open(testFile) as f:
-    testData = json.loads(f.read())
-
-for communicationMethod in cmakelib.communicationMethods:
-    proc = cmakelib.initServerProc(cmakeCommand, communicationMethod)
-    if proc is None:
-        continue
-
-    for obj in testData:
-        if cmakelib.handleBasicMessage(proc, obj, debug):
-            pass
-        elif 'reply' in obj:
-            data = obj['reply']
-            if debug: print("Waiting for reply:", json.dumps(data))
-            originalType = ""
-            cookie = ""
-            skipProgress = False;
-            if 'cookie' in data: cookie = data['cookie']
-            if 'type' in data: originalType = data['type']
-            if 'skipProgress' in data: skipProgress = data['skipProgress']
-            cmakelib.waitForReply(proc, originalType, cookie, skipProgress)
-        elif 'error' in obj:
-            data = obj['error']
-            if debug: print("Waiting for error:", json.dumps(data))
-            originalType = ""
-            cookie = ""
-            message = ""
-            if 'cookie' in data: cookie = data['cookie']
-            if 'type' in data: originalType = data['type']
-            if 'message' in data: message = data['message']
-            cmakelib.waitForError(proc, originalType, cookie, message)
-        elif 'progress' in obj:
-            data = obj['progress']
-            if debug: print("Waiting for progress:", json.dumps(data))
-            originalType = ''
-            cookie = ""
-            current = 0
-            message = ""
-            if 'cookie' in data: cookie = data['cookie']
-            if 'type' in data: originalType = data['type']
-            if 'current' in data: current = data['current']
-            if 'message' in data: message = data['message']
-            cmakelib.waitForProgress(proc, originalType, cookie, current, message)
-        elif 'handshake' in obj:
-            data = obj['handshake']
-            if debug: print("Doing handshake:", json.dumps(data))
-            major = -1
-            minor = -1
-            generator = cmakeGenerator
-            extraGenerator = ''
-            sourceDirectory = sourceDir
-            buildDirectory = buildDir
-            if 'major' in data: major = data['major']
-            if 'minor' in data: minor = data['minor']
-            if 'buildDirectory' in data: buildDirectory = data['buildDirectory']
-            if 'sourceDirectory' in data: sourceDirectory = data['sourceDirectory']
-            if 'generator' in data: generator = data['generator']
-            if 'extraGenerator' in data: extraGenerator = data['extraGenerator']
-
-            if not os.path.isabs(buildDirectory):
-                buildDirectory = buildDir + "/" + buildDirectory
-            if sourceDirectory != '' and not os.path.isabs(sourceDirectory):
-                sourceDirectory = sourceDir + "/" + sourceDirectory
-            cmakelib.handshake(proc, major, minor, sourceDirectory, buildDirectory,
-                               generator, extraGenerator)
-        elif 'validateGlobalSettings' in obj:
-            data = obj['validateGlobalSettings']
-            if not 'buildDirectory' in data: data['buildDirectory'] = buildDir
-            if not 'sourceDirectory' in data: data['sourceDirectory'] = sourceDir
-            if not 'generator' in data: data['generator'] = cmakeGenerator
-            if not 'extraGenerator' in data: data['extraGenerator'] = ''
-            cmakelib.validateGlobalSettings(proc, cmakeCommand, data)
-        elif 'validateCache' in obj:
-            data = obj['validateCache']
-            if not 'isEmpty' in data: data['isEmpty'] = false
-            cmakelib.validateCache(proc, data)
-        elif 'reconnect' in obj:
-            cmakelib.exitProc(proc)
-            proc = cmakelib.initServerProc(cmakeCommand, communicationMethod)
-        else:
-            print("Unknown command:", json.dumps(obj))
-            sys.exit(2)
-    cmakelib.shutdownProc(proc)
-    print("Completed")
diff --git a/Tests/Server/tc_buildsystem1.json b/Tests/Server/tc_buildsystem1.json
deleted file mode 100644
index 08831b7..0000000
--- a/Tests/Server/tc_buildsystem1.json
+++ /dev/null
@@ -1,27 +0,0 @@
-[
-{ "message": "Testing globalSettings" },
-
-{ "handshake": {"major": 1, "sourceDirectory":"buildsystem1","buildDirectory":"buildsystem1"} },
-
-{ "message": "Configure:" },
-{ "send": { "type": "configure", "cookie":"CONFIG" } },
-{ "reply": { "type": "configure", "cookie":"CONFIG", "skipProgress":true } },
-
-{ "message": "Compute:" },
-{ "send": { "type": "compute", "cookie":"COMPUTE" } },
-{ "reply": { "type": "compute", "cookie":"COMPUTE", "skipProgress":true } },
-
-{ "message": "Codemodel:" },
-{ "send": { "type": "codemodel", "cookie":"CODEMODEL" } },
-{ "reply": { "type": "codemodel", "cookie":"CODEMODEL" } },
-
-{ "message": "CMake Inputs:"},
-{ "send": { "type": "cmakeInputs", "cookie":"INPUTS" } },
-{ "reply": { "type": "cmakeInputs", "cookie":"INPUTS" } },
-
-{ "message": "Cache:"},
-{ "send": { "type": "cache", "cookie":"CACHE" } },
-{ "reply": { "type": "cache", "cookie":"CACHE" } },
-
-{ "message": "Everything ok." }
-]
diff --git a/Tests/Server/tc_cache.json b/Tests/Server/tc_cache.json
deleted file mode 100644
index 74af6d9..0000000
--- a/Tests/Server/tc_cache.json
+++ /dev/null
@@ -1,24 +0,0 @@
-[
-{ "message": "Testing cache" },
-
-{ "message": "Cache after first handshake is empty:" },
-{ "handshake": {"major": 1, "sourceDirectory": "buildsystem1", "buildDirectory": "buildsystem1"} },
-{ "send": { "type": "cache" } },
-{ "validateCache": { "isEmpty": true } },
-
-{ "message": "Cache after configure is populated:" },
-{ "send": { "type": "configure" } },
-{ "reply": { "type": "configure", "skipProgress":true } },
-{ "send": { "type": "cache" } },
-{ "validateCache": { "isEmpty": false } },
-
-{ "message": "Handshake for existing cache requires buildDirectory only:" },
-{ "reconnect": {} },
-{ "handshake": {"major": 1, "sourceDirectory": "", "buildDirectory": "buildsystem1"} },
-
-{ "message": "Cache after reconnect is again populated:" },
-{ "send": { "type": "cache" } },
-{ "validateCache": { "isEmpty": false } },
-
-{ "message": "Everything ok." }
-]
diff --git a/Tests/Server/tc_globalSettings.json b/Tests/Server/tc_globalSettings.json
deleted file mode 100644
index d72fb41..0000000
--- a/Tests/Server/tc_globalSettings.json
+++ /dev/null
@@ -1,140 +0,0 @@
-[
-{ "message": "Testing globalSettings" },
-
-{ "handshake": {"major": 1} },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-
-
-{ "message": "Change settings:" },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": true, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUninitialized": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": true, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUninitialized": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "traceExpand": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": true, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "traceExpand": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-
-
-{ "send": { "type": "setGlobalSettings", "trace": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": true, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "trace": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnusedCli": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": false, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnusedCli": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "checkSystemVars": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": true } },
-
-{ "send": { "type": "setGlobalSettings", "checkSystemVars": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-
-{ "message": "Ignore unknown/readonly" },
-
-{ "send": { "type": "setGlobalSettings", "unknownKey": "unknownValue", "extraGenerator": "XXX", "generator": "YYY", "sourceDirectory": "/tmp/source", "buildDirectory": "/tmp/build" } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-
-{ "message": "Error paths:" },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": true, "warnUnused": 1 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"warnUnused\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": 1 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"debugOutput\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUninitialized": 1, "warnUnused": true, "debugOutput": true } },
-{ "error": { "type": "setGlobalSettings", "message": "\"warnUninitialized\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "traceExpand": 1 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"traceExpand\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": true, "trace": 1, "warnUnused": true } },
-{ "error": { "type": "setGlobalSettings", "message": "\"trace\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "warnUnusedCli": 1.0 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"warnUnusedCli\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "checkSystemVars": "some string" } },
-{ "error": { "type": "setGlobalSettings", "message": "\"checkSystemVars\" must be unset or a bool value." } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-
-{ "message": "Everything ok." }
-]
diff --git a/Tests/Server/tc_handshake.json b/Tests/Server/tc_handshake.json
deleted file mode 100644
index 4bb7fa7..0000000
--- a/Tests/Server/tc_handshake.json
+++ /dev/null
@@ -1,75 +0,0 @@
-[
-{ "message": "Testing basic message handling:" },
-
-{ "sendRaw": "Sometext"},
-{ "recv": {"cookie":"","errorMessage":"Failed to parse JSON input.","inReplyTo":"","type":"error"} },
-
-{ "message": "Testing invalid json input"},
-{ "send": { "test": "sometext" } },
-{ "recv": {"cookie":"","errorMessage":"No type given in request.","inReplyTo":"","type":"error"} },
-
-{ "send": {"test": "sometext","cookie":"monster"} },
-{ "recv": {"cookie":"monster","errorMessage":"No type given in request.","inReplyTo":"","type":"error"} },
-
-{ "message": "Testing commands before handshake" },
-{ "send": {"type": "cache","cookie":"monster"} },
-{ "recv": {"cookie":"monster","errorMessage":"Waiting for type \"handshake\".","inReplyTo":"cache","type":"error"} },
-
-{ "message": "Testing handshake" },
-{ "send": {"type": "sometype","cookie":"monster2"} },
-{ "recv": {"cookie":"monster2","errorMessage":"Waiting for type \"handshake\".","inReplyTo":"sometype","type":"error"} },
-
-{ "send": {"type": "handshake"} },
-{ "recv": {"cookie":"","errorMessage":"\"protocolVersion\" is required for \"handshake\".","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","foo":"bar"} },
-{ "recv": {"cookie":"","errorMessage":"\"protocolVersion\" is required for \"handshake\".","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":"bar"} },
-{ "recv": {"cookie":"","errorMessage":"\"protocolVersion\" must be a JSON object.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{}} },
-{ "recv": {"cookie":"","errorMessage":"\"major\" must be set and an integer.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":"foo"}} },
-{ "recv": {"cookie":"","errorMessage":"\"major\" must be set and an integer.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":1, "minor":"foo"}} },
-{ "recv": {"cookie":"","errorMessage":"\"minor\" must be unset or an integer.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":-1, "minor":-1}} },
-{ "recv": {"cookie":"","errorMessage":"\"major\" must be >= 0.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":10, "minor":-1}} },
-{ "recv": {"cookie":"","errorMessage":"\"minor\" must be >= 0 when set.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":10000}} },
-{ "recv": {"cookie":"","errorMessage":"Protocol version not supported.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":1, "minor":10000}} },
-{ "recv": {"cookie":"","errorMessage":"Protocol version not supported.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1}} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"buildDirectory\" is missing."} },
-
-{ "message": "Testing protocol version specific options (1.0):" },
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":"/tmp/src"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"buildDirectory\" is missing."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":"/tmp/src","buildDirectory":"/tmp/build"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"sourceDirectory\" is not a directory."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","extraGenerator":"CodeBlocks"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"generator\" is unset but required."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","generator":"XXXX","extraGenerator":"CodeBlocks"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: Generator \"XXXX\" not supported."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","generator":"Ninja","extraGenerator":"XXXX"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: The combination of generator \"Ninja\" and extra generator \"XXXX\" is not supported."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","generator":"Ninja","extraGenerator":"CodeBlocks"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"reply"} },
-
-{ "message": "Everything ok." }
-]
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index 5bf13f3..a880f7a 100644
--- a/Utilities/Doxygen/CMakeLists.txt
+++ b/Utilities/Doxygen/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 if(NOT CMake_SOURCE_DIR)
   set(CMakeDeveloperReference_STANDALONE 1)
-  cmake_minimum_required(VERSION 3.1...3.15 FATAL_ERROR)
+  cmake_minimum_required(VERSION 3.1...3.18 FATAL_ERROR)
   get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
   get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
   include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index e5be43a..f989907 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 if(NOT CMake_SOURCE_DIR)
   set(CMakeHelp_STANDALONE 1)
-  cmake_minimum_required(VERSION 3.1...3.15 FATAL_ERROR)
+  cmake_minimum_required(VERSION 3.1...3.18 FATAL_ERROR)
   get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
   get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
   include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/bootstrap b/bootstrap
index 0c1368d..b7fcd7e 100755
--- a/bootstrap
+++ b/bootstrap
@@ -308,6 +308,7 @@
   cmContinueCommand \
   cmCoreTryCompile \
   cmCreateTestSourceList \
+  cmCryptoHash \
   cmCustomCommand \
   cmCustomCommandGenerator \
   cmCustomCommandLines \
@@ -413,6 +414,8 @@
   cmProjectCommand \
   cmPropertyDefinition \
   cmPropertyMap \
+  cmGccDepfileLexerHelper \
+  cmGccDepfileReader \
   cmReturnCommand \
   cmRulePlaceholderExpander \
   cmRuntimeDependencyArchive \
@@ -453,6 +456,7 @@
   cmTest \
   cmTestGenerator \
   cmTimestamp \
+  cmTransformDepfile \
   cmTryCompileCommand \
   cmTryRunCommand \
   cmUnsetCommand \
@@ -492,6 +496,7 @@
   cmCommandArgumentParser \
   cmExprLexer \
   cmExprParser \
+  cmGccDepfileLexer \
 "
 
 LexerParser_C_SOURCES="\
@@ -536,6 +541,18 @@
   SystemTools.hxx \
   Terminal.h"
 
+LIBRHASH_C_SOURCES="\
+  librhash/algorithms.c \
+  librhash/byte_order.c \
+  librhash/hex.c \
+  librhash/md5.c \
+  librhash/rhash.c \
+  librhash/sha1.c \
+  librhash/sha256.c \
+  librhash/sha3.c \
+  librhash/sha512.c \
+  "
+
 if ${cmake_system_mingw}; then
   LIBUV_C_SOURCES="\
     src/fs-poll.c \
@@ -1013,7 +1030,6 @@
 # Add generator-specific files
 if test "${cmake_bootstrap_generator}" = "Ninja"; then
   CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES} \
-    cmCryptoHash \
     cmFortranParserImpl \
     cmGlobalNinjaGenerator \
     cmLocalNinjaGenerator \
@@ -1034,18 +1050,6 @@
     src/lib_json/json_value.cpp \
     src/lib_json/json_writer.cpp \
     "
-
-  LIBRHASH_C_SOURCES="\
-    librhash/algorithms.c \
-    librhash/byte_order.c \
-    librhash/hex.c \
-    librhash/md5.c \
-    librhash/rhash.c \
-    librhash/sha1.c \
-    librhash/sha256.c \
-    librhash/sha3.c \
-    librhash/sha512.c \
-    "
 else
   CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES} \
     cmDepends \
@@ -1059,7 +1063,6 @@
     "
 
   JSONCPP_CXX_SOURCES=
-  LIBRHASH_C_SOURCES=
 fi
 
 # Add Cygwin-specific flags
@@ -1629,17 +1632,17 @@
     objs="${objs} uv-`cmake_obj ${a}`"
   done
 fi
+if test "x${bootstrap_system_librhash}" = "x"; then
+  for a in ${LIBRHASH_C_SOURCES}; do
+    objs="${objs} rhash-`cmake_obj ${a}`"
+  done
+fi
 if test "${cmake_bootstrap_generator}" = "Ninja"; then
   if test "x${bootstrap_system_jsoncpp}" = "x"; then
     for a in ${JSONCPP_CXX_SOURCES}; do
       objs="${objs} jsoncpp-`cmake_obj ${a}`"
     done
   fi
-  if test "x${bootstrap_system_librhash}" = "x"; then
-    for a in ${LIBRHASH_C_SOURCES}; do
-      objs="${objs} rhash-`cmake_obj ${a}`"
-    done
-  fi
 fi
 
 libs=""
@@ -1699,6 +1702,15 @@
   libs="${libs} -luv"
 fi
 
+if test "x${bootstrap_system_librhash}" != "x"; then
+  if test `which pkg-config`; then
+    use_librhash_flags="`pkg-config --cflags librhash`"
+    cmake_c_flags="${cmake_c_flags} ${use_librhash_flags}"
+    cmake_cxx_flags="${cmake_cxx_flags} ${use_librhash_flags}"
+  fi
+  libs="${libs} -lrhash"
+fi
+
 if test "${cmake_bootstrap_generator}" = "Ninja"; then
   jsoncpp_cxx_flags=
   if test "x${bootstrap_system_jsoncpp}" = "x"; then
@@ -1710,15 +1722,6 @@
     fi
     libs="${libs} -ljsoncpp"
   fi
-
-  if test "x${bootstrap_system_librhash}" != "x"; then
-    if test `which pkg-config`; then
-      use_librhash_flags="`pkg-config --cflags librhash`"
-      cmake_c_flags="${cmake_c_flags} ${use_librhash_flags}"
-      cmake_cxx_flags="${cmake_cxx_flags} ${use_librhash_flags}"
-    fi
-    libs="${libs} -lrhash"
-  fi
 fi
 
 if test "x${cmake_ansi_cxx_flags}" != "x"; then
@@ -1842,6 +1845,12 @@
     write_source_rule "c" "uv-`cmake_obj ${a}`" "${src}" "${uv_c_flags}"
   done
 fi
+if test "x${bootstrap_system_librhash}" = "x"; then
+  for a in ${LIBRHASH_C_SOURCES}; do
+    src=`cmake_escape_artifact "${cmake_source_dir}/Utilities/cmlibrhash/${a}"`
+    write_source_rule "c" "rhash-`cmake_obj ${a}`" "${src}" ""
+  done
+fi
 if test "${cmake_bootstrap_generator}" = "Ninja"; then
   if test "x${bootstrap_system_jsoncpp}" = "x"; then
     for a in ${JSONCPP_CXX_SOURCES}; do
@@ -1849,12 +1858,6 @@
       write_source_rule "cxx" "jsoncpp-`cmake_obj ${a}`" "${src}" "${jsoncpp_cxx_flags}"
     done
   fi
-  if test "x${bootstrap_system_librhash}" = "x"; then
-    for a in ${LIBRHASH_C_SOURCES}; do
-      src=`cmake_escape_artifact "${cmake_source_dir}/Utilities/cmlibrhash/${a}"`
-      write_source_rule "c" "rhash-`cmake_obj ${a}`" "${src}" ""
-    done
-  fi
 fi
 if test "${cmake_bootstrap_generator}" = "Ninja"; then
   echo "