Merge topic 'fileapi-config-dir'

1df94443fe fileapi: Add support for user-wide queries
a991a5019b Tests: Isolate test suite from user-wide configuration
320b81847d Tests: Remove unused cvs anonymous access credentials

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !9744
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 85ef4e7..2cb55f2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1209,7 +1209,7 @@
     variables:
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang17.0-cl-ninja:
+t:windows-clang18.1-cl-ninja:
     extends:
         - .windows_clang_ninja
         - .cmake_test_windows_external
@@ -1221,10 +1221,10 @@
     needs:
         - t:windows-vs2022-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang17.0_cl_ninja
+        CMAKE_CI_BUILD_NAME: windows_clang18.1_cl_ninja
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang17.0-cl-nmake:
+t:windows-clang18.1-cl-nmake:
     extends:
         - .windows_clang_nmake
         - .cmake_test_windows_external
@@ -1236,10 +1236,10 @@
     needs:
         - t:windows-vs2022-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang17.0_cl_nmake
+        CMAKE_CI_BUILD_NAME: windows_clang18.1_cl_nmake
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang17.0-gnu-ninja:
+t:windows-clang18.1-gnu-ninja:
     extends:
         - .windows_clang_ninja
         - .cmake_test_windows_external
@@ -1251,10 +1251,10 @@
     needs:
         - t:windows-vs2022-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang17.0_gnu_ninja
+        CMAKE_CI_BUILD_NAME: windows_clang18.1_gnu_ninja
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang17.0-gnu-nmake:
+t:windows-clang18.1-gnu-nmake:
     extends:
         - .windows_clang_nmake
         - .cmake_test_windows_external
@@ -1266,7 +1266,7 @@
     needs:
         - t:windows-vs2022-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang17.0_gnu_nmake
+        CMAKE_CI_BUILD_NAME: windows_clang18.1_gnu_nmake
         CMAKE_CI_JOB_NIGHTLY: "true"
 
 t:windows-intel2021.9.0-ninja:
diff --git a/.gitlab/ci/clang.ps1 b/.gitlab/ci/clang.ps1
index 204bff5..5e3ff3c 100644
--- a/.gitlab/ci/clang.ps1
+++ b/.gitlab/ci/clang.ps1
@@ -1,10 +1,10 @@
 $erroractionpreference = "stop"
 
-if ("$env:CMAKE_CI_BUILD_NAME".Contains("clang17.0")) {
-    # LLVM/Clang 17.0.1
-    # https://github.com/llvm/llvm-project/releases/tag/llvmorg-17.0.1
-    $filename = "llvm-17.0.1-win-x86_64-1"
-    $sha256sum = "803F5D7291219BE60D2EE69CE8882341F94A8707A214DED190614895B6996F55"
+if ("$env:CMAKE_CI_BUILD_NAME".Contains("clang18.1")) {
+    # LLVM/Clang 18.1.8
+    # https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.8
+    $filename = "llvm-18.1.8-win-x86_64-1"
+    $sha256sum = "AAB44C676DEDC7D36F90073DB6DE5C573F21D2F98D0B48269507478A63D48CA0"
 } else {
     throw ('unknown CMAKE_CI_BUILD_NAME: ' + "$env:CMAKE_CI_BUILD_NAME")
 }
diff --git a/.gitlab/ci/ctest_exclusions.cmake b/.gitlab/ci/ctest_exclusions.cmake
index ed5e1dd..a2789c3 100644
--- a/.gitlab/ci/ctest_exclusions.cmake
+++ b/.gitlab/ci/ctest_exclusions.cmake
@@ -34,13 +34,6 @@
     )
 endif()
 
-if ("$ENV{CMAKE_CONFIGURATION}" STREQUAL "windows_vs2022_x64_ninja")
-  list(APPEND test_exclusions
-    # FIXME(#25573): This test failure needs further investigation.
-    "^SwiftMixLib$"
-    )
-endif()
-
 string(REPLACE ";" "|" test_exclusions "${test_exclusions}")
 if (test_exclusions)
   set(test_exclusions "(${test_exclusions})")
diff --git a/.gitlab/ci/docker/ninja/centos7-aarch64.bash b/.gitlab/ci/docker/ninja/centos7-aarch64.bash
deleted file mode 100755
index 4052f29..0000000
--- a/.gitlab/ci/docker/ninja/centos7-aarch64.bash
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -x
-
-cleanup() {
-    docker container rm -fv "$build_container" >/dev/null 2>&1 || true
-    docker image rm -f "$build_image" >/dev/null 2>&1 || true
-}
-
-readonly suffix="-$(date -u +%Y-%m-%d)-${RANDOM}"
-readonly build_container="ninja-build-linux-aarch64$suffix"
-readonly build_image="ninja:build-linux-aarch64$suffix"
-readonly git_tag="${1-v1.11.0}"
-
-trap "cleanup" EXIT INT TERM
-
-docker image build --build-arg GIT_TAG="$git_tag" --tag="$build_image" "${BASH_SOURCE%/*}/centos7-aarch64"
-docker container create --name "$build_container" "$build_image"
-docker cp "$build_container:/ninja/ninja" "ninja"
diff --git a/.gitlab/ci/docker/ninja/centos7-aarch64/Dockerfile b/.gitlab/ci/docker/ninja/centos7-aarch64/Dockerfile
deleted file mode 100644
index 3fb13b0..0000000
--- a/.gitlab/ci/docker/ninja/centos7-aarch64/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM kitware/cmake:build-linux-aarch64-base-2020-12-21
-MAINTAINER Brad King <brad.king@kitware.com>
-
-ARG GIT_TAG=v1.11.0
-
-COPY build_ninja.sh /root/build_ninja.sh
-RUN scl enable devtoolset-7 -- sh /root/build_ninja.sh $GIT_TAG
diff --git a/.gitlab/ci/docker/ninja/centos7-aarch64/build_ninja.sh b/.gitlab/ci/docker/ninja/centos7-aarch64/build_ninja.sh
deleted file mode 100755
index 91fb2d4..0000000
--- a/.gitlab/ci/docker/ninja/centos7-aarch64/build_ninja.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-set -e
-
-git clone https://github.com/ninja-build/ninja.git
-cd ninja
-git checkout "${1-v1.11.0}"
-./configure.py --bootstrap
-./ninja all
-./ninja_test
-strip ninja
diff --git a/.gitlab/ci/ninja.ps1 b/.gitlab/ci/ninja.ps1
index 4c4d675..81d3f2e 100644
--- a/.gitlab/ci/ninja.ps1
+++ b/.gitlab/ci/ninja.ps1
@@ -5,9 +5,18 @@
     exit $LASTEXITCODE
 }
 
-$version = "1.11.0"
-$sha256sum = "D0EE3DA143211AA447E750085876C9B9D7BCDD637AB5B2C5B41349C617F22F3B"
-$filename = "ninja-win"
+$version = "1.12.1"
+
+if ("$env:PROCESSOR_ARCHITECTURE" -eq "AMD64") {
+    $sha256sum = "F550FEC705B6D6FF58F2DB3C374C2277A37691678D6ABA463ADCBB129108467A"
+    $filename = "ninja-win"
+} elseif ("$env:PROCESSOR_ARCHITECTURE" -eq "ARM64") {
+    $sha256sum = "79C96A50E0DEAFEC212CFA85AA57C6B74003F52D9D1673DDCD1EAB1C958C5900"
+    $filename = "ninja-winarm64"
+} else {
+    throw ('unknown PROCESSOR_ARCHITECTURE: ' + "$env:PROCESSOR_ARCHITECTURE")
+}
+
 $tarball = "$filename.zip"
 
 $outdir = $pwd.Path
diff --git a/.gitlab/ci/ninja.sh b/.gitlab/ci/ninja.sh
index 753596b..530feac 100755
--- a/.gitlab/ci/ninja.sh
+++ b/.gitlab/ci/ninja.sh
@@ -6,25 +6,23 @@
     exec .gitlab/ci/ninja-nightly.sh
 fi
 
-readonly version="1.11.0"
+readonly version="1.12.1"
 baseurl="https://github.com/ninja-build/ninja/releases/download/v$version"
 
 case "$(uname -s)-$(uname -m)" in
     Linux-x86_64)
         shatool="sha256sum"
-        sha256sum="9726e730d5b8599f82654dc80265e64a10a8a817552c34153361ed0c017f9f02"
+        sha256sum="6f98805688d19672bd699fbbfa2c2cf0fc054ac3df1f0e6a47664d963d530255"
         filename="ninja-linux"
         ;;
     Linux-aarch64)
         shatool="sha256sum"
-        sha256sum="b002eb77cfcef6d329cccf8b1cc7ad138302d6e19b5b76b10b4c4d38564b47b5"
-        # Use binary built by adjacent 'docker/ninja/centos7-aarch64.bash' script.
-        baseurl="https://cmake.org/files/dependencies"
-        filename="ninja-$version-1-linux-aarch64"
+        sha256sum="5c25c6570b0155e95fce5918cb95f1ad9870df5768653afe128db822301a05a1"
+        filename="ninja-linux-aarch64"
         ;;
     Darwin-*)
         shatool="shasum -a 256"
-        sha256sum="21915277db59756bfc61f6f281c1f5e3897760b63776fd3d360f77dd7364137f"
+        sha256sum="89a287444b5b3e98f88a945afa50ce937b8ffd1dcc59c555ad9b1baf855298c9"
         filename="ninja-mac"
         ;;
     *)
diff --git a/.gitlab/os-macos.yml b/.gitlab/os-macos.yml
index 2b265ea..527923e 100644
--- a/.gitlab/os-macos.yml
+++ b/.gitlab/os-macos.yml
@@ -7,7 +7,7 @@
         GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci ext/$CI_CONCURRENT_ID"
         # TODO: Factor this out so that each job selects the Xcode version to
         # use so that different versions can be tested in a single pipeline.
-        DEVELOPER_DIR: "/Applications/Xcode-15.3.app/Contents/Developer"
+        DEVELOPER_DIR: "/Applications/Xcode-15.4.app/Contents/Developer"
         # Avoid conflicting with other projects running on the same machine.
         SCCACHE_SERVER_PORT: 4227
 
@@ -142,7 +142,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-x86_64
         - shell
-        - xcode-15.3
+        - xcode-15.4
         - nonconcurrent
 
 .macos_x86_64_tags_ext:
@@ -150,7 +150,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-x86_64
         - shell
-        - xcode-15.3
+        - xcode-15.4
         - concurrent
 
 .macos_arm64_tags:
@@ -158,7 +158,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-arm64
         - shell
-        - xcode-15.3
+        - xcode-15.4
         - nonconcurrent
 
 .macos_arm64_tags_ext:
@@ -166,7 +166,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-arm64
         - shell
-        - xcode-15.3
+        - xcode-15.4
         - concurrent
 
 .macos_arm64_tags_package:
@@ -174,7 +174,7 @@
         - cmake # Since this is a bare runner, pin to a project.
         - macos-arm64
         - shell
-        - xcode-15.3
+        - xcode-15.4
         - nonconcurrent
         - finder
 
diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml
index 33d0d57..fdde3b7 100644
--- a/.gitlab/os-windows.yml
+++ b/.gitlab/os-windows.yml
@@ -35,25 +35,25 @@
     variables:
         VCVARSALL: "${VS170COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat"
         VCVARSPLATFORM: "x64"
-        VCVARSVERSION: "14.40.33807"
+        VCVARSVERSION: "14.41.34120"
 
 .windows_vcvarsall_vs2022_x86:
     variables:
         VCVARSALL: "${VS170COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat"
         VCVARSPLATFORM: "x86"
-        VCVARSVERSION: "14.40.33807"
+        VCVARSVERSION: "14.41.34120"
 
 .windows_vcvarsall_vs2022_x64_arm64:
     variables:
         VCVARSALL: "${VS170COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat"
         VCVARSPLATFORM: "x64_arm64"
-        VCVARSVERSION: "14.40.33807"
+        VCVARSVERSION: "14.41.34120"
 
 .windows_arm64_vcvarsall_vs2022:
     variables:
         VCVARSALL: "${VS170COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat"
         VCVARSPLATFORM: "arm64"
-        VCVARSVERSION: "14.40.33807"
+        VCVARSVERSION: "14.41.34120"
 
 .windows_vs2022_x64_pch:
     extends:
@@ -119,7 +119,7 @@
         CMAKE_CONFIGURATION: windows_vs2022_x64
         CMAKE_GENERATOR: "Visual Studio 17 2022"
         CMAKE_GENERATOR_PLATFORM: "x64"
-        CMAKE_GENERATOR_TOOLSET: "v143,version=14.40.33807"
+        CMAKE_GENERATOR_TOOLSET: "v143,version=14.41.34120"
         CMAKE_CI_NIGHTLY_IGNORE_DEPS: "true"
 
 .windows_vs2019_x64:
@@ -282,7 +282,7 @@
         CMAKE_CONFIGURATION: windows_arm64_vs2022
         CMAKE_GENERATOR: "Visual Studio 17 2022"
         CMAKE_GENERATOR_PLATFORM: "ARM64"
-        CMAKE_GENERATOR_TOOLSET: "v143,version=14.40.33807"
+        CMAKE_GENERATOR_TOOLSET: "v143,version=14.41.34120"
         CMAKE_CI_NIGHTLY_IGNORE_DEPS: "true"
 
 .mingw_osdn_io:
@@ -316,7 +316,7 @@
         - windows-x86_64
         - shell
         - vs2022
-        - msvc-14.40
+        - msvc-14.41
         - nonconcurrent
 
 .windows_x86_64_tags_nonconcurrent_vs2022_arm64:
@@ -325,7 +325,7 @@
         - windows-x86_64
         - shell
         - vs2022
-        - msvc-14.40-arm64
+        - msvc-14.41-arm64
         - nonconcurrent
 
 .windows_x86_64_tags_concurrent_vs2022:
@@ -334,7 +334,7 @@
         - windows-x86_64
         - shell
         - vs2022
-        - msvc-14.40
+        - msvc-14.41
         - concurrent
 
 .windows_x86_64_tags_concurrent_vs2022_android:
@@ -344,7 +344,7 @@
         - shell
         - vs2022
         - vs17-android
-        - msvc-14.40
+        - msvc-14.41
         - concurrent
 
 .windows_x86_64_tags_concurrent_vs2019_android:
@@ -370,7 +370,7 @@
         - windows-arm64
         - shell
         - vs2022
-        - msvc-14.40
+        - msvc-14.41
         - nonconcurrent
 
 .windows_arm64_tags_concurrent_vs2022:
@@ -379,7 +379,7 @@
         - windows-arm64
         - shell
         - vs2022
-        - msvc-14.40
+        - msvc-14.41
         - concurrent
 
 ## Windows-specific scripts
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 51c2b3f..79a562c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -267,9 +267,7 @@
   endif()
 
   # configure some files for testing
-  configure_file(Templates/CTestScript.cmake.in CTestScript.cmake @ONLY)
   configure_file(Tests/.NoDartCoverage Tests/.NoDartCoverage)
-  configure_file(Tests/.NoDartCoverage Modules/.NoDartCoverage)
   configure_file(CTestCustom.cmake.in CTestCustom.cmake @ONLY)
 endmacro()
 
diff --git a/Help/command/file.rst b/Help/command/file.rst
index ede95a1..0ac49f4 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -1169,6 +1169,14 @@
 
   5. Otherwise, the dependency is unresolved.
 
+  .. versionchanged:: 3.31
+
+    Resolution of each encountered library file name occurs at most once
+    while processing a given root ELF file (executable or shared object).
+    If a library file name is encountered again in the dependency tree,
+    the original resolution is assumed.  This behavior more closely matches
+    the dynamic loader's behavior on Linux.
+
   On Windows platforms, library resolution works as follows:
 
   1. DLL dependency names are converted to lowercase for matching filters.
diff --git a/Help/command/get_property.rst b/Help/command/get_property.rst
index a0a12bb..202bfd9 100644
--- a/Help/command/get_property.rst
+++ b/Help/command/get_property.rst
@@ -29,7 +29,7 @@
   Scope is unique and does not accept a name.
 
 ``DIRECTORY``
-  Scope defaults to the current directory but another
+  Scope defaults to the current directory, but another
   directory (already processed by CMake) may be named by the
   full or relative path ``<dir>``.
   Relative paths are treated as relative to the current source directory.
@@ -79,10 +79,10 @@
 
     ``DIRECTORY <dir>``
       The test property will be read from the ``<dir>`` directory's
-      scope.  CMake must already know about the directory, either by having added
-      it through a call to :command:`add_subdirectory` or ``<dir>`` being the top
-      level directory. Relative paths are treated as relative to the current
-      source directory. ``<dir>`` may reference a binary directory.
+      scope.  CMake must already know about the directory, either by having
+      added it through a call to :command:`add_subdirectory` or ``<dir>`` being
+      the top level directory. Relative paths are treated as relative to the
+      current source directory. ``<dir>`` may reference a binary directory.
 
 ``CACHE``
   Scope must name one cache entry.
@@ -91,19 +91,20 @@
   Scope is unique and does not accept a name.
 
 The required ``PROPERTY`` option is immediately followed by the name of
-the property to get.  If the property is not set an empty value is
-returned, although some properties support inheriting from a parent scope
-if defined to behave that way (see :command:`define_property`).
+the property to get.  If the property is not set, the named ``<variable>``
+will be unset in the calling scope upon return, although some properties
+support inheriting from a parent scope if defined to behave that way
+(see :command:`define_property`).
 
-If the ``SET`` option is given the variable is set to a boolean
+If the ``SET`` option is given, the variable is set to a boolean
 value indicating whether the property has been set.  If the ``DEFINED``
-option is given the variable is set to a boolean value indicating
-whether the property has been defined such as with the
+option is given, the variable is set to a boolean value indicating
+whether the property has been defined, such as with the
 :command:`define_property` command.
 
-If ``BRIEF_DOCS`` or ``FULL_DOCS`` is given then the variable is set to a
+If ``BRIEF_DOCS`` or ``FULL_DOCS`` is given, then the variable is set to a
 string containing documentation for the requested property.  If
-documentation is requested for a property that has not been defined
+documentation is requested for a property that has not been defined,
 ``NOTFOUND`` is returned.
 
 .. note::
diff --git a/Help/command/if.rst b/Help/command/if.rst
index de25ad3..c6e1c61 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -41,13 +41,15 @@
 
 1. `Parentheses`_.
 
-2. Unary tests such as `EXISTS`_, `COMMAND`_, and `DEFINED`_.
+2. Unary tests such as `COMMAND`_, `POLICY`_, `TARGET`_, `TEST`_,
+    `EXISTS`_, `IS_READABLE`_, `IS_WRITABLE`_, `IS_EXECUTABLE`_,
+    `IS_DIRECTORY`_, `IS_SYMLINK`_, `IS_ABSOLUTE`_, and `DEFINED`_.
 
 3. Binary tests such as `EQUAL`_, `LESS`_, `LESS_EQUAL`_, `GREATER`_,
    `GREATER_EQUAL`_, `STREQUAL`_, `STRLESS`_, `STRLESS_EQUAL`_,
    `STRGREATER`_, `STRGREATER_EQUAL`_, `VERSION_EQUAL`_, `VERSION_LESS`_,
    `VERSION_LESS_EQUAL`_, `VERSION_GREATER`_, `VERSION_GREATER_EQUAL`_,
-   `PATH_EQUAL`_, and `MATCHES`_.
+   `PATH_EQUAL`_, `IN_LIST`_, `IS_NEWER_THAN`_, and `MATCHES`_.
 
 4. Unary logical operator `NOT`_.
 
@@ -471,6 +473,10 @@
   variables.  If so, their defined values are used otherwise the original value
   is used.
 
+* The left hand argument to `IN_LIST`_ is tested to see if it is a defined
+  variable.  If so, the variable's value is used, otherwise the original
+  value is used.
+
 * The right hand argument to `NOT`_ is tested to see if it is a boolean
   constant.  If so, the value is used, otherwise it is assumed to be a
   variable and it is dereferenced.
diff --git a/Help/command/project.rst b/Help/command/project.rst
index 2b93880..0188291 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -33,10 +33,17 @@
 
   Boolean value indicating whether the project is top-level.
 
-Further variables are set by the optional arguments described in the following.
-If any of these arguments is not used, then the corresponding variables are
+Further variables are set by the optional arguments described in `Options`_
+further below. Where an option is not given, its corresponding variable is
 set to the empty string.
 
+Note that variables of the form ``<name>_SOURCE_DIR`` and ``<name>_BINARY_DIR``
+may also be set by other commands before ``project()`` is called (see the
+:command:`FetchContent_MakeAvailable` command for one example).
+Projects should not rely on ``<PROJECT-NAME>_SOURCE_DIR`` or
+``<PROJECT-NAME>_BINARY_DIR`` holding a particular value outside of the scope
+of the call to ``project()`` or one of its child scopes.
+
 Options
 ^^^^^^^
 
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 82e11ef..9f014e1 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -55,7 +55,6 @@
    /module/CMakeBackwardCompatibilityCXX
    /module/CMakeDependentOption
    /module/CMakeFindDependencyMacro
-   /module/CMakeFindFrameworks
    /module/CMakeFindPackageMode
    /module/CMakeGraphVizOptions
    /module/CMakePackageConfigHelpers
@@ -269,6 +268,7 @@
    /module/AddFileDependencies
    /module/CMakeDetermineVSServicePack
    /module/CMakeExpandImportedTargets
+   /module/CMakeFindFrameworks
    /module/CMakeForceCompiler
    /module/CMakeParseArguments
    /module/Dart
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 92953fd..4130e14 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -57,6 +57,7 @@
 .. toctree::
    :maxdepth: 1
 
+   CMP0173: The CMakeFindFrameworks module is removed. </policy/CMP0173>
    CMP0172: The CPack module enables per-machine installation by default in the CPack WIX Generator. </policy/CMP0172>
    CMP0171: 'codegen' is a reserved target name. </policy/CMP0171>
 
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index e52d74e..e52376f 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -323,10 +323,14 @@
   (which may not be an empty string), and the value is either ``null`` or
   a string representing the value of the variable. Each variable is set
   regardless of whether or not a value was given to it by the process's
-  environment. This field supports `macro expansion`_, and environment
-  variables in this map may reference each other, and may be listed in any
-  order, as long as such references do not cause a cycle (for example,
-  if ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+  environment.
+
+  This field supports `macro expansion`_, and environment variables in this map
+  may reference each other, and may be listed in any order, as long as such
+  references do not cause a cycle (for example, if ``ENV_1`` is
+  ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``).  ``$penv{NAME}``
+  allows one to prepend or append values to existing environment variables by
+  accessing only values from the parent environment.
 
   Environment variables are inherited through the ``inherits`` field, and
   the preset's environment will be the union of its own ``environment`` and
@@ -508,10 +512,14 @@
   (which may not be an empty string), and the value is either ``null`` or
   a string representing the value of the variable. Each variable is set
   regardless of whether or not a value was given to it by the process's
-  environment. This field supports macro expansion, and environment
-  variables in this map may reference each other, and may be listed in any
-  order, as long as such references do not cause a cycle (for example, if
-  ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+  environment.
+
+  This field supports `macro expansion`_, and environment variables in this map
+  may reference each other, and may be listed in any order, as long as such
+  references do not cause a cycle (for example, if ``ENV_1`` is
+  ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``).  ``$penv{NAME}``
+  allows one to prepend or append values to existing environment variables by
+  accessing only values from the parent environment.
 
   Environment variables are inherited through the ``inherits`` field, and
   the preset's environment will be the union of its own ``environment``
@@ -669,10 +677,14 @@
   (which may not be an empty string), and the value is either ``null`` or
   a string representing the value of the variable. Each variable is set
   regardless of whether or not a value was given to it by the process's
-  environment. This field supports macro expansion, and environment
-  variables in this map may reference each other, and may be listed in any
-  order, as long as such references do not cause a cycle (for example, if
-  ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+  environment.
+
+  This field supports `macro expansion`_, and environment variables in this map
+  may reference each other, and may be listed in any order, as long as such
+  references do not cause a cycle (for example, if ``ENV_1`` is
+  ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``).  ``$penv{NAME}``
+  allows one to prepend or append values to existing environment variables by
+  accessing only values from the parent environment.
 
   Environment variables are inherited through the ``inherits`` field, and
   the preset's environment will be the union of its own ``environment``
@@ -1010,10 +1022,14 @@
   (which may not be an empty string), and the value is either ``null`` or
   a string representing the value of the variable. Each variable is set
   regardless of whether or not a value was given to it by the process's
-  environment. This field supports macro expansion, and environment
-  variables in this map may reference each other, and may be listed in any
-  order, as long as such references do not cause a cycle (for example, if
-  ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+  environment.
+
+  This field supports `macro expansion`_, and environment variables in this map
+  may reference each other, and may be listed in any order, as long as such
+  references do not cause a cycle (for example, if ``ENV_1`` is
+  ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``).  ``$penv{NAME}``
+  allows one to prepend or append values to existing environment variables by
+  accessing only values from the parent environment.
 
   Environment variables are inherited through the ``inherits`` field, and
   the preset's environment will be the union of its own ``environment``
@@ -1280,7 +1296,7 @@
 ``$penv{<variable-name>}``
   Similar to ``$env{<variable-name>}``, except that the value only comes from
   the parent environment, and never from the ``environment`` field. This
-  allows you to prepend or append values to existing environment variables.
+  allows one to prepend or append values to existing environment variables.
   For example, setting ``PATH`` to ``/path/to/ninja/bin:$penv{PATH}`` will
   prepend ``/path/to/ninja/bin`` to the ``PATH`` environment variable. This
   is needed because ``$env{<variable-name>}`` does not allow circular
diff --git a/Help/policy/CMP0173.rst b/Help/policy/CMP0173.rst
new file mode 100644
index 0000000..30de19f
--- /dev/null
+++ b/Help/policy/CMP0173.rst
@@ -0,0 +1,22 @@
+CMP0173
+-------
+
+.. versionadded:: 3.31
+
+The :module:`CMakeFindFrameworks` module is removed.
+
+CMake's framework handling has evolved well beyond what the
+``CMakeFindFrameworks`` module supports. The module lacks any handling of
+XCFrameworks, it never documented the one command it provides, and
+:command:`find_library` provides superior capabilities in all respects.
+
+The ``OLD`` behavior of this policy is for :module:`CMakeFindFrameworks` to
+continue to provide the undocumented ``cmake_find_frameworks()`` command.
+The ``NEW`` behavior halts with a fatal error if anything tries to include
+the module.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.31
+.. |WARNS_OR_DOES_NOT_WARN| replace:: warns
+.. include:: STANDARD_ADVICE.txt
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_tgt/COMPILE_FLAGS.rst b/Help/prop_tgt/COMPILE_FLAGS.rst
index 8fe651b..5229d46 100644
--- a/Help/prop_tgt/COMPILE_FLAGS.rst
+++ b/Help/prop_tgt/COMPILE_FLAGS.rst
@@ -7,5 +7,8 @@
 build sources within the target.  Use :prop_tgt:`COMPILE_DEFINITIONS`
 to pass additional preprocessor definitions.
 
-This property is deprecated.  Use the :prop_tgt:`COMPILE_OPTIONS`
-property or the :command:`target_compile_options` command instead.
+.. note::
+
+  This property has been superseded by the :prop_tgt:`COMPILE_OPTIONS` property.
+  Alternatively, you can also use the :command:`target_compile_options` command
+  instead.
diff --git a/Help/release/dev/deprecate-CMakeFindFrameworks.rst b/Help/release/dev/deprecate-CMakeFindFrameworks.rst
new file mode 100644
index 0000000..785962f
--- /dev/null
+++ b/Help/release/dev/deprecate-CMakeFindFrameworks.rst
@@ -0,0 +1,5 @@
+deprecate-CMakeFindFrameworks
+-----------------------------
+
+* The :module:`CMakeFindFrameworks` module has been deprecated via
+  :policy:`CMP0173`. Projects should use :command:`find_library` instead.
diff --git a/Help/release/dev/elf-lib-deps-resolve.rst b/Help/release/dev/elf-lib-deps-resolve.rst
new file mode 100644
index 0000000..f7866eb
--- /dev/null
+++ b/Help/release/dev/elf-lib-deps-resolve.rst
@@ -0,0 +1,5 @@
+elf-lib-deps-resolve
+--------------------
+
+* The :command:`file(GET_RUNTIME_DEPENDENCIES)` command was updated
+  to more closely match the dynamic loader's behavior on Linux.
diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake
index e667099..d7a99b0 100644
--- a/Modules/CMakeDetermineHIPCompiler.cmake
+++ b/Modules/CMakeDetermineHIPCompiler.cmake
@@ -223,7 +223,7 @@
     endif()
     unset(_CMAKE_HIP_COMPILER_ROCM_LIB_DIRS)
   endif()
-  if(CMAKE_HIP_COMPILER_ROCM_LIB MATCHES "/lib64$" AND NOT DEFINED CMAKE_SIZEOF_VOID_P)
+  if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
     # We have not yet determined the target ABI but we need 'find_package' to
     # search lib64 directories to find hip-lang CMake package dependencies.
     # This will be replaced by ABI detection later.
diff --git a/Modules/CMakeFindFrameworks.cmake b/Modules/CMakeFindFrameworks.cmake
index 1aa3929..46010f5 100644
--- a/Modules/CMakeFindFrameworks.cmake
+++ b/Modules/CMakeFindFrameworks.cmake
@@ -5,6 +5,9 @@
 CMakeFindFrameworks
 -------------------
 
+.. deprecated:: 3.31
+  This module does nothing, unless policy :policy:`CMP0173` is set to ``OLD``.
+
 helper module to find OSX frameworks
 
 This module reads hints about search locations from variables::
@@ -12,6 +15,25 @@
   CMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS - Extra directories
 #]=======================================================================]
 
+cmake_policy(GET CMP0173 _cmp0173)
+if(_cmp0173 STREQUAL "NEW")
+  message(FATAL_ERROR
+    "CMakeFindFrameworks.cmake is not maintained and lacks support for more "
+    "recent framework handling. It will be removed in a future version of "
+    "CMake. Update the code to use find_library() instead. "
+    "Use of this module is now an error according to policy CMP0173."
+  )
+elseif(_cmp0173 STREQUAL "")
+  # CMake will have already emitted the standard policy warning for the point
+  # of inclusion. We only need to add the context-specific info here.
+  message(AUTHOR_WARNING
+    "CMakeFindFrameworks.cmake is not maintained and lacks support for more "
+    "recent framework handling. It will be removed in a future version of "
+    "CMake. Update the code to use find_library() instead."
+  )
+endif ()
+unset(_cmp0173)
+
 if(NOT CMAKE_FIND_FRAMEWORKS_INCLUDED)
   set(CMAKE_FIND_FRAMEWORKS_INCLUDED 1)
   macro(CMAKE_FIND_FRAMEWORKS fwk)
diff --git a/Modules/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake
index 27b7ae8..696f7a3 100644
--- a/Modules/CheckCCompilerFlag.cmake
+++ b/Modules/CheckCCompilerFlag.cmake
@@ -27,6 +27,8 @@
 order to force the check to be re-evaluated, the variable named by
 ``<resultVar>`` must be manually removed from the cache.
 
+See also :command:`check_compiler_flag` for a more general command syntax.
+
 The compile and link commands can be influenced by setting any of the
 following variables prior to calling ``check_c_compiler_flag()``
 
diff --git a/Modules/CheckCSourceCompiles.cmake b/Modules/CheckCSourceCompiles.cmake
index c01b6cf..801cf17 100644
--- a/Modules/CheckCSourceCompiles.cmake
+++ b/Modules/CheckCSourceCompiles.cmake
@@ -28,6 +28,8 @@
   ``STATIC_LIBRARY``, the source is compiled but not linked. In any case, all
   functions must be declared as usual.
 
+  See also :command:`check_source_compiles` for a more general command syntax.
+
   See also :command:`check_source_runs` to run compiled source.
 
   The compile and link commands can be influenced by setting any of the
diff --git a/Modules/CheckCSourceRuns.cmake b/Modules/CheckCSourceRuns.cmake
index e06bcca..7a34ece 100644
--- a/Modules/CheckCSourceRuns.cmake
+++ b/Modules/CheckCSourceRuns.cmake
@@ -5,7 +5,7 @@
 CheckCSourceRuns
 ----------------
 
-Check if given C source compiles and links into an executable and can
+Check once if given C source compiles and links into an executable and can
 subsequently be run.
 
 .. command:: check_c_source_runs
@@ -14,18 +14,16 @@
 
     check_c_source_runs(<code> <resultVar>)
 
-  Check that the source supplied in ``<code>`` can be compiled as a C source
-  file, linked as an executable and then run. The ``<code>`` must contain at
-  least a ``main()`` function. If the ``<code>`` could be built and run
-  successfully, the internal cache variable specified by ``<resultVar>`` will
-  be set to 1, otherwise it will be set to an value that evaluates to boolean
-  false (e.g. an empty string or an error message).
+  Check once that the source supplied in ``<code>`` can be built, linked as an
+  executable, and then run. The ``<code>`` must contain at least a ``main()``
+  function.
 
-  The check is only performed once, with the result cached in the variable named
-  by ``<resultVar>``. Every subsequent CMake run will reuse this cached value
-  rather than performing the check again, even if the ``<code>`` changes. In
-  order to force the check to be re-evaluated, the variable named by
-  ``<resultVar>`` must be manually removed from the cache.
+  The result is stored in the internal cache variable specified by
+  ``<resultVar>``. Success of build and run is indicated by boolean ``true``.
+  Failure to build or run is indicated by boolean ``false`` such as an empty
+  string or an error message.
+
+  See also :command:`check_source_runs` for a more general command syntax.
 
   The compile and link commands can be influenced by setting any of the
   following variables prior to calling ``check_c_source_runs()``:
diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake
index 61ed640..90cd488 100644
--- a/Modules/CheckCXXCompilerFlag.cmake
+++ b/Modules/CheckCXXCompilerFlag.cmake
@@ -21,6 +21,8 @@
 issue a diagnostic message when given the flag.  Whether the flag has any
 effect or even a specific one is beyond the scope of this module.
 
+See also :command:`check_compiler_flag` for a more general command syntax.
+
 .. note::
   Since the :command:`try_compile` command forwards flags from variables
   like :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags
diff --git a/Modules/CheckCXXSourceCompiles.cmake b/Modules/CheckCXXSourceCompiles.cmake
index 7c03c4a..c9616d8 100644
--- a/Modules/CheckCXXSourceCompiles.cmake
+++ b/Modules/CheckCXXSourceCompiles.cmake
@@ -28,6 +28,8 @@
   ``STATIC_LIBRARY``, the source is compiled but not linked. In any case, all
   functions must be declared as usual.
 
+  See also :command:`check_source_compiles` for a more general command syntax.
+
   See also :command:`check_source_runs` to run compiled source.
 
   The compile and link commands can be influenced by setting any of the
diff --git a/Modules/CheckCXXSourceRuns.cmake b/Modules/CheckCXXSourceRuns.cmake
index eb643eb..0f14a3a 100644
--- a/Modules/CheckCXXSourceRuns.cmake
+++ b/Modules/CheckCXXSourceRuns.cmake
@@ -5,7 +5,7 @@
 CheckCXXSourceRuns
 ------------------
 
-Check if given C++ source compiles and links into an executable and can
+Check once if given C++ source compiles and links into an executable and can
 subsequently be run.
 
 .. command:: check_cxx_source_runs
@@ -14,18 +14,16 @@
 
     check_cxx_source_runs(<code> <resultVar>)
 
-  Check that the source supplied in ``<code>`` can be compiled as a C++ source
-  file, linked as an executable and then run. The ``<code>`` must contain at
-  least a ``main()`` function. If the ``<code>`` could be built and run
-  successfully, the internal cache variable specified by ``<resultVar>`` will
-  be set to 1, otherwise it will be set to an value that evaluates to boolean
-  false (e.g. an empty string or an error message).
+  Check once that the source supplied in ``<code>`` can be built, linked as an
+  executable, and then run. The ``<code>`` must contain at least a ``main()``
+  function.
 
-  The check is only performed once, with the result cached in the variable named
-  by ``<resultVar>``. Every subsequent CMake run will reuse this cached value
-  rather than performing the check again, even if the ``<code>`` changes. In
-  order to force the check to be re-evaluated, the variable named by
-  ``<resultVar>`` must be manually removed from the cache.
+  The result is stored in the internal cache variable specified by
+  ``<resultVar>``. Success of build and run is indicated by boolean ``true``.
+  Failure to build or run is indicated by boolean ``false`` such as an empty
+  string or an error message.
+
+  See also :command:`check_source_runs` for a more general command syntax.
 
   The compile and link commands can be influenced by setting any of the
   following variables prior to calling ``check_cxx_source_runs()``:
diff --git a/Modules/CheckFortranCompilerFlag.cmake b/Modules/CheckFortranCompilerFlag.cmake
index 81a2345..94090ef 100644
--- a/Modules/CheckFortranCompilerFlag.cmake
+++ b/Modules/CheckFortranCompilerFlag.cmake
@@ -29,6 +29,8 @@
 order to force the check to be re-evaluated, the variable named by
 ``<resultVar>`` must be manually removed from the cache.
 
+See also :command:`check_compiler_flag` for a more general command syntax.
+
 The compile and link commands can be influenced by setting any of the
 following variables prior to calling ``check_fortran_compiler_flag()``
 
diff --git a/Modules/CheckFortranSourceCompiles.cmake b/Modules/CheckFortranSourceCompiles.cmake
index 4cbe67a..e9545ab 100644
--- a/Modules/CheckFortranSourceCompiles.cmake
+++ b/Modules/CheckFortranSourceCompiles.cmake
@@ -30,6 +30,8 @@
   ``SRC_EXT`` option can be used to override this with ``.<extension>`` instead--
   ``.F90`` is a typical choice.
 
+  See also :command:`check_source_compiles` for a more general command syntax.
+
   See also :command:`check_source_runs` to run compiled source.
 
   Internally, :command:`try_compile` is used to compile the source. If
diff --git a/Modules/CheckFortranSourceRuns.cmake b/Modules/CheckFortranSourceRuns.cmake
index 9bf9fb2..97d750a 100644
--- a/Modules/CheckFortranSourceRuns.cmake
+++ b/Modules/CheckFortranSourceRuns.cmake
@@ -7,7 +7,7 @@
 
 .. versionadded:: 3.14
 
-Check if given Fortran source compiles and links into an executable and can
+Check once if given Fortran source compiles and links into an executable and can
 subsequently be run.
 
 .. command:: check_fortran_source_runs
@@ -17,9 +17,13 @@
     check_fortran_source_runs(<code> <resultVar>
         [SRC_EXT <extension>])
 
-  Check that the source supplied in ``<code>`` can be compiled as a Fortran source
-  file, linked as an executable and then run. The ``<code>`` must be a Fortran
-  ``program``.
+  Check once that the source supplied in ``<code>`` can be built, linked as an
+  executable, and then run. The ``<code>`` must contain a Fortran ``program``.
+
+  The result is stored in the internal cache variable specified by
+  ``<resultVar>``. Success of build and run is indicated by boolean ``true``.
+  Failure to build or run is indicated by boolean ``false`` such as an empty
+  string or an error message.
 
   .. code-block:: cmake
 
@@ -29,25 +33,10 @@
     end program"
     HAVE_COARRAY)
 
-  This command can help avoid costly build processes when a compiler lacks support
-  for a necessary feature, or a particular vendor library is not compatible with
-  the Fortran compiler version being used. Some of these failures only occur at runtime
-  instead of linktime, and a trivial runtime example can catch the issue before the
-  main build process.
-
-  If the ``<code>`` could be built and run
-  successfully, the internal cache variable specified by ``<resultVar>`` will
-  be set to 1, otherwise it will be set to an value that evaluates to boolean
-  false (e.g. an empty string or an error message).
-
   By default, the test source file will be given a ``.F90`` file extension. The
   ``SRC_EXT`` option can be used to override this with ``.<extension>`` instead.
 
-  The check is only performed once, with the result cached in the variable named
-  by ``<resultVar>``. Every subsequent CMake run will reuse this cached value
-  rather than performing the check again, even if the ``<code>`` changes. In
-  order to force the check to be re-evaluated, the variable named by
-  ``<resultVar>`` must be manually removed from the cache.
+  See also :command:`check_source_runs` for a more general command syntax.
 
   The compile and link commands can be influenced by setting any of the
   following variables prior to calling ``check_fortran_source_runs()``:
diff --git a/Modules/CheckOBJCCompilerFlag.cmake b/Modules/CheckOBJCCompilerFlag.cmake
index f6d259e..f87949b 100644
--- a/Modules/CheckOBJCCompilerFlag.cmake
+++ b/Modules/CheckOBJCCompilerFlag.cmake
@@ -29,6 +29,8 @@
 order to force the check to be re-evaluated, the variable named by
 ``<resultVar>`` must be manually removed from the cache.
 
+See also :command:`check_compiler_flag` for a more general command syntax.
+
 The compile and link commands can be influenced by setting any of the
 following variables prior to calling ``check_objc_compiler_flag()``
 
diff --git a/Modules/CheckOBJCSourceCompiles.cmake b/Modules/CheckOBJCSourceCompiles.cmake
index c6e09db..1158b91 100644
--- a/Modules/CheckOBJCSourceCompiles.cmake
+++ b/Modules/CheckOBJCSourceCompiles.cmake
@@ -30,6 +30,8 @@
   ``STATIC_LIBRARY``, the source is compiled but not linked. In any case, all
   functions must be declared as usual.
 
+  See also :command:`check_source_compiles` for a more general command syntax.
+
   See also :command:`check_source_runs` to run compiled source.
 
   The compile and link commands can be influenced by setting any of the
diff --git a/Modules/CheckOBJCSourceRuns.cmake b/Modules/CheckOBJCSourceRuns.cmake
index 511cac6..6b8160d 100644
--- a/Modules/CheckOBJCSourceRuns.cmake
+++ b/Modules/CheckOBJCSourceRuns.cmake
@@ -7,8 +7,8 @@
 
 .. versionadded:: 3.16
 
-Check if given Objective-C source compiles and links into an executable and can
-subsequently be run.
+Check once if given Objective-C source compiles and links into an executable and
+can subsequently be run.
 
 .. command:: check_objc_source_runs
 
@@ -16,18 +16,16 @@
 
     check_objc_source_runs(<code> <resultVar>)
 
-  Check that the source supplied in ``<code>`` can be compiled as a Objective-C source
-  file, linked as an executable and then run. The ``<code>`` must contain at
-  least a ``main()`` function. If the ``<code>`` could be built and run
-  successfully, the internal cache variable specified by ``<resultVar>`` will
-  be set to 1, otherwise it will be set to an value that evaluates to boolean
-  false (e.g. an empty string or an error message).
+  Check once that the source supplied in ``<code>`` can be built, linked as an
+  executable, and then run. The ``<code>`` must contain at least a ``main()``
+  function.
 
-  The check is only performed once, with the result cached in the variable named
-  by ``<resultVar>``. Every subsequent CMake run will reuse this cached value
-  rather than performing the check again, even if the ``<code>`` changes. In
-  order to force the check to be re-evaluated, the variable named by
-  ``<resultVar>`` must be manually removed from the cache.
+  The result is stored in the internal cache variable specified by
+  ``<resultVar>``. Success of build and run is indicated by boolean ``true``.
+  Failure to build or run is indicated by boolean ``false`` such as an empty
+  string or an error message.
+
+  See also :command:`check_source_runs` for a more general command syntax.
 
   The compile and link commands can be influenced by setting any of the
   following variables prior to calling ``check_objc_source_runs()``
diff --git a/Modules/CheckOBJCXXCompilerFlag.cmake b/Modules/CheckOBJCXXCompilerFlag.cmake
index 32d50c9..5091a75 100644
--- a/Modules/CheckOBJCXXCompilerFlag.cmake
+++ b/Modules/CheckOBJCXXCompilerFlag.cmake
@@ -29,6 +29,8 @@
 order to force the check to be re-evaluated, the variable named by
 ``<resultVar>`` must be manually removed from the cache.
 
+See also :command:`check_compiler_flag` for a more general command syntax.
+
 The compile and link commands can be influenced by setting any of the
 following variables prior to calling ``check_objcxx_compiler_flag()``
 
diff --git a/Modules/CheckOBJCXXSourceCompiles.cmake b/Modules/CheckOBJCXXSourceCompiles.cmake
index 4a18c21..af3ffde 100644
--- a/Modules/CheckOBJCXXSourceCompiles.cmake
+++ b/Modules/CheckOBJCXXSourceCompiles.cmake
@@ -30,6 +30,8 @@
   ``STATIC_LIBRARY``, the source is compiled but not linked. In any case, all
   functions must be declared as usual.
 
+  See also :command:`check_source_compiles` for a more general command syntax.
+
   See also :command:`check_source_runs` to run compiled source.
 
   The compile and link commands can be influenced by setting any of the
diff --git a/Modules/CheckOBJCXXSourceRuns.cmake b/Modules/CheckOBJCXXSourceRuns.cmake
index 49db3cb..f867ac3 100644
--- a/Modules/CheckOBJCXXSourceRuns.cmake
+++ b/Modules/CheckOBJCXXSourceRuns.cmake
@@ -7,8 +7,8 @@
 
 .. versionadded:: 3.16
 
-Check if given Objective-C++ source compiles and links into an executable and can
-subsequently be run.
+Check once if given Objective-C++ source compiles and links into an executable
+and can subsequently be run.
 
 .. command:: check_objcxx_source_runs
 
@@ -16,18 +16,16 @@
 
     check_objcxx_source_runs(<code> <resultVar>)
 
-  Check that the source supplied in ``<code>`` can be compiled as a Objective-C++ source
-  file, linked as an executable and then run. The ``<code>`` must contain at
-  least a ``main()`` function. If the ``<code>`` could be built and run
-  successfully, the internal cache variable specified by ``<resultVar>`` will
-  be set to 1, otherwise it will be set to an value that evaluates to boolean
-  false (e.g. an empty string or an error message).
+  Check once that the source supplied in ``<code>`` can be built, linked as an
+  executable, and then run. The ``<code>`` must contain at least a ``main()``
+  function.
 
-  The check is only performed once, with the result cached in the variable named
-  by ``<resultVar>``. Every subsequent CMake run will reuse this cached value
-  rather than performing the check again, even if the ``<code>`` changes. In
-  order to force the check to be re-evaluated, the variable named by
-  ``<resultVar>`` must be manually removed from the cache.
+  The result is stored in the internal cache variable specified by
+  ``<resultVar>``. Success of build and run is indicated by boolean ``true``.
+  Failure to build or run is indicated by boolean ``false`` such as an empty
+  string or an error message.
+
+  See also :command:`check_source_runs` for a more general command syntax.
 
   The compile and link commands can be influenced by setting any of the
   following variables prior to calling ``check_objcxx_source_runs()``
diff --git a/Modules/CheckSourceRuns.cmake b/Modules/CheckSourceRuns.cmake
index 75636f4..84684b6 100644
--- a/Modules/CheckSourceRuns.cmake
+++ b/Modules/CheckSourceRuns.cmake
@@ -18,12 +18,14 @@
     check_source_runs(<lang> <code> <resultVar>
                       [SRC_EXT <extension>])
 
-  Check that the source supplied in ``<code>`` can be compiled as a source
-  file for the requested language, linked as an executable and then run.
-  If the ``<code>`` could be built and run successfully, the internal cache variable
-  specified by ``<resultVar>`` will be set to 1, otherwise it will be set to
-  a value that evaluates to boolean false (e.g. an empty string or an error
-  message).
+  Check once that the ``<lang>`` source supplied in ``<code>`` can be built,
+  linked as an executable, and then run. The ``<code>`` must contain at least
+  a ``main()`` function, or in Fortran a ``program``.
+
+  The result is stored in the internal cache variable specified by
+  ``<resultVar>``. Success of build and run is indicated by boolean ``true``.
+  Failure to build or run is indicated by boolean ``false`` such as an empty
+  string or an error message.
 
   By default, the test source file will be given a file extension that matches
   the requested language. The ``SRC_EXT`` option can be used to override this
@@ -47,12 +49,6 @@
     end program"
     HAVE_COARRAY)
 
-  The check is only performed once, with the result cached in the variable named
-  by ``<resultVar>``. Every subsequent CMake run will reuse this cached value
-  rather than performing the check again, even if the ``<code>`` changes. In
-  order to force the check to be re-evaluated, the variable named by
-  ``<resultVar>`` must be manually removed from the cache.
-
   The compile and link commands can be influenced by setting any of the
   following variables prior to calling ``check_source_runs()``
 
diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake
index 51f05b9..82e3d88 100644
--- a/Modules/FindJNI.cmake
+++ b/Modules/FindJNI.cmake
@@ -391,8 +391,10 @@
     execute_process(
       COMMAND xcodebuild -version
       OUTPUT_VARIABLE _FindJNI_XCODEBUILD_VERSION
+      ERROR_VARIABLE _FindJNI_XCODEBUILD_VERSION
+      RESULT_VARIABLE _FindJNI_XCODEBUILD_RESULT
       )
-    if(_FindJNI_XCODEBUILD_VERSION MATCHES "Xcode ([0-9]+(\\.[0-9]+)*)")
+    if(_FindJNI_XCODEBUILD_RESULT EQUAL 0 AND _FindJNI_XCODEBUILD_VERSION MATCHES "Xcode ([0-9]+(\\.[0-9]+)*)")
       set(_FindJNI_XCODE_VERSION "${CMAKE_MATCH_1}")
     else()
       set(_FindJNI_XCODE_VERSION "")
diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake
index 112adae..5dc71ac 100644
--- a/Modules/FindPythonLibs.cmake
+++ b/Modules/FindPythonLibs.cmake
@@ -81,7 +81,10 @@
   endif()
 endif()
 
-include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake)
+block(SCOPE_FOR POLICIES)
+  cmake_policy(SET CMP0173 OLD)
+  include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake)
+endblock()
 # Search for the python framework on Apple.
 CMAKE_FIND_FRAMEWORKS(Python)
 
diff --git a/Modules/FindTCL.cmake b/Modules/FindTCL.cmake
index 9b771dc..eb53667 100644
--- a/Modules/FindTCL.cmake
+++ b/Modules/FindTCL.cmake
@@ -45,7 +45,10 @@
       and dig from there.
 #]=======================================================================]
 
-include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake)
+block(SCOPE_FOR POLICIES)
+  cmake_policy(SET CMP0173 OLD)
+  include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake)
+endblock()
 include(${CMAKE_CURRENT_LIST_DIR}/FindTclsh.cmake)
 include(${CMAKE_CURRENT_LIST_DIR}/FindWish.cmake)
 
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index b42a85e..88aaf96 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -467,7 +467,7 @@
       list(APPEND wxWidgets_LIBRARIES imm32)
     endif()
 
-    list(APPEND wxWidgets_LIBRARIES winmm comctl32 uuid oleacc uxtheme rpcrt4 shlwapi version wsock32)
+    list(APPEND wxWidgets_LIBRARIES gdiplus msimg32 winmm comctl32 uuid oleacc uxtheme rpcrt4 shlwapi version wsock32)
   endmacro()
 
   #-------------------------------------------------------------------
diff --git a/Modules/Internal/CMakeSwiftLinkerInformation.cmake b/Modules/Internal/CMakeSwiftLinkerInformation.cmake
index fb3e986..6d1881f 100644
--- a/Modules/Internal/CMakeSwiftLinkerInformation.cmake
+++ b/Modules/Internal/CMakeSwiftLinkerInformation.cmake
@@ -13,7 +13,7 @@
 set(_INCLUDED_FILE 0)
 
 # Load linker-specific information.
-if(CMAKE_Swoft_COMPILER_LINKER_ID)
+if(CMAKE_Swift_COMPILER_LINKER_ID)
   include(Linker/${CMAKE_Swift_COMPILER_LINKER_ID}-Swift OPTIONAL)
 endif()
 
diff --git a/Modules/Internal/CPack/ISScript.template.in b/Modules/Internal/CPack/ISScript.template.in
index 1171058..db475fe 100644
--- a/Modules/Internal/CPack/ISScript.template.in
+++ b/Modules/Internal/CPack/ISScript.template.in
@@ -1,4 +1,4 @@
-; Script generated by the CPack Inno Setup generator.
+; Script generated by the CPack Inno Setup generator.
 ; All changes made in this file will be lost when CPack is run again.
 
 @CPACK_INNOSETUP_INCLUDES_INTERNAL@
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index 95bf30d..bab6042 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -375,21 +375,21 @@
 if(CMAKE_ANDROID_ARCH_ABI AND NOT DEFINED "NDK_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC")
   message(FATAL_ERROR "Android: Unknown ABI CMAKE_ANDROID_ARCH_ABI='${CMAKE_ANDROID_ARCH_ABI}'.")
 endif()
-if(CMAKE_SYSTEM_PROCESSOR AND NOT DEFINED "NDK_PROC_${CMAKE_SYSTEM_PROCESSOR}_ABI")
-  message(FATAL_ERROR "Android: Unknown processor CMAKE_SYSTEM_PROCESSOR='${CMAKE_SYSTEM_PROCESSOR}'.")
-endif()
-if(_ANDROID_SYSROOT_ARCH AND NOT DEFINED "NDK_ARCH_${_ANDROID_SYSROOT_ARCH}_ABI")
-  message(FATAL_ERROR
-    "Android: Unknown architecture '${_ANDROID_SYSROOT_ARCH}' specified in CMAKE_SYSROOT:\n"
-    "  ${CMAKE_SYSROOT}"
-    )
-endif()
 
 # Select an ABI.
 if(NOT CMAKE_ANDROID_ARCH_ABI)
   if(CMAKE_SYSTEM_PROCESSOR)
+    if(NOT DEFINED "NDK_PROC_${CMAKE_SYSTEM_PROCESSOR}_ABI")
+      message(FATAL_ERROR "Android: Unknown processor CMAKE_SYSTEM_PROCESSOR='${CMAKE_SYSTEM_PROCESSOR}'.")
+    endif()
     set(CMAKE_ANDROID_ARCH_ABI "${NDK_PROC_${CMAKE_SYSTEM_PROCESSOR}_ABI}")
   elseif(_ANDROID_SYSROOT_ARCH)
+    if(NOT DEFINED "NDK_ARCH_${_ANDROID_SYSROOT_ARCH}_ABI")
+      message(FATAL_ERROR
+        "Android: Unknown architecture '${_ANDROID_SYSROOT_ARCH}' specified in CMAKE_SYSROOT:\n"
+        "  ${CMAKE_SYSROOT}"
+        )
+    endif()
     set(CMAKE_ANDROID_ARCH_ABI "${NDK_ARCH_${_ANDROID_SYSROOT_ARCH}_ABI}")
   elseif(_INCLUDED_ABIS)
     # Default to the oldest ARM ABI.
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 5337094..857d3ff 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 30)
-set(CMake_VERSION_PATCH 20240816)
+set(CMake_VERSION_PATCH 20240826)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 03b8766..b025570 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -1552,6 +1552,7 @@
 #ifdef _WIN32
     // Given name matches a reserved name (on Windows)?
     // Then return it prepended with an underscore.
+    // See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
     cmsys::RegularExpression reserved_pattern("^("
                                               "[Cc][Oo][Nn]|"
                                               "[Pp][Rr][Nn]|"
@@ -1559,7 +1560,7 @@
                                               "[Nn][Uu][Ll]|"
                                               "[Cc][Oo][Mm][1-9]|"
                                               "[Ll][Pp][Tt][1-9]"
-                                              ")([.].+)?");
+                                              ")[.]?$");
     if (reserved_pattern.find(name)) {
       return "_" + name;
     }
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 43b1d76..155bc9e 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -863,8 +863,8 @@
     /* clang-format on */
     componentCode += out.str();
   } else {
-    componentCode +=
-      "  File /r \"${INST_DIR}\\" + component->Name + "\\*.*\"\n";
+    componentCode += "  File /r \"${INST_DIR}\\" +
+      this->GetSanitizedDirOrFileName(component->Name) + "\\*.*\"\n";
   }
   componentCode += "SectionEnd\n";
 
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
index 4d60c6c..a64093e 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -434,7 +434,7 @@
   }
 
   std::string inFName = cmStrCat("CPack.", name, ".in");
-  std::string inFileName = this->FindTemplate(inFName.c_str());
+  std::string inFileName = this->FindTemplate(inFName);
   if (inFileName.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
                   "Cannot find input file: " << inFName << std::endl);
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 39a8e85..305ac56 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -583,7 +583,7 @@
               cmValue projVersionPatch =
                 mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
               std::ostringstream ostr;
-              ostr << *projVersionMajor << "." << *projVersionMinor << '.'
+              ostr << *projVersionMajor << '.' << *projVersionMinor << '.'
                    << *projVersionPatch;
               mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str());
             }
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index 0a03f3a..0ba0c22 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -36,6 +36,8 @@
         )
     endif()
     set(check_output "${OUTPUT}")
+    # Filter out ninja warnings.
+    string(REGEX REPLACE "[^\n]*ninja: warning: [^\n]*" "" check_output "${check_output}")
     # Filter out MSBuild output that looks like a warning.
     string(REGEX REPLACE " +0 Warning\\(s\\)" "" check_output "${check_output}")
     # Filter out MSBuild output that looks like a warning.
diff --git a/Source/Checks/cm_cxx_filesystem.cxx b/Source/Checks/cm_cxx_filesystem.cxx
index bdc7c6d..456ec46 100644
--- a/Source/Checks/cm_cxx_filesystem.cxx
+++ b/Source/Checks/cm_cxx_filesystem.cxx
@@ -47,7 +47,7 @@
 #if defined(__GLIBCXX__)
   // RH gcc-toolset-10 has a strange bug: it selects, in some circumstances,
   // the wrong constructor which generate error in template instantiation.
-  class my_string_view : std::string_view
+  class my_string_view : public std::string_view
   {
   public:
     my_string_view(const char* p)
diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx
index e2a8f92..ca40726 100644
--- a/Source/cmBinUtilsLinuxELFLinker.cxx
+++ b/Source/cmBinUtilsLinuxELFLinker.cxx
@@ -3,7 +3,10 @@
 
 #include "cmBinUtilsLinuxELFLinker.h"
 
+#include <queue>
 #include <sstream>
+#include <unordered_set>
+#include <utility>
 
 #include <cm/memory>
 #include <cm/string_view>
@@ -89,8 +92,6 @@
 bool cmBinUtilsLinuxELFLinker::ScanDependencies(
   std::string const& file, cmStateEnums::TargetType /* unused */)
 {
-  std::vector<std::string> parentRpaths;
-
   cmELF elf(file.c_str());
   if (!elf) {
     return false;
@@ -106,40 +107,53 @@
     }
   }
 
-  return this->ScanDependencies(file, parentRpaths);
+  return this->ScanDependencies(file);
 }
 
-bool cmBinUtilsLinuxELFLinker::ScanDependencies(
-  std::string const& file, std::vector<std::string> const& parentRpaths)
+bool cmBinUtilsLinuxELFLinker::ScanDependencies(std::string const& mainFile)
 {
-  std::string origin = cmSystemTools::GetFilenamePath(file);
-  std::vector<std::string> needed;
-  std::vector<std::string> rpaths;
-  std::vector<std::string> runpaths;
-  if (!this->Tool->GetFileInfo(file, needed, rpaths, runpaths)) {
-    return false;
-  }
-  for (auto& runpath : runpaths) {
-    runpath = ReplaceOrigin(runpath, origin);
-  }
-  for (auto& rpath : rpaths) {
-    rpath = ReplaceOrigin(rpath, origin);
-  }
+  std::unordered_set<std::string> resolvedDependencies;
+  std::queue<std::pair<std::string, std::vector<std::string>>> queueToResolve;
+  queueToResolve.push(std::make_pair(mainFile, std::vector<std::string>{}));
 
-  std::vector<std::string> searchPaths;
-  if (!runpaths.empty()) {
-    searchPaths = runpaths;
-  } else {
-    searchPaths = rpaths;
-    searchPaths.insert(searchPaths.end(), parentRpaths.begin(),
-                       parentRpaths.end());
-  }
+  while (!queueToResolve.empty()) {
+    std::string file = std::move(queueToResolve.front().first);
+    std::vector<std::string> parentRpaths =
+      std::move(queueToResolve.front().second);
+    queueToResolve.pop();
 
-  searchPaths.insert(searchPaths.end(), this->LDConfigPaths.begin(),
-                     this->LDConfigPaths.end());
+    std::string origin = cmSystemTools::GetFilenamePath(file);
+    std::vector<std::string> needed;
+    std::vector<std::string> rpaths;
+    std::vector<std::string> runpaths;
+    if (!this->Tool->GetFileInfo(file, needed, rpaths, runpaths)) {
+      return false;
+    }
+    for (auto& runpath : runpaths) {
+      runpath = ReplaceOrigin(runpath, origin);
+    }
+    for (auto& rpath : rpaths) {
+      rpath = ReplaceOrigin(rpath, origin);
+    }
 
-  for (auto const& dep : needed) {
-    if (!this->Archive->IsPreExcluded(dep)) {
+    std::vector<std::string> searchPaths;
+    if (!runpaths.empty()) {
+      searchPaths = runpaths;
+    } else {
+      searchPaths = rpaths;
+      searchPaths.insert(searchPaths.end(), parentRpaths.begin(),
+                         parentRpaths.end());
+    }
+
+    searchPaths.insert(searchPaths.end(), this->LDConfigPaths.begin(),
+                       this->LDConfigPaths.end());
+
+    for (auto const& dep : needed) {
+      if (resolvedDependencies.count(dep) != 0 ||
+          this->Archive->IsPreExcluded(dep)) {
+        continue;
+      }
+
       std::string path;
       bool resolved = false;
       if (dep.find('/') != std::string::npos) {
@@ -150,6 +164,7 @@
         return false;
       }
       if (resolved) {
+        resolvedDependencies.emplace(dep);
         if (!this->Archive->IsPostExcluded(path)) {
           bool unique;
           this->Archive->AddResolvedPath(dep, path, unique);
@@ -157,9 +172,8 @@
             std::vector<std::string> combinedParentRpaths = parentRpaths;
             combinedParentRpaths.insert(combinedParentRpaths.end(),
                                         rpaths.begin(), rpaths.end());
-            if (!this->ScanDependencies(path, combinedParentRpaths)) {
-              return false;
-            }
+
+            queueToResolve.push(std::make_pair(path, combinedParentRpaths));
           }
         }
       } else {
diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h
index 395ed56..0b0d8b5 100644
--- a/Source/cmBinUtilsLinuxELFLinker.h
+++ b/Source/cmBinUtilsLinuxELFLinker.h
@@ -34,8 +34,7 @@
   std::vector<std::string> LDConfigPaths;
   std::uint16_t Machine = 0;
 
-  bool ScanDependencies(std::string const& file,
-                        std::vector<std::string> const& parentRpaths);
+  bool ScanDependencies(std::string const& mainFile);
 
   bool ResolveDependency(std::string const& name,
                          std::vector<std::string> const& searchPaths,
diff --git a/Source/cmCMakePresetsErrors.cxx b/Source/cmCMakePresetsErrors.cxx
index 5919512..ab0afed 100644
--- a/Source/cmCMakePresetsErrors.cxx
+++ b/Source/cmCMakePresetsErrors.cxx
@@ -238,6 +238,16 @@
   state->AddError("File version must be 7 or higher for trace preset support");
 }
 
+JsonErrors::ErrorGenerator UNRECOGNIZED_VERSION_RANGE(int min, int max)
+{
+  return [min, max](const Json::Value* value, cmJSONState* state) -> void {
+    state->AddErrorAtValue(cmStrCat("Unrecognized \"version\" ",
+                                    value->asString(), ": must be >=", min,
+                                    " and <=", max),
+                           value);
+  };
+}
+
 JsonErrors::ErrorGenerator UNRECOGNIZED_CMAKE_VERSION(
   const std::string& version, int current, int required)
 {
diff --git a/Source/cmCMakePresetsErrors.h b/Source/cmCMakePresetsErrors.h
index dda9274..22830d2 100644
--- a/Source/cmCMakePresetsErrors.h
+++ b/Source/cmCMakePresetsErrors.h
@@ -94,6 +94,8 @@
 
 void TRACE_UNSUPPORTED(cmJSONState* state);
 
+JsonErrors::ErrorGenerator UNRECOGNIZED_VERSION_RANGE(int min, int max);
+
 JsonErrors::ErrorGenerator UNRECOGNIZED_CMAKE_VERSION(
   const std::string& version, int current, int required);
 
diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx
index df6482d..18ae9af 100644
--- a/Source/cmCMakePresetsGraphReadJSON.cxx
+++ b/Source/cmCMakePresetsGraphReadJSON.cxx
@@ -256,9 +256,14 @@
 auto const VersionHelper = JSONHelperBuilder::Required<int>(
   cmCMakePresetsErrors::NO_VERSION, VersionIntHelper);
 
+auto const VersionRangeHelper = JSONHelperBuilder::Checked<int>(
+  cmCMakePresetsErrors::UNRECOGNIZED_VERSION_RANGE(MIN_VERSION, MAX_VERSION),
+  VersionHelper,
+  [](const int v) -> bool { return v >= MIN_VERSION && v <= MAX_VERSION; });
+
 auto const RootVersionHelper =
   JSONHelperBuilder::Object<int>(cmCMakePresetsErrors::INVALID_ROOT_OBJECT)
-    .Bind("version"_s, VersionHelper, false);
+    .Bind("version"_s, VersionRangeHelper, false);
 
 auto const CMakeVersionUIntHelper =
   JSONHelperBuilder::UInt(cmCMakePresetsErrors::INVALID_VERSION);
@@ -481,11 +486,6 @@
   if ((result = RootVersionHelper(v, &root, &parseState)) != true) {
     return result;
   }
-  if (v < MIN_VERSION || v > MAX_VERSION) {
-    cmCMakePresetsErrors::UNRECOGNIZED_VERSION(&root["version"],
-                                               &this->parseState);
-    return false;
-  }
 
   // Support for build and test presets added in version 2.
   if (v < 2) {
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index f42d7f6..7d51dd1 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -235,8 +235,8 @@
   char buf[1024];
   // add todays year day and month to the time in str because
   // curl_getdate no longer assumes the day is today
-  snprintf(buf, sizeof(buf), "%d%02d%02d %s", lctime->tm_year + 1900,
-           lctime->tm_mon + 1, lctime->tm_mday, str.c_str());
+  std::snprintf(buf, sizeof(buf), "%d%02d%02d %s", lctime->tm_year + 1900,
+                lctime->tm_mon + 1, lctime->tm_mday, str.c_str());
   cmCTestLog(this, OUTPUT,
              "Determine Nightly Start Time" << std::endl
                                             << "   Specified time: " << str
@@ -1074,11 +1074,6 @@
   return cmCTest::EXPERIMENTAL;
 }
 
-// ######################################################################
-// ######################################################################
-// ######################################################################
-// ######################################################################
-
 bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
                              int* retVal, const char* dir, cmDuration timeout,
                              std::ostream& ofs, Encoding encoding)
@@ -1191,11 +1186,6 @@
   return true;
 }
 
-// ######################################################################
-// ######################################################################
-// ######################################################################
-// ######################################################################
-
 bool cmCTest::RunTest(const std::vector<std::string>& argv,
                       std::string* output, int* retVal, std::ostream* log,
                       cmDuration testTimeOut,
@@ -1857,22 +1847,20 @@
 void cmCTest::ErrorMessageUnknownDashDValue(std::string& val)
 {
   cmCTestLog(this, ERROR_MESSAGE,
-             "CTest -D called with incorrect option: " << val << std::endl);
+             "CTest -D called with incorrect option: " << val << '\n');
 
-  cmCTestLog(
-    this, ERROR_MESSAGE,
-    "Available options are:"
-      << std::endl
-      << "  ctest -D Continuous" << std::endl
-      << "  ctest -D Continuous(Start|Update|Configure|Build)" << std::endl
-      << "  ctest -D Continuous(Test|Coverage|MemCheck|Submit)" << std::endl
-      << "  ctest -D Experimental" << std::endl
-      << "  ctest -D Experimental(Start|Update|Configure|Build)" << std::endl
-      << "  ctest -D Experimental(Test|Coverage|MemCheck|Submit)" << std::endl
-      << "  ctest -D Nightly" << std::endl
-      << "  ctest -D Nightly(Start|Update|Configure|Build)" << std::endl
-      << "  ctest -D Nightly(Test|Coverage|MemCheck|Submit)" << std::endl
-      << "  ctest -D NightlyMemoryCheck" << std::endl);
+  cmCTestLog(this, ERROR_MESSAGE,
+             "Available options are:\n"
+             "  ctest -D Continuous\n"
+             "  ctest -D Continuous(Start|Update|Configure|Build)\n"
+             "  ctest -D Continuous(Test|Coverage|MemCheck|Submit)\n"
+             "  ctest -D Experimental\n"
+             "  ctest -D Experimental(Start|Update|Configure|Build)\n"
+             "  ctest -D Experimental(Test|Coverage|MemCheck|Submit)\n"
+             "  ctest -D Nightly\n"
+             "  ctest -D Nightly(Start|Update|Configure|Build)\n"
+             "  ctest -D Nightly(Test|Coverage|MemCheck|Submit)\n"
+             "  ctest -D NightlyMemoryCheck\n");
 }
 
 bool cmCTest::CheckArgument(const std::string& arg, cm::string_view varg1,
@@ -1982,7 +1970,7 @@
       this->SetTestLoad(load);
     } else {
       cmCTestLog(this, WARNING,
-                 "Invalid value for 'Test Load' : " << args[i] << std::endl);
+                 "Invalid value for 'Test Load' : " << args[i] << '\n');
     }
   }
 
@@ -2908,21 +2896,21 @@
     if (!this->SetTest(args[i], false)) {
       success = false;
       cmCTestLog(this, ERROR_MESSAGE,
-                 "CTest -T called with incorrect option: " << args[i]
-                                                           << std::endl);
+                 "CTest -T called with incorrect option: " << args[i] << '\n');
+      /* clang-format off */
       cmCTestLog(this, ERROR_MESSAGE,
-                 "Available options are:"
-                   << std::endl
-                   << "  " << ctestExec << " -T all" << std::endl
-                   << "  " << ctestExec << " -T start" << std::endl
-                   << "  " << ctestExec << " -T update" << std::endl
-                   << "  " << ctestExec << " -T configure" << std::endl
-                   << "  " << ctestExec << " -T build" << std::endl
-                   << "  " << ctestExec << " -T test" << std::endl
-                   << "  " << ctestExec << " -T coverage" << std::endl
-                   << "  " << ctestExec << " -T memcheck" << std::endl
-                   << "  " << ctestExec << " -T notes" << std::endl
-                   << "  " << ctestExec << " -T submit" << std::endl);
+                 "Available options are:\n"
+                 "  " << ctestExec << " -T all\n"
+                 "  " << ctestExec << " -T start\n"
+                 "  " << ctestExec << " -T update\n"
+                 "  " << ctestExec << " -T configure\n"
+                 "  " << ctestExec << " -T build\n"
+                 "  " << ctestExec << " -T test\n"
+                 "  " << ctestExec << " -T coverage\n"
+                 "  " << ctestExec << " -T memcheck\n"
+                 "  " << ctestExec << " -T notes\n"
+                 "  " << ctestExec << " -T submit\n");
+      /* clang-format on */
     }
   }
   return success;
@@ -2948,14 +2936,14 @@
     } else {
       success = false;
       cmCTestLog(this, ERROR_MESSAGE,
-                 "CTest -M called with incorrect option: " << str
-                                                           << std::endl);
+                 "CTest -M called with incorrect option: " << str << '\n');
+      /* clang-format off */
       cmCTestLog(this, ERROR_MESSAGE,
-                 "Available options are:"
-                   << std::endl
-                   << "  " << ctestExec << " -M Continuous" << std::endl
-                   << "  " << ctestExec << " -M Experimental" << std::endl
-                   << "  " << ctestExec << " -M Nightly" << std::endl);
+                 "Available options are:\n"
+                 "  " << ctestExec << " -M Continuous\n"
+                 "  " << ctestExec << " -M Experimental\n"
+                 "  " << ctestExec << " -M Nightly\n");
+      /* clang-format on */
     }
   }
   return success;
@@ -3497,10 +3485,10 @@
   size_t epos = overStr.find('=');
   if (epos == std::string::npos) {
     cmCTestLog(this, ERROR_MESSAGE,
-               "CTest configuration overwrite specified in the wrong format."
-                 << std::endl
-                 << "Valid format is: --overwrite key=value" << std::endl
-                 << "The specified was: --overwrite " << overStr << std::endl);
+               "CTest configuration overwrite specified in the wrong format.\n"
+               "Valid format is: --overwrite key=value\n"
+               "The specified was: --overwrite "
+                 << overStr << '\n');
     return;
   }
   std::string key = overStr.substr(0, epos);
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index e069b77..21ea463 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -202,9 +202,7 @@
 #  endif
   command = commandInDir;
   if (verbose) {
-    cmSystemTools::Stdout("running ");
-    cmSystemTools::Stdout(command);
-    cmSystemTools::Stdout("\n");
+    cmSystemTools::Stdout(cmStrCat("running ", command, '\n'));
   }
   fflush(stdout);
   fflush(stderr);
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 7d62fa8..b051d67 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -573,13 +573,7 @@
   cm->GetState()->SetWindowsShell(true);
 
   // Attempt to use full path to COMSPEC, default "cmd.exe"
-  std::string comspec;
-  if (cmSystemTools::GetEnv("COMSPEC", comspec) &&
-      cmSystemTools::FileIsFullPath(comspec)) {
-    this->Comspec = comspec;
-  } else {
-    this->Comspec = "cmd.exe";
-  }
+  this->Comspec = cmSystemTools::GetComspec();
 #endif
   cm->GetState()->SetNinja(true);
   this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index 4956054..5ac2bd3 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -20,6 +20,7 @@
 {
   static std::map<std::string, cmPolicies::PolicyID> DeprecatedModules;
   if (DeprecatedModules.empty()) {
+    DeprecatedModules["CMakeFindFrameworks"] = cmPolicies::CMP0173;
     DeprecatedModules["Dart"] = cmPolicies::CMP0145;
     DeprecatedModules["Documentation"] = cmPolicies::CMP0106;
     DeprecatedModules["FindBoost"] = cmPolicies::CMP0167;
diff --git a/Source/cmInstallScriptHandler.cxx b/Source/cmInstallScriptHandler.cxx
index d421ce7..353deee 100644
--- a/Source/cmInstallScriptHandler.cxx
+++ b/Source/cmInstallScriptHandler.cxx
@@ -72,8 +72,9 @@
   cm::uv_loop_ptr loop;
   loop.init();
   std::vector<InstallScript> scripts;
+  scripts.reserve(this->commands.size());
   for (auto const& cmd : this->commands) {
-    scripts.push_back(InstallScript(cmd));
+    scripts.emplace_back(cmd);
   }
   std::size_t working = 0;
   std::size_t installed = 0;
@@ -153,7 +154,7 @@
 
 void InstallScript::printResult(std::size_t n, std::size_t total)
 {
-  cmSystemTools::Stdout(cmStrCat("[", n, "/", total, "] ", this->name, "\n"));
+  cmSystemTools::Stdout(cmStrCat('[', n, '/', total, "] ", this->name, '\n'));
   for (auto const& line : this->output) {
     cmSystemTools::Stdout(line);
   }
diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h
index 368a0df..0bb32f4 100644
--- a/Source/cmJSONHelpers.h
+++ b/Source/cmJSONHelpers.h
@@ -34,9 +34,11 @@
   ExtraField,
   MissingRequired
 };
+
 using ErrorGenerator = std::function<void(const Json::Value*, cmJSONState*)>;
 using ObjectErrorGenerator =
   std::function<ErrorGenerator(ObjectError, const Json::Value::Members&)>;
+
 ErrorGenerator EXPECTED_TYPE(const std::string& type);
 
 void INVALID_STRING(const Json::Value* value, cmJSONState* state);
@@ -104,7 +106,6 @@
     bool operator()(T& out, const Json::Value* value, cmJSONState* state) const
     {
       Json::Value::Members extraFields;
-      bool success = true;
       if (!value && this->AnyRequired) {
         Error(JsonErrors::ObjectError::RequiredMissing, extraFields)(value,
                                                                      state);
@@ -125,6 +126,7 @@
           extraFields.end());
       }
 
+      bool success = true;
       for (auto const& m : this->Members) {
         std::string name(m.Name.data(), m.Name.size());
         state->push_stack(name, value);
@@ -159,6 +161,12 @@
                                               cmJSONState* state)>;
     struct Member
     {
+      Member(cm::string_view name, MemberFunction func, bool required)
+        : Name{ name }
+        , Function{ std::move(func) }
+        , Required{ required }
+      {
+      }
       cm::string_view Name;
       MemberFunction Function;
       bool Required;
@@ -171,14 +179,8 @@
     Object& BindPrivate(const cm::string_view& name, MemberFunction&& func,
                         bool required)
     {
-      Member m;
-      m.Name = name;
-      m.Function = std::move(func);
-      m.Required = required;
-      this->Members.push_back(std::move(m));
-      if (required) {
-        this->AnyRequired = true;
-      }
+      this->Members.emplace_back(name, std::move(func), required);
+      this->AnyRequired = this->AnyRequired || required;
       return *this;
     }
   };
@@ -195,7 +197,6 @@
       }
       if (!value->isString()) {
         error(value, state);
-        ;
         return false;
       }
       out = value->asString();
@@ -220,7 +221,6 @@
       }
       if (!value->isInt()) {
         error(value, state);
-        ;
         return false;
       }
       out = value->asInt();
@@ -245,7 +245,6 @@
       }
       if (!value->isUInt()) {
         error(value, state);
-        ;
         return false;
       }
       out = value->asUInt();
@@ -270,7 +269,6 @@
       }
       if (!value->isBool()) {
         error(value, state);
-        ;
         return false;
       }
       out = value->asBool();
@@ -332,19 +330,18 @@
     return [error, func, filter](std::map<std::string, T>& out,
                                  const Json::Value* value,
                                  cmJSONState* state) -> bool {
-      bool success = true;
       if (!value) {
         out.clear();
         return true;
       }
       if (!value->isObject()) {
         error(value, state);
-        ;
         return false;
       }
       out.clear();
+      bool success = true;
       for (auto const& key : value->getMemberNames()) {
-        state->push_stack(cmStrCat(key, ""), &(*value)[key]);
+        state->push_stack(key, &(*value)[key]);
         if (!filter(key)) {
           state->pop_stack();
           continue;
@@ -353,7 +350,7 @@
         if (!func(t, &(*value)[key], state)) {
           success = false;
         }
-        out[key] = std::move(t);
+        out.emplace(key, std::move(t));
         state->pop_stack();
       }
       return success;
@@ -390,10 +387,24 @@
                          cmJSONState* state) -> bool {
       if (!value) {
         error(value, state);
-        ;
         return false;
       }
       return func(out, value, state);
     };
   }
+
+  template <typename T, typename F, typename P>
+  static cmJSONHelper<T> Checked(const JsonErrors::ErrorGenerator& error,
+                                 F func, P predicate)
+  {
+    return [error, func, predicate](T& out, const Json::Value* value,
+                                    cmJSONState* state) -> bool {
+      bool result = func(out, value, state);
+      if (result && !predicate(out)) {
+        error(value, state);
+        result = false;
+      }
+      return result;
+    };
+  }
 };
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index b4ea71c..a2e81db 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -21,6 +21,129 @@
 #  include "cmDebuggerAdapter.h"
 #endif
 
+namespace {
+const char* getMessageTypeStr(MessageType t)
+{
+  switch (t) {
+    case MessageType::FATAL_ERROR:
+      return "Error";
+    case MessageType::INTERNAL_ERROR:
+      return "Internal Error (please report a bug)";
+    case MessageType::LOG:
+      return "Debug Log";
+    case MessageType::DEPRECATION_ERROR:
+      return "Deprecation Error";
+    case MessageType::DEPRECATION_WARNING:
+      return "Deprecation Warning";
+    case MessageType::AUTHOR_WARNING:
+      return "Warning (dev)";
+    case MessageType::AUTHOR_ERROR:
+      return "Error (dev)";
+    default:
+      break;
+  }
+  return "Warning";
+}
+
+int getMessageColor(MessageType t)
+{
+  switch (t) {
+    case MessageType::INTERNAL_ERROR:
+    case MessageType::FATAL_ERROR:
+    case MessageType::AUTHOR_ERROR:
+      return cmsysTerminal_Color_ForegroundRed;
+    case MessageType::AUTHOR_WARNING:
+    case MessageType::WARNING:
+      return cmsysTerminal_Color_ForegroundYellow;
+    default:
+      return cmsysTerminal_Color_Normal;
+  }
+}
+
+void printMessageText(std::ostream& msg, std::string const& text)
+{
+  msg << ":\n";
+  cmDocumentationFormatter formatter;
+  formatter.SetIndent(2u);
+  formatter.PrintFormatted(msg, text);
+}
+
+void displayMessage(MessageType t, std::ostringstream& msg)
+{
+  // Add a note about warning suppression.
+  if (t == MessageType::AUTHOR_WARNING) {
+    msg << "This warning is for project developers.  Use -Wno-dev to suppress "
+           "it.";
+  } else if (t == MessageType::AUTHOR_ERROR) {
+    msg << "This error is for project developers. Use -Wno-error=dev to "
+           "suppress it.";
+  }
+
+  // Add a terminating blank line.
+  msg << '\n';
+
+#if !defined(CMAKE_BOOTSTRAP)
+  // Add a C++ stack trace to internal errors.
+  if (t == MessageType::INTERNAL_ERROR) {
+    std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
+    if (!stack.empty()) {
+      if (cmHasLiteralPrefix(stack, "WARNING:")) {
+        stack = "Note:" + stack.substr(8);
+      }
+      msg << stack << '\n';
+    }
+  }
+#endif
+
+  // Output the message.
+  cmMessageMetadata md;
+  md.desiredColor = getMessageColor(t);
+  if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
+      t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
+    cmSystemTools::SetErrorOccurred();
+    md.title = "Error";
+    cmSystemTools::Message(msg.str(), md);
+  } else {
+    md.title = "Warning";
+    cmSystemTools::Message(msg.str(), md);
+  }
+}
+
+void PrintCallStack(std::ostream& out, cmListFileBacktrace bt,
+                    cm::optional<std::string> const& topSource)
+{
+  // The call stack exists only if we have at least two calls on top
+  // of the bottom.
+  if (bt.Empty()) {
+    return;
+  }
+  bt = bt.Pop();
+  if (bt.Empty()) {
+    return;
+  }
+
+  bool first = true;
+  for (; !bt.Empty(); bt = bt.Pop()) {
+    cmListFileContext lfc = bt.Top();
+    if (lfc.Name.empty() &&
+        lfc.Line != cmListFileContext::DeferPlaceholderLine) {
+      // Skip this whole-file scope.  When we get here we already will
+      // have printed a more-specific context within the file.
+      continue;
+    }
+    if (first) {
+      first = false;
+      out << "Call Stack (most recent call first):\n";
+    }
+    if (topSource) {
+      lfc.FilePath = cmSystemTools::RelativeIfUnder(*topSource, lfc.FilePath);
+    }
+    out << "  " << lfc << '\n';
+  }
+}
+
+} // anonymous namespace
+
 MessageType cmMessenger::ConvertMessageType(MessageType t) const
 {
   if (t == MessageType::AUTHOR_WARNING || t == MessageType::AUTHOR_ERROR) {
@@ -57,128 +180,6 @@
   return true;
 }
 
-static bool printMessagePreamble(MessageType t, std::ostream& msg)
-{
-  // Construct the message header.
-  if (t == MessageType::FATAL_ERROR) {
-    msg << "CMake Error";
-  } else if (t == MessageType::INTERNAL_ERROR) {
-    msg << "CMake Internal Error (please report a bug)";
-  } else if (t == MessageType::LOG) {
-    msg << "CMake Debug Log";
-  } else if (t == MessageType::DEPRECATION_ERROR) {
-    msg << "CMake Deprecation Error";
-  } else if (t == MessageType::DEPRECATION_WARNING) {
-    msg << "CMake Deprecation Warning";
-  } else if (t == MessageType::AUTHOR_WARNING) {
-    msg << "CMake Warning (dev)";
-  } else if (t == MessageType::AUTHOR_ERROR) {
-    msg << "CMake Error (dev)";
-  } else {
-    msg << "CMake Warning";
-  }
-  return true;
-}
-
-static int getMessageColor(MessageType t)
-{
-  switch (t) {
-    case MessageType::INTERNAL_ERROR:
-    case MessageType::FATAL_ERROR:
-    case MessageType::AUTHOR_ERROR:
-      return cmsysTerminal_Color_ForegroundRed;
-    case MessageType::AUTHOR_WARNING:
-    case MessageType::WARNING:
-      return cmsysTerminal_Color_ForegroundYellow;
-    default:
-      return cmsysTerminal_Color_Normal;
-  }
-}
-
-static void printMessageText(std::ostream& msg, std::string const& text)
-{
-  msg << ":\n";
-  cmDocumentationFormatter formatter;
-  formatter.SetIndent(2u);
-  formatter.PrintFormatted(msg, text);
-}
-
-static void displayMessage(MessageType t, std::ostringstream& msg)
-{
-  // Add a note about warning suppression.
-  if (t == MessageType::AUTHOR_WARNING) {
-    msg << "This warning is for project developers.  Use -Wno-dev to suppress "
-           "it.";
-  } else if (t == MessageType::AUTHOR_ERROR) {
-    msg << "This error is for project developers. Use -Wno-error=dev to "
-           "suppress it.";
-  }
-
-  // Add a terminating blank line.
-  msg << "\n";
-
-#if !defined(CMAKE_BOOTSTRAP)
-  // Add a C++ stack trace to internal errors.
-  if (t == MessageType::INTERNAL_ERROR) {
-    std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
-    if (!stack.empty()) {
-      if (cmHasLiteralPrefix(stack, "WARNING:")) {
-        stack = "Note:" + stack.substr(8);
-      }
-      msg << stack << "\n";
-    }
-  }
-#endif
-
-  // Output the message.
-  cmMessageMetadata md;
-  md.desiredColor = getMessageColor(t);
-  if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
-      t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
-    cmSystemTools::SetErrorOccurred();
-    md.title = "Error";
-    cmSystemTools::Message(msg.str(), md);
-  } else {
-    md.title = "Warning";
-    cmSystemTools::Message(msg.str(), md);
-  }
-}
-
-namespace {
-void PrintCallStack(std::ostream& out, cmListFileBacktrace bt,
-                    cm::optional<std::string> const& topSource)
-{
-  // The call stack exists only if we have at least two calls on top
-  // of the bottom.
-  if (bt.Empty()) {
-    return;
-  }
-  bt = bt.Pop();
-  if (bt.Empty()) {
-    return;
-  }
-
-  bool first = true;
-  for (; !bt.Empty(); bt = bt.Pop()) {
-    cmListFileContext lfc = bt.Top();
-    if (lfc.Name.empty() &&
-        lfc.Line != cmListFileContext::DeferPlaceholderLine) {
-      // Skip this whole-file scope.  When we get here we already will
-      // have printed a more-specific context within the file.
-      continue;
-    }
-    if (first) {
-      first = false;
-      out << "Call Stack (most recent call first):\n";
-    }
-    if (topSource) {
-      lfc.FilePath = cmSystemTools::RelativeIfUnder(*topSource, lfc.FilePath);
-    }
-    out << "  " << lfc << "\n";
-  }
-}
-}
-
 void cmMessenger::IssueMessage(MessageType t, const std::string& text,
                                const cmListFileBacktrace& backtrace) const
 {
@@ -199,9 +200,9 @@
                                  const cmListFileBacktrace& backtrace) const
 {
   std::ostringstream msg;
-  if (!printMessagePreamble(t, msg)) {
-    return;
-  }
+
+  // Print the message preamble.
+  msg << "CMake " << getMessageTypeStr(t);
 
   // Add the immediate context.
   this->PrintBacktraceTitle(msg, backtrace);
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index c76a88a..2c3763f 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -531,7 +531,9 @@
   SELECT(POLICY, CMP0172,                                                     \
          "The CPack module enables per-machine installation by default in "   \
          "the CPack WIX Generator.",                                          \
-         3, 31, 0, cmPolicies::WARN)
+         3, 31, 0, cmPolicies::WARN)                                          \
+  SELECT(POLICY, CMP0173, "The CMakeFindFrameworks module is removed.", 3,    \
+         31, 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/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 408a22c..c07f361 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -345,6 +345,8 @@
     void MaybeWriteResponseFile(std::string const& outputFile,
                                 std::vector<std::string>& cmd) const;
 
+    static void MaybePrependCmdExe(std::vector<std::string>& cmd);
+
     /** @brief Run an external process. Use only during Process() call!  */
     bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
                     std::vector<std::string> const& command,
@@ -848,6 +850,54 @@
 #endif
 }
 
+/*
+ *  According to the CreateProcessW documentation which is the underlying
+ *  function for all RunProcess calls:
+ *
+ *  "To run a batch file, you must start the command interpreter; set"
+ *  "lpApplicationName to cmd.exe and set lpCommandLine to the following"
+ *  "arguments: /c plus the name of the batch file."
+ *
+ *  we should to take care of the correctness of the command line when
+ *  attempting to execute the batch files.
+ *
+ *  Also cmd.exe is unable to parse batch file names correctly if they
+ *  contain spaces. This function uses cmSystemTools::GetShortPath conversion
+ *  to suppress this behavior.
+ *
+ *  The function is noop on platforms different from the pure WIN32 one.
+ */
+void cmQtAutoMocUicT::JobT::MaybePrependCmdExe(
+  std::vector<std::string>& cmdLine)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  if (!cmdLine.empty()) {
+    const auto& applicationName = cmdLine.at(0);
+    if (cmSystemTools::StringEndsWith(applicationName, ".bat") ||
+        cmSystemTools::StringEndsWith(applicationName, ".cmd")) {
+      std::vector<std::string> output;
+      output.reserve(cmdLine.size() + 2);
+      output.emplace_back(cmSystemTools::GetComspec());
+      output.emplace_back("/c");
+      std::string tmpShortPath;
+      if (applicationName.find(' ') != std::string::npos &&
+          cmSystemTools::GetShortPath(applicationName, tmpShortPath)) {
+        // If the batch file name contains spaces convert it to the windows
+        // short path. Otherwise it might cause issue when running cmd.exe.
+        output.emplace_back(tmpShortPath);
+      } else {
+        output.push_back(applicationName);
+      }
+      std::move(cmdLine.begin() + 1, cmdLine.end(),
+                std::back_inserter(output));
+      cmdLine = std::move(output);
+    }
+  }
+#else
+  static_cast<void>(cmdLine);
+#endif
+}
+
 bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
                                        cmWorkerPool::ProcessResultT& result,
                                        std::vector<std::string> const& command,
@@ -891,6 +941,9 @@
       cm::append(cmd, this->MocConst().OptionsIncludes);
       // Check if response file is necessary
       MaybeWriteResponseFile(this->MocConst().PredefsFileAbs, cmd);
+
+      MaybePrependCmdExe(cmd);
+
       // Execute command
       if (!this->RunProcess(GenT::MOC, result, cmd, reason.get())) {
         this->LogCommandError(GenT::MOC,
@@ -2090,6 +2143,7 @@
     cmd.push_back(sourceFile);
 
     MaybeWriteResponseFile(outputFile, cmd);
+    MaybePrependCmdExe(cmd);
   }
 
   // Execute moc command
@@ -2156,6 +2210,8 @@
   cmd.emplace_back(outputFile);
   cmd.emplace_back(sourceFile);
 
+  MaybePrependCmdExe(cmd);
+
   cmWorkerPool::ProcessResultT result;
   if (this->RunProcess(GenT::UIC, result, cmd, this->Reason.get())) {
     // Uic command success
diff --git a/Source/cmString.hxx b/Source/cmString.hxx
index 1994c2c..5e1b524 100644
--- a/Source/cmString.hxx
+++ b/Source/cmString.hxx
@@ -518,7 +518,7 @@
     *this = std::move(s);
   }
 
-  void swap(String& other)
+  void swap(String& other) noexcept
   {
     std::swap(this->string_, other.string_);
     std::swap(this->view_, other.view_);
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 8e59a35..0a6b683 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -970,6 +970,17 @@
   result.dwBuildNumber = osviex.dwBuildNumber;
   return result;
 }
+
+std::string cmSystemTools::GetComspec()
+{
+  std::string comspec;
+  if (!cmSystemTools::GetEnv("COMSPEC", comspec) ||
+      !cmSystemTools::FileIsFullPath(comspec)) {
+    comspec = "cmd.exe";
+  }
+  return comspec;
+}
+
 #endif
 
 std::string cmSystemTools::GetRealPathResolvingWindowsSubst(
@@ -2140,15 +2151,14 @@
 
     if (verbose) {
       if (extract) {
-        cmSystemTools::Stdout("x ");
-        cmSystemTools::Stdout(cm_archive_entry_pathname(entry));
+        cmSystemTools::Stdout(
+          cmStrCat("x ", cm_archive_entry_pathname(entry)));
       } else {
         list_item_verbose(stdout, entry);
       }
       cmSystemTools::Stdout("\n");
     } else if (!extract) {
-      cmSystemTools::Stdout(cm_archive_entry_pathname(entry));
-      cmSystemTools::Stdout("\n");
+      cmSystemTools::Stdout(cmStrCat(cm_archive_entry_pathname(entry), '\n'));
     }
     if (extract) {
       if (extractTimestamps == cmSystemTools::cmTarExtractTimestamps::Yes) {
@@ -3026,10 +3036,10 @@
         std::ostringstream e;
         /* clang-format off */
         e << "The current " << se_name << " is:\n"
-          << "  " << inRPath << "\n"
-          << "which does not contain:\n"
-          << "  " << oldRPath << "\n"
-          << "as was expected.";
+             "  " << inRPath << "\n"
+             "which does not contain:\n"
+             "  " << oldRPath << "\n"
+             "as was expected.";
         /* clang-format on */
         *emsg2 = e.str();
       }
@@ -3113,10 +3123,10 @@
         std::ostringstream e;
         /* clang-format off */
         e << "The current RPATH is:\n"
-          << "  " << libPath << "\n"
-          << "which does not contain:\n"
-          << "  " << oldRPath << "\n"
-          << "as was expected.";
+             "  " << libPath << "\n"
+             "which does not contain:\n"
+             "  " << oldRPath << "\n"
+             "as was expected.";
         /* clang-format on */
         *emsg = e.str();
       }
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index a07c749..d0b6046 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -585,6 +585,9 @@
     unsigned int dwBuildNumber;
   };
   static WindowsVersion GetWindowsVersion();
+
+  /** Attempt to get full path to COMSPEC, default "cmd.exe" */
+  static std::string GetComspec();
 #endif
 
   /** Get the real path for a given path, removing all symlinks.
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 408e5d2..804f5ef 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -75,13 +75,17 @@
   { "--preset <preset>,--preset=<preset>", "Specify a configure preset." },
   { "--list-presets[=<type>]", "List available presets." },
   { "--workflow [<options>]", "Run a workflow preset." },
-  { "-E", "CMake command mode." },
+  { "-E", "CMake command mode. Run \"cmake -E\" for a summary of commands." },
   { "-L[A][H]", "List non-advanced cached variables." },
   { "-LR[A][H] <regex>", "Show cached variables that match the regex." },
   { "--fresh",
     "Configure a fresh build tree, removing any existing cache file." },
-  { "--build <dir>", "Build a CMake-generated project binary tree." },
-  { "--install <dir>", "Install a CMake-generated project binary tree." },
+  { "--build <dir>",
+    "Build a CMake-generated project binary tree. Run \"cmake --build\" to "
+    "see compatible options and a quick help." },
+  { "--install <dir>",
+    "Install a CMake-generated project binary tree. Run \"cmake --install\" "
+    "to see compatible options and a quick help." },
   { "--open <dir>", "Open generated project in the associated application." },
   { "-N", "View mode only." },
   { "-P <file>", "Process script mode." },
@@ -175,11 +179,11 @@
   // cannot use it to print messages.  Another implementation will
   // be needed to print colored messages on Windows.
   static_cast<void>(md);
-  std::cerr << m << cmakemainGetStack(cm) << '\n' << std::flush;
+  std::cerr << m << cmakemainGetStack(cm) << std::endl;
 #else
   cmsysTerminal_cfprintf(md.desiredColor, stderr, "%s", m.c_str());
   fflush(stderr); // stderr is buffered in some cases.
-  std::cerr << cmakemainGetStack(cm) << '\n' << std::flush;
+  std::cerr << cmakemainGetStack(cm) << std::endl;
 #endif
 }
 
@@ -810,7 +814,7 @@
   std::ostringstream oss;
   for (auto i = 0u; i < parsedPermissions.size(); i++) {
     if (i != 0) {
-      oss << ";";
+      oss << ';';
     }
     oss << parsedPermissions[i];
   }
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 25b2ced..eaff8ef 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -60,7 +60,6 @@
 #include <cstring>
 #include <iostream>
 #include <memory>
-#include <sstream>
 #include <utility>
 
 #ifdef _WIN32
@@ -81,101 +80,89 @@
                              std::vector<std::string>::const_iterator argEnd);
 
 namespace {
+// ATTENTION If you add new commands, change here,
+// and in `cmakemain.cxx` in the options table
+const char* const HELP_AVAILABLE_COMMANDS = R"(Available commands:
+  capabilities              - Report capabilities built into cmake in JSON format
+  cat [--] <files>...       - concat the files and print them to the standard output
+  chdir dir cmd [args...]   - run command in a given directory
+  compare_files [--ignore-eol] file1 file2
+                              - check if file1 is same as file2
+  copy <file>... destination  - copy files to destination (either file or directory)
+  copy_directory <dir>... destination   - copy content of <dir>... directories to 'destination' directory
+  copy_directory_if_different <dir>... destination   - copy changed content of <dir>... directories to 'destination' directory
+  copy_if_different <file>... destination  - copy files if it has changed
+  echo [<string>...]        - displays arguments as text
+  echo_append [<string>...] - displays arguments as text but no new line
+  env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]
+                            - run command in a modified environment
+  environment               - display the current environment
+  make_directory <dir>...   - create parent and <dir> directories
+  md5sum <file>...          - create MD5 checksum of files
+  sha1sum <file>...         - create SHA1 checksum of files
+  sha224sum <file>...       - create SHA224 checksum of files
+  sha256sum <file>...       - create SHA256 checksum of files
+  sha384sum <file>...       - create SHA384 checksum of files
+  sha512sum <file>...       - create SHA512 checksum of files
+  remove [-f] <file>...     - remove the file(s), use -f to force it (deprecated: use rm instead)
+  remove_directory <dir>... - remove directories and their contents (deprecated: use rm instead)
+  rename oldname newname    - rename a file or directory (on one volume)
+  rm [-rRf] [--] <file/dir>... - remove files or directories, use -f to force it, r or R to remove directories and their contents recursively
+  sleep <number>...         - sleep for given number of seconds
+  tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]
+                            - create or extract a tar or zip archive
+  time command [args...]    - run command and display elapsed time
+  touch <file>...           - touch a <file>.
+  touch_nocreate <file>...  - touch a <file> but do not create it.
+  create_symlink old new    - create a symbolic link new -> old
+  create_hardlink old new   - create a hard link new -> old
+  true                      - do nothing with an exit code of 0
+  false                     - do nothing with an exit code of 1
+)";
+#if defined(_WIN32) && !defined(__CYGWIN__)
+const char* const HELP_AVAILABLE_WINDOWS_COMMANDS =
+  R"(Available on Windows only:
+  delete_regv key           - delete registry value
+  env_vs8_wince sdkname     - displays a batch file which sets the environment for the provided Windows CE SDK installed in VS2005
+  env_vs9_wince sdkname     - displays a batch file which sets the environment for the provided Windows CE SDK installed in VS2008
+  write_regv key value      - write registry value
+)";
+#endif
+
 void CMakeCommandUsage(std::string const& program)
 {
-  std::ostringstream errorStream;
-
+  /* clang-format off */
+  std::string help_screen = cmStrCat(
 #ifndef CMAKE_BOOTSTRAP
-  /* clang-format off */
-  errorStream
-    << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
-/* clang-format on */
+    "cmake version "
+  , cmVersion::GetCMakeVersion()
+  , "\n"
 #else
-  /* clang-format off */
-  errorStream
-    << "cmake bootstrap\n";
-/* clang-format on */
+    "cmake bootstrap\n"
 #endif
-  // If you add new commands, change here,
-  // and in cmakemain.cxx in the options table
-  /* clang-format off */
-  errorStream
-    << "Usage: " << program << " -E <command> [arguments...]\n"
-    << "Available commands: \n"
-    << "  capabilities              - Report capabilities built into cmake "
-       "in JSON format\n"
-    << "  cat [--] <files>...       - concat the files and print them to the "
-       "standard output\n"
-    << "  chdir dir cmd [args...]   - run command in a given directory\n"
-    << "  compare_files [--ignore-eol] file1 file2\n"
-    << "                              - check if file1 is same as file2\n"
-    << "  copy <file>... destination  - copy files to destination "
-       "(either file or directory)\n"
-    << "  copy_directory <dir>... destination   - copy content of <dir>... "
-       "directories to 'destination' directory\n"
-    << "  copy_directory_if_different <dir>... destination   - copy changed content of <dir>... "
-       "directories to 'destination' directory\n"
-    << "  copy_if_different <file>... destination  - copy files if it has "
-       "changed\n"
-    << "  echo [<string>...]        - displays arguments as text\n"
-    << "  echo_append [<string>...] - displays arguments as text but no new "
-       "line\n"
-    << "  env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]\n"
-    << "                            - run command in a modified environment\n"
-    << "  environment               - display the current environment\n"
-    << "  make_directory <dir>...   - create parent and <dir> directories\n"
-    << "  md5sum <file>...          - create MD5 checksum of files\n"
-    << "  sha1sum <file>...         - create SHA1 checksum of files\n"
-    << "  sha224sum <file>...       - create SHA224 checksum of files\n"
-    << "  sha256sum <file>...       - create SHA256 checksum of files\n"
-    << "  sha384sum <file>...       - create SHA384 checksum of files\n"
-    << "  sha512sum <file>...       - create SHA512 checksum of files\n"
-    << "  remove [-f] <file>...     - remove the file(s), use -f to force "
-       "it (deprecated: use rm instead)\n"
-    << "  remove_directory <dir>... - remove directories and their contents (deprecated: use rm instead)\n"
-    << "  rename oldname newname    - rename a file or directory "
-       "(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"
-    << "  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"
-    << "  time command [args...]    - run command and display elapsed time\n"
-    << "  touch <file>...           - touch a <file>.\n"
-    << "  touch_nocreate <file>...  - touch a <file> but do not create it.\n"
-    << "  create_symlink old new    - create a symbolic link new -> old\n"
-    << "  create_hardlink old new   - create a hard link new -> old\n"
-    << "  true                      - do nothing with an exit code of 0\n"
-    << "  false                     - do nothing with an exit code of 1\n"
+    "Usage: "
+  , program
+  , " -E <command> [arguments...]\n"
+  , HELP_AVAILABLE_COMMANDS
 #if defined(_WIN32) && !defined(__CYGWIN__)
-    << "Available on Windows only:\n"
-    << "  delete_regv key           - delete registry value\n"
-    << "  env_vs8_wince sdkname     - displays a batch file which sets the "
-       "environment for the provided Windows CE SDK installed in VS2005\n"
-    << "  env_vs9_wince sdkname     - displays a batch file which sets the "
-       "environment for the provided Windows CE SDK installed in VS2008\n"
-    << "  write_regv key value      - write registry value\n"
+  , HELP_AVAILABLE_WINDOWS_COMMANDS
 #endif
-    ;
+  );
   /* clang-format on */
-
-  cmSystemTools::Error(errorStream.str());
+  cmSystemTools::Error(help_screen);
 }
 
 bool cmTarFilesFrom(std::string const& file, std::vector<std::string>& files)
 {
   if (cmSystemTools::FileIsDirectory(file)) {
-    std::ostringstream e;
-    e << "-E tar --files-from= file '" << file << "' is a directory";
-    cmSystemTools::Error(e.str());
+    cmSystemTools::Error(
+      cmStrCat("-E tar --files-from= file '", file, "' is a directory"));
     return false;
   }
   cmsys::ifstream fin(file.c_str());
   if (!fin) {
-    std::ostringstream e;
-    e << "-E tar --files-from= file '" << file << "' not found";
-    cmSystemTools::Error(e.str());
+    cmSystemTools::Error(
+      cmStrCat("-E tar --files-from= file '", file, "' not found"));
     return false;
   }
   std::string line;
@@ -186,10 +173,8 @@
     if (cmHasLiteralPrefix(line, "--add-file=")) {
       files.push_back(line.substr(11));
     } else if (cmHasLiteralPrefix(line, "-")) {
-      std::ostringstream e;
-      e << "-E tar --files-from='" << file << "' file invalid line:\n"
-        << line << "\n";
-      cmSystemTools::Error(e.str());
+      cmSystemTools::Error(cmStrCat("-E tar --files-from='", file,
+                                    "' file invalid line:\n", line, '\n'));
       return false;
     } else {
       files.push_back(line);
@@ -252,7 +237,7 @@
       cmSystemTools::ConvertToLongPath(path);
       this->DepFile << cmCMakePath(path).GenericString() << std::endl;
     } else {
-      this->Output << this->Line << std::endl << std::flush;
+      this->Output << this->Line << std::endl;
     }
 
     return true;
@@ -347,14 +332,14 @@
   int ret;
   if (!cmSystemTools::RunSingleCommand(iwyu_cmd, nullptr, &stdErr, &ret,
                                        nullptr, cmSystemTools::OUTPUT_NONE)) {
-    std::cerr << "Error running '" << iwyu_cmd[0] << "': " << stdErr << "\n";
+    std::cerr << "Error running '" << iwyu_cmd[0] << "': " << stdErr << '\n';
     return 1;
   }
   // Warn if iwyu reported anything.
   if (stdErr.find("should remove these lines:") != std::string::npos ||
       stdErr.find("should add these lines:") != std::string::npos) {
     std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
-              << stdErr << "\n";
+              << stdErr << '\n';
   }
   // Older versions of iwyu always returned a non-zero exit code,
   // so ignore it unless the user has enabled errors.
@@ -403,7 +388,7 @@
   std::string stdErr;
   if (!cmSystemTools::RunSingleCommand(tidy_cmd, &stdOut, &stdErr, &ret,
                                        nullptr, cmSystemTools::OUTPUT_NONE)) {
-    std::cerr << "Error running '" << tidy_cmd[0] << "': " << stdErr << "\n";
+    std::cerr << "Error running '" << tidy_cmd[0] << "': " << stdErr << '\n';
     return 1;
   }
   // Output the stdout from clang-tidy to stderr
@@ -432,7 +417,7 @@
   int ret;
   if (!cmSystemTools::RunSingleCommand(lwyu_cmd, &stdOut, &stdErr, &ret,
                                        nullptr, cmSystemTools::OUTPUT_NONE)) {
-    std::cerr << "Error running '" << lwyu_cmd[0] << "': " << stdErr << "\n";
+    std::cerr << "Error running '" << lwyu_cmd[0] << "': " << stdErr << '\n';
     return 1;
   }
 
@@ -457,13 +442,13 @@
   if (!cmSystemTools::RunSingleCommand(cpplint_cmd, &stdOut, &stdOut, &ret,
                                        nullptr, cmSystemTools::OUTPUT_NONE)) {
     std::cerr << "Error running '" << cpplint_cmd[0] << "': " << stdOut
-              << "\n";
+              << '\n';
     return 1;
   }
   if (!stdOut.empty()) {
-    std::cerr << "Warning: cpplint diagnostics:\n";
-    // Output the output from cpplint to stderr
-    std::cerr << stdOut;
+    std::cerr << "Warning: cpplint diagnostics:\n"
+              // Output the output from cpplint to stderr
+              << stdOut;
   }
 
   // always return 0 so the build can continue as cpplint returns non-zero
@@ -503,7 +488,7 @@
   if (!cmSystemTools::RunSingleCommand(cppcheck_cmd, &stdOut, &stdErr, &ret,
                                        nullptr, cmSystemTools::OUTPUT_NONE)) {
     std::cerr << "Error running '" << cppcheck_cmd[0] << "': " << stdOut
-              << "\n";
+              << '\n';
     return 1;
   }
   std::cerr << stdOut;
@@ -593,7 +578,7 @@
         } else {
           // if it was not a co-compiler or --source/--launcher then error
           std::cerr << "__run_co_compile given unknown argument: " << arg
-                    << "\n";
+                    << '\n';
           return 1;
         }
       }
@@ -605,7 +590,7 @@
     std::cerr << "__run_co_compile missing command to run. "
                  "Looking for one or more of the following:\n";
     for (CoCompiler const& cc : CoCompilers) {
-      std::cerr << cc.Option << "\n";
+      std::cerr << cc.Option << '\n';
     }
     return 1;
   }
@@ -792,7 +777,7 @@
       }
       cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary);
       if (!fin) {
-        std::cerr << "could not open object list file: " << args[3] << "\n";
+        std::cerr << "could not open object list file: " << args[3] << '\n';
         return 1;
       }
       std::vector<std::string> files;
@@ -815,7 +800,7 @@
       }
       FILE* fout = cmsys::SystemTools::Fopen(args[2], "w+");
       if (!fout) {
-        std::cerr << "could not open output .def file: " << args[2] << "\n";
+        std::cerr << "could not open output .def file: " << args[2] << '\n';
         return 1;
       }
       bindexplib deffile;
@@ -824,7 +809,7 @@
         if (cmHasLiteralPrefix(a, "--nm=")) {
           deffile.SetNmPath(a.substr(5));
         } else {
-          std::cerr << "unknown argument: " << a << "\n";
+          std::cerr << "unknown argument: " << a << '\n';
         }
       }
       for (std::string const& file : files) {
@@ -1052,8 +1037,7 @@
     if (args[1] == "touch" && args.size() > 2) {
       for (auto const& arg : cmMakeRange(args).advance(2)) {
         if (!cmSystemTools::Touch(arg, true)) {
-          std::cerr << "cmake -E touch: failed to update \"";
-          std::cerr << arg << "\".\n";
+          std::cerr << "cmake -E touch: failed to update \"" << arg << "\".\n";
           return 1;
         }
       }
@@ -1064,8 +1048,8 @@
     if (args[1] == "touch_nocreate" && args.size() > 2) {
       for (auto const& arg : cmMakeRange(args).advance(2)) {
         if (!cmSystemTools::Touch(arg, false)) {
-          std::cerr << "cmake -E touch_nocreate: failed to update \"";
-          std::cerr << arg << "\".\n";
+          std::cerr << "cmake -E touch_nocreate: failed to update \"" << arg
+                    << "\".\n";
           return 1;
         }
       }
@@ -1115,7 +1099,7 @@
       auto time_finish = std::chrono::steady_clock::now();
 
       std::chrono::duration<double> time_elapsed = time_finish - time_start;
-      std::cout << "Elapsed time (seconds): " << time_elapsed.count() << "\n";
+      std::cout << "Elapsed time (seconds): " << time_elapsed.count() << '\n';
       return ret;
     }
 
@@ -1252,7 +1236,7 @@
         std::string emsg = cmSystemTools::GetLastSystemError();
         std::cerr << "failed to create symbolic link '" << destinationFileName
                   << "' because existing path cannot be removed: " << emsg
-                  << "\n";
+                  << '\n';
         return 1;
       }
       if (!cmSystemTools::CreateSymlink(args[2], destinationFileName)) {
@@ -1269,7 +1253,7 @@
 
       if (!cmSystemTools::FileExists(sourceFileName)) {
         std::cerr << "failed to create hard link because source path '"
-                  << sourceFileName << "' does not exist \n";
+                  << sourceFileName << "' does not exist\n";
         return 1;
       }
 
@@ -1278,7 +1262,7 @@
         std::string emsg = cmSystemTools::GetLastSystemError();
         std::cerr << "failed to create hard link '" << destinationFileName
                   << "' because existing path cannot be removed: " << emsg
-                  << "\n";
+                  << '\n';
         return 1;
       }
 
@@ -1416,7 +1400,7 @@
       if (args.size() == 3) {
         std::cerr << "  Variable " << args[2] << " is not set.";
       }
-      std::cerr << std::endl;
+      std::cerr << '\n';
       return 1;
     }
 
@@ -1535,7 +1519,7 @@
             action = cmSystemTools::TarActionExtract;
           } break;
           default: {
-            std::cerr << "tar: Unknown argument: " << flag << "\n";
+            std::cerr << "tar: Unknown argument: " << flag << '\n';
           }
         }
       }
@@ -1692,17 +1676,17 @@
   for (auto const& filename : cmMakeRange(args).advance(2)) {
     // Cannot compute sum of a directory
     if (cmSystemTools::FileIsDirectory(filename)) {
-      std::cerr << "Error: " << filename << " is a directory" << std::endl;
+      std::cerr << "Error: " << filename << " is a directory\n";
       retval++;
     } else {
       cmCryptoHash hasher(algo);
       std::string value = hasher.HashFile(filename);
       if (value.empty()) {
         // To mimic "md5sum/shasum" behavior in a shell:
-        std::cerr << filename << ": No such file or directory" << std::endl;
+        std::cerr << filename << ": No such file or directory\n";
         retval++;
       } else {
-        std::cout << value << "  " << filename << std::endl;
+        std::cout << value << "  " << filename << '\n';
       }
     }
   }
@@ -1897,8 +1881,7 @@
   // Read command lines from the script.
   cmsys::ifstream fin(args[2].c_str());
   if (!fin) {
-    std::cerr << "Error opening link script \"" << args[2] << "\""
-              << std::endl;
+    std::cerr << "Error opening link script \"" << args[2] << "\"\n";
     return 1;
   }
 
@@ -1929,7 +1912,7 @@
 
     // Report the command if verbose output is enabled.
     if (verbose) {
-      std::cout << command << std::endl;
+      std::cout << command << '\n';
     }
 
     // Run the command and wait for it to exit.
@@ -1971,7 +1954,7 @@
                  "echo Environment Selection: " << name << "\n"
                  "set PATH=" << parser.GetPathDirectories() << "\n"
                  "set INCLUDE=" << parser.GetIncludeDirectories() << "\n"
-                 "set LIB=" << parser.GetLibraryDirectories() << std::endl;
+                 "set LIB=" << parser.GetLibraryDirectories() << '\n';
     /* clang-format on */
     return 0;
   }
@@ -2245,7 +2228,7 @@
 {
   if (verbose) {
     std::cout << comment << ":\n";
-    std::cout << cmJoin(command, " ") << "\n";
+    std::cout << cmJoin(command, " ") << '\n';
   }
   std::string output;
   int retCode = 0;
@@ -2415,7 +2398,7 @@
   std::string absManifestFile =
     cmSystemTools::CollapseFullPath(this->ManifestFile);
   if (this->Verbose) {
-    std::cout << "Create " << this->ManifestFileRC << "\n";
+    std::cout << "Create " << this->ManifestFileRC << '\n';
   }
   {
     cmsys::ofstream fout(this->ManifestFileRC.c_str());
@@ -2423,8 +2406,8 @@
       return -1;
     }
     // Insert a pragma statement to specify utf-8 encoding.
-    fout << "#pragma code_page(65001)\n";
-    fout << this->Type
+    fout << "#pragma code_page(65001)\n"
+         << this->Type
          << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
             "24 /* RT_MANIFEST */ \""
          << absManifestFile << "\"";
@@ -2434,7 +2417,7 @@
   // generate a manifest file so the resource compiler succeeds.
   if (!cmSystemTools::FileExists(this->ManifestFile)) {
     if (this->Verbose) {
-      std::cout << "Create empty: " << this->ManifestFile << "\n";
+      std::cout << "Create empty: " << this->ManifestFile << '\n';
     }
     if (this->UserManifests.empty()) {
       // generate an empty manifest because there are no user provided
diff --git a/Templates/CTestScript.cmake.in b/Templates/CTestScript.cmake.in
deleted file mode 100644
index 5fb3529..0000000
--- a/Templates/CTestScript.cmake.in
+++ /dev/null
@@ -1,33 +0,0 @@
-cmake_minimum_required(VERSION 2.4)
-
-# This is a template for the CTest script for this system
-
-set(CTEST_SITE                          "@SITE@")
-set(CTEST_BUILD_NAME                    "@BUILDNAME@")
-
-# ---
-set(CTEST_SOURCE_DIRECTORY              "@CMAKE_SOURCE_DIR@")
-set(CTEST_BINARY_DIRECTORY              "@CMAKE_BINARY_DIR@")
-set(CTEST_UPDATE_COMMAND                "@UPDATE_COMMAND@")
-set(CTEST_UPDATE_OPTIONS                "@UPDATE_OPTIONS@")
-set(CTEST_CMAKE_GENERATOR               "@CMAKE_GENERATOR@")
-set(CTEST_BUILD_CONFIGURATION           "Release")
-#set(CTEST_MEMORYCHECK_COMMAND           "@MEMORYCHECK_COMMAND@")
-#set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "@MEMORYCHECK_SUPPRESSIONS_FILE@")
-#set(CTEST_MEMORYCHECK_COMMAND_OPTIONS   "@MEMORYCHECK_COMMAND_OPTIONS@")
-#set(CTEST_COVERAGE_COMMAND              "@COVERAGE_COMMAND@")
-set(CTEST_NOTES_FILES                   "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}")
-
-#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY})
-
-set(CTEST_DROP_METHOD "@DROP_METHOD@")
-
-CTEST_START(Experimental TRACK Weekly)
-CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}")
-CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}")
-CTEST_READ_CUSTOM_FILES("${CTEST_BINARY_DIRECTORY}")
-CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}")
-CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}")
-#CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}")
-#CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}")
-CTEST_SUBMIT()
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index 4d43e08..008a7d9 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Render the header file with source path macro
+configure_file(testConfig.h.in testConfig.h @ONLY)
+
 include_directories(
   ${CMAKE_CURRENT_BINARY_DIR}
   ${CMake_BINARY_DIR}/Source
@@ -65,10 +68,8 @@
   list(APPEND CMakeLib_TESTS
     testVisualStudioSlnParser.cxx
     )
-  configure_file(testVisualStudioSlnParser.h.in testVisualStudioSlnParser.h @ONLY)
 endif()
 
-configure_file(testXMLParser.h.in testXMLParser.h @ONLY)
 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testUVProcessChainInput.txt" "HELLO WORLD!")
 
 create_test_sourcelist(CMakeLib_TEST_SRCS CMakeLibTests.cxx ${CMakeLib_TESTS})
diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx
index 88b62e5..880f3ee 100644
--- a/Tests/CMakeLib/testArgumentParser.cxx
+++ b/Tests/CMakeLib/testArgumentParser.cxx
@@ -16,6 +16,8 @@
 #include "cmArgumentParser.h"
 #include "cmArgumentParserTypes.h"
 
+#include "testCommon.h"
+
 namespace {
 
 struct Result : public ArgumentParser::ParseResult
@@ -182,14 +184,6 @@
   static std::vector<std::string> const unparsed = { "pos2", "bar", "ign1",
                                                      "ign2", "ign4" };
 
-#define ASSERT_TRUE(x)                                                        \
-  do {                                                                        \
-    if (!(x)) {                                                               \
-      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
-      return false;                                                           \
-    }                                                                         \
-  } while (false)
-
   ASSERT_TRUE(!result);
 
   ASSERT_TRUE(result.Option1);
diff --git a/Tests/CMakeLib/testCMFilesystemPath.cxx b/Tests/CMakeLib/testCMFilesystemPath.cxx
index 52cb43a..1da5925 100644
--- a/Tests/CMakeLib/testCMFilesystemPath.cxx
+++ b/Tests/CMakeLib/testCMFilesystemPath.cxx
@@ -9,6 +9,8 @@
 
 #include <cm/filesystem>
 
+#include "testCommon.h"
+
 namespace {
 
 namespace fs = cm::filesystem;
@@ -971,38 +973,9 @@
 
 int testCMFilesystemPath(int /*unused*/, char* /*unused*/[])
 {
-  int result = 0;
-
-  if (!testConstructors()) {
-    result = 1;
-  }
-  if (!testConcatenation()) {
-    result = 1;
-  }
-  if (!testModifiers()) {
-    result = 1;
-  }
-  if (!testObservers()) {
-    result = 1;
-  }
-  if (!testCompare()) {
-    result = 1;
-  }
-  if (!testGeneration()) {
-    result = 1;
-  }
-  if (!testDecomposition()) {
-    result = 1;
-  }
-  if (!testQueries()) {
-    result = 1;
-  }
-  if (!testIterators()) {
-    result = 1;
-  }
-  if (!testNonMemberFunctions()) {
-    result = 1;
-  }
-
-  return result;
+  return runTests({ testConstructors, testConcatenation, testModifiers,
+                    testObservers, testCompare, testGeneration,
+                    testDecomposition, testQueries, testIterators,
+                    testNonMemberFunctions },
+                  false);
 }
diff --git a/Tests/CMakeLib/testCMakePath.cxx b/Tests/CMakeLib/testCMakePath.cxx
index aa17e50..9b11286 100644
--- a/Tests/CMakeLib/testCMakePath.cxx
+++ b/Tests/CMakeLib/testCMakePath.cxx
@@ -12,6 +12,8 @@
 
 #include "cmCMakePath.h"
 
+#include "testCommon.h"
+
 namespace {
 
 void checkResult(bool success)
@@ -422,20 +424,6 @@
 
 int testCMakePath(int /*unused*/, char* /*unused*/[])
 {
-  int result = 0;
-
-  if (!testConstructors()) {
-    result = 1;
-  }
-  if (!testAssign()) {
-    result = 1;
-  }
-  if (!testConcat()) {
-    result = 1;
-  }
-  if (!testAppend()) {
-    result = 1;
-  }
-
-  return result;
+  return runTests({ testConstructors, testAssign, testConcat, testAppend },
+                  false);
 }
diff --git a/Tests/CMakeLib/testCommon.h b/Tests/CMakeLib/testCommon.h
index bd2d54e..c1d2b3c 100644
--- a/Tests/CMakeLib/testCommon.h
+++ b/Tests/CMakeLib/testCommon.h
@@ -3,28 +3,38 @@
 #pragma once
 
 #include <functional>
+#include <initializer_list>
 #include <iostream>
-#include <vector>
 
 #define ASSERT_TRUE(x)                                                        \
   do {                                                                        \
     if (!(x)) {                                                               \
-      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
+      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << '\n'; \
       return false;                                                           \
     }                                                                         \
   } while (false)
 
-inline int runTests(std::vector<std::function<bool()>> const& tests)
+#define BOOL_STRING(b) ((b) ? "TRUE" : "FALSE")
+
+namespace {
+
+inline int runTests(std::initializer_list<std::function<bool()>> const& tests,
+                    const bool fail_fast = true)
 {
+  int result = 0;
   for (auto const& test : tests) {
     if (!test()) {
-      return 1;
+      result = 1;
+      if (fail_fast) {
+        break;
+      }
     }
-    std::cout << ".";
+    std::cout << '.';
   }
-
-  std::cout << " Passed" << std::endl;
-  return 0;
+  if (!result) {
+    std::cout << " Passed\n";
+  }
+  return result;
 }
 
-#define BOOL_STRING(b) ((b) ? "TRUE" : "FALSE")
+}
diff --git a/Tests/CMakeLib/testConfig.h.in b/Tests/CMakeLib/testConfig.h.in
new file mode 100644
index 0000000..f57f97e
--- /dev/null
+++ b/Tests/CMakeLib/testConfig.h.in
@@ -0,0 +1,7 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#pragma once
+
+#define SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@"
+#define BUILD_DIR "@CMAKE_CURRENT_BINARY_DIR@"
diff --git a/Tests/CMakeLib/testDebuggerAdapter.cxx b/Tests/CMakeLib/testDebuggerAdapter.cxx
index e66d990..d585250 100644
--- a/Tests/CMakeLib/testDebuggerAdapter.cxx
+++ b/Tests/CMakeLib/testDebuggerAdapter.cxx
@@ -7,7 +7,6 @@
 #include <future>
 #include <memory>
 #include <string>
-#include <vector>
 
 #include <cm3p/cppdap/future.h>
 #include <cm3p/cppdap/io.h>
@@ -194,8 +193,6 @@
 
 int testDebuggerAdapter(int, char*[])
 {
-  return runTests(std::vector<std::function<bool()>>{
-    testBasicProtocol,
-    testThreadsRequestAfterThreadExitedEvent,
-  });
+  return runTests(
+    { testBasicProtocol, testThreadsRequestAfterThreadExitedEvent });
 }
diff --git a/Tests/CMakeLib/testDebuggerAdapterPipe.cxx b/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
index c0f2e9b..5b41be9 100644
--- a/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
+++ b/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
@@ -3,13 +3,11 @@
 
 #include <chrono>
 #include <cstdio>
-#include <functional>
 #include <future>
 #include <iostream>
 #include <memory>
 #include <stdexcept>
 #include <string>
-#include <vector>
 
 #include <cm3p/cppdap/future.h>
 #include <cm3p/cppdap/io.h>
@@ -180,7 +178,5 @@
 
 int testDebuggerAdapterPipe(int, char*[])
 {
-  return runTests(std::vector<std::function<bool()>>{
-    testProtocolWithPipes,
-  });
+  return runTests({ testProtocolWithPipes });
 }
diff --git a/Tests/CMakeLib/testDebuggerBreakpointManager.cxx b/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
index f654442..3973826 100644
--- a/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
+++ b/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
@@ -3,7 +3,6 @@
 
 #include <atomic>
 #include <chrono>
-#include <functional>
 #include <future>
 #include <memory>
 #include <string>
@@ -177,9 +176,7 @@
 
 int testDebuggerBreakpointManager(int, char*[])
 {
-  return runTests(std::vector<std::function<bool()>>{
-    testHandleBreakpointRequestBeforeFileIsLoaded,
-    testHandleBreakpointRequestAfterFileIsLoaded,
-    testSourceFileLoadedAfterHandleBreakpointRequest,
-  });
+  return runTests({ testHandleBreakpointRequestBeforeFileIsLoaded,
+                    testHandleBreakpointRequestAfterFileIsLoaded,
+                    testSourceFileLoadedAfterHandleBreakpointRequest });
 }
diff --git a/Tests/CMakeLib/testDebuggerThread.cxx b/Tests/CMakeLib/testDebuggerThread.cxx
index 0ea95b6..3b7fe6e 100644
--- a/Tests/CMakeLib/testDebuggerThread.cxx
+++ b/Tests/CMakeLib/testDebuggerThread.cxx
@@ -1,4 +1,3 @@
-#include <functional>
 #include <memory>
 #include <string>
 #include <vector>
@@ -27,7 +26,5 @@
 
 int testDebuggerThread(int, char*[])
 {
-  return runTests(std::vector<std::function<bool()>>{
-    testStackFrameFunctionName,
-  });
+  return runTests({ testStackFrameFunctionName });
 }
diff --git a/Tests/CMakeLib/testDebuggerVariables.cxx b/Tests/CMakeLib/testDebuggerVariables.cxx
index bb3f14d..1193778 100644
--- a/Tests/CMakeLib/testDebuggerVariables.cxx
+++ b/Tests/CMakeLib/testDebuggerVariables.cxx
@@ -204,11 +204,7 @@
 
 int testDebuggerVariables(int, char*[])
 {
-  return runTests(std::vector<std::function<bool()>>{
-    testUniqueIds,
-    testConstructors,
-    testIgnoreEmptyStringEntries,
-    testSortTheResult,
-    testNoSupportsVariableType,
-  });
+  return runTests({ testUniqueIds, testConstructors,
+                    testIgnoreEmptyStringEntries, testSortTheResult,
+                    testNoSupportsVariableType });
 }
diff --git a/Tests/CMakeLib/testDebuggerVariablesHelper.cxx b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
index d61b73b..5fe1c63 100644
--- a/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
+++ b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
@@ -1,7 +1,6 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 
-#include <functional>
 #include <memory>
 #include <set>
 #include <string>
@@ -571,18 +570,10 @@
 
 int testDebuggerVariablesHelper(int, char*[])
 {
-  return runTests(std::vector<std::function<bool()>>{
-    testCreateFromPolicyMap,
-    testCreateFromPairVector,
-    testCreateFromSet,
-    testCreateFromStringVector,
-    testCreateFromTarget,
-    testCreateFromGlobalGenerator,
-    testCreateFromMakefile,
-    testCreateFromStackFrame,
-    testCreateFromTests,
-    testCreateFromBTStringVector,
-    testCreateFromFileSet,
-    testCreateFromFileSets,
-  });
+  return runTests({ testCreateFromPolicyMap, testCreateFromPairVector,
+                    testCreateFromSet, testCreateFromStringVector,
+                    testCreateFromTarget, testCreateFromGlobalGenerator,
+                    testCreateFromMakefile, testCreateFromStackFrame,
+                    testCreateFromTests, testCreateFromBTStringVector,
+                    testCreateFromFileSet, testCreateFromFileSets });
 }
diff --git a/Tests/CMakeLib/testDebuggerVariablesManager.cxx b/Tests/CMakeLib/testDebuggerVariablesManager.cxx
index 3013b9f..a1881c0 100644
--- a/Tests/CMakeLib/testDebuggerVariablesManager.cxx
+++ b/Tests/CMakeLib/testDebuggerVariablesManager.cxx
@@ -1,7 +1,6 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 
-#include <functional>
 #include <memory>
 #include <vector>
 
@@ -44,7 +43,5 @@
 
 int testDebuggerVariablesManager(int, char*[])
 {
-  return runTests(std::vector<std::function<bool()>>{
-    testVariablesRegistration,
-  });
+  return runTests({ testVariablesRegistration });
 }
diff --git a/Tests/CMakeLib/testJSONHelpers.cxx b/Tests/CMakeLib/testJSONHelpers.cxx
index 50f0386..05404fa 100644
--- a/Tests/CMakeLib/testJSONHelpers.cxx
+++ b/Tests/CMakeLib/testJSONHelpers.cxx
@@ -1,5 +1,4 @@
 #include <functional>
-#include <iostream>
 #include <map>
 #include <string>
 #include <vector>
@@ -12,13 +11,7 @@
 #include "cmJSONHelpers.h"
 #include "cmJSONState.h"
 
-#define ASSERT_TRUE(x)                                                        \
-  do {                                                                        \
-    if (!(x)) {                                                               \
-      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
-      return false;                                                           \
-    }                                                                         \
-  } while (false)
+#include "testCommon.h"
 
 namespace {
 struct ObjectStruct
@@ -472,47 +465,8 @@
 
 int testJSONHelpers(int /*unused*/, char* /*unused*/[])
 {
-  if (!testInt()) {
-    return 1;
-  }
-  if (!testUInt()) {
-    return 1;
-  }
-  if (!testBool()) {
-    return 1;
-  }
-  if (!testString()) {
-    return 1;
-  }
-  if (!testObject()) {
-    return 1;
-  }
-  if (!testObjectInherited()) {
-    return 1;
-  }
-  if (!testObjectNoExtra()) {
-    return 1;
-  }
-  if (!testObjectOptional()) {
-    return 1;
-  }
-  if (!testVector()) {
-    return 1;
-  }
-  if (!testVectorFilter()) {
-    return 1;
-  }
-  if (!testMap()) {
-    return 1;
-  }
-  if (!testMapFilter()) {
-    return 1;
-  }
-  if (!testOptional()) {
-    return 1;
-  }
-  if (!testRequired()) {
-    return 1;
-  }
-  return 0;
+  return runTests({ testInt, testUInt, testBool, testString, testObject,
+                    testObjectInherited, testObjectNoExtra, testObjectOptional,
+                    testVector, testVectorFilter, testMap, testMapFilter,
+                    testOptional, testRequired });
 }
diff --git a/Tests/CMakeLib/testList.cxx b/Tests/CMakeLib/testList.cxx
index 8822806..4bff217 100644
--- a/Tests/CMakeLib/testList.cxx
+++ b/Tests/CMakeLib/testList.cxx
@@ -11,6 +11,8 @@
 
 #include "cmList.h"
 
+#include "testCommon.h"
+
 namespace {
 
 void checkResult(bool success)
@@ -951,44 +953,9 @@
 
 int testList(int /*unused*/, char* /*unused*/[])
 {
-  int result = 0;
-
-  if (!testConstructors()) {
-    result = 1;
-  }
-  if (!testAssign()) {
-    result = 1;
-  }
-  if (!testConversions()) {
-    result = 1;
-  }
-  if (!testAccess()) {
-    result = 1;
-  }
-  if (!testModifiers()) {
-    result = 1;
-  }
-  if (!testRemoveItems()) {
-    result = 1;
-  }
-  if (!testRemoveDuplicates()) {
-    result = 1;
-  }
-  if (!testFilter()) {
-    result = 1;
-  }
-  if (!testReverse()) {
-    result = 1;
-  }
-  if (!testSort()) {
-    result = 1;
-  }
-  if (!testTransform()) {
-    result = 1;
-  }
-  if (!testStaticModifiers()) {
-    result = 1;
-  }
-
-  return result;
+  return runTests({ testConstructors, testAssign, testConversions, testAccess,
+                    testModifiers, testRemoveItems, testRemoveDuplicates,
+                    testFilter, testReverse, testSort, testTransform,
+                    testStaticModifiers },
+                  false);
 }
diff --git a/Tests/CMakeLib/testOptional.cxx b/Tests/CMakeLib/testOptional.cxx
index 933ab70..eba2dd5 100644
--- a/Tests/CMakeLib/testOptional.cxx
+++ b/Tests/CMakeLib/testOptional.cxx
@@ -4,6 +4,8 @@
 #include <cm/optional>
 #include <cm/utility>
 
+#include "testCommon.h"
+
 class EventLogger;
 
 class Event
@@ -93,14 +95,6 @@
   NoMoveAssignEventLogger& operator=(NoMoveAssignEventLogger&&) = delete;
 };
 
-#define ASSERT_TRUE(x)                                                        \
-  do {                                                                        \
-    if (!(x)) {                                                               \
-      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
-      return false;                                                           \
-    }                                                                         \
-  } while (false)
-
 // Certain builds of GCC generate false -Wmaybe-uninitialized warnings when
 // doing a release build with the system version of std::optional. These
 // warnings do not manifest when using our own cm::optional implementation.
diff --git a/Tests/CMakeLib/testRange.cxx b/Tests/CMakeLib/testRange.cxx
index 36c1e18..64bc3d7 100644
--- a/Tests/CMakeLib/testRange.cxx
+++ b/Tests/CMakeLib/testRange.cxx
@@ -1,19 +1,12 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 
-#include <iostream>
 #include <string>
 #include <vector>
 
 #include "cmRange.h"
 
-#define ASSERT_TRUE(x)                                                        \
-  do {                                                                        \
-    if (!(x)) {                                                               \
-      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
-      return -1;                                                              \
-    }                                                                         \
-  } while (false)
+#include "testCommon.h"
 
 int testRange(int /*unused*/, char* /*unused*/[])
 {
diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx
index 3509266..a6489ab 100644
--- a/Tests/CMakeLib/testString.cxx
+++ b/Tests/CMakeLib/testString.cxx
@@ -14,13 +14,7 @@
 
 #include "cmString.hxx"
 
-#define ASSERT_TRUE(x)                                                        \
-  do {                                                                        \
-    if (!(x)) {                                                               \
-      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
-      return false;                                                           \
-    }                                                                         \
-  } while (false)
+#include "testCommon.h"
 
 static bool testConstructDefault()
 {
@@ -1163,188 +1157,65 @@
 
 int testString(int /*unused*/, char* /*unused*/[])
 {
-  if (!testConstructDefault()) {
-    return 1;
-  }
-  if (!testConstructFromNullPtr()) {
-    return 1;
-  }
-  if (!testConstructFromCStrNull()) {
-    return 1;
-  }
-  if (!testConstructFromCharArray()) {
-    return 1;
-  }
-  if (!testConstructFromCStr()) {
-    return 1;
-  }
-  if (!testConstructFromStdString()) {
-    return 1;
-  }
-  if (!testConstructFromView()) {
-    return 1;
-  }
-  if (!testConstructFromChar()) {
-    return 1;
-  }
-  if (!testConstructFromInitList()) {
-    return 1;
-  }
-  if (!testConstructFromBuffer()) {
-    return 1;
-  }
-  if (!testConstructFromInputIterator()) {
-    return 1;
-  }
-  if (!testConstructFromN()) {
-    return 1;
-  }
-  if (!testConstructFromStaticStringView()) {
-    return 1;
-  }
-  if (!testConstructCopy()) {
-    return 1;
-  }
-  if (!testConstructMove()) {
-    return 1;
-  }
-  if (!testAssignCopy()) {
-    return 1;
-  }
-  if (!testAssignMove()) {
-    return 1;
-  }
-  if (!testAssignFromChar()) {
-    return 1;
-  }
-  if (!testAssignFromView()) {
-    return 1;
-  }
-  if (!testAssignFromStdString()) {
-    return 1;
-  }
-  if (!testAssignFromCStr()) {
-    return 1;
-  }
-  if (!testAssignFromCharArray()) {
-    return 1;
-  }
-  if (!testAssignFromCStrNull()) {
-    return 1;
-  }
-  if (!testAssignFromNullPtr()) {
-    return 1;
-  }
-  if (!testAssignFromInitList()) {
-    return 1;
-  }
-  if (!testAssignFromStaticStringView()) {
-    return 1;
-  }
-  if (!testOperatorBool()) {
-    return 1;
-  }
-  if (!testOperatorIndex()) {
-    return 1;
-  }
-  if (!testOperatorPlusEqual()) {
-    return 1;
-  }
-  if (!testOperatorCompare()) {
-    return 1;
-  }
-  if (!testOperatorStream()) {
-    return 1;
-  }
-  if (!testOperatorStdStringPlusEqual()) {
-    return 1;
-  }
-  if (!testMethod_borrow()) {
-    return 1;
-  }
-  if (!testMethod_view()) {
-    return 1;
-  }
-  if (!testMethod_empty()) {
-    return 1;
-  }
-  if (!testMethod_length()) {
-    return 1;
-  }
-  if (!testMethod_at()) {
-    return 1;
-  }
-  if (!testMethod_front_back()) {
-    return 1;
-  }
-  if (!testMethod_clear()) {
-    return 1;
-  }
-  if (!testMethod_insert()) {
-    return 1;
-  }
-  if (!testMethod_erase()) {
-    return 1;
-  }
-  if (!testMethod_push_back()) {
-    return 1;
-  }
-  if (!testMethod_pop_back()) {
-    return 1;
-  }
-  if (!testMethod_replace()) {
-    return 1;
-  }
-  if (!testMethod_copy()) {
-    return 1;
-  }
-  if (!testMethod_resize()) {
-    return 1;
-  }
-  if (!testMethod_swap()) {
-    return 1;
-  }
-  if (!testMethodIterators()) {
-    return 1;
-  }
-  if (!testMethod_substr_AtEndBorrowed()) {
-    return 1;
-  }
-  if (!testMethod_substr_AtEndOwned()) {
-    return 1;
-  }
-  if (!testMethod_substr_AtStartBorrowed()) {
-    return 1;
-  }
-  if (!testMethod_substr_AtStartOwned()) {
-    return 1;
-  }
-  if (!testMethod_compare()) {
-    return 1;
-  }
-  if (!testMethod_find()) {
-    return 1;
-  }
-  if (!testMethod_rfind()) {
-    return 1;
-  }
-  if (!testMethod_find_first_of()) {
-    return 1;
-  }
-  if (!testMethod_find_first_not_of()) {
-    return 1;
-  }
-  if (!testMethod_find_last_of()) {
-    return 1;
-  }
-  if (!testMethod_find_last_not_of()) {
-    return 1;
-  }
-  if (!testAddition()) {
-    return 1;
-  }
-  if (!testStability()) {
-    return 1;
-  }
-  return 0;
+  return runTests({ testConstructDefault,
+                    testConstructFromNullPtr,
+                    testConstructFromCStrNull,
+                    testConstructFromCharArray,
+                    testConstructFromCStr,
+                    testConstructFromStdString,
+                    testConstructFromView,
+                    testConstructFromChar,
+                    testConstructFromInitList,
+                    testConstructFromBuffer,
+                    testConstructFromInputIterator,
+                    testConstructFromN,
+                    testConstructFromStaticStringView,
+                    testConstructCopy,
+                    testConstructMove,
+                    testAssignCopy,
+                    testAssignMove,
+                    testAssignFromChar,
+                    testAssignFromView,
+                    testAssignFromStdString,
+                    testAssignFromCStr,
+                    testAssignFromCharArray,
+                    testAssignFromCStrNull,
+                    testAssignFromNullPtr,
+                    testAssignFromInitList,
+                    testAssignFromStaticStringView,
+                    testOperatorBool,
+                    testOperatorIndex,
+                    testOperatorPlusEqual,
+                    testOperatorCompare,
+                    testOperatorStream,
+                    testOperatorStdStringPlusEqual,
+                    testMethod_borrow,
+                    testMethod_view,
+                    testMethod_empty,
+                    testMethod_length,
+                    testMethod_at,
+                    testMethod_front_back,
+                    testMethod_clear,
+                    testMethod_insert,
+                    testMethod_erase,
+                    testMethod_push_back,
+                    testMethod_pop_back,
+                    testMethod_replace,
+                    testMethod_copy,
+                    testMethod_resize,
+                    testMethod_swap,
+                    testMethodIterators,
+                    testMethod_substr_AtEndBorrowed,
+                    testMethod_substr_AtEndOwned,
+                    testMethod_substr_AtStartBorrowed,
+                    testMethod_substr_AtStartOwned,
+                    testMethod_compare,
+                    testMethod_find,
+                    testMethod_rfind,
+                    testMethod_find_first_of,
+                    testMethod_find_first_not_of,
+                    testMethod_find_last_of,
+                    testMethod_find_last_not_of,
+                    testAddition,
+                    testStability });
 }
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser.cxx b/Tests/CMakeLib/testVisualStudioSlnParser.cxx
index 3485bac..3bab2ba 100644
--- a/Tests/CMakeLib/testVisualStudioSlnParser.cxx
+++ b/Tests/CMakeLib/testVisualStudioSlnParser.cxx
@@ -1,10 +1,12 @@
-#include "testVisualStudioSlnParser.h"
-
 #include <iostream>
 
 #include "cmVisualStudioSlnData.h"
 #include "cmVisualStudioSlnParser.h"
 
+#include "testConfig.h"
+
+#define SLN_EXTENSION "sln-file"
+
 static bool parsedRight(cmVisualStudioSlnParser& parser,
                         const std::string& file, cmSlnData& data,
                         cmVisualStudioSlnParser::ParseResult expected =
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser.h.in b/Tests/CMakeLib/testVisualStudioSlnParser.h.in
deleted file mode 100644
index 62c3f4d..0000000
--- a/Tests/CMakeLib/testVisualStudioSlnParser.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef testVisualStudioSlnParser_h
-#define testVisualStudioSlnParser_h
-
-#define SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@"
-#define SLN_EXTENSION "sln-file"
-
-#endif
diff --git a/Tests/CMakeLib/testXMLParser.cxx b/Tests/CMakeLib/testXMLParser.cxx
index 32ee3ec..3b7af3a 100644
--- a/Tests/CMakeLib/testXMLParser.cxx
+++ b/Tests/CMakeLib/testXMLParser.cxx
@@ -1,9 +1,9 @@
-#include "testXMLParser.h"
-
 #include <iostream>
 
 #include "cmXMLParser.h"
 
+#include "testConfig.h"
+
 int testXMLParser(int /*unused*/, char* /*unused*/[])
 {
   // TODO: Derive from parser and check attributes.
diff --git a/Tests/CMakeLib/testXMLParser.h.in b/Tests/CMakeLib/testXMLParser.h.in
deleted file mode 100644
index da0b275..0000000
--- a/Tests/CMakeLib/testXMLParser.h.in
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef testXMLParser_h
-#define testXMLParser_h
-
-#define SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@"
-
-#endif
diff --git a/Tests/CPackNSISGenerator/CMakeLists.txt b/Tests/CPackNSISGenerator/CMakeLists.txt
index 5d6320b..cb0b13d 100644
--- a/Tests/CPackNSISGenerator/CMakeLists.txt
+++ b/Tests/CPackNSISGenerator/CMakeLists.txt
@@ -10,6 +10,26 @@
   LIBRARY DESTINATION .
   BUNDLE DESTINATION .)
 
+# Component that is a reserved name on Windows.
+# See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
+install(
+  DIRECTORY .
+  DESTINATION txt
+  COMPONENT CON
+  FILES_MATCHING PATTERN *.txt)
+# Component name that is similar to a reserved name on Windows.
+install(
+  DIRECTORY .
+  DESTINATION txt
+  COMPONENT Console
+  FILES_MATCHING PATTERN *.txt)
+# Component name that is strongly discouraged on Windows.
+install(
+  DIRECTORY .
+  DESTINATION txt
+  COMPONENT EndsWithDot.
+  FILES_MATCHING PATTERN *.txt)
+
 set(CPACK_NSIS_MUI_HEADERIMAGE "${PROJECT_SOURCE_DIR}\\\\header-image.bmp")
 set(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}\\\\header-icon.bmp")
 set(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}\\\\install.ico")
diff --git a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
index 31a2560..3e4d7b4 100644
--- a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
+++ b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
@@ -69,3 +69,24 @@
 else()
   message(FATAL_ERROR "License found in the project")
 endif()
+
+file(STRINGS "${project_file}" line REGEX [[\\_CON\\]])
+string(FIND "${line}" [[\_CON\]] output_index)
+message(STATUS "Found CON component reserved directory name as _CON")
+if("${output_index}" EQUAL "-1")
+  message(FATAL_ERROR "CON component reserved directory name not found as _CON in the project")
+endif()
+
+file(STRINGS "${project_file}" line REGEX [[\\Console\\]])
+string(FIND "${line}" [[\Console\]] output_index)
+message(STATUS "Found Console component directory name as Console")
+if("${output_index}" EQUAL "-1")
+  message(FATAL_ERROR "Console component directory name not found as Console in the project")
+endif()
+
+file(STRINGS "${project_file}" line REGEX [[\\EndsWithDot._\\]])
+string(FIND "${line}" [[\EndsWithDot._\]] output_index)
+message(STATUS "Found EndsWithDot. component directory name as EndsWithDot._")
+if("${output_index}" EQUAL "-1")
+  message(FATAL_ERROR "EndsWithDot. component directory name not found as EndsWithDot._ in the project")
+endif()
diff --git a/Tests/RunCMake/CMP0173/CMP0173-NEW-result.txt b/Tests/RunCMake/CMP0173/CMP0173-NEW-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-NEW-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0173/CMP0173-NEW-stderr.txt b/Tests/RunCMake/CMP0173/CMP0173-NEW-stderr.txt
new file mode 100644
index 0000000..384a027
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-NEW-stderr.txt
@@ -0,0 +1,9 @@
+CMake Error at .*/Modules/CMakeFindFrameworks\.cmake:[0-9]+ \(message\):
+  CMakeFindFrameworks\.cmake is not maintained and lacks support for more
+  recent framework handling\.  It will be removed in a future version of
+  CMake\.  Update the code to use find_library\(\) instead\.  Use of this module
+  is now an error according to policy CMP0173\.
+Call Stack \(most recent call first\):
+  CMP0173-common\.cmake:12 \(include\)
+  CMP0173-NEW\.cmake:4 \(include\)
+  CMakeLists\.txt:3 \(include\)
diff --git a/Tests/RunCMake/CMP0173/CMP0173-NEW.cmake b/Tests/RunCMake/CMP0173/CMP0173-NEW.cmake
new file mode 100644
index 0000000..f26093a
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-NEW.cmake
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0173 NEW)
+
+set(should_find NO)
+include(CMP0173-common.cmake)
diff --git a/Tests/RunCMake/CMP0173/CMP0173-OLD-stdout.txt b/Tests/RunCMake/CMP0173/CMP0173-OLD-stdout.txt
new file mode 100644
index 0000000..f32056a
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-OLD-stdout.txt
@@ -0,0 +1,2 @@
+-- Configuring done \([0-9]+\.[0-9]s\)
+-- Generating done \([0-9]+\.[0-9]s\)
diff --git a/Tests/RunCMake/CMP0173/CMP0173-OLD.cmake b/Tests/RunCMake/CMP0173/CMP0173-OLD.cmake
new file mode 100644
index 0000000..7316728
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-OLD.cmake
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0173 OLD)
+
+set(should_find YES)
+include(CMP0173-common.cmake)
diff --git a/Tests/RunCMake/CMP0173/CMP0173-WARN-stderr.txt b/Tests/RunCMake/CMP0173/CMP0173-WARN-stderr.txt
new file mode 100644
index 0000000..3a4c130
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-WARN-stderr.txt
@@ -0,0 +1,29 @@
+CMake Warning \(dev\) at CMP0173-common\.cmake:1 \(include\):
+  Policy CMP0173 is not set: The CMakeFindFrameworks module is removed\.  Run
+  "cmake --help-policy CMP0173" for policy details\.  Use the cmake_policy
+  command to set the policy and suppress this warning\.
+
+Call Stack \(most recent call first\):
+  CMP0173-WARN\.cmake:2 \(include\)
+  CMakeLists\.txt:3 \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at .*/Modules/CMakeFindFrameworks\.cmake:[0-9]+ \(message\):
+  CMakeFindFrameworks\.cmake is not maintained and lacks support for more
+  recent framework handling\.  It will be removed in a future version of
+  CMake\.  Update the code to use find_library\(\) instead\.
+Call Stack \(most recent call first\):
+  CMP0173-common\.cmake:1 \(include\)
+  CMP0173-WARN\.cmake:2 \(include\)
+  CMakeLists\.txt:3 \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at .*/Modules/CMakeFindFrameworks\.cmake:[0-9]+ \(message\):
+  CMakeFindFrameworks\.cmake is not maintained and lacks support for more
+  recent framework handling\.  It will be removed in a future version of
+  CMake\.  Update the code to use find_library\(\) instead\.
+Call Stack \(most recent call first\):
+  CMP0173-common\.cmake:12 \(include\)
+  CMP0173-WARN\.cmake:2 \(include\)
+  CMakeLists\.txt:3 \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/CMP0173/CMP0173-WARN.cmake b/Tests/RunCMake/CMP0173/CMP0173-WARN.cmake
new file mode 100644
index 0000000..dcc59b7
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-WARN.cmake
@@ -0,0 +1,2 @@
+set(should_find YES)
+include(CMP0173-common.cmake)
diff --git a/Tests/RunCMake/CMP0173/CMP0173-common.cmake b/Tests/RunCMake/CMP0173/CMP0173-common.cmake
new file mode 100644
index 0000000..4a46bbe
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMP0173-common.cmake
@@ -0,0 +1,12 @@
+include(CMakeFindFrameworks OPTIONAL RESULT_VARIABLE found)
+if(NOT should_find AND found)
+  message(FATAL_ERROR
+    "The CMakeFindFrameworks module should not have been found, but it was."
+  )
+endif()
+if(should_find AND NOT found)
+  message(FATAL_ERROR
+    "The CMakeFindFrameworks module should have been found, but it was not."
+  )
+endif()
+include(${CMAKE_ROOT}/Modules/CMakeFindFrameworks.cmake)
diff --git a/Tests/RunCMake/CMP0173/CMakeLists.txt b/Tests/RunCMake/CMP0173/CMakeLists.txt
new file mode 100644
index 0000000..dda37d8
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.30)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0173/RunCMakeTest.cmake b/Tests/RunCMake/CMP0173/RunCMakeTest.cmake
new file mode 100644
index 0000000..42d5e30
--- /dev/null
+++ b/Tests/RunCMake/CMP0173/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0173-OLD)
+run_cmake(CMP0173-NEW)
+run_cmake(CMP0173-WARN)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 3ae7a81..1f7b8c5 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -177,6 +177,7 @@
 add_RunCMake_test(CMP0169)
 add_RunCMake_test(CMP0170)
 add_RunCMake_test(CMP0171)
+add_RunCMake_test(CMP0173)
 
 # The test for Policy 65 requires the use of the
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
diff --git a/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
index 598478f..f8454b9 100644
--- a/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
@@ -1,5 +1,5 @@
 ^CMake Error: Could not read presets from [^
 ]*/Tests/RunCMake/CMakePresets/HighVersion:
-Error: @2,14: Unrecognized "version" field
+Error: @2,14: Unrecognized "version" 1000: must be >=1 and <=10
   "version": 1000,
              \^$
diff --git a/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
index e933100..f4f65f9 100644
--- a/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
@@ -1,5 +1,5 @@
 ^CMake Error: Could not read presets from [^
 ]*/Tests/RunCMake/CMakePresets/LowVersion:
-Error: @2,14: Unrecognized "version" field
+Error: @2,14: Unrecognized "version" 0: must be >=1 and <=10
   "version": 0,
              \^
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake
index f7ede51..5583407 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake
@@ -72,6 +72,7 @@
   run_install_test(linux-unresolved)
   run_install_test(linux-conflict)
   run_install_test(linux-notfile)
+  run_install_test(linux-indirect-dependencies)
   run_cmake(project)
   run_cmake(badargs1)
   run_cmake(badargs2)
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake
index d3d1cd6..012ed58 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake
@@ -1,4 +1,5 @@
 set(_check
+  [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/conflict/libconflict\.so]]
   [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/libtest_rpath\.so]]
   [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/libtest_runpath\.so]]
   [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/rpath/librpath\.so]]
@@ -19,7 +20,7 @@
 check_contents(deps/udeps2.txt "^${_check}$")
 check_contents(deps/udeps3.txt "^${_check}$")
 set(_check
-  "^libconflict\\.so:[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/conflict/libconflict\\.so;[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/conflict2/libconflict\\.so\n$"
+  "^$"
   )
 check_contents(deps/cdeps1.txt "${_check}")
 check_contents(deps/cdeps2.txt "${_check}")
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-indirect-dependencies-all-stdout.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-indirect-dependencies-all-stdout.txt
new file mode 100644
index 0000000..9f5e07d
--- /dev/null
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-indirect-dependencies-all-stdout.txt
@@ -0,0 +1 @@
+Resolved dependencies: /
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-indirect-dependencies.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-indirect-dependencies.cmake
new file mode 100644
index 0000000..1d0a913
--- /dev/null
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-indirect-dependencies.cmake
@@ -0,0 +1,83 @@
+enable_language(C)
+cmake_policy(SET CMP0095 NEW)
+
+file(WRITE "${CMAKE_BINARY_DIR}/A.c" "void libA(void) {}\n")
+file(WRITE "${CMAKE_BINARY_DIR}/C.c" "void libC(void) {}\n")
+file(WRITE "${CMAKE_BINARY_DIR}/BUseAC.c" [[
+extern void libA(void);
+extern void libC(void);
+void libB(void)
+{
+    libA();
+    libC();
+}
+]])
+file(WRITE "${CMAKE_BINARY_DIR}/mainABC.c" [[
+extern void libA(void);
+extern void libB(void);
+extern void libC(void);
+
+int main(void)
+{
+    libA();
+    libB();
+    libC();
+    return 0;
+}
+
+]])
+
+set(lib_dirExe "${CMAKE_BINARY_DIR}/Exe")
+set(lib_dirA "${CMAKE_BINARY_DIR}/libA")
+set(lib_dirB "${CMAKE_BINARY_DIR}/libB")
+set(lib_dirC "${CMAKE_BINARY_DIR}/libC")
+file(MAKE_DIRECTORY ${lib_dirExe})
+file(MAKE_DIRECTORY ${lib_dirA})
+file(MAKE_DIRECTORY ${lib_dirB})
+file(MAKE_DIRECTORY ${lib_dirC})
+
+add_library(A SHARED "${CMAKE_BINARY_DIR}/A.c")
+set_property(TARGET A PROPERTY LIBRARY_OUTPUT_DIRECTORY ${lib_dirA})
+
+add_library(C SHARED "${CMAKE_BINARY_DIR}/C.c")
+set_property(TARGET C PROPERTY LIBRARY_OUTPUT_DIRECTORY ${lib_dirC})
+
+# We doesn't need to set A as a dependency of B, because we don't need `RUNPATH` value set for B
+add_library(B SHARED "${CMAKE_BINARY_DIR}/BUseAC.c")
+target_link_libraries(B PRIVATE A C)
+set_property(TARGET B PROPERTY LIBRARY_OUTPUT_DIRECTORY ${lib_dirB})
+
+# We MUST have empty `RUNPATH` in A & B
+set_target_properties(A B C PROPERTIES
+    BUILD_WITH_INSTALL_RPATH 1
+)
+
+# The executable is really workable without `RUNPATH` in B
+add_executable(exe "${CMAKE_BINARY_DIR}/mainABC.c")
+target_link_libraries(exe A B C)
+set_property(TARGET exe PROPERTY RUNTIME_OUTPUT_DIRECTORY ${lib_dirExe})
+
+# We MUST have `RUNPATH` in exe, not `RPATH`
+# Test will pass if we have `RPATH`, because of the inheritance
+target_link_options(exe PRIVATE -Wl,--enable-new-dtags)
+
+install(CODE [[
+    # Work with non-installed binary, because of the RUNPATH values
+    set(exeFile "$<TARGET_FILE:exe>")
+
+    # Check executable is can be successfully finished
+    execute_process(
+        COMMAND "${exeFile}"
+        COMMAND_ERROR_IS_FATAL ANY
+    )
+
+    # Check dependencies resolved
+    file(GET_RUNTIME_DEPENDENCIES
+        RESOLVED_DEPENDENCIES_VAR RESOLVED
+        PRE_INCLUDE_REGEXES "^lib[ABC]\\.so$"
+        PRE_EXCLUDE_REGEXES ".*"
+        EXECUTABLES
+            "${exeFile}"
+    )
+    message(STATUS "Resolved dependencies: ${RESOLVED}")
+]])
diff --git a/Tests/SwiftMixLib/CMakeLists.txt b/Tests/SwiftMixLib/CMakeLists.txt
index d23c6ba..c2cfb8f 100644
--- a/Tests/SwiftMixLib/CMakeLists.txt
+++ b/Tests/SwiftMixLib/CMakeLists.txt
@@ -10,3 +10,15 @@
 
 add_executable(c_main main.c)
 target_link_libraries(c_main PUBLIC SwiftMixedLib)
+
+if(WIN32)
+  # TODO: On macOS and Linux, Swift has mechanism for determining what libraries
+  #       an object, or objects from a static archive, need to link against,
+  #       which is how the Swift driver is able to determine that `c_main`
+  #       needs to link swiftCore. Windows does not have this mechanism.
+  #       Eventually CMake should learn how to do this, explicitly forwarding
+  #       the required library to the link command when linking a static
+  #       archive containing Swift sources into something else, even if the
+  #       linker language is Swift.
+  target_link_libraries(c_main PRIVATE swiftCore)
+endif()