Merge topic 'fileapi-install-generators'

d70a0f8681 fileapi: Fix codemodel target install destination for cross-dir rules

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3639
diff --git a/.clang-tidy b/.clang-tidy
index bfcb67c..57e571a 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -3,16 +3,21 @@
 bugprone-*,\
 -bugprone-macro-parentheses,\
 -bugprone-misplaced-widening-cast,\
+-bugprone-narrowing-conversions,\
+-bugprone-too-small-loop-variable,\
 google-readability-casting,\
 misc-*,\
 -misc-incorrect-roundings,\
 -misc-macro-parentheses,\
 -misc-misplaced-widening-cast,\
+-misc-non-private-member-variables-in-classes,\
 -misc-static-assert,\
 modernize-*,\
+-modernize-avoid-c-arrays,\
 -modernize-deprecated-headers,\
 -modernize-return-braced-init-list,\
 -modernize-use-auto,\
+-modernize-use-nodiscard,\
 -modernize-use-noexcept,\
 -modernize-use-transparent-functors,\
 -modernize-use-using,\
@@ -24,8 +29,11 @@
 -readability-implicit-bool-cast,\
 -readability-implicit-bool-conversion,\
 -readability-inconsistent-declaration-parameter-name,\
+-readability-isolate-declaration,\
+-readability-magic-numbers,\
 -readability-named-parameter,\
 -readability-redundant-declaration,\
+-readability-uppercase-literal-suffix,\
 "
 HeaderFilterRegex: 'Source/cm[^/]*\.(h|hxx|cxx)$'
 CheckOptions:
diff --git a/.gitattributes b/.gitattributes
index 24fd9c2..3854b73 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,4 +1,4 @@
-.gitattributes   export-ignore
+.git*            export-ignore
 .hooks*          export-ignore
 
 # Custom attribute to mark sources as using our C code style.
diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el
index e4fa6c1..caaf0d5 100644
--- a/Auxiliary/cmake-mode.el
+++ b/Auxiliary/cmake-mode.el
@@ -1,5 +1,7 @@
 ;;; cmake-mode.el --- major-mode for editing CMake sources
 
+;; Package-Requires: ((emacs "24.1"))
+
 ; Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 ; file Copyright.txt or https://cmake.org/licensing for details.
 
@@ -224,17 +226,11 @@
 ;;
 (defvar cmake-mode-hook nil)
 
-;------------------------------------------------------------------------------
-
-;; For compatibility with Emacs < 24
-(defalias 'cmake--parent-mode
-  (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
-
 ;;------------------------------------------------------------------------------
 ;; Mode definition.
 ;;
 ;;;###autoload
-(define-derived-mode cmake-mode cmake--parent-mode "CMake"
+(define-derived-mode cmake-mode prog-mode "CMake"
   "Major mode for editing CMake source files."
 
   ; Setup font-lock mode.
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index cd8385b..5de117b 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -288,6 +288,7 @@
             \ SKIP_AUTORCC
             \ SKIP_AUTOUIC
             \ SKIP_BUILD_RPATH
+            \ SKIP_REGULAR_EXPRESSION
             \ SKIP_RETURN_CODE
             \ SOURCES
             \ SOURCE_DIR
@@ -915,6 +916,7 @@
             \ CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES
             \ CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT
             \ CMAKE_ECLIPSE_MAKE_ARGUMENTS
+            \ CMAKE_ECLIPSE_RESOURCE_ENCODING
             \ CMAKE_ECLIPSE_VERSION
             \ CMAKE_EDIT_COMMAND
             \ CMAKE_ENABLE_EXPORTS
@@ -948,6 +950,12 @@
             \ CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
             \ CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
             \ CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
+            \ CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH
+            \ CMAKE_FIND_USE_CMAKE_PATH
+            \ CMAKE_FIND_USE_CMAKE_SYSTEM_PATH
+            \ CMAKE_FIND_USE_PACKAGE_REGISTRY
+            \ CMAKE_FIND_USE_PACKAGE_ROOT_PATH
+            \ CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH
             \ CMAKE_FOLDER
             \ CMAKE_FRAMEWORK
             \ CMAKE_FRAMEWORK_PATH
@@ -1765,6 +1773,7 @@
             \ NAME
             \ OFF
             \ PASS_REGULAR_EXPRESSION
+            \ SKIP_REGULAR_EXPRESSION
             \ TARGET_FILE
             \ WILL_FAIL
             \ WORKING_DIRECTORY
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 51a1d8b..75ac8bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -429,10 +429,7 @@
     set(_CMAKE_USE_OPENSSL_DEFAULT OFF)
     if(NOT DEFINED CMAKE_USE_OPENSSL AND NOT WIN32 AND NOT APPLE
         AND CMAKE_SYSTEM_NAME MATCHES "(Linux|FreeBSD)")
-      find_package(OpenSSL QUIET)
-      if(OPENSSL_FOUND)
-        set(_CMAKE_USE_OPENSSL_DEFAULT ON)
-      endif()
+      set(_CMAKE_USE_OPENSSL_DEFAULT ON)
     endif()
     option(CMAKE_USE_OPENSSL "Use OpenSSL." ${_CMAKE_USE_OPENSSL_DEFAULT})
     mark_as_advanced(CMAKE_USE_OPENSSL)
@@ -629,8 +626,7 @@
 # The main section of the CMakeLists file
 #
 #-----------------------------------------------------------------------
-# Compute CMake_VERSION, etc.
-include(Source/CMakeVersionCompute.cmake)
+include(Source/CMakeVersion.cmake)
 
 # Include the standard Dart testing module
 enable_testing()
@@ -817,7 +813,7 @@
     PATTERN "*.sh*" PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE
                                 GROUP_READ GROUP_EXECUTE
                                 WORLD_READ WORLD_EXECUTE
-    REGEX "Help/dev($|/)" EXCLUDE
+    REGEX "Help/(dev|guide|index.rst)($|/)" EXCLUDE
     )
 
   # Install auxiliary files integrating with other tools.
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index dde4dbb..40f1c1a 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -89,7 +89,8 @@
    searched after paths from the current module,
    i.e. ``<CurrentPackage>_ROOT``, ``ENV{<CurrentPackage>_ROOT}``,
    ``<ParentPackage>_ROOT``, ``ENV{<ParentPackage>_ROOT}``, etc.
-   This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+   This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting
+   the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``.
    See policy :policy:`CMP0074`.
 
    * |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX|
@@ -97,7 +98,8 @@
 2. Search paths specified in cmake-specific cache variables.
    These are intended to be used on the command line with a ``-DVAR=value``.
    The values are interpreted as :ref:`semicolon-separated lists <CMake Language Lists>`.
-   This can be skipped if ``NO_CMAKE_PATH`` is passed.
+   This can be skipped if ``NO_CMAKE_PATH`` is passed or by setting the
+   :variable:`CMAKE_FIND_USE_CMAKE_PATH` to ``FALSE``.
 
    * |CMAKE_PREFIX_PATH_XXX|
    * |CMAKE_XXX_PATH|
@@ -107,7 +109,8 @@
    These are intended to be set in the user's shell configuration,
    and therefore use the host's native path separator
    (``;`` on Windows and ``:`` on UNIX).
-   This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed.
+   This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed or
+   by setting the :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH` to ``FALSE``.
 
    * |CMAKE_PREFIX_PATH_XXX|
    * |CMAKE_XXX_PATH|
@@ -119,13 +122,16 @@
    Hard-coded guesses should be specified with the ``PATHS`` option.
 
 5. Search the standard system environment variables.
-   This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is an argument.
+   This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed or by
+   setting the :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH` to ``FALSE``.
 
    * |SYSTEM_ENVIRONMENT_PATH_XXX|
+   * |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX|
 
 6. Search cmake variables defined in the Platform files
    for the current system.  This can be skipped if ``NO_CMAKE_SYSTEM_PATH``
-   is passed.
+   is passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`
+   to ``FALSE``.
 
    * |CMAKE_SYSTEM_PREFIX_PATH_XXX|
    * |CMAKE_SYSTEM_XXX_PATH|
diff --git a/Help/command/add_test.rst b/Help/command/add_test.rst
index 46b9b63..a77ba37 100644
--- a/Help/command/add_test.rst
+++ b/Help/command/add_test.rst
@@ -7,7 +7,8 @@
 
   add_test(NAME <name> COMMAND <command> [<arg>...]
            [CONFIGURATIONS <config>...]
-           [WORKING_DIRECTORY <dir>])
+           [WORKING_DIRECTORY <dir>]
+           [COMMAND_EXPAND_LISTS])
 
 Adds a test called ``<name>``.  The test name may not contain spaces,
 quotes, or other characters special in CMake syntax.  The options are:
@@ -28,12 +29,18 @@
   directory set to the build directory corresponding to the
   current source directory.
 
+``COMMAND_EXPAND_LISTS``
+  Lists in ``COMMAND`` arguments will be expanded, including those
+  created with
+  :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
 The given test command is expected to exit with code ``0`` to pass and
 non-zero to fail, or vice-versa if the :prop_test:`WILL_FAIL` test
 property is set.  Any output written to stdout or stderr will be
 captured by :manual:`ctest(1)` but does not affect the pass/fail status
-unless the :prop_test:`PASS_REGULAR_EXPRESSION` or
-:prop_test:`FAIL_REGULAR_EXPRESSION` test property is used.
+unless the :prop_test:`PASS_REGULAR_EXPRESSION`,
+:prop_test:`FAIL_REGULAR_EXPRESSION` or
+:prop_test:`SKIP_REGULAR_EXPRESSION` test property is used.
 
 The ``COMMAND`` and ``WORKING_DIRECTORY`` options may use "generator
 expressions" with the syntax ``$<...>``.  See the
diff --git a/Help/command/file.rst b/Help/command/file.rst
index f99021e..c06451a 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -13,6 +13,7 @@
     file(`STRINGS`_ <filename> <out-var> [...])
     file(`\<HASH\> <HASH_>`_ <filename> <out-var>)
     file(`TIMESTAMP`_ <filename> <out-var> [...])
+    file(`GET_RUNTIME_DEPENDENCIES`_ [...])
 
   `Writing`_
     file({`WRITE`_ | `APPEND`_} <filename> <content>...)
@@ -130,6 +131,273 @@
 See the :command:`string(TIMESTAMP)` command for documentation of
 the ``<format>`` and ``UTC`` options.
 
+.. _GET_RUNTIME_DEPENDENCIES:
+
+.. code-block:: cmake
+
+  file(GET_RUNTIME_DEPENDENCIES
+    [RESOLVED_DEPENDENCIES_VAR <deps_var>]
+    [UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>]
+    [CONFLICTING_DEPENDENICES_PREFIX <conflicting_deps_prefix>]
+    [EXECUTABLES [<executable_files>...]]
+    [LIBRARIES [<library_files>...]]
+    [MODULES [<module_files>...]]
+    [DIRECTORIES [<directories>...]]
+    [BUNDLE_EXECUTABLE <bundle_executable_file>]
+    [PRE_INCLUDE_REGEXES [<regexes>...]]
+    [PRE_EXCLUDE_REGEXES [<regexes>...]]
+    [POST_INCLUDE_REGEXES [<regexes>...]]
+    [POST_EXCLUDE_REGEXES [<regexes>...]]
+    )
+
+Recursively get the list of libraries depended on by the given files.
+
+Please note that this sub-command is not intended to be used in project mode.
+Instead, use it in an :command:`install(CODE)` or :command:`install(SCRIPT)`
+block. For example:
+
+.. code-block:: cmake
+
+  install(CODE [[
+    file(GET_RUNTIME_DEPENDENCIES
+      # ...
+      )
+    ]])
+
+The arguments are as follows:
+
+``RESOLVED_DEPENDENCIES_VAR <deps_var>``
+  Name of the variable in which to store the list of resolved dependencies.
+
+``UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>``
+  Name of the variable in which to store the list of unresolved dependencies.
+  If this variable is not specified, and there are any unresolved dependencies,
+  an error is issued.
+
+``CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>``
+  Variable prefix in which to store conflicting dependency information.
+  Dependencies are conflicting if two files with the same name are found in
+  two different directories. The list of filenames that conflict are stored in
+  ``<conflicting_deps_prefix>_FILENAMES``. For each filename, the list of paths
+  that were found for that filename are stored in
+  ``<conflicting_deps_prefix>_<filename>``.
+
+``EXECUTABLES <executable_files>``
+  List of executable files to read for dependencies. These are executables that
+  are typically created with :command:`add_executable`, but they do not have to
+  be created by CMake. On Apple platforms, the paths to these files determine
+  the value of ``@executable_path`` when recursively resolving the libraries.
+  Specifying ``STATIC`` libraries, ``MODULE`` s, or ``SHARED`` libraries here
+  will result in undefined behavior.
+
+``LIBRARIES <library_files>``
+  List of library files to read for dependencies. These are libraries that are
+  typically created with :command:`add_library(SHARED)`, but they do not have
+  to be created by CMake. Specifying ``STATIC`` libraries, ``MODULE`` s, or
+  executables here will result in undefined behavior.
+
+``MODULES <module_files>``
+  List of loadable module files to read for dependencies. These are modules
+  that are typically created with :command:`add_library(MODULE)`, but they do
+  not have to be created by CMake. They are typically used by calling
+  ``dlopen()`` at runtime rather than linked at link time with ``ld -l``.
+  Specifying ``STATIC`` libraries, ``SHARED`` libraries, or executables here
+  will result in undefined behavior.
+
+``DIRECTORIES <directories>``
+  List of additional directories to search for dependencies. On Linux
+  platforms, these directories are searched if the dependency is not found in
+  any of the other usual paths. If it is found in such a directory, a warning
+  is issued, because it means that the file is incomplete (it does not list all
+  of the directories that contain its dependencies.) On Windows platforms,
+  these directories are searched if the dependency is not found in any of the
+  other search paths, but no warning is issued, because searching other paths
+  is a normal part of Windows dependency resolution. On Apple platforms, this
+  argument has no effect.
+
+``BUNDLE_EXECTUBLE <bundle_executable_file>``
+  Executable to treat as the "bundle executable" when resolving libraries. On
+  Apple platforms, this argument determines the value of ``@executable_path``
+  when recursively resolving libraries for ``LIBRARIES`` and ``MODULES`` files.
+  It has no effect on ``EXECUTABLES`` files. On other platforms, it has no
+  effect. This is typically (but not always) one of the executables in the
+  ``EXECUTABLES`` argument which designates the "main" executable of the
+  package.
+
+The following arguments specify filters for including or excluding libraries to
+be resolved. See below for a full description of how they work.
+
+``PRE_INCLUDE_REGEXES <regexes>``
+  List of pre-include regexes through which to filter the names of
+  not-yet-resolved dependencies.
+
+``PRE_EXCLUDE_REGEXES <regexes>``
+  List of pre-exclude regexes through which to filter the names of
+  not-yet-resolved dependencies.
+
+``POST_INCLUDE_REGEXES <regexes>``
+  List of post-include regexes through which to filter the names of resolved
+  dependencies.
+
+``POST_EXCLUDE_REGEXES <regexes>``
+  List of post-exclude regexes through which to filter the names of resolved
+  dependencies.
+
+These arguments can be used to blacklist unwanted system libraries when
+resolving the dependencies, or to whitelist libraries from a specific
+directory. The filtering works as follows:
+
+1. If the not-yet-resolved dependency matches any of the
+   ``PRE_INCLUDE_REGEXES``, steps 2 and 3 are skipped, and the dependency
+   resolution proceeds to step 4.
+2. If the not-yet-resolved dependency matches any of the
+   ``PRE_EXCLUDE_REGEXES``, dependency resolution stops for that dependency.
+3. Otherwise, dependency resolution proceeds.
+4. ``file(GET_RUNTIME_DEPENDENCIES)`` searches for the dependency according to
+   the linking rules of the platform (see below).
+5. If the dependency is found, and its full path matches one of the
+   ``POST_INCLUDE_REGEXES``, the full path is added to the resolved
+   dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves
+   that library's own dependencies. Otherwise, resolution proceeds to step 6.
+6. If the dependency is found, but its full path matches one of the
+   ``POST_EXCLUDE_REGEXES``, it is not added to the resolved dependencies, and
+   dependency resolution stops for that dependency.
+7. If the dependency is found, and its full path does not match either
+   ``POST_INCLUDE_REGEXES`` or ``POST_EXCLUDE_REGEXES``, the full path is added
+   to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)``
+   recursively resolves that library's own dependencies.
+
+Different platforms have different rules for how dependencies are resolved.
+These specifics are described here.
+
+On Linux platforms, library resolution works as follows:
+
+1. If the depending file does not have any ``RUNPATH`` entries, and the library
+   exists in one of the depending file's ``RPATH`` entries, or its parents', in
+   that order, the dependency is resolved to that file.
+2. Otherwise, if the depending file has any ``RUNPATH`` entries, and the
+   library exists in one of those entries, the dependency is resolved to that
+   file.
+3. Otherwise, if the library exists in one of the directories listed by
+   ``ldconfig``, the dependency is resolved to that file.
+4. Otherwise, if the library exists in one of the ``DIRECTORIES`` entries, the
+   dependency is resolved to that file. In this case, a warning is issued,
+   because finding a file in one of the ``DIRECTORIES`` means that the
+   depending file is not complete (it does not list all the directories from
+   which it pulls dependencies.)
+5. Otherwise, the dependency is unresolved.
+
+On Windows platforms, library resolution works as follows:
+
+1. The dependent DLL name is converted to lowercase. Windows DLL names are
+   case-insensitive, and some linkers mangle the case of the DLL dependency
+   names. However, this makes it more difficult for ``PRE_INCLUDE_REGEXES``,
+   ``PRE_EXCLUDE_REGEXES``, ``POST_INCLUDE_REGEXES``, and
+   ``POST_EXCLUDE_REGEXES`` to properly filter DLL names - every regex would
+   have to check for both uppercase and lowercase letters. For example:
+
+   .. code-block:: cmake
+
+     file(GET_RUNTIME_DEPENDENCIES
+       # ...
+       PRE_INCLUDE_REGEXES "^[Mm][Yy][Ll][Ii][Bb][Rr][Aa][Rr][Yy]\\.[Dd][Ll][Ll]$"
+       )
+
+   Converting the DLL name to lowercase allows the regexes to only match
+   lowercase names, thus simplifying the regex. For example:
+
+   .. code-block:: cmake
+
+     file(GET_RUNTIME_DEPENDENCIES
+       # ...
+       PRE_INCLUDE_REGEXES "^mylibrary\\.dll$"
+       )
+
+   This regex will match ``mylibrary.dll`` regardless of how it is cased,
+   either on disk or in the depending file. (For example, it will match
+   ``mylibrary.dll``, ``MyLibrary.dll``, and ``MYLIBRARY.DLL``.)
+
+   Please note that the directory portion of any resolved DLLs retains its
+   casing and is not converted to lowercase. Only the filename portion is
+   converted.
+
+2. (**Not yet implemented**) If the depending file is a Windows Store app, and
+   the dependency is listed as a dependency in the application's package
+   manifest, the dependency is resolved to that file.
+3. Otherwise, if the library exists in the same directory as the depending
+   file, the dependency is resolved to that file.
+4. Otherwise, if the library exists in either the operating system's
+   ``system32`` directory or the ``Windows`` directory, in that order, the
+   dependency is resolved to that file.
+5. Otherwise, if the library exists in one of the directories specified by
+   ``DIRECTORIES``, in the order they are listed, the dependency is resolved to
+   that file. (In this case, a warning is not issued, because searching other
+   directories is a normal part of Windows library resolution.)
+6. Otherwise, the dependency is unresolved.
+
+On Apple platforms, library resolution works as follows:
+
+1. If the dependency starts with ``@executable_path/``, and an ``EXECUTABLES``
+   argument is in the process of being resolved, and replacing
+   ``@executable_path/`` with the directory of the executable yields an
+   existing file, the dependency is resolved to that file.
+2. Otherwise, if the dependency starts with ``@executable_path/``, and there is
+   a ``BUNDLE_EXECUTABLE`` argument, and replacing ``@executable_path/`` with
+   the directory of the bundle executable yields an existing file, the
+   dependency is resolved to that file.
+3. Otherwise, if the dependency starts with ``@loader_path/``, and replacing
+   ``@loader_path/`` with the directory of the depending file yields an
+   existing file, the dependency is resolved to that file.
+4. Otherwise, if the dependency starts with ``@rpath/``, and replacing
+   ``@rpath/`` with one of the ``RPATH`` entries of the depending file yields
+   an existing file, the dependency is resolved to that file. (Note that
+   ``RPATH`` entries that start with ``@executable_path/`` or ``@loader_path/``
+   also have these items replaced with the appropriate path.)
+5. Otherwise, if the dependency is an absolute file that exists, the dependency
+   is resolved to that file.
+6. Otherwise, the dependency is unresolved.
+
+This function accepts several variables that determine which tool is used for
+dependency resolution:
+
+.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM
+
+  Determines which operating system and executable format the files are built
+  for. This could be one of several values:
+
+  * ``linux+elf``
+  * ``windows+pe``
+  * ``macos+macho``
+
+  If this variable is not specified, it is determined automatically by system
+  introspection.
+
+.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL
+
+  Determines the tool to use for dependency resolution. It could be one of
+  several values, depending on the value of
+  :variable:`CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`:
+
+  ================================================= =============================================
+     ``CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM``       ``CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL``
+  ================================================= =============================================
+  ``linux+elf``                                     ``objdump``
+  ``windows+pe``                                    ``dumpbin``
+  ``windows+pe``                                    ``objdump``
+  ``macos+macho``                                   ``otool``
+  ================================================= =============================================
+
+  If this variable is not specified, it is determined automatically by system
+  introspection.
+
+.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND
+
+  Determines the path to the tool to use for dependency resolution. This is the
+  actual path to ``objdump``, ``dumpbin``, or ``otool``.
+
+  If this variable is not specified, it is determined automatically by system
+  introspection.
+
 Writing
 ^^^^^^^
 
@@ -235,6 +503,11 @@
 specified, the results will be returned as relative paths to the given
 path.  The results will be ordered lexicographically.
 
+On Windows and macOS, globbing is case-insensitive even if the underlying
+filesystem is case-sensitive (both filenames and globbing expressions are
+converted to lowercase before matching).  On other platforms, globbing is
+case-sensitive.
+
 If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic
 to the main build system check target to rerun the flagged ``GLOB`` commands
 at build time. If any of the outputs change, CMake will regenerate the build
diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst
index 2a14ad7..3f03f37 100644
--- a/Help/command/find_file.rst
+++ b/Help/command/find_file.rst
@@ -17,11 +17,10 @@
 .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_INCLUDE_PATH`
 .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH`
 
-.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in ``INCLUDE``.
-   On Windows hosts:
-   ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
-   is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, and the
-   directories in ``PATH`` itself.
+.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` and ``INCLUDE``.
+.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts:
+      ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+      is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|.
 
 .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace::
    ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst
index 0861d67..8a55aca 100644
--- a/Help/command/find_library.rst
+++ b/Help/command/find_library.rst
@@ -17,11 +17,10 @@
 .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_LIBRARY_PATH`
 .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH`
 
-.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in ``LIB``.
-   On Windows hosts:
-   ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
-   and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|,
-   and the directories in ``PATH`` itself.
+.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` and ``INCLUDE``.
+.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts:
+      ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+      is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|.
 
 .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace::
    ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index e5e5b2c..2186bd8 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -293,13 +293,15 @@
    The package root variables are maintained as a stack so if
    called from within a find module, root paths from the parent's find
    module will also be searched after paths for the current package.
-   This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+   This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting
+   the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``.
    See policy :policy:`CMP0074`.
 
 2. Search paths specified in cmake-specific cache variables.  These
    are intended to be used on the command line with a ``-DVAR=value``.
    The values are interpreted as :ref:`semicolon-separated lists <CMake Language Lists>`.
-   This can be skipped if ``NO_CMAKE_PATH`` is passed::
+   This can be skipped if ``NO_CMAKE_PATH`` is passed or by setting the
+   :variable:`CMAKE_FIND_USE_CMAKE_PATH` to ``FALSE``::
 
      CMAKE_PREFIX_PATH
      CMAKE_FRAMEWORK_PATH
@@ -309,7 +311,8 @@
    These are intended to be set in the user's shell configuration,
    and therefore use the host's native path separator
    (``;`` on Windows and ``:`` on UNIX).
-   This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed::
+   This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed or by setting
+   the :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH` to ``FALSE``::
 
      <PackageName>_DIR
      CMAKE_PREFIX_PATH
@@ -322,7 +325,8 @@
    be specified with the ``PATHS`` option.
 
 5. Search the standard system environment variables.  This can be
-   skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed.  Path entries
+   skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed  or by setting the
+   :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH` to ``FALSE``. Path entries
    ending in ``/bin`` or ``/sbin`` are automatically converted to their
    parent directories::
 
@@ -330,14 +334,17 @@
 
 6. Search paths stored in the CMake :ref:`User Package Registry`.
    This can be skipped if ``NO_CMAKE_PACKAGE_REGISTRY`` is passed or by
-   setting the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`
-   to ``TRUE``.
+   setting the variable :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`
+   to ``FALSE`` or the deprecated variable
+   :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` to ``TRUE``.
+
    See the :manual:`cmake-packages(7)` manual for details on the user
    package registry.
 
 7. Search cmake variables defined in the Platform files for the
    current system.  This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is
-   passed::
+   passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`
+   to ``FALSE``::
 
      CMAKE_SYSTEM_PREFIX_PATH
      CMAKE_SYSTEM_FRAMEWORK_PATH
diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst
index 988a3fa..52ffe3c 100644
--- a/Help/command/find_path.rst
+++ b/Help/command/find_path.rst
@@ -17,11 +17,10 @@
 .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_INCLUDE_PATH`
 .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH`
 
-.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in ``INCLUDE``.
-   On Windows hosts:
-   ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
-   is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, and the
-   directories in ``PATH`` itself.
+.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` and ``INCLUDE``.
+.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts:
+      ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+      is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|.
 
 .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace::
    ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst
index 4f00773..e2ff693 100644
--- a/Help/command/find_program.rst
+++ b/Help/command/find_program.rst
@@ -15,7 +15,8 @@
 .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_PROGRAM_PATH`
 .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_APPBUNDLE_PATH`
 
-.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: ``PATH``
+.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` itself.
+.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts no extra search paths are included
 
 .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace::
    |CMAKE_SYSTEM_PREFIX_PATH_XXX_SUBDIR|
diff --git a/Help/command/install.rst b/Help/command/install.rst
index ab6fef6..5affc5b 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -126,6 +126,8 @@
   marked with the ``FRAMEWORK`` property on macOS (see ``FRAMEWORK``
   below.) For DLL platforms (all Windows-based systems including
   Cygwin), the DLL import library is treated as an ``ARCHIVE`` target.
+  On AIX, the linker import file created for executables with
+  :prop_tgt:`ENABLE_EXPORTS` is treated as an ``ARCHIVE`` target.
 
 ``LIBRARY``
   Module libraries are always treated as ``LIBRARY`` targets. For non-
diff --git a/Help/command/message.rst b/Help/command/message.rst
index 5dca6b4..3002842 100644
--- a/Help/command/message.rst
+++ b/Help/command/message.rst
@@ -60,6 +60,11 @@
 interactive pop-up box.  The ``--loglevel`` command-line option to each of
 these tools can be used to control which messages will be shown.
 
+Messages of log levels ``NOTICE`` and below will also have each line preceded
+by the content of the :variable:`CMAKE_MESSAGE_INDENT` variable (converted to
+a single string by concatenating its list items).  For ``STATUS`` to ``TRACE``
+messages, this indenting content will be inserted after the hyphens.
+
 CMake Warning and Error message text displays using a simple markup
 language.  Non-indented text is formatted in line-wrapped paragraphs
 delimited by newlines.  Indented text is considered pre-formatted.
diff --git a/Help/command/string.rst b/Help/command/string.rst
index 2e89d7b..81a2061 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -22,8 +22,8 @@
     string(`PREPEND`_ <string-var> [<input>...])
     string(`CONCAT`_ <out-var> [<input>...])
     string(`JOIN`_ <glue> <out-var> [<input>...])
-    string(`TOLOWER`_ <string1> <out-var>)
-    string(`TOUPPER`_ <string1> <out-var>)
+    string(`TOLOWER`_ <string> <out-var>)
+    string(`TOUPPER`_ <string> <out-var>)
     string(`LENGTH`_ <string> <out-var>)
     string(`SUBSTRING`_ <string> <begin> <length> <out-var>)
     string(`STRIP`_ <string> <out-var>)
@@ -38,7 +38,7 @@
 
   `Generation`_
     string(`ASCII`_ <number>... <out-var>)
-    string(`CONFIGURE`_ <string1> <out-var> [...])
+    string(`CONFIGURE`_ <string> <out-var> [...])
     string(`MAKE_C_IDENTIFIER`_ <string> <out-var>)
     string(`RANDOM`_ [<option>...] <out-var>)
     string(`TIMESTAMP`_ <out-var> [<format string>] [UTC])
@@ -51,23 +51,28 @@
 
 .. code-block:: cmake
 
-  string(FIND <string> <substring> <output variable> [REVERSE])
+  string(FIND <string> <substring> <output_variable> [REVERSE])
 
-Return the position where the given substring was found in
-the supplied string.  If the ``REVERSE`` flag was used, the command will
+Return the position where the given ``<substring>`` was found in
+the supplied ``<string>``.  If the ``REVERSE`` flag was used, the command will
 search for the position of the last occurrence of the specified
-substring.  If the substring is not found, a position of -1 is returned.
+``<substring>``.  If the ``<substring>`` is not found, a position of -1 is
+returned.
+
+The ``string(FIND)`` subcommand treats all strings as ASCII-only characters.
+The index stored in ``<output_variable>`` will also be counted in bytes,
+so strings containing multi-byte characters may lead to unexpected results.
 
 .. _REPLACE:
 
 .. code-block:: cmake
 
   string(REPLACE <match_string>
-         <replace_string> <output variable>
+         <replace_string> <output_variable>
          <input> [<input>...])
 
-Replace all occurrences of ``match_string`` in the input
-with ``replace_string`` and store the result in the output.
+Replace all occurrences of ``<match_string>`` in the ``<input>``
+with ``<replace_string>`` and store the result in the ``<output_variable>``.
 
 Regular Expressions
 ^^^^^^^^^^^^^^^^^^^
@@ -77,9 +82,10 @@
 .. code-block:: cmake
 
   string(REGEX MATCH <regular_expression>
-         <output variable> <input> [<input>...])
+         <output_variable> <input> [<input>...])
 
-Match the regular expression once and store the match in the output variable.
+Match the ``<regular_expression>`` once and store the match in the
+``<output_variable>``.
 All ``<input>`` arguments are concatenated before matching.
 
 .. _`REGEX MATCHALL`:
@@ -87,10 +93,10 @@
 .. code-block:: cmake
 
   string(REGEX MATCHALL <regular_expression>
-         <output variable> <input> [<input>...])
+         <output_variable> <input> [<input>...])
 
-Match the regular expression as many times as possible and store the matches
-in the output variable as a list.
+Match the ``<regular_expression>`` as many times as possible and store the
+matches in the ``<output_variable>`` as a list.
 All ``<input>`` arguments are concatenated before matching.
 
 .. _`REGEX REPLACE`:
@@ -98,16 +104,17 @@
 .. code-block:: cmake
 
   string(REGEX REPLACE <regular_expression>
-         <replace_expression> <output variable>
+         <replacement_expression> <output_variable>
          <input> [<input>...])
 
-Match the regular expression as many times as possible and substitute the
-replacement expression for the match in the output.
+Match the ``<regular_expression>`` as many times as possible and substitute
+the ``<replacement_expression>`` for the match in the output.
 All ``<input>`` arguments are concatenated before matching.
 
-The replace expression may refer to paren-delimited subexpressions of the
-match using ``\1``, ``\2``, ..., ``\9``.  Note that two backslashes (``\\1``)
-are required in CMake code to get a backslash through argument parsing.
+The ``<replacement_expression>`` may refer to parenthesis-delimited
+subexpressions of the match using ``\1``, ``\2``, ..., ``\9``.  Note that
+two backslashes (``\\1``) are required in CMake code to get a backslash
+through argument parsing.
 
 .. _`Regex Specification`:
 
@@ -180,103 +187,109 @@
 
 .. code-block:: cmake
 
-  string(APPEND <string variable> [<input>...])
+  string(APPEND <string_variable> [<input>...])
 
-Append all the input arguments to the string.
+Append all the ``<input>`` arguments to the string.
 
 .. _PREPEND:
 
 .. code-block:: cmake
 
-  string(PREPEND <string variable> [<input>...])
+  string(PREPEND <string_variable> [<input>...])
 
-Prepend all the input arguments to the string.
+Prepend all the ``<input>`` arguments to the string.
 
 .. _CONCAT:
 
 .. code-block:: cmake
 
-  string(CONCAT <output variable> [<input>...])
+  string(CONCAT <output_variable> [<input>...])
 
-Concatenate all the input arguments together and store
-the result in the named output variable.
+Concatenate all the ``<input>`` arguments together and store
+the result in the named ``<output_variable>``.
 
 .. _JOIN:
 
 .. code-block:: cmake
 
-  string(JOIN <glue> <output variable> [<input>...])
+  string(JOIN <glue> <output_variable> [<input>...])
 
-Join all the input arguments together using the glue
-string and store the result in the named output variable.
+Join all the ``<input>`` arguments together using the ``<glue>``
+string and store the result in the named ``<output_variable>``.
 
-To join list's elements, use preferably the ``JOIN`` operator
-from :command:`list` command. This allows for the elements to have
+To join a list's elements, prefer to use the ``JOIN`` operator
+from the :command:`list` command.  This allows for the elements to have
 special characters like ``;`` in them.
 
 .. _TOLOWER:
 
 .. code-block:: cmake
 
-  string(TOLOWER <string1> <output variable>)
+  string(TOLOWER <string> <output_variable>)
 
-Convert string to lower characters.
+Convert ``<string>`` to lower characters.
 
 .. _TOUPPER:
 
 .. code-block:: cmake
 
-  string(TOUPPER <string1> <output variable>)
+  string(TOUPPER <string> <output_variable>)
 
-Convert string to upper characters.
+Convert ``<string>`` to upper characters.
 
 .. _LENGTH:
 
 .. code-block:: cmake
 
-  string(LENGTH <string> <output variable>)
+  string(LENGTH <string> <output_variable>)
 
-Store in an output variable a given string's length.
+Store in an ``<output_variable>`` a given string's length in bytes.
+Note that this means if ``<string>`` contains multi-byte characters, the
+result stored in ``<output_variable>`` will *not* be the number of characters.
 
 .. _SUBSTRING:
 
 .. code-block:: cmake
 
-  string(SUBSTRING <string> <begin> <length> <output variable>)
+  string(SUBSTRING <string> <begin> <length> <output_variable>)
 
-Store in an output variable a substring of a given string.  If length is
-``-1`` the remainder of the string starting at begin will be returned.
-If string is shorter than length then end of string is used instead.
+Store in an ``<output_variable>`` a substring of a given ``<string>``.  If
+``<length>`` is ``-1`` the remainder of the string starting at ``<begin>``
+will be returned.  If ``<string>`` is shorter than ``<length>`` then the
+end of the string is used instead.
+
+Both ``<begin>`` and ``<length>`` are counted in bytes, so care must
+be exercised if ``<string>`` could contain multi-byte characters.
 
 .. note::
-  CMake 3.1 and below reported an error if length pointed past
-  the end of string.
+  CMake 3.1 and below reported an error if ``<length>`` pointed past
+  the end of ``<string>``.
 
 .. _STRIP:
 
 .. code-block:: cmake
 
-  string(STRIP <string> <output variable>)
+  string(STRIP <string> <output_variable>)
 
-Store in an output variable a substring of a given string with leading and
-trailing spaces removed.
+Store in an ``<output_variable>`` a substring of a given ``<string>`` with
+leading and trailing spaces removed.
 
 .. _GENEX_STRIP:
 
 .. code-block:: cmake
 
-  string(GENEX_STRIP <input string> <output variable>)
+  string(GENEX_STRIP <string> <output_variable>)
 
 Strip any :manual:`generator expressions <cmake-generator-expressions(7)>`
-from the ``input string`` and store the result in the ``output variable``.
+from the input ``<string>`` and store the result in the ``<output_variable>``.
 
 .. _REPEAT:
 
 .. code-block:: cmake
 
-  string(REPEAT <input string> <count> <output variable>)
+  string(REPEAT <string> <count> <output_variable>)
 
-Produce the output string as repetion of ``input string`` ``count`` times.
+Produce the output string as the input ``<string>`` repeated ``<count>`` times.
 
 Comparison
 ^^^^^^^^^^
@@ -285,14 +298,14 @@
 
 .. code-block:: cmake
 
-  string(COMPARE LESS <string1> <string2> <output variable>)
-  string(COMPARE GREATER <string1> <string2> <output variable>)
-  string(COMPARE EQUAL <string1> <string2> <output variable>)
-  string(COMPARE NOTEQUAL <string1> <string2> <output variable>)
-  string(COMPARE LESS_EQUAL <string1> <string2> <output variable>)
-  string(COMPARE GREATER_EQUAL <string1> <string2> <output variable>)
+  string(COMPARE LESS <string1> <string2> <output_variable>)
+  string(COMPARE GREATER <string1> <string2> <output_variable>)
+  string(COMPARE EQUAL <string1> <string2> <output_variable>)
+  string(COMPARE NOTEQUAL <string1> <string2> <output_variable>)
+  string(COMPARE LESS_EQUAL <string1> <string2> <output_variable>)
+  string(COMPARE GREATER_EQUAL <string1> <string2> <output_variable>)
 
-Compare the strings and store true or false in the output variable.
+Compare the strings and store true or false in the ``<output_variable>``.
 
 .. _`Supported Hash Algorithms`:
 
@@ -303,9 +316,9 @@
 
 .. code-block:: cmake
 
-  string(<HASH> <output variable> <input>)
+  string(<HASH> <output_variable> <input>)
 
-Compute a cryptographic hash of the input string.
+Compute a cryptographic hash of the ``<input>`` string.
 The supported ``<HASH>`` algorithm names are:
 
 ``MD5``
@@ -336,7 +349,7 @@
 
 .. code-block:: cmake
 
-  string(ASCII <number> [<number> ...] <output variable>)
+  string(ASCII <number> [<number> ...] <output_variable>)
 
 Convert all numbers into corresponding ASCII characters.
 
@@ -344,31 +357,31 @@
 
 .. code-block:: cmake
 
-  string(CONFIGURE <string1> <output variable>
+  string(CONFIGURE <string> <output_variable>
          [@ONLY] [ESCAPE_QUOTES])
 
-Transform a string like :command:`configure_file` transforms a file.
+Transform a ``<string>`` like :command:`configure_file` transforms a file.
 
 .. _MAKE_C_IDENTIFIER:
 
 .. code-block:: cmake
 
-  string(MAKE_C_IDENTIFIER <input string> <output variable>)
+  string(MAKE_C_IDENTIFIER <string> <output_variable>)
 
-Convert each non-alphanumeric character in the ``<input string>`` to an
-underscore and store the result in the ``<output variable>``.  If the first
-character of the string is a digit, an underscore will also be prepended to
-the result.
+Convert each non-alphanumeric character in the input ``<string>`` to an
+underscore and store the result in the ``<output_variable>``.  If the first
+character of the ``<string>`` is a digit, an underscore will also be prepended
+to the result.
 
 .. _RANDOM:
 
 .. code-block:: cmake
 
   string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]
-         [RANDOM_SEED <seed>] <output variable>)
+         [RANDOM_SEED <seed>] <output_variable>)
 
-Return a random string of given length consisting of
-characters from the given alphabet.  Default length is 5 characters
+Return a random string of given ``<length>`` consisting of
+characters from the given ``<alphabet>``.  Default length is 5 characters
 and default alphabet is all numbers and upper and lower case letters.
 If an integer ``RANDOM_SEED`` is given, its value will be used to seed the
 random number generator.
@@ -377,18 +390,18 @@
 
 .. code-block:: cmake
 
-  string(TIMESTAMP <output variable> [<format string>] [UTC])
+  string(TIMESTAMP <output_variable> [<format_string>] [UTC])
 
 Write a string representation of the current date
-and/or time to the output variable.
+and/or time to the ``<output_variable>``.
 
-Should the command be unable to obtain a timestamp the output variable
-will be set to the empty string "".
+If the command is unable to obtain a timestamp, the ``<output_variable>``
+will be set to the empty string ``""``.
 
 The optional ``UTC`` flag requests the current date/time representation to
 be in Coordinated Universal Time (UTC) rather than local time.
 
-The optional ``<format string>`` may contain the following format
+The optional ``<format_string>`` may contain the following format
 specifiers:
 
 ::
@@ -415,7 +428,7 @@
 Unknown format specifiers will be ignored and copied to the output
 as-is.
 
-If no explicit ``<format string>`` is given it will default to:
+If no explicit ``<format_string>`` is given, it will default to:
 
 ::
 
@@ -432,7 +445,7 @@
 
 .. code-block:: cmake
 
-  string(UUID <output variable> NAMESPACE <namespace> NAME <name>
+  string(UUID <output_variable> NAMESPACE <namespace> NAME <name>
          TYPE <MD5|SHA1> [UPPER])
 
 Create a universally unique identifier (aka GUID) as per RFC4122
@@ -441,6 +454,6 @@
 The hash algorithm can be either ``MD5`` (Version 3 UUID) or
 ``SHA1`` (Version 5 UUID).
 A UUID has the format ``xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx``
-where each `x` represents a lower case hexadecimal character.
-Where required an uppercase representation can be requested
+where each ``x`` represents a lower case hexadecimal character.
+Where required, an uppercase representation can be requested
 with the optional ``UPPER`` flag.
diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst
index 1153a09..37a1d3a 100644
--- a/Help/dev/maint.rst
+++ b/Help/dev/maint.rst
@@ -92,6 +92,45 @@
 .. _`CMake Review Process`: review.rst
 .. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake
 
+Create Release Version
+======================
+
+When the ``release`` branch is ready to create a new release, follow the
+steps in the above `Maintain Current Release`_ section to checkout a local
+``release-$ver`` branch, where ``$ver`` is the version number of the
+current release in the form ``$major.$minor``.
+
+Edit ``Source/CMakeVersion.cmake`` to set the full version:
+
+.. code-block:: cmake
+
+  # CMake version number components.
+  set(CMake_VERSION_MAJOR $major)
+  set(CMake_VERSION_MINOR $minor)
+  set(CMake_VERSION_PATCH $patch)
+  #set(CMake_VERSION_RC $rc) # uncomment for release candidates
+
+In the following we use the placeholder ``$fullver`` for the full version
+number of the new release with the form ``$major.$minor.$patch[-rc$rc]``.
+If the version is not a release candidate, comment out the RC version
+component above and leave off the ``-rc$rc`` suffix from ``$fullver``.
+
+Commit the release version with the **exact** message ``CMake $fullver``:
+
+.. code-block:: shell
+
+  git commit -m "CMake $fullver"
+
+Tag the release using an annotated tag with the same message as the
+commit and named with the **exact** form ``v$fullver``:
+
+.. code-block:: shell
+
+  git tag -s -m "CMake $fullver" "v$fullver"
+
+Follow the steps in the above `Maintain Current Release`_ section to
+merge the ``release-$ver`` branch into ``master`` and publish both.
+
 Branch a New Release
 ====================
 
@@ -178,7 +217,7 @@
   the CMake Release Notes index page.
 
 Update ``Source/CMakeVersion.cmake`` to set the version to
-``$major.$minor.0-rc1``:
+``$major.$minor.0-rc0``:
 
 .. code-block:: cmake
 
@@ -186,7 +225,7 @@
   set(CMake_VERSION_MAJOR $major)
   set(CMake_VERSION_MINOR $minor)
   set(CMake_VERSION_PATCH 0)
-  set(CMake_VERSION_RC 1)
+  set(CMake_VERSION_RC 0)
 
 Update uses of ``DEVEL_CMAKE_VERSION`` in the source tree to mention the
 actual version number:
@@ -197,7 +236,7 @@
 
 Commit with a message such as::
 
-  CMake $major.$minor.0-rc1 version update
+  Begin $ver release versioning
 
 Merge the ``release-$ver`` branch to ``master``:
 
@@ -225,7 +264,7 @@
   set(CMake_VERSION_MAJOR $major)
   set(CMake_VERSION_MINOR $minor)
   set(CMake_VERSION_PATCH $date)
-  #set(CMake_VERSION_RC 1)
+  #set(CMake_VERSION_RC 0)
 
 Commit with a message such as::
 
diff --git a/Tests/Tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt
similarity index 85%
copy from Tests/Tutorial/Complete/CMakeLists.txt
copy to Help/guide/tutorial/Complete/CMakeLists.txt
index 9658e65..4541392 100644
--- a/Tests/Tutorial/Complete/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/CMakeLists.txt
@@ -1,21 +1,30 @@
-cmake_minimum_required(VERSION 3.3)
+cmake_minimum_required(VERSION 3.15)
 project(Tutorial)
 
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+  "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+  "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
+
+# set the version number
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
 # control where the static and shared libraries are built so that on windows
 # we don't need to tinker with the path to run the executable
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-
 option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
 
-# the version number.
-set(Tutorial_VERSION_MAJOR 1)
-set(Tutorial_VERSION_MINOR 0)
-
 if(APPLE)
   set(CMAKE_INSTALL_RPATH "@executable_path/../lib")
 elseif(UNIX)
diff --git a/Tests/Tutorial/Complete/Config.cmake.in b/Help/guide/tutorial/Complete/Config.cmake.in
similarity index 100%
rename from Tests/Tutorial/Complete/Config.cmake.in
rename to Help/guide/tutorial/Complete/Config.cmake.in
diff --git a/Tests/Tutorial/Complete/License.txt b/Help/guide/tutorial/Complete/License.txt
similarity index 100%
rename from Tests/Tutorial/Complete/License.txt
rename to Help/guide/tutorial/Complete/License.txt
diff --git a/Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
similarity index 81%
rename from Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
index 161ad64..c12955d 100644
--- a/Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
@@ -1,4 +1,3 @@
-
 # add the library that runs
 add_library(MathFunctions MathFunctions.cxx)
 
@@ -22,6 +21,7 @@
 
   # first we add the executable that generates the table
   add_executable(MakeTable MakeTable.cxx)
+  target_link_libraries(MakeTable tutorial_compiler_flags)
 
   # add the command to generate the source code
   add_custom_command(
@@ -45,14 +45,18 @@
                         POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
                         )
 
-  target_compile_definitions(SqrtLibrary PRIVATE
-                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
-                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
-                             )
+  target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
+
+
+  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
+  if(HAVE_LOG AND HAVE_EXP)
+    target_compile_definitions(SqrtLibrary
+                               PRIVATE "HAVE_LOG" "HAVE_EXP")
+  endif()
   target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
 endif()
 
-target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
+target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
 
 # define the symbol stating we are using the declspec(dllexport) when
 # building on windows
@@ -62,7 +66,8 @@
 set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
 set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
 
-install(TARGETS MathFunctions
+# install rules
+install(TARGETS MathFunctions tutorial_compiler_flags
         DESTINATION lib
         EXPORT MathFunctionsTargets)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Complete/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Complete/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx
similarity index 100%
rename from Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx
rename to Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx
diff --git a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Complete/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Complete/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Complete/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Complete/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Complete/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Complete/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Complete/MathFunctions/mysqrt.h b/Help/guide/tutorial/Complete/MathFunctions/mysqrt.h
similarity index 100%
rename from Tests/Tutorial/Complete/MathFunctions/mysqrt.h
rename to Help/guide/tutorial/Complete/MathFunctions/mysqrt.h
diff --git a/Tests/Tutorial/Complete/TutorialConfig.h.in b/Help/guide/tutorial/Complete/TutorialConfig.h.in
similarity index 100%
rename from Tests/Tutorial/Complete/TutorialConfig.h.in
rename to Help/guide/tutorial/Complete/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Complete/tutorial.cxx b/Help/guide/tutorial/Complete/tutorial.cxx
similarity index 91%
rename from Tests/Tutorial/Complete/tutorial.cxx
rename to Help/guide/tutorial/Complete/tutorial.cxx
index 443d195..4451cbd 100644
--- a/Tests/Tutorial/Complete/tutorial.cxx
+++ b/Help/guide/tutorial/Complete/tutorial.cxx
@@ -10,7 +10,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Consumer/CMakeLists.txt b/Help/guide/tutorial/Consumer/CMakeLists.txt
similarity index 100%
rename from Tests/Tutorial/Consumer/CMakeLists.txt
rename to Help/guide/tutorial/Consumer/CMakeLists.txt
diff --git a/Tests/Tutorial/Consumer/Config.cmake.in b/Help/guide/tutorial/Consumer/Config.cmake.in
similarity index 100%
rename from Tests/Tutorial/Consumer/Config.cmake.in
rename to Help/guide/tutorial/Consumer/Config.cmake.in
diff --git a/Tests/Tutorial/Consumer/consumer.cxx b/Help/guide/tutorial/Consumer/consumer.cxx
similarity index 100%
rename from Tests/Tutorial/Consumer/consumer.cxx
rename to Help/guide/tutorial/Consumer/consumer.cxx
diff --git a/Tests/Tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/MultiPackage/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Complete/CMakeLists.txt
rename to Help/guide/tutorial/MultiPackage/CMakeLists.txt
index 9658e65..bea611c 100644
--- a/Tests/Tutorial/Complete/CMakeLists.txt
+++ b/Help/guide/tutorial/MultiPackage/CMakeLists.txt
@@ -1,21 +1,21 @@
 cmake_minimum_required(VERSION 3.3)
 project(Tutorial)
 
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+# set the version number
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
 # control where the static and shared libraries are built so that on windows
 # we don't need to tinker with the path to run the executable
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-
 option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
 
-# the version number.
-set(Tutorial_VERSION_MAJOR 1)
-set(Tutorial_VERSION_MINOR 0)
-
 if(APPLE)
   set(CMAKE_INSTALL_RPATH "@executable_path/../lib")
 elseif(UNIX)
diff --git a/Tests/Tutorial/MultiPackage/Config.cmake.in b/Help/guide/tutorial/MultiPackage/Config.cmake.in
similarity index 100%
rename from Tests/Tutorial/MultiPackage/Config.cmake.in
rename to Help/guide/tutorial/MultiPackage/Config.cmake.in
diff --git a/Tests/Tutorial/MultiPackage/License.txt b/Help/guide/tutorial/MultiPackage/License.txt
similarity index 100%
rename from Tests/Tutorial/MultiPackage/License.txt
rename to Help/guide/tutorial/MultiPackage/License.txt
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/MultiPackage/MathFunctions/CMakeLists.txt
similarity index 99%
rename from Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/MultiPackage/MathFunctions/CMakeLists.txt
index 161ad64..63c0f5f 100644
--- a/Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/MultiPackage/MathFunctions/CMakeLists.txt
@@ -1,4 +1,3 @@
-
 # add the library that runs
 add_library(MathFunctions MathFunctions.cxx)
 
@@ -62,6 +61,7 @@
 set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
 set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
 
+# install rules
 install(TARGETS MathFunctions
         DESTINATION lib
         EXPORT MathFunctionsTargets)
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/MultiPackage/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/MultiPackage/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.cxx
similarity index 100%
rename from Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx
rename to Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.cxx
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h b/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h b/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.h
similarity index 100%
rename from Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h
rename to Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.h
diff --git a/Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake b/Help/guide/tutorial/MultiPackage/MultiCPackConfig.cmake
similarity index 100%
rename from Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake
rename to Help/guide/tutorial/MultiPackage/MultiCPackConfig.cmake
diff --git a/Tests/Tutorial/MultiPackage/TutorialConfig.h.in b/Help/guide/tutorial/MultiPackage/TutorialConfig.h.in
similarity index 100%
rename from Tests/Tutorial/MultiPackage/TutorialConfig.h.in
rename to Help/guide/tutorial/MultiPackage/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Complete/tutorial.cxx b/Help/guide/tutorial/MultiPackage/tutorial.cxx
similarity index 91%
copy from Tests/Tutorial/Complete/tutorial.cxx
copy to Help/guide/tutorial/MultiPackage/tutorial.cxx
index 443d195..4451cbd 100644
--- a/Tests/Tutorial/Complete/tutorial.cxx
+++ b/Help/guide/tutorial/MultiPackage/tutorial.cxx
@@ -10,7 +10,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step1/CMakeLists.txt b/Help/guide/tutorial/Step1/CMakeLists.txt
similarity index 100%
rename from Tests/Tutorial/Step1/CMakeLists.txt
rename to Help/guide/tutorial/Step1/CMakeLists.txt
diff --git a/Tests/Tutorial/Step1/TutorialConfig.h.in b/Help/guide/tutorial/Step1/TutorialConfig.h.in
similarity index 99%
rename from Tests/Tutorial/Step1/TutorialConfig.h.in
rename to Help/guide/tutorial/Step1/TutorialConfig.h.in
index 5395a06..7e4d7fa 100644
--- a/Tests/Tutorial/Step1/TutorialConfig.h.in
+++ b/Help/guide/tutorial/Step1/TutorialConfig.h.in
@@ -1,4 +1,3 @@
 // the configured options and settings for Tutorial
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-
diff --git a/Tests/Tutorial/Step1/tutorial.cxx b/Help/guide/tutorial/Step1/tutorial.cxx
similarity index 100%
rename from Tests/Tutorial/Step1/tutorial.cxx
rename to Help/guide/tutorial/Step1/tutorial.cxx
diff --git a/Tests/Tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step10/CMakeLists.txt
rename to Help/guide/tutorial/Step10/CMakeLists.txt
index b1d46c4..25bc0c1 100644
--- a/Tests/Tutorial/Step10/CMakeLists.txt
+++ b/Help/guide/tutorial/Step10/CMakeLists.txt
@@ -1,21 +1,21 @@
 cmake_minimum_required(VERSION 3.3)
 project(Tutorial)
 
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+# Set the version number
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
 # control where the static and shared libraries are built so that on windows
 # we don't need to tinker with the path to run the executable
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-
 option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
 
-# the version number.
-set(Tutorial_VERSION_MAJOR 1)
-set(Tutorial_VERSION_MINOR 0)
-
 # configure a header file to pass the version number only
 configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
diff --git a/Tests/Tutorial/Step10/License.txt b/Help/guide/tutorial/Step10/License.txt
similarity index 100%
rename from Tests/Tutorial/Step10/License.txt
rename to Help/guide/tutorial/Step10/License.txt
diff --git a/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
index 7a23505..aafd090 100644
--- a/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
@@ -1,4 +1,3 @@
-
 # add the library that runs
 add_library(MathFunctions MathFunctions.cxx)
 
@@ -57,5 +56,6 @@
 # building on windows
 target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
 
+# install rules
 install(TARGETS MathFunctions DESTINATION lib)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step10/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Step10/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx
similarity index 100%
rename from Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx
rename to Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx
diff --git a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step10/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step10/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.h
similarity index 100%
rename from Tests/Tutorial/Step10/MathFunctions/mysqrt.h
rename to Help/guide/tutorial/Step10/MathFunctions/mysqrt.h
diff --git a/Tests/Tutorial/Step10/TutorialConfig.h.in b/Help/guide/tutorial/Step10/TutorialConfig.h.in
similarity index 100%
rename from Tests/Tutorial/Step10/TutorialConfig.h.in
rename to Help/guide/tutorial/Step10/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Complete/tutorial.cxx b/Help/guide/tutorial/Step10/tutorial.cxx
similarity index 88%
copy from Tests/Tutorial/Complete/tutorial.cxx
copy to Help/guide/tutorial/Step10/tutorial.cxx
index 443d195..42eaab9 100644
--- a/Tests/Tutorial/Complete/tutorial.cxx
+++ b/Help/guide/tutorial/Step10/tutorial.cxx
@@ -9,8 +9,9 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt
similarity index 78%
copy from Tests/Tutorial/Step10/CMakeLists.txt
copy to Help/guide/tutorial/Step11/CMakeLists.txt
index b1d46c4..e54bdde 100644
--- a/Tests/Tutorial/Step10/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/CMakeLists.txt
@@ -1,21 +1,30 @@
-cmake_minimum_required(VERSION 3.3)
+cmake_minimum_required(VERSION 3.15)
 project(Tutorial)
 
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+  "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+  "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
+
+# set the version number
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
 # control where the static and shared libraries are built so that on windows
 # we don't need to tinker with the path to run the executable
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-
 option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
 
-# the version number.
-set(Tutorial_VERSION_MAJOR 1)
-set(Tutorial_VERSION_MINOR 0)
-
 # configure a header file to pass the version number only
 configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
diff --git a/Tests/Tutorial/Step11/License.txt b/Help/guide/tutorial/Step11/License.txt
similarity index 100%
rename from Tests/Tutorial/Step11/License.txt
rename to Help/guide/tutorial/Step11/License.txt
diff --git a/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
similarity index 89%
copy from Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt
copy to Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
index 7a23505..daaaa55 100644
--- a/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
@@ -1,4 +1,3 @@
-
 # add the library that runs
 add_library(MathFunctions MathFunctions.cxx)
 
@@ -20,6 +19,7 @@
 
   # first we add the executable that generates the table
   add_executable(MakeTable MakeTable.cxx)
+  target_link_libraries(MakeTable tutorial_compiler_flags)
 
   # add the command to generate the source code
   add_custom_command(
@@ -39,23 +39,26 @@
                              ${CMAKE_CURRENT_BINARY_DIR}
                              )
 
-  # state that SqrtLibrary need PIC when the default is shared libraries
   set_target_properties(SqrtLibrary PROPERTIES
                         POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
                         )
 
+  target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
+
   target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
   if(HAVE_LOG AND HAVE_EXP)
     target_compile_definitions(SqrtLibrary
                                PRIVATE "HAVE_LOG" "HAVE_EXP")
   endif()
-
   target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
 endif()
 
+target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
+
 # define the symbol stating we are using the declspec(dllexport) when
-# building on windows
+#building on windows
 target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
 
+# install rules
 install(TARGETS MathFunctions DESTINATION lib)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step11/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Step11/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx
similarity index 100%
rename from Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx
rename to Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx
diff --git a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step11/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step11/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step11/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step11/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step11/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step11/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step11/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step11/MathFunctions/mysqrt.h
similarity index 100%
rename from Tests/Tutorial/Step11/MathFunctions/mysqrt.h
rename to Help/guide/tutorial/Step11/MathFunctions/mysqrt.h
diff --git a/Tests/Tutorial/Step11/TutorialConfig.h.in b/Help/guide/tutorial/Step11/TutorialConfig.h.in
similarity index 100%
rename from Tests/Tutorial/Step11/TutorialConfig.h.in
rename to Help/guide/tutorial/Step11/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Step11/tutorial.cxx b/Help/guide/tutorial/Step11/tutorial.cxx
similarity index 88%
rename from Tests/Tutorial/Step11/tutorial.cxx
rename to Help/guide/tutorial/Step11/tutorial.cxx
index 3768855..6acafd2 100644
--- a/Tests/Tutorial/Step11/tutorial.cxx
+++ b/Help/guide/tutorial/Step11/tutorial.cxx
@@ -9,8 +9,9 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step2/CMakeLists.txt b/Help/guide/tutorial/Step2/CMakeLists.txt
similarity index 95%
rename from Tests/Tutorial/Step2/CMakeLists.txt
rename to Help/guide/tutorial/Step2/CMakeLists.txt
index 48afaa3..059b89a 100644
--- a/Tests/Tutorial/Step2/CMakeLists.txt
+++ b/Help/guide/tutorial/Step2/CMakeLists.txt
@@ -4,7 +4,7 @@
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED True)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
diff --git a/Tests/Tutorial/Step2/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt
similarity index 100%
rename from Tests/Tutorial/Step2/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt
diff --git a/Tests/Tutorial/Step2/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step2/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Help/guide/tutorial/Step2/TutorialConfig.h.in
similarity index 99%
rename from Tests/Tutorial/Step2/TutorialConfig.h.in
rename to Help/guide/tutorial/Step2/TutorialConfig.h.in
index 5395a06..7e4d7fa 100644
--- a/Tests/Tutorial/Step2/TutorialConfig.h.in
+++ b/Help/guide/tutorial/Step2/TutorialConfig.h.in
@@ -1,4 +1,3 @@
 // the configured options and settings for Tutorial
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-
diff --git a/Tests/Tutorial/Step2/tutorial.cxx b/Help/guide/tutorial/Step2/tutorial.cxx
similarity index 87%
rename from Tests/Tutorial/Step2/tutorial.cxx
rename to Help/guide/tutorial/Step2/tutorial.cxx
index 75b7d67..f2ab446 100644
--- a/Tests/Tutorial/Step2/tutorial.cxx
+++ b/Help/guide/tutorial/Step2/tutorial.cxx
@@ -8,8 +8,9 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step3/CMakeLists.txt b/Help/guide/tutorial/Step3/CMakeLists.txt
similarity index 97%
rename from Tests/Tutorial/Step3/CMakeLists.txt
rename to Help/guide/tutorial/Step3/CMakeLists.txt
index f904ea7..9804abf 100644
--- a/Tests/Tutorial/Step3/CMakeLists.txt
+++ b/Help/guide/tutorial/Step3/CMakeLists.txt
@@ -7,7 +7,7 @@
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
diff --git a/Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt
similarity index 100%
rename from Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt
diff --git a/Tests/Tutorial/Step3/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step3/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step3/TutorialConfig.h.in b/Help/guide/tutorial/Step3/TutorialConfig.h.in
similarity index 99%
rename from Tests/Tutorial/Step3/TutorialConfig.h.in
rename to Help/guide/tutorial/Step3/TutorialConfig.h.in
index 25a0602..e23f521 100644
--- a/Tests/Tutorial/Step3/TutorialConfig.h.in
+++ b/Help/guide/tutorial/Step3/TutorialConfig.h.in
@@ -2,4 +2,3 @@
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
 #cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step3/tutorial.cxx
similarity index 79%
rename from Tests/Tutorial/Step3/tutorial.cxx
rename to Help/guide/tutorial/Step3/tutorial.cxx
index 1d5742d..8156a9c 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Help/guide/tutorial/Step3/tutorial.cxx
@@ -5,6 +5,7 @@
 
 #include "TutorialConfig.h"
 
+// should we include the MathFunctions header?
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
 #endif
@@ -12,14 +13,16 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
   double inputValue = std::stod(argv[1]);
 
+  // which square root function should we use?
 #ifdef USE_MYMATH
   double outputValue = mysqrt(inputValue);
 #else
diff --git a/Tests/Tutorial/Step4/CMakeLists.txt b/Help/guide/tutorial/Step4/CMakeLists.txt
similarity index 97%
rename from Tests/Tutorial/Step4/CMakeLists.txt
rename to Help/guide/tutorial/Step4/CMakeLists.txt
index 34eab55..0ae2648 100644
--- a/Tests/Tutorial/Step4/CMakeLists.txt
+++ b/Help/guide/tutorial/Step4/CMakeLists.txt
@@ -7,7 +7,7 @@
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
diff --git a/Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt
similarity index 100%
rename from Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt
diff --git a/Tests/Tutorial/Step4/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step4/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step4/TutorialConfig.h.in b/Help/guide/tutorial/Step4/TutorialConfig.h.in
similarity index 99%
rename from Tests/Tutorial/Step4/TutorialConfig.h.in
rename to Help/guide/tutorial/Step4/TutorialConfig.h.in
index 25a0602..e23f521 100644
--- a/Tests/Tutorial/Step4/TutorialConfig.h.in
+++ b/Help/guide/tutorial/Step4/TutorialConfig.h.in
@@ -2,4 +2,3 @@
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
 #cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step4/tutorial.cxx
similarity index 79%
copy from Tests/Tutorial/Step3/tutorial.cxx
copy to Help/guide/tutorial/Step4/tutorial.cxx
index 1d5742d..8156a9c 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Help/guide/tutorial/Step4/tutorial.cxx
@@ -5,6 +5,7 @@
 
 #include "TutorialConfig.h"
 
+// should we include the MathFunctions header?
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
 #endif
@@ -12,14 +13,16 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
   double inputValue = std::stod(argv[1]);
 
+  // which square root function should we use?
 #ifdef USE_MYMATH
   double outputValue = mysqrt(inputValue);
 #else
diff --git a/Tests/Tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step5/CMakeLists.txt
rename to Help/guide/tutorial/Step5/CMakeLists.txt
index 63e5410..dac9b45 100644
--- a/Tests/Tutorial/Step5/CMakeLists.txt
+++ b/Help/guide/tutorial/Step5/CMakeLists.txt
@@ -7,7 +7,7 @@
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
diff --git a/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt
similarity index 95%
rename from Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt
index 11cf412..b12f27d 100644
--- a/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt
@@ -6,5 +6,6 @@
           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
           )
 
+# install rules
 install(TARGETS MathFunctions DESTINATION lib)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step5/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Step5/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Step5/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step5/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step5/TutorialConfig.h.in b/Help/guide/tutorial/Step5/TutorialConfig.h.in
similarity index 99%
rename from Tests/Tutorial/Step5/TutorialConfig.h.in
rename to Help/guide/tutorial/Step5/TutorialConfig.h.in
index 25a0602..e23f521 100644
--- a/Tests/Tutorial/Step5/TutorialConfig.h.in
+++ b/Help/guide/tutorial/Step5/TutorialConfig.h.in
@@ -2,4 +2,3 @@
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
 #cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step5/tutorial.cxx
similarity index 79%
copy from Tests/Tutorial/Step3/tutorial.cxx
copy to Help/guide/tutorial/Step5/tutorial.cxx
index 1d5742d..8156a9c 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Help/guide/tutorial/Step5/tutorial.cxx
@@ -5,6 +5,7 @@
 
 #include "TutorialConfig.h"
 
+// should we include the MathFunctions header?
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
 #endif
@@ -12,14 +13,16 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
   double inputValue = std::stod(argv[1]);
 
+  // which square root function should we use?
 #ifdef USE_MYMATH
   double outputValue = mysqrt(inputValue);
 #else
diff --git a/Tests/Tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step6/CMakeLists.txt
rename to Help/guide/tutorial/Step6/CMakeLists.txt
index 503a312..1465e46 100644
--- a/Tests/Tutorial/Step6/CMakeLists.txt
+++ b/Help/guide/tutorial/Step6/CMakeLists.txt
@@ -4,7 +4,7 @@
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED True)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
diff --git a/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
similarity index 96%
rename from Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
index 2946075..def1140 100644
--- a/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
@@ -4,11 +4,11 @@
 # to find MathFunctions.h, while we don't.
 # state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
 # TutorialConfig.h include is an implementation detail
-
 target_include_directories(MathFunctions
           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
           PRIVATE ${Tutorial_BINARY_DIR}
           )
 
+# install rules
 install(TARGETS MathFunctions DESTINATION lib)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Step6/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step6/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step8/TutorialConfig.h.in b/Help/guide/tutorial/Step6/TutorialConfig.h.in
similarity index 100%
copy from Tests/Tutorial/Step8/TutorialConfig.h.in
copy to Help/guide/tutorial/Step6/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step6/tutorial.cxx
similarity index 79%
copy from Tests/Tutorial/Step3/tutorial.cxx
copy to Help/guide/tutorial/Step6/tutorial.cxx
index 1d5742d..8156a9c 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Help/guide/tutorial/Step6/tutorial.cxx
@@ -5,6 +5,7 @@
 
 #include "TutorialConfig.h"
 
+// should we include the MathFunctions header?
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
 #endif
@@ -12,14 +13,16 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
   double inputValue = std::stod(argv[1]);
 
+  // which square root function should we use?
 #ifdef USE_MYMATH
   double outputValue = mysqrt(inputValue);
 #else
diff --git a/Tests/Tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step7/CMakeLists.txt
rename to Help/guide/tutorial/Step7/CMakeLists.txt
index f2d3839..a1efa77 100644
--- a/Tests/Tutorial/Step7/CMakeLists.txt
+++ b/Help/guide/tutorial/Step7/CMakeLists.txt
@@ -4,7 +4,7 @@
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED True)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
diff --git a/Tests/Tutorial/Step7/License.txt b/Help/guide/tutorial/Step7/License.txt
similarity index 100%
rename from Tests/Tutorial/Step7/License.txt
rename to Help/guide/tutorial/Step7/License.txt
diff --git a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
index dc3eb98..3c3a816 100644
--- a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
@@ -25,5 +25,6 @@
                   ${CMAKE_CURRENT_BINARY_DIR}
           )
 
+# install rules
 install(TARGETS MathFunctions DESTINATION lib)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Step7/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step7/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step8/TutorialConfig.h.in b/Help/guide/tutorial/Step7/TutorialConfig.h.in
similarity index 100%
copy from Tests/Tutorial/Step8/TutorialConfig.h.in
copy to Help/guide/tutorial/Step7/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step7/tutorial.cxx
similarity index 79%
copy from Tests/Tutorial/Step3/tutorial.cxx
copy to Help/guide/tutorial/Step7/tutorial.cxx
index 1d5742d..8156a9c 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Help/guide/tutorial/Step7/tutorial.cxx
@@ -5,6 +5,7 @@
 
 #include "TutorialConfig.h"
 
+// should we include the MathFunctions header?
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
 #endif
@@ -12,14 +13,16 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
   double inputValue = std::stod(argv[1]);
 
+  // which square root function should we use?
 #ifdef USE_MYMATH
   double outputValue = mysqrt(inputValue);
 #else
diff --git a/Tests/Tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt
similarity index 97%
rename from Tests/Tutorial/Step8/CMakeLists.txt
rename to Help/guide/tutorial/Step8/CMakeLists.txt
index c66bf96..a0316a0 100644
--- a/Tests/Tutorial/Step8/CMakeLists.txt
+++ b/Help/guide/tutorial/Step8/CMakeLists.txt
@@ -4,7 +4,7 @@
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED True)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
@@ -75,6 +75,7 @@
 do_test(Tutorial -25 "-25 is [-nan|nan|0]")
 do_test(Tutorial 0.0001 "0.0001 is 0.01")
 
+# setup installer
 include(InstallRequiredSystemLibraries)
 set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
 set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
diff --git a/Tests/Tutorial/Step8/License.txt b/Help/guide/tutorial/Step8/License.txt
similarity index 100%
rename from Tests/Tutorial/Step8/License.txt
rename to Help/guide/tutorial/Step8/License.txt
diff --git a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt
similarity index 98%
copy from Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt
copy to Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt
index dc3eb98..3c3a816 100644
--- a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt
@@ -25,5 +25,6 @@
                   ${CMAKE_CURRENT_BINARY_DIR}
           )
 
+# install rules
 install(TARGETS MathFunctions DESTINATION lib)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step8/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Step8/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Step8/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step8/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step8/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step8/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step8/TutorialConfig.h.in b/Help/guide/tutorial/Step8/TutorialConfig.h.in
similarity index 100%
rename from Tests/Tutorial/Step8/TutorialConfig.h.in
rename to Help/guide/tutorial/Step8/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step8/tutorial.cxx
similarity index 79%
copy from Tests/Tutorial/Step3/tutorial.cxx
copy to Help/guide/tutorial/Step8/tutorial.cxx
index 1d5742d..8156a9c 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Help/guide/tutorial/Step8/tutorial.cxx
@@ -5,6 +5,7 @@
 
 #include "TutorialConfig.h"
 
+// should we include the MathFunctions header?
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
 #endif
@@ -12,14 +13,16 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
   double inputValue = std::stod(argv[1]);
 
+  // which square root function should we use?
 #ifdef USE_MYMATH
   double outputValue = mysqrt(inputValue);
 #else
diff --git a/Tests/Tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step9/CMakeLists.txt
rename to Help/guide/tutorial/Step9/CMakeLists.txt
index 309d513..e610b99 100644
--- a/Tests/Tutorial/Step9/CMakeLists.txt
+++ b/Help/guide/tutorial/Step9/CMakeLists.txt
@@ -4,7 +4,7 @@
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED True)
 
-# the version number.
+# set the version number
 set(Tutorial_VERSION_MAJOR 1)
 set(Tutorial_VERSION_MINOR 0)
 
diff --git a/Tests/Tutorial/Step9/CTestConfig.cmake b/Help/guide/tutorial/Step9/CTestConfig.cmake
similarity index 100%
rename from Tests/Tutorial/Step9/CTestConfig.cmake
rename to Help/guide/tutorial/Step9/CTestConfig.cmake
diff --git a/Tests/Tutorial/Step9/License.txt b/Help/guide/tutorial/Step9/License.txt
similarity index 100%
rename from Tests/Tutorial/Step9/License.txt
rename to Help/guide/tutorial/Step9/License.txt
diff --git a/Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt
similarity index 98%
rename from Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt
rename to Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt
index e651a57..c8cd1dd 100644
--- a/Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt
@@ -31,5 +31,6 @@
                              PRIVATE "HAVE_LOG" "HAVE_EXP")
 endif()
 
+# install rules
 install(TARGETS MathFunctions DESTINATION lib)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step9/MathFunctions/MakeTable.cxx
similarity index 100%
rename from Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx
rename to Help/guide/tutorial/Step9/MathFunctions/MakeTable.cxx
diff --git a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx
similarity index 100%
rename from Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx
rename to Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx
diff --git a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h
similarity index 100%
rename from Tests/Tutorial/Step9/MathFunctions/MathFunctions.h
rename to Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h
diff --git a/Tests/Tutorial/Step9/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx
similarity index 100%
rename from Tests/Tutorial/Step9/MathFunctions/mysqrt.cxx
rename to Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx
diff --git a/Tests/Tutorial/Step9/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h
similarity index 100%
rename from Tests/Tutorial/Step9/MathFunctions/mysqrt.h
rename to Help/guide/tutorial/Step9/MathFunctions/mysqrt.h
diff --git a/Tests/Tutorial/Step9/TutorialConfig.h.in b/Help/guide/tutorial/Step9/TutorialConfig.h.in
similarity index 100%
rename from Tests/Tutorial/Step9/TutorialConfig.h.in
rename to Help/guide/tutorial/Step9/TutorialConfig.h.in
diff --git a/Tests/Tutorial/Step9/tutorial.cxx b/Help/guide/tutorial/Step9/tutorial.cxx
similarity index 80%
rename from Tests/Tutorial/Step9/tutorial.cxx
rename to Help/guide/tutorial/Step9/tutorial.cxx
index 73e67a9..3286bc8 100644
--- a/Tests/Tutorial/Step9/tutorial.cxx
+++ b/Help/guide/tutorial/Step9/tutorial.cxx
@@ -6,6 +6,7 @@
 
 #include "TutorialConfig.h"
 
+// should we include the MathFunctions header?
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
 #endif
@@ -13,14 +14,16 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
+    // report version
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
   double inputValue = std::stod(argv[1]);
 
+  // which square root function should we use?
 #ifdef USE_MYMATH
   double outputValue = mysqrt(inputValue);
 #else
diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst
new file mode 100644
index 0000000..068499e
--- /dev/null
+++ b/Help/guide/tutorial/index.rst
@@ -0,0 +1,780 @@
+CMake Tutorial
+**************
+
+.. only:: html
+
+   .. contents::
+
+This tutorial provides a step-by-step guide that covers common build
+system issues that CMake helps address. Seeing how various topics all
+work together in an example project can be very helpful. This tutorial
+can be found in the ``Help/guide/tutorial`` directory of the CMake
+source code tree. Each topic has its own subdirectory containing code
+that may be used as a starting point for that step. The tutorial
+examples are progressive so that each step provides the complete
+solution for the previous step.
+
+A Basic Starting Point (Step 1)
+===============================
+
+The most basic project is an executable built from source code files.
+For simple projects, a two line CMakeLists file is all that is required.
+This will be the starting point for our tutorial. The CMakeLists file
+looks like:
+
+.. literalinclude:: Step1/CMakeLists.txt
+  :language: cmake
+
+Note that this example uses lower case commands in the CMakeLists file.
+Upper, lower, and mixed case commands are supported by CMake. The source
+code for ``tutorial.cxx`` will compute the square root of a number and
+the first version of it is very simple, as follows:
+
+.. literalinclude:: Step1/tutorial.cxx
+  :language: c++
+
+Adding a Version Number and Configured Header File
+--------------------------------------------------
+
+The first feature we will add is to provide our executable and project with a
+version number. While we could do this exclusively in the source code, using
+CMakeLists provides more flexibility.
+
+To add a version number we modify the CMakeLists file as follows:
+
+.. literalinclude:: Step2/CMakeLists.txt
+  :language: cmake
+  :start-after: # set the version number
+  :end-before: # configure a header file
+
+Since the configured file will be written into the binary tree, we
+must add that directory to the list of paths to search for include
+files.
+
+.. literalinclude:: Step2/CMakeLists.txt
+  :language: cmake
+  :start-after: # so that we will find TutorialConfig.h
+
+We then create a ``TutorialConfig.h.in`` file in the source tree with the
+following contents:
+
+.. literalinclude:: Step1/TutorialConfig.h.in
+  :language: cmake
+
+When CMake configures this header file the values for
+``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
+replaced by the values from the CMakeLists file. Next we modify
+``tutorial.cxx`` to include the configured header file and to make use of the
+version numbers. The updated source code is listed below.
+
+.. literalinclude:: Step2/tutorial.cxx
+  :language: c++
+  :start-after: // report version
+  :end-before: return 1;
+
+The main changes are the inclusion of the ``TutorialConfig.h`` header
+file and printing out a version number as part of the usage message.
+
+Specify the C++ Standard
+-------------------------
+
+Next let's add some C++11 features to our project. We will need to explicitly
+state in the CMake code that it should use the correct flags. The easiest way
+to enable C++11 support for CMake is by using the ``CMAKE_CXX_STANDARD``
+variable.
+
+First, replace ``atof`` with ``std::stod`` in ``tutorial.cxx``.
+
+Then, set the ``CMAKE_CXX_STANDARD`` variable in the CMakeLists file.
+
+Which variable can we set in the CMakeLists file to treat the
+``CMAKE_CXX_STANDARD`` value as a requirement?
+
+Build and Test
+--------------
+
+Run **cmake** or **cmake-gui** to configure the project and then build it
+with your chosen build tool.
+
+cd to the directory where Tutorial was built (likely the make directory or
+a Debug or Release build configuration subdirectory) and run these commands:
+
+.. code-block:: console
+
+  Tutorial 4294967296
+  Tutorial 10
+  Tutorial
+
+Adding a Library (Step 2)
+=========================
+
+Now we will add a library to our project. This library will contain our own
+implementation for computing the square root of a number. The executable can
+then use this library instead of the standard square root function provided by
+the compiler.
+
+For this tutorial we will put the library into a subdirectory
+called MathFunctions. It will have the following one line CMakeLists file:
+
+.. literalinclude:: Step2/MathFunctions/CMakeLists.txt
+  :language: cmake
+
+The source file ``mysqrt.cxx`` has one function called ``mysqrt`` that
+provides similar functionality to the compiler’s ``sqrt`` function. To make use
+of the new library we add an ``add_subdirectory`` call in the top-level
+CMakeLists file so that the library will get built. We add the new library to
+the executable, and add MathFunctions as an include directory so that the
+``mqsqrt.h`` header file can be found. The last few lines of the top-level
+CMakeLists file now look like:
+
+.. code-block:: cmake
+
+        # add the MathFunctions library
+        add_subdirectory(MathFunctions)
+
+        # add the executable
+        add_executable(Tutorial tutorial.cxx)
+
+        target_link_libraries(Tutorial MathFunctions)
+
+        # add the binary tree to the search path for include files
+        # so that we will find TutorialConfig.h
+        target_include_directories(Tutorial PUBLIC
+                                  "${PROJECT_BINARY_DIR}"
+                                  "${PROJECT_SOURCE_DIR}/MathFunctions"
+                                  )
+
+Now let us make the MathFunctions library optional. While for the tutorial
+there really isn’t any need to do so, for larger projects this is a common
+occurrence. The first step is to add an option to the top-level CMakeLists
+file.
+
+.. literalinclude:: Step3/CMakeLists.txt
+  :language: cmake
+  :start-after: # should we use our own math functions
+  :end-before: # set the version number
+
+This will show up in the CMake GUI and ccmake with a default value of ON
+that can be changed by the user. This setting will be stored in the cache so
+that the user does not need to set the value each time they run CMake on this
+build directory.
+
+The next change is to make building and linking the MathFunctions library
+conditional. To do this we change the end of the top-level CMakeLists file to
+look like the following:
+
+.. literalinclude:: Step3/CMakeLists.txt
+  :language: cmake
+  :start-after: # add the MathFunctions library?
+
+Note the use of the variables ``EXTRA_LIBS`` and ``EXTRA_INCLUDES`` to collect
+up any optional libraries to later be linked into the executable. This is a
+classic approach when dealing with many optional components, we will cover the
+modern approach in the next step.
+
+The corresponding changes to the source code are fairly straightforward. First,
+include the MathFunctions header if we need it:
+
+.. literalinclude:: Step3/tutorial.cxx
+  :language: c++
+  :start-after: // should we include the MathFunctions header
+  :end-before: int main
+
+Then make which square root function is used dependent on ``USE_MYMATH``:
+
+.. literalinclude:: Step3/tutorial.cxx
+  :language: c++
+  :start-after: // which square root function should we use?
+  :end-before: std::cout << "The square root of
+
+Since the source code now requires ``USE_MYMATH`` we can add it to
+``TutorialConfig.h.in`` with the following line:
+
+.. literalinclude:: Step3/TutorialConfig.h.in
+  :language: c
+  :lines: 4
+
+Run **cmake** or **cmake-gui** to configure the project and then build it
+with your chosen build tool. Then run the built Tutorial executable.
+
+Which function gives better results, Step1’s sqrt or Step2’s mysqrt?
+
+Adding Usage Requirements for Library (Step 3)
+==============================================
+
+Usage requirements allow for far better control over a library or executable's
+link and include line while also giving more control over the transitive
+property of targets inside CMake. The primary commands that leverage usage
+requirements are:
+
+  - ``target_compile_definitions``
+  - ``target_compile_options``
+  - ``target_include_directories``
+  - ``target_link_libraries``
+
+First up is MathFunctions. We first state that anybody linking to MathFunctions
+needs to include the current source directory, while MathFunctions itself
+doesn't. So this can become an ``INTERFACE`` usage requirement.
+
+Remember ``INTERFACE`` means things that consumers require but the producer
+doesn't. Update ``MathFunctions/CMakeLists.txt`` with:
+
+.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :start-after: # to find MathFunctions.h
+
+Now that we've specified usage requirements for MathFunctions we can safely
+remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
+CMakeLists.
+
+Once this is done, run **cmake** or **cmake-gui** to configure the project
+and then build it with your chosen build tool or by using ``cmake --build .``
+from the build directory.
+
+Installing and Testing (Step 4)
+===============================
+
+Now we can start adding install rules and testing support to our project.
+
+Install Rules
+-------------
+
+The install rules are fairly simple for MathFunctions we want to install the
+library and header file and for the application we want to install the
+executable and configured header.
+
+So to ``MathFunctions/CMakeLists.txt`` we add:
+
+.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :start-after: # install rules
+
+And the to top-level ``CMakeLists.txt`` we add:
+
+.. literalinclude:: Step5/CMakeLists.txt
+  :language: cmake
+  :start-after: # add the install targets
+  :end-before: # enable testing
+
+That is all that is needed to create a basic local install of the tutorial.
+
+Run **cmake** or **cmake-gui** to configure the project and then build it
+with your chosen build tool. Run the install step by typing
+``cmake --install .`` or  from the command line, or build the ``INSTALL``
+target from an IDE. This will install the appropriate header files, libraries,
+and executables.
+
+Verify that the installed Tutorial runs. Note: The CMake variable
+``CMAKE_INSTALL_PREFIX`` is used to determine the root of where the files will
+be installed. If using ``cmake --install`` a custom installation directory can
+be given via ``--prefix`` argument.
+
+Testing Support
+---------------
+
+Next let's test our application. At the end of the top-level CMakeLists file we
+can add a number of basic tests to verify that the application is
+working correctly.
+
+.. literalinclude:: Step5/CMakeLists.txt
+  :language: cmake
+  :start-after: # enable testing
+
+The first test simply verifies that the application runs, does not segfault or
+otherwise crash, and has a zero return value. This is the basic form of a CTest
+test.
+
+The next test makes use of the ``PASS_REGULAR_EXPRESSION`` test property to
+verify that the output of the test contains certain strings, in this case:
+verifying that the the usage message is printed when an incorrect number of
+arguments are provided.
+
+Lastly, we have a function called ``do_test`` that runs the application and
+verifies that the computed square root is correct for given input. For each
+invocation of ``do_test``, another test is added to the project with a name,
+input, and expected results based on the passed arguments.
+
+Rebuild the application and then cd to the binary directory and run
+``ctest -N`` and ``ctest -VV``.
+
+Adding System Introspection (Step 5)
+====================================
+
+Let us consider adding some code to our project that depends on features the
+target platform may not have. For this example, we will add some code that
+depends on whether or not the target platform has the ``log`` and ``exp``
+functions. Of course almost every platform has these functions but for this
+tutorial assume that they are not common.
+
+If the platform has ``log`` and ``exp`` then we will use them to compute the
+square root in the ``mysqrt`` function. We first test for the availability of
+these functions using the ``CheckSymbolExists.cmake`` macro in the top-level
+CMakeLists file as follows:
+
+.. literalinclude:: Step6/CMakeLists.txt
+  :language: cmake
+  :start-after: # does this system provide the log and exp functions?
+  :end-before: # should we use our own math functions
+
+Now let's add these defines to ``TutorialConfig.h.in`` so that we can use them
+from ``mysqrt.cxx``:
+
+.. literalinclude:: Step6/TutorialConfig.h.in
+  :language: c
+  :start-after: // does the platform provide exp and log functions?
+
+Finally, in the ``mysqrt`` function we can provide an alternate implementation
+based on ``log`` and ``exp`` if they are available on the system using the
+following code:
+
+.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
+  :language: c++
+  :start-after: // if we have both log and exp then use them
+  :end-before: #else
+
+Run **cmake** or **cmake-gui** to configure the project and then build it
+with your chosen build tool.
+
+You will notice that even though ``HAVE_LOG`` and ``HAVE_EXP`` are both
+defined ``mysqrt`` isn't using them. We should realize quickly that we have
+forgotten to include ``TutorialConfig.h`` in ``mysqrt.cxx``.
+
+After making this update, go ahead and build the project again.
+
+Run the built Tutorial executable. Which function gives better results now,
+Step1’s sqrt or Step5’s mysqrt?
+
+**Exercise**: Why is it important that we configure ``TutorialConfig.h.in``
+after the checks for ``HAVE_LOG`` and ``HAVE_EXP``? What would happen if we
+inverted the two?
+
+**Exercise**: Is there a better place for us to save the ``HAVE_LOG`` and
+``HAVE_EXP`` values other than in ``TutorialConfig.h``?
+
+Adding a Custom Command and Generated File (Step 6)
+===================================================
+
+In this section, we will add a generated source file into the build process
+of an application. For this example, we will create a table of precomputed
+square roots as part of the build process, and then compile that
+table into our application.
+
+To accomplish this, we first need a program that will generate the table. In
+the MathFunctions subdirectory a new source file named ``MakeTable.cxx`` will
+do just that.
+
+.. literalinclude:: Step7/MathFunctions/MakeTable.cxx
+  :language: c++
+
+Note that the table is produced as valid C++ code and that the output filename
+is passed in as an argument.
+
+The next step is to add the appropriate commands to MathFunctions' CMakeLists
+file to build the MakeTable executable and then run it as part of the build
+process. A few commands are needed to accomplish this.
+
+First, the executable for ``MakeTable`` is added as any other executable would
+be added.
+
+.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :start-after: # first we add the executable that generates the table
+  :end-before: # add the command to generate the source code
+
+Then we add a custom command that specifies how to produce ``Table.h``
+by running MakeTable.
+
+.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :start-after: # add the command to generate the source code
+  :end-before: # add the main library
+
+Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated
+file ``Table.h``. This is done by adding the generated ``Table.h`` to the list
+of sources for the library MathFunctions.
+
+.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :start-after: # add the main library
+  :end-before: # state that anybody linking
+
+We also have to add the current binary directory to the list of include
+directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
+
+.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+  :start-after: # state that we depend on our bin
+  :end-before: # install rules
+
+Now let's use the generated table. First, modify ``mysqrt.cxx`` to include
+``Table.h``. Next, we can rewrite the mysqrt function to use the table:
+
+.. literalinclude:: Step7/MathFunctions/mysqrt.cxx
+  :language: c++
+  :start-after: // a hack square root calculation using simple operations
+
+Run **cmake** or **cmake-gui** to configure the project and then build it
+with your chosen build tool. When this project is built it will first build
+the ``MakeTable`` executable. It will then run ``MakeTable`` to produce
+``Table.h``. Finally, it will compile ``mysqrt.cxx`` which includes
+``Table.h`` to produce the MathFunctions library.
+
+Building an Installer (Step 7)
+==============================
+
+Next suppose that we want to distribute our project to other people so that
+they can use it. We want to provide both binary and source distributions on a
+variety of platforms. This is a little different from the install we did
+previously in `Installing and Testing (Step 4)`_ , where we were
+installing the binaries that we had built from the source code. In this
+example we will be building installation packages that support binary
+installations and package management features. To accomplish this we will use
+CPack to create platform specific installers. Specifically we need to add
+a few lines to the bottom of our top-level ``CMakeLists.txt`` file.
+
+.. literalinclude:: Step8/CMakeLists.txt
+  :language: cmake
+  :start-after: # setup installer
+
+That is all there is to it. We start by including
+``InstallRequiredSystemLibraries``. This module will include any runtime
+libraries that are needed by the project for the current platform. Next we
+set some CPack variables to where we have stored the license and version
+information for this project. The version information makes use of the
+variables we set earlier in this tutorial. Finally we include the CPack
+module which will use these variables and some other properties of the system
+you are on to setup an installer.
+
+The next step is to build the project in the usual manner and then run
+CPack on it. To build a binary distribution you would run:
+
+.. code-block:: console
+
+  cpack
+
+To create a source distribution you would type:
+
+.. code-block:: console
+
+  cpack -C CPackSourceConfig.cmake
+
+Alternatively, run ``make package`` or right click the ``Package`` target and
+``Build Project`` from an IDE.
+
+Run the installer executable found in the binary directory. Then run the
+installed executable and verify that it works.
+
+Adding Support for a Dashboard (Step 8)
+=======================================
+
+Adding support for submitting our test results to a dashboard is very easy. We
+already defined a number of tests for our project in the earlier steps of this
+tutorial. We just have to run those tests and submit them to a dashboard. To
+include support for dashboards we include the CTest module in our top-level
+``CMakeLists.txt``.
+
+Replace:
+
+.. code-block:: cmake
+
+  # enable testing
+  enable_testing()
+
+With:
+
+.. code-block:: cmake
+
+  # enable dashboard scripting
+  include(CTest)
+
+The CTest module will automatically call ``enable_testing()``, so
+we can remove it from our CMake files.
+
+We will also need to create a ``CTestConfig.cmake`` file where we can specify
+the name of the project and where to submit the dashboard.
+
+.. literalinclude:: Step9/CTestConfig.cmake
+  :language: cmake
+
+CTest will read in this file when it runs. To create a simple dashboard you can
+run **cmake** or **cmake-gui** to configure the project, but do not build it
+yet. Instead, change directory to the binary tree, and then run:
+
+.. code-block:: console
+
+ 'ctest [-VV] –D Experimental'
+
+On Windows, build the EXPERIMENTAL target.
+
+Ctest will build and test the project and submit the results to the Kitware
+public dashboard. The results of your dashboard will be uploaded to Kitware's
+public dashboard here: https://my.cdash.org/index.php?project=CMakeTutorial.
+
+Mixing Static and Shared (Step 9)
+=================================
+
+In this section we will show how by using the ``BUILD_SHARED_LIBS`` variable
+we can control the default behavior of ``add_library``, and allow control
+over how libraries without an explicit type (STATIC/SHARED/MODULE/OBJECT) are
+built.
+
+To accomplish this we need to add ``BUILD_SHARED_LIBS`` to the top-level
+``CMakeLists.txt``. We use the ``option`` command as it allows users to
+optionally select if the value should be On or Off.
+
+Next we are going to refactor MathFunctions to become a real library that
+encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling
+code to do this logic. This will also mean that ``USE_MYMATH`` will not control
+building MathFuctions, but instead will control the behavior of this library.
+
+The first step is to update the starting section of the top-level
+``CMakeLists.txt`` to look like:
+
+.. literalinclude:: Step10/CMakeLists.txt
+  :language: cmake
+  :start-after: set(Tutorial_VERSION_MINOR
+  :end-before: # add the binary tree
+
+Now that we have made MathFunctions always be used, we will need to update
+the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to
+create a SqrtLibrary that will conditionally be built when ``USE_MYMATH`` is
+enabled. Now, since this is a tutorial, we are going to explicitly require
+that SqrtLibrary is built statically.
+
+The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
+
+.. literalinclude:: Step10/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :lines: 1-40,46-
+
+Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and
+``detail`` namespaces:
+
+.. literalinclude:: Step10/MathFunctions/mysqrt.cxx
+  :language: c++
+
+We also need to make some changes in ``tutorial.cxx``, so that it no longer
+uses ``USE_MYMATH``:
+
+#. Always include ``MathFunctions.h``
+#. Always use ``mathfunctions::sqrt``
+
+Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines:
+
+.. literalinclude:: Step10/MathFunctions/MathFunctions.h
+  :language: c++
+
+At this point, if you build everything, you will notice that linking fails
+as we are combining a static library without position enabled code with a
+library that has position enabled code. The solution to this is to explicitly
+set the ``POSITION_INDEPENDENT_CODE`` target property of SqrtLibrary to be
+True no matter the build type.
+
+**Exercise**: We modified ``MathFunctions.h`` to use dll export defines.
+Using CMake documentation can you find a helper module to simplify this?
+
+Adding Generator Expressions (Step 10)
+======================================
+
+Generator expressions are evaluated during build system generation to produce
+information specific to each build configuration.
+
+Generator expressions are allowed in the context of many target properties,
+such as ``LINK_LIBRARIES``, ``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS``
+and others. They may also be used when using commands to populate those
+properties, such as ``target_link_libraries()``,
+``target_include_directories()``,
+``target_compile_definitions()`` and others.
+
+Generator expressions may be used to enable conditional linking, conditional
+definitions used when compiling, conditional include directories and more.
+The conditions may be based on the build configuration, target properties,
+platform information or any other queryable information.
+
+There are different types of generator expressions including Logical,
+Informational, and Output expressions.
+
+Logical expressions are used to create conditional output. The basic
+expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty
+string, and ``<1:...>`` results in the content of "...".  They can also be
+nested.
+
+A common usage of generator expressions is to conditionally add compiler
+flags, such as those as language levels or warnings. A nice pattern is
+to associate this information to an ``INTERFACE`` target allowing this
+information to propagate. Lets start by constructing an ``INTERFACE``
+target and specifying the required C++ standard level of ``11`` instead
+of using ``CMAKE_CXX_STANDARD``.
+
+So the following code:
+
+.. literalinclude:: Step10/CMakeLists.txt
+  :language: cmake
+  :start-after: project(Tutorial)
+  :end-before: # Set the version number
+
+Would be replaced with:
+
+.. literalinclude:: Step11/CMakeLists.txt
+  :language: cmake
+  :start-after: project(Tutorial)
+  :end-before: # add compiler warning flags just when building this project via
+
+
+Next we add the desired compiler warning flags that we want for our
+project. As warning flags vary based on the compiler we use
+the ``COMPILE_LANG_AND_ID`` generator expression to control which
+flags to apply given a language and a set of compiler ids as seen
+below:
+
+.. literalinclude:: Step11/CMakeLists.txt
+  :language: cmake
+  :start-after: # the BUILD_INTERFACE genex
+  :end-before: # set the version number
+
+Looking at this we see that the warning flags are encapsulated inside a
+``BUILD_INTERFACE`` condition. This is done so that consumers of our installed
+project will not inherit our warning flags.
+
+
+**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that
+all targets have a ``target_link_libraries()`` call to ``tutorial_compiler_flags``.
+
+
+Adding Export Configuration (Step 11)
+=====================================
+
+During `Installing and Testing (Step 4)`_ of the tutorial we added the ability
+for CMake to install the library and headers of the project. During
+`Building an Installer (Step 7)`_ we added the ability to package up this
+information so it could be distributed to other people.
+
+The next step is to add the necessary information so that other CMake projects
+can use our project, be it from a build directory, a local install or when
+packaged.
+
+The first step is to update our ``install(TARGETS)`` commands to not only
+specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword
+generates and installs a CMake file containing code to import all targets
+listed in the install command from the installation tree. So let's go ahead
+and explicitly ``EXPORT`` the MathFunctions library by updating the
+``install`` command in ``MathFunctions/CMakeLists.txt`` to look like:
+
+.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :start-after: # install rules
+
+Now that we have MathFunctions being exported, we also need to explicitly
+install the generated ``MathFunctionsTargets.cmake`` file. This is done by
+adding the following to the bottom of the top-level ``CMakeLists.txt``:
+
+.. literalinclude:: Complete/CMakeLists.txt
+  :language: cmake
+  :start-after: # install the configuration targets
+  :end-before: include(CMakePackageConfigHelpers)
+
+At this point you should try and run CMake. If everything is setup properly
+you will see that CMake will generate an error that looks like:
+
+.. code-block:: console
+
+  Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
+  path:
+
+    "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
+
+  which is prefixed in the source directory.
+
+What CMake is trying to say is that during generating the export information
+it will export a path that is intrinsically tied to the current machine and
+will not be valid on other machines. The solution to this is to update the
+MathFunctions ``target_include_directories`` to understand that it needs
+different ``INTERFACE`` locations when being used from within the build
+directory and from an install / package. This means converting the
+``target_include_directories`` call for MathFunctions to look like:
+
+.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
+  :language: cmake
+  :start-after: # to find MathFunctions.h, while we don't.
+  :end-before: # should we use our own math functions
+
+Once this has been updated, we can re-run CMake and see verify that it doesn't
+warn anymore.
+
+At this point, we have CMake properly packaging the target information that is
+required but we will still need to generate a ``MathFunctionsConfig.cmake`` so
+that the CMake ``find_package command`` can find our project. So let's go
+ahead and add a new file to the top-level of the project called
+``Config.cmake.in`` with the following contents:
+
+.. literalinclude:: Complete/Config.cmake.in
+
+Then, to properly configure and install that file, add the following to the
+bottom of the top-level CMakeLists:
+
+.. literalinclude:: Complete/CMakeLists.txt
+  :language: cmake
+  :start-after: # install the configuration targets
+  :end-before: # generate the export
+
+At this point, we have generated a relocatable CMake Configuration for our
+project that can be used after the project has been installed or packaged. If
+we want our project to also be used from a build directory we only have to add
+the following to the bottom of the top level CMakeLists:
+
+.. literalinclude:: Complete/CMakeLists.txt
+  :language: cmake
+  :start-after: # needs to be after the install(TARGETS ) command
+
+With this export call we now generate a ``Targets.cmake``, allowing the
+configured ``MathFunctionsConfig.cmake`` in the build directory to be used by
+other projects, without needing it to be installed.
+
+Import a CMake Project (Consumer)
+=================================
+
+This examples shows how a project can find other CMake packages that
+generate ``Config.cmake`` files.
+
+It also shows how to state a project's external dependencies when generating
+a ``Config.cmake``.
+
+Packaging Debug and Release (MultiPackage)
+==========================================
+
+By default CMake is model is that a build directory only contains a single
+configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo.
+
+But it is possible to setup CPack to bundle multiple build directories at the
+same time to build a package that contains multiple configurations of the
+same project.
+
+First we need to ahead and construct a directory called ``multi_config`` this
+will contain all the builds that we want to package together.
+
+Second create a ``debug`` and ``release`` directory underneath
+``multi_config``. At the end you should have a layout that looks like:
+
+─ multi_config
+    ├── debug
+    └── release
+
+Now we need to setup debug and release builds, which would roughly entail
+the following:
+
+.. code-block:: console
+
+  cd debug
+  cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/
+  cmake --build .
+  cd ../release
+  cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/
+  cmake --build .
+  cd ..
+
+
+Now that both the debug and release builds are complete we can now use
+the custom MultiCPackConfig to package both builds into a single release.
+
+.. code-block:: console
+
+  cpack --config ../../MultiPackage/MultiCPackConfig.cmake
diff --git a/Help/index.rst b/Help/index.rst
index a948939..cf1d2f1 100644
--- a/Help/index.rst
+++ b/Help/index.rst
@@ -44,6 +44,14 @@
    /manual/cmake-variables.7
    /manual/cpack-generators.7
 
+Guides
+######
+
+.. toctree::
+   :maxdepth: 1
+
+   /guide/tutorial/index
+
 .. only:: html or text
 
  Release Notes
diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst
index 8cd6e68..d8142a2 100644
--- a/Help/manual/cmake-buildsystem.7.rst
+++ b/Help/manual/cmake-buildsystem.7.rst
@@ -811,6 +811,10 @@
   executable target created by the :command:`add_executable` command
   when its :prop_tgt:`ENABLE_EXPORTS` target property is set.
 
+* On AIX: the linker import file (e.g. ``.imp``) of an executable target
+  created by the :command:`add_executable` command when its
+  :prop_tgt:`ENABLE_EXPORTS` target property is set.
+
 The :prop_tgt:`ARCHIVE_OUTPUT_DIRECTORY` and :prop_tgt:`ARCHIVE_OUTPUT_NAME`
 target properties may be used to control archive output artifact locations
 and names in the build tree.
diff --git a/Help/manual/cmake-packages.7.rst b/Help/manual/cmake-packages.7.rst
index f5aa42d..4b2934a 100644
--- a/Help/manual/cmake-packages.7.rst
+++ b/Help/manual/cmake-packages.7.rst
@@ -654,8 +654,13 @@
   :command:`export(PACKAGE)` populates the user package registry unless
   the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable explicitly
   disables it.
-* :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` disables the
-  User Package Registry in all the :command:`find_package` calls.
+* :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` disables the
+  User Package Registry in all the :command:`find_package` calls when
+  set to ``FALSE``.
+* Deprecated :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` disables the
+  User Package Registry in all the :command:`find_package` calls when set
+  to ``TRUE``. This variable is ignored when
+  :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` has been set.
 * :variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` disables
   the System Package Registry in all the :command:`find_package` calls.
 
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 1d023cb..44ea1a8 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,16 @@
 to determine whether to report an error on use of deprecated macros or
 functions.
 
+Policies Introduced by CMake 3.16
+=================================
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0097: ExternalProject_Add with GIT_SUBMODULES "" initializes no submodules. </policy/CMP0097>
+   CMP0096: project() preserves leading zeros in version components. </policy/CMP0096>
+   CMP0095: RPATH entries are properly escaped in the intermediary CMake install script. </policy/CMP0095>
+
 Policies Introduced by CMake 3.15
 =================================
 
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 77b1ae8..62d23c7 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -228,6 +228,7 @@
    /prop_tgt/IMPORT_SUFFIX
    /prop_tgt/INCLUDE_DIRECTORIES
    /prop_tgt/INSTALL_NAME_DIR
+   /prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH
    /prop_tgt/INSTALL_RPATH
    /prop_tgt/INSTALL_RPATH_USE_LINK_PATH
    /prop_tgt/INTERFACE_AUTOUIC_OPTIONS
@@ -331,6 +332,7 @@
    /prop_tgt/VS_DOTNET_REFERENCES
    /prop_tgt/VS_DOTNET_REFERENCES_COPY_LOCAL
    /prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION
+   /prop_tgt/VS_DPI_AWARE
    /prop_tgt/VS_GLOBAL_KEYWORD
    /prop_tgt/VS_GLOBAL_PROJECT_TYPES
    /prop_tgt/VS_GLOBAL_ROOTNAMESPACE
@@ -406,6 +408,7 @@
    /prop_test/REQUIRED_FILES
    /prop_test/RESOURCE_LOCK
    /prop_test/RUN_SERIAL
+   /prop_test/SKIP_REGULAR_EXPRESSION
    /prop_test/SKIP_RETURN_CODE
    /prop_test/TIMEOUT
    /prop_test/TIMEOUT_AFTER_MATCH
diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst
index 7435d9a..f233d08 100644
--- a/Help/manual/cmake-toolchains.7.rst
+++ b/Help/manual/cmake-toolchains.7.rst
@@ -399,8 +399,10 @@
   be false unless using a NDK that does not provide unified headers.
 
 :variable:`CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION`
-  Set to the version of the NDK toolchain to be selected as the compiler.
-  If not specified, the default will be the latest available GCC toolchain.
+  On NDK r19 or above, this variable must be unset or set to ``clang``.
+  On NDK r18 or below, set this to the version of the NDK toolchain to
+  be selected as the compiler.  If not specified, the default will be
+  the latest available GCC toolchain.
 
 :variable:`CMAKE_ANDROID_STL_TYPE`
   Set to specify which C++ standard library to use.  If not specified,
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index e3c2f9f..432d7fc 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -69,6 +69,7 @@
    /variable/CMAKE_MAKE_PROGRAM
    /variable/CMAKE_MATCH_COUNT
    /variable/CMAKE_MATCH_n
+   /variable/CMAKE_MESSAGE_INDENT
    /variable/CMAKE_MINIMUM_REQUIRED_VERSION
    /variable/CMAKE_MINOR_VERSION
    /variable/CMAKE_NETRC
@@ -158,6 +159,7 @@
    /variable/CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES
    /variable/CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT
    /variable/CMAKE_ECLIPSE_MAKE_ARGUMENTS
+   /variable/CMAKE_ECLIPSE_RESOURCE_ENCODING
    /variable/CMAKE_ECLIPSE_VERSION
    /variable/CMAKE_ERROR_DEPRECATED
    /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
@@ -181,6 +183,12 @@
    /variable/CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
    /variable/CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
    /variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
+   /variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH
+   /variable/CMAKE_FIND_USE_CMAKE_PATH
+   /variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH
+   /variable/CMAKE_FIND_USE_PACKAGE_REGISTRY
+   /variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH
+   /variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH
    /variable/CMAKE_FRAMEWORK_PATH
    /variable/CMAKE_IGNORE_PATH
    /variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE
@@ -364,6 +372,7 @@
    /variable/CMAKE_INCLUDE_CURRENT_DIR
    /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE
    /variable/CMAKE_INSTALL_NAME_DIR
+   /variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH
    /variable/CMAKE_INSTALL_RPATH
    /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH
    /variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION
@@ -602,7 +611,6 @@
    /variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
    /variable/CPACK_INCLUDE_TOPLEVEL_DIRECTORY
    /variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
-   /variable/CPACK_INSTALL_SCRIPT
    /variable/CPACK_PACKAGING_INSTALL_PREFIX
    /variable/CPACK_SET_DESTDIR
    /variable/CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 7b5399d..68d88e7 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -604,6 +604,12 @@
 .. note::
   Path to where ``<new>`` symbolic link will be created has to exist beforehand.
 
+``true``
+  Do nothing, with an exit code of 0.
+
+``false``
+  Do nothing, with an exit code of 1.
+
 Windows-specific Command-Line Tools
 -----------------------------------
 
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 5773176..c6b1425 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -443,7 +443,8 @@
  Specify the name of the project to build.
 
 ``--build-makeprogram``
- Override the make program chosen by CTest with a given one.
+ Specify the explicit make program to be used by CMake when configuring and
+ building the project. Only applicable for Make and Ninja based generators.
 
 ``--build-noclean``
  Skip the make clean step.
diff --git a/Help/policy/CMP0095.rst b/Help/policy/CMP0095.rst
new file mode 100644
index 0000000..4c56a05
--- /dev/null
+++ b/Help/policy/CMP0095.rst
@@ -0,0 +1,30 @@
+CMP0095
+-------
+
+``RPATH`` entries are properly escaped in the intermediary CMake install script.
+
+In CMake 3.15 and earlier, ``RPATH`` entries set via
+:variable:`CMAKE_INSTALL_RPATH` or via :prop_tgt:`INSTALL_RPATH` have not been
+escaped before being inserted into the ``cmake_install.cmake`` script. Dynamic
+linkers on ELF-based systems (e.g. Linux and FreeBSD) allow certain keywords in
+``RPATH`` entries, such as ``${ORIGIN}`` (More details are available in the
+``ld.so`` man pages on those systems). The syntax of these keywords can match
+CMake's variable syntax. In order to not be substituted (usually to an empty
+string) already by the intermediary ``cmake_install.cmake`` script, the user had
+to double-escape such ``RPATH`` keywords, e.g.
+``set(CMAKE_INSTALL_RPATH "\\\${ORIGIN}/../lib")``. Since the intermediary
+``cmake_install.cmake`` script is an implementation detail of CMake, CMake 3.16
+and later will make sure ``RPATH`` entries are inserted literally by escaping
+any coincidental CMake syntax.
+
+The ``OLD`` behavior of this policy is to not escape ``RPATH`` entries in the
+intermediary ``cmake_install.cmake`` script. The ``NEW`` behavior is to properly
+escape coincidental CMake syntax in ``RPATH`` entries when generating the
+intermediary ``cmake_install.cmake`` script.
+
+This policy was introduced in CMake version 3.16. CMake version |release| warns
+when the policy is not set and detected usage of CMake-like syntax and uses
+``OLD`` behavior. Use the :command:`cmake_policy` command to set it to ``OLD``
+or ``NEW`` explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0096.rst b/Help/policy/CMP0096.rst
new file mode 100644
index 0000000..8eaf0f9
--- /dev/null
+++ b/Help/policy/CMP0096.rst
@@ -0,0 +1,25 @@
+CMP0096
+-------
+
+The :command:`project` command preserves leading zeros in version components.
+
+When a ``VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]`` argument is given
+to the :command:`project` command, it stores the version string in the
+``PROJECT_VERSION`` variable and stores individual integer version components
+in ``PROJECT_VERSION_{MAJOR,MINOR,PATCH,TWEAK}`` variables (see policy
+:policy:`CMP0048`).  CMake 3.15 and below dropped leading zeros from each
+component.  CMake 3.16 and higher prefer to preserve leading zeros.  This
+policy provides compatibility for projects that have not been updated to
+expect the new behavior.
+
+The ``OLD`` behavior of this policy drops leading zeros in all components,
+e.g.  such that version ``1.07.06`` becomes ``1.7.6``.  The ``NEW`` behavior
+of this policy preserves the leading zeros in all components, such that
+version ``1.07.06`` remains unchanged.
+
+This policy was introduced in CMake version 3.16.  Unlike many policies, CMake
+version |release| does *not* warn when this policy is not set and simply uses
+the ``OLD`` behavior.  Use the :command:`cmake_policy` command to set it to
+``OLD`` or ``NEW`` explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0097.rst b/Help/policy/CMP0097.rst
new file mode 100644
index 0000000..8a5ff88
--- /dev/null
+++ b/Help/policy/CMP0097.rst
@@ -0,0 +1,23 @@
+CMP0097
+-------
+
+:command:`ExternalProject_Add` with ``GIT_SUBMODULES ""`` initializes no
+submodules.
+
+The module provides a ``GIT_SUBMODULES`` option which controls what submodules
+to initialize and update. Starting with CMake 3.16, explicitly setting
+``GIT_SUBMODULES`` to an empty string means no submodules will be initialized
+or updated.
+
+This policy provides compatibility for projects that have not been updated
+to expect the new behavior.
+
+The ``OLD`` behavior for this policy is for ``GIT_SUBMODULES`` when set to
+an empty string to initialize and update all git submodules.
+The ``New`` behavior for this policy is for ``GIT_SUBMODULES`` when set to
+an empty string to initialize and update no git submodules.
+
+This policy was introduced in CMake version 3.16.  Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike most policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
diff --git a/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst
new file mode 100644
index 0000000..2c6d980
--- /dev/null
+++ b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst
@@ -0,0 +1,17 @@
+SKIP_REGULAR_EXPRESSION
+-----------------------
+
+If the output matches this regular expression the test will be marked as skipped.
+
+If set, if the output matches one of specified regular expressions,
+the test will be marked as skipped.  Example:
+
+.. code-block:: cmake
+
+  set_property(TEST mytest PROPERTY
+    SKIP_REGULAR_EXPRESSION "[^a-z]Skip" "SKIP" "Skipped"
+  )
+
+``SKIP_REGULAR_EXPRESSION`` expects a list of regular expressions.
+
+See also the :prop_test:`SKIP_RETURN_CODE` property.
diff --git a/Help/prop_test/SKIP_RETURN_CODE.rst b/Help/prop_test/SKIP_RETURN_CODE.rst
index a05fbf3..23c4c62 100644
--- a/Help/prop_test/SKIP_RETURN_CODE.rst
+++ b/Help/prop_test/SKIP_RETURN_CODE.rst
@@ -6,4 +6,7 @@
 Sometimes only a test itself can determine if all requirements for the
 test are met. If such a situation should not be considered a hard failure
 a return code of the process can be specified that will mark the test as
-``Not Run`` if it is encountered.
+``Not Run`` if it is encountered. Valid values are in the range of
+0 to 255, inclusive.
+
+See also the :prop_test:`SKIP_REGULAR_EXPRESSION` property.
diff --git a/Help/prop_tgt/BUILD_RPATH.rst b/Help/prop_tgt/BUILD_RPATH.rst
index 13c9c1d..d978b94 100644
--- a/Help/prop_tgt/BUILD_RPATH.rst
+++ b/Help/prop_tgt/BUILD_RPATH.rst
@@ -8,3 +8,6 @@
 
 This property is initialized by the value of the variable
 :variable:`CMAKE_BUILD_RPATH` if it is set when a target is created.
+
+This property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/prop_tgt/ENABLE_EXPORTS.rst b/Help/prop_tgt/ENABLE_EXPORTS.rst
index 581c2b9..0b1064a 100644
--- a/Help/prop_tgt/ENABLE_EXPORTS.rst
+++ b/Help/prop_tgt/ENABLE_EXPORTS.rst
@@ -7,16 +7,25 @@
 final program.  It is possible for an executable to export symbols to
 be used by loadable modules.  When this property is set to true CMake
 will allow other targets to "link" to the executable with the
-:command:`TARGET_LINK_LIBRARIES` command.  On all platforms a target-level
+:command:`target_link_libraries` command.  On all platforms a target-level
 dependency on the executable is created for targets that link to it.
-For DLL platforms an import library will be created for the exported
-symbols and then used for linking.  All Windows-based systems
-including Cygwin are DLL platforms.  For non-DLL platforms that
-require all symbols to be resolved at link time, such as macOS, the
-module will "link" to the executable using a flag like
-``-bundle_loader``.  For other non-DLL platforms the link rule is simply
-ignored since the dynamic loader will automatically bind symbols when
-the module is loaded.
+Handling of the executable on the link lines of the loadable modules
+varies by platform:
+
+* On Windows-based systems (including Cygwin) an "import library" is
+  created along with the executable to list the exported symbols.
+  Loadable modules link to the import library to get the symbols.
+
+* On macOS, loadable modules link to the executable itself using the
+  ``-bundle_loader`` flag.
+
+* On AIX, a linker "import file" is created along with the executable
+  to list the exported symbols for import when linking other targets.
+  Loadable modules link to the import file to get the symbols.
+
+* On other platforms, loadable modules are simply linked without
+  referencing the executable since the dynamic loader will
+  automatically bind symbols when the module is loaded.
 
 This property is initialized by the value of the variable
 :variable:`CMAKE_ENABLE_EXPORTS` if it is set when a target is created.
diff --git a/Help/prop_tgt/IMPORTED_IMPLIB.rst b/Help/prop_tgt/IMPORTED_IMPLIB.rst
index 77fb552..c8b6fde 100644
--- a/Help/prop_tgt/IMPORTED_IMPLIB.rst
+++ b/Help/prop_tgt/IMPORTED_IMPLIB.rst
@@ -3,5 +3,7 @@
 
 Full path to the import library for an ``IMPORTED`` target.
 
-Set this to the location of the ``.lib`` part of a Windows DLL.  Ignored
-for non-imported targets.
+Set this to the location of the ``.lib`` part of a Windows DLL, or on
+AIX set it to an import file created for executables that export symbols
+(see the :prop_tgt:`ENABLE_EXPORTS` target property).
+Ignored for non-imported targets.
diff --git a/Help/prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH.rst b/Help/prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH.rst
new file mode 100644
index 0000000..a474fc6
--- /dev/null
+++ b/Help/prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH.rst
@@ -0,0 +1,10 @@
+INSTALL_REMOVE_ENVIRONMENT_RPATH
+--------------------------------
+
+Removes compiler defined rpaths durimg installation.
+
+``INSTALL_REMOVE_ENVIRONMENT_RPATH`` is a boolean that if set to ``True`` will
+remove compiler defined rpaths from the project if the user also defines rpath
+with :prop_tgt:`INSTALL_RPATH`.  This property is initialized by whether the
+value of :variable:`CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH` is set when a
+target is created.
diff --git a/Help/prop_tgt/INSTALL_RPATH.rst b/Help/prop_tgt/INSTALL_RPATH.rst
index 6403f4c..93b4488 100644
--- a/Help/prop_tgt/INSTALL_RPATH.rst
+++ b/Help/prop_tgt/INSTALL_RPATH.rst
@@ -7,3 +7,6 @@
 targets (for platforms that support it).  This property is initialized
 by the value of the variable :variable:`CMAKE_INSTALL_RPATH` if it is set when
 a target is created.
+
+This property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/prop_tgt/VS_DPI_AWARE.rst b/Help/prop_tgt/VS_DPI_AWARE.rst
new file mode 100644
index 0000000..82640cc
--- /dev/null
+++ b/Help/prop_tgt/VS_DPI_AWARE.rst
@@ -0,0 +1,14 @@
+VS_DPI_AWARE
+------------
+
+Set the Manifest Tool -> Input and Output -> DPI Awareness in the Visual Studio
+target project properties.
+
+Valid values are ``PerMonitor``, ``ON``, or ``OFF``.
+
+For example:
+
+.. code-block:: cmake
+
+  add_executable(myproject myproject.cpp)
+  set_property(TARGET myproject PROPERTY VS_DPI_AWARE "PerMonitor")
diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+  Developers should add similar notes for each topic branch
+  making a noteworthy change.  Each document should be named
+  and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/CMP0095.rst b/Help/release/dev/CMP0095.rst
new file mode 100644
index 0000000..21d0550
--- /dev/null
+++ b/Help/release/dev/CMP0095.rst
@@ -0,0 +1,5 @@
+CMP0095
+-------
+
+* ``RPATH`` entries are properly escaped in the intermediary CMake install script.
+  See policy :policy:`CMP0095`.
diff --git a/Help/release/dev/FindPython-FIND_ABI.rst b/Help/release/dev/FindPython-FIND_ABI.rst
new file mode 100644
index 0000000..19e3f71
--- /dev/null
+++ b/Help/release/dev/FindPython-FIND_ABI.rst
@@ -0,0 +1,5 @@
+FindPython-FIND_ABI
+-------------------
+
+* Modules :module:`FindPython3` and :module:`FindPython` gain the capability
+  to control which ``ABIs`` will be searched.
diff --git a/Help/release/dev/add-install-remove-environment-rpath.rst b/Help/release/dev/add-install-remove-environment-rpath.rst
new file mode 100644
index 0000000..156106c
--- /dev/null
+++ b/Help/release/dev/add-install-remove-environment-rpath.rst
@@ -0,0 +1,6 @@
+add-install-remove-environment-rpath
+------------------------------------
+
+* A new target property, :prop_tgt:`INSTALL_REMOVE_ENVIRONMENT_RPATH`, was
+  added which removes compiler-defined rpaths from a target. This property is
+  initialized by :variable:`CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH`.
diff --git a/Help/release/dev/add_cmake_find_use_package_registry.rst b/Help/release/dev/add_cmake_find_use_package_registry.rst
new file mode 100644
index 0000000..1b02bad
--- /dev/null
+++ b/Help/release/dev/add_cmake_find_use_package_registry.rst
@@ -0,0 +1,11 @@
+add_cmake_find_use_package_registry
+-----------------------------------
+
+* The :command:`find_package` command has learned to check the following
+  variables to control searching
+
+  * :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` - Controls the searching the
+    cmake user registry.
+
+* The :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` has been deprecated.
+  Instead use :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`
diff --git a/Help/release/dev/add_skip_regular_expression_test_property.rst b/Help/release/dev/add_skip_regular_expression_test_property.rst
new file mode 100644
index 0000000..20ef214
--- /dev/null
+++ b/Help/release/dev/add_skip_regular_expression_test_property.rst
@@ -0,0 +1,10 @@
+add_skip_regular_expression_test_property
+-----------------------------------------
+
+* A new test property, :prop_test:`SKIP_REGULAR_EXPRESSION`, has been added.
+  This property is similar to :prop_test:`FAIL_REGULAR_EXPRESSION` and
+  :prop_test:`PASS_REGULAR_EXPRESSION`, but with the same meaning as
+  :prop_test:`SKIP_RETURN_CODE`. This is useful, for example, in cases where
+  the user has no control over the return code of the test. For example, in
+  Catch2, the return value is the number of assertion failed, therefore it is
+  impossible to use it for :prop_test:`SKIP_RETURN_CODE`.
diff --git a/Help/release/dev/add_test-expand_lists.rst b/Help/release/dev/add_test-expand_lists.rst
new file mode 100644
index 0000000..88d26b7
--- /dev/null
+++ b/Help/release/dev/add_test-expand_lists.rst
@@ -0,0 +1,6 @@
+add_test-expand_lists
+---------------------
+
+* The command :command:`add_test` learned the option ``COMMAND_EXPAND_LISTS``
+  which causes lists in the ``COMMAND`` argument to be expanded, including
+  lists created by generator expressions.
diff --git a/Help/release/dev/aix.rst b/Help/release/dev/aix.rst
new file mode 100644
index 0000000..6919358
--- /dev/null
+++ b/Help/release/dev/aix.rst
@@ -0,0 +1,20 @@
+aix
+---
+
+* On AIX, executables using the :prop_tgt:`ENABLE_EXPORTS` target property
+  now produce a linker import file with a ``.imp`` extension in addition
+  to the executable file.  Plugins (created via :command:`add_library` with
+  the ``MODULE`` option) that use :command:`target_link_libraries` to link
+  to the executable for its symbols are now linked using the import file.
+  The :command:`install(TARGETS)` command now installs the import file as
+  an ``ARCHIVE`` artifact.
+
+* On AIX, runtime linking is no longer enabled by default.  CMake provides
+  the linker enough information to resolve all symbols up front.
+  One may manually enable runtime linking for shared libraries and/or
+  loadable modules by adding ``-Wl,-G`` to their link flags
+  (e.g. in the :variable:`CMAKE_SHARED_LINKER_FLAGS` or
+  :variable:`CMAKE_MODULE_LINKER_FLAGS` variable).
+  One may manually enable runtime linking for executables by adding
+  ``-Wl,-brtl`` to their link flags (e.g. in the
+  :variable:`CMAKE_EXE_LINKER_FLAGS` variable).
diff --git a/Help/release/dev/build-install-rpath-genex.rst b/Help/release/dev/build-install-rpath-genex.rst
new file mode 100644
index 0000000..644b1b2
--- /dev/null
+++ b/Help/release/dev/build-install-rpath-genex.rst
@@ -0,0 +1,5 @@
+build-install-rpath-genex
+-------------------------
+
+* :prop_tgt:`BUILD_RPATH` and :prop_tgt:`INSTALL_RPATH` now support
+  :manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/release/dev/cmake-e-true-false.rst b/Help/release/dev/cmake-e-true-false.rst
new file mode 100644
index 0000000..173fabd
--- /dev/null
+++ b/Help/release/dev/cmake-e-true-false.rst
@@ -0,0 +1,5 @@
+cmake-e-true-false
+------------------
+
+* :manual:`cmake(1)` ``-E`` now supports ``true`` and ``false`` commands, which
+  do nothing while returning exit codes of 0 and 1, respectively.
diff --git a/Help/release/dev/cmake-qch-no-version-in-filename.rst b/Help/release/dev/cmake-qch-no-version-in-filename.rst
new file mode 100644
index 0000000..3c5cb04
--- /dev/null
+++ b/Help/release/dev/cmake-qch-no-version-in-filename.rst
@@ -0,0 +1,8 @@
+cmake-qch-no-version-in-filename
+--------------------------------
+
+* The Qt Compressed Help file is now named ``CMake.qch``, which no longer
+  contains the release version in the file name.  When CMake is upgraded
+  in-place, the name and location of this file will remain constant.
+  Tools such as IDEs, help viewers, etc. should now be able to refer to this
+  file at a fixed location that remains valid across CMake upgrades.
diff --git a/Help/release/dev/cpack-install-scripts.rst b/Help/release/dev/cpack-install-scripts.rst
new file mode 100644
index 0000000..7b80d33
--- /dev/null
+++ b/Help/release/dev/cpack-install-scripts.rst
@@ -0,0 +1,5 @@
+cpack-install-scripts
+---------------------
+
+* The ``CPACK_INSTALL_SCRIPT`` variable has been deprecated in favor of the
+  new, more accurately named :variable:`CPACK_INSTALL_SCRIPTS` variable.
diff --git a/Help/release/dev/ctest-build-makeprogram-propagated-configure-pass.rst b/Help/release/dev/ctest-build-makeprogram-propagated-configure-pass.rst
new file mode 100644
index 0000000..4465de8
--- /dev/null
+++ b/Help/release/dev/ctest-build-makeprogram-propagated-configure-pass.rst
@@ -0,0 +1,6 @@
+ctest-build-makeprogram-propagated-configure-pass
+-------------------------------------------------
+
+* :manual:`ctest(1)`  ``--build-makeprogram`` now specifies the make program
+  used when configuring a project with the Ninja and Makefiles generators
+  in addition to building it.
diff --git a/Help/release/dev/deprecate-policy-old.rst b/Help/release/dev/deprecate-policy-old.rst
new file mode 100644
index 0000000..440efa9
--- /dev/null
+++ b/Help/release/dev/deprecate-policy-old.rst
@@ -0,0 +1,8 @@
+deprecate-policy-old
+--------------------
+
+* An explicit deprecation diagnostic was added for policy ``CMP0067``
+  (``CMP0066`` and below were already deprecated).
+  The :manual:`cmake-policies(7)` manual explains that the OLD behaviors
+  of all policies are deprecated and that projects should port to the
+  NEW behaviors.
diff --git a/Help/release/dev/eclipse-resource-encoding.rst b/Help/release/dev/eclipse-resource-encoding.rst
new file mode 100644
index 0000000..6ceca0c
--- /dev/null
+++ b/Help/release/dev/eclipse-resource-encoding.rst
@@ -0,0 +1,6 @@
+eclipse-resource-encoding
+-------------------------
+
+* The :generator:`Eclipse CDT4` extra generator gained a new
+  :variable:`CMAKE_ECLIPSE_RESOURCE_ENCODING` option to specify
+  the resource encoding.
diff --git a/Help/release/dev/external-project-support-no-git-submodules.rst b/Help/release/dev/external-project-support-no-git-submodules.rst
new file mode 100644
index 0000000..1d4be66
--- /dev/null
+++ b/Help/release/dev/external-project-support-no-git-submodules.rst
@@ -0,0 +1,6 @@
+external-project-support-no-git-submodules
+------------------------------------------
+
+* The :module:`ExternalProject` module's ``ExternalProject_Add`` command
+  has been updated so that ``GIT_SUBMODULES ""`` initializes no submodules. See
+  policy :policy:`CMP0097`.
diff --git a/Help/release/dev/get-runtime-dependencies.rst b/Help/release/dev/get-runtime-dependencies.rst
new file mode 100644
index 0000000..b9dc6e6
--- /dev/null
+++ b/Help/release/dev/get-runtime-dependencies.rst
@@ -0,0 +1,9 @@
+get-runtime-dependencies
+------------------------
+
+* The :command:`file` command learned a new sub-command,
+  ``GET_RUNTIME_DEPENDENCIES``, which allows you to recursively get the list of
+  libraries linked by an executable or library. This sub-command is intended as
+  a replacement for :module:`GetPrerequisites`.
+* The :module:`GetPrerequisites` module has been deprecated, as it has been
+  superceded by :command:`file(GET_RUNTIME_DEPENDENCIES)`.
diff --git a/Help/release/dev/global-controls-over-find-locations.rst b/Help/release/dev/global-controls-over-find-locations.rst
new file mode 100644
index 0000000..1c0b226
--- /dev/null
+++ b/Help/release/dev/global-controls-over-find-locations.rst
@@ -0,0 +1,21 @@
+global-controls-over-find-locations
+-----------------------------------
+
+* The :command:`find_file`, :command:`find_library`, :command:`find_path`,
+  :command:`find_package`, and :command:`find_program` commands have learned to
+  check the following variables to control searching
+
+  * :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH` - Controls the searching
+    the cmake-specific environment variables.
+
+  * :variable:`CMAKE_FIND_USE_CMAKE_PATH` - Controls the searching the
+    cmake-specific cache variables.
+
+  * :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH` - Controls the searching
+    cmake platform specific variables.
+
+  * :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` - Controls the searching of
+    :variable:`<PackageName>_ROOT` variables.
+
+  * :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH` - Controls the searching
+    the standard system environment variables.
diff --git a/Help/release/dev/message-indent.rst b/Help/release/dev/message-indent.rst
new file mode 100644
index 0000000..b170708
--- /dev/null
+++ b/Help/release/dev/message-indent.rst
@@ -0,0 +1,5 @@
+message-indent
+--------------
+
+* The :command:`message` command learned indentation control with the new
+  :variable:`CMAKE_MESSAGE_INDENT` variable.
diff --git a/Help/release/dev/project-version-0.rst b/Help/release/dev/project-version-0.rst
new file mode 100644
index 0000000..6525522
--- /dev/null
+++ b/Help/release/dev/project-version-0.rst
@@ -0,0 +1,5 @@
+project-version-0
+-----------------
+
+* The :command:`project` no longer strips leading zeros in version components.
+  See policy :policy:`CMP0096`.
diff --git a/Help/release/dev/vs-dpi-aware.rst b/Help/release/dev/vs-dpi-aware.rst
new file mode 100644
index 0000000..f76f26c
--- /dev/null
+++ b/Help/release/dev/vs-dpi-aware.rst
@@ -0,0 +1,6 @@
+vs-dpi-aware
+------------
+
+* The :prop_tgt:`VS_DPI_AWARE` target property was added to tell
+  :ref:`Visual Studio Generators` to set the ``EnableDpiAwareness``
+  property in ``.vcxproj`` files.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 35a47aa..62032e6 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -7,6 +7,8 @@
   This file should include the adjacent "dev.txt" file
   in development versions but not in release versions.
 
+.. include:: dev.txt
+
 Releases
 ========
 
diff --git a/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst b/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst
index 5ae55d1..22808e3 100644
--- a/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst
+++ b/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst
@@ -3,7 +3,11 @@
 
 When :ref:`Cross Compiling for Android with the NDK`, this variable
 may be set to specify the version of the toolchain to be used
-as the compiler.  The variable must be set to one of these forms:
+as the compiler.
+
+On NDK r19 or above, this variable must be unset or set to ``clang``.
+
+On NDK r18 or below, this variable must be set to one of these forms:
 
 * ``<major>.<minor>``: GCC of specified version
 * ``clang<major>.<minor>``: Clang of specified version
diff --git a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst
index eea2c4f..6d34c5c 100644
--- a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst
+++ b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst
@@ -4,4 +4,5 @@
 Executable to use when compiling host code when compiling ``CUDA`` language
 files. Maps to the ``nvcc -ccbin`` option.  Will only be used by CMake on the first
 configuration to determine a valid host compiler for ``CUDA``. After a valid
-host compiler has been found, this value is read-only.
+host compiler has been found, this value is read-only.  This variable takes
+priority over the :envvar:`CUDAHOSTCXX` environment variable.
diff --git a/Help/variable/CMAKE_ECLIPSE_RESOURCE_ENCODING.rst b/Help/variable/CMAKE_ECLIPSE_RESOURCE_ENCODING.rst
new file mode 100644
index 0000000..314efe5
--- /dev/null
+++ b/Help/variable/CMAKE_ECLIPSE_RESOURCE_ENCODING.rst
@@ -0,0 +1,6 @@
+CMAKE_ECLIPSE_RESOURCE_ENCODING
+-------------------------------
+
+This cache variable tells the :generator:`Eclipse CDT4` project generator
+to set the resource encoding to the given value in generated project files.
+If no value is given, no encoding will be set.
diff --git a/Help/variable/CMAKE_ENABLE_EXPORTS.rst b/Help/variable/CMAKE_ENABLE_EXPORTS.rst
index 7ec4d63..8848da1 100644
--- a/Help/variable/CMAKE_ENABLE_EXPORTS.rst
+++ b/Help/variable/CMAKE_ENABLE_EXPORTS.rst
@@ -1,22 +1,8 @@
 CMAKE_ENABLE_EXPORTS
 --------------------
 
-Specify whether an executable exports symbols for loadable modules.
+Specify whether executables export symbols for loadable modules.
 
-Normally an executable does not export any symbols because it is the
-final program.  It is possible for an executable to export symbols to
-be used by loadable modules.  When this property is set to true CMake
-will allow other targets to ``link`` to the executable with the
-:command:`TARGET_LINK_LIBRARIES` command.  On all platforms a target-level
-dependency on the executable is created for targets that link to it.
-For DLL platforms an import library will be created for the exported
-symbols and then used for linking.  All Windows-based systems
-including Cygwin are DLL platforms.  For non-DLL platforms that
-require all symbols to be resolved at link time, such as macOS, the
-module will ``link`` to the executable using a flag like
-``-bundle_loader``.  For other non-DLL platforms the link rule is simply
-ignored since the dynamic loader will automatically bind symbols when
-the module is loaded.
-
-This variable is used to initialize the target property
-:prop_tgt:`ENABLE_EXPORTS` for executable targets.
+This variable is used to initialize the :prop_tgt:`ENABLE_EXPORTS` target
+property for executable targets when they are created by calls to the
+:command:`add_executable` command.  See the property documentation for details.
diff --git a/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst b/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst
index 9058471..ffb8a2c 100644
--- a/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst
+++ b/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst
@@ -1,12 +1,23 @@
 CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
 --------------------------------------
 
-Skip :ref:`User Package Registry` in :command:`find_package` calls.
+.. deprecated:: 3.16
+
+  Use the :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` variable instead.
+
+By default this variable is not set. If neither
+:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` nor
+``CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`` is set, then
+:command:`find_package()` will use the `User Package Registry` unless the
+`NO_CMAKE_PACKAGE_REGISTRY` option is provided.
+
+``CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`` is ignored if
+:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` is set.
 
 In some cases, for example to locate only system wide installations, it
 is not desirable to use the :ref:`User Package Registry` when searching
 for packages. If the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`
-variable is enabled, all the :command:`find_package` commands will skip
+variable is ``TRUE``, all the :command:`find_package` commands will skip
 the :ref:`User Package Registry` as if they were called with the
 ``NO_CMAKE_PACKAGE_REGISTRY`` argument.
 
diff --git a/Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst b/Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst
new file mode 100644
index 0000000..2db5081
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst
@@ -0,0 +1,18 @@
+CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH
+-------------------------------------
+
+Controls the searching the cmake-specific environment variables by the
+:command:`find_program`, :command:`find_library`, :command:`find_file`,
+:command:`find_path`, and command:`find_package` commands.
+This is useful in cross-compiling environments.
+
+By default this variable is not set, which is equivalent to it having
+a value of ``TRUE``.  Explicit options given to the :command:`find_program`,
+:command:`find_library`, :command:`find_file`, and :command:`find_path`
+commands take precedence over this variable.
+
+See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
+:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,
+and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables.
diff --git a/Help/variable/CMAKE_FIND_USE_CMAKE_PATH.rst b/Help/variable/CMAKE_FIND_USE_CMAKE_PATH.rst
new file mode 100644
index 0000000..4ca7ad1
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_USE_CMAKE_PATH.rst
@@ -0,0 +1,18 @@
+CMAKE_FIND_USE_CMAKE_PATH
+-------------------------
+
+Controls the searching the cmake-specific cache variables by the
+:command:`find_program`, :command:`find_library`, :command:`find_file`,
+:command:`find_path`, and command:`find_package` commands.
+This is useful in cross-compiling environments.
+
+By default this variable is not set, which is equivalent to it having
+a value of ``TRUE``.  Explicit options given to the :command:`find_program`,
+:command:`find_library`, :command:`find_file`, and :command:`find_path`
+commands take precedence over this variable.
+
+See also the :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
+:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,
+and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables.
diff --git a/Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst b/Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst
new file mode 100644
index 0000000..d3259ae
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst
@@ -0,0 +1,18 @@
+CMAKE_FIND_USE_CMAKE_SYSTEM_PATH
+--------------------------------
+
+Controls the searching cmake platform specific variables by the
+:command:`find_program`, :command:`find_library`, :command:`find_file`,
+:command:`find_path`, and command:`find_package` commands.
+This is useful in cross-compiling environments.
+
+By default this variable is not set, which is equivalent to it having
+a value of ``TRUE``.  Explicit options given to the :command:`find_program`,
+:command:`find_library`, :command:`find_file`, and :command:`find_path`
+commands take precedence over this variable.
+
+See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,
+and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables.
diff --git a/Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst b/Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst
new file mode 100644
index 0000000..75e910f
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst
@@ -0,0 +1,29 @@
+CMAKE_FIND_USE_PACKAGE_REGISTRY
+-------------------------------
+
+Controls the searching the :ref:`User Package Registry` by the :command:`find_package`
+command.
+
+By default this variable is not set and the behavior will fall back
+to that determined by the deprecated :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`
+variable.  If that is also not set, then `find_package()` will use the
+`User Package Registry` unless the `NO_CMAKE_PACKAGE_REGISTRY` option
+is provided.
+
+This variable takes precedence over :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`
+when both are set.
+
+In some cases, for example to locate only system wide installations, it
+is not desirable to use the :ref:`User Package Registry` when searching
+for packages. If the :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`
+variable is ``FALSE``, all the :command:`find_package` commands will skip
+the :ref:`User Package Registry` as if they were called with the
+``NO_CMAKE_PACKAGE_REGISTRY`` argument.
+
+See also :ref:`Disabling the Package Registry`.
+
+See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
+:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
+and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables.
diff --git a/Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst b/Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst
new file mode 100644
index 0000000..e17fdcc
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst
@@ -0,0 +1,18 @@
+CMAKE_FIND_USE_PACKAGE_ROOT_PATH
+--------------------------------
+
+Controls the searching of :variable:`<PackageName>_ROOT` variables by the
+:command:`find_program`, :command:`find_library`, :command:`find_file`,
+:command:`find_path`, and command:`find_package` commands.
+This is useful in cross-compiling environments.
+
+By default this variable is not set, which is equivalent to it having
+a value of ``TRUE``.  Explicit options given to the :command:`find_program`,
+:command:`find_library`, :command:`find_file`, and :command:`find_path`
+commands take precedence over this variable.
+
+See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
+:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
+and :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` variables.
diff --git a/Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst b/Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst
new file mode 100644
index 0000000..71432f6
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst
@@ -0,0 +1,18 @@
+CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH
+--------------------------------------
+
+Controls the searching the standard system environment variables by the
+:command:`find_program`, :command:`find_library`, :command:`find_file`,
+:command:`find_path`, and command:`find_package` commands.
+This is useful in cross-compiling environments.
+
+By default this variable is not set, which is equivalent to it having
+a value of ``TRUE``.  Explicit options given to the :command:`find_program`,
+:command:`find_library`, :command:`find_file`, and :command:`find_path`
+commands take precedence over this variable.
+
+See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
+:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,
+and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables.
diff --git a/Help/variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH.rst b/Help/variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH.rst
new file mode 100644
index 0000000..19ae5f3
--- /dev/null
+++ b/Help/variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH.rst
@@ -0,0 +1,9 @@
+CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH
+--------------------------------------
+
+Removes compiler defined rpaths durimg installation.
+
+``CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH`` is a boolean that if set to ``true``
+removes compiler defined rpaths from the project if the user also defines rpath
+with :prop_tgt:`INSTALL_RPATH`. This is used to initialize the target property
+:prop_tgt:`INSTALL_REMOVE_ENVIRONMENT_RPATH` for all targets.
diff --git a/Help/variable/CMAKE_MESSAGE_INDENT.rst b/Help/variable/CMAKE_MESSAGE_INDENT.rst
new file mode 100644
index 0000000..f7975ab
--- /dev/null
+++ b/Help/variable/CMAKE_MESSAGE_INDENT.rst
@@ -0,0 +1,30 @@
+CMAKE_MESSAGE_INDENT
+--------------------
+
+The :command:`message` command joins the strings from this list and for
+log levels of ``NOTICE`` and below, it prepends the resultant string to
+each line of the message.
+
+Example:
+
+.. code-block:: cmake
+
+  list(APPEND listVar one two three)
+
+  message(VERBOSE [[Collected items in the "listVar":]])
+  list(APPEND CMAKE_MESSAGE_INDENT "  ")
+
+  foreach(item IN LISTS listVar)
+    message(VERBOSE ${item})
+  endforeach()
+
+  list(POP_BACK CMAKE_MESSAGE_INDENT)
+  message(VERBOSE "No more indent")
+
+Which results in the following output:
+
+  -- Collected items in the "listVar":
+  --   one
+  --   two
+  --   tree
+  -- No more indent
diff --git a/Help/variable/CPACK_INSTALL_SCRIPT.rst b/Help/variable/CPACK_INSTALL_SCRIPT.rst
deleted file mode 100644
index 12a48a4..0000000
--- a/Help/variable/CPACK_INSTALL_SCRIPT.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-CPACK_INSTALL_SCRIPT
---------------------
-
-Extra CMake script provided by the user.
-
-If set this CMake script will be executed by CPack during its local
-[CPack-private] installation which is done right before packaging the
-files.  The script is not called by e.g.: ``make install``.
diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake
index f94fc5c..2f3b9e1 100644
--- a/Modules/BundleUtilities.cmake
+++ b/Modules/BundleUtilities.cmake
@@ -243,11 +243,13 @@
   endif()
 endif()
 
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
 # The functions defined in this file depend on the get_prerequisites function
 # (and possibly others) found in:
 #
-get_filename_component(BundleUtilities_cmake_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
-include("${BundleUtilities_cmake_dir}/GetPrerequisites.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/GetPrerequisites.cmake")
 
 
 function(get_bundle_main_executable bundle result_var)
@@ -280,7 +282,7 @@
       endif()
     endforeach()
 
-    if(NOT "${bundle_executable}" STREQUAL "")
+    if(NOT bundle_executable STREQUAL "")
       if(EXISTS "${bundle}/Contents/MacOS/${bundle_executable}")
         set(result "${bundle}/Contents/MacOS/${bundle_executable}")
       else()
@@ -600,17 +602,9 @@
       set_bundle_key_values(${keys_var} "${lib}" "${lib}" "${exepath}" "${dirs}" 0 "${main_rpaths}")
 
       set(prereqs "")
-      set(ignoreFile FALSE)
       get_filename_component(prereq_filename ${lib} NAME)
-      if(NOT "${CFG_IGNORE_ITEM}" STREQUAL "" )
-        foreach(item ${CFG_IGNORE_ITEM})
-            if("${item}" STREQUAL "${prereq_filename}")
-              set(ignoreFile TRUE)
-            endif()
-        endforeach()
-      endif()
 
-      if(NOT ignoreFile)
+      if(NOT prereq_filename IN_LIST CFG_IGNORE_ITEM)
         get_prerequisites("${lib}" prereqs 1 1 "${exepath}" "${dirs}" "${main_rpaths}")
         foreach(pr ${prereqs})
           set_bundle_key_values(${keys_var} "${lib}" "${pr}" "${exepath}" "${dirs}" 1 "${main_rpaths}")
@@ -627,7 +621,7 @@
     foreach(exe ${exes})
       # Main executable is scanned first above:
       #
-      if(NOT "${exe}" STREQUAL "${executable}")
+      if(NOT exe STREQUAL executable)
         # Add the exe itself to the keys:
         #
         set_bundle_key_values(${keys_var} "${exe}" "${exe}" "${exepath}" "${dirs}" 0 "${main_rpaths}")
@@ -643,17 +637,9 @@
       # Add each prerequisite to the keys:
       #
       set(prereqs "")
-      set(ignoreFile FALSE)
       get_filename_component(prereq_filename ${exe} NAME)
-      if(NOT "${CFG_IGNORE_ITEM}" STREQUAL "" )
-        foreach(item ${CFG_IGNORE_ITEM})
-            if("${item}" STREQUAL "${prereq_filename}")
-              set(ignoreFile TRUE)
-            endif()
-        endforeach()
-      endif()
 
-      if(NOT ignoreFile)
+      if(NOT prereq_filename IN_LIST CFG_IGNORE_ITEM)
         get_prerequisites("${exe}" prereqs 1 1 "${exepath}" "${dirs}" "${exe_rpaths}")
         foreach(pr ${prereqs})
           set_bundle_key_values(${keys_var} "${exe}" "${pr}" "${exepath}" "${dirs}" 1 "${exe_rpaths}")
@@ -665,7 +651,7 @@
 
     # preserve library symlink structure
     foreach(key ${${keys_var}})
-      if("${${key}_COPYFLAG}" STREQUAL 1)
+      if("${${key}_COPYFLAG}" STREQUAL "1")
         if(IS_SYMLINK "${${key}_RESOLVED_ITEM}")
           get_filename_component(target "${${key}_RESOLVED_ITEM}" REALPATH)
           set_bundle_key_values(${keys_var} "${exe}" "${target}" "${exepath}" "${dirs}" 1 "${exe_rpaths}")
@@ -682,7 +668,7 @@
           get_filename_component(resolved_item_compare "${resolved_item_compare}" NAME)
           get_filename_component(resolved_embedded_item_compare "${resolved_embedded_item_compare}" NAME)
 
-          if(NOT "${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
+          if(NOT resolved_item_compare STREQUAL resolved_embedded_item_compare)
             set(${key}_COPYFLAG "2")
             set(${key}_RESOLVED_ITEM "${${targetkey}_RESOLVED_EMBEDDED_ITEM}")
           endif()
@@ -716,7 +702,7 @@
     set(resolved_embedded_item_compare "${resolved_embedded_item}")
   endif()
 
-  if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
+  if(resolved_item_compare STREQUAL resolved_embedded_item_compare)
     message(STATUS "warning: resolved_item == resolved_embedded_item - not linking...")
   else()
     get_filename_component(target_dir "${resolved_embedded_item}" DIRECTORY)
@@ -738,7 +724,7 @@
     set(resolved_embedded_item_compare "${resolved_embedded_item}")
   endif()
 
-  if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
+  if(resolved_item_compare STREQUAL resolved_embedded_item_compare)
     message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
   else()
     #message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
@@ -761,7 +747,7 @@
     set(resolved_embedded_item_compare "${resolved_embedded_item}")
   endif()
 
-  if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
+  if(resolved_item_compare STREQUAL resolved_embedded_item_compare)
     message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
   else()
     if(BU_COPY_FULL_FRAMEWORK_CONTENTS)
@@ -841,12 +827,12 @@
   string(LENGTH "${resolved_embedded_item}" resolved_embedded_item_length)
   set(path_too_short 0)
   set(is_embedded 0)
-  if(${resolved_embedded_item_length} LESS ${exe_dotapp_dir_length})
+  if(resolved_embedded_item_length LESS exe_dotapp_dir_length)
     set(path_too_short 1)
   endif()
   if(NOT path_too_short)
     string(SUBSTRING "${resolved_embedded_item}" 0 ${exe_dotapp_dir_length} item_substring)
-    if("${exe_dotapp_dir}/" STREQUAL "${item_substring}")
+    if("${exe_dotapp_dir}/" STREQUAL item_substring)
       set(is_embedded 1)
     endif()
   endif()
@@ -1032,18 +1018,9 @@
       message(STATUS "executable file ${count}: ${f}")
 
       set(prereqs "")
-      set(ignoreFile FALSE)
       get_filename_component(prereq_filename ${f} NAME)
 
-      if(NOT "${CFG_IGNORE_ITEM}" STREQUAL "" )
-        foreach(item ${CFG_IGNORE_ITEM})
-            if("${item}" STREQUAL "${prereq_filename}")
-              set(ignoreFile TRUE)
-            endif()
-        endforeach()
-      endif()
-
-      if(NOT ignoreFile)
+      if(NOT prereq_filename IN_LIST CFG_IGNORE_ITEM)
         get_item_rpaths(${f} _main_exe_rpaths)
         get_prerequisites("${f}" prereqs 1 1 "${exepath}" "${_main_exe_rpaths}")
 
@@ -1063,11 +1040,11 @@
           gp_file_type("${f}" "${p}" p_type)
 
           if(APPLE)
-            if(NOT "${p_type}" STREQUAL "embedded" AND NOT "${p_type}" STREQUAL "system")
+            if(NOT p_type STREQUAL "embedded" AND NOT p_type STREQUAL "system")
               set(external_prereqs ${external_prereqs} "${p}")
             endif()
           else()
-            if(NOT "${p_type}" STREQUAL "local" AND NOT "${p_type}" STREQUAL "system")
+            if(NOT p_type STREQUAL "local" AND NOT p_type STREQUAL "system")
               set(external_prereqs ${external_prereqs} "${p}")
             endif()
           endif()
@@ -1142,3 +1119,5 @@
     message(FATAL_ERROR "error: verify_app failed")
   endif()
 endfunction()
+
+cmake_policy(POP)
diff --git a/Modules/CMakeDetermineCSharpCompiler.cmake b/Modules/CMakeDetermineCSharpCompiler.cmake
index dab9414..da860a8 100644
--- a/Modules/CMakeDetermineCSharpCompiler.cmake
+++ b/Modules/CMakeDetermineCSharpCompiler.cmake
@@ -18,7 +18,6 @@
   set(CMAKE_CSharp_COMPILER_ID_RUN 1)
 
   # Try to identify the compiler.
-  set(CMAKE_CSharp_COMPILER_ID_STRINGS_PARAMETERS ENCODING UTF-16LE)
   set(CMAKE_CSharp_COMPILER_ID)
   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
   CMAKE_DETERMINE_COMPILER_ID(CSharp CSFLAGS CMakeCSharpCompilerId.cs)
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index 6083358..0fcbbb7 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -138,7 +138,7 @@
 
   set(_variant "")
   if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang")
-    if(CMAKE_HOST_WIN32 AND "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC")
+    if("x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC")
       if(CMAKE_GENERATOR MATCHES "Visual Studio")
         set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "MSVC")
       else()
@@ -640,10 +640,14 @@
     set(ARCHITECTURE_ID)
     set(SIMULATE_ID)
     set(SIMULATE_VERSION)
-    file(STRINGS ${file}
-      CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38
-      ${CMAKE_${lang}_COMPILER_ID_STRINGS_PARAMETERS}
-      REGEX ".?I.?N.?F.?O.?:.?[A-Za-z0-9_]+\\[[^]]*\\]")
+    foreach(encoding "" "ENCODING;UTF-16LE" "ENCODING;UTF-16BE")
+      file(STRINGS "${file}" CMAKE_${lang}_COMPILER_ID_STRINGS
+        LIMIT_COUNT 38 ${encoding}
+        REGEX ".?I.?N.?F.?O.?:.?[A-Za-z0-9_]+\\[[^]]*\\]")
+      if(NOT CMAKE_${lang}_COMPILER_ID_STRINGS STREQUAL "")
+        break()
+      endif()
+    endforeach()
     set(COMPILER_ID_TWICE)
     # With the IAR Compiler, some strings are found twice, first time as incomplete
     # list like "?<Constant "INFO:compiler[IAR]">".  Remove the incomplete copies.
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 0e84116..773ee53 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -72,7 +72,7 @@
   find_program(CMAKE_LINKER NAMES link HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
   find_program(CMAKE_MT     NAMES mt   HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
 
-  list(APPEND _CMAKE_TOOL_VARS CMAKE_LINKER CMAKE_MT)
+  list(APPEND _CMAKE_TOOL_VARS LINKER MT)
 
 # in all other cases search for ar, ranlib, etc.
 else()
@@ -84,27 +84,36 @@
   endif()
 
   if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang)
-    set(LLVM_OBJDUMP "llvm-objdump")
-    set(LLVM_LLD "ld.lld")
-    set(LLVM_RANLIB "llvm-ranlib")
-    set(LLVM_AR "llvm-ar")
+    set(_CMAKE_ADDITIONAL_AR_NAMES "llvm-ar")
+    set(_CMAKE_ADDITIONAL_RANLIB_NAMES "llvm-ranlib")
+    set(_CMAKE_ADDITIONAL_STRIP_NAMES "llvm-strip")
+    set(_CMAKE_ADDITIONAL_LINKER_NAMES "ld.lld")
+    set(_CMAKE_ADDITIONAL_NM_NAMES "llvm-nm")
+    set(_CMAKE_ADDITIONAL_OBJDUMP_NAMES "llvm-objdump")
+    set(_CMAKE_ADDITIONAL_OBJCOPY_NAMES "llvm-objcopy")
+    set(_CMAKE_ADDITIONAL_READELF_NAMES "llvm-readelf")
+    set(_CMAKE_ADDITIONAL_DLLTOOL_NAMES "llvm-dlltool")
+    set(_CMAKE_ADDITIONAL_ADDR2LINE_NAMES "llvm-addr2line")
   endif()
 
-  find_program(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar${_CMAKE_TOOLCHAIN_SUFFIX} ${LLVM_AR} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar${_CMAKE_TOOLCHAIN_SUFFIX} ${_CMAKE_ADDITIONAL_AR_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
 
-  find_program(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib ${LLVM_RANLIB} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib ${_CMAKE_ADDITIONAL_RANLIB_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
   if(NOT CMAKE_RANLIB)
     set(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib")
   endif()
 
 
-  find_program(CMAKE_STRIP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}strip${_CMAKE_TOOLCHAIN_SUFFIX} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
-  find_program(CMAKE_LINKER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ld ${LLVM_LLD} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
-  find_program(CMAKE_NM NAMES ${_CMAKE_TOOLCHAIN_PREFIX}nm HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
-  find_program(CMAKE_OBJDUMP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objdump ${LLVM_OBJDUMP} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
-  find_program(CMAKE_OBJCOPY NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objcopy HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_STRIP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}strip${_CMAKE_TOOLCHAIN_SUFFIX} ${_CMAKE_ADDITIONAL_STRIP_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_LINKER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ld ${_CMAKE_ADDITIONAL_LINKER_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_NM NAMES ${_CMAKE_TOOLCHAIN_PREFIX}nm ${_CMAKE_ADDITIONAL_NM_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_OBJDUMP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objdump ${_CMAKE_ADDITIONAL_OBJDUMP_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_OBJCOPY NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objcopy ${_CMAKE_ADDITIONAL_OBJCOPY_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_READELF NAMES ${_CMAKE_TOOLCHAIN_PREFIX}readelf ${_CMAKE_ADDITIONAL_READELF_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_DLLTOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}dlltool ${_CMAKE_ADDITIONAL_DLLTOOL_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+  find_program(CMAKE_ADDR2LINE NAMES ${_CMAKE_TOOLCHAIN_PREFIX}addr2line ${_CMAKE_ADDITIONAL_ADDR2LINE_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
 
-  list(APPEND _CMAKE_TOOL_VARS CMAKE_AR CMAKE_RANLIB CMAKE_STRIP CMAKE_LINKER CMAKE_NM CMAKE_OBJDUMP CMAKE_OBJCOPY)
+  list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE)
 
 endif()
 
@@ -115,15 +124,16 @@
     message(FATAL_ERROR "Could not find install_name_tool, please check your installation.")
   endif()
 
-  list(APPEND _CMAKE_TOOL_VARS CMAKE_INSTALL_NAME_TOOL)
+  list(APPEND _CMAKE_TOOL_VARS INSTALL_NAME_TOOL)
 endif()
 
 # Mark any tool cache entries as advanced.
 foreach(var IN LISTS _CMAKE_TOOL_VARS)
-  get_property(_CMAKE_TOOL_CACHED CACHE ${var} PROPERTY TYPE)
+  get_property(_CMAKE_TOOL_CACHED CACHE CMAKE_${var} PROPERTY TYPE)
   if(_CMAKE_TOOL_CACHED)
-    mark_as_advanced(${var})
+    mark_as_advanced(CMAKE_${var})
   endif()
+  unset(_CMAKE_ADDITIONAL_${var}_NAMES)
 endforeach()
 unset(_CMAKE_TOOL_VARS)
 unset(_CMAKE_TOOL_CACHED)
diff --git a/Modules/CMakeRCInformation.cmake b/Modules/CMakeRCInformation.cmake
index 7bf6567..7c3a5ab 100644
--- a/Modules/CMakeRCInformation.cmake
+++ b/Modules/CMakeRCInformation.cmake
@@ -17,6 +17,17 @@
   ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake)
 include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL)
 
+# This should be included before the _INIT variables are
+# used to initialize the cache.  Since the rule variables
+# have if blocks on them, users can still define them here.
+# But, it should still be after the platform file so changes can
+# be made to those values.
+if(CMAKE_USER_MAKE_RULES_OVERRIDE)
+  # Save the full path of the file so try_compile can use it.
+  include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
+  set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
+endif()
+
 set(CMAKE_RC_FLAGS_INIT "$ENV{RCFLAGS} ${CMAKE_RC_FLAGS_INIT}")
 
 cmake_initialize_per_config_variable(CMAKE_RC_FLAGS "Flags for Windows Resource Compiler")
diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake
index f6510b9..58b0813 100644
--- a/Modules/CMakeSwiftInformation.cmake
+++ b/Modules/CMakeSwiftInformation.cmake
@@ -23,7 +23,13 @@
 endif()
 
 set(CMAKE_Swift_COMPILE_OPTIONS_TARGET "-target ")
-set(CMAKE_Swift_COMPILER_ARG1 -frontend)
+set(CMAKE_Swift_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "-tools-directory ")
+# NOTE(compnerd) the `-sdk` support is not yet ready in the compiler; when that
+# is fully working, we should be able to enable this.
+# set(CMAKE_Swift_COMPILE_OPTIONS_SYSROOT "-sdk ")
+# NOTE(compnerd) do not setup `-frontend` as we use the compiler as the driver
+# during the link phase and use that to drive the compilation
+set(CMAKE_Swift_COMPILER_ARG1 "")
 set(CMAKE_Swift_DEFINE_FLAG -D)
 set(CMAKE_Swift_FRAMEWORK_SEARCH_FLAG "-F ")
 set(CMAKE_Swift_LIBRARY_PATH_FLAG "-L ")
@@ -57,11 +63,7 @@
 endif()
 
 if(NOT CMAKE_Swift_CREATE_SHARED_LIBRARY)
-  if(CMAKE_Swift_COMPILER_TARGET)
-    set(CMAKE_Swift_CREATE_SHARED_LIBRARY "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <SONAME_FLAG> <TARGET_SONAME> <LINK_LIBRARIES>")
-  else()
-    set(CMAKE_Swift_CREATE_SHARED_LIBRARY "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <SONAME_FLAG> <TARGET_SONAME> <LINK_LIBRARIES>")
-  endif()
+  set(CMAKE_Swift_CREATE_SHARED_LIBRARY "<CMAKE_Swift_COMPILER> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <SONAME_FLAG> <TARGET_SONAME> <LINK_LIBRARIES>")
 endif()
 
 if(NOT CMAKE_Swift_CREATE_SHARED_MODULE)
@@ -69,19 +71,11 @@
 endif()
 
 if(NOT CMAKE_Swift_LINK_EXECUTABLE)
-  if(CMAKE_Swift_COMPILER_TARGET)
-    set(CMAKE_Swift_LINK_EXECUTABLE "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
-  else()
-    set(CMAKE_Swift_LINK_EXECUTABLE "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
-  endif()
+  set(CMAKE_Swift_LINK_EXECUTABLE "<CMAKE_Swift_COMPILER> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
 endif()
 
 if(NOT CMAKE_Swift_CREATE_STATIC_LIBRARY)
-  if(CMAKE_Swift_COMPILER_TARGET)
-    set(CMAKE_Swift_CREATE_STATIC_LIBRARY "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -static -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
-  else()
-    set(CMAKE_Swift_CREATE_STATIC_LIBRARY "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -static -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
-  endif()
+  set(CMAKE_Swift_CREATE_STATIC_LIBRARY "<CMAKE_Swift_COMPILER> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -static -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
 
   set(CMAKE_Swift_ARCHIVE_CREATE "<CMAKE_AR> crs <TARGET> <OBJECTS>")
   set(CMAKE_Swift_ARCHIVE_FINISH "")
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index c9008db..8a6a712 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -325,7 +325,21 @@
 
 .. variable:: CPACK_INSTALL_COMMANDS
 
-  Extra commands to install components.
+  Extra commands to install components.  The environment variable
+  ``CMAKE_INSTALL_PREFIX`` is set to the temporary install directory
+  during execution.
+
+.. variable:: CPACK_INSTALL_SCRIPTS
+
+  Extra CMake scripts executed by CPack during its local staging
+  installation, which is done right before packaging the files.
+  The scripts are not called by a standalone install (e.g.: ``make install``).
+  For every script, the following variables will be set:
+  :variable:`CMAKE_CURRENT_SOURCE_DIR`, :variable:`CMAKE_CURRENT_BINARY_DIR`
+  and :variable:`CMAKE_INSTALL_PREFIX` (which is set to the staging install
+  directory).  The singular form ``CMAKE_INSTALL_SCRIPT`` is supported as
+  an alternative variable for historical reasons, but its value is ignored if
+  ``CMAKE_INSTALL_SCRIPTS`` is set and a warning will be issued.
 
 .. variable:: CPACK_INSTALLED_DIRECTORIES
 
diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index 2cccd09..5c9079d 100644
--- a/Modules/CheckCXXSymbolExists.cmake
+++ b/Modules/CheckCXXSymbolExists.cmake
@@ -5,26 +5,38 @@
 CheckCXXSymbolExists
 --------------------
 
-Check if a symbol exists as a function, variable, or macro in C++
+Check if a symbol exists as a function, variable, or macro in ``C++``.
 
-.. command:: CHECK_CXX_SYMBOL_EXISTS
+.. command:: check_cxx_symbol_exists
 
   .. code-block:: cmake
 
-    CHECK_CXX_SYMBOL_EXISTS(<symbol> <files> <variable>)
+    check_cxx_symbol_exists(<symbol> <files> <variable>)
 
   Check that the ``<symbol>`` is available after including given header
   ``<files>`` and store the result in a ``<variable>``.  Specify the list of
   files in one argument as a semicolon-separated list.
-  ``CHECK_CXX_SYMBOL_EXISTS()`` can be used to check in C++ files, as
-  opposed to ``CHECK_SYMBOL_EXISTS()``, which works only for ``C``.
+  ``check_cxx_symbol_exists()`` can be used to check for symbols as seen by
+  the C++ compiler, as opposed to :command:`check_symbol_exists`, which always
+  uses the ``C`` compiler.
 
   If the header files define the symbol as a macro it is considered
   available and assumed to work.  If the header files declare the symbol
   as a function or variable then the symbol must also be available for
-  linking.  If the symbol is a type or enum value it will not be
-  recognized (consider using :module:`CheckTypeSize`
-  or :module:`CheckCXXSourceCompiles`).
+  linking.  If the symbol is a type, enum value, or C++ template it will
+  not be recognized: consider using the :module:`CheckTypeSize`
+  or :module:`CheckCXXSourceCompiles` module instead.
+
+.. note::
+
+  This command is unreliable when ``<symbol>`` is (potentially) an overloaded
+  function. Since there is no reliable way to predict whether a given function
+  in the system environment may be defined as an overloaded function or may be
+  an overloaded function on other systems or will become so in the future, it
+  is generally advised to use the :module:`CheckCXXSourceCompiles` module for
+  checking any function symbol (unless somehow you surely know the checked
+  function is not overloaded on other systems or will not be so in the
+  future).
 
 The following variables may be set before calling this macro to modify
 the way the check is run:
@@ -43,6 +55,17 @@
   command. See policy :policy:`CMP0075`.
 ``CMAKE_REQUIRED_QUIET``
   execute quietly without messages.
+
+For example:
+
+.. code-block:: cmake
+
+  include(CheckCXXSymbolExists)
+
+  # Check for macro SEEK_SET
+  check_cxx_symbol_exists(SEEK_SET "cstdio" HAVE_SEEK_SET)
+  # Check for function std::fopen
+  check_cxx_symbol_exists(std::fopen "cstdio" HAVE_STD_FOPEN)
 #]=======================================================================]
 
 include_guard(GLOBAL)
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index b9ef808..1053383 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -45,6 +45,17 @@
   command. See policy :policy:`CMP0075`.
 ``CMAKE_REQUIRED_QUIET``
   execute quietly without messages.
+
+For example:
+
+.. code-block:: cmake
+
+  include(CheckSymbolExists)
+
+  # Check for macro SEEK_SET
+  check_symbol_exists(SEEK_SET "stdio.h" HAVE_SEEK_SET)
+  # Check for function fopen
+  check_symbol_exists(fopen "stdio.h" HAVE_FOPEN)
 #]=======================================================================]
 
 include_guard(GLOBAL)
@@ -88,8 +99,28 @@
       string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
         "#include <${FILE}>\n")
     endforeach()
-    string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
-      "\nint main(int argc, char** argv)\n{\n  (void)argv;\n#ifndef ${SYMBOL}\n  return ((int*)(&${SYMBOL}))[argc];\n#else\n  (void)argc;\n  return 0;\n#endif\n}\n")
+    string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+int main(int argc, char** argv)
+{
+  (void)argv;")
+    set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];")
+    if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$")
+      # The SYMBOL has a legal macro name.  Test whether it exists as a macro.
+      string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+#ifndef ${SYMBOL}
+  ${_CSE_CHECK_NON_MACRO}
+#else
+  (void)argc;
+  return 0;
+#endif")
+    else()
+      # The SYMBOL cannot be a macro (e.g., a template function).
+      string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+  ${_CSE_CHECK_NON_MACRO}")
+    endif()
+    string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+}")
+    unset(_CSE_CHECK_NON_MACRO)
 
     configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
       "${SOURCEFILE}" @ONLY)
@@ -128,6 +159,7 @@
         "${OUTPUT}\nFile ${SOURCEFILE}:\n"
         "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
     endif()
+    unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
   endif()
 endmacro()
 
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
index d18adaf..45c5470 100644
--- a/Modules/Compiler/GNU-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -18,18 +18,18 @@
 set(_cmake_feature_test_cxx_decltype_auto "${GNU49_CXX14}")
 set(_cmake_feature_test_cxx_digit_separators "${GNU49_CXX14}")
 set(_cmake_feature_test_cxx_generic_lambdas "${GNU49_CXX14}")
-set(_cmake_feature_test_cxx_lambda_init_captures "${GNU49_CXX14}")
 # GNU 4.3 supports binary literals as an extension, but may warn about
 # use of extensions prior to GNU 4.9
 # http://stackoverflow.com/questions/16334024/difference-between-gcc-binary-literals-and-c14-ones
 set(_cmake_feature_test_cxx_binary_literals "${GNU49_CXX14}")
-# The feature below is documented as available in GNU 4.8 (by implementing an
+# The features below are documented as available in GNU 4.8 (by implementing an
 # earlier draft of the standard paper), but that version of the compiler
 # does not set __cplusplus to a value greater than 201103L until GNU 4.9:
 # http://gcc.gnu.org/onlinedocs/gcc-4.8.2/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
 # http://gcc.gnu.org/onlinedocs/gcc-4.9.0/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
 # So, CMake only reports availability for it with GNU 4.9 or later.
 set(_cmake_feature_test_cxx_return_type_deduction "${GNU49_CXX14}")
+set(_cmake_feature_test_cxx_lambda_init_captures "${GNU49_CXX14}")
 
 # Introduced in GCC 4.8.1
 set(GNU481_CXX11 "((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L")
diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake
index 18a4a75..e03ce3f 100644
--- a/Modules/Compiler/IAR-C.cmake
+++ b/Modules/Compiler/IAR-C.cmake
@@ -15,7 +15,7 @@
   set(CMAKE_C90_EXTENSION_COMPILE_OPTION --c89 -e)
   set(CMAKE_C99_STANDARD_COMPILE_OPTION "")
   set(CMAKE_C99_EXTENSION_COMPILE_OPTION -e)
-elseif()
+else()
   set(CMAKE_C90_STANDARD_COMPILE_OPTION "")
   set(CMAKE_C90_EXTENSION_COMPILE_OPTION -e)
 endif()
diff --git a/Modules/Compiler/XL.cmake b/Modules/Compiler/XL.cmake
index a9cec11..fc71ab4 100644
--- a/Modules/Compiler/XL.cmake
+++ b/Modules/Compiler/XL.cmake
@@ -18,6 +18,8 @@
   set(CMAKE_${lang}_RESPONSE_FILE_FLAG "-qoptfile=")
   set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-qoptfile=")
 
+  set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-qmkshrobj")
+
   set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
   set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
 
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 20b37d2..e55ed46 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -261,7 +261,9 @@
 
       ``GIT_SUBMODULES <module>...``
         Specific git submodules that should also be updated. If this option is
-        not provided, all git submodules will be updated.
+        not provided, all git submodules will be updated. When :policy:`CMP0097`
+        is set to ``NEW`` if this value is set to an empty string then no submodules
+        are initialized or updated.
 
       ``GIT_SHALLOW <bool>``
         When this option is enabled, the ``git clone`` operation will be given
@@ -1016,6 +1018,9 @@
       endif()
     else()
       set(key "${arg}")
+      if(key MATCHES GIT)
+       get_property(have_key TARGET ${name} PROPERTY ${ns}${key} SET)
+      endif()
     endif()
   endforeach()
 endfunction()
@@ -1060,7 +1065,7 @@
   "ExternalProject module."
   )
 
-function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify)
+function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify)
   if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5)
     # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path.
     set(git_checkout_explicit-- "--")
@@ -1074,7 +1079,7 @@
     message(FATAL_ERROR "Tag for git checkout should not be empty.")
   endif()
 
-  set(git_clone_options)
+  set(git_clone_options "--no-checkout")
   if(git_shallow)
     if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10)
       list(APPEND git_clone_options "--depth 1 --no-single-branch")
@@ -1145,11 +1150,14 @@
   message(FATAL_ERROR \"Failed to checkout tag: '${git_tag}'\")
 endif()
 
-execute_process(
-  COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update --recursive --init ${git_submodules}
-  WORKING_DIRECTORY \"${work_dir}/${src_name}\"
-  RESULT_VARIABLE error_code
-  )
+set(init_submodules ${init_submodules})
+if(init_submodules)
+  execute_process(
+    COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update --recursive --init ${git_submodules}
+    WORKING_DIRECTORY \"${work_dir}/${src_name}\"
+    RESULT_VARIABLE error_code
+    )
+endif()
 if(error_code)
   message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\")
 endif()
@@ -1226,7 +1234,7 @@
 endfunction()
 
 
-function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name git_submodules git_repository work_dir)
+function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name init_submodules git_submodules git_repository work_dir)
   if("${git_tag}" STREQUAL "")
     message(FATAL_ERROR "Tag for git checkout should not be empty.")
   endif()
@@ -1383,11 +1391,14 @@
     endif()
   endif()
 
-  execute_process(
-    COMMAND \"${git_EXECUTABLE}\" submodule update --recursive --init ${git_submodules}
-    WORKING_DIRECTORY \"${work_dir}/${src_name}\"
-    RESULT_VARIABLE error_code
-    )
+  set(init_submodules ${init_submodules})
+  if(init_submodules)
+    execute_process(
+      COMMAND \"${git_EXECUTABLE}\" submodule update --recursive --init ${git_submodules}
+      WORKING_DIRECTORY \"${work_dir}/${src_name}\"
+      RESULT_VARIABLE error_code
+      )
+  endif()
   if(error_code)
     message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\")
   endif()
@@ -1972,7 +1983,7 @@
     set(stderr_log "${logbase}-err.log")
   endif()
   set(code "
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.15)
 ${code_cygpath_make}
 set(command \"${command}\")
 set(log_merged \"${log_merged}\")
@@ -2420,7 +2431,15 @@
     if(NOT git_tag)
       set(git_tag "master")
     endif()
-    get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
+
+    set(git_init_submodules TRUE)
+    get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
+    if(git_submodules_set)
+      get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
+      if(git_submodules  STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
+        set(git_init_submodules FALSE)
+      endif()
+    endif()
 
     get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME)
     if(NOT git_remote_name)
@@ -2458,7 +2477,7 @@
     # The script will delete the source directory and then call git clone.
     #
     _ep_write_gitclone_script(${tmp_dir}/${name}-gitclone.cmake ${source_dir}
-      ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir}
+      ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir}
       ${stamp_dir}/${name}-gitinfo.txt ${stamp_dir}/${name}-gitclone-lastrun.txt "${tls_verify}"
       )
     set(comment "Performing download step (git clone) for '${name}'")
@@ -2723,9 +2742,18 @@
     if(NOT git_remote_name)
       set(git_remote_name "origin")
     endif()
-    get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
+
+    set(git_init_submodules TRUE)
+    get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
+    if(git_submodules_set)
+      get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
+      if(git_submodules  STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
+        set(git_init_submodules FALSE)
+      endif()
+    endif()
+
     _ep_write_gitupdate_script(${tmp_dir}/${name}-gitupdate.cmake
-      ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} "${git_submodules}" ${git_repository} ${work_dir}
+      ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules}" ${git_repository} ${work_dir}
       )
     set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake)
     set(always 1)
@@ -3138,6 +3166,10 @@
 
 
 function(ExternalProject_Add name)
+  cmake_policy(GET CMP0097 _EP_CMP0097
+    PARENT_SCOPE # undocumented, do not use outside of CMake
+    )
+
   _ep_get_configuration_subdir_suffix(cfgdir)
 
   # Add a custom target for the external project.
diff --git a/Modules/FindBacktrace.cmake b/Modules/FindBacktrace.cmake
index cf1632a..3d8ce88 100644
--- a/Modules/FindBacktrace.cmake
+++ b/Modules/FindBacktrace.cmake
@@ -74,7 +74,7 @@
   if(Backtrace_INCLUDE_DIR)
     # OpenBSD has libbacktrace renamed to libexecinfo
     find_library(Backtrace_LIBRARY "execinfo")
-  elseif()     # respect user wishes
+  else()     # respect user wishes
     set(_Backtrace_HEADER_TRY "backtrace.h")
     find_path(Backtrace_INCLUDE_DIR ${_Backtrace_HEADER_TRY})
     find_library(Backtrace_LIBRARY "backtrace")
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 3315505..b6859aa 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -375,6 +375,11 @@
   CUDA_nvcuvid_LIBRARY  -- CUDA Video Decoder library.
                            Only available for CUDA version 3.2+.
                            Windows only.
+  CUDA_nvToolsExt_LIBRARY
+                        -- NVIDA CUDA Tools Extension library.
+                           Available for CUDA version 5+.
+  CUDA_OpenCL_LIBRARY   -- NVIDA CUDA OpenCL library.
+                           Available for CUDA version 5+.
 
 #]=======================================================================]
 
@@ -642,6 +647,8 @@
   unset(CUDA_npps_LIBRARY CACHE)
   unset(CUDA_nvcuvenc_LIBRARY CACHE)
   unset(CUDA_nvcuvid_LIBRARY CACHE)
+  unset(CUDA_nvToolsExt_LIBRARY CACHE)
+  unset(CUDA_OpenCL_LIBRARY CACHE)
   unset(CUDA_GPU_DETECT_OUTPUT CACHE)
 endmacro()
 
@@ -973,6 +980,11 @@
   find_cuda_helper_libs(cublas_device)
 endif()
 
+if(NOT CUDA_VERSION VERSION_LESS "5.0")
+  find_cuda_helper_libs(nvToolsExt)
+  find_cuda_helper_libs(OpenCL)
+endif()
+
 if(NOT CUDA_VERSION VERSION_LESS "9.0")
   # In CUDA 9.0 NPP was nppi was removed
   find_cuda_helper_libs(nppc)
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index c9c3cce..844d36d 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -173,11 +173,15 @@
   #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}")
 endif()
 
-if(_libraries_work)
-  set(${LIBRARIES} ${${LIBRARIES}} ${_blas} ${_threads})
-else()
-  set(${LIBRARIES} FALSE)
-endif()
+ if(_libraries_work)
+   if("${_list}" STREQUAL "")
+     set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
+   else()
+     set(${LIBRARIES} ${${LIBRARIES}} ${_blas} ${_threads})
+   endif()
+ else()
+    set(${LIBRARIES} FALSE)
+ endif()
 
 endmacro()
 
@@ -206,6 +210,7 @@
 
 #intel lapack
 if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
+  if(NOT LAPACK_LIBRARIES)
   if (NOT WIN32)
     set(LAPACK_mkl_LM "-lm")
     set(LAPACK_mkl_LDL "-ldl")
@@ -280,6 +285,7 @@
     unset(LAPACK_mkl_LM)
     unset(LAPACK_mkl_LDL)
   endif ()
+  endif()
 endif()
 
 if (BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All")
@@ -426,5 +432,11 @@
   endif()
 endif()
 
+# On compilers that implicitly link LAPACK (such as ftn, cc, and CC on Cray HPC machines)
+# we used a placeholder for empty LAPACK_LIBRARIES to get through our logic above.
+if (LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
+  set(LAPACK_LIBRARIES "")
+endif()
+
 cmake_pop_check_state()
 set(CMAKE_FIND_LIBRARY_SUFFIXES ${_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index 9471be8..a79758f 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -310,11 +310,15 @@
   set(_MPI_${LANG}_COMPILER_NAMES "")
   foreach (id IN ITEMS GNU Intel MSVC PGI XL)
     if (NOT CMAKE_${LANG}_COMPILER_ID OR CMAKE_${LANG}_COMPILER_ID STREQUAL id)
-      list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_MPI_${id}_${LANG}_COMPILER_NAMES}${MPI_EXECUTABLE_SUFFIX})
+      foreach(_COMPILER_NAME IN LISTS _MPI_${id}_${LANG}_COMPILER_NAMES)
+        list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX})
+      endforeach()
     endif()
     unset(_MPI_${id}_${LANG}_COMPILER_NAMES)
   endforeach()
-  list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_MPI_${LANG}_GENERIC_COMPILER_NAMES}${MPI_EXECUTABLE_SUFFIX})
+  foreach(_COMPILER_NAME IN LISTS _MPI_${LANG}_GENERIC_COMPILER_NAMES)
+    list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX})
+  endforeach()
   unset(_MPI_${LANG}_GENERIC_COMPILER_NAMES)
 endforeach()
 
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 3547642..c8cae2e 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -224,6 +224,9 @@
   this list.
 #]=======================================================================]
 
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
 set(_FindMatlab_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}")
 
 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
@@ -395,7 +398,7 @@
       )
 
 
-    if(${resultMatlab} EQUAL 0)
+    if(resultMatlab EQUAL 0)
 
       string(
         REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)"
@@ -606,15 +609,25 @@
     set(devnull INPUT_FILE NUL)
   endif()
 
+  if(WIN32)
+    # this environment variable is used to determine the arch on Windows
+    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+      set(ENV{MATLAB_ARCH} "win64")
+    else()
+      set(ENV{MATLAB_ARCH} "win32")
+    endif()
+  endif()
+
   # this is the preferred way. If this does not work properly (eg. MCR on Windows), then we use our own knowledge
   execute_process(
     COMMAND ${Matlab_MEXEXTENSIONS_PROG}
     OUTPUT_VARIABLE _matlab_mex_extension
-    #RESULT_VARIABLE _matlab_mex_extension_call
     ERROR_VARIABLE _matlab_mex_extension_error
+    OUTPUT_STRIP_TRAILING_WHITESPACE
     ${devnull})
+  unset(ENV{MATLAB_ARCH})
 
-  if(NOT "${_matlab_mex_extension_error}" STREQUAL "")
+  if(_matlab_mex_extension_error)
     if(WIN32)
       # this is only for intel architecture
       if(CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -627,7 +640,7 @@
 
   string(STRIP "${_matlab_mex_extension}"  _matlab_mex_extension)
   if(MATLAB_FIND_DEBUG)
-    message(STATUS "[MATLAB] '${Matlab_MEXEXTENSIONS_PROG}' : returned '${_matlab_mex_extension_call}', determined extension '${_matlab_mex_extension}' and error string is '${_matlab_mex_extension_error}'")
+    message(STATUS "[MATLAB] '${Matlab_MEXEXTENSIONS_PROG}' : determined extension '${_matlab_mex_extension}' and error string is '${_matlab_mex_extension_error}'")
   endif()
 
   unset(Matlab_MEXEXTENSIONS_PROG CACHE)
@@ -700,7 +713,7 @@
     ${devnull}
     )
 
-  if("${_matlab_result_version_call}" MATCHES "timeout")
+  if(_matlab_result_version_call MATCHES "timeout")
     if(MATLAB_FIND_DEBUG)
       message(WARNING "[MATLAB] Unable to determine the version of Matlab."
         " Matlab call timed out after 120 seconds.")
@@ -885,6 +898,7 @@
          [DOCUMENTATION file.txt]
          [LINK_TO target1 target2 ...]
          [R2017b | R2018a]
+         [EXCLUDE_FROM_ALL]
          [...]
      )
 
@@ -914,6 +928,10 @@
   ``MODULE`` or ``SHARED`` may be given to specify the type of library to be
     created. ``EXECUTABLE`` may be given to create an executable instead of
     a library. If no type is given explicitly, the type is ``SHARED``.
+  ``EXCLUDE_FROM_ALL``
+    This option has the same meaning as for :prop_tgt:`EXCLUDE_FROM_ALL` and
+    is forwarded to :command:`add_library` or :command:`add_executable`
+    commands.
 
   The documentation file is not processed and should be in the following
   format:
@@ -940,7 +958,7 @@
 
   endif()
 
-  set(options EXECUTABLE MODULE SHARED R2017b R2018a)
+  set(options EXECUTABLE MODULE SHARED R2017b R2018a EXCLUDE_FROM_ALL)
   set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME)
   set(multiValueArgs LINK_TO SRC)
 
@@ -955,14 +973,14 @@
     set(${prefix}_OUTPUT_NAME ${${prefix}_NAME})
   endif()
 
-  if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file
+  if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file
     # TODO: check the file extensions in ${${prefix}_SRC} to see if they're C or C++ files
     # Currently, the C and C++ versions of the version files are identical, so this doesn't matter.
     set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c")
     #set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp")
   endif()
 
-  if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro
+  if(NOT Matlab_VERSION_STRING VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro
     if(${${prefix}_R2018a})
       set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a")
     else()
@@ -970,8 +988,14 @@
     endif()
   endif()
 
+  set(_option_EXCLUDE_FROM_ALL)
+  if(${prefix}_EXCLUDE_FROM_ALL)
+    set(_option_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL")
+  endif()
+
   if(${prefix}_EXECUTABLE)
     add_executable(${${prefix}_NAME}
+      ${_option_EXCLUDE_FROM_ALL}
       ${${prefix}_SRC}
       ${MEX_VERSION_FILE}
       ${${prefix}_DOCUMENTATION}
@@ -985,6 +1009,7 @@
 
     add_library(${${prefix}_NAME}
       ${type}
+      ${_option_EXCLUDE_FROM_ALL}
       ${${prefix}_SRC}
       ${MEX_VERSION_FILE}
       ${${prefix}_DOCUMENTATION}
@@ -1023,18 +1048,13 @@
     if (MSVC)
 
       set(_link_flags "${_link_flags} /EXPORT:mexFunction")
-      if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version
+      if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version
         set(_link_flags "${_link_flags} /EXPORT:mexfilerequiredapiversion")
       endif()
 
-      if(Matlab_HAS_CPP_API)
-        set(_link_flags "${_link_flags} /EXPORT:mexCreateMexFunction /EXPORT:mexDestroyMexFunction /EXPORT:mexFunctionAdapter")
-        #TODO: Is this necessary?
-      endif()
-
       set_property(TARGET ${${prefix}_NAME} APPEND PROPERTY LINK_FLAGS ${_link_flags})
 
-    endif() # TODO: what if there's a different compiler on Windows?
+    endif() # No other compiler currently supported on Windows.
 
     set_target_properties(${${prefix}_NAME}
       PROPERTIES
@@ -1042,18 +1062,18 @@
 
   else()
 
-    if(${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For versions prior to 9.1 (R2016b)
+    if(Matlab_VERSION_STRING VERSION_LESS "9.1") # For versions prior to 9.1 (R2016b)
       set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/mexFunction.map)
     else()                                          # For 9.1 (R2016b) and newer
       set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/c_exportsmexfileversion.map)
     endif()
 
-    if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.5") # For 9.5 (R2018b) (and newer?)
+    if(NOT Matlab_VERSION_STRING VERSION_LESS "9.5") # For 9.5 (R2018b) (and newer?)
       target_compile_options(${${prefix}_NAME} PRIVATE "-fvisibility=default")
       # This one is weird, it might be a bug in <mex.h> for R2018b. When compiling with
       # -fvisibility=hidden, the symbol `mexFunction` cannot be exported. Reading the
       # source code for <mex.h>, it seems that the preprocessor macro `MW_NEEDS_VERSION_H`
-      # needs to be defined for `__attribute__ ((visibility("default")))` to be added
+      # needs to be defined for `__attribute__((visibility("default")))` to be added
       # in front of the declaration of `mexFunction`. In previous versions of MATLAB this
       # was not the case, there `DLL_EXPORT_SYM` needed to be defined.
       # Adding `-fvisibility=hidden` to the `mex` command causes the build to fail.
@@ -1089,11 +1109,13 @@
       set(_link_flags "${_link_flags} -Wl,${_export_flag_name},${_file}")
     endforeach()
 
+    # The `mex` command doesn't add this define. It is specified here in order
+    # to export the symbol in case the client code decides to hide its symbols
     set_target_properties(${${prefix}_NAME}
       PROPERTIES
-        DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__ ((visibility (\"default\")))"
+        DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__((visibility(\"default\")))"
         LINK_FLAGS "${_link_flags}"
-    ) # The `mex` command doesn't add this define. Is it necessary?
+    )
 
   endif()
 
@@ -1112,14 +1134,14 @@
   #  set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version")
   #endif()
 
-  if(NOT ${matlab_known_version} STREQUAL "NOTFOUND")
+  if(NOT matlab_known_version STREQUAL "NOTFOUND")
     # the version is known, we just return it
     set(${matlab_final_version} ${matlab_known_version} PARENT_SCOPE)
     set(Matlab_VERSION_STRING_INTERNAL ${matlab_known_version} CACHE INTERNAL "Matlab version (automatically determined)" FORCE)
     return()
   endif()
 
-  if("${matlab_or_mcr}" STREQUAL "UNKNOWN")
+  if(matlab_or_mcr STREQUAL "UNKNOWN")
     if(MATLAB_FIND_DEBUG)
       message(WARNING "[MATLAB] Determining Matlab or MCR")
     endif()
@@ -1134,10 +1156,10 @@
 
       # default fallback to Matlab
       set(matlab_or_mcr "MATLAB")
-      if(NOT "${CMAKE_MATCH_1}" STREQUAL "")
+      if(NOT CMAKE_MATCH_1 STREQUAL "")
         string(TOLOWER "${CMAKE_MATCH_1}" product_reg_match)
 
-        if("${product_reg_match}" STREQUAL "matlab runtime")
+        if(product_reg_match STREQUAL "matlab runtime")
           set(matlab_or_mcr "MCR")
         endif()
       endif()
@@ -1151,7 +1173,7 @@
   # UNKNOWN is the default behaviour in case we
   # - have an erroneous matlab_root
   # - have an initial 'UNKNOWN'
-  if("${matlab_or_mcr}" STREQUAL "MATLAB" OR "${matlab_or_mcr}" STREQUAL "UNKNOWN")
+  if(matlab_or_mcr STREQUAL "MATLAB" OR matlab_or_mcr STREQUAL "UNKNOWN")
     # MATLAB versions
     set(_matlab_current_program ${Matlab_MAIN_PROGRAM})
 
@@ -1203,7 +1225,7 @@
     matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions)
 
     list(LENGTH matlab_list_of_all_versions list_of_all_versions_length)
-    if(${list_of_all_versions_length} GREATER 0)
+    if(list_of_all_versions_length GREATER 0)
       list(GET matlab_list_of_all_versions 0 _matlab_version_tmp)
     else()
       set(_matlab_version_tmp "unknown")
@@ -1213,7 +1235,7 @@
     set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE)
 
     # warning, just in case several versions found (should not happen)
-    if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG)
+    if((list_of_all_versions_length GREATER 1) AND MATLAB_FIND_DEBUG)
       message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})")
     endif()
 
@@ -1233,10 +1255,8 @@
              ${versioninfo_string}
             )
 
-      if(NOT "${version_reg_match}" STREQUAL "")
-        if("${CMAKE_MATCH_1}" MATCHES "(([0-9])\\.([0-9]))[\\.0-9]*")
-          set(_matlab_version_tmp "${CMAKE_MATCH_1}")
-        endif()
+      if(CMAKE_MATCH_1 MATCHES "(([0-9])\\.([0-9]))[\\.0-9]*")
+        set(_matlab_version_tmp "${CMAKE_MATCH_1}")
       endif()
     endif()
     set(${matlab_final_version} "${_matlab_version_tmp}" PARENT_SCOPE)
@@ -1442,14 +1462,28 @@
 set(Matlab_VERSION_STRING "NOTFOUND")
 set(Matlab_Or_MCR "UNKNOWN")
 if(_numbers_of_matlab_roots GREATER 0)
-  list(GET _matlab_possible_roots 0 Matlab_Or_MCR)
-  list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING)
-  list(GET _matlab_possible_roots 2 Matlab_ROOT_DIR)
+  if(Matlab_FIND_VERSION_EXACT)
+    list(FIND _matlab_possible_roots ${Matlab_FIND_VERSION} _list_index)
+    if(_list_index LESS 0)
+      set(_list_index 1)
+    endif()
 
-  # adding a warning in case of ambiguity
-  if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG)
-    message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})."
-                    " If this is not the desired behaviour, provide the -DMatlab_ROOT_DIR=... on the command line")
+    math(EXPR _matlab_or_mcr_index "${_list_index} - 1")
+    math(EXPR _matlab_root_dir_index "${_list_index} + 1")
+
+    list(GET _matlab_possible_roots ${_matlab_or_mcr_index} Matlab_Or_MCR)
+    list(GET _matlab_possible_roots ${_list_index} Matlab_VERSION_STRING)
+    list(GET _matlab_possible_roots ${_matlab_root_dir_index} Matlab_ROOT_DIR)
+  else()
+    list(GET _matlab_possible_roots 0 Matlab_Or_MCR)
+    list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING)
+    list(GET _matlab_possible_roots 2 Matlab_ROOT_DIR)
+
+    # adding a warning in case of ambiguity
+    if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG)
+      message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})."
+                      " If this is not the desired behaviour, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line")
+    endif()
   endif()
 endif()
 
@@ -1503,7 +1537,9 @@
   message(STATUS "[MATLAB] Current version is ${Matlab_VERSION_STRING} located ${Matlab_ROOT_DIR}")
 endif()
 
-if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # MATLAB 9.4 (R2018a) and newer have a new C++ API
+# MATLAB 9.4 (R2018a) and newer have a new C++ API
+# This API pulls additional required libraries.
+if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4")
   set(Matlab_HAS_CPP_API 1)
 endif()
 
@@ -1589,6 +1625,10 @@
 
 set(_matlab_required_variables)
 
+# Order is as follow:
+# - unconditionally required libraries/headers first
+# - then library components
+# - then program components
 
 # the MEX library/header are required
 find_path(
@@ -1614,38 +1654,6 @@
 # the matlab root is required
 list(APPEND _matlab_required_variables Matlab_ROOT_DIR)
 
-# component Mex Compiler
-list(FIND Matlab_FIND_COMPONENTS MEX_COMPILER _matlab_find_mex_compiler)
-if(_matlab_find_mex_compiler GREATER -1)
-  find_program(
-    Matlab_MEX_COMPILER
-    "mex"
-    PATHS ${Matlab_BINARIES_DIR}
-    DOC "Matlab MEX compiler"
-    NO_DEFAULT_PATH
-  )
-  if(Matlab_MEX_COMPILER)
-    set(Matlab_MEX_COMPILER_FOUND TRUE)
-  endif()
-endif()
-unset(_matlab_find_mex_compiler)
-
-# component Matlab program
-list(FIND Matlab_FIND_COMPONENTS MAIN_PROGRAM _matlab_find_matlab_program)
-if(_matlab_find_matlab_program GREATER -1)
-  find_program(
-    Matlab_MAIN_PROGRAM
-    matlab
-    PATHS ${Matlab_ROOT_DIR} ${Matlab_ROOT_DIR}/bin
-    DOC "Matlab main program"
-    NO_DEFAULT_PATH
-  )
-  if(Matlab_MAIN_PROGRAM)
-    set(Matlab_MAIN_PROGRAM_FOUND TRUE)
-  endif()
-endif()
-unset(_matlab_find_matlab_program)
-
 # The MX library is required
 _Matlab_find_library(
   ${_matlab_lib_prefix_for_search}
@@ -1659,70 +1667,6 @@
   set(Matlab_MX_LIBRARY_FOUND TRUE)
 endif()
 
-# Component ENG library
-list(FIND Matlab_FIND_COMPONENTS ENG_LIBRARY _matlab_find_eng)
-if(_matlab_find_eng GREATER -1)
-  _Matlab_find_library(
-    ${_matlab_lib_prefix_for_search}
-    Matlab_ENG_LIBRARY
-    eng
-    PATHS ${_matlab_lib_dir_for_search}
-    NO_DEFAULT_PATH
-  )
-  if(Matlab_ENG_LIBRARY)
-    set(Matlab_ENG_LIBRARY_FOUND TRUE)
-  endif()
-endif()
-unset(_matlab_find_eng)
-
-# Component MAT library
-list(FIND Matlab_FIND_COMPONENTS MAT_LIBRARY _matlab_find_mat)
-if(_matlab_find_mat GREATER -1)
-  _Matlab_find_library(
-    ${_matlab_lib_prefix_for_search}
-    Matlab_MAT_LIBRARY
-    mat
-    PATHS ${_matlab_lib_dir_for_search}
-    NO_DEFAULT_PATH
-  )
-  if(Matlab_MAT_LIBRARY)
-    set(Matlab_MAT_LIBRARY_FOUND TRUE)
-  endif()
-endif()
-unset(_matlab_find_mat)
-
-# Component Simulink
-list(FIND Matlab_FIND_COMPONENTS SIMULINK _matlab_find_simulink)
-if(_matlab_find_simulink GREATER -1)
-  find_path(
-    Matlab_SIMULINK_INCLUDE_DIR
-    simstruc.h
-    PATHS "${Matlab_ROOT_DIR}/simulink/include"
-    NO_DEFAULT_PATH
-    )
-  if(Matlab_SIMULINK_INCLUDE_DIR)
-    set(Matlab_SIMULINK_FOUND TRUE)
-    list(APPEND Matlab_INCLUDE_DIRS "${Matlab_SIMULINK_INCLUDE_DIR}")
-  endif()
-endif()
-unset(_matlab_find_simulink)
-
-# component MCC Compiler
-list(FIND Matlab_FIND_COMPONENTS MCC_COMPILER _matlab_find_mcc_compiler)
-if(_matlab_find_mcc_compiler GREATER -1)
-  find_program(
-    Matlab_MCC_COMPILER
-    "mcc"
-    PATHS ${Matlab_BINARIES_DIR}
-    DOC "Matlab MCC compiler"
-    NO_DEFAULT_PATH
-  )
-  if(Matlab_MCC_COMPILER)
-    set(Matlab_MCC_COMPILER_FOUND TRUE)
-  endif()
-endif()
-unset(_matlab_find_mcc_compiler)
-
 if(Matlab_HAS_CPP_API)
 
   # The MatlabEngine library is required for R2018a+
@@ -1755,7 +1699,89 @@
 
 endif()
 
-unset(_matlab_lib_dir_for_search)
+# Component ENG library
+if("ENG_LIBRARY" IN_LIST Matlab_FIND_COMPONENTS)
+  _Matlab_find_library(
+    ${_matlab_lib_prefix_for_search}
+    Matlab_ENG_LIBRARY
+    eng
+    PATHS ${_matlab_lib_dir_for_search}
+    NO_DEFAULT_PATH
+  )
+  if(Matlab_ENG_LIBRARY)
+    set(Matlab_ENG_LIBRARY_FOUND TRUE)
+  endif()
+endif()
+
+# Component MAT library
+if("MAT_LIBRARY" IN_LIST Matlab_FIND_COMPONENTS)
+  _Matlab_find_library(
+    ${_matlab_lib_prefix_for_search}
+    Matlab_MAT_LIBRARY
+    mat
+    PATHS ${_matlab_lib_dir_for_search}
+    NO_DEFAULT_PATH
+  )
+  if(Matlab_MAT_LIBRARY)
+    set(Matlab_MAT_LIBRARY_FOUND TRUE)
+  endif()
+endif()
+
+# Component Simulink
+if("SIMULINK" IN_LIST Matlab_FIND_COMPONENTS)
+  find_path(
+    Matlab_SIMULINK_INCLUDE_DIR
+    simstruc.h
+    PATHS "${Matlab_ROOT_DIR}/simulink/include"
+    NO_DEFAULT_PATH
+    )
+  if(Matlab_SIMULINK_INCLUDE_DIR)
+    set(Matlab_SIMULINK_FOUND TRUE)
+    list(APPEND Matlab_INCLUDE_DIRS "${Matlab_SIMULINK_INCLUDE_DIR}")
+  endif()
+endif()
+
+# component Matlab program
+if("MAIN_PROGRAM" IN_LIST Matlab_FIND_COMPONENTS)
+  find_program(
+    Matlab_MAIN_PROGRAM
+    matlab
+    PATHS ${Matlab_ROOT_DIR} ${Matlab_ROOT_DIR}/bin
+    DOC "Matlab main program"
+    NO_DEFAULT_PATH
+  )
+  if(Matlab_MAIN_PROGRAM)
+    set(Matlab_MAIN_PROGRAM_FOUND TRUE)
+  endif()
+endif()
+
+# component Mex Compiler
+if("MEX_COMPILER" IN_LIST Matlab_FIND_COMPONENTS)
+  find_program(
+    Matlab_MEX_COMPILER
+    "mex"
+    PATHS ${Matlab_BINARIES_DIR}
+    DOC "Matlab MEX compiler"
+    NO_DEFAULT_PATH
+  )
+  if(Matlab_MEX_COMPILER)
+    set(Matlab_MEX_COMPILER_FOUND TRUE)
+  endif()
+endif()
+
+# component MCC Compiler
+if("MCC_COMPILER" IN_LIST Matlab_FIND_COMPONENTS)
+  find_program(
+    Matlab_MCC_COMPILER
+    "mcc"
+    PATHS ${Matlab_BINARIES_DIR}
+    DOC "Matlab MCC compiler"
+    NO_DEFAULT_PATH
+  )
+  if(Matlab_MCC_COMPILER)
+    set(Matlab_MCC_COMPILER_FOUND TRUE)
+  endif()
+endif()
 
 set(Matlab_LIBRARIES
   ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY}
@@ -1792,3 +1818,5 @@
     Matlab_MEX_EXTENSION
   )
 endif()
+
+cmake_policy(POP)
diff --git a/Modules/FindPNG.cmake b/Modules/FindPNG.cmake
index a7908c5..bd400c7 100644
--- a/Modules/FindPNG.cmake
+++ b/Modules/FindPNG.cmake
@@ -69,8 +69,8 @@
     unset(_PNG_VERSION_SUFFIX_MIN)
   endif ()
   foreach(v IN LISTS _PNG_VERSION_SUFFIXES)
-    list(APPEND PNG_NAMES png${v} libpng${v})
-    list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d)
+    list(APPEND PNG_NAMES png${v} libpng${v} libpng${v}_static)
+    list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d libpng${v}_staticd)
   endforeach()
   unset(_PNG_VERSION_SUFFIXES)
   # For compatibility with versions prior to this multi-config search, honor
diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake
index 76bc873..2d45965 100644
--- a/Modules/FindProtobuf.cmake
+++ b/Modules/FindProtobuf.cmake
@@ -521,6 +521,16 @@
             set_target_properties(protobuf::libprotobuf PROPERTIES
               IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}")
           endif()
+          if (Protobuf_VERSION VERSION_GREATER_EQUAL "3.6")
+            set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
+              INTERFACE_COMPILE_FEATURES cxx_std_11
+            )
+          endif()
+          if (MSVC AND NOT Protobuf_USE_STATIC_LIBS)
+            set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
+              INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS"
+            )
+          endif()
           if(UNIX AND TARGET Threads::Threads)
             set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
                 INTERFACE_LINK_LIBRARIES Threads::Threads)
@@ -549,6 +559,11 @@
             set_target_properties(protobuf::libprotobuf-lite PROPERTIES
               IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}")
           endif()
+          if (MSVC AND NOT Protobuf_USE_STATIC_LIBS)
+            set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
+              INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS"
+            )
+          endif()
           if(UNIX AND TARGET Threads::Threads)
             set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
                 INTERFACE_LINK_LIBRARIES Threads::Threads)
@@ -577,6 +592,16 @@
             set_target_properties(protobuf::libprotoc PROPERTIES
               IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}")
           endif()
+          if (Protobuf_VERSION VERSION_GREATER_EQUAL "3.6")
+            set_property(TARGET protobuf::libprotoc APPEND PROPERTY
+              INTERFACE_COMPILE_FEATURES cxx_std_11
+            )
+          endif()
+          if (MSVC AND NOT Protobuf_USE_STATIC_LIBS)
+            set_property(TARGET protobuf::libprotoc APPEND PROPERTY
+              INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS"
+            )
+          endif()
           if(UNIX AND TARGET Threads::Threads)
             set_property(TARGET protobuf::libprotoc APPEND PROPERTY
                 INTERFACE_LINK_LIBRARIES Threads::Threads)
diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake
index e2f3bf3..6a9decb 100644
--- a/Modules/FindPython.cmake
+++ b/Modules/FindPython.cmake
@@ -137,6 +137,51 @@
   * If set to TRUE, search **only** for static libraries.
   * If set to FALSE, search **only** for shared libraries.
 
+``Python_FIND_ABI``
+  This variable defines which ABIs, as defined in
+  `PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched.
+
+  .. note::
+
+    This hint will be honored only when searched for ``Python`` version 3.
+
+  .. note::
+
+    If ``Python_FIND_ABI`` is not defined, any ABI will be searched.
+
+  The ``Python_FIND_ABI`` variable is a 3-tuple specifying, in that order,
+  ``pydebug`` (``d``), ``pymalloc`` (``m``) and ``unicode`` (``u``) flags.
+  Each element can be set to one of the following:
+
+  * ``ON``: Corresponding flag is selected.
+  * ``OFF``: Corresponding flag is not selected.
+  * ``ANY``: The two posibilties (``ON`` and ``OFF``) will be searched.
+
+  From this 3-tuple, various ABIs will be searched starting from the most
+  specialized to the most general. Moreover, ``debug`` versions will be
+  searched **after** ``non-debug`` ones.
+
+  For example, if we have::
+
+    set (Python_FIND_ABI "ON" "ANY" "ANY")
+
+  The following flags combinations will be appended, in that order, to the
+  artifact names: ``dmu``, ``dm``, ``du``, and ``d``.
+
+  And to search any possible ABIs::
+
+    set (Python_FIND_ABI "ANY" "ANY" "ANY")
+
+  The following combinations, in that order, will be used: ``mu``, ``m``,
+  ``u``, ``<empty>``, ``dmu``, ``dm``, ``du`` and ``d``.
+
+  .. note::
+
+    This hint is useful only on ``POSIX`` systems. So, on ``Windows`` systems,
+    when ``Python_FIND_ABI`` is defined, ``Python`` distributions from
+    `python.org <https://www.python.org/>`_ will be found only if value for
+    each flag is ``OFF`` or ``ANY``.
+
 ``Python_FIND_STRATEGY``
   This variable defines how lookup will be done.
   The ``Python_FIND_STRATEGY`` variable can be set to empty or one of the
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index 590c7af..8faec03 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -96,51 +96,149 @@
        PARENT_SCOPE)
 endfunction()
 
-function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES _PYTHON_VERSION _PYTHON_TYPE)
-  set (path_suffixes)
 
-  if (_PYTHON_TYPE STREQUAL "LIBRARY")
+function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS)
+  set (abiflags)
+  list (GET _${_PYTHON_PREFIX}_FIND_ABI 0 pydebug)
+  list (GET _${_PYTHON_PREFIX}_FIND_ABI 1 pymalloc)
+  list (GET _${_PYTHON_PREFIX}_FIND_ABI 2 unicode)
+
+  if (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ANY")
+    set (abiflags "mu" "m" "u" "")
+  elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ON")
+    set (abiflags "mu" "u")
+  elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "OFF")
+    set (abiflags "m" "")
+  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY")
+    set (abiflags "mu" "m")
+  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ON")
+    set (abiflags "mu")
+  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "OFF")
+    set (abiflags "m")
+  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY")
+    set (abiflags "u" "")
+  elseif (pymalloc STREQUAL "OFF" AND unicode STREQUAL "ON")
+    set (abiflags "u")
+  endif()
+
+  if (pydebug STREQUAL "ON")
+    if (abiflags)
+      list (TRANSFORM abiflags PREPEND "d")
+    else()
+      set (abiflags "d")
+    endif()
+  elseif (pydebug STREQUAL "ANY")
+    if (abiflags)
+      set (flags "${abiflags}")
+      list (TRANSFORM flags PREPEND "d")
+      list (APPEND abiflags "${flags}")
+    else()
+      set (abiflags "" "d")
+    endif()
+  endif()
+
+  set (${_PGABIFLAGS} "${abiflags}" PARENT_SCOPE)
+endfunction()
+
+function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES)
+  cmake_parse_arguments (PARSE_ARGV 1 _PGPS "LIBRARY;INCLUDE" "VERSION" "")
+
+  if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS)
+    set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}")
+  else()
+    set (abi "mu" "m" "u" "")
+  endif()
+
+  set (path_suffixes)
+  if (_PGPS_LIBRARY)
     if (CMAKE_LIBRARY_ARCHITECTURE)
       list (APPEND path_suffixes lib/${CMAKE_LIBRARY_ARCHITECTURE})
     endif()
     list (APPEND path_suffixes lib libs)
 
     if (CMAKE_LIBRARY_ARCHITECTURE)
-      list (APPEND path_suffixes lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}mu-${CMAKE_LIBRARY_ARCHITECTURE}
-                                 lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}m-${CMAKE_LIBRARY_ARCHITECTURE}
-                                 lib/python${_PYTHON_VERSION}/config-${CMAKE_MATCH_1}u-${CMAKE_LIBRARY_ARCHITECTURE}
-                                 lib/python${_PYTHON_VERSION}/config-${CMAKE_MATCH_1}-${CMAKE_LIBRARY_ARCHITECTURE})
+      set (suffixes "${abi}")
+      if (suffixes)
+        list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
+        list (TRANSFORM suffixes APPEND "-${CMAKE_LIBRARY_ARCHITECTURE}")
+      else()
+        set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}-${CMAKE_LIBRARY_ARCHITECTURE}")
+      endif()
+      list (APPEND path_suffixes ${suffixes})
     endif()
-    list (APPEND path_suffixes lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}mu
-                               lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}m
-                               lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}u
-                               lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}
-                               lib/python${_PYTHON_VERSION}/config)
-
-  elseif (_PYTHON_TYPE STREQUAL "INCLUDE")
-    list (APPEND path_suffixes include/python${_PYTHON_VERSION}mu
-                               include/python${_PYTHON_VERSION}m
-                               include/python${_PYTHON_VERSION}u
-                               include/python${_PYTHON_VERSION}
-                               include)
+    set (suffixes "${abi}")
+    if (suffixes)
+      list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
+    else()
+      set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
+    endif()
+    list (APPEND path_suffixes ${suffixes})
+  elseif (_PGPS_INCLUDE)
+    set (suffixes "${abi}")
+    if (suffixes)
+      list (TRANSFORM suffixes PREPEND "include/python${_PGPS_VERSION}")
+    else()
+      set (suffixes "include/python${_PGPS_VERSION}")
+    endif()
+    list (APPEND path_suffixes ${suffixes} include)
   endif()
 
   set (${_PYTHON_PGPS_PATH_SUFFIXES} ${path_suffixes} PARENT_SCOPE)
 endfunction()
 
-function (_PYTHON_GET_LIB_NAMES _PYTHON_PGLN_NAMES _PYTHON_VERSION)
-  string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PYTHON_VERSION})
+function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
+  cmake_parse_arguments (PARSE_ARGV 1 _PGN "POSIX;EXECUTABLE;CONFIG;LIBRARY;WIN32;DEBUG" "VERSION" "")
 
-  if (ARGC EQUAL 3 AND ARGV2 STREQUAL "DEBUG")
-    set (${_PYTHON_PGLN_NAMES} python${_PYTHON_VERSION_NO_DOTS}_d PARENT_SCOPE)
-  else()
-    set (${_PYTHON_PGLN_NAMES} python${_PYTHON_VERSION_NO_DOTS}
-                               python${_PYTHON_VERSION}mu
-                               python${_PYTHON_VERSION}m
-                               python${_PYTHON_VERSION}u
-                               python${_PYTHON_VERSION}
-         PARENT_SCOPE)
+  set (names)
+
+  if (_PGN_WIN32)
+    string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PGN_VERSION})
+
+    set (name python${_PYTHON_VERSION_NO_DOTS})
+    if (_PGN_DEBUG)
+      string (APPEND name "_d")
+    endif()
+
+    list (APPEND names "${name}")
   endif()
+
+  if (_PGN_POSIX)
+    if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS)
+      set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}")
+    else()
+      if (_PGN_EXECUTABLE OR _PGN_CONFIG)
+        set (abi "")
+      else()
+        set (abi "mu" "m" "u" "")
+      endif()
+    endif()
+
+    if (abi)
+      if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
+        set (abinames "${abi}")
+        list (TRANSFORM abinames PREPEND "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}")
+        list (TRANSFORM abinames APPEND "-config")
+        list (APPEND names ${abinames})
+      endif()
+      set (abinames "${abi}")
+      list (TRANSFORM abinames PREPEND "python${_PGN_VERSION}")
+      if (_PGN_CONFIG)
+        list (TRANSFORM abinames APPEND "-config")
+      endif()
+      list (APPEND names ${abinames})
+    else()
+      if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
+        set (abinames "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}")
+      endif()
+      list (APPEND abinames "python${_PGN_VERSION}")
+      if (_PGN_CONFIG)
+        list (TRANSFORM abinames APPEND "-config")
+      endif()
+      list (APPEND names ${abinames})
+    endif()
+  endif()
+
+  set (${_PYTHON_PGN_NAMES} ${names} PARENT_SCOPE)
 endfunction()
 
 
@@ -149,16 +247,35 @@
     return()
   endif()
 
-  cmake_parse_arguments (_PVI "EXACT" "" "" ${ARGN})
+  cmake_parse_arguments (PARSE_ARGV 0 _PVI "EXACT" "" "")
   if (_PVI_UNPARSED_ARGUMENTS)
     set (expected_version ${_PVI_UNPARSED_ARGUMENTS})
   else()
     unset (expected_version)
   endif()
 
+  # validate ABI compatibility
+  if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI)
+    execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+                             "import sys; sys.stdout.write(sys.abiflags)"
+                     RESULT_VARIABLE result
+                     OUTPUT_VARIABLE abi
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (result)
+      # assume ABI is not supported
+      set (abi "")
+    endif()
+    if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
+      # incompatible ABI
+      set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
+      return()
+    endif()
+  endif()
+
   get_filename_component (python_name "${${_PYTHON_PREFIX}_EXECUTABLE}" NAME)
 
-  if (expected_version AND NOT python_name STREQUAL "python${expected_version}${CMAKE_EXECUTABLE_SUFFIX}")
+  if (expected_version AND NOT python_name STREQUAL "python${expected_version}${abi}${CMAKE_EXECUTABLE_SUFFIX}")
     # executable found must have a specific version
     execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
                              "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))"
@@ -168,7 +285,7 @@
                      OUTPUT_STRIP_TRAILING_WHITESPACE)
     if (result OR (_PVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version))
       # interpreter not usable or has wrong major version
-      set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+      set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
       return()
     endif()
   else()
@@ -183,7 +300,7 @@
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
       if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
         # interpreter not usable or has wrong major version
-        set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+        set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
         return()
       endif()
     endif()
@@ -200,7 +317,7 @@
                      OUTPUT_STRIP_TRAILING_WHITESPACE)
     if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P)
       # interpreter not usable or has wrong architecture
-      set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+      set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
       return()
     endif()
   endif()
@@ -244,7 +361,7 @@
 
   if (result OR (_PVC_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version))
     # Compiler not usable or has wrong version
-    set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE)
+    set_property (CACHE ${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
   endif()
 endfunction()
 
@@ -321,6 +438,28 @@
   endif()
 endif()
 
+# Set ABIs to search
+## default: search any ABI
+if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS 3)
+  # ABI not supported
+  unset (_${_PYTHON_PREFIX}_FIND_ABI)
+  set (_${_PYTHON_PREFIX}_ABIFLAGS "")
+else()
+  unset (_${_PYTHON_PREFIX}_FIND_ABI)
+  unset (_${_PYTHON_PREFIX}_ABIFLAGS)
+  if (DEFINED ${_PYTHON_PREFIX}_FIND_ABI)
+    # normalization
+    string (TOUPPER "${${_PYTHON_PREFIX}_FIND_ABI}" _${_PYTHON_PREFIX}_FIND_ABI)
+    list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(TRUE|Y(ES)?|1)$" "ON")
+    list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(FALSE|N(O)?|0)$" "OFF")
+    if (NOT _${_PYTHON_PREFIX}_FIND_ABI MATCHES "^(ON|OFF|ANY);(ON|OFF|ANY);(ON|OFF|ANY)$")
+      message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_ABI}: invalid value for '${_PYTHON_PREFIX}_FIND_ABI'. Ignore it")
+      unset (_${_PYTHON_PREFIX}_FIND_ABI)
+    endif()
+    _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS)
+  endif()
+endif()
+
 # Define lookup strategy
 if (_${_PYTHON_PREFIX}_LOOKUP_POLICY STREQUAL "NEW")
   set (_${_PYTHON_PREFIX}_FIND_STRATEGY "LOCATION")
@@ -446,7 +585,8 @@
 
     foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
       # build all executable names
-      list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_VERSION})
+      _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE)
+      list (APPEND _${_PYTHON_PREFIX}_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES})
 
       # Framework Paths
       _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION})
@@ -516,12 +656,24 @@
         endif()
       endif()
 
-      # try using HINTS and standard paths
+      # try using HINTS
       find_program (${_PYTHON_PREFIX}_EXECUTABLE
                     NAMES ${_${_PYTHON_PREFIX}_NAMES}
                           ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
                     NAMES_PER_DIR
                     HINTS ${_${_PYTHON_PREFIX}_HINTS}
+                    PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
+                    NO_SYSTEM_ENVIRONMENT_PATH
+                    NO_CMAKE_SYSTEM_PATH)
+      _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
+      if (${_PYTHON_PREFIX}_EXECUTABLE)
+        break()
+      endif()
+      # try using standard paths
+      find_program (${_PYTHON_PREFIX}_EXECUTABLE
+                    NAMES ${_${_PYTHON_PREFIX}_NAMES}
+                          ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+                    NAMES_PER_DIR
                     PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES})
       _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION})
       if (${_PYTHON_PREFIX}_EXECUTABLE)
@@ -561,9 +713,9 @@
   else()
     # look-up for various versions and locations
     foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
-      set (_${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_VERSION}
-                                    python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
-                                    python)
+      _python_get_names (_${_PYTHON_PREFIX}_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE)
+      list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+                                            python)
 
       _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
       _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION})
@@ -643,12 +795,12 @@
       # systematically 'python' (i.e. version 2) even if version 3 is searched.
       if (CMAKE_HOST_WIN32)
         find_program (${_PYTHON_PREFIX}_EXECUTABLE
-                      NAMES python${_${_PYTHON_PREFIX}_VERSION}
+                      NAMES ${_${_PYTHON_PREFIX}_NAMES}
                             python
                             ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES})
       else()
         find_program (${_PYTHON_PREFIX}_EXECUTABLE
-                      NAMES python${_${_PYTHON_PREFIX}_VERSION})
+                      NAMES ${_${_PYTHON_PREFIX}_NAMES})
       endif()
       _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT)
       if (${_PYTHON_PREFIX}_EXECUTABLE)
@@ -715,7 +867,7 @@
       list (GET _${_PYTHON_PREFIX}_VERSIONS 2 ${_PYTHON_PREFIX}_VERSION_PATCH)
     else()
       # Interpreter is not usable
-      set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+      set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
       unset (${_PYTHON_PREFIX}_VERSION)
     endif()
   endif()
@@ -723,8 +875,17 @@
   if (${_PYTHON_PREFIX}_EXECUTABLE
       AND ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
     set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE)
-    # Use interpreter version for future searches to ensure consistency
+    # Use interpreter version and ABI for future searches to ensure consistency
     set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+    execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.abiflags)"
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_ABIFLAGS
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (_${_PYTHON_PREFIX}_RESULT)
+      # assunme ABI is not supported
+      set (_${_PYTHON_PREFIX}_ABIFLAGS "")
+    endif()
   endif()
 
   if (${_PYTHON_PREFIX}_Interpreter_FOUND)
@@ -932,7 +1093,7 @@
       endif()
     else()
       # compiler not usable
-      set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE)
+      set_property (CACHE ${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
     endif()
     file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
   endif()
@@ -1014,16 +1175,15 @@
       endif()
     endif()
   endif()
-  set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_EXEC_PREFIX}" "${_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+  set (_${_PYTHON_PREFIX}_BASE_HINTS "${_${_PYTHON_PREFIX}_EXEC_PREFIX}" "${_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+  set (_${_PYTHON_PREFIX}_HINTS ${_${_PYTHON_PREFIX}_BASE_HINTS})
 
   if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION")
     set (_${_PYTHON_PREFIX}_CONFIG_NAMES)
 
     foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
-      if (DEFINED CMAKE_LIBRARY_ARCHITECTURE)
-        list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "${CMAKE_LIBRARY_ARCHITECTURE}-python${_${_PYTHON_PREFIX}_VERSION}-config")
-      endif()
-      list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "python${_${_PYTHON_PREFIX}_VERSION}-config")
+      _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG)
+      list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES})
     endforeach()
 
     find_program (_${_PYTHON_PREFIX}_CONFIG
@@ -1032,6 +1192,22 @@
                   HINTS ${_${_PYTHON_PREFIX}_HINTS}
                   PATH_SUFFIXES bin)
 
+    if (_${_PYTHON_PREFIX}_CONFIG)
+      execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags
+                       RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                       OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS
+                       ERROR_QUIET
+                       OUTPUT_STRIP_TRAILING_WHITESPACE)
+      if (_${_PYTHON_PREFIX}_RESULT)
+        # assume ABI is not supported
+        set (__${_PYTHON_PREFIX}_ABIFLAGS "")
+      endif()
+      if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
+        # Wrong ABI
+        unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
+      endif()
+    endif()
+
     if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
       # check that config tool match library architecture
       execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir
@@ -1051,11 +1227,7 @@
   else()
     foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
       # try to use pythonX.Y-config tool
-      set (_${_PYTHON_PREFIX}_CONFIG_NAMES)
-      if (DEFINED CMAKE_LIBRARY_ARCHITECTURE)
-        set (_${_PYTHON_PREFIX}_CONFIG_NAMES "${CMAKE_LIBRARY_ARCHITECTURE}-python${_${_PYTHON_PREFIX}_VERSION}-config")
-      endif()
-      list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "python${_${_PYTHON_PREFIX}_VERSION}-config")
+      _python_get_names (_${_PYTHON_PREFIX}_CONFIG_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG)
       find_program (_${_PYTHON_PREFIX}_CONFIG
                     NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
                     NAMES_PER_DIR
@@ -1066,6 +1238,22 @@
       if (NOT _${_PYTHON_PREFIX}_CONFIG)
         continue()
       endif()
+
+      execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags
+                       RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                       OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS
+                       ERROR_QUIET
+                       OUTPUT_STRIP_TRAILING_WHITESPACE)
+      if (_${_PYTHON_PREFIX}_RESULT)
+        # assume ABI is not supported
+        set (__${_PYTHON_PREFIX}_ABIFLAGS "")
+      endif()
+      if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
+        # Wrong ABI
+        unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
+        continue()
+      endif()
+
       if (DEFINED CMAKE_LIBRARY_ARCHITECTURE)
         # check that config tool match library architecture
         execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir
@@ -1104,49 +1292,32 @@
   endif()
 
   if (_${_PYTHON_PREFIX}_CONFIG)
-    set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}")
-
-    unset (_${_PYTHON_PREFIX}_LIB_DIRS)
-    unset (_${_PYTHON_PREFIX}_PATH_SUFFIXES)
-    unset (_${_PYTHON_PREFIX}_LIB_NAMES)
-
-    # retrieve library
-    execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags
+    # enforce current ABI
+    execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags
                      RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
-                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_ABIFLAGS
                      ERROR_QUIET
                      OUTPUT_STRIP_TRAILING_WHITESPACE)
-    if (NOT _${_PYTHON_PREFIX}_RESULT)
-      # retrieve library directory
-      string (REGEX MATCHALL "-L[^ ]+" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_FLAGS}")
-      string (REPLACE "-L" "" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_LIB_DIRS}")
-      if (_${_PYTHON_PREFIX}_CONFIG MATCHES "python([0-9.]+)-config")
-        _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES ${CMAKE_MATCH_1} LIBRARY)
-      endif()
-
-      # retrieve library name
-      string (REGEX MATCHALL "-lpython[^ ]+" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_FLAGS}")
-      string (REPLACE "-l" "" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_LIB_NAMES}")
-      list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_NAMES)
+    if (_${_PYTHON_PREFIX}_RESULT)
+      # assume ABI is not supported
+      set (_${_PYTHON_PREFIX}_ABIFLAGS "")
     endif()
 
+    set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}")
+
+    # retrieve library
+    ## compute some paths and artifact names
+    string (REGEX REPLACE "^.+python([0-9.]+)[a-z]*-config" "\\1" _${_PYTHON_PREFIX}_CONFIG_VERSION "${_${_PYTHON_PREFIX}_CONFIG}")
+    _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_CONFIG_VERSION} LIBRARY)
+    _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_CONFIG_VERSION} POSIX LIBRARY)
+
     execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir
                      RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
                      OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR
                      ERROR_QUIET
                      OUTPUT_STRIP_TRAILING_WHITESPACE)
     if (NOT _${_PYTHON_PREFIX}_RESULT)
-      list (APPEND _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_CONFIGDIR}")
-    endif()
-    list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_DIRS)
-    list (APPEND _${_PYTHON_PREFIX}_HINTS ${_${_PYTHON_PREFIX}_LIB_DIRS})
-
-    if (NOT _${_PYTHON_PREFIX}_LIB_NAMES)
-      # config tool do not specify "-l" option (it is the case starting with 3.8)
-      # extract version from the config tool name and list all possible lib names
-      if (_${_PYTHON_PREFIX}_CONFIG MATCHES "python([0-9.]+)-config")
-        _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES ${CMAKE_MATCH_1})
-      endif()
+      list (APPEND _${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_CONFIGDIR}")
     endif()
 
     list (APPEND _${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
@@ -1194,7 +1365,7 @@
 
   # Rely on HINTS and standard paths if config tool failed to locate artifacts
   if (NOT ${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT ${_PYTHON_PREFIX}_INCLUDE_DIR)
-    set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+    set (_${_PYTHON_PREFIX}_HINTS ${_${_PYTHON_PREFIX}_BASE_HINTS})
 
     if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION")
       unset (_${_PYTHON_PREFIX}_LIB_NAMES)
@@ -1205,9 +1376,9 @@
 
       foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
         # library names
-        _python_get_lib_names (_${_PYTHON_PREFIX}_VERSION_NAMES ${_${_PYTHON_PREFIX}_LIB_VERSION})
+        _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY)
         list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES})
-        _python_get_lib_names (_${_PYTHON_PREFIX}_VERSION_NAMES ${_${_PYTHON_PREFIX}_LIB_VERSION} DEBUG)
+        _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG)
         list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION_NAMES})
 
         # Framework Paths
@@ -1219,7 +1390,7 @@
         list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS})
 
         # Paths suffixes
-        _python_get_path_suffixes (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY)
+        _python_get_path_suffixes (_${_PYTHON_PREFIX}_VERSION_PATHS VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY)
         list (APPEND _${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_VERSION_PATHS})
       endforeach()
 
@@ -1289,7 +1460,7 @@
         # search for debug library
         if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
           # use library location as a hint
-          _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION} DEBUG)
+          _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG)
           get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
           find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
                         NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG}
@@ -1326,13 +1497,13 @@
       endif()
     else()
       foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
-        _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_LIB_VERSION})
-        _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_LIB_VERSION} DEBUG)
+        _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY)
+        _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG)
 
         _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION})
         _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION})
 
-        _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY)
+        _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY)
 
         if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
           find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
@@ -1428,7 +1599,7 @@
 
     # retrieve runtime libraries
     if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
-      _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_VERSION})
+      _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 POSIX LIBRARY)
       get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
       get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY)
       _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
@@ -1438,7 +1609,7 @@
                                     PATH_SUFFIXES bin)
     endif()
     if (${_PYTHON_PREFIX}_LIBRARY_DEBUG)
-      _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION} DEBUG)
+      _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG)
       get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY)
       get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY)
       _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
@@ -1487,7 +1658,7 @@
 
       _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
       _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION})
-      _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_VERSION} INCLUDE)
+      _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_VERSION} INCLUDE)
 
       if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
         find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake
index 2ead5b6..c8d9f24 100644
--- a/Modules/FindPython3.cmake
+++ b/Modules/FindPython3.cmake
@@ -138,6 +138,47 @@
   * If set to TRUE, search **only** for static libraries.
   * If set to FALSE, search **only** for shared libraries.
 
+``Python3_FIND_ABI``
+  This variable defines which ABIs, as defined in
+  `PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched.
+
+  .. note::
+
+    If ``Python3_FIND_ABI`` is not defined, any ABI will be searched.
+
+  The ``Python3_FIND_ABI`` variable is a 3-tuple specifying, in that order,
+  ``pydebug`` (``d``), ``pymalloc`` (``m``) and ``unicode`` (``u``) flags.
+  Each element can be set to one of the following:
+
+  * ``ON``: Corresponding flag is selected.
+  * ``OFF``: Corresponding flag is not selected.
+  * ``ANY``: The two posibilties (``ON`` and ``OFF``) will be searched.
+
+  From this 3-tuple, various ABIs will be searched starting from the most
+  specialized to the most general. Moreover, ``debug`` versions will be
+  searched **after** ``non-debug`` ones.
+
+  For example, if we have::
+
+    set (Python3_FIND_ABI "ON" "ANY" "ANY")
+
+  The following flags combinations will be appended, in that order, to the
+  artifact names: ``dmu``, ``dm``, ``du``, and ``d``.
+
+  And to search any possible ABIs::
+
+    set (Python3_FIND_ABI "ANY" "ANY" "ANY")
+
+  The following combinations, in that order, will be used: ``mu``, ``m``,
+  ``u``, ``<empty>``, ``dmu``, ``dm``, ``du`` and ``d``.
+
+  .. note::
+
+    This hint is useful only on ``POSIX`` systems. So, on ``Windows`` systems,
+    when ``Python3_FIND_ABI`` is defined, ``Python`` distributions from
+    `python.org <https://www.python.org/>`_ will be found only if value for
+    each flag is ``OFF`` or ``ANY``.
+
 ``Python3_FIND_STRATEGY``
   This variable defines how lookup will be done.
   The ``Python3_FIND_STRATEGY`` variable can be set to empty or one of the
diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake
index da33301..ccc7d5b 100644
--- a/Modules/FindPythonInterp.cmake
+++ b/Modules/FindPythonInterp.cmake
@@ -39,6 +39,15 @@
 ``find_package(PythonLibs)``, call ``find_package(PythonInterp)`` first to
 get the currently active Python version by default with a consistent version
 of PYTHON_LIBRARIES.
+
+.. note::
+
+  A call to ``find_package(PythonInterp ${V})`` for python version ``V``
+  may find a ``python`` executable with no version suffix.  In this case
+  no attempt is made to avoid python executables from other versions.
+  Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython`
+  instead.
+
 #]=======================================================================]
 
 unset(_Python_NAMES)
diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake
index a145b46..3993968 100644
--- a/Modules/FindQt4.cmake
+++ b/Modules/FindQt4.cmake
@@ -670,7 +670,7 @@
           get_filename_component(qt_headers "${QT_QTCORE_INCLUDE_DIR}/../" ABSOLUTE)
           set(QT_HEADERS_DIR "${qt_headers}" CACHE INTERNAL "" FORCE)
         endif()
-      elseif()
+      else()
         message("Warning: QT_QMAKE_EXECUTABLE reported QT_INSTALL_HEADERS as ${qt_headers}")
         message("Warning: But QtCore couldn't be found.  Qt must NOT be installed correctly.")
       endif()
diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake
index ae8d72d..55da55f 100644
--- a/Modules/FindVulkan.cmake
+++ b/Modules/FindVulkan.cmake
@@ -5,7 +5,7 @@
 FindVulkan
 ----------
 
-Find Vulkan, which isis a low-overhead, cross-platform 3D graphics
+Find Vulkan, which is a low-overhead, cross-platform 3D graphics
 and computing API.
 
 IMPORTED Targets
diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake
index 5be4676..2beea00 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -5,6 +5,10 @@
 GetPrerequisites
 ----------------
 
+.. deprecated:: 3.16
+
+  Use :command:`file(GET_RUNTIME_DEPENDENCIES)` instead.
+
 Functions to analyze and list executable file prerequisites.
 
 This module provides functions to list the .dll, .dylib or .so files
@@ -706,7 +710,9 @@
       find_program(gp_dumpbin "dumpbin" PATHS ${gp_cmd_paths})
       if(gp_dumpbin)
         set(gp_tool "dumpbin")
-      else() # Try harder. Maybe we're on MinGW
+      elseif(CMAKE_OBJDUMP) # Try harder. Maybe we're on MinGW
+        set(gp_tool "${CMAKE_OBJDUMP}")
+      else()
         set(gp_tool "objdump")
       endif()
     endif()
diff --git a/Modules/CPack.DS_Store.in b/Modules/Internal/CPack/CPack.DS_Store.in
similarity index 100%
rename from Modules/CPack.DS_Store.in
rename to Modules/Internal/CPack/CPack.DS_Store.in
Binary files differ
diff --git a/Modules/CPack.Description.plist.in b/Modules/Internal/CPack/CPack.Description.plist.in
similarity index 100%
rename from Modules/CPack.Description.plist.in
rename to Modules/Internal/CPack/CPack.Description.plist.in
diff --git a/Modules/CPack.Info.plist.in b/Modules/Internal/CPack/CPack.Info.plist.in
similarity index 100%
rename from Modules/CPack.Info.plist.in
rename to Modules/Internal/CPack/CPack.Info.plist.in
diff --git a/Modules/CPack.NuGet.nuspec.in b/Modules/Internal/CPack/CPack.NuGet.nuspec.in
similarity index 100%
rename from Modules/CPack.NuGet.nuspec.in
rename to Modules/Internal/CPack/CPack.NuGet.nuspec.in
diff --git a/Modules/CPack.OSXScriptLauncher.in b/Modules/Internal/CPack/CPack.OSXScriptLauncher.in
old mode 100755
new mode 100644
similarity index 100%
rename from Modules/CPack.OSXScriptLauncher.in
rename to Modules/Internal/CPack/CPack.OSXScriptLauncher.in
Binary files differ
diff --git a/Modules/CPack.OSXScriptLauncher.rsrc.in b/Modules/Internal/CPack/CPack.OSXScriptLauncher.rsrc.in
similarity index 100%
rename from Modules/CPack.OSXScriptLauncher.rsrc.in
rename to Modules/Internal/CPack/CPack.OSXScriptLauncher.rsrc.in
Binary files differ
diff --git a/Modules/CPack.OSXX11.Info.plist.in b/Modules/Internal/CPack/CPack.OSXX11.Info.plist.in
similarity index 100%
rename from Modules/CPack.OSXX11.Info.plist.in
rename to Modules/Internal/CPack/CPack.OSXX11.Info.plist.in
diff --git a/Modules/CPack.OSXX11.main.scpt.in b/Modules/Internal/CPack/CPack.OSXX11.main.scpt.in
similarity index 100%
rename from Modules/CPack.OSXX11.main.scpt.in
rename to Modules/Internal/CPack/CPack.OSXX11.main.scpt.in
Binary files differ
diff --git a/Modules/CPack.RuntimeScript.in b/Modules/Internal/CPack/CPack.RuntimeScript.in
similarity index 100%
rename from Modules/CPack.RuntimeScript.in
rename to Modules/Internal/CPack/CPack.RuntimeScript.in
diff --git a/Modules/CPack.STGZ_Header.sh.in b/Modules/Internal/CPack/CPack.STGZ_Header.sh.in
similarity index 98%
rename from Modules/CPack.STGZ_Header.sh.in
rename to Modules/Internal/CPack/CPack.STGZ_Header.sh.in
index 70f63d2..003fcfe 100755
--- a/Modules/CPack.STGZ_Header.sh.in
+++ b/Modules/Internal/CPack/CPack.STGZ_Header.sh.in
@@ -43,10 +43,10 @@
     cpack_prefix_dir=`cpack_fix_slashes "${cpack_prefix_dir}"`
   fi
   if echo $a | grep "^--help" > /dev/null 2> /dev/null; then
-    cpack_usage 
+    cpack_usage
   fi
   if echo $a | grep "^--version" > /dev/null 2> /dev/null; then
-    cpack_version 
+    cpack_version
     exit 2
   fi
   if echo $a | grep "^--include-subdir" > /dev/null 2> /dev/null; then
@@ -143,4 +143,3 @@
 #-----------------------------------------------------------
 #      Start of TAR.GZ file
 #-----------------------------------------------------------;
-
diff --git a/Modules/CPack.VolumeIcon.icns.in b/Modules/Internal/CPack/CPack.VolumeIcon.icns.in
similarity index 100%
rename from Modules/CPack.VolumeIcon.icns.in
rename to Modules/Internal/CPack/CPack.VolumeIcon.icns.in
Binary files differ
diff --git a/Modules/CPack.background.png.in b/Modules/Internal/CPack/CPack.background.png.in
similarity index 100%
rename from Modules/CPack.background.png.in
rename to Modules/Internal/CPack/CPack.background.png.in
Binary files differ
diff --git a/Modules/CPack.distribution.dist.in b/Modules/Internal/CPack/CPack.distribution.dist.in
similarity index 100%
rename from Modules/CPack.distribution.dist.in
rename to Modules/Internal/CPack/CPack.distribution.dist.in
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 89dc6f0..7791822 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -45,7 +45,7 @@
       ERROR_QUIET
       OUTPUT_STRIP_TRAILING_WHITESPACE)
     if(result EQUAL 0)
-      string(REGEX MATCH "\\(SONAME\\)[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}")
+      string(REGEX MATCH "\\(?SONAME\\)?[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}")
       set(${libname} "${CMAKE_MATCH_1}" PARENT_SCOPE)
       set(${version} "${CMAKE_MATCH_2}" PARENT_SCOPE)
     else()
diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake
index 4b2ce92..82053b2 100644
--- a/Modules/Internal/CPack/CPackNuGet.cmake
+++ b/Modules/Internal/CPack/CPackNuGet.cmake
@@ -262,7 +262,7 @@
     # NuGet will name it properly.
     _cpack_nuget_debug("Rendering `${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec` file...")
     configure_file(
-        "${CMAKE_ROOT}/Modules/CPack.NuGet.nuspec.in"
+        "${CMAKE_ROOT}/Modules/Internal/CPack/CPack.NuGet.nuspec.in"
         "${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec"
         @ONLY
       )
diff --git a/Modules/NSIS.InstallOptions.ini.in b/Modules/Internal/CPack/NSIS.InstallOptions.ini.in
similarity index 100%
rename from Modules/NSIS.InstallOptions.ini.in
rename to Modules/Internal/CPack/NSIS.InstallOptions.ini.in
diff --git a/Modules/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in
similarity index 100%
rename from Modules/NSIS.template.in
rename to Modules/Internal/CPack/NSIS.template.in
diff --git a/Modules/WIX.template.in b/Modules/Internal/CPack/WIX.template.in
similarity index 100%
rename from Modules/WIX.template.in
rename to Modules/Internal/CPack/WIX.template.in
diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake
index 0abbb61..61d213a 100644
--- a/Modules/Platform/AIX-GNU.cmake
+++ b/Modules/Platform/AIX-GNU.cmake
@@ -8,23 +8,26 @@
 endif()
 set(__AIX_COMPILER_GNU 1)
 
-#
-# By default, runtime linking is enabled. All shared objects specified on the command line
-# will be listed, even if there are no symbols referenced, in the output file.
-string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " -Wl,-brtl")
-string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " -Wl,-brtl")
-string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,-brtl")
-
-
 macro(__aix_compiler_gnu lang)
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-blibpath:")
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":")
-  string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-G,-bnoipath")
-  set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall")
+  string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-bnoipath")
+  set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall") # CMP0065 old behavior
   set(CMAKE_${lang}_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH 1)
 
   set(CMAKE_${lang}_LINK_FLAGS "-Wl,-bnoipath")
   if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 7 OR CMAKE_SYSTEM_VERSION VERSION_LESS 7.1)
     unset(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY)
   endif()
+
+  # Construct the export list ourselves to pass only the object files so
+  # that we export only the symbols actually provided by the sources.
+  set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
+    "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/objects.exp <OBJECTS>"
+    "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/objects.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
+    )
+
+  set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
+    "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <OBJECTS>"
+    "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
 endmacro()
diff --git a/Modules/Platform/AIX-XL.cmake b/Modules/Platform/AIX-XL.cmake
index 06a806b..64b0bc1 100644
--- a/Modules/Platform/AIX-XL.cmake
+++ b/Modules/Platform/AIX-XL.cmake
@@ -8,43 +8,24 @@
 endif()
 set(__AIX_COMPILER_XL 1)
 
-#
-# By default, runtime linking is enabled. All shared objects specified on the command line
-# will be listed, even if there are no symbols referenced, in the output file.
-string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " -Wl,-brtl")
-string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " -Wl,-brtl")
-string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,-brtl")
-
-
 macro(__aix_compiler_xl lang)
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-blibpath:")
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":")
-  set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-G -Wl,-bnoipath")  # -shared
-  set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall")
+  string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-bnoipath")
+  set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall") # CMP0065 old behavior
   set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS " ")
   set(CMAKE_SHARED_MODULE_${lang}_FLAGS  " ")
 
   set(CMAKE_${lang}_LINK_FLAGS "-Wl,-bnoipath")
 
-  # Find the CreateExportList program that comes with this toolchain.
-  find_program(CMAKE_XL_CreateExportList
-    NAMES CreateExportList
-    DOC "IBM XL CreateExportList tool"
+  # Construct the export list ourselves to pass only the object files so
+  # that we export only the symbols actually provided by the sources.
+  set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
+    "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/objects.exp <OBJECTS>"
+    "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/objects.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
     )
 
-  # CMAKE_XL_CreateExportList is part of the AIX XL compilers but not the linux ones.
-  # If we found the tool, we'll use it to create exports, otherwise stick with the regular
-  # create shared library compile line.
-  if (CMAKE_XL_CreateExportList)
-    # The compiler front-end passes all object files, archive files, and shared
-    # library files named on the command line to CreateExportList to create a
-    # list of all symbols to be exported from the shared library.  This causes
-    # all archive members to be copied into the shared library whether they are
-    # needed or not.  Instead we run the tool ourselves to pass only the object
-    # files so that we export only the symbols actually provided by the sources.
-    set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
-      "${CMAKE_XL_CreateExportList} <OBJECT_DIR>/objects.exp <OBJECTS>"
-      "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/objects.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
-      )
-  endif()
+  set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
+    "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <OBJECTS>"
+    "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
 endmacro()
diff --git a/Modules/Platform/AIX.cmake b/Modules/Platform/AIX.cmake
index 551a995..03cef51 100644
--- a/Modules/Platform/AIX.cmake
+++ b/Modules/Platform/AIX.cmake
@@ -1,5 +1,7 @@
 set(CMAKE_SHARED_LIBRARY_PREFIX "lib")          # lib
 set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")          # .so
+set(CMAKE_AIX_IMPORT_FILE_PREFIX "")
+set(CMAKE_AIX_IMPORT_FILE_SUFFIX ".imp")
 set(CMAKE_DL_LIBS "-lld")
 
 # RPATH support on AIX is called libpath.  By default the runtime
diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList
new file mode 100755
index 0000000..4f67ef5
--- /dev/null
+++ b/Modules/Platform/AIX/ExportImportList
@@ -0,0 +1,53 @@
+#!/bin/sh
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# This script is internal to CMake and meant only to be
+# invoked by CMake-generated build systems on AIX.
+
+usage='usage: ExportImportList -o <out-file> [-l <lib>] [--] <objects>...'
+
+die() {
+    echo "$@" 1>&2; exit 1
+}
+
+# Process command-line arguments.
+out=''
+lib=''
+while test "$#" != 0; do
+    case "$1" in
+    -l) shift; lib="$1" ;;
+    -o) shift; out="$1" ;;
+    --) shift; break ;;
+    -*) die "$usage" ;;
+    *)  break ;;
+    esac
+    shift
+done
+test -n "$out" || die "$usage"
+
+# Collect symbols exported from all object files.
+out_tmp="$out.tmp$$"
+trap 'rm -f "$out_tmp"' EXIT INT TERM
+for f in "$@"; do
+    dump -tov -X 32_64 "$f" |
+    awk '
+        BEGIN {
+            V["EXPORTED"]=" export"
+            V["PROTECTED"]=" protected"
+        }
+        /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / {
+            if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) {
+                print $NF V[$(NF-1)]
+            }
+        }
+    '
+done > "$out_tmp"
+
+# Generate the export/import file.
+{
+    if test -n "$lib"; then
+        echo "#! $lib"
+    fi
+    sort -u "$out_tmp"
+} > "$out"
diff --git a/Modules/Platform/Android-Clang.cmake b/Modules/Platform/Android-Clang.cmake
index 9ed1e01..847178f 100644
--- a/Modules/Platform/Android-Clang.cmake
+++ b/Modules/Platform/Android-Clang.cmake
@@ -40,6 +40,9 @@
   endif()
   if(NOT CMAKE_${lang}_COMPILER_TARGET)
     set(CMAKE_${lang}_COMPILER_TARGET "${_ANDROID_ABI_CLANG_TARGET}")
+    if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+      string(APPEND CMAKE_${lang}_COMPILER_TARGET "${CMAKE_SYSTEM_VERSION}")
+    endif()
     list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}")
   endif()
 endmacro()
diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake
index f8b9346..1affcd0 100644
--- a/Modules/Platform/Android-Common.cmake
+++ b/Modules/Platform/Android-Common.cmake
@@ -47,7 +47,41 @@
 endif()
 
 if(CMAKE_ANDROID_STL_TYPE)
-  if(CMAKE_ANDROID_NDK)
+  if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+    if(CMAKE_ANDROID_STL_TYPE STREQUAL "system")
+      set(_ANDROID_STL_EXCEPTIONS 0)
+      set(_ANDROID_STL_RTTI 0)
+      macro(__android_stl lang)
+        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libstdc++")
+      endmacro()
+    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_static")
+      set(_ANDROID_STL_EXCEPTIONS 1)
+      set(_ANDROID_STL_RTTI 1)
+      macro(__android_stl lang)
+        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
+        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -static-libstdc++")
+      endmacro()
+    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_shared")
+      set(_ANDROID_STL_EXCEPTIONS 1)
+      set(_ANDROID_STL_RTTI 1)
+      macro(__android_stl lang)
+        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
+      endmacro()
+    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "none")
+      set(_ANDROID_STL_RTTI 0)
+      set(_ANDROID_STL_EXCEPTIONS 0)
+      macro(__android_stl lang)
+        # FIXME: Add a way to add project-wide language-specific compile-only flags.
+        set(CMAKE_CXX_COMPILE_OBJECT
+          "<CMAKE_CXX_COMPILER>  <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE> -nostdinc++")
+        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -nostdlib++")
+      endmacro()
+    else()
+      message(FATAL_ERROR
+        "Android: STL '${CMAKE_ANDROID_STL_TYPE}' not supported by this NDK."
+        )
+    endif()
+  elseif(CMAKE_ANDROID_NDK)
 
     macro(__android_stl_inc lang dir req)
       if(EXISTS "${dir}")
@@ -152,6 +186,10 @@
     __android_stl(CXX)
   endif()
 
+  if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+    string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -latomic -lm")
+  endif()
+
   # <ndk>/build/core/definitions.mk appends the sysroot's include directory
   # explicitly at the end of the command-line include path so that it
   # precedes the toolchain's builtin include directories.  This is
@@ -161,7 +199,7 @@
   #
   # Do not do this for a standalone toolchain because it is already
   # tied to a specific API version.
-  if(CMAKE_ANDROID_NDK)
+  if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
     if(CMAKE_SYSROOT_COMPILE)
       set(_cmake_sysroot_compile "${CMAKE_SYSROOT_COMPILE}")
     else()
@@ -170,7 +208,7 @@
     if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
       list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES
         "${_cmake_sysroot_compile}/usr/include"
-        "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}"
+        "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_TRIPLE}"
         )
     else()
       list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${_cmake_sysroot_compile}/usr/include")
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index bb42eed..e7c1b48 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -198,32 +198,66 @@
   message(FATAL_ERROR "Android: The API specified by CMAKE_SYSTEM_VERSION='${CMAKE_SYSTEM_VERSION}' is not an integer.")
 endif()
 
+if(CMAKE_ANDROID_NDK)
+  # Identify the host platform.
+  if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+    if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86_64")
+    else()
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86")
+    endif()
+  elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+    if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86_64")
+    else()
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86")
+    endif()
+  elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+    if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64")
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "windows-x86_64")
+    else()
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "windows")
+    endif()
+  else()
+    message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.")
+  endif()
+
+  # Look for a unified toolchain/sysroot provided with the NDK.
+  set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "${CMAKE_ANDROID_NDK}/toolchains/llvm/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}")
+  if(NOT IS_DIRECTORY "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/sysroot")
+    set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "")
+  endif()
+else()
+  set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "")
+  set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "")
+endif()
+
 # https://developer.android.com/ndk/guides/abis.html
 
 set(_ANDROID_ABI_arm64-v8a_PROC     "aarch64")
 set(_ANDROID_ABI_arm64-v8a_ARCH     "arm64")
-set(_ANDROID_ABI_arm64-v8a_HEADER   "aarch64-linux-android")
+set(_ANDROID_ABI_arm64-v8a_TRIPLE   "aarch64-linux-android")
 set(_ANDROID_ABI_armeabi-v7a_PROC   "armv7-a")
 set(_ANDROID_ABI_armeabi-v7a_ARCH   "arm")
-set(_ANDROID_ABI_armeabi-v7a_HEADER "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi-v7a_TRIPLE "arm-linux-androideabi")
 set(_ANDROID_ABI_armeabi-v6_PROC    "armv6")
 set(_ANDROID_ABI_armeabi-v6_ARCH    "arm")
-set(_ANDROID_ABI_armeabi-v6_HEADER  "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi-v6_TRIPLE  "arm-linux-androideabi")
 set(_ANDROID_ABI_armeabi_PROC       "armv5te")
 set(_ANDROID_ABI_armeabi_ARCH       "arm")
-set(_ANDROID_ABI_armeabi_HEADER     "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi_TRIPLE     "arm-linux-androideabi")
 set(_ANDROID_ABI_mips_PROC          "mips")
 set(_ANDROID_ABI_mips_ARCH          "mips")
-set(_ANDROID_ABI_mips_HEADER        "mipsel-linux-android")
+set(_ANDROID_ABI_mips_TRIPLE        "mipsel-linux-android")
 set(_ANDROID_ABI_mips64_PROC        "mips64")
 set(_ANDROID_ABI_mips64_ARCH        "mips64")
-set(_ANDROID_ABI_mips64_HEADER      "mips64el-linux-android")
+set(_ANDROID_ABI_mips64_TRIPLE      "mips64el-linux-android")
 set(_ANDROID_ABI_x86_PROC           "i686")
 set(_ANDROID_ABI_x86_ARCH           "x86")
-set(_ANDROID_ABI_x86_HEADER         "i686-linux-android")
+set(_ANDROID_ABI_x86_TRIPLE         "i686-linux-android")
 set(_ANDROID_ABI_x86_64_PROC        "x86_64")
 set(_ANDROID_ABI_x86_64_ARCH        "x86_64")
-set(_ANDROID_ABI_x86_64_HEADER      "x86_64-linux-android")
+set(_ANDROID_ABI_x86_64_TRIPLE      "x86_64-linux-android")
 
 set(_ANDROID_PROC_aarch64_ARCH_ABI "arm64-v8a")
 set(_ANDROID_PROC_armv7-a_ARCH_ABI "armeabi-v7a")
@@ -308,7 +342,7 @@
     "does not match architecture '${CMAKE_ANDROID_ARCH}' for the ABI '${CMAKE_ANDROID_ARCH_ABI}'."
     )
 endif()
-set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_HEADER}")
+set(CMAKE_ANDROID_ARCH_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_TRIPLE}")
 
 # Select a processor.
 if(NOT CMAKE_SYSTEM_PROCESSOR)
@@ -321,7 +355,7 @@
 endif()
 
 if(CMAKE_ANDROID_NDK AND NOT DEFINED CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
-  if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}")
+  if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_TRIPLE}")
     # Unified headers exist so we use them by default.
     set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS 0)
   else()
@@ -340,8 +374,10 @@
 
 if(CMAKE_ANDROID_NDK)
   string(APPEND CMAKE_SYSTEM_CUSTOM_CODE
-    "set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE \"${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}\")\n"
+    "set(CMAKE_ANDROID_ARCH_TRIPLE \"${CMAKE_ANDROID_ARCH_TRIPLE}\")\n"
     "set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS \"${CMAKE_ANDROID_NDK_DEPRECATED_HEADERS}\")\n"
+    "set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}\")\n"
+    "set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED \"${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}\")\n"
     )
 endif()
 
diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake
index a434f90..a5d2820 100644
--- a/Modules/Platform/Android-Initialize.cmake
+++ b/Modules/Platform/Android-Initialize.cmake
@@ -17,6 +17,13 @@
   return()
 endif()
 
+set(CMAKE_BUILD_TYPE_INIT Debug)
+
+# Skip sysroot selection if the NDK has a unified toolchain.
+if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+  return()
+endif()
+
 if(NOT CMAKE_SYSROOT)
   if(CMAKE_ANDROID_NDK)
     set(CMAKE_SYSROOT "${CMAKE_ANDROID_NDK}/platforms/android-${CMAKE_SYSTEM_VERSION}/arch-${CMAKE_ANDROID_ARCH}")
@@ -40,5 +47,3 @@
     "Android: No CMAKE_SYSROOT was selected."
     )
 endif()
-
-set(CMAKE_BUILD_TYPE_INIT Debug)
diff --git a/Modules/Platform/Android/Determine-Compiler-NDK.cmake b/Modules/Platform/Android/Determine-Compiler-NDK.cmake
index 5f2cc52..e009c10 100644
--- a/Modules/Platform/Android/Determine-Compiler-NDK.cmake
+++ b/Modules/Platform/Android/Determine-Compiler-NDK.cmake
@@ -1,6 +1,31 @@
 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 # file Copyright.txt or https://cmake.org/licensing for details.
 
+# In Android NDK r19 and above there is a single clang toolchain.
+if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+  if(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION STREQUAL "clang")
+    message(FATAL_ERROR
+      "Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value '${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}' "
+      "is not supported by this NDK.  It must be 'clang' or not set at all."
+      )
+  endif()
+  message(STATUS "Android: Selected unified Clang toolchain")
+  set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "clang")
+  set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_VERSION "")
+  set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN "")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang++${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_VERSION "")
+  set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
+  return()
+endif()
+
 # In Android NDK releases there is build system toolchain selection logic in
 # these files:
 #
@@ -195,40 +220,16 @@
   set(_ANDROID_TOOL_PREFIX "${CMAKE_MATCH_1}")
 endif()
 
-# Identify the host platform.
-if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
-  if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
-    set(_ANDROID_HOST_DIR "darwin-x86_64")
-  else()
-    set(_ANDROID_HOST_DIR "darwin-x86")
-  endif()
-elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
-  if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
-    set(_ANDROID_HOST_DIR "linux-x86_64")
-  else()
-    set(_ANDROID_HOST_DIR "linux-x86")
-  endif()
-elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
-  if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64")
-    set(_ANDROID_HOST_DIR "windows-x86_64")
-  else()
-    set(_ANDROID_HOST_DIR "windows")
-  endif()
-else()
-  message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.")
-endif()
-
 # Help CMakeFindBinUtils locate things.
 set(_CMAKE_TOOLCHAIN_PREFIX "${_ANDROID_TOOL_PREFIX}")
 
-set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "${_ANDROID_HOST_DIR}")
 set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "${_ANDROID_TOOL_VERS_NDK}")
 
 # _ANDROID_TOOL_PREFIX should now match `gcc -dumpmachine`.
 string(REGEX REPLACE "-$" "" _ANDROID_TOOL_C_TOOLCHAIN_MACHINE "${_ANDROID_TOOL_PREFIX}")
 
 set(_ANDROID_TOOL_C_TOOLCHAIN_VERSION "${_ANDROID_TOOL_VERS}")
-set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/${_ANDROID_TOOL_PREFIX}")
+set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/${_ANDROID_TOOL_PREFIX}")
 set(_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
 
 set(_ANDROID_TOOL_CXX_TOOLCHAIN_MACHINE "${_ANDROID_TOOL_C_TOOLCHAIN_MACHINE}")
@@ -238,9 +239,9 @@
 
 if(_ANDROID_TOOL_CLANG_NAME)
   message(STATUS "Android: Selected Clang toolchain '${_ANDROID_TOOL_CLANG_NAME}' with GCC toolchain '${_ANDROID_TOOL_NAME}'")
-  set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/clang${_ANDROID_HOST_EXT}")
-  set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN ${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${_ANDROID_HOST_DIR})
-  set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/clang++${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/clang${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN ${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG})
+  set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/clang++${_ANDROID_HOST_EXT}")
   set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "${_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN}")
 else()
   message(STATUS "Android: Selected GCC toolchain '${_ANDROID_TOOL_NAME}'")
@@ -267,4 +268,3 @@
 unset(_ANDROID_TOOL_CLANG_NAME)
 unset(_ANDROID_TOOL_CLANG_VERS)
 unset(_ANDROID_TOOL_LLVM_NAME)
-unset(_ANDROID_HOST_DIR)
diff --git a/Modules/Platform/Android/Determine-Compiler-Standalone.cmake b/Modules/Platform/Android/Determine-Compiler-Standalone.cmake
index 4c1ac1f..5095aff 100644
--- a/Modules/Platform/Android/Determine-Compiler-Standalone.cmake
+++ b/Modules/Platform/Android/Determine-Compiler-Standalone.cmake
@@ -62,5 +62,4 @@
   set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "")
 endif()
 
-set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "")
 set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "")
diff --git a/Modules/Platform/Android/Determine-Compiler.cmake b/Modules/Platform/Android/Determine-Compiler.cmake
index a03ebcc..5c6b97b 100644
--- a/Modules/Platform/Android/Determine-Compiler.cmake
+++ b/Modules/Platform/Android/Determine-Compiler.cmake
@@ -40,7 +40,6 @@
 elseif(CMAKE_ANDROID_STANDALONE_TOOLCHAIN)
   include(Platform/Android/Determine-Compiler-Standalone)
 else()
-  set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "")
   set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "")
   set(_ANDROID_TOOL_C_COMPILER "")
   set(_ANDROID_TOOL_C_TOOLCHAIN_MACHINE "")
@@ -65,7 +64,6 @@
 
     # Save the Android-specific information in CMake${lang}Compiler.cmake.
     set(CMAKE_${lang}_COMPILER_CUSTOM_CODE "
-set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG}\")
 set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION \"${_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION}\")
 set(CMAKE_${lang}_ANDROID_TOOLCHAIN_MACHINE \"${_ANDROID_TOOL_${lang}_TOOLCHAIN_MACHINE}\")
 set(CMAKE_${lang}_ANDROID_TOOLCHAIN_VERSION \"${_ANDROID_TOOL_${lang}_TOOLCHAIN_VERSION}\")
diff --git a/Modules/Platform/Android/abi-common.cmake b/Modules/Platform/Android/abi-common.cmake
index 6bce3c7..b01ef61 100644
--- a/Modules/Platform/Android/abi-common.cmake
+++ b/Modules/Platform/Android/abi-common.cmake
@@ -3,7 +3,7 @@
   " -no-canonical-prefixes"
   )
 
-if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
+if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
   string(APPEND _ANDROID_ABI_INIT_CFLAGS " -D__ANDROID_API__=${CMAKE_SYSTEM_VERSION}")
 endif()
 
diff --git a/Modules/Platform/Apple-XL-C.cmake b/Modules/Platform/Apple-XL-C.cmake
index 2aeb132..e4fc3dd 100644
--- a/Modules/Platform/Apple-XL-C.cmake
+++ b/Modules/Platform/Apple-XL-C.cmake
@@ -1,4 +1,3 @@
-set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-qmkshrobj")
 set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle")
 
 # Enable shared library versioning.
diff --git a/Modules/Platform/Apple-XL-CXX.cmake b/Modules/Platform/Apple-XL-CXX.cmake
index f8e1906..ea330c8 100644
--- a/Modules/Platform/Apple-XL-CXX.cmake
+++ b/Modules/Platform/Apple-XL-CXX.cmake
@@ -1,4 +1,3 @@
-set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-qmkshrobj")
 set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "-bundle")
 
 # Enable shared library versioning.
diff --git a/Modules/Platform/Linux-XL-C.cmake b/Modules/Platform/Linux-XL-C.cmake
index d595e44..ef0c52b 100644
--- a/Modules/Platform/Linux-XL-C.cmake
+++ b/Modules/Platform/Linux-XL-C.cmake
@@ -1,2 +1 @@
-set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-qmkshrobj")
 set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,-export-dynamic")
diff --git a/Modules/Platform/Linux-XL-CXX.cmake b/Modules/Platform/Linux-XL-CXX.cmake
index 5ceb255..aa57d6e 100644
--- a/Modules/Platform/Linux-XL-CXX.cmake
+++ b/Modules/Platform/Linux-XL-CXX.cmake
@@ -1,2 +1 @@
-set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-qmkshrobj")
 set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,-export-dynamic")
diff --git a/Modules/Platform/Linux-XL-Fortran.cmake b/Modules/Platform/Linux-XL-Fortran.cmake
index a878991..d9b4c2d 100644
--- a/Modules/Platform/Linux-XL-Fortran.cmake
+++ b/Modules/Platform/Linux-XL-Fortran.cmake
@@ -1,2 +1 @@
-set(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-qmkshrobj")
 set(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-Wl,-export-dynamic")
diff --git a/Source/.gitattributes b/Source/.gitattributes
index 7c160cc..d0aedc2 100644
--- a/Source/.gitattributes
+++ b/Source/.gitattributes
@@ -1,2 +1,4 @@
+CMakeVersion.cmake    export-subst
+
 # Do not format third-party sources.
 /kwsys/**                                  -format.clang-format-6.0
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 695e075..fe40af3 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -142,10 +142,33 @@
 
   cmAffinity.cxx
   cmAffinity.h
+  cmAlgorithms.h
   cmArchiveWrite.cxx
   cmArgumentParser.cxx
   cmArgumentParser.h
   cmBase32.cxx
+  cmBinUtilsLinker.cxx
+  cmBinUtilsLinker.h
+  cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
+  cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
+  cmBinUtilsLinuxELFLinker.cxx
+  cmBinUtilsLinuxELFLinker.h
+  cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
+  cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
+  cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
+  cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
+  cmBinUtilsMacOSMachOLinker.cxx
+  cmBinUtilsMacOSMachOLinker.h
+  cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
+  cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
+  cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
+  cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h
+  cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
+  cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
+  cmBinUtilsWindowsPELinker.cxx
+  cmBinUtilsWindowsPELinker.h
+  cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
+  cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
   cmCacheManager.cxx
   cmCacheManager.h
   cmCLocaleEnvironmentScope.h
@@ -295,6 +318,10 @@
   cmInstallTargetGenerator.cxx
   cmInstallDirectoryGenerator.h
   cmInstallDirectoryGenerator.cxx
+  cmLDConfigLDConfigTool.cxx
+  cmLDConfigLDConfigTool.h
+  cmLDConfigTool.cxx
+  cmLDConfigTool.h
   cmLinkedTree.h
   cmLinkItem.cxx
   cmLinkItem.h
@@ -338,7 +365,6 @@
   cmProcessOutput.h
   cmProcessTools.cxx
   cmProcessTools.h
-  cmProperty.cxx
   cmProperty.h
   cmPropertyDefinition.cxx
   cmPropertyDefinition.h
@@ -360,6 +386,8 @@
   cmQtAutoRcc.h
   cmRST.cxx
   cmRST.h
+  cmRuntimeDependencyArchive.cxx
+  cmRuntimeDependencyArchive.h
   cmScriptGenerator.h
   cmScriptGenerator.cxx
   cmSourceFile.cxx
@@ -376,6 +404,8 @@
   cmStateSnapshot.cxx
   cmStateSnapshot.h
   cmStateTypes.h
+  cmStringAlgorithms.cxx
+  cmStringAlgorithms.h
   cmSystemTools.cxx
   cmSystemTools.h
   cmTarget.cxx
@@ -635,8 +665,6 @@
   cmTryCompileCommand.h
   cmTryRunCommand.cxx
   cmTryRunCommand.h
-  cmUnexpectedCommand.cxx
-  cmUnexpectedCommand.h
   cmUnsetCommand.cxx
   cmUnsetCommand.h
   cmUseMangledMesaCommand.cxx
@@ -1134,6 +1162,21 @@
 include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
 
 if(WIN32)
+  # Compute the binary version that appears in the RC file. Version
+  # components in the RC file are 16-bit integers so we may have to
+  # split the patch component.
+  if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$")
+    set(CMake_RCVERSION_YEAR "${CMAKE_MATCH_1}")
+    set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}")
+    string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}")
+    set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY})
+    unset(CMake_RCVERSION_MONTH_DAY)
+    unset(CMake_RCVERSION_YEAR)
+  else()
+    set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH})
+  endif()
+  set(CMake_RCVERSION_STR ${CMake_VERSION})
+
   # Add Windows executable version information.
   configure_file("CMakeVersion.rc.in" "CMakeVersion.rc" @ONLY)
 
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 4b4f9b0..3bbbd28 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,82 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 15)
-set(CMake_VERSION_PATCH 1)
+set(CMake_VERSION_PATCH 20190805)
 #set(CMake_VERSION_RC 0)
+set(CMake_VERSION_IS_DIRTY 0)
+
+# Start with the full version number used in tags.  It has no dev info.
+set(CMake_VERSION
+  "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}")
+if(DEFINED CMake_VERSION_RC)
+  set(CMake_VERSION "${CMake_VERSION}-rc${CMake_VERSION_RC}")
+endif()
+
+# Releases define a small patch level.
+if("${CMake_VERSION_PATCH}" VERSION_LESS 20000000)
+  set(CMake_VERSION_IS_RELEASE 1)
+else()
+  set(CMake_VERSION_IS_RELEASE 0)
+endif()
+
+if(EXISTS ${CMake_SOURCE_DIR}/.git)
+  find_package(Git QUIET)
+  if(GIT_FOUND)
+    macro(_git)
+      execute_process(
+        COMMAND ${GIT_EXECUTABLE} ${ARGN}
+        WORKING_DIRECTORY ${CMake_SOURCE_DIR}
+        RESULT_VARIABLE _git_res
+        OUTPUT_VARIABLE _git_out OUTPUT_STRIP_TRAILING_WHITESPACE
+        ERROR_VARIABLE _git_err ERROR_STRIP_TRAILING_WHITESPACE
+        )
+    endmacro()
+  endif()
+endif()
+
+# Try to identify the current development source version.
+if(COMMAND _git)
+  # Get the commit checked out in this work tree.
+  _git(log -n 1 HEAD "--pretty=format:%h %s" --)
+  set(git_info "${_git_out}")
+else()
+  # Get the commit exported by 'git archive'.
+  set(git_info [==[$Format:%h %s$]==])
+endif()
+
+# Extract commit information if available.
+if(git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* (.*)$")
+  # Have commit information.
+  set(git_hash "${CMAKE_MATCH_1}")
+  set(git_subject "${CMAKE_MATCH_2}")
+
+  # If this is not the exact commit of a release, add dev info.
+  if(NOT "${git_subject}" MATCHES "^[Cc][Mm]ake ${CMake_VERSION}$")
+    set(CMake_VERSION "${CMake_VERSION}-g${git_hash}")
+  endif()
+
+  # If this is a work tree, check whether it is dirty.
+  if(COMMAND _git)
+    _git(update-index -q --refresh)
+    _git(diff-index --name-only HEAD --)
+    if(_git_out)
+      set(CMake_VERSION_IS_DIRTY 1)
+    endif()
+  endif()
+else()
+  # No commit information.
+  if(NOT CMake_VERSION_IS_RELEASE)
+    # Generic development version.
+    set(CMake_VERSION "${CMake_VERSION}-git")
+  endif()
+endif()
+
+# Extract the version suffix component.
+if(CMake_VERSION MATCHES "-(.*)$")
+  set(CMake_VERSION_SUFFIX "${CMAKE_MATCH_1}")
+else()
+  set(CMake_VERSION_SUFFIX "")
+endif()
+if(CMake_VERSION_IS_DIRTY)
+  set(CMake_VERSION ${CMake_VERSION}-dirty)
+endif()
diff --git a/Source/CMakeVersionCompute.cmake b/Source/CMakeVersionCompute.cmake
deleted file mode 100644
index 72a5800..0000000
--- a/Source/CMakeVersionCompute.cmake
+++ /dev/null
@@ -1,44 +0,0 @@
-# Load version number components.
-include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake)
-
-# Releases define a small patch level.
-if("${CMake_VERSION_PATCH}" VERSION_LESS 20000000)
-  set(CMake_VERSION_IS_DIRTY 0)
-  set(CMake_VERSION_IS_RELEASE 1)
-  set(CMake_VERSION_SOURCE "")
-else()
-  set(CMake_VERSION_IS_DIRTY 0) # may be set to 1 by CMakeVersionSource
-  set(CMake_VERSION_IS_RELEASE 0)
-  include(${CMake_SOURCE_DIR}/Source/CMakeVersionSource.cmake)
-endif()
-
-# Compute the full version string.
-set(CMake_VERSION ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH})
-if(CMake_VERSION_SOURCE)
-  set(CMake_VERSION_SUFFIX "${CMake_VERSION_SOURCE}")
-elseif(CMake_VERSION_RC)
-  set(CMake_VERSION_SUFFIX "rc${CMake_VERSION_RC}")
-else()
-  set(CMake_VERSION_SUFFIX "")
-endif()
-if(CMake_VERSION_SUFFIX)
-  set(CMake_VERSION ${CMake_VERSION}-${CMake_VERSION_SUFFIX})
-endif()
-if(CMake_VERSION_IS_DIRTY)
-  set(CMake_VERSION ${CMake_VERSION}-dirty)
-endif()
-
-# Compute the binary version that appears in the RC file. Version
-# components in the RC file are 16-bit integers so we may have to
-# split the patch component.
-if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$")
-  set(CMake_RCVERSION_YEAR "${CMAKE_MATCH_1}")
-  set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}")
-  string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}")
-  set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY})
-  unset(CMake_RCVERSION_MONTH_DAY)
-  unset(CMake_RCVERSION_YEAR)
-else()
-  set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH})
-endif()
-set(CMake_RCVERSION_STR ${CMake_VERSION})
diff --git a/Source/CMakeVersionSource.cmake b/Source/CMakeVersionSource.cmake
deleted file mode 100644
index 5ea1de3..0000000
--- a/Source/CMakeVersionSource.cmake
+++ /dev/null
@@ -1,30 +0,0 @@
-# Try to identify the current development source version.
-set(CMake_VERSION_SOURCE "")
-if(EXISTS ${CMake_SOURCE_DIR}/.git/HEAD)
-  find_program(GIT_EXECUTABLE NAMES git git.cmd)
-  mark_as_advanced(GIT_EXECUTABLE)
-  if(GIT_EXECUTABLE)
-    execute_process(
-      COMMAND ${GIT_EXECUTABLE} rev-parse --verify -q --short=4 HEAD
-      OUTPUT_VARIABLE head
-      OUTPUT_STRIP_TRAILING_WHITESPACE
-      WORKING_DIRECTORY ${CMake_SOURCE_DIR}
-      )
-    if(head)
-      set(CMake_VERSION_SOURCE "g${head}")
-      execute_process(
-        COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
-        WORKING_DIRECTORY ${CMake_SOURCE_DIR}
-        )
-      execute_process(
-        COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD --
-        OUTPUT_VARIABLE dirty
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-        WORKING_DIRECTORY ${CMake_SOURCE_DIR}
-        )
-      if(dirty)
-        set(CMake_VERSION_IS_DIRTY 1)
-      endif()
-    endif()
-  endif()
-endif()
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 045d93d..fa64d79 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -604,7 +604,7 @@
 
 bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
 {
-  std::string wixTemplate = FindTemplate("WIX.template.in");
+  std::string wixTemplate = FindTemplate("Internal/CPack/WIX.template.in");
   if (GetOption("CPACK_WIX_TEMPLATE") != 0) {
     wixTemplate = GetOption("CPACK_WIX_TEMPLATE");
   }
diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx
index 9dc9853..b4c7a5a 100644
--- a/Source/CPack/cmCPackExternalGenerator.cxx
+++ b/Source/CPack/cmCPackExternalGenerator.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackExternalGenerator.h"
 
-#include "cmAlgorithms.h"
 #include "cmCPackComponentGroup.h"
 #include "cmCPackLog.h"
 #include "cmMakefile.h"
@@ -17,6 +16,8 @@
 #include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 int cmCPackExternalGenerator::InitializeInternal()
 {
   this->SetOption("CPACK_EXTERNAL_KNOWN_VERSIONS", "1.0");
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 7e07ff4..3fd124b 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -7,7 +7,7 @@
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <cstring>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <utility>
 
 #include "cmCPackComponentGroup.h"
@@ -21,6 +21,7 @@
 #include "cmMakefile.h"
 #include "cmState.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 #include "cmVersion.h"
 #include "cmWorkingDirectory.h"
 #include "cmXMLSafe.h"
@@ -235,7 +236,7 @@
     return 0;
   }
 
-  // If the CPackConfig file sets CPACK_INSTALL_SCRIPT then run them
+  // If the CPackConfig file sets CPACK_INSTALL_SCRIPT(S) then run them
   // as listed
   if (!this->InstallProjectViaInstallScript(setDestDir,
                                             tempInstallDirectory)) {
@@ -448,7 +449,19 @@
 int cmCPackGenerator::InstallProjectViaInstallScript(
   bool setDestDir, const std::string& tempInstallDirectory)
 {
-  const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPT");
+  const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS");
+  {
+    const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT");
+    if (cmakeScript && cmakeScripts) {
+      cmCPackLogger(
+        cmCPackLog::LOG_WARNING,
+        "Both CPACK_INSTALL_SCRIPTS and CPACK_INSTALL_SCRIPT are set, "
+        "the latter will be ignored."
+          << std::endl);
+    } else if (cmakeScript && !cmakeScripts) {
+      cmakeScripts = cmakeScript;
+    }
+  }
   if (cmakeScripts && *cmakeScripts) {
     cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                   "- Install scripts: " << cmakeScripts << std::endl);
@@ -747,7 +760,7 @@
     if (this->GetOption("CPACK_INSTALL_PREFIX")) {
       dir += this->GetOption("CPACK_INSTALL_PREFIX");
     }
-    mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str());
+    mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir);
 
     cmCPackLogger(
       cmCPackLog::LOG_DEBUG,
@@ -760,7 +773,7 @@
     // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
     // exists:
     //
-    if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) {
+    if (cmHasLiteralPrefix(dir, "/")) {
       dir = tempInstallDirectory + dir;
     } else {
       dir = tempInstallDirectory + "/" + dir;
@@ -787,7 +800,7 @@
       return 0;
     }
   } else {
-    mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());
+    mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory);
 
     if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
                                            default_dir_mode)) {
@@ -806,11 +819,11 @@
   }
 
   if (!buildConfig.empty()) {
-    mf.AddDefinition("BUILD_TYPE", buildConfig.c_str());
+    mf.AddDefinition("BUILD_TYPE", buildConfig);
   }
   std::string installComponentLowerCase = cmSystemTools::LowerCase(component);
   if (installComponentLowerCase != "all") {
-    mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component.c_str());
+    mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component);
   }
 
   // strip on TRUE, ON, 1, one or several file names, but not on
@@ -851,9 +864,8 @@
   // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
   // to CPack (may be used by generators like CPack RPM or DEB)
   // in order to transparently handle ABSOLUTE PATH
-  if (mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
-    mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES",
-                     mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES"));
+  if (const char* def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
+    mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", def);
   }
 
   // Now rebuild the list of files after installation
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index e2020c5..87c36fa 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -36,7 +36,8 @@
 {
   // TODO: Fix nsis to force out file name
 
-  std::string nsisInFileName = this->FindTemplate("NSIS.template.in");
+  std::string nsisInFileName =
+    this->FindTemplate("Internal/CPack/NSIS.template.in");
   if (nsisInFileName.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
                   "CPack error: Could not find NSIS installer template file."
@@ -44,7 +45,7 @@
     return false;
   }
   std::string nsisInInstallOptions =
-    this->FindTemplate("NSIS.InstallOptions.ini.in");
+    this->FindTemplate("Internal/CPack/NSIS.InstallOptions.ini.in");
   if (nsisInInstallOptions.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
                   "CPack error: Could not find NSIS installer options file."
diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx
index 76f0699..19a3a0a 100644
--- a/Source/CPack/cmCPackNuGetGenerator.cxx
+++ b/Source/CPack/cmCPackNuGetGenerator.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackNuGetGenerator.h"
 
-#include "cmAlgorithms.h"
 #include "cmCPackComponentGroup.h"
 #include "cmCPackLog.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <algorithm>
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 90e0afe..41470c9 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -245,7 +245,7 @@
   const std::string& name, const std::string& dir,
   const char* outputFileName /* = 0 */, bool copyOnly /* = false */)
 {
-  std::string inFName = "CPack.";
+  std::string inFName = "Internal/CPack/CPack.";
   inFName += name;
   inFName += ".in";
   std::string inFileName = this->FindTemplate(inFName.c_str());
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
index 8c22c65..d361921 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -48,7 +48,7 @@
 void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
 {
   std::string distributionTemplate =
-    this->FindTemplate("CPack.distribution.dist.in");
+    this->FindTemplate("Internal/CPack/CPack.distribution.dist.in");
   if (distributionTemplate.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
                   "Cannot find input file: " << distributionTemplate
@@ -305,7 +305,7 @@
     outName = name.c_str();
   }
 
-  std::string inFName = "CPack.";
+  std::string inFName = "Internal/CPack/CPack.";
   inFName += name;
   inFName += ".in";
   std::string inFileName = this->FindTemplate(inFName.c_str());
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index aba15d2..4666dc2 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -21,7 +21,8 @@
 {
   this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "0");
 
-  std::string inFile = this->FindTemplate("CPack.STGZ_Header.sh.in");
+  std::string inFile =
+    this->FindTemplate("Internal/CPack/CPack.STGZ_Header.sh.in");
   if (inFile.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
                   "Cannot find template file: " << inFile << std::endl);
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 58b9e70..89c3b1c 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -5,7 +5,6 @@
 #include "cmsys/Encoding.hxx"
 #include <iostream>
 #include <map>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stddef.h>
 #include <string>
@@ -29,19 +28,20 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-static const char* cmDocumentationName[][2] = {
+namespace {
+const char* cmDocumentationName[][2] = {
   { nullptr, "  cpack - Packaging driver provided by CMake." },
   { nullptr, nullptr }
 };
 
-static const char* cmDocumentationUsage[][2] = {
+const char* cmDocumentationUsage[][2] = {
   // clang-format off
   { nullptr, "  cpack [options]" },
   { nullptr, nullptr }
   // clang-format on
 };
 
-static const char* cmDocumentationOptions[][2] = {
+const char* cmDocumentationOptions[][2] = {
   { "-G <generators>", "Override/define CPACK_GENERATOR" },
   { "-C <Configuration>", "Specify the project configuration" },
   { "-D <var>=<value>", "Set a CPack variable." },
@@ -90,10 +90,11 @@
   return 1;
 }
 
-static void cpackProgressCallback(const std::string& message, float /*unused*/)
+void cpackProgressCallback(const std::string& message, float /*unused*/)
 {
   std::cout << "-- " << message << std::endl;
 }
+} // namespace
 
 // this is CPack.
 int main(int argc, char const* const* argv)
@@ -269,7 +270,7 @@
     }
 
     if (!cpackBuildConfig.empty()) {
-      globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());
+      globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig);
     }
 
     if (cmSystemTools::FileExists(cpackConfigFile)) {
@@ -291,24 +292,21 @@
     }
 
     if (!generator.empty()) {
-      globalMF.AddDefinition("CPACK_GENERATOR", generator.c_str());
+      globalMF.AddDefinition("CPACK_GENERATOR", generator);
     }
     if (!cpackProjectName.empty()) {
-      globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName.c_str());
+      globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName);
     }
     if (!cpackProjectVersion.empty()) {
-      globalMF.AddDefinition("CPACK_PACKAGE_VERSION",
-                             cpackProjectVersion.c_str());
+      globalMF.AddDefinition("CPACK_PACKAGE_VERSION", cpackProjectVersion);
     }
     if (!cpackProjectVendor.empty()) {
-      globalMF.AddDefinition("CPACK_PACKAGE_VENDOR",
-                             cpackProjectVendor.c_str());
+      globalMF.AddDefinition("CPACK_PACKAGE_VENDOR", cpackProjectVendor);
     }
     // if this is not empty it has been set on the command line
     // go for it. Command line override values set in config file.
     if (!cpackProjectDirectory.empty()) {
-      globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",
-                             cpackProjectDirectory.c_str());
+      globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);
     }
     // The value has not been set on the command line
     else {
@@ -317,11 +315,11 @@
       // use default value iff no value has been provided by the config file
       if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) {
         globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",
-                               cpackProjectDirectory.c_str());
+                               cpackProjectDirectory);
       }
     }
     for (auto const& cd : definitions.Map) {
-      globalMF.AddDefinition(cd.first, cd.second.c_str());
+      globalMF.AddDefinition(cd.first, cd.second);
     }
 
     const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH");
@@ -425,7 +423,7 @@
               std::ostringstream ostr;
               ostr << projVersionMajor << "." << projVersionMinor << "."
                    << projVersionPatch;
-              mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str().c_str());
+              mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str());
             }
 
             int res = cpackGenerator->DoPackage();
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 9ad9669..3aea1f4 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -76,6 +76,11 @@
   if (config) {
     args.push_back("-DCMAKE_BUILD_TYPE:STRING=" + std::string(config));
   }
+  if (!this->BuildMakeProgram.empty() &&
+      (this->BuildGenerator.find("Make") != std::string::npos ||
+       this->BuildGenerator.find("Ninja") != std::string::npos)) {
+    args.push_back("-DCMAKE_MAKE_PROGRAM:FILEPATH=" + this->BuildMakeProgram);
+  }
 
   for (std::string const& opt : this->BuildOptions) {
     args.push_back(opt);
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 2eacaf1..e71eafe 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -156,15 +156,14 @@
   if (this->Values[ctb_NUMBER_ERRORS] && *this->Values[ctb_NUMBER_ERRORS]) {
     std::ostringstream str;
     str << this->Handler->GetTotalErrors();
-    this->Makefile->AddDefinition(this->Values[ctb_NUMBER_ERRORS],
-                                  str.str().c_str());
+    this->Makefile->AddDefinition(this->Values[ctb_NUMBER_ERRORS], str.str());
   }
   if (this->Values[ctb_NUMBER_WARNINGS] &&
       *this->Values[ctb_NUMBER_WARNINGS]) {
     std::ostringstream str;
     str << this->Handler->GetTotalWarnings();
     this->Makefile->AddDefinition(this->Values[ctb_NUMBER_WARNINGS],
-                                  str.str().c_str());
+                                  str.str());
   }
   return ret;
 }
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index 77b0549..a62c301 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -6,13 +6,16 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 class cmCTestBuildHandler;
 class cmCTestGenericHandler;
-class cmCommand;
 class cmExecutionStatus;
 class cmGlobalGenerator;
 
@@ -30,12 +33,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestBuildCommand* ni = new cmCTestBuildCommand;
+    auto ni = cm::make_unique<cmCTestBuildCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index c8e4fa1..407e9f8 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -9,6 +9,7 @@
 #include "cmGeneratedFileStream.h"
 #include "cmMakefile.h"
 #include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h
index 0cbcbfa..4677c83 100644
--- a/Source/CTest/cmCTestConfigureCommand.h
+++ b/Source/CTest/cmCTestConfigureCommand.h
@@ -6,11 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
+
+#include "cm_memory.hxx"
 
 class cmCTestGenericHandler;
-class cmCommand;
 
 /** \class cmCTestConfigure
  * \brief Run a ctest script
@@ -25,12 +28,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestConfigureCommand* ni = new cmCTestConfigureCommand;
+    auto ni = cm::make_unique<cmCTestConfigureCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index 1ae2d86..08f31f7 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -6,12 +6,15 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
 
 #include <set>
 #include <string>
+#include <utility>
+
+#include "cm_memory.hxx"
 
 class cmCTestGenericHandler;
-class cmCommand;
 
 /** \class cmCTestCoverage
  * \brief Run a ctest script
@@ -26,12 +29,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestCoverageCommand* ni = new cmCTestCoverageCommand;
+    auto ni = cm::make_unique<cmCTestCoverageCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index f6028c4..54fe612 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -13,6 +13,7 @@
 #include "cmParseGTMCoverage.h"
 #include "cmParseJacocoCoverage.h"
 #include "cmParsePHPCoverage.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 #include "cmXMLWriter.h"
@@ -1181,7 +1182,7 @@
         // gcov 4.7 can have output lines saying "No executable lines" and
         // "Removing 'filename.gcov'"... Don't log those as "errors."
         if (line != "No executable lines" &&
-            !cmSystemTools::StringStartsWith(line.c_str(), "Removing ")) {
+            !cmHasLiteralPrefix(line, "Removing ")) {
           cmCTestLog(this->CTest, ERROR_MESSAGE,
                      "Unknown gcov output line: [" << line << "]"
                                                    << std::endl);
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
index 9425ece..84250cb 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
@@ -6,11 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
 #include <vector>
 
-class cmCommand;
+#include "cm_memory.hxx"
+
 class cmExecutionStatus;
 
 /** \class cmCTestEmptyBinaryDirectory
@@ -27,13 +30,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestEmptyBinaryDirectoryCommand* ni =
-      new cmCTestEmptyBinaryDirectoryCommand;
+    auto ni = cm::make_unique<cmCTestEmptyBinaryDirectoryCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 9d9761c..093017c 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -10,11 +10,11 @@
 #include <time.h>
 #include <vector>
 
-#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessOutput.h"
 #include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major,
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index adf9553..8ceca08 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -4,6 +4,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestGenericHandler.h"
+#include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmSystemTools.h"
@@ -13,8 +14,6 @@
 #include <sstream>
 #include <stdlib.h>
 
-class cmExecutionStatus;
-
 cmCTestHandlerCommand::cmCTestHandlerCommand()
 {
   const size_t INIT_SIZE = 100;
@@ -86,7 +85,7 @@
 }
 
 bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
-                                        cmExecutionStatus& /*unused*/)
+                                        cmExecutionStatus& status)
 {
   // save error state and restore it if needed
   SaveRestoreErrorState errorState;
@@ -113,20 +112,20 @@
       foundBadArgument = true;
     }
   }
-  bool capureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] &&
-                           *this->Values[ct_CAPTURE_CMAKE_ERROR]);
+  bool captureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] &&
+                            *this->Values[ct_CAPTURE_CMAKE_ERROR]);
   // now that arguments are parsed check to see if there is a
   // CAPTURE_CMAKE_ERROR specified let the errorState object know.
-  if (capureCMakeError) {
+  if (captureCMakeError) {
     errorState.CaptureCMakeError();
   }
   // if we found a bad argument then exit before running command
   if (foundBadArgument) {
     // store the cmake error
-    if (capureCMakeError) {
+    if (captureCMakeError) {
       this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                     "-1");
-      std::string const err = this->GetName() + " " + this->GetError();
+      std::string const err = this->GetName() + " " + status.GetError();
       if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
         cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
       }
@@ -192,11 +191,11 @@
     cmCTestLog(this->CTest, ERROR_MESSAGE,
                "Cannot instantiate test handler " << this->GetName()
                                                   << std::endl);
-    if (capureCMakeError) {
+    if (captureCMakeError) {
       this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                     "-1");
-      const char* err = this->GetError();
-      if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+      std::string const& err = status.GetError();
+      if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
         cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
       }
       return true;
@@ -216,11 +215,11 @@
     this->SetError("failed to change directory to " +
                    this->CTest->GetCTestConfiguration("BuildDirectory") +
                    " : " + std::strerror(workdir.GetLastResult()));
-    if (capureCMakeError) {
+    if (captureCMakeError) {
       this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                     "-1");
       cmCTestLog(this->CTest, ERROR_MESSAGE,
-                 this->GetName() << " " << this->GetError() << "\n");
+                 this->GetName() << " " << status.GetError() << "\n");
       // return success because failure is recorded in CAPTURE_CMAKE_ERROR
       return true;
     }
@@ -231,19 +230,18 @@
   if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
     std::ostringstream str;
     str << res;
-    this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE],
-                                  str.str().c_str());
+    this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE], str.str());
   }
   this->ProcessAdditionalValues(handler);
   // log the error message if there was an error
-  if (capureCMakeError) {
+  if (captureCMakeError) {
     const char* returnString = "0";
     if (cmSystemTools::GetErrorOccuredFlag()) {
       returnString = "-1";
-      const char* err = this->GetError();
+      std::string const& err = status.GetError();
       // print out the error if it is not "unknown error" which means
       // there was no message
-      if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+      if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
         cmCTestLog(this->CTest, ERROR_MESSAGE, err);
       }
     }
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index a96513e..bbf490e 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -6,7 +6,6 @@
 #include "cmsys/Process.h"
 #include "cmsys/RegularExpression.hxx"
 #include <iostream>
-#include <memory> // IWYU pragma: keep
 #include <stdlib.h>
 #include <string.h>
 
@@ -17,6 +16,7 @@
 #include "cmProcessOutput.h"
 #include "cmState.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 #include "cmake.h"
@@ -595,7 +595,7 @@
 bool cmCTestLaunch::MatchesFilterPrefix(std::string const& line) const
 {
   return !this->OptionFilterPrefix.empty() &&
-    cmSystemTools::StringStartsWith(line, this->OptionFilterPrefix.c_str());
+    cmHasPrefix(line, this->OptionFilterPrefix);
 }
 
 int cmCTestLaunch::Main(int argc, const char* const argv[])
diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx
index 7dad1ce..d7d42bf 100644
--- a/Source/CTest/cmCTestMemCheckCommand.cxx
+++ b/Source/CTest/cmCTestMemCheckCommand.cxx
@@ -3,7 +3,6 @@
 #include "cmCTestMemCheckCommand.h"
 
 #include <sstream>
-#include <string>
 #include <vector>
 
 #include "cmCTest.h"
@@ -47,7 +46,6 @@
   if (this->Values[ctm_DEFECT_COUNT] && *this->Values[ctm_DEFECT_COUNT]) {
     std::ostringstream str;
     str << static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount();
-    this->Makefile->AddDefinition(this->Values[ctm_DEFECT_COUNT],
-                                  str.str().c_str());
+    this->Makefile->AddDefinition(this->Values[ctm_DEFECT_COUNT], str.str());
   }
 }
diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h
index b6b3c40..837a687 100644
--- a/Source/CTest/cmCTestMemCheckCommand.h
+++ b/Source/CTest/cmCTestMemCheckCommand.h
@@ -5,10 +5,14 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <utility>
+
+#include "cm_memory.hxx"
+
 #include "cmCTestTestCommand.h"
+#include "cmCommand.h"
 
 class cmCTestGenericHandler;
-class cmCommand;
 
 /** \class cmCTestMemCheck
  * \brief Run a ctest script
@@ -23,12 +27,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestMemCheckCommand* ni = new cmCTestMemCheckCommand;
+    auto ni = cm::make_unique<cmCTestMemCheckCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
 protected:
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index ef63073..42534f7 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -29,11 +29,13 @@
 #include <iostream>
 #include <list>
 #include <math.h>
+#include <memory>
 #include <sstream>
 #include <stack>
 #include <stdlib.h>
 #include <unordered_map>
 #include <utility>
+#include <vector>
 
 namespace cmsys {
 class RegularExpression;
@@ -821,6 +823,11 @@
       "FAIL_REGULAR_EXPRESSION",
       DumpRegExToJsonArray(testProperties.ErrorRegularExpressions)));
   }
+  if (!testProperties.SkipRegularExpressions.empty()) {
+    properties.append(DumpCTestProperty(
+      "SKIP_REGULAR_EXPRESSION",
+      DumpRegExToJsonArray(testProperties.SkipRegularExpressions)));
+  }
   if (!testProperties.FixturesCleanup.empty()) {
     properties.append(DumpCTestProperty(
       "FIXTURES_CLEANUP", DumpToJsonArray(testProperties.FixturesCleanup)));
diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.h b/Source/CTest/cmCTestReadCustomFilesCommand.h
index ba25c51..db2ac5e 100644
--- a/Source/CTest/cmCTestReadCustomFilesCommand.h
+++ b/Source/CTest/cmCTestReadCustomFilesCommand.h
@@ -6,11 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
 #include <vector>
 
-class cmCommand;
+#include "cm_memory.hxx"
+
 class cmExecutionStatus;
 
 /** \class cmCTestReadCustomFiles
@@ -27,11 +30,11 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestReadCustomFilesCommand* ni = new cmCTestReadCustomFilesCommand;
+    auto ni = cm::make_unique<cmCTestReadCustomFilesCommand>();
     ni->CTest = this->CTest;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx
index a7e47d3..c03cffd 100644
--- a/Source/CTest/cmCTestRunScriptCommand.cxx
+++ b/Source/CTest/cmCTestRunScriptCommand.cxx
@@ -43,7 +43,7 @@
                                       args[i].c_str(), !np, &ret);
       std::ostringstream str;
       str << ret;
-      this->Makefile->AddDefinition(returnVariable, str.str().c_str());
+      this->Makefile->AddDefinition(returnVariable, str.str());
     }
   }
   return true;
diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h
index 9d8b4b5..6961f6e 100644
--- a/Source/CTest/cmCTestRunScriptCommand.h
+++ b/Source/CTest/cmCTestRunScriptCommand.h
@@ -6,11 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
 #include <vector>
 
-class cmCommand;
+#include "cm_memory.hxx"
+
 class cmExecutionStatus;
 
 /** \class cmCTestRunScript
@@ -27,12 +30,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestRunScriptCommand* ni = new cmCTestRunScriptCommand;
+    auto ni = cm::make_unique<cmCTestRunScriptCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 31976b9..65cf646 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -11,7 +11,6 @@
 
 #include "cmsys/RegularExpression.hxx"
 #include <chrono>
-#include <cmAlgorithms.h>
 #include <cstdint>
 #include <cstring>
 #include <iomanip>
@@ -20,6 +19,8 @@
 #include <stdio.h>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler)
   : MultiTestHandler(multiHandler)
 {
@@ -76,6 +77,7 @@
   }
   std::int64_t retVal = this->TestProcess->GetExitValue();
   bool forceFail = false;
+  bool forceSkip = false;
   bool skipped = false;
   bool outputTestErrorsToConsole = false;
   if (!this->TestProperties->RequiredRegularExpressions.empty() &&
@@ -85,43 +87,64 @@
       if (pass.first.find(this->ProcessOutput)) {
         found = true;
         reason = "Required regular expression found.";
+        reason += " Regex=[";
+        reason += pass.second;
+        reason += "]";
         break;
       }
     }
     if (!found) {
       reason = "Required regular expression not found.";
+      reason += " Regex=[";
+      for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
+        reason += pass.second;
+        reason += "\n";
+      }
+      reason += "]";
       forceFail = true;
     }
-    reason += "Regex=[";
-    for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
-      reason += pass.second;
-      reason += "\n";
-    }
-    reason += "]";
   }
   if (!this->TestProperties->ErrorRegularExpressions.empty() &&
       this->FailedDependencies.empty()) {
-    for (auto& pass : this->TestProperties->ErrorRegularExpressions) {
-      if (pass.first.find(this->ProcessOutput)) {
+    for (auto& fail : this->TestProperties->ErrorRegularExpressions) {
+      if (fail.first.find(this->ProcessOutput)) {
         reason = "Error regular expression found in output.";
         reason += " Regex=[";
-        reason += pass.second;
+        reason += fail.second;
         reason += "]";
         forceFail = true;
         break;
       }
     }
   }
+  if (!this->TestProperties->SkipRegularExpressions.empty() &&
+      this->FailedDependencies.empty()) {
+    for (auto& skip : this->TestProperties->SkipRegularExpressions) {
+      if (skip.first.find(this->ProcessOutput)) {
+        reason = "Skip regular expression found in output.";
+        reason += " Regex=[";
+        reason += skip.second;
+        reason += "]";
+        forceSkip = true;
+        break;
+      }
+    }
+  }
   std::ostringstream outputStream;
   if (res == cmProcess::State::Exited) {
     bool success = !forceFail &&
       (retVal == 0 ||
        !this->TestProperties->RequiredRegularExpressions.empty());
-    if (this->TestProperties->SkipReturnCode >= 0 &&
-        this->TestProperties->SkipReturnCode == retVal) {
+    if ((this->TestProperties->SkipReturnCode >= 0 &&
+         this->TestProperties->SkipReturnCode == retVal) ||
+        forceSkip) {
       this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
       std::ostringstream s;
-      s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode;
+      if (forceSkip) {
+        s << "SKIP_REGULAR_EXPRESSION_MATCHED";
+      } else {
+        s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode;
+      }
       this->TestResult.CompletionStatus = s.str();
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Skipped ");
       skipped = true;
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 38cc417..43dfe8e 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <memory>
 #include <set>
 #include <stddef.h>
 #include <string>
@@ -12,7 +13,7 @@
 
 #include "cmCTestTestHandler.h"
 #include "cmDuration.h"
-#include "cmProcess.h" // IWYU pragma: keep (for unique_ptr)
+#include "cmProcess.h"
 
 class cmCTest;
 class cmCTestMultiProcessHandler;
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index a739f44..7a5b8d1 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -4,13 +4,8 @@
 
 #include "cmsys/Directory.hxx"
 #include "cmsys/Process.h"
-#include <map>
-#include <ratio>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <utility>
+
+#include "cm_memory.hxx"
 
 #include "cmCTest.h"
 #include "cmCTestBuildCommand.h"
@@ -27,6 +22,7 @@
 #include "cmCTestTestCommand.h"
 #include "cmCTestUpdateCommand.h"
 #include "cmCTestUploadCommand.h"
+#include "cmCommand.h"
 #include "cmDuration.h"
 #include "cmFunctionBlocker.h"
 #include "cmGeneratedFileStream.h"
@@ -38,6 +34,15 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
+#include <map>
+#include <memory>
+#include <ratio>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
+
 #ifdef _WIN32
 #  include <windows.h>
 #else
@@ -163,16 +168,16 @@
     auto itime = cmDurationTo<unsigned int>(std::chrono::steady_clock::now() -
                                             this->ScriptStartTime);
     auto timeString = std::to_string(itime);
-    this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString.c_str());
+    this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString);
   }
 }
 
-void cmCTestScriptHandler::AddCTestCommand(std::string const& name,
-                                           cmCTestCommand* command)
+void cmCTestScriptHandler::AddCTestCommand(
+  std::string const& name, std::unique_ptr<cmCTestCommand> command)
 {
   command->CTest = this->CTest;
   command->CTestScriptHandler = this;
-  this->CMake->GetState()->AddBuiltinCommand(name, command);
+  this->CMake->GetState()->AddBuiltinCommand(name, std::move(command));
 }
 
 int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
@@ -295,21 +300,28 @@
       }
     });
 
-  this->AddCTestCommand("ctest_build", new cmCTestBuildCommand);
-  this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand);
-  this->AddCTestCommand("ctest_coverage", new cmCTestCoverageCommand);
+  this->AddCTestCommand("ctest_build", cm::make_unique<cmCTestBuildCommand>());
+  this->AddCTestCommand("ctest_configure",
+                        cm::make_unique<cmCTestConfigureCommand>());
+  this->AddCTestCommand("ctest_coverage",
+                        cm::make_unique<cmCTestCoverageCommand>());
   this->AddCTestCommand("ctest_empty_binary_directory",
-                        new cmCTestEmptyBinaryDirectoryCommand);
-  this->AddCTestCommand("ctest_memcheck", new cmCTestMemCheckCommand);
+                        cm::make_unique<cmCTestEmptyBinaryDirectoryCommand>());
+  this->AddCTestCommand("ctest_memcheck",
+                        cm::make_unique<cmCTestMemCheckCommand>());
   this->AddCTestCommand("ctest_read_custom_files",
-                        new cmCTestReadCustomFilesCommand);
-  this->AddCTestCommand("ctest_run_script", new cmCTestRunScriptCommand);
-  this->AddCTestCommand("ctest_sleep", new cmCTestSleepCommand);
-  this->AddCTestCommand("ctest_start", new cmCTestStartCommand);
-  this->AddCTestCommand("ctest_submit", new cmCTestSubmitCommand);
-  this->AddCTestCommand("ctest_test", new cmCTestTestCommand);
-  this->AddCTestCommand("ctest_update", new cmCTestUpdateCommand);
-  this->AddCTestCommand("ctest_upload", new cmCTestUploadCommand);
+                        cm::make_unique<cmCTestReadCustomFilesCommand>());
+  this->AddCTestCommand("ctest_run_script",
+                        cm::make_unique<cmCTestRunScriptCommand>());
+  this->AddCTestCommand("ctest_sleep", cm::make_unique<cmCTestSleepCommand>());
+  this->AddCTestCommand("ctest_start", cm::make_unique<cmCTestStartCommand>());
+  this->AddCTestCommand("ctest_submit",
+                        cm::make_unique<cmCTestSubmitCommand>());
+  this->AddCTestCommand("ctest_test", cm::make_unique<cmCTestTestCommand>());
+  this->AddCTestCommand("ctest_update",
+                        cm::make_unique<cmCTestUpdateCommand>());
+  this->AddCTestCommand("ctest_upload",
+                        cm::make_unique<cmCTestUploadCommand>());
 }
 
 // this sets up some variables for the script to use, creates the required
@@ -340,21 +352,21 @@
   this->CreateCMake();
 
   // set a variable with the path to the current script
-  this->Makefile->AddDefinition(
-    "CTEST_SCRIPT_DIRECTORY", cmSystemTools::GetFilenamePath(script).c_str());
-  this->Makefile->AddDefinition(
-    "CTEST_SCRIPT_NAME", cmSystemTools::GetFilenameName(script).c_str());
+  this->Makefile->AddDefinition("CTEST_SCRIPT_DIRECTORY",
+                                cmSystemTools::GetFilenamePath(script));
+  this->Makefile->AddDefinition("CTEST_SCRIPT_NAME",
+                                cmSystemTools::GetFilenameName(script));
   this->Makefile->AddDefinition("CTEST_EXECUTABLE_NAME",
-                                cmSystemTools::GetCTestCommand().c_str());
+                                cmSystemTools::GetCTestCommand());
   this->Makefile->AddDefinition("CMAKE_EXECUTABLE_NAME",
-                                cmSystemTools::GetCMakeCommand().c_str());
-  this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", true);
+                                cmSystemTools::GetCMakeCommand());
+  this->Makefile->AddDefinitionBool("CTEST_RUN_CURRENT_SCRIPT", true);
   this->SetRunCurrentScript(true);
   this->UpdateElapsedTime();
 
   // add the script arg if defined
   if (!script_arg.empty()) {
-    this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg.c_str());
+    this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg);
   }
 
 #if defined(__CYGWIN__)
@@ -362,9 +374,11 @@
 #endif
 
   // always add a function blocker to update the elapsed time
-  cmCTestScriptFunctionBlocker* f = new cmCTestScriptFunctionBlocker();
-  f->CTestScriptHandler = this;
-  this->Makefile->AddFunctionBlocker(f);
+  {
+    auto fb = cm::make_unique<cmCTestScriptFunctionBlocker>();
+    fb->CTestScriptHandler = this;
+    this->Makefile->AddFunctionBlocker(std::move(fb));
+  }
 
   /* Execute CTestScriptMode.cmake, which loads CMakeDetermineSystem and
   CMakeSystemSpecificInformation, so
@@ -384,7 +398,7 @@
   const std::map<std::string, std::string>& defs =
     this->CTest->GetDefinitions();
   for (auto const& d : defs) {
-    this->Makefile->AddDefinition(d.first, d.second.c_str());
+    this->Makefile->AddDefinition(d.first, d.second);
   }
 
   // finally read in the script
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index d93b5f8..b2e8cbf 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -9,6 +9,7 @@
 #include "cmDuration.h"
 
 #include <chrono>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -131,7 +132,8 @@
   int RunConfigurationDashboard();
 
   // Add ctest command
-  void AddCTestCommand(std::string const& name, cmCTestCommand* command);
+  void AddCTestCommand(std::string const& name,
+                       std::unique_ptr<cmCTestCommand> command);
 
   // Try to remove the binary directory once
   static bool TryToRemoveBinaryDirectoryOnce(const std::string& directoryPath);
diff --git a/Source/CTest/cmCTestSleepCommand.h b/Source/CTest/cmCTestSleepCommand.h
index 5cd185a..7b17081 100644
--- a/Source/CTest/cmCTestSleepCommand.h
+++ b/Source/CTest/cmCTestSleepCommand.h
@@ -6,11 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
 #include <vector>
 
-class cmCommand;
+#include "cm_memory.hxx"
+
 class cmExecutionStatus;
 
 /** \class cmCTestSleep
@@ -27,12 +30,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestSleepCommand* ni = new cmCTestSleepCommand;
+    auto ni = cm::make_unique<cmCTestSleepCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h
index 542f27c..7c71f36 100644
--- a/Source/CTest/cmCTestStartCommand.h
+++ b/Source/CTest/cmCTestStartCommand.h
@@ -6,12 +6,15 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestCommand.h"
+#include "cmCommand.h"
 
 #include <iosfwd>
 #include <string>
+#include <utility>
 #include <vector>
 
-class cmCommand;
+#include "cm_memory.hxx"
+
 class cmExecutionStatus;
 
 /** \class cmCTestStart
@@ -27,14 +30,14 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestStartCommand* ni = new cmCTestStartCommand;
+    auto ni = cm::make_unique<cmCTestStartCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
     ni->CreateNewTag = this->CreateNewTag;
     ni->Quiet = this->Quiet;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index afc3e67..58c0a1b 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -4,11 +4,15 @@
 
 #include "cmCTest.h"
 #include "cmCTestSubmitHandler.h"
+#include "cmCommand.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmSystemTools.h"
 
 #include <sstream>
+#include <utility>
+
+#include "cm_memory.hxx"
 
 class cmExecutionStatus;
 
@@ -27,12 +31,12 @@
 /**
  * This is a virtual constructor for the command.
  */
-cmCommand* cmCTestSubmitCommand::Clone()
+std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone()
 {
-  cmCTestSubmitCommand* ni = new cmCTestSubmitCommand;
+  auto ni = cm::make_unique<cmCTestSubmitCommand>();
   ni->CTest = this->CTest;
   ni->CTestScriptHandler = this->CTestScriptHandler;
-  return ni;
+  return std::unique_ptr<cmCommand>(std::move(ni));
 }
 
 cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
@@ -139,7 +143,7 @@
 
   if (this->Values[cts_BUILD_ID] && *this->Values[cts_BUILD_ID]) {
     this->Makefile->AddDefinition(this->Values[cts_BUILD_ID],
-                                  this->CTest->GetBuildID().c_str());
+                                  this->CTest->GetBuildID());
   }
 
   return ret;
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index 1e27046..5bbcd39 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -8,12 +8,13 @@
 #include "cmCTest.h"
 #include "cmCTestHandlerCommand.h"
 
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
 
-class cmCTestGenericHandler;
 class cmCommand;
+class cmCTestGenericHandler;
 class cmExecutionStatus;
 
 /** \class cmCTestSubmit
@@ -26,7 +27,7 @@
 {
 public:
   cmCTestSubmitCommand();
-  cmCommand* Clone() override;
+  std::unique_ptr<cmCommand> Clone() override;
 
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 54c4bae..2c6ff83 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -19,6 +19,7 @@
 #include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 #include "cmake.h"
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index 11c0db9..d74136c 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -6,11 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
+
+#include "cm_memory.hxx"
 
 class cmCTestGenericHandler;
-class cmCommand;
 
 /** \class cmCTestTest
  * \brief Run a ctest script
@@ -25,12 +28,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestTestCommand* ni = new cmCTestTestCommand;
+    auto ni = cm::make_unique<cmCTestTestCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 0ed56c8..67c24ca 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -11,14 +11,15 @@
 #include <functional>
 #include <iomanip>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
 #include <set>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
+#include <utility>
 
-#include "cmAlgorithms.h"
+#include "cm_memory.hxx"
+
 #include "cmCTest.h"
 #include "cmCTestMultiProcessHandler.h"
 #include "cmCommand.h"
@@ -28,6 +29,7 @@
 #include "cmMakefile.h"
 #include "cmState.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 #include "cmXMLWriter.h"
@@ -43,11 +45,11 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestSubdirCommand* c = new cmCTestSubdirCommand;
+    auto c = cm::make_unique<cmCTestSubdirCommand>();
     c->TestHandler = this->TestHandler;
-    return c;
+    return std::unique_ptr<cmCommand>(std::move(c));
   }
 
   /**
@@ -122,11 +124,11 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestAddSubdirectoryCommand* c = new cmCTestAddSubdirectoryCommand;
+    auto c = cm::make_unique<cmCTestAddSubdirectoryCommand>();
     c->TestHandler = this->TestHandler;
-    return c;
+    return std::unique_ptr<cmCommand>(std::move(c));
   }
 
   /**
@@ -187,11 +189,11 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestAddTestCommand* c = new cmCTestAddTestCommand;
+    auto c = cm::make_unique<cmCTestAddTestCommand>();
     c->TestHandler = this->TestHandler;
-    return c;
+    return std::unique_ptr<cmCommand>(std::move(c));
   }
 
   /**
@@ -220,11 +222,11 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestSetTestsPropertiesCommand* c = new cmCTestSetTestsPropertiesCommand;
+    auto c = cm::make_unique<cmCTestSetTestsPropertiesCommand>();
     c->TestHandler = this->TestHandler;
-    return c;
+    return std::unique_ptr<cmCommand>(std::move(c));
   }
 
   /**
@@ -249,12 +251,11 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestSetDirectoryPropertiesCommand* c =
-      new cmCTestSetDirectoryPropertiesCommand;
+    auto c = cm::make_unique<cmCTestSetDirectoryPropertiesCommand>();
     c->TestHandler = this->TestHandler;
-    return c;
+    return std::unique_ptr<cmCommand>(std::move(c));
   }
 
   /**
@@ -422,10 +423,93 @@
   return 1;
 }
 
-// clearly it would be nice if this were broken up into a few smaller
-// functions and commented...
 int cmCTestTestHandler::ProcessHandler()
 {
+  if (!this->ProcessOptions()) {
+    return -1;
+  }
+
+  this->TestResults.clear();
+
+  cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+                     (this->MemCheck ? "Memory check" : "Test")
+                       << " project "
+                       << cmSystemTools::GetCurrentWorkingDirectory()
+                       << std::endl,
+                     this->Quiet);
+  if (!this->PreProcessHandler()) {
+    return -1;
+  }
+
+  cmGeneratedFileStream mLogFile;
+  this->StartLogFile((this->MemCheck ? "DynamicAnalysis" : "Test"), mLogFile);
+  this->LogFile = &mLogFile;
+
+  std::vector<std::string> passed;
+  std::vector<std::string> failed;
+
+  // start the real time clock
+  auto clock_start = std::chrono::steady_clock::now();
+
+  this->ProcessDirectory(passed, failed);
+
+  auto clock_finish = std::chrono::steady_clock::now();
+
+  if (passed.size() + failed.size() == 0) {
+    if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+                 "No tests were found!!!" << std::endl);
+    }
+  } else {
+    if (this->HandlerVerbose && !passed.empty() &&
+        (this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag)) {
+      cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+                         std::endl
+                           << "The following tests passed:" << std::endl,
+                         this->Quiet);
+      for (std::string const& j : passed) {
+        cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+                           "\t" << j << std::endl, this->Quiet);
+      }
+    }
+
+    SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end());
+    std::vector<cmCTestTestHandler::cmCTestTestResult> disabledTests;
+
+    for (cmCTestTestResult const& ft : resultsSet) {
+      if (cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_") ||
+          ft.CompletionStatus == "Disabled") {
+        disabledTests.push_back(ft);
+      }
+    }
+
+    cmDuration durationInSecs = clock_finish - clock_start;
+    this->LogTestSummary(passed, failed, durationInSecs);
+
+    this->LogDisabledTests(disabledTests);
+
+    this->LogFailedTests(failed, resultsSet);
+  }
+
+  if (!this->GenerateXML()) {
+    return 1;
+  }
+
+  if (!this->PostProcessHandler()) {
+    this->LogFile = nullptr;
+    return -1;
+  }
+
+  if (!failed.empty()) {
+    this->LogFile = nullptr;
+    return -1;
+  }
+  this->LogFile = nullptr;
+  return 0;
+}
+
+bool cmCTestTestHandler::ProcessOptions()
+{
   // Update internal data structure from generic one
   this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));
   this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
@@ -471,152 +555,110 @@
   }
   this->SetRerunFailed(cmSystemTools::IsOn(this->GetOption("RerunFailed")));
 
-  this->TestResults.clear();
+  return true;
+}
 
-  cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
-                     (this->MemCheck ? "Memory check" : "Test")
-                       << " project "
-                       << cmSystemTools::GetCurrentWorkingDirectory()
-                       << std::endl,
-                     this->Quiet);
-  if (!this->PreProcessHandler()) {
-    return -1;
+void cmCTestTestHandler::LogTestSummary(const std::vector<std::string>& passed,
+                                        const std::vector<std::string>& failed,
+                                        const cmDuration& durationInSecs)
+{
+  std::size_t total = passed.size() + failed.size();
+
+  float percent = float(passed.size()) * 100.0f / float(total);
+  if (!failed.empty() && percent > 99) {
+    percent = 99;
   }
 
-  cmGeneratedFileStream mLogFile;
-  this->StartLogFile((this->MemCheck ? "DynamicAnalysis" : "Test"), mLogFile);
-  this->LogFile = &mLogFile;
-
-  std::vector<std::string> passed;
-  std::vector<std::string> failed;
-  int total;
-
-  // start the real time clock
-  auto clock_start = std::chrono::steady_clock::now();
-
-  this->ProcessDirectory(passed, failed);
-
-  auto clock_finish = std::chrono::steady_clock::now();
-
-  total = int(passed.size()) + int(failed.size());
-
-  if (total == 0) {
-    if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
-      cmCTestLog(this->CTest, ERROR_MESSAGE,
-                 "No tests were found!!!" << std::endl);
-    }
+  std::string passColorCode;
+  std::string failedColorCode;
+  if (failed.empty()) {
+    passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN);
   } else {
-    if (this->HandlerVerbose && !passed.empty() &&
-        (this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag)) {
-      cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
-                         std::endl
-                           << "The following tests passed:" << std::endl,
-                         this->Quiet);
-      for (std::string const& j : passed) {
-        cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
-                           "\t" << j << std::endl, this->Quiet);
-      }
-    }
+    failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED);
+  }
+  cmCTestLog(this->CTest, HANDLER_OUTPUT,
+             std::endl
+               << passColorCode << std::lround(percent) << "% tests passed"
+               << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+               << ", " << failedColorCode << failed.size() << " tests failed"
+               << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+               << " out of " << total << std::endl);
+  if ((!this->CTest->GetLabelsForSubprojects().empty() &&
+       this->CTest->GetSubprojectSummary())) {
+    this->PrintLabelOrSubprojectSummary(true);
+  }
+  if (this->CTest->GetLabelSummary()) {
+    this->PrintLabelOrSubprojectSummary(false);
+  }
+  char realBuf[1024];
+  sprintf(realBuf, "%6.2f sec", durationInSecs.count());
+  cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+                     "\nTotal Test time (real) = " << realBuf << "\n",
+                     this->Quiet);
+}
 
-    typedef std::set<cmCTestTestHandler::cmCTestTestResult,
-                     cmCTestTestResultLess>
-      SetOfTests;
-    SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end());
-    std::vector<cmCTestTestHandler::cmCTestTestResult> disabledTests;
-
-    for (cmCTestTestResult const& ft : resultsSet) {
-      if (cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") ||
-          ft.CompletionStatus == "Disabled") {
-        disabledTests.push_back(ft);
-      }
-    }
-
-    float percent = float(passed.size()) * 100.0f / float(total);
-    if (!failed.empty() && percent > 99) {
-      percent = 99;
-    }
-
-    std::string passColorCode;
-    std::string failedColorCode;
-    if (failed.empty()) {
-      passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN);
-    } else {
-      failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED);
-    }
+void cmCTestTestHandler::LogDisabledTests(
+  const std::vector<cmCTestTestResult>& disabledTests)
+{
+  if (!disabledTests.empty()) {
+    cmGeneratedFileStream ofs;
     cmCTestLog(this->CTest, HANDLER_OUTPUT,
                std::endl
-                 << passColorCode << std::lround(percent) << "% tests passed"
-                 << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
-                 << ", " << failedColorCode << failed.size() << " tests failed"
-                 << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
-                 << " out of " << total << std::endl);
-    if ((!this->CTest->GetLabelsForSubprojects().empty() &&
-         this->CTest->GetSubprojectSummary())) {
-      this->PrintLabelOrSubprojectSummary(true);
-    }
-    if (this->CTest->GetLabelSummary()) {
-      this->PrintLabelOrSubprojectSummary(false);
-    }
-    char realBuf[1024];
-    cmDuration durationInSecs = clock_finish - clock_start;
-    sprintf(realBuf, "%6.2f sec", durationInSecs.count());
-    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
-                       "\nTotal Test time (real) = " << realBuf << "\n",
-                       this->Quiet);
+                 << "The following tests did not run:" << std::endl);
+    this->StartLogFile("TestsDisabled", ofs);
 
-    if (!disabledTests.empty()) {
-      cmGeneratedFileStream ofs;
-      cmCTestLog(this->CTest, HANDLER_OUTPUT,
-                 std::endl
-                   << "The following tests did not run:" << std::endl);
-      this->StartLogFile("TestsDisabled", ofs);
-
-      const char* disabled_reason;
-      cmCTestLog(this->CTest, HANDLER_OUTPUT,
-                 this->CTest->GetColorCode(cmCTest::Color::BLUE));
-      for (cmCTestTestResult const& dt : disabledTests) {
-        ofs << dt.TestCount << ":" << dt.Name << std::endl;
-        if (dt.CompletionStatus == "Disabled") {
-          disabled_reason = "Disabled";
-        } else {
-          disabled_reason = "Skipped";
-        }
-        cmCTestLog(this->CTest, HANDLER_OUTPUT,
-                   "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name
-                        << " (" << disabled_reason << ")" << std::endl);
+    const char* disabled_reason;
+    cmCTestLog(this->CTest, HANDLER_OUTPUT,
+               this->CTest->GetColorCode(cmCTest::Color::BLUE));
+    for (cmCTestTestResult const& dt : disabledTests) {
+      ofs << dt.TestCount << ":" << dt.Name << std::endl;
+      if (dt.CompletionStatus == "Disabled") {
+        disabled_reason = "Disabled";
+      } else {
+        disabled_reason = "Skipped";
       }
       cmCTestLog(this->CTest, HANDLER_OUTPUT,
-                 this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR));
+                 "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name
+                      << " (" << disabled_reason << ")" << std::endl);
     }
+    cmCTestLog(this->CTest, HANDLER_OUTPUT,
+               this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR));
+  }
+}
 
-    if (!failed.empty()) {
-      cmGeneratedFileStream ofs;
-      cmCTestLog(this->CTest, HANDLER_OUTPUT,
-                 std::endl
-                   << "The following tests FAILED:" << std::endl);
-      this->StartLogFile("TestsFailed", ofs);
+void cmCTestTestHandler::LogFailedTests(const std::vector<std::string>& failed,
+                                        const SetOfTests& resultsSet)
+{
+  if (!failed.empty()) {
+    cmGeneratedFileStream ofs;
+    cmCTestLog(this->CTest, HANDLER_OUTPUT,
+               std::endl
+                 << "The following tests FAILED:" << std::endl);
+    this->StartLogFile("TestsFailed", ofs);
 
-      for (cmCTestTestResult const& ft : resultsSet) {
-        if (ft.Status != cmCTestTestHandler::COMPLETED &&
-            !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") &&
-            ft.CompletionStatus != "Disabled") {
-          ofs << ft.TestCount << ":" << ft.Name << std::endl;
-          auto testColor = cmCTest::Color::RED;
-          if (this->GetTestStatus(ft) == "Not Run") {
-            testColor = cmCTest::Color::YELLOW;
-          }
-          cmCTestLog(
-            this->CTest, HANDLER_OUTPUT,
-            "\t" << this->CTest->GetColorCode(testColor) << std::setw(3)
-                 << ft.TestCount << " - " << ft.Name << " ("
-                 << this->GetTestStatus(ft) << ")"
-                 << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
-                 << std::endl);
+    for (cmCTestTestResult const& ft : resultsSet) {
+      if (ft.Status != cmCTestTestHandler::COMPLETED &&
+          !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_") &&
+          ft.CompletionStatus != "Disabled") {
+        ofs << ft.TestCount << ":" << ft.Name << std::endl;
+        auto testColor = cmCTest::Color::RED;
+        if (this->GetTestStatus(ft) == "Not Run") {
+          testColor = cmCTest::Color::YELLOW;
         }
+        cmCTestLog(
+          this->CTest, HANDLER_OUTPUT,
+          "\t" << this->CTest->GetColorCode(testColor) << std::setw(3)
+               << ft.TestCount << " - " << ft.Name << " ("
+               << this->GetTestStatus(ft) << ")"
+               << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+               << std::endl);
       }
     }
   }
+}
 
+bool cmCTestTestHandler::GenerateXML()
+{
   if (this->CTest->GetProduceXML()) {
     cmGeneratedFileStream xmlfile;
     if (!this->StartResultingXML(
@@ -627,23 +669,13 @@
                    << (this->MemCheck ? "memory check" : "testing")
                    << " XML file" << std::endl);
       this->LogFile = nullptr;
-      return 1;
+      return false;
     }
     cmXMLWriter xml(xmlfile);
     this->GenerateDartOutput(xml);
   }
 
-  if (!this->PostProcessHandler()) {
-    this->LogFile = nullptr;
-    return -1;
-  }
-
-  if (!failed.empty()) {
-    this->LogFile = nullptr;
-    return -1;
-  }
-  this->LogFile = nullptr;
-  return 0;
+  return true;
 }
 
 void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
@@ -1682,36 +1714,34 @@
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
   cmGlobalGenerator gg(&cm);
   cmMakefile mf(&gg, cm.GetCurrentSnapshot());
-  mf.AddDefinition("CTEST_CONFIGURATION_TYPE",
-                   this->CTest->GetConfigType().c_str());
+  mf.AddDefinition("CTEST_CONFIGURATION_TYPE", this->CTest->GetConfigType());
 
   // Add handler for ADD_TEST
-  cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand;
+  auto newCom1 = cm::make_unique<cmCTestAddTestCommand>();
   newCom1->TestHandler = this;
-  cm.GetState()->AddBuiltinCommand("add_test", newCom1);
+  cm.GetState()->AddBuiltinCommand("add_test", std::move(newCom1));
 
   // Add handler for SUBDIRS
-  cmCTestSubdirCommand* newCom2 = new cmCTestSubdirCommand;
+  auto newCom2 = cm::make_unique<cmCTestSubdirCommand>();
   newCom2->TestHandler = this;
-  cm.GetState()->AddBuiltinCommand("subdirs", newCom2);
+  cm.GetState()->AddBuiltinCommand("subdirs", std::move(newCom2));
 
   // Add handler for ADD_SUBDIRECTORY
-  cmCTestAddSubdirectoryCommand* newCom3 = new cmCTestAddSubdirectoryCommand;
+  auto newCom3 = cm::make_unique<cmCTestAddSubdirectoryCommand>();
   newCom3->TestHandler = this;
-  cm.GetState()->AddBuiltinCommand("add_subdirectory", newCom3);
+  cm.GetState()->AddBuiltinCommand("add_subdirectory", std::move(newCom3));
 
   // Add handler for SET_TESTS_PROPERTIES
-  cmCTestSetTestsPropertiesCommand* newCom4 =
-    new cmCTestSetTestsPropertiesCommand;
+  auto newCom4 = cm::make_unique<cmCTestSetTestsPropertiesCommand>();
   newCom4->TestHandler = this;
-  cm.GetState()->AddBuiltinCommand("set_tests_properties", newCom4);
+  cm.GetState()->AddBuiltinCommand("set_tests_properties", std::move(newCom4));
 
   // Add handler for SET_DIRECTORY_PROPERTIES
   cm.GetState()->RemoveBuiltinCommand("set_directory_properties");
-  cmCTestSetDirectoryPropertiesCommand* newCom5 =
-    new cmCTestSetDirectoryPropertiesCommand;
+  auto newCom5 = cm::make_unique<cmCTestSetDirectoryPropertiesCommand>();
   newCom5->TestHandler = this;
-  cm.GetState()->AddBuiltinCommand("set_directory_properties", newCom5);
+  cm.GetState()->AddBuiltinCommand("set_directory_properties",
+                                   std::move(newCom5));
 
   const char* testFilename;
   if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
@@ -2229,6 +2259,13 @@
               rt.ErrorRegularExpressions.emplace_back(cr, cr);
             }
           }
+          if (key == "SKIP_REGULAR_EXPRESSION") {
+            std::vector<std::string> lval;
+            cmSystemTools::ExpandListArgument(val, lval);
+            for (std::string const& cr : lval) {
+              rt.SkipRegularExpressions.emplace_back(cr, cr);
+            }
+          }
           if (key == "PROCESSORS") {
             rt.Processors = atoi(val.c_str());
             if (rt.Processors < 1) {
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 7f3f5e4..9345185 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -118,6 +118,8 @@
     std::vector<std::pair<cmsys::RegularExpression, std::string>>
       RequiredRegularExpressions;
     std::vector<std::pair<cmsys::RegularExpression, std::string>>
+      SkipRegularExpressions;
+    std::vector<std::pair<cmsys::RegularExpression, std::string>>
       TimeoutRegularExpressions;
     std::map<std::string, std::string> Measurements;
     bool IsInBasedOnREOptions;
@@ -189,12 +191,25 @@
   typedef std::vector<cmCTestTestProperties> ListOfTests;
 
 protected:
+  typedef std::set<cmCTestTestHandler::cmCTestTestResult,
+                   cmCTestTestResultLess>
+    SetOfTests;
+
   // compute a final test list
   virtual int PreProcessHandler();
   virtual int PostProcessHandler();
   virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
   int ExecuteCommands(std::vector<std::string>& vec);
 
+  bool ProcessOptions();
+  void LogTestSummary(const std::vector<std::string>& passed,
+                      const std::vector<std::string>& failed,
+                      const cmDuration& durationInSecs);
+  void LogDisabledTests(const std::vector<cmCTestTestResult>& disabledTests);
+  void LogFailedTests(const std::vector<std::string>& failed,
+                      const SetOfTests& resultsSet);
+  bool GenerateXML();
+
   void WriteTestResultHeader(cmXMLWriter& xml,
                              cmCTestTestResult const& result);
   void WriteTestResultFooter(cmXMLWriter& xml,
diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h
index 3b2f3e1..55c4b80 100644
--- a/Source/CTest/cmCTestUpdateCommand.h
+++ b/Source/CTest/cmCTestUpdateCommand.h
@@ -6,11 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
 
 #include <string>
+#include <utility>
+
+#include "cm_memory.hxx"
 
 class cmCTestGenericHandler;
-class cmCommand;
 
 /** \class cmCTestUpdate
  * \brief Run a ctest script
@@ -25,12 +28,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestUpdateCommand* ni = new cmCTestUpdateCommand;
+    auto ni = cm::make_unique<cmCTestUpdateCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 5cfc4a7..d80b5a5 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestUpdateHandler.h"
 
-#include "cmAlgorithms.h"
 #include "cmCLocaleEnvironmentScope.h"
 #include "cmCTest.h"
 #include "cmCTestBZR.h"
@@ -18,9 +17,10 @@
 #include "cmXMLWriter.h"
 
 #include <chrono>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 
+#include "cm_memory.hxx"
+
 static const char* cmCTestUpdateHandlerUpdateStrings[] = {
   "Unknown", "CVS", "SVN", "BZR", "GIT", "HG", "P4"
 };
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index 0d3b06e..2bb072f 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -6,12 +6,15 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
 
 #include <set>
 #include <string>
+#include <utility>
+
+#include "cm_memory.hxx"
 
 class cmCTestGenericHandler;
-class cmCommand;
 
 /** \class cmCTestUpload
  * \brief Run a ctest script
@@ -25,12 +28,12 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmCTestUploadCommand* ni = new cmCTestUploadCommand;
+    auto ni = cm::make_unique<cmCTestUploadCommand>();
     ni->CTest = this->CTest;
     ni->CTestScriptHandler = this->CTestScriptHandler;
-    return ni;
+    return std::unique_ptr<cmCommand>(std::move(ni));
   }
 
   /**
diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx
index 63d6a15..b74decb 100644
--- a/Source/CTest/cmParseBlanketJSCoverage.cxx
+++ b/Source/CTest/cmParseBlanketJSCoverage.cxx
@@ -110,7 +110,8 @@
 {
 }
 
-bool cmParseBlanketJSCoverage::LoadCoverageData(std::vector<std::string> files)
+bool cmParseBlanketJSCoverage::LoadCoverageData(
+  std::vector<std::string> const& files)
 {
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      "Found " << files.size() << " Files" << std::endl,
diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h
index 696121f..cd1b225 100644
--- a/Source/CTest/cmParseBlanketJSCoverage.h
+++ b/Source/CTest/cmParseBlanketJSCoverage.h
@@ -29,7 +29,7 @@
 public:
   cmParseBlanketJSCoverage(cmCTestCoverageHandlerContainer& cont,
                            cmCTest* ctest);
-  bool LoadCoverageData(std::vector<std::string> files);
+  bool LoadCoverageData(std::vector<std::string> const& files);
   //  Read the JSON output
   bool ReadJSONFile(std::string const& file);
 
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 0722753..881bf2d 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -1,8 +1,8 @@
 #include "cmParseGTMCoverage.h"
 
-#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/Directory.hxx"
diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx
index b78142a..5f1e712 100644
--- a/Source/CTest/cmParseJacocoCoverage.cxx
+++ b/Source/CTest/cmParseJacocoCoverage.cxx
@@ -2,6 +2,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 
@@ -118,7 +119,7 @@
     // Check if any of the locations found match our package.
     for (std::string const& f : files) {
       std::string dir = cmsys::SystemTools::GetParentDirectory(f);
-      if (cmsys::SystemTools::StringEndsWith(dir, this->PackageName.c_str())) {
+      if (cmHasSuffix(dir, this->PackageName)) {
         cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                            "Found package directory for " << fileName << ": "
                                                           << dir << std::endl,
diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx
index b965b32..ae7fb42 100644
--- a/Source/LexerParser/cmCommandArgumentParser.cxx
+++ b/Source/LexerParser/cmCommandArgumentParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
    define necessary library symbols; they are noted "INFRINGES ON
    USER NAME SPACE" below.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 /* Identify Bison output.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
 #define yynerrs         cmCommandArgument_yynerrs
 
 
-/* Copy the first part of user declarations.  */
-#line 1 "cmCommandArgumentParser.y" /* yacc.c:339  */
+/* First part of user prologue.  */
+#line 1 "cmCommandArgumentParser.y" /* yacc.c:337  */
 
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
@@ -130,13 +134,16 @@
 # pragma GCC diagnostic ignored "-Wconversion"
 #endif
 
-#line 134 "cmCommandArgumentParser.cxx" /* yacc.c:339  */
-
+#line 138 "cmCommandArgumentParser.cxx" /* yacc.c:337  */
 # ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
+#  if defined __cplusplus
+#   if 201103L <= __cplusplus
+#    define YY_NULLPTR nullptr
+#   else
+#    define YY_NULLPTR 0
+#   endif
 #  else
-#   define YY_NULLPTR 0
+#   define YY_NULLPTR ((void*)0)
 #  endif
 # endif
 
@@ -201,9 +208,7 @@
 
 #endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED  */
 
-/* Copy the second part of user declarations.  */
 
-#line 207 "cmCommandArgumentParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -224,13 +229,13 @@
 #ifdef YYTYPE_UINT16
 typedef YYTYPE_UINT16 yytype_uint16;
 #else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
 #endif
 
 #ifdef YYTYPE_INT16
 typedef YYTYPE_INT16 yytype_int16;
 #else
-typedef short int yytype_int16;
+typedef short yytype_int16;
 #endif
 
 #ifndef YYSIZE_T
@@ -242,7 +247,7 @@
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
-#  define YYSIZE_T unsigned int
+#  define YYSIZE_T unsigned
 # endif
 #endif
 
@@ -278,15 +283,6 @@
 # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
 #endif
 
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
-# else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
 # define YYUSE(E) ((void) (E))
@@ -294,7 +290,7 @@
 # define YYUSE(E) /* empty */
 #endif
 
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
 /* Suppress an incorrect diagnostic about yylval being uninitialized.  */
 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
     _Pragma ("GCC diagnostic push") \
@@ -456,16 +452,16 @@
 /* YYNSTATES -- Number of states.  */
 #define YYNSTATES  33
 
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
 #define YYMAXUTOK   269
 
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, with out-of-bounds checking.  */
 #define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+  ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
+   as returned by yylex.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -513,7 +509,7 @@
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "cal_ENVCURLY", "cal_NCURLY",
-  "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", R"("\\")",
+  "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"",
   "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start",
   "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable",
   "EnvVarName", "MultipleIds", "ID", YY_NULLPTR
@@ -633,22 +629,22 @@
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
+#define YYBACKUP(Token, Value)                                    \
+  do                                                              \
+    if (yychar == YYEMPTY)                                        \
+      {                                                           \
+        yychar = (Token);                                         \
+        yylval = (Value);                                         \
+        YYPOPSTACK (yylen);                                       \
+        yystate = *yyssp;                                         \
+        goto yybackup;                                            \
+      }                                                           \
+    else                                                          \
+      {                                                           \
+        yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+        YYERROR;                                                  \
+      }                                                           \
+  while (0)
 
 /* Error token number */
 #define YYTERROR        1
@@ -688,38 +684,38 @@
 } while (0)
 
 
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO.  |
+`-----------------------------------*/
 
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
+  FILE *yyoutput = yyo;
+  YYUSE (yyoutput);
   YYUSE (yyscanner);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+    YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
 # endif
   YYUSE (yytype);
 }
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO.  |
+`---------------------------*/
 
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  YYFPRINTF (yyoutput, "%s %s (",
+  YYFPRINTF (yyo, "%s %s (",
              yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
-  YYFPRINTF (yyoutput, ")");
+  yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyo, ")");
 }
 
 /*------------------------------------------------------------------.
@@ -753,7 +749,7 @@
 static void
 yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
 {
-  unsigned long int yylno = yyrline[yyrule];
+  unsigned long yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -764,7 +760,7 @@
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr,
                        yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       &yyvsp[(yyi + 1) - (yynrhs)]
                                               , yyscanner);
       YYFPRINTF (stderr, "\n");
     }
@@ -868,7 +864,10 @@
           case '\\':
             if (*++yyp != '\\')
               goto do_not_strip_quotes;
-            /* Fall through.  */
+            else
+              goto append;
+
+          append:
           default:
             if (yyres)
               yyres[yyn] = *yyp;
@@ -886,7 +885,7 @@
   if (! yyres)
     return yystrlen (yystr);
 
-  return yystpcpy (yyres, yystr) - yyres;
+  return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
 }
 # endif
 
@@ -964,10 +963,10 @@
                 yyarg[yycount++] = yytname[yyx];
                 {
                   YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                  if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+                    yysize = yysize1;
+                  else
                     return 2;
-                  yysize = yysize1;
                 }
               }
         }
@@ -979,6 +978,7 @@
       case N:                               \
         yyformat = S;                       \
       break
+    default: /* Avoid compiler warnings. */
       YYCASE_(0, YY_("syntax error"));
       YYCASE_(1, YY_("syntax error, unexpected %s"));
       YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -990,9 +990,10 @@
 
   {
     YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+      yysize = yysize1;
+    else
       return 2;
-    yysize = yysize1;
   }
 
   if (*yymsg_alloc < yysize)
@@ -1123,23 +1124,31 @@
   yychar = YYEMPTY; /* Cause a token to be read.  */
   goto yysetstate;
 
+
 /*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
+| yynewstate -- push a new state, which is found in yystate.  |
 `------------------------------------------------------------*/
- yynewstate:
+yynewstate:
   /* In all cases, when you get here, the value and location stacks
      have just been pushed.  So pushing a state here evens the stacks.  */
   yyssp++;
 
- yysetstate:
-  *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate.  |
+`--------------------------------------------------------------------*/
+yysetstate:
+  *yyssp = (yytype_int16) yystate;
 
   if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+    goto yyexhaustedlab;
+#else
     {
       /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
+      YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
 
-#ifdef yyoverflow
+# if defined yyoverflow
       {
         /* Give user a chance to reallocate the stack.  Use copies of
            these so that the &'s don't force the real ones into
@@ -1155,14 +1164,10 @@
                     &yyss1, yysize * sizeof (*yyssp),
                     &yyvs1, yysize * sizeof (*yyvsp),
                     &yystacksize);
-
         yyss = yyss1;
         yyvs = yyvs1;
       }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
         goto yyexhaustedlab;
@@ -1178,22 +1183,22 @@
           goto yyexhaustedlab;
         YYSTACK_RELOCATE (yyss_alloc, yyss);
         YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
         if (yyss1 != yyssa)
           YYSTACK_FREE (yyss1);
       }
 # endif
-#endif /* no yyoverflow */
 
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
+                  (unsigned long) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
         YYABORT;
     }
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
@@ -1202,11 +1207,11 @@
 
   goto yybackup;
 
+
 /*-----------.
 | yybackup.  |
 `-----------*/
 yybackup:
-
   /* Do appropriate processing given the current state.  Read a
      lookahead token if we need one and don't already have one.  */
 
@@ -1279,7 +1284,7 @@
 
 
 /*-----------------------------.
-| yyreduce -- Do a reduction.  |
+| yyreduce -- do a reduction.  |
 `-----------------------------*/
 yyreduce:
   /* yyn is the number of a rule to reduce with.  */
@@ -1300,192 +1305,192 @@
   switch (yyn)
     {
         case 2:
-#line 99 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 99 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = 0;
     yyGetParser->SetResult((yyvsp[0].str));
   }
-#line 1309 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 3:
-#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 105 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1317 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 4:
-#line 108 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 108 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
   }
-#line 1325 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 5:
-#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 113 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = 0;
   }
-#line 1333 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 6:
-#line 116 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 116 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
   }
-#line 1341 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 7:
-#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 121 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1349 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 8:
-#line 124 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 124 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1357 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 9:
-#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 129 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1365 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 10:
-#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 132 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1373 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 11:
-#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 135 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1381 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 12:
-#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 138 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1389 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 13:
-#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 141 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1397 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 14:
-#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 144 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1405 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 15:
-#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 149 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
   }
-#line 1413 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 16:
-#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 152 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
   }
-#line 1421 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 17:
-#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 155 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
   }
-#line 1429 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 18:
-#line 158 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 158 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
   }
-#line 1437 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 19:
-#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 163 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1445 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 20:
-#line 166 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 166 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[-1].str);
   }
-#line 1453 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 21:
-#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 171 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = 0;
   }
-#line 1461 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 22:
-#line 174 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 174 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
   }
-#line 1469 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 23:
-#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 179 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1477 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
   case 24:
-#line 182 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+#line 182 "cmCommandArgumentParser.y" /* yacc.c:1652  */
     {
     (yyval.str) = (yyvsp[0].str);
   }
-#line 1485 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1490 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
     break;
 
 
-#line 1489 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+#line 1494 "cmCommandArgumentParser.cxx" /* yacc.c:1652  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1510,14 +1515,13 @@
   /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
+  {
+    const int yylhs = yyr1[yyn] - YYNTOKENS;
+    const int yyi = yypgoto[yylhs] + *yyssp;
+    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+               ? yytable[yyi]
+               : yydefgoto[yylhs]);
+  }
 
   goto yynewstate;
 
@@ -1601,12 +1605,10 @@
 | yyerrorlab -- error raised explicitly by YYERROR.  |
 `---------------------------------------------------*/
 yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
+  /* Pacify compilers when the user code never invokes YYERROR and the
+     label yyerrorlab therefore never appears in user code.  */
+  if (0)
+    YYERROR;
 
   /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
@@ -1669,6 +1671,7 @@
   yyresult = 0;
   goto yyreturn;
 
+
 /*-----------------------------------.
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
@@ -1676,6 +1679,7 @@
   yyresult = 1;
   goto yyreturn;
 
+
 #if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
@@ -1686,6 +1690,10 @@
   /* Fall through.  */
 #endif
 
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result.  |
+`-----------------------------------------------------*/
 yyreturn:
   if (yychar != YYEMPTY)
     {
@@ -1715,7 +1723,7 @@
 #endif
   return yyresult;
 }
-#line 187 "cmCommandArgumentParser.y" /* yacc.c:1906  */
+#line 187 "cmCommandArgumentParser.y" /* yacc.c:1918  */
 
 /* End of grammar */
 
diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h
index 3172182..56c9794 100644
--- a/Source/LexerParser/cmCommandArgumentParserTokens.h
+++ b/Source/LexerParser/cmCommandArgumentParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 #ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
 # define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
 /* Debug traces.  */
diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx
index e83afa9..6c1fb2c 100644
--- a/Source/LexerParser/cmDependsJavaParser.cxx
+++ b/Source/LexerParser/cmDependsJavaParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
    define necessary library symbols; they are noted "INFRINGES ON
    USER NAME SPACE" below.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 /* Identify Bison output.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
 #define yynerrs         cmDependsJava_yynerrs
 
 
-/* Copy the first part of user declarations.  */
-#line 1 "cmDependsJavaParser.y" /* yacc.c:339  */
+/* First part of user prologue.  */
+#line 1 "cmDependsJavaParser.y" /* yacc.c:337  */
 
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
@@ -119,13 +123,16 @@
 # pragma GCC diagnostic ignored "-Wconversion"
 #endif
 
-#line 123 "cmDependsJavaParser.cxx" /* yacc.c:339  */
-
+#line 127 "cmDependsJavaParser.cxx" /* yacc.c:337  */
 # ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
+#  if defined __cplusplus
+#   if 201103L <= __cplusplus
+#    define YY_NULLPTR nullptr
+#   else
+#    define YY_NULLPTR 0
+#   endif
 #  else
-#   define YY_NULLPTR 0
+#   define YY_NULLPTR ((void*)0)
 #  endif
 # endif
 
@@ -372,9 +379,7 @@
 
 #endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED  */
 
-/* Copy the second part of user declarations.  */
 
-#line 378 "cmDependsJavaParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -395,13 +400,13 @@
 #ifdef YYTYPE_UINT16
 typedef YYTYPE_UINT16 yytype_uint16;
 #else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
 #endif
 
 #ifdef YYTYPE_INT16
 typedef YYTYPE_INT16 yytype_int16;
 #else
-typedef short int yytype_int16;
+typedef short yytype_int16;
 #endif
 
 #ifndef YYSIZE_T
@@ -413,7 +418,7 @@
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
-#  define YYSIZE_T unsigned int
+#  define YYSIZE_T unsigned
 # endif
 #endif
 
@@ -449,15 +454,6 @@
 # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
 #endif
 
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
-# else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
 # define YYUSE(E) ((void) (E))
@@ -465,7 +461,7 @@
 # define YYUSE(E) /* empty */
 #endif
 
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
 /* Suppress an incorrect diagnostic about yylval being uninitialized.  */
 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
     _Pragma ("GCC diagnostic push") \
@@ -627,16 +623,16 @@
 /* YYNSTATES -- Number of states.  */
 #define YYNSTATES  575
 
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
 #define YYMAXUTOK   360
 
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, with out-of-bounds checking.  */
 #define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+  ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
+   as returned by yylex.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -1618,22 +1614,22 @@
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
+#define YYBACKUP(Token, Value)                                    \
+  do                                                              \
+    if (yychar == YYEMPTY)                                        \
+      {                                                           \
+        yychar = (Token);                                         \
+        yylval = (Value);                                         \
+        YYPOPSTACK (yylen);                                       \
+        yystate = *yyssp;                                         \
+        goto yybackup;                                            \
+      }                                                           \
+    else                                                          \
+      {                                                           \
+        yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+        YYERROR;                                                  \
+      }                                                           \
+  while (0)
 
 /* Error token number */
 #define YYTERROR        1
@@ -1673,38 +1669,38 @@
 } while (0)
 
 
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO.  |
+`-----------------------------------*/
 
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
+  FILE *yyoutput = yyo;
+  YYUSE (yyoutput);
   YYUSE (yyscanner);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+    YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
 # endif
   YYUSE (yytype);
 }
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO.  |
+`---------------------------*/
 
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  YYFPRINTF (yyoutput, "%s %s (",
+  YYFPRINTF (yyo, "%s %s (",
              yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
-  YYFPRINTF (yyoutput, ")");
+  yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyo, ")");
 }
 
 /*------------------------------------------------------------------.
@@ -1738,7 +1734,7 @@
 static void
 yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
 {
-  unsigned long int yylno = yyrline[yyrule];
+  unsigned long yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -1749,7 +1745,7 @@
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr,
                        yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       &yyvsp[(yyi + 1) - (yynrhs)]
                                               , yyscanner);
       YYFPRINTF (stderr, "\n");
     }
@@ -1853,7 +1849,10 @@
           case '\\':
             if (*++yyp != '\\')
               goto do_not_strip_quotes;
-            /* Fall through.  */
+            else
+              goto append;
+
+          append:
           default:
             if (yyres)
               yyres[yyn] = *yyp;
@@ -1871,7 +1870,7 @@
   if (! yyres)
     return yystrlen (yystr);
 
-  return yystpcpy (yyres, yystr) - yyres;
+  return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
 }
 # endif
 
@@ -1949,10 +1948,10 @@
                 yyarg[yycount++] = yytname[yyx];
                 {
                   YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                  if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+                    yysize = yysize1;
+                  else
                     return 2;
-                  yysize = yysize1;
                 }
               }
         }
@@ -1964,6 +1963,7 @@
       case N:                               \
         yyformat = S;                       \
       break
+    default: /* Avoid compiler warnings. */
       YYCASE_(0, YY_("syntax error"));
       YYCASE_(1, YY_("syntax error, unexpected %s"));
       YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -1975,9 +1975,10 @@
 
   {
     YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+      yysize = yysize1;
+    else
       return 2;
-    yysize = yysize1;
   }
 
   if (*yymsg_alloc < yysize)
@@ -2108,23 +2109,31 @@
   yychar = YYEMPTY; /* Cause a token to be read.  */
   goto yysetstate;
 
+
 /*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
+| yynewstate -- push a new state, which is found in yystate.  |
 `------------------------------------------------------------*/
- yynewstate:
+yynewstate:
   /* In all cases, when you get here, the value and location stacks
      have just been pushed.  So pushing a state here evens the stacks.  */
   yyssp++;
 
- yysetstate:
-  *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate.  |
+`--------------------------------------------------------------------*/
+yysetstate:
+  *yyssp = (yytype_int16) yystate;
 
   if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+    goto yyexhaustedlab;
+#else
     {
       /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
+      YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
 
-#ifdef yyoverflow
+# if defined yyoverflow
       {
         /* Give user a chance to reallocate the stack.  Use copies of
            these so that the &'s don't force the real ones into
@@ -2140,14 +2149,10 @@
                     &yyss1, yysize * sizeof (*yyssp),
                     &yyvs1, yysize * sizeof (*yyvsp),
                     &yystacksize);
-
         yyss = yyss1;
         yyvs = yyvs1;
       }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
         goto yyexhaustedlab;
@@ -2163,22 +2168,22 @@
           goto yyexhaustedlab;
         YYSTACK_RELOCATE (yyss_alloc, yyss);
         YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
         if (yyss1 != yyssa)
           YYSTACK_FREE (yyss1);
       }
 # endif
-#endif /* no yyoverflow */
 
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
+                  (unsigned long) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
         YYABORT;
     }
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
@@ -2187,11 +2192,11 @@
 
   goto yybackup;
 
+
 /*-----------.
 | yybackup.  |
 `-----------*/
 yybackup:
-
   /* Do appropriate processing given the current state.  Read a
      lookahead token if we need one and don't already have one.  */
 
@@ -2264,7 +2269,7 @@
 
 
 /*-----------------------------.
-| yyreduce -- Do a reduction.  |
+| yyreduce -- do a reduction.  |
 `-----------------------------*/
 yyreduce:
   /* yyn is the number of a rule to reduce with.  */
@@ -2285,214 +2290,214 @@
   switch (yyn)
     {
         case 2:
-#line 183 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 183 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2296 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2301 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 3:
-#line 192 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 192 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2307 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2312 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 4:
-#line 200 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 200 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2318 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2323 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 5:
-#line 208 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 208 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2329 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2334 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 6:
-#line 216 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 216 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2340 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2345 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 7:
-#line 224 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 224 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2351 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2356 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 8:
-#line 232 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 232 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2362 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2367 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 9:
-#line 241 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 241 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2373 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2378 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 10:
-#line 249 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 249 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2384 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2389 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 11:
-#line 258 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 258 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2395 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2400 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 12:
-#line 266 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 266 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2406 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 13:
-#line 275 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 275 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2414 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 14:
-#line 280 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 280 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2422 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 15:
-#line 285 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 285 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2430 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 16:
-#line 290 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 290 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2438 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 17:
-#line 295 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 295 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2446 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 18:
-#line 300 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 300 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2454 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 19:
-#line 305 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 305 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2462 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 20:
-#line 310 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 310 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
 }
-#line 2470 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2475 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 21:
-#line 316 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 316 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2481 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2486 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 22:
-#line 324 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 324 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2492 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2497 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 23:
-#line 333 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 333 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpStoreClass((yyvsp[0].str));
@@ -2500,44 +2505,44 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2504 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2509 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 24:
-#line 343 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 343 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2515 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2520 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 25:
-#line 352 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 352 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2526 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2531 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 26:
-#line 361 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 361 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2537 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2542 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 27:
-#line 369 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 369 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpStoreClass((yyvsp[-1].str));
@@ -2545,56 +2550,56 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2549 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2554 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 28:
-#line 379 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 379 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = (yyvsp[0].str);
 }
-#line 2558 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2563 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 29:
-#line 385 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 385 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = (yyvsp[0].str);
 }
-#line 2567 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2572 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 30:
-#line 392 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 392 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = (yyvsp[0].str);
 }
-#line 2576 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2581 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 31:
-#line 399 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 399 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = (yyvsp[0].str);
 }
-#line 2585 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2590 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 32:
-#line 405 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 405 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   (yyval.str) = (yyvsp[0].str);
 }
-#line 2594 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2599 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 33:
-#line 412 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 412 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->AddClassFound((yyvsp[-2].str));
@@ -2602,11 +2607,11 @@
   yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
   (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine());
 }
-#line 2606 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2611 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 34:
-#line 421 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 421 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpStoreClass((yyvsp[-2].str));
@@ -2615,11 +2620,11 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2619 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2624 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 35:
-#line 431 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 431 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpStoreClass((yyvsp[-2].str));
@@ -2628,118 +2633,118 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2632 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2637 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 36:
-#line 441 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 441 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2643 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2648 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 37:
-#line 450 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 450 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2654 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2659 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 38:
-#line 458 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 458 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2665 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2670 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 39:
-#line 467 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 467 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2676 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2681 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 40:
-#line 475 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 475 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2686 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2691 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 41:
-#line 482 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 482 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2697 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2702 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 42:
-#line 490 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 490 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2707 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2712 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 43:
-#line 497 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 497 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2718 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2723 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 44:
-#line 505 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 505 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2728 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2733 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 45:
-#line 512 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 512 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2739 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2744 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 46:
-#line 521 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 521 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->SetCurrentPackage((yyvsp[-1].str));
@@ -2749,33 +2754,33 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2753 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2758 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 47:
-#line 533 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 533 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2764 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2769 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 48:
-#line 541 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 541 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2775 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2780 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 49:
-#line 550 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 550 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->AddPackagesImport((yyvsp[-1].str));
@@ -2785,11 +2790,11 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2789 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2794 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 50:
-#line 562 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 562 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   std::string str = (yyvsp[-3].str);
@@ -2800,77 +2805,77 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2804 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2809 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 51:
-#line 575 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 575 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2815 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2820 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 52:
-#line 583 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 583 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2826 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2831 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 53:
-#line 591 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 591 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2837 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2842 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 54:
-#line 600 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 600 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2848 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2853 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 55:
-#line 608 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 608 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2859 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2864 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 67:
-#line 623 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 623 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   yyGetParser->StartClass((yyvsp[0].str));
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
 }
-#line 2870 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2875 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 68:
-#line 633 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 633 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -2878,11 +2883,11 @@
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
-#line 2882 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2887 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 69:
-#line 642 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 642 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(2);
@@ -2890,11 +2895,11 @@
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
-#line 2894 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2899 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 70:
-#line 651 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 651 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -2902,11 +2907,11 @@
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
-#line 2906 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2911 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 71:
-#line 660 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 660 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -2914,226 +2919,226 @@
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
-#line 2918 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2923 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 72:
-#line 669 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 669 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2928 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2933 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 73:
-#line 676 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 676 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2939 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2944 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 74:
-#line 685 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 685 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2950 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2955 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 75:
-#line 694 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 694 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2961 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2966 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 76:
-#line 703 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 703 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2972 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2977 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 77:
-#line 711 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 711 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2983 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2988 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 78:
-#line 720 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 720 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 2994 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 2999 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 79:
-#line 728 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 728 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3004 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3009 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 80:
-#line 735 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 735 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3015 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3020 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 81:
-#line 744 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 744 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3026 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3031 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 82:
-#line 752 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 752 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3037 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3042 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 83:
-#line 760 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 760 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3048 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3053 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 84:
-#line 768 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 768 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3059 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3064 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 85:
-#line 777 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 777 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3070 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3075 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 86:
-#line 785 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 785 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3081 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 87:
-#line 794 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 794 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
 }
-#line 3089 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3094 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 88:
-#line 800 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 800 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3100 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3105 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 89:
-#line 808 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 808 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3111 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3116 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 90:
-#line 817 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 817 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3122 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3127 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 91:
-#line 825 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 825 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3133 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3138 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 92:
-#line 834 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 834 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -3141,77 +3146,77 @@
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3145 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3150 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 93:
-#line 843 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 843 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3156 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3161 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 94:
-#line 852 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 852 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3167 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3172 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 95:
-#line 860 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 860 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3178 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3183 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 96:
-#line 869 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 869 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3189 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3194 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 97:
-#line 877 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 877 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3200 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3205 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 98:
-#line 885 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 885 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3211 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3216 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 99:
-#line 894 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 894 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -3219,11 +3224,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3223 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3228 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 100:
-#line 903 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 903 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -3231,22 +3236,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3235 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3240 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 101:
-#line 912 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 912 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3246 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3251 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 102:
-#line 920 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 920 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3254,11 +3259,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3258 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3263 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 103:
-#line 930 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 930 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -3267,40 +3272,40 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3271 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3276 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 104:
-#line 940 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 940 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
 
 }
-#line 3280 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3285 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 105:
-#line 946 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 946 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3291 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3296 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 107:
-#line 957 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 957 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
 
 }
-#line 3300 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3305 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 108:
-#line 963 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 963 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -3308,11 +3313,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3312 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3317 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 109:
-#line 973 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 973 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -3320,11 +3325,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3324 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3329 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 110:
-#line 983 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 983 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3332,20 +3337,20 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3336 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3341 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 111:
-#line 993 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 993 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
 
 }
-#line 3345 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3350 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 112:
-#line 999 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 999 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -3353,11 +3358,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3357 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3362 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 113:
-#line 1009 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1009 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3365,11 +3370,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3369 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3374 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 114:
-#line 1019 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1019 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3377,11 +3382,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3381 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3386 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 115:
-#line 1029 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1029 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -3389,11 +3394,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3393 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3398 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 116:
-#line 1038 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1038 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -3401,11 +3406,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3405 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3410 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 117:
-#line 1048 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1048 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -3414,11 +3419,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3418 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3423 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 118:
-#line 1059 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1059 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -3426,22 +3431,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3430 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3435 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 119:
-#line 1068 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1068 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3441 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3446 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 120:
-#line 1076 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1076 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3449,11 +3454,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3453 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3458 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 121:
-#line 1086 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1086 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -3461,11 +3466,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3465 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3470 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 122:
-#line 1095 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1095 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -3473,22 +3478,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3477 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3482 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 123:
-#line 1105 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1105 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   yyGetParser->StartClass((yyvsp[0].str));
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
 }
-#line 3488 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3493 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 124:
-#line 1114 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1114 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3496,21 +3501,21 @@
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
-#line 3500 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3505 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 125:
-#line 1123 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1123 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
-#line 3510 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3515 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 126:
-#line 1130 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1130 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3518,11 +3523,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3522 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3527 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 127:
-#line 1140 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1140 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3530,11 +3535,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3534 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3539 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 128:
-#line 1149 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1149 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -3542,11 +3547,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3546 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3551 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 129:
-#line 1159 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1159 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -3554,33 +3559,33 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3558 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3563 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 130:
-#line 1168 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1168 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3569 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3574 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 131:
-#line 1176 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1176 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3580 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3585 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 132:
-#line 1185 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1185 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3588,11 +3593,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3592 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3597 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 133:
-#line 1194 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1194 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3600,11 +3605,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3604 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3609 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 134:
-#line 1203 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1203 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3612,22 +3617,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3616 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3621 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 135:
-#line 1212 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1212 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3627 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3632 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 136:
-#line 1220 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1220 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3635,22 +3640,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3639 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3644 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 137:
-#line 1229 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1229 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3650 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3655 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 138:
-#line 1238 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1238 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3658,11 +3663,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3662 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3667 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 139:
-#line 1248 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1248 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3670,11 +3675,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3674 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3679 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 140:
-#line 1258 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1258 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3682,11 +3687,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3686 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3691 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 141:
-#line 1267 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1267 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3694,11 +3699,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3698 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3703 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 142:
-#line 1277 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1277 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -3706,22 +3711,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3710 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3715 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 143:
-#line 1286 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1286 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3721 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3726 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 144:
-#line 1294 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1294 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3729,11 +3734,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3733 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3738 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 145:
-#line 1303 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1303 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -3741,11 +3746,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3745 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3750 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 146:
-#line 1313 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1313 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3753,11 +3758,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3757 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3762 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 147:
-#line 1322 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1322 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -3765,33 +3770,33 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3769 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3774 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 148:
-#line 1332 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1332 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3780 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3785 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 149:
-#line 1340 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1340 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3791 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3796 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 150:
-#line 1348 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1348 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3799,11 +3804,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3803 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3808 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 151:
-#line 1358 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1358 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3811,11 +3816,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3815 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3820 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 152:
-#line 1367 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1367 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(2);
@@ -3823,11 +3828,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3827 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3832 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 153:
-#line 1377 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1377 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3835,11 +3840,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3839 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3844 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 154:
-#line 1386 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1386 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3847,11 +3852,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3851 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3856 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 155:
-#line 1395 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1395 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3859,11 +3864,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3863 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3868 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 156:
-#line 1405 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1405 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(2);
@@ -3871,11 +3876,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3875 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3880 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 157:
-#line 1415 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1415 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(3);
@@ -3883,11 +3888,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3887 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3892 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 158:
-#line 1424 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1424 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(2);
@@ -3895,11 +3900,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3899 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3904 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 159:
-#line 1434 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1434 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3907,11 +3912,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3911 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3916 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 160:
-#line 1443 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1443 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3919,11 +3924,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3923 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3928 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 161:
-#line 1452 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1452 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3931,11 +3936,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3935 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3940 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 162:
-#line 1461 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1461 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3943,11 +3948,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3947 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3952 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 163:
-#line 1470 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1470 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3955,11 +3960,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3959 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3964 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 164:
-#line 1479 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1479 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3967,11 +3972,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3971 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3976 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 165:
-#line 1489 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1489 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3979,11 +3984,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3983 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 3988 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 166:
-#line 1498 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1498 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -3991,11 +3996,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 3995 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4000 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 167:
-#line 1507 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1507 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4003,11 +4008,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4007 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4012 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 168:
-#line 1516 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1516 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4015,11 +4020,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4019 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4024 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 169:
-#line 1525 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1525 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4027,11 +4032,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4031 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4036 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 170:
-#line 1535 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1535 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4039,11 +4044,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4043 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4048 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 171:
-#line 1544 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1544 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4051,11 +4056,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4055 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4060 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 172:
-#line 1553 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1553 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4063,11 +4068,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4067 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4072 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 173:
-#line 1562 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1562 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4075,11 +4080,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4079 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4084 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 174:
-#line 1571 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1571 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4087,11 +4092,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4091 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4096 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 175:
-#line 1580 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1580 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4099,11 +4104,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4103 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4108 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 176:
-#line 1589 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1589 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4111,11 +4116,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4115 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4120 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 177:
-#line 1598 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1598 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4123,11 +4128,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4127 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4132 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 178:
-#line 1607 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1607 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4135,11 +4140,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4139 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4144 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 179:
-#line 1616 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1616 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4147,11 +4152,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4151 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4156 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 180:
-#line 1625 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1625 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4159,11 +4164,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4163 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4168 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 181:
-#line 1634 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1634 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4171,11 +4176,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4175 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4180 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 182:
-#line 1644 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1644 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4183,11 +4188,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4187 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4192 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 183:
-#line 1654 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1654 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
@@ -4196,11 +4201,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4200 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4205 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 184:
-#line 1665 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1665 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4208,11 +4213,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4212 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4217 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 185:
-#line 1675 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1675 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -4220,11 +4225,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4224 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4229 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 186:
-#line 1685 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1685 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4232,11 +4237,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4236 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4241 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 187:
-#line 1694 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1694 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4244,11 +4249,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4248 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4253 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 188:
-#line 1703 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1703 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4256,11 +4261,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4260 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4265 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 189:
-#line 1712 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1712 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4268,11 +4273,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4272 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4277 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 190:
-#line 1721 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1721 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4280,11 +4285,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4284 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4289 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 191:
-#line 1730 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1730 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4292,11 +4297,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4296 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4301 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 192:
-#line 1739 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1739 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4304,11 +4309,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4308 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4313 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 193:
-#line 1749 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1749 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -4316,11 +4321,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4320 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4325 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 194:
-#line 1759 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1759 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(7);
   jpCheckEmpty(7);
@@ -4328,11 +4333,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4332 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4337 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 195:
-#line 1769 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1769 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(7);
   jpCheckEmpty(7);
@@ -4340,40 +4345,40 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4344 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4349 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 196:
-#line 1779 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1779 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
 
 }
-#line 4353 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4358 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 197:
-#line 1786 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1786 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
 
 }
-#line 4362 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4367 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 198:
-#line 1792 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1792 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4373 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4378 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 199:
-#line 1800 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1800 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4381,22 +4386,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4385 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4390 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 200:
-#line 1809 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1809 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4396 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4401 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 201:
-#line 1817 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1817 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -4404,11 +4409,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4408 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4413 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 202:
-#line 1827 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1827 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -4416,11 +4421,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4420 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4425 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 203:
-#line 1837 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1837 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4428,11 +4433,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4432 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4437 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 204:
-#line 1846 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1846 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -4440,11 +4445,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4444 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4449 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 205:
-#line 1856 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1856 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4452,11 +4457,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4456 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4461 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 206:
-#line 1865 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1865 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -4464,58 +4469,58 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4468 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4473 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 207:
-#line 1875 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1875 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
 
 }
-#line 4477 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4482 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 208:
-#line 1882 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1882 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
 
 }
-#line 4486 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4491 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 209:
-#line 1889 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1889 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(7);
 
 }
-#line 4495 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4500 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 210:
-#line 1897 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1897 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(9);
 
 }
-#line 4504 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4509 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 211:
-#line 1903 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1903 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4515 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4520 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 212:
-#line 1911 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1911 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4523,22 +4528,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4527 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4532 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 213:
-#line 1920 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1920 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4538 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4543 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 214:
-#line 1928 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1928 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4546,33 +4551,33 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4550 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4555 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 215:
-#line 1939 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1939 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(9);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4561 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4566 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 216:
-#line 1947 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1947 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4572 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4577 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 217:
-#line 1955 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1955 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4580,11 +4585,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4584 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4589 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 218:
-#line 1965 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1965 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4592,11 +4597,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4596 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4601 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 219:
-#line 1974 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1974 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4604,11 +4609,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4608 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4613 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 220:
-#line 1984 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1984 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4616,11 +4621,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4620 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4625 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 221:
-#line 1994 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 1994 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4628,11 +4633,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4632 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4637 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 222:
-#line 2003 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2003 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4640,11 +4645,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4644 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4649 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 223:
-#line 2013 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2013 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4652,11 +4657,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4656 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4661 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 224:
-#line 2022 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2022 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -4664,11 +4669,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4668 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4673 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 225:
-#line 2032 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2032 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
@@ -4677,31 +4682,31 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4681 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4686 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 226:
-#line 2042 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2042 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4692 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4697 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 227:
-#line 2050 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2050 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
 
 }
-#line 4701 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4706 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 228:
-#line 2057 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2057 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
@@ -4710,11 +4715,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4714 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4719 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 229:
-#line 2068 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2068 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4722,11 +4727,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4726 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4731 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 230:
-#line 2078 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2078 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4734,11 +4739,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4738 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4743 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 231:
-#line 2088 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2088 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -4746,11 +4751,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4750 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4755 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 232:
-#line 2098 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2098 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4758,11 +4763,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4762 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4767 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 233:
-#line 2107 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2107 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -4770,22 +4775,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4774 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4779 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 234:
-#line 2116 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2116 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4785 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4790 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 235:
-#line 2124 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2124 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4793,11 +4798,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4797 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4802 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 236:
-#line 2134 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2134 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4805,11 +4810,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4809 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4814 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 237:
-#line 2143 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2143 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -4817,20 +4822,20 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4821 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4826 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 238:
-#line 2153 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2153 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
 
 }
-#line 4830 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4835 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 239:
-#line 2160 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2160 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -4838,11 +4843,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4842 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4847 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 240:
-#line 2170 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2170 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4850,11 +4855,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4854 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4859 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 241:
-#line 2179 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2179 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4862,11 +4867,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4866 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4871 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 242:
-#line 2189 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2189 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4874,20 +4879,20 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4878 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4883 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 243:
-#line 2198 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2198 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
 
 }
-#line 4887 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4892 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 244:
-#line 2204 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2204 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -4895,11 +4900,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4899 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4904 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 245:
-#line 2213 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2213 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4907,11 +4912,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4911 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4916 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 246:
-#line 2222 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2222 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4919,11 +4924,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4923 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4928 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 247:
-#line 2231 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2231 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4931,11 +4936,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4935 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4940 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 248:
-#line 2240 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2240 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4943,11 +4948,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4947 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4952 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 249:
-#line 2250 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2250 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(6);
   jpCheckEmpty(6);
@@ -4955,22 +4960,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4959 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4964 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 250:
-#line 2259 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2259 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4970 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4975 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 251:
-#line 2267 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2267 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -4978,22 +4983,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4982 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4987 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 252:
-#line 2276 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2276 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 4993 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 4998 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 253:
-#line 2284 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2284 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5001,11 +5006,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5005 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5010 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 254:
-#line 2294 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2294 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5013,11 +5018,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5017 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5022 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 255:
-#line 2303 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2303 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5025,11 +5030,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5029 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5034 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 256:
-#line 2313 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2313 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -5037,11 +5042,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5041 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5046 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 257:
-#line 2322 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2322 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -5049,11 +5054,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5053 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5058 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 258:
-#line 2331 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2331 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -5061,11 +5066,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5065 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5070 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 259:
-#line 2340 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2340 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -5073,22 +5078,22 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5077 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5082 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 260:
-#line 2349 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2349 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(0);
   (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5088 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5093 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 261:
-#line 2357 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2357 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5096,11 +5101,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5100 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5105 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 262:
-#line 2367 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2367 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5108,11 +5113,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5112 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5117 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 263:
-#line 2376 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2376 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5120,11 +5125,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5124 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5129 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 264:
-#line 2386 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2386 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5132,29 +5137,29 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5136 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5141 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 265:
-#line 2396 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2396 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
 
 }
-#line 5145 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5150 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 266:
-#line 2402 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2402 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
 
 }
-#line 5154 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5159 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 267:
-#line 2409 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2409 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5163,11 +5168,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5167 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5172 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 268:
-#line 2419 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2419 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5176,11 +5181,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5180 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5185 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 269:
-#line 2429 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2429 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5189,11 +5194,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5193 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5198 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 270:
-#line 2439 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2439 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5202,11 +5207,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5206 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5211 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 271:
-#line 2450 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2450 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5215,11 +5220,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5219 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5224 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 272:
-#line 2460 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2460 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(6);
   yyGetParser->DeallocateParserType(&((yyvsp[-5].str)));
@@ -5229,11 +5234,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5233 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5238 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 273:
-#line 2471 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2471 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(6);
   yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5242,11 +5247,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5246 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5251 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 274:
-#line 2481 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2481 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(6);
   yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5255,11 +5260,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5259 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5264 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 275:
-#line 2492 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2492 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5268,11 +5273,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5272 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5277 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 276:
-#line 2502 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2502 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -5280,11 +5285,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5284 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5289 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 277:
-#line 2512 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2512 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5292,11 +5297,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5296 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5301 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 278:
-#line 2521 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2521 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5304,11 +5309,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5308 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5313 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 279:
-#line 2530 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2530 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5316,11 +5321,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5320 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5325 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 280:
-#line 2539 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2539 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5328,11 +5333,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5332 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5337 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 281:
-#line 2548 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2548 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5340,11 +5345,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5344 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5349 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 282:
-#line 2558 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2558 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5352,11 +5357,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5356 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5361 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 283:
-#line 2568 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2568 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5364,11 +5369,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5368 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5373 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 284:
-#line 2578 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2578 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5376,11 +5381,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5380 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5385 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 285:
-#line 2587 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2587 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5388,11 +5393,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5392 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5397 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 286:
-#line 2596 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2596 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5400,11 +5405,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5404 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5409 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 287:
-#line 2605 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2605 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5412,11 +5417,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5416 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5421 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 288:
-#line 2614 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2614 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5424,11 +5429,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5428 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5433 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 289:
-#line 2624 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2624 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5436,11 +5441,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5440 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5445 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 290:
-#line 2634 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2634 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5448,11 +5453,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5452 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5457 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 291:
-#line 2644 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2644 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5460,11 +5465,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5464 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5469 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 292:
-#line 2653 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2653 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5472,11 +5477,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5476 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5481 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 293:
-#line 2662 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2662 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
@@ -5484,11 +5489,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5488 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5493 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 294:
-#line 2671 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2671 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5496,11 +5501,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5500 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5505 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 295:
-#line 2681 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2681 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -5508,11 +5513,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5512 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5517 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 296:
-#line 2690 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2690 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
@@ -5520,20 +5525,20 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5524 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5529 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 297:
-#line 2699 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2699 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
 
 }
-#line 5533 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5538 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 298:
-#line 2706 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2706 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5541,11 +5546,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5545 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5550 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 299:
-#line 2715 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2715 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5553,11 +5558,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5557 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5562 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 300:
-#line 2724 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2724 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5565,11 +5570,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5569 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5574 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 301:
-#line 2733 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2733 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5577,11 +5582,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5581 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5586 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 302:
-#line 2743 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2743 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5589,11 +5594,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5593 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5598 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 303:
-#line 2752 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2752 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5601,11 +5606,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5605 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5610 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 304:
-#line 2761 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2761 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5613,11 +5618,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5617 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5622 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 305:
-#line 2771 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2771 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5625,11 +5630,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5629 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5634 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 306:
-#line 2780 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2780 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5637,11 +5642,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5641 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5646 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 307:
-#line 2789 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2789 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5649,11 +5654,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5653 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5658 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 308:
-#line 2798 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2798 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5661,11 +5666,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5665 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5670 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 309:
-#line 2808 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2808 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5673,11 +5678,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5677 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5682 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 310:
-#line 2817 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2817 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5685,11 +5690,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5689 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5694 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 311:
-#line 2826 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2826 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5697,11 +5702,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5701 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5706 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 312:
-#line 2835 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2835 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5709,11 +5714,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5713 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5718 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 313:
-#line 2844 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2844 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5721,11 +5726,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5725 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5730 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 314:
-#line 2853 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2853 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5733,11 +5738,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5737 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5742 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 315:
-#line 2863 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2863 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5745,11 +5750,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5749 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5754 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 316:
-#line 2872 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2872 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5757,11 +5762,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5761 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5766 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 317:
-#line 2881 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2881 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5769,11 +5774,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5773 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5778 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 318:
-#line 2891 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2891 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5781,11 +5786,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5785 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5790 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 319:
-#line 2900 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2900 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5793,11 +5798,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5797 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5802 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 320:
-#line 2910 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2910 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5805,11 +5810,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5809 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5814 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 321:
-#line 2919 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2919 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5817,11 +5822,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5821 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5826 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 322:
-#line 2929 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2929 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5829,11 +5834,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5833 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5838 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 323:
-#line 2938 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2938 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5841,11 +5846,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5845 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5850 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 324:
-#line 2948 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2948 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5853,11 +5858,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5857 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5862 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 325:
-#line 2957 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2957 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5865,11 +5870,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5869 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5874 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 326:
-#line 2967 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2967 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5877,11 +5882,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5881 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5886 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 327:
-#line 2976 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2976 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5889,11 +5894,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5893 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5898 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 328:
-#line 2986 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2986 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5901,11 +5906,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5905 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5910 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 329:
-#line 2995 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 2995 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
@@ -5913,11 +5918,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5917 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5922 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 330:
-#line 3005 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3005 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5925,11 +5930,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5929 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5934 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 331:
-#line 3014 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3014 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5937,11 +5942,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5941 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5946 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 332:
-#line 3024 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3024 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
@@ -5949,11 +5954,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5953 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5958 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 333:
-#line 3034 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3034 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5962,11 +5967,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5966 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5971 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 334:
-#line 3044 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3044 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5974,11 +5979,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5978 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5983 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 335:
-#line 3053 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3053 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5986,11 +5991,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 5990 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 5995 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 336:
-#line 3063 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3063 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -5998,11 +6003,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6002 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6007 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 337:
-#line 3072 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3072 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6010,11 +6015,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6014 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6019 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 338:
-#line 3081 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3081 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6022,11 +6027,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6026 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6031 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 339:
-#line 3090 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3090 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6034,11 +6039,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6038 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6043 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 340:
-#line 3099 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3099 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6046,11 +6051,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6050 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6055 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 341:
-#line 3108 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3108 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6058,11 +6063,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6062 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6067 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 342:
-#line 3117 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3117 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6070,11 +6075,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6074 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6079 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 343:
-#line 3126 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3126 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6082,11 +6087,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6086 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6091 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 344:
-#line 3135 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3135 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6094,11 +6099,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6098 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6103 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 345:
-#line 3144 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3144 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6106,11 +6111,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6110 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6115 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 346:
-#line 3153 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3153 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6118,11 +6123,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6122 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6127 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 347:
-#line 3162 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3162 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6130,11 +6135,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6134 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6139 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 348:
-#line 3172 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3172 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6142,11 +6147,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6146 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6151 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 349:
-#line 3182 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3182 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6154,11 +6159,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6158 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6163 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 350:
-#line 3192 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3192 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
@@ -6166,11 +6171,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6170 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6175 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
   case 351:
-#line 3201 "cmDependsJavaParser.y" /* yacc.c:1646  */
+#line 3201 "cmDependsJavaParser.y" /* yacc.c:1652  */
     {
   jpElementStart(3);
   jpStoreClass((yyvsp[-2].str));
@@ -6179,11 +6184,11 @@
   yyGetParser->SetCurrentCombine("");
 
 }
-#line 6183 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6188 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
     break;
 
 
-#line 6187 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+#line 6192 "cmDependsJavaParser.cxx" /* yacc.c:1652  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -6208,14 +6213,13 @@
   /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
+  {
+    const int yylhs = yyr1[yyn] - YYNTOKENS;
+    const int yyi = yypgoto[yylhs] + *yyssp;
+    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+               ? yytable[yyi]
+               : yydefgoto[yylhs]);
+  }
 
   goto yynewstate;
 
@@ -6299,12 +6303,10 @@
 | yyerrorlab -- error raised explicitly by YYERROR.  |
 `---------------------------------------------------*/
 yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
+  /* Pacify compilers when the user code never invokes YYERROR and the
+     label yyerrorlab therefore never appears in user code.  */
+  if (0)
+    YYERROR;
 
   /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
@@ -6367,6 +6369,7 @@
   yyresult = 0;
   goto yyreturn;
 
+
 /*-----------------------------------.
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
@@ -6374,6 +6377,7 @@
   yyresult = 1;
   goto yyreturn;
 
+
 #if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
@@ -6384,6 +6388,10 @@
   /* Fall through.  */
 #endif
 
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result.  |
+`-----------------------------------------------------*/
 yyreturn:
   if (yychar != YYEMPTY)
     {
@@ -6413,7 +6421,7 @@
 #endif
   return yyresult;
 }
-#line 3210 "cmDependsJavaParser.y" /* yacc.c:1906  */
+#line 3210 "cmDependsJavaParser.y" /* yacc.c:1918  */
 
 /* End of grammar */
 
diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h
index 7f18f1d..6bbc084 100644
--- a/Source/LexerParser/cmDependsJavaParserTokens.h
+++ b/Source/LexerParser/cmDependsJavaParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 #ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
 # define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
 /* Debug traces.  */
diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx
index 73ece2b..8416e72 100644
--- a/Source/LexerParser/cmExprParser.cxx
+++ b/Source/LexerParser/cmExprParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
    define necessary library symbols; they are noted "INFRINGES ON
    USER NAME SPACE" below.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 /* Identify Bison output.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
 #define yynerrs         cmExpr_yynerrs
 
 
-/* Copy the first part of user declarations.  */
-#line 1 "cmExprParser.y" /* yacc.c:339  */
+/* First part of user prologue.  */
+#line 1 "cmExprParser.y" /* yacc.c:337  */
 
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
@@ -112,13 +116,16 @@
 # pragma GCC diagnostic ignored "-Wconversion"
 #endif
 
-#line 116 "cmExprParser.cxx" /* yacc.c:339  */
-
+#line 120 "cmExprParser.cxx" /* yacc.c:337  */
 # ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
+#  if defined __cplusplus
+#   if 201103L <= __cplusplus
+#    define YY_NULLPTR nullptr
+#   else
+#    define YY_NULLPTR 0
+#   endif
 #  else
-#   define YY_NULLPTR 0
+#   define YY_NULLPTR ((void*)0)
 #  endif
 # endif
 
@@ -187,9 +194,7 @@
 
 #endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED  */
 
-/* Copy the second part of user declarations.  */
 
-#line 193 "cmExprParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -210,13 +215,13 @@
 #ifdef YYTYPE_UINT16
 typedef YYTYPE_UINT16 yytype_uint16;
 #else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
 #endif
 
 #ifdef YYTYPE_INT16
 typedef YYTYPE_INT16 yytype_int16;
 #else
-typedef short int yytype_int16;
+typedef short yytype_int16;
 #endif
 
 #ifndef YYSIZE_T
@@ -228,7 +233,7 @@
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
-#  define YYSIZE_T unsigned int
+#  define YYSIZE_T unsigned
 # endif
 #endif
 
@@ -264,15 +269,6 @@
 # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
 #endif
 
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
-# else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
 # define YYUSE(E) ((void) (E))
@@ -280,7 +276,7 @@
 # define YYUSE(E) /* empty */
 #endif
 
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
 /* Suppress an incorrect diagnostic about yylval being uninitialized.  */
 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
     _Pragma ("GCC diagnostic push") \
@@ -429,29 +425,29 @@
 #endif /* !YYCOPY_NEEDED */
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  17
+#define YYFINAL  19
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   30
+#define YYLAST   34
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  17
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  10
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  23
+#define YYNRULES  24
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  39
+#define YYNSTATES  41
 
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
 #define YYMAXUTOK   271
 
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, with out-of-bounds checking.  */
 #define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+  ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
+   as returned by yylex.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -490,7 +486,7 @@
 {
        0,    77,    77,    82,    85,    90,    93,    98,   101,   106,
      109,   112,   117,   120,   123,   128,   131,   134,   140,   145,
-     148,   151,   156,   159
+     148,   151,   154,   159,   162
 };
 #endif
 
@@ -517,10 +513,10 @@
 };
 # endif
 
-#define YYPACT_NINF -8
+#define YYPACT_NINF -11
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-8)))
+  (!!((Yystate) == (-11)))
 
 #define YYTABLE_NINF -1
 
@@ -531,10 +527,11 @@
      STATE-NUM.  */
 static const yytype_int8 yypact[] =
 {
-       0,     0,     0,     0,    -8,     2,    -7,    -5,     8,     3,
-      10,     1,    -8,    -8,    -8,    -8,     6,    -8,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    -8,    -5,
-       8,     3,    10,    10,     1,     1,    -8,    -8,    -8
+       1,     1,     1,     1,     1,   -11,     6,   -10,    -4,     9,
+       4,    11,     2,   -11,   -11,   -11,   -11,     7,   -11,   -11,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+     -11,    -4,     9,     4,    11,    11,     2,     2,   -11,   -11,
+     -11
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -542,22 +539,23 @@
      means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     0,    22,     0,     2,     3,     5,     7,
-       9,    12,    15,    19,    20,    21,     0,     1,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    23,     4,
-       6,     8,    10,    11,    13,    14,    16,    17,    18
+       0,     0,     0,     0,     0,    23,     0,     2,     3,     5,
+       7,     9,    12,    15,    19,    20,    21,     0,    22,     1,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      24,     4,     6,     8,    10,    11,    13,    14,    16,    17,
+      18
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-      -8,    -8,    12,     5,    11,     9,    -2,     4,    -1,    -8
+     -11,   -11,    22,    10,     8,    12,    -3,    -2,    -1,   -11
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     5,     6,     7,     8,     9,    10,    11,    12,    13
+      -1,     6,     7,     8,     9,    10,    11,    12,    13,    14
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -565,28 +563,29 @@
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-      14,    15,    17,     1,     2,    18,    25,    26,    27,    19,
-       3,    21,    22,    23,    24,    16,     4,    28,    18,    32,
-      33,    20,     0,    29,    36,    37,    38,    34,    35,    31,
-      30
+      15,    16,    20,    18,     1,     2,    19,    27,    28,    29,
+      21,     3,    23,    24,    25,    26,     4,     5,    30,    20,
+      34,    35,    22,    36,    37,    17,    38,    39,    40,    32,
+      31,     0,     0,     0,    33
 };
 
 static const yytype_int8 yycheck[] =
 {
-       1,     2,     0,     3,     4,    12,     5,     6,     7,    14,
-      10,     8,     9,     3,     4,     3,    16,    11,    12,    21,
-      22,    13,    -1,    18,    25,    26,    27,    23,    24,    20,
-      19
+       1,     2,    12,     4,     3,     4,     0,     5,     6,     7,
+      14,    10,     8,     9,     3,     4,    15,    16,    11,    12,
+      23,    24,    13,    25,    26,     3,    27,    28,    29,    21,
+      20,    -1,    -1,    -1,    22
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,     4,    10,    16,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    25,    25,    19,     0,    12,    14,
-      13,     8,     9,     3,     4,     5,     6,     7,    11,    20,
-      21,    22,    23,    23,    24,    24,    25,    25,    25
+       0,     3,     4,    10,    15,    16,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    25,    25,    19,    25,     0,
+      12,    14,    13,     8,     9,     3,     4,     5,     6,     7,
+      11,    20,    21,    22,    23,    23,    24,    24,    25,    25,
+      25
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
@@ -594,7 +593,7 @@
 {
        0,    17,    18,    19,    19,    20,    20,    21,    21,    22,
       22,    22,    23,    23,    23,    24,    24,    24,    24,    25,
-      25,    25,    26,    26
+      25,    25,    25,    26,    26
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
@@ -602,7 +601,7 @@
 {
        0,     2,     1,     1,     3,     1,     3,     1,     3,     1,
        3,     3,     1,     3,     3,     1,     3,     3,     3,     1,
-       2,     2,     1,     3
+       2,     2,     2,     1,     3
 };
 
 
@@ -618,22 +617,22 @@
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
+#define YYBACKUP(Token, Value)                                    \
+  do                                                              \
+    if (yychar == YYEMPTY)                                        \
+      {                                                           \
+        yychar = (Token);                                         \
+        yylval = (Value);                                         \
+        YYPOPSTACK (yylen);                                       \
+        yystate = *yyssp;                                         \
+        goto yybackup;                                            \
+      }                                                           \
+    else                                                          \
+      {                                                           \
+        yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+        YYERROR;                                                  \
+      }                                                           \
+  while (0)
 
 /* Error token number */
 #define YYTERROR        1
@@ -673,38 +672,38 @@
 } while (0)
 
 
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO.  |
+`-----------------------------------*/
 
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
+  FILE *yyoutput = yyo;
+  YYUSE (yyoutput);
   YYUSE (yyscanner);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+    YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
 # endif
   YYUSE (yytype);
 }
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO.  |
+`---------------------------*/
 
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  YYFPRINTF (yyoutput, "%s %s (",
+  YYFPRINTF (yyo, "%s %s (",
              yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
-  YYFPRINTF (yyoutput, ")");
+  yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyo, ")");
 }
 
 /*------------------------------------------------------------------.
@@ -738,7 +737,7 @@
 static void
 yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
 {
-  unsigned long int yylno = yyrline[yyrule];
+  unsigned long yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -749,7 +748,7 @@
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr,
                        yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       &yyvsp[(yyi + 1) - (yynrhs)]
                                               , yyscanner);
       YYFPRINTF (stderr, "\n");
     }
@@ -853,7 +852,10 @@
           case '\\':
             if (*++yyp != '\\')
               goto do_not_strip_quotes;
-            /* Fall through.  */
+            else
+              goto append;
+
+          append:
           default:
             if (yyres)
               yyres[yyn] = *yyp;
@@ -871,7 +873,7 @@
   if (! yyres)
     return yystrlen (yystr);
 
-  return yystpcpy (yyres, yystr) - yyres;
+  return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
 }
 # endif
 
@@ -949,10 +951,10 @@
                 yyarg[yycount++] = yytname[yyx];
                 {
                   YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                  if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+                    yysize = yysize1;
+                  else
                     return 2;
-                  yysize = yysize1;
                 }
               }
         }
@@ -964,6 +966,7 @@
       case N:                               \
         yyformat = S;                       \
       break
+    default: /* Avoid compiler warnings. */
       YYCASE_(0, YY_("syntax error"));
       YYCASE_(1, YY_("syntax error, unexpected %s"));
       YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -975,9 +978,10 @@
 
   {
     YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+      yysize = yysize1;
+    else
       return 2;
-    yysize = yysize1;
   }
 
   if (*yymsg_alloc < yysize)
@@ -1108,23 +1112,31 @@
   yychar = YYEMPTY; /* Cause a token to be read.  */
   goto yysetstate;
 
+
 /*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
+| yynewstate -- push a new state, which is found in yystate.  |
 `------------------------------------------------------------*/
- yynewstate:
+yynewstate:
   /* In all cases, when you get here, the value and location stacks
      have just been pushed.  So pushing a state here evens the stacks.  */
   yyssp++;
 
- yysetstate:
-  *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate.  |
+`--------------------------------------------------------------------*/
+yysetstate:
+  *yyssp = (yytype_int16) yystate;
 
   if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+    goto yyexhaustedlab;
+#else
     {
       /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
+      YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
 
-#ifdef yyoverflow
+# if defined yyoverflow
       {
         /* Give user a chance to reallocate the stack.  Use copies of
            these so that the &'s don't force the real ones into
@@ -1140,14 +1152,10 @@
                     &yyss1, yysize * sizeof (*yyssp),
                     &yyvs1, yysize * sizeof (*yyvsp),
                     &yystacksize);
-
         yyss = yyss1;
         yyvs = yyvs1;
       }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
         goto yyexhaustedlab;
@@ -1163,22 +1171,22 @@
           goto yyexhaustedlab;
         YYSTACK_RELOCATE (yyss_alloc, yyss);
         YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
         if (yyss1 != yyssa)
           YYSTACK_FREE (yyss1);
       }
 # endif
-#endif /* no yyoverflow */
 
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
+                  (unsigned long) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
         YYABORT;
     }
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
@@ -1187,11 +1195,11 @@
 
   goto yybackup;
 
+
 /*-----------.
 | yybackup.  |
 `-----------*/
 yybackup:
-
   /* Do appropriate processing given the current state.  Read a
      lookahead token if we need one and don't already have one.  */
 
@@ -1264,7 +1272,7 @@
 
 
 /*-----------------------------.
-| yyreduce -- Do a reduction.  |
+| yyreduce -- do a reduction.  |
 `-----------------------------*/
 yyreduce:
   /* yyn is the number of a rule to reduce with.  */
@@ -1285,186 +1293,194 @@
   switch (yyn)
     {
         case 2:
-#line 77 "cmExprParser.y" /* yacc.c:1646  */
+#line 77 "cmExprParser.y" /* yacc.c:1652  */
     {
     cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
   }
-#line 1293 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1301 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 3:
-#line 82 "cmExprParser.y" /* yacc.c:1646  */
+#line 82 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1301 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1309 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 4:
-#line 85 "cmExprParser.y" /* yacc.c:1646  */
+#line 85 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
   }
-#line 1309 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1317 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 5:
-#line 90 "cmExprParser.y" /* yacc.c:1646  */
+#line 90 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1317 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1325 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 6:
-#line 93 "cmExprParser.y" /* yacc.c:1646  */
+#line 93 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
   }
-#line 1325 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1333 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 7:
-#line 98 "cmExprParser.y" /* yacc.c:1646  */
+#line 98 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1333 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1341 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 8:
-#line 101 "cmExprParser.y" /* yacc.c:1646  */
+#line 101 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
   }
-#line 1341 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1349 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 9:
-#line 106 "cmExprParser.y" /* yacc.c:1646  */
+#line 106 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1349 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1357 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 10:
-#line 109 "cmExprParser.y" /* yacc.c:1646  */
+#line 109 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
   }
-#line 1357 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1365 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 11:
-#line 112 "cmExprParser.y" /* yacc.c:1646  */
+#line 112 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
   }
-#line 1365 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1373 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 12:
-#line 117 "cmExprParser.y" /* yacc.c:1646  */
+#line 117 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1373 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1381 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 13:
-#line 120 "cmExprParser.y" /* yacc.c:1646  */
+#line 120 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
   }
-#line 1381 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1389 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 14:
-#line 123 "cmExprParser.y" /* yacc.c:1646  */
+#line 123 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
   }
-#line 1389 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1397 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 15:
-#line 128 "cmExprParser.y" /* yacc.c:1646  */
+#line 128 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1397 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1405 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 16:
-#line 131 "cmExprParser.y" /* yacc.c:1646  */
+#line 131 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
   }
-#line 1405 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1413 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 17:
-#line 134 "cmExprParser.y" /* yacc.c:1646  */
+#line 134 "cmExprParser.y" /* yacc.c:1652  */
     {
     if (yyvsp[0].Number == 0) {
       throw std::overflow_error("divide by zero");
     }
     (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
   }
-#line 1416 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1424 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 18:
-#line 140 "cmExprParser.y" /* yacc.c:1646  */
+#line 140 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
   }
-#line 1424 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1432 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 19:
-#line 145 "cmExprParser.y" /* yacc.c:1646  */
+#line 145 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1432 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1440 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 20:
-#line 148 "cmExprParser.y" /* yacc.c:1646  */
+#line 148 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = + (yyvsp[0].Number);
   }
-#line 1440 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1448 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 21:
-#line 151 "cmExprParser.y" /* yacc.c:1646  */
+#line 151 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = - (yyvsp[0].Number);
   }
-#line 1448 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1456 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 22:
-#line 156 "cmExprParser.y" /* yacc.c:1646  */
+#line 154 "cmExprParser.y" /* yacc.c:1652  */
     {
-    (yyval.Number) = (yyvsp[0].Number);
+    (yyval.Number) = ~ (yyvsp[0].Number);
   }
-#line 1456 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1464 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
   case 23:
-#line 159 "cmExprParser.y" /* yacc.c:1646  */
+#line 159 "cmExprParser.y" /* yacc.c:1652  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1472 "cmExprParser.cxx" /* yacc.c:1652  */
+    break;
+
+  case 24:
+#line 162 "cmExprParser.y" /* yacc.c:1652  */
     {
     (yyval.Number) = (yyvsp[-1].Number);
   }
-#line 1464 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1480 "cmExprParser.cxx" /* yacc.c:1652  */
     break;
 
 
-#line 1468 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1484 "cmExprParser.cxx" /* yacc.c:1652  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1489,14 +1505,13 @@
   /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
+  {
+    const int yylhs = yyr1[yyn] - YYNTOKENS;
+    const int yyi = yypgoto[yylhs] + *yyssp;
+    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+               ? yytable[yyi]
+               : yydefgoto[yylhs]);
+  }
 
   goto yynewstate;
 
@@ -1580,12 +1595,10 @@
 | yyerrorlab -- error raised explicitly by YYERROR.  |
 `---------------------------------------------------*/
 yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
+  /* Pacify compilers when the user code never invokes YYERROR and the
+     label yyerrorlab therefore never appears in user code.  */
+  if (0)
+    YYERROR;
 
   /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
@@ -1648,6 +1661,7 @@
   yyresult = 0;
   goto yyreturn;
 
+
 /*-----------------------------------.
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
@@ -1655,6 +1669,7 @@
   yyresult = 1;
   goto yyreturn;
 
+
 #if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
@@ -1665,6 +1680,10 @@
   /* Fall through.  */
 #endif
 
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result.  |
+`-----------------------------------------------------*/
 yyreturn:
   if (yychar != YYEMPTY)
     {
@@ -1694,7 +1713,7 @@
 #endif
   return yyresult;
 }
-#line 164 "cmExprParser.y" /* yacc.c:1906  */
+#line 167 "cmExprParser.y" /* yacc.c:1918  */
 
 /* End of grammar */
 
diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y
index 2137473..7ae2118 100644
--- a/Source/LexerParser/cmExprParser.y
+++ b/Source/LexerParser/cmExprParser.y
@@ -151,6 +151,9 @@
 | exp_MINUS unary {
     $<Number>$ = - $<Number>2;
   }
+| exp_NOT unary {
+    $<Number>$ = ~ $<Number>2;
+  }
 
 factor:
   exp_NUMBER {
diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h
index 84b2bbd..5ffd7c5 100644
--- a/Source/LexerParser/cmExprParserTokens.h
+++ b/Source/LexerParser/cmExprParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 #ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
 # define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
 /* Debug traces.  */
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 015cab9..2ca7927 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
    define necessary library symbols; they are noted "INFRINGES ON
    USER NAME SPACE" below.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 /* Identify Bison output.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
 #define yynerrs         cmFortran_yynerrs
 
 
-/* Copy the first part of user declarations.  */
-#line 1 "cmFortranParser.y" /* yacc.c:339  */
+/* First part of user prologue.  */
+#line 1 "cmFortranParser.y" /* yacc.c:337  */
 
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
@@ -131,13 +135,16 @@
 # pragma GCC diagnostic ignored "-Wconversion"
 #endif
 
-#line 135 "cmFortranParser.cxx" /* yacc.c:339  */
-
+#line 139 "cmFortranParser.cxx" /* yacc.c:337  */
 # ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
+#  if defined __cplusplus
+#   if 201103L <= __cplusplus
+#    define YY_NULLPTR nullptr
+#   else
+#    define YY_NULLPTR 0
+#   endif
 #  else
-#   define YY_NULLPTR 0
+#   define YY_NULLPTR ((void*)0)
 #  endif
 # endif
 
@@ -251,11 +258,11 @@
 
 union YYSTYPE
 {
-#line 73 "cmFortranParser.y" /* yacc.c:355  */
+#line 73 "cmFortranParser.y" /* yacc.c:352  */
 
   char* string;
 
-#line 259 "cmFortranParser.cxx" /* yacc.c:355  */
+#line 266 "cmFortranParser.cxx" /* yacc.c:352  */
 };
 
 typedef union YYSTYPE YYSTYPE;
@@ -269,9 +276,7 @@
 
 #endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED  */
 
-/* Copy the second part of user declarations.  */
 
-#line 275 "cmFortranParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -292,13 +297,13 @@
 #ifdef YYTYPE_UINT16
 typedef YYTYPE_UINT16 yytype_uint16;
 #else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
 #endif
 
 #ifdef YYTYPE_INT16
 typedef YYTYPE_INT16 yytype_int16;
 #else
-typedef short int yytype_int16;
+typedef short yytype_int16;
 #endif
 
 #ifndef YYSIZE_T
@@ -310,7 +315,7 @@
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
-#  define YYSIZE_T unsigned int
+#  define YYSIZE_T unsigned
 # endif
 #endif
 
@@ -346,15 +351,6 @@
 # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
 #endif
 
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
-# else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
 # define YYUSE(E) ((void) (E))
@@ -362,7 +358,7 @@
 # define YYUSE(E) /* empty */
 #endif
 
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
 /* Suppress an incorrect diagnostic about yylval being uninitialized.  */
 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
     _Pragma ("GCC diagnostic push") \
@@ -524,16 +520,16 @@
 /* YYNSTATES -- Number of states.  */
 #define YYNSTATES  126
 
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
 #define YYMAXUTOK   295
 
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, with out-of-bounds checking.  */
 #define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+  ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
+   as returned by yylex.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -863,22 +859,22 @@
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
+#define YYBACKUP(Token, Value)                                    \
+  do                                                              \
+    if (yychar == YYEMPTY)                                        \
+      {                                                           \
+        yychar = (Token);                                         \
+        yylval = (Value);                                         \
+        YYPOPSTACK (yylen);                                       \
+        yystate = *yyssp;                                         \
+        goto yybackup;                                            \
+      }                                                           \
+    else                                                          \
+      {                                                           \
+        yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+        YYERROR;                                                  \
+      }                                                           \
+  while (0)
 
 /* Error token number */
 #define YYTERROR        1
@@ -918,38 +914,38 @@
 } while (0)
 
 
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO.  |
+`-----------------------------------*/
 
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
+  FILE *yyoutput = yyo;
+  YYUSE (yyoutput);
   YYUSE (yyscanner);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+    YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
 # endif
   YYUSE (yytype);
 }
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO.  |
+`---------------------------*/
 
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  YYFPRINTF (yyoutput, "%s %s (",
+  YYFPRINTF (yyo, "%s %s (",
              yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
-  YYFPRINTF (yyoutput, ")");
+  yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyo, ")");
 }
 
 /*------------------------------------------------------------------.
@@ -983,7 +979,7 @@
 static void
 yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
 {
-  unsigned long int yylno = yyrline[yyrule];
+  unsigned long yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -994,7 +990,7 @@
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr,
                        yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       &yyvsp[(yyi + 1) - (yynrhs)]
                                               , yyscanner);
       YYFPRINTF (stderr, "\n");
     }
@@ -1098,7 +1094,10 @@
           case '\\':
             if (*++yyp != '\\')
               goto do_not_strip_quotes;
-            /* Fall through.  */
+            else
+              goto append;
+
+          append:
           default:
             if (yyres)
               yyres[yyn] = *yyp;
@@ -1116,7 +1115,7 @@
   if (! yyres)
     return yystrlen (yystr);
 
-  return yystpcpy (yyres, yystr) - yyres;
+  return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
 }
 # endif
 
@@ -1194,10 +1193,10 @@
                 yyarg[yycount++] = yytname[yyx];
                 {
                   YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                  if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+                    yysize = yysize1;
+                  else
                     return 2;
-                  yysize = yysize1;
                 }
               }
         }
@@ -1209,6 +1208,7 @@
       case N:                               \
         yyformat = S;                       \
       break
+    default: /* Avoid compiler warnings. */
       YYCASE_(0, YY_("syntax error"));
       YYCASE_(1, YY_("syntax error, unexpected %s"));
       YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -1220,9 +1220,10 @@
 
   {
     YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+      yysize = yysize1;
+    else
       return 2;
-    yysize = yysize1;
   }
 
   if (*yymsg_alloc < yysize)
@@ -1353,23 +1354,31 @@
   yychar = YYEMPTY; /* Cause a token to be read.  */
   goto yysetstate;
 
+
 /*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
+| yynewstate -- push a new state, which is found in yystate.  |
 `------------------------------------------------------------*/
- yynewstate:
+yynewstate:
   /* In all cases, when you get here, the value and location stacks
      have just been pushed.  So pushing a state here evens the stacks.  */
   yyssp++;
 
- yysetstate:
-  *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate.  |
+`--------------------------------------------------------------------*/
+yysetstate:
+  *yyssp = (yytype_int16) yystate;
 
   if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+    goto yyexhaustedlab;
+#else
     {
       /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
+      YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
 
-#ifdef yyoverflow
+# if defined yyoverflow
       {
         /* Give user a chance to reallocate the stack.  Use copies of
            these so that the &'s don't force the real ones into
@@ -1385,14 +1394,10 @@
                     &yyss1, yysize * sizeof (*yyssp),
                     &yyvs1, yysize * sizeof (*yyvsp),
                     &yystacksize);
-
         yyss = yyss1;
         yyvs = yyvs1;
       }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
         goto yyexhaustedlab;
@@ -1408,22 +1413,22 @@
           goto yyexhaustedlab;
         YYSTACK_RELOCATE (yyss_alloc, yyss);
         YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
         if (yyss1 != yyssa)
           YYSTACK_FREE (yyss1);
       }
 # endif
-#endif /* no yyoverflow */
 
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
+                  (unsigned long) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
         YYABORT;
     }
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
@@ -1432,11 +1437,11 @@
 
   goto yybackup;
 
+
 /*-----------.
 | yybackup.  |
 `-----------*/
 yybackup:
-
   /* Do appropriate processing given the current state.  Read a
      lookahead token if we need one and don't already have one.  */
 
@@ -1509,7 +1514,7 @@
 
 
 /*-----------------------------.
-| yyreduce -- Do a reduction.  |
+| yyreduce -- do a reduction.  |
 `-----------------------------*/
 yyreduce:
   /* yyn is the number of a rule to reduce with.  */
@@ -1530,26 +1535,26 @@
   switch (yyn)
     {
         case 4:
-#line 104 "cmFortranParser.y" /* yacc.c:1646  */
+#line 104 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_SetInInterface(parser, true);
   }
-#line 1539 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1544 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 5:
-#line 108 "cmFortranParser.y" /* yacc.c:1646  */
+#line 108 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1549 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1554 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 6:
-#line 113 "cmFortranParser.y" /* yacc.c:1646  */
+#line 113 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
@@ -1559,22 +1564,22 @@
     }
     free((yyvsp[-2].string));
   }
-#line 1563 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1568 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 7:
-#line 122 "cmFortranParser.y" /* yacc.c:1646  */
+#line 122 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string));
     free((yyvsp[-4].string));
     free((yyvsp[-2].string));
   }
-#line 1574 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1579 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 8:
-#line 128 "cmFortranParser.y" /* yacc.c:1646  */
+#line 128 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
@@ -1582,40 +1587,40 @@
     free((yyvsp[-4].string));
     free((yyvsp[-2].string));
   }
-#line 1586 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1591 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 9:
-#line 135 "cmFortranParser.y" /* yacc.c:1646  */
+#line 135 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_SetInInterface(parser, true);
     free((yyvsp[-2].string));
   }
-#line 1596 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1601 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 10:
-#line 140 "cmFortranParser.y" /* yacc.c:1646  */
+#line 140 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_SetInInterface(parser, false);
   }
-#line 1605 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1610 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 11:
-#line 144 "cmFortranParser.y" /* yacc.c:1646  */
+#line 144 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1615 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1620 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 12:
-#line 149 "cmFortranParser.y" /* yacc.c:1646  */
+#line 149 "cmFortranParser.y" /* yacc.c:1652  */
     {
     if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
       cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
@@ -1624,139 +1629,139 @@
     free((yyvsp[-4].string));
     free((yyvsp[-2].string));
   }
-#line 1628 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1633 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 13:
-#line 157 "cmFortranParser.y" /* yacc.c:1646  */
+#line 157 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1638 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1643 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 14:
-#line 162 "cmFortranParser.y" /* yacc.c:1646  */
+#line 162 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1648 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1653 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 15:
-#line 167 "cmFortranParser.y" /* yacc.c:1646  */
+#line 167 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1658 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1663 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 16:
-#line 172 "cmFortranParser.y" /* yacc.c:1646  */
+#line 172 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1668 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1673 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 17:
-#line 177 "cmFortranParser.y" /* yacc.c:1646  */
+#line 177 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1678 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1683 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 18:
-#line 182 "cmFortranParser.y" /* yacc.c:1646  */
+#line 182 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1688 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1693 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 19:
-#line 187 "cmFortranParser.y" /* yacc.c:1646  */
+#line 187 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1698 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1703 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 20:
-#line 192 "cmFortranParser.y" /* yacc.c:1646  */
+#line 192 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
     free((yyvsp[-2].string));
   }
-#line 1708 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1713 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 21:
-#line 197 "cmFortranParser.y" /* yacc.c:1646  */
+#line 197 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleIf(parser);
   }
-#line 1717 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1722 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 22:
-#line 201 "cmFortranParser.y" /* yacc.c:1646  */
+#line 201 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleElif(parser);
   }
-#line 1726 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1731 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 23:
-#line 205 "cmFortranParser.y" /* yacc.c:1646  */
+#line 205 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleElse(parser);
   }
-#line 1735 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1740 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 24:
-#line 209 "cmFortranParser.y" /* yacc.c:1646  */
+#line 209 "cmFortranParser.y" /* yacc.c:1652  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleEndif(parser);
   }
-#line 1744 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1749 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 48:
-#line 231 "cmFortranParser.y" /* yacc.c:1646  */
+#line 231 "cmFortranParser.y" /* yacc.c:1652  */
     { free ((yyvsp[0].string)); }
-#line 1750 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1755 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
   case 55:
-#line 238 "cmFortranParser.y" /* yacc.c:1646  */
+#line 238 "cmFortranParser.y" /* yacc.c:1652  */
     { free ((yyvsp[0].string)); }
-#line 1756 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1761 "cmFortranParser.cxx" /* yacc.c:1652  */
     break;
 
 
-#line 1760 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1765 "cmFortranParser.cxx" /* yacc.c:1652  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1781,14 +1786,13 @@
   /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
+  {
+    const int yylhs = yyr1[yyn] - YYNTOKENS;
+    const int yyi = yypgoto[yylhs] + *yyssp;
+    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+               ? yytable[yyi]
+               : yydefgoto[yylhs]);
+  }
 
   goto yynewstate;
 
@@ -1872,12 +1876,10 @@
 | yyerrorlab -- error raised explicitly by YYERROR.  |
 `---------------------------------------------------*/
 yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
+  /* Pacify compilers when the user code never invokes YYERROR and the
+     label yyerrorlab therefore never appears in user code.  */
+  if (0)
+    YYERROR;
 
   /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
@@ -1940,6 +1942,7 @@
   yyresult = 0;
   goto yyreturn;
 
+
 /*-----------------------------------.
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
@@ -1947,6 +1950,7 @@
   yyresult = 1;
   goto yyreturn;
 
+
 #if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
@@ -1957,6 +1961,10 @@
   /* Fall through.  */
 #endif
 
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result.  |
+`-----------------------------------------------------*/
 yyreturn:
   if (yychar != YYEMPTY)
     {
@@ -1986,6 +1994,6 @@
 #endif
   return yyresult;
 }
-#line 249 "cmFortranParser.y" /* yacc.c:1906  */
+#line 249 "cmFortranParser.y" /* yacc.c:1918  */
 
 /* End of grammar */
diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h
index 29c6d60..0da4c1c 100644
--- a/Source/LexerParser/cmFortranParserTokens.h
+++ b/Source/LexerParser/cmFortranParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
+/* A Bison parser, made by GNU Bison 3.3.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 #ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
 # define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
 /* Debug traces.  */
@@ -130,11 +134,11 @@
 
 union YYSTYPE
 {
-#line 73 "cmFortranParser.y" /* yacc.c:1909  */
+#line 73 "cmFortranParser.y" /* yacc.c:1921  */
 
   char* string;
 
-#line 138 "cmFortranParserTokens.h" /* yacc.c:1909  */
+#line 142 "cmFortranParserTokens.h" /* yacc.c:1921  */
 };
 
 typedef union YYSTYPE YYSTYPE;
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index c9ebba8..287a482 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -6,6 +6,7 @@
 #include "cmAlgorithms.h"
 #include "cmDocumentation.h"
 #include "cmDocumentationEntry.h"
+#include "cmStringAlgorithms.h"
 #include "cmVersion.h"
 #include "cmake.h"
 #include "cmsys/CommandLineArguments.hxx"
diff --git a/Source/cmAddCompileDefinitionsCommand.h b/Source/cmAddCompileDefinitionsCommand.h
index e985dca..5f90ed9 100644
--- a/Source/cmAddCompileDefinitionsCommand.h
+++ b/Source/cmAddCompileDefinitionsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -18,7 +20,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddCompileDefinitionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddCompileDefinitionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h
index 3d53d09..b34b7fc 100644
--- a/Source/cmAddCompileOptionsCommand.h
+++ b/Source/cmAddCompileOptionsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -18,7 +20,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddCompileOptionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddCompileOptionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 0be3c85..6eb38bd 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -95,30 +95,29 @@
   MAKE_STATIC_KEYWORD(VERBATIM);
   MAKE_STATIC_KEYWORD(WORKING_DIRECTORY);
 #undef MAKE_STATIC_KEYWORD
-  static std::unordered_set<std::string> keywords;
-  if (keywords.empty()) {
-    keywords.insert(keyAPPEND);
-    keywords.insert(keyARGS);
-    keywords.insert(keyBYPRODUCTS);
-    keywords.insert(keyCOMMAND);
-    keywords.insert(keyCOMMAND_EXPAND_LISTS);
-    keywords.insert(keyCOMMENT);
-    keywords.insert(keyDEPENDS);
-    keywords.insert(keyDEPFILE);
-    keywords.insert(keyIMPLICIT_DEPENDS);
-    keywords.insert(keyJOB_POOL);
-    keywords.insert(keyMAIN_DEPENDENCY);
-    keywords.insert(keyOUTPUT);
-    keywords.insert(keyOUTPUTS);
-    keywords.insert(keyPOST_BUILD);
-    keywords.insert(keyPRE_BUILD);
-    keywords.insert(keyPRE_LINK);
-    keywords.insert(keySOURCE);
-    keywords.insert(keyTARGET);
-    keywords.insert(keyUSES_TERMINAL);
-    keywords.insert(keyVERBATIM);
-    keywords.insert(keyWORKING_DIRECTORY);
-  }
+  static std::unordered_set<std::string> const keywords{
+    keyAPPEND,
+    keyARGS,
+    keyBYPRODUCTS,
+    keyCOMMAND,
+    keyCOMMAND_EXPAND_LISTS,
+    keyCOMMENT,
+    keyDEPENDS,
+    keyDEPFILE,
+    keyIMPLICIT_DEPENDS,
+    keyJOB_POOL,
+    keyMAIN_DEPENDENCY,
+    keyOUTPUT,
+    keyOUTPUTS,
+    keyPOST_BUILD,
+    keyPRE_BUILD,
+    keyPRE_LINK,
+    keySOURCE,
+    keyTARGET,
+    keyUSES_TERMINAL,
+    keyVERBATIM,
+    keyWORKING_DIRECTORY
+  };
 
   for (std::string const& copy : args) {
     if (keywords.count(copy)) {
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index 6af4f10..931aeab 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddCustomCommandCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddCustomCommandCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h
index 1a55116..db577bc 100644
--- a/Source/cmAddCustomTargetCommand.h
+++ b/Source/cmAddCustomTargetCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddCustomTargetCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddCustomTargetCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h
index 7b75638..0e32c83 100644
--- a/Source/cmAddDefinitionsCommand.h
+++ b/Source/cmAddDefinitionsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddDefinitionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddDefinitionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddDependenciesCommand.h b/Source/cmAddDependenciesCommand.h
index e10df71..ce912d3 100644
--- a/Source/cmAddDependenciesCommand.h
+++ b/Source/cmAddDependenciesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddDependenciesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddDependenciesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h
index bdf607d..ec57c3f 100644
--- a/Source/cmAddExecutableCommand.h
+++ b/Source/cmAddExecutableCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddExecutableCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddExecutableCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index aa21261..56dab41 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddLibraryCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddLibraryCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddLinkOptionsCommand.h b/Source/cmAddLinkOptionsCommand.h
index 30fff00..8e46be6 100644
--- a/Source/cmAddLinkOptionsCommand.h
+++ b/Source/cmAddLinkOptionsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -18,7 +20,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddLinkOptionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddLinkOptionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h
index 0ea4423..664334e 100644
--- a/Source/cmAddSubDirectoryCommand.h
+++ b/Source/cmAddSubDirectoryCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddSubDirectoryCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddSubDirectoryCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx
index bf28702..b0c462b 100644
--- a/Source/cmAddTestCommand.cxx
+++ b/Source/cmAddTestCommand.cxx
@@ -58,6 +58,7 @@
   std::vector<std::string> configurations;
   std::string working_directory;
   std::vector<std::string> command;
+  bool command_expand_lists = false;
 
   // Read the arguments.
   enum Doing
@@ -88,6 +89,13 @@
         return false;
       }
       doing = DoingWorkingDirectory;
+    } else if (args[i] == "COMMAND_EXPAND_LISTS") {
+      if (command_expand_lists) {
+        this->SetError(" may be given at most one COMMAND_EXPAND_LISTS.");
+        return false;
+      }
+      command_expand_lists = true;
+      doing = DoingNone;
     } else if (doing == DoingName) {
       name = args[i];
       doing = DoingNone;
@@ -134,6 +142,7 @@
   if (!working_directory.empty()) {
     test->SetProperty("WORKING_DIRECTORY", working_directory.c_str());
   }
+  test->SetCommandExpandLists(command_expand_lists);
   this->Makefile->AddTestGenerator(new cmTestGenerator(test, configurations));
 
   return true;
diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index bea3f3d..3d37d2b 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAddTestCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAddTestCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index d1e32b0..d7ea483 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -6,79 +6,14 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmRange.h"
-
 #include "cm_kwiml.h"
 #include <algorithm>
 #include <functional>
 #include <iterator>
-#include <memory>
-#include <sstream>
-#include <string.h>
-#include <string>
 #include <unordered_set>
 #include <utility>
 #include <vector>
 
-inline bool cmHasLiteralPrefixImpl(const std::string& str1, const char* str2,
-                                   size_t N)
-{
-  return strncmp(str1.c_str(), str2, N) == 0;
-}
-
-inline bool cmHasLiteralPrefixImpl(const char* str1, const char* str2,
-                                   size_t N)
-{
-  return strncmp(str1, str2, N) == 0;
-}
-
-inline bool cmHasLiteralSuffixImpl(const std::string& str1, const char* str2,
-                                   size_t N)
-{
-  size_t len = str1.size();
-  return len >= N && strcmp(str1.c_str() + len - N, str2) == 0;
-}
-
-inline bool cmHasLiteralSuffixImpl(const char* str1, const char* str2,
-                                   size_t N)
-{
-  size_t len = strlen(str1);
-  return len >= N && strcmp(str1 + len - N, str2) == 0;
-}
-
-template <typename T, size_t N>
-bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N])
-{
-  return cmHasLiteralPrefixImpl(str1, str2, N - 1);
-}
-
-template <typename T, size_t N>
-bool cmHasLiteralSuffix(const T& str1, const char (&str2)[N])
-{
-  return cmHasLiteralSuffixImpl(str1, str2, N - 1);
-}
-
-struct cmStrCmp
-{
-  cmStrCmp(const char* test)
-    : m_test(test)
-  {
-  }
-  cmStrCmp(std::string test)
-    : m_test(std::move(test))
-  {
-  }
-
-  bool operator()(const std::string& input) const { return m_test == input; }
-
-  bool operator()(const char* input) const
-  {
-    return strcmp(input, m_test.c_str()) == 0;
-  }
-
-private:
-  const std::string m_test;
-};
-
 template <typename FwdIt>
 FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last)
 {
@@ -158,8 +93,6 @@
 };
 }
 
-typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange;
-
 class cmListFileBacktrace;
 typedef cmRange<std::vector<cmListFileBacktrace>::const_iterator>
   cmBacktraceRange;
@@ -184,31 +117,6 @@
 }
 
 template <typename Range>
-std::string cmJoin(Range const& r, const char* delimiter)
-{
-  if (r.empty()) {
-    return std::string();
-  }
-  std::ostringstream os;
-  typedef typename Range::value_type ValueType;
-  typedef typename Range::const_iterator InputIt;
-  const InputIt first = r.begin();
-  InputIt last = r.end();
-  --last;
-  std::copy(first, last, std::ostream_iterator<ValueType>(os, delimiter));
-
-  os << *last;
-
-  return os.str();
-}
-
-template <typename Range>
-std::string cmJoin(Range const& r, std::string const& delimiter)
-{
-  return cmJoin(r, delimiter.c_str());
-}
-
-template <typename Range>
 typename Range::const_iterator cmRemoveN(Range& r, size_t n)
 {
   return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n);
@@ -286,23 +194,6 @@
   return cmRemoveDuplicates(r.begin(), r.end());
 }
 
-template <typename Range>
-std::string cmWrap(std::string const& prefix, Range const& r,
-                   std::string const& suffix, std::string const& sep)
-{
-  if (r.empty()) {
-    return std::string();
-  }
-  return prefix + cmJoin(r, suffix + sep + prefix) + suffix;
-}
-
-template <typename Range>
-std::string cmWrap(char prefix, Range const& r, char suffix,
-                   std::string const& sep)
-{
-  return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep);
-}
-
 template <typename Range, typename T>
 typename Range::const_iterator cmFindNot(Range const& r, T const& t)
 {
@@ -315,45 +206,8 @@
   return std::reverse_iterator<Iter>(it);
 }
 
-inline bool cmHasPrefix(std::string const& str, std::string const& prefix)
-{
-  if (str.size() < prefix.size()) {
-    return false;
-  }
-  return str.compare(0, prefix.size(), prefix) == 0;
-}
-
-inline bool cmHasSuffix(const std::string& str, const std::string& suffix)
-{
-  if (str.size() < suffix.size()) {
-    return false;
-  }
-  return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
-}
-
-inline void cmStripSuffixIfExists(std::string& str, const std::string& suffix)
-{
-  if (cmHasSuffix(str, suffix)) {
-    str.resize(str.size() - suffix.size());
-  }
-}
-
 namespace cm {
 
-#if defined(CMake_HAVE_CXX_MAKE_UNIQUE)
-
-using std::make_unique;
-
-#else
-
-template <typename T, typename... Args>
-std::unique_ptr<T> make_unique(Args&&... args)
-{
-  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-
-#endif
-
 #if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
 
 using std::size;
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 106e7a7..45c6411 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -7,9 +7,9 @@
 #include <stddef.h>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -74,6 +74,6 @@
     sourceListValue += ";";
   }
   sourceListValue += cmJoin(files, ";");
-  this->Makefile->AddDefinition(args[1], sourceListValue.c_str());
+  this->Makefile->AddDefinition(args[1], sourceListValue);
   return true;
 }
diff --git a/Source/cmAuxSourceDirectoryCommand.h b/Source/cmAuxSourceDirectoryCommand.h
index 3742e3e..973a464 100644
--- a/Source/cmAuxSourceDirectoryCommand.h
+++ b/Source/cmAuxSourceDirectoryCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -27,7 +29,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmAuxSourceDirectoryCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmAuxSourceDirectoryCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmBinUtilsLinker.cxx b/Source/cmBinUtilsLinker.cxx
new file mode 100644
index 0000000..3dac85c
--- /dev/null
+++ b/Source/cmBinUtilsLinker.cxx
@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsLinker.h"
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsLinker::cmBinUtilsLinker(cmRuntimeDependencyArchive* archive)
+  : Archive(archive)
+{
+}
+
+void cmBinUtilsLinker::SetError(const std::string& e)
+{
+  this->Archive->SetError(e);
+}
diff --git a/Source/cmBinUtilsLinker.h b/Source/cmBinUtilsLinker.h
new file mode 100644
index 0000000..29853a5
--- /dev/null
+++ b/Source/cmBinUtilsLinker.h
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsLinker_h
+#define cmBinUtilsLinker_h
+
+#include "cmStateTypes.h"
+
+#include <string>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinker
+{
+public:
+  cmBinUtilsLinker(cmRuntimeDependencyArchive* archive);
+  virtual ~cmBinUtilsLinker() = default;
+
+  virtual bool Prepare() { return true; }
+
+  virtual bool ScanDependencies(std::string const& file,
+                                cmStateEnums::TargetType type) = 0;
+
+protected:
+  cmRuntimeDependencyArchive* Archive;
+
+  void SetError(const std::string& e);
+};
+
+#endif // cmBinUtilsLinker_h
diff --git a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
new file mode 100644
index 0000000..40de592
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,18 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsLinuxELFGetRuntimeDependenciesTool::
+  cmBinUtilsLinuxELFGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive)
+  : Archive(archive)
+{
+}
+
+void cmBinUtilsLinuxELFGetRuntimeDependenciesTool::SetError(
+  const std::string& error)
+{
+  this->Archive->SetError(error);
+}
diff --git a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
new file mode 100644
index 0000000..d514e7f
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
+#define cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinuxELFGetRuntimeDependenciesTool
+{
+public:
+  cmBinUtilsLinuxELFGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive);
+  virtual ~cmBinUtilsLinuxELFGetRuntimeDependenciesTool() = default;
+
+  virtual bool GetFileInfo(std::string const& file,
+                           std::vector<std::string>& needed,
+                           std::vector<std::string>& rpaths,
+                           std::vector<std::string>& runpaths) = 0;
+
+protected:
+  cmRuntimeDependencyArchive* Archive;
+
+  void SetError(const std::string& e);
+};
+
+#endif // cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx
new file mode 100644
index 0000000..86846cb
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFLinker.cxx
@@ -0,0 +1,178 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsLinuxELFLinker.h"
+
+#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
+#include "cmLDConfigLDConfigTool.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmSystemTools.h"
+
+#include <cmsys/RegularExpression.hxx>
+
+#include <sstream>
+
+#include "cm_memory.hxx"
+
+static std::string ReplaceOrigin(const std::string& rpath,
+                                 const std::string& origin)
+{
+  static const cmsys::RegularExpression originRegex(
+    "(\\$ORIGIN)([^a-zA-Z0-9_]|$)");
+  static const cmsys::RegularExpression originCurlyRegex("\\${ORIGIN}");
+
+  cmsys::RegularExpressionMatch match;
+  if (originRegex.find(rpath.c_str(), match)) {
+    std::string begin = rpath.substr(0, match.start(1));
+    std::string end = rpath.substr(match.end(1));
+    return begin + origin + end;
+  }
+  if (originCurlyRegex.find(rpath.c_str(), match)) {
+    std::string begin = rpath.substr(0, match.start());
+    std::string end = rpath.substr(match.end());
+    return begin + origin + end;
+  }
+  return rpath;
+}
+
+cmBinUtilsLinuxELFLinker::cmBinUtilsLinuxELFLinker(
+  cmRuntimeDependencyArchive* archive)
+  : cmBinUtilsLinker(archive)
+{
+}
+
+bool cmBinUtilsLinuxELFLinker::Prepare()
+{
+  std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
+  if (tool.empty()) {
+    tool = "objdump";
+  }
+  if (tool == "objdump") {
+    this->Tool =
+      cm::make_unique<cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool>(
+        this->Archive);
+  } else {
+    std::ostringstream e;
+    e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
+    this->SetError(e.str());
+    return false;
+  }
+
+  std::string ldConfigTool =
+    this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_TOOL");
+  if (ldConfigTool.empty()) {
+    ldConfigTool = "ldconfig";
+  }
+  if (ldConfigTool == "ldconfig") {
+    this->LDConfigTool =
+      cm::make_unique<cmLDConfigLDConfigTool>(this->Archive);
+  } else {
+    std::ostringstream e;
+    e << "Invalid value for CMAKE_LDCONFIG_TOOL: " << ldConfigTool;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return true;
+}
+
+bool cmBinUtilsLinuxELFLinker::ScanDependencies(
+  std::string const& file, cmStateEnums::TargetType /* unused */)
+{
+  std::vector<std::string> parentRpaths;
+  return this->ScanDependencies(file, parentRpaths);
+}
+
+bool cmBinUtilsLinuxELFLinker::ScanDependencies(
+  std::string const& file, std::vector<std::string> const& parentRpaths)
+{
+  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::vector<std::string> searchPaths;
+  if (!runpaths.empty()) {
+    searchPaths = runpaths;
+  } else {
+    searchPaths = rpaths;
+    searchPaths.insert(searchPaths.end(), parentRpaths.begin(),
+                       parentRpaths.end());
+  }
+
+  std::vector<std::string> ldConfigPaths;
+  if (!this->LDConfigTool->GetLDConfigPaths(ldConfigPaths)) {
+    return false;
+  }
+  searchPaths.insert(searchPaths.end(), ldConfigPaths.begin(),
+                     ldConfigPaths.end());
+
+  for (auto const& dep : needed) {
+    if (!this->Archive->IsPreExcluded(dep)) {
+      std::string path;
+      bool resolved = false;
+      if (dep.find('/') != std::string::npos) {
+        this->SetError("Paths to dependencies are not supported");
+        return false;
+      }
+      if (!this->ResolveDependency(dep, searchPaths, path, resolved)) {
+        return false;
+      }
+      if (resolved) {
+        if (!this->Archive->IsPostExcluded(path)) {
+          bool unique;
+          this->Archive->AddResolvedPath(dep, path, unique);
+          if (unique && !this->ScanDependencies(path, rpaths)) {
+            return false;
+          }
+        }
+      } else {
+        this->Archive->AddUnresolvedPath(dep);
+      }
+    }
+  }
+
+  return true;
+}
+
+bool cmBinUtilsLinuxELFLinker::ResolveDependency(
+  std::string const& name, std::vector<std::string> const& searchPaths,
+  std::string& path, bool& resolved)
+{
+  for (auto const& searchPath : searchPaths) {
+    path = searchPath + '/' + name;
+    if (cmSystemTools::PathExists(path)) {
+      resolved = true;
+      return true;
+    }
+  }
+
+  for (auto const& searchPath : this->Archive->GetSearchDirectories()) {
+    path = searchPath + '/' + name;
+    if (cmSystemTools::PathExists(path)) {
+      std::ostringstream warning;
+      warning << "Dependency " << name << " found in search directory:\n  "
+              << searchPath
+              << "\nSee file(GET_RUNTIME_DEPENDENCIES) documentation for "
+              << "more information.";
+      this->Archive->GetMakefile()->IssueMessage(MessageType::WARNING,
+                                                 warning.str());
+      resolved = true;
+      return true;
+    }
+  }
+
+  resolved = false;
+  return true;
+}
diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h
new file mode 100644
index 0000000..e209637
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFLinker.h
@@ -0,0 +1,44 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsLinuxELFLinker_h
+#define cmBinUtilsLinuxELFLinker_h
+
+#include "cmBinUtilsLinker.h"
+#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
+#include "cmLDConfigTool.h"
+#include "cmStateTypes.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinuxELFLinker : public cmBinUtilsLinker
+{
+public:
+  cmBinUtilsLinuxELFLinker(cmRuntimeDependencyArchive* archive);
+
+  bool Prepare() override;
+
+  bool ScanDependencies(std::string const& file,
+                        cmStateEnums::TargetType type) override;
+
+private:
+  std::unique_ptr<cmBinUtilsLinuxELFGetRuntimeDependenciesTool> Tool;
+  std::unique_ptr<cmLDConfigTool> LDConfigTool;
+  bool HaveLDConfigPaths = false;
+  std::vector<std::string> LDConfigPaths;
+
+  bool ScanDependencies(std::string const& file,
+                        std::vector<std::string> const& parentRpaths);
+
+  bool ResolveDependency(std::string const& name,
+                         std::vector<std::string> const& searchPaths,
+                         std::string& path, bool& resolved);
+
+  bool GetLDConfigPaths();
+};
+
+#endif // cmBinUtilsLinuxELFLinker_h
diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
new file mode 100644
index 0000000..3bf7bf8
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,84 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmSystemTools.h"
+#include "cmUVProcessChain.h"
+
+#include <cmsys/RegularExpression.hxx>
+
+#include <sstream>
+
+cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::
+  cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive)
+  : cmBinUtilsLinuxELFGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::GetFileInfo(
+  std::string const& file, std::vector<std::string>& needed,
+  std::vector<std::string>& rpaths, std::vector<std::string>& runpaths)
+{
+  cmUVProcessChainBuilder builder;
+  builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
+
+  std::vector<std::string> command;
+  if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) {
+    this->SetError("Could not find objdump");
+    return false;
+  }
+  command.emplace_back("-p");
+  command.push_back(file);
+  builder.AddCommand(command);
+
+  auto process = builder.Start();
+  if (!process.Valid()) {
+    std::ostringstream e;
+    e << "Failed to start objdump process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  std::string line;
+  static const cmsys::RegularExpression neededRegex("^ *NEEDED *([^\n]*)$");
+  static const cmsys::RegularExpression rpathRegex("^ *RPATH *([^\n]*)$");
+  static const cmsys::RegularExpression runpathRegex("^ *RUNPATH *([^\n]*)$");
+  while (std::getline(*process.OutputStream(), line)) {
+    cmsys::RegularExpressionMatch match;
+    if (neededRegex.find(line.c_str(), match)) {
+      needed.push_back(match.match(1));
+    } else if (rpathRegex.find(line.c_str(), match)) {
+      std::vector<std::string> rpathSplit =
+        cmSystemTools::SplitString(match.match(1), ':');
+      rpaths.reserve(rpaths.size() + rpathSplit.size());
+      for (auto const& rpath : rpathSplit) {
+        rpaths.push_back(rpath);
+      }
+    } else if (runpathRegex.find(line.c_str(), match)) {
+      std::vector<std::string> runpathSplit =
+        cmSystemTools::SplitString(match.match(1), ':');
+      runpaths.reserve(runpaths.size() + runpathSplit.size());
+      for (auto const& runpath : runpathSplit) {
+        runpaths.push_back(runpath);
+      }
+    }
+  }
+
+  if (!process.Wait()) {
+    std::ostringstream e;
+    e << "Failed to wait on objdump process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+  auto status = process.GetStatus();
+  if (!status[0] || status[0]->ExitStatus != 0) {
+    std::ostringstream e;
+    e << "Failed to run objdump on:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return true;
+}
diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
new file mode 100644
index 0000000..286337f
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
@@ -0,0 +1,26 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h
+#define cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h
+
+#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool
+  : public cmBinUtilsLinuxELFGetRuntimeDependenciesTool
+{
+public:
+  cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive);
+
+  bool GetFileInfo(std::string const& file, std::vector<std::string>& needed,
+                   std::vector<std::string>& rpaths,
+                   std::vector<std::string>& runpaths) override;
+};
+
+#endif // cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
new file mode 100644
index 0000000..a296a47
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,19 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
+
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsMacOSMachOGetRuntimeDependenciesTool::
+  cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive)
+  : Archive(archive)
+{
+}
+
+void cmBinUtilsMacOSMachOGetRuntimeDependenciesTool::SetError(
+  const std::string& error)
+{
+  this->Archive->SetError(error);
+}
diff --git a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
new file mode 100644
index 0000000..dbb2882
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
@@ -0,0 +1,29 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
+#define cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsMacOSMachOGetRuntimeDependenciesTool
+{
+public:
+  cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive);
+  virtual ~cmBinUtilsMacOSMachOGetRuntimeDependenciesTool() = default;
+
+  virtual bool GetFileInfo(std::string const& file,
+                           std::vector<std::string>& libs,
+                           std::vector<std::string>& rpaths) = 0;
+
+protected:
+  cmRuntimeDependencyArchive* Archive;
+
+  void SetError(const std::string& error);
+};
+
+#endif // cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsMacOSMachOLinker.cxx b/Source/cmBinUtilsMacOSMachOLinker.cxx
new file mode 100644
index 0000000..0c73ac8
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOLinker.cxx
@@ -0,0 +1,230 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsMacOSMachOLinker.h"
+
+#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "cm_memory.hxx"
+
+cmBinUtilsMacOSMachOLinker::cmBinUtilsMacOSMachOLinker(
+  cmRuntimeDependencyArchive* archive)
+  : cmBinUtilsLinker(archive)
+{
+}
+
+bool cmBinUtilsMacOSMachOLinker::Prepare()
+{
+  std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
+  if (tool.empty()) {
+    tool = "otool";
+  }
+  if (tool == "otool") {
+    this->Tool =
+      cm::make_unique<cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool>(
+        this->Archive);
+  } else {
+    std::ostringstream e;
+    e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
+  std::string const& file, cmStateEnums::TargetType type)
+{
+  std::string executableFile;
+  if (type == cmStateEnums::EXECUTABLE) {
+    executableFile = file;
+  } else {
+    executableFile = this->Archive->GetBundleExecutable();
+  }
+  std::string executablePath;
+  if (!executableFile.empty()) {
+    executablePath = cmSystemTools::GetFilenamePath(executableFile);
+  }
+  return this->ScanDependencies(file, executablePath);
+}
+
+bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
+  std::string const& file, std::string const& executablePath)
+{
+  std::vector<std::string> libs, rpaths;
+  if (!this->Tool->GetFileInfo(file, libs, rpaths)) {
+    return false;
+  }
+
+  std::string loaderPath = cmSystemTools::GetFilenamePath(file);
+  return this->GetFileDependencies(libs, executablePath, loaderPath, rpaths);
+}
+
+bool cmBinUtilsMacOSMachOLinker::GetFileDependencies(
+  std::vector<std::string> const& names, std::string const& executablePath,
+  std::string const& loaderPath, std::vector<std::string> const& rpaths)
+{
+  for (std::string const& name : names) {
+    if (!this->Archive->IsPreExcluded(name)) {
+      std::string path;
+      bool resolved;
+      if (!this->ResolveDependency(name, executablePath, loaderPath, rpaths,
+                                   path, resolved)) {
+        return false;
+      }
+      if (resolved) {
+        if (!this->Archive->IsPostExcluded(path)) {
+          auto filename = cmSystemTools::GetFilenameName(path);
+          bool unique;
+          this->Archive->AddResolvedPath(filename, path, unique);
+          if (unique && !this->ScanDependencies(path, executablePath)) {
+            return false;
+          }
+        }
+      } else {
+        this->Archive->AddUnresolvedPath(name);
+      }
+    }
+  }
+
+  return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveDependency(
+  std::string const& name, std::string const& executablePath,
+  std::string const& loaderPath, std::vector<std::string> const& rpaths,
+  std::string& path, bool& resolved)
+{
+  resolved = false;
+  if (cmHasLiteralPrefix(name, "@rpath/")) {
+    if (!this->ResolveRPathDependency(name, executablePath, loaderPath, rpaths,
+                                      path, resolved)) {
+      return false;
+    }
+  } else if (cmHasLiteralPrefix(name, "@loader_path/")) {
+    if (!this->ResolveLoaderPathDependency(name, loaderPath, path, resolved)) {
+      return false;
+    }
+  } else if (cmHasLiteralPrefix(name, "@executable_path/")) {
+    if (!this->ResolveExecutablePathDependency(name, executablePath, path,
+                                               resolved)) {
+      return false;
+    }
+  } else {
+    resolved = true;
+    path = name;
+  }
+
+  if (resolved && !cmSystemTools::FileIsFullPath(path)) {
+    this->SetError("Resolved path is not absolute");
+    return false;
+  }
+
+  return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveExecutablePathDependency(
+  std::string const& name, std::string const& executablePath,
+  std::string& path, bool& resolved)
+{
+  if (executablePath.empty()) {
+    resolved = false;
+    return true;
+  }
+
+  // 16 is == "@executable_path".length()
+  path = name;
+  path.replace(0, 16, executablePath);
+
+  if (!cmSystemTools::PathExists(path)) {
+    resolved = false;
+    return true;
+  }
+
+  resolved = true;
+  return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveLoaderPathDependency(
+  std::string const& name, std::string const& loaderPath, std::string& path,
+  bool& resolved)
+{
+  if (loaderPath.empty()) {
+    resolved = false;
+    return true;
+  }
+
+  // 12 is "@loader_path".length();
+  path = name;
+  path.replace(0, 12, loaderPath);
+
+  if (!cmSystemTools::PathExists(path)) {
+    resolved = false;
+    return true;
+  }
+
+  resolved = true;
+  return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveRPathDependency(
+  std::string const& name, std::string const& executablePath,
+  std::string const& loaderPath, std::vector<std::string> const& rpaths,
+  std::string& path, bool& resolved)
+{
+  for (std::string const& rpath : rpaths) {
+    std::string searchFile = name;
+    searchFile.replace(0, 6, rpath);
+    if (cmHasLiteralPrefix(searchFile, "@loader_path/")) {
+      if (!this->ResolveLoaderPathDependency(searchFile, loaderPath, path,
+                                             resolved)) {
+        return false;
+      }
+      if (resolved) {
+        return true;
+      }
+    } else if (cmHasLiteralPrefix(searchFile, "@executable_path/")) {
+      if (!this->ResolveExecutablePathDependency(searchFile, executablePath,
+                                                 path, resolved)) {
+        return false;
+      }
+      if (resolved) {
+        return true;
+      }
+    } else if (cmSystemTools::PathExists(searchFile)) {
+      /*
+       * paraphrasing @ben.boeckel:
+       *  if /b/libB.dylib is supposed to be used,
+       *  /a/libbB.dylib will be found first if it exists. CMake tries to
+       *  sort rpath directories to avoid this, but sometimes there is no
+       *  right answer.
+       *
+       *  I believe it is possible to resolve this using otools -l
+       *  then checking the LC_LOAD_DYLIB command whose name is
+       *  equal to the value of search_file, UNLESS the build
+       *  specifically sets the RPath to paths that will match
+       *  duplicate libs; at this point can we just point to
+       *  user error, or is there a reason why the advantages
+       *  to this scenario outweigh its disadvantages?
+       *
+       *  Also priority seems to be the order as passed in when compiled
+       *  so as long as this method's resolution guarantees priority
+       *  in that manner further checking should not be necessary?
+       */
+      path = searchFile;
+      resolved = true;
+      return true;
+    }
+  }
+
+  resolved = false;
+  return true;
+}
diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h
new file mode 100644
index 0000000..f4f309d
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOLinker.h
@@ -0,0 +1,59 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsMacOSMachOLinker_h
+#define cmBinUtilsMacOSMachOLinker_h
+
+#include "cmBinUtilsLinker.h"
+#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
+#include "cmStateTypes.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsMacOSMachOLinker : public cmBinUtilsLinker
+{
+public:
+  cmBinUtilsMacOSMachOLinker(cmRuntimeDependencyArchive* archive);
+
+  bool Prepare() override;
+
+  bool ScanDependencies(std::string const& file,
+                        cmStateEnums::TargetType type) override;
+
+private:
+  std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool;
+
+  bool ScanDependencies(std::string const& file,
+                        std::string const& executablePath);
+
+  bool GetFileDependencies(std::vector<std::string> const& names,
+                           std::string const& executablePath,
+                           std::string const& loaderPath,
+                           std::vector<std::string> const& rpaths);
+
+  bool ResolveDependency(std::string const& name,
+                         std::string const& executablePath,
+                         std::string const& loaderPath,
+                         std::vector<std::string> const& rpaths,
+                         std::string& path, bool& resolved);
+
+  bool ResolveExecutablePathDependency(std::string const& name,
+                                       std::string const& executablePath,
+                                       std::string& path, bool& resolved);
+
+  bool ResolveLoaderPathDependency(std::string const& name,
+                                   std::string const& loaderPath,
+                                   std::string& path, bool& resolved);
+
+  bool ResolveRPathDependency(std::string const& name,
+                              std::string const& executablePath,
+                              std::string const& loaderPath,
+                              std::vector<std::string> const& rpaths,
+                              std::string& path, bool& resolved);
+};
+
+#endif // cmBinUtilsMacOSMachOLinker_h
diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
new file mode 100644
index 0000000..bab2382
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,100 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h"
+
+#include "cmRuntimeDependencyArchive.h"
+#include "cmUVProcessChain.h"
+
+#include <cmsys/RegularExpression.hxx>
+
+#include <sstream>
+
+cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::
+  cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive)
+  : cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
+  std::string const& file, std::vector<std::string>& libs,
+  std::vector<std::string>& rpaths)
+{
+  std::vector<std::string> command;
+  if (!this->Archive->GetGetRuntimeDependenciesCommand("otool", command)) {
+    this->SetError("Could not find otool");
+    return false;
+  }
+  command.emplace_back("-l");
+  command.emplace_back(file);
+
+  cmUVProcessChainBuilder builder;
+  builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
+    .AddCommand(command);
+
+  auto process = builder.Start();
+  if (!process.Valid()) {
+    std::ostringstream e;
+    e << "Failed to start otool process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  std::string line;
+  static const cmsys::RegularExpression rpathRegex("^ *cmd LC_RPATH$");
+  static const cmsys::RegularExpression loadDylibRegex(
+    "^ *cmd LC_LOAD_DYLIB$");
+  static const cmsys::RegularExpression pathRegex(
+    "^ *path (.*) \\(offset [0-9]+\\)$");
+  static const cmsys::RegularExpression nameRegex(
+    "^ *name (.*) \\(offset [0-9]+\\)$");
+  while (std::getline(*process.OutputStream(), line)) {
+    cmsys::RegularExpressionMatch cmdMatch;
+    if (rpathRegex.find(line.c_str(), cmdMatch)) {
+      if (!std::getline(*process.OutputStream(), line) ||
+          !std::getline(*process.OutputStream(), line)) {
+        this->SetError("Invalid output from otool");
+        return false;
+      }
+
+      cmsys::RegularExpressionMatch pathMatch;
+      if (pathRegex.find(line.c_str(), pathMatch)) {
+        rpaths.push_back(pathMatch.match(1));
+      } else {
+        this->SetError("Invalid output from otool");
+        return false;
+      }
+    } else if (loadDylibRegex.find(line.c_str(), cmdMatch)) {
+      if (!std::getline(*process.OutputStream(), line) ||
+          !std::getline(*process.OutputStream(), line)) {
+        this->SetError("Invalid output from otool");
+        return false;
+      }
+
+      cmsys::RegularExpressionMatch nameMatch;
+      if (nameRegex.find(line.c_str(), nameMatch)) {
+        libs.push_back(nameMatch.match(1));
+      } else {
+        this->SetError("Invalid output from otool");
+        return false;
+      }
+    }
+  }
+
+  if (!process.Wait()) {
+    std::ostringstream e;
+    e << "Failed to wait on otool process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+  auto status = process.GetStatus();
+  if (!status[0] || status[0]->ExitStatus != 0) {
+    std::ostringstream e;
+    e << "Failed to run otool on:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return true;
+}
diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
new file mode 100644
index 0000000..12bcbc1
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
+#define cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
+
+#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool
+  : public cmBinUtilsMacOSMachOGetRuntimeDependenciesTool
+{
+public:
+  cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive);
+
+  bool GetFileInfo(std::string const& file, std::vector<std::string>& libs,
+                   std::vector<std::string>& rpaths) override;
+};
+
+#endif // cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
new file mode 100644
index 0000000..2b35e30
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,67 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmUVProcessChain.h"
+
+#include <cmsys/RegularExpression.hxx>
+
+#include <sstream>
+
+cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::
+  cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive)
+  : cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::GetFileInfo(
+  const std::string& file, std::vector<std::string>& needed)
+{
+  cmUVProcessChainBuilder builder;
+  builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
+
+  std::vector<std::string> command;
+  if (!this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
+    this->SetError("Could not find dumpbin");
+    return false;
+  }
+  command.emplace_back("/dependents");
+  command.push_back(file);
+  builder.AddCommand(command);
+
+  auto process = builder.Start();
+  if (!process.Valid()) {
+    std::ostringstream e;
+    e << "Failed to start dumpbin process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  std::string line;
+  static const cmsys::RegularExpression regex(
+    "^    ([^\n]*\\.[Dd][Ll][Ll])\r$");
+  while (std::getline(*process.OutputStream(), line)) {
+    cmsys::RegularExpressionMatch match;
+    if (regex.find(line.c_str(), match)) {
+      needed.push_back(match.match(1));
+    }
+  }
+
+  if (!process.Wait()) {
+    std::ostringstream e;
+    e << "Failed to wait on dumpbin process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+  auto status = process.GetStatus();
+  if (!status[0] || status[0]->ExitStatus != 0) {
+    std::ostringstream e;
+    e << "Failed to run dumpbin on:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return true;
+}
diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h
new file mode 100644
index 0000000..4c17f8d
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
+#define cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
+
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool
+  : public cmBinUtilsWindowsPEGetRuntimeDependenciesTool
+{
+public:
+  cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive);
+
+  bool GetFileInfo(const std::string& file,
+                   std::vector<std::string>& needed) override;
+};
+
+#endif // cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
new file mode 100644
index 0000000..f5a4431
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,18 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsWindowsPEGetRuntimeDependenciesTool::
+  cmBinUtilsWindowsPEGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive)
+  : Archive(archive)
+{
+}
+
+void cmBinUtilsWindowsPEGetRuntimeDependenciesTool::SetError(
+  const std::string& error)
+{
+  this->Archive->SetError(error);
+}
diff --git a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
new file mode 100644
index 0000000..e9e402b
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
@@ -0,0 +1,28 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
+#define cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPEGetRuntimeDependenciesTool
+{
+public:
+  cmBinUtilsWindowsPEGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive);
+  virtual ~cmBinUtilsWindowsPEGetRuntimeDependenciesTool() = default;
+
+  virtual bool GetFileInfo(const std::string& file,
+                           std::vector<std::string>& needed) = 0;
+
+protected:
+  cmRuntimeDependencyArchive* Archive;
+
+  void SetError(const std::string& error);
+};
+
+#endif // cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsWindowsPELinker.cxx b/Source/cmBinUtilsWindowsPELinker.cxx
new file mode 100644
index 0000000..31602c4
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPELinker.cxx
@@ -0,0 +1,122 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsWindowsPELinker.h"
+
+#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
+#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmSystemTools.h"
+
+#include <sstream>
+#include <vector>
+
+#include "cm_memory.hxx"
+
+#ifdef _WIN32
+#  include <windows.h>
+#endif
+
+cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
+  cmRuntimeDependencyArchive* archive)
+  : cmBinUtilsLinker(archive)
+{
+}
+
+bool cmBinUtilsWindowsPELinker::Prepare()
+{
+  std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
+  if (tool.empty()) {
+    std::vector<std::string> command;
+    if (this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
+      tool = "dumpbin";
+    } else {
+      tool = "objdump";
+    }
+  }
+  if (tool == "dumpbin") {
+    this->Tool =
+      cm::make_unique<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool>(
+        this->Archive);
+  } else if (tool == "objdump") {
+    this->Tool =
+      cm::make_unique<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool>(
+        this->Archive);
+  } else {
+    std::ostringstream e;
+    e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return true;
+}
+
+bool cmBinUtilsWindowsPELinker::ScanDependencies(
+  std::string const& file, cmStateEnums::TargetType /* unused */)
+{
+  std::vector<std::string> needed;
+  if (!this->Tool->GetFileInfo(file, needed)) {
+    return false;
+  }
+  for (auto& n : needed) {
+    n = cmSystemTools::LowerCase(n);
+  }
+  std::string origin = cmSystemTools::GetFilenamePath(file);
+
+  for (auto const& lib : needed) {
+    if (!this->Archive->IsPreExcluded(lib)) {
+      std::string path;
+      bool resolved = false;
+      if (!this->ResolveDependency(lib, origin, path, resolved)) {
+        return false;
+      }
+      if (resolved) {
+        if (!this->Archive->IsPostExcluded(path)) {
+          bool unique;
+          this->Archive->AddResolvedPath(lib, path, unique);
+          if (unique &&
+              !this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) {
+            return false;
+          }
+        }
+      } else {
+        this->Archive->AddUnresolvedPath(lib);
+      }
+    }
+  }
+
+  return true;
+}
+
+bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string const& name,
+                                                  std::string const& origin,
+                                                  std::string& path,
+                                                  bool& resolved)
+{
+  auto dirs = this->Archive->GetSearchDirectories();
+
+#ifdef _WIN32
+  char buf[MAX_PATH];
+  unsigned int len;
+  if ((len = GetWindowsDirectoryA(buf, MAX_PATH)) > 0) {
+    dirs.insert(dirs.begin(), std::string(buf, len));
+  }
+  if ((len = GetSystemDirectoryA(buf, MAX_PATH)) > 0) {
+    dirs.insert(dirs.begin(), std::string(buf, len));
+  }
+#endif
+
+  dirs.insert(dirs.begin(), origin);
+
+  for (auto const& searchPath : dirs) {
+    path = searchPath + '/' + name;
+    if (cmSystemTools::PathExists(path)) {
+      resolved = true;
+      return true;
+    }
+  }
+
+  resolved = false;
+  return true;
+}
diff --git a/Source/cmBinUtilsWindowsPELinker.h b/Source/cmBinUtilsWindowsPELinker.h
new file mode 100644
index 0000000..8d2bf4b
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPELinker.h
@@ -0,0 +1,33 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsWindowsPELinker_h
+#define cmBinUtilsWindowsPELinker_h
+
+#include "cmBinUtilsLinker.h"
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+#include "cmStateTypes.h"
+
+#include <memory>
+#include <string>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPELinker : public cmBinUtilsLinker
+{
+public:
+  cmBinUtilsWindowsPELinker(cmRuntimeDependencyArchive* archive);
+
+  bool Prepare() override;
+
+  bool ScanDependencies(std::string const& file,
+                        cmStateEnums::TargetType type) override;
+
+private:
+  std::unique_ptr<cmBinUtilsWindowsPEGetRuntimeDependenciesTool> Tool;
+
+  bool ResolveDependency(std::string const& name, std::string const& origin,
+                         std::string& path, bool& resolved);
+};
+
+#endif // cmBinUtilsWindowsPELinker_h
diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
new file mode 100644
index 0000000..1f27003
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,67 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmUVProcessChain.h"
+
+#include <cmsys/RegularExpression.hxx>
+
+#include <sstream>
+
+cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::
+  cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive)
+  : cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo(
+  const std::string& file, std::vector<std::string>& needed)
+{
+  cmUVProcessChainBuilder builder;
+  builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
+
+  std::vector<std::string> command;
+  if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) {
+    this->SetError("Could not find objdump");
+    return false;
+  }
+  command.emplace_back("-p");
+  command.push_back(file);
+  builder.AddCommand(command);
+
+  auto process = builder.Start();
+  if (!process.Valid()) {
+    std::ostringstream e;
+    e << "Failed to start objdump process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  std::string line;
+  static const cmsys::RegularExpression regex(
+    "^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])\r$");
+  while (std::getline(*process.OutputStream(), line)) {
+    cmsys::RegularExpressionMatch match;
+    if (regex.find(line.c_str(), match)) {
+      needed.push_back(match.match(1));
+    }
+  }
+
+  if (!process.Wait()) {
+    std::ostringstream e;
+    e << "Failed to wait on objdump process for:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+  auto status = process.GetStatus();
+  if (!status[0] || status[0]->ExitStatus != 0) {
+    std::ostringstream e;
+    e << "Failed to run objdump on:\n  " << file;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return true;
+}
diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
new file mode 100644
index 0000000..1d1a5b0
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
+#define cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
+
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool
+  : public cmBinUtilsWindowsPEGetRuntimeDependenciesTool
+{
+public:
+  cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool(
+    cmRuntimeDependencyArchive* archive);
+
+  bool GetFileInfo(const std::string& file,
+                   std::vector<std::string>& needed) override;
+};
+
+#endif // cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
diff --git a/Source/cmBreakCommand.h b/Source/cmBreakCommand.h
index 3b18567..e6f218e 100644
--- a/Source/cmBreakCommand.h
+++ b/Source/cmBreakCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmBreakCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmBreakCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index 428a0b2..e9e1d49 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -92,7 +92,7 @@
     this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand(
       target, configuration, "", this->Makefile->IgnoreErrorsCMP0061());
 
-  this->Makefile->AddDefinition(variable, makecommand.c_str());
+  this->Makefile->AddDefinition(variable, makecommand);
 
   return true;
 }
diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h
index e0529a4..d373103 100644
--- a/Source/cmBuildCommand.h
+++ b/Source/cmBuildCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmBuildCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmBuildCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h
index 4bb72d1..bd2d146 100644
--- a/Source/cmBuildNameCommand.h
+++ b/Source/cmBuildNameCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmBuildNameCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmBuildNameCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmBuildNameCommand>();
+  }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 };
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 54f08bb..b4cd2a5 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -55,7 +55,7 @@
     result_list += value;
   }
 
-  this->Makefile->AddDefinition(variable, result_list.c_str());
+  this->Makefile->AddDefinition(variable, result_list);
 
   return true;
 }
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
index b871641..8ea2d55 100644
--- a/Source/cmCMakeHostSystemInformationCommand.h
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -28,9 +30,9 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    return new cmCMakeHostSystemInformationCommand;
+    return cm::make_unique<cmCMakeHostSystemInformationCommand>();
   }
 
   /**
diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx
index 4b4bca2..f2eae38 100644
--- a/Source/cmCMakeMinimumRequired.cxx
+++ b/Source/cmCMakeMinimumRequired.cxx
@@ -61,8 +61,7 @@
   }
 
   // Save the required version string.
-  this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
-                                version_min.c_str());
+  this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION", version_min);
 
   // Get the current version number.
   unsigned int current_major = cmVersion::GetMajorVersion();
diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h
index f9b61e1..3881133 100644
--- a/Source/cmCMakeMinimumRequired.h
+++ b/Source/cmCMakeMinimumRequired.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmCMakeMinimumRequired; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmCMakeMinimumRequired>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index 8da5ef7..ce046fc 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -209,8 +209,7 @@
   }
 
   // Lookup the policy warning.
-  this->Makefile->AddDefinition(var,
-                                cmPolicies::GetPolicyWarning(pid).c_str());
+  this->Makefile->AddDefinition(var, cmPolicies::GetPolicyWarning(pid));
 
   return true;
 }
diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h
index cca1406..919402c 100644
--- a/Source/cmCMakePolicyCommand.h
+++ b/Source/cmCMakePolicyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmCMakePolicyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmCMakePolicyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 255a8e6..80ca898 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -65,8 +65,10 @@
 
 void CCONV cmAddDefinition(void* arg, const char* name, const char* value)
 {
-  cmMakefile* mf = static_cast<cmMakefile*>(arg);
-  mf->AddDefinition(name, value);
+  if (value) {
+    cmMakefile* mf = static_cast<cmMakefile*>(arg);
+    mf->AddDefinition(name, value);
+  }
 }
 
 /* Add a definition to this makefile and the global cmake cache. */
@@ -421,7 +423,7 @@
     // Assume all arguments are quoted.
     lff.Arguments.emplace_back(args[i], cmListFileArgument::Quoted, 0);
   }
-  cmExecutionStatus status;
+  cmExecutionStatus status(*mf);
   return mf->ExecuteCommand(lff, status);
 }
 
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index d1226c3..026250d 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -15,7 +15,6 @@
 #include <ctype.h>
 #include <iostream>
 #include <map>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,6 +29,8 @@
 #  include <unistd.h> // IWYU pragma: keep
 #endif
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmCTestBuildAndTestHandler.h"
 #include "cmCTestBuildHandler.h"
@@ -51,6 +52,7 @@
 #include "cmState.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 #include "cmVersionConfig.h"
@@ -1098,9 +1100,10 @@
   cmProcessOutput processOutput(encoding);
   std::string strdata;
   cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
-             "   Each . represents " << tick_len << " bytes of output"
-                                     << std::endl
-                                     << "    " << std::flush);
+             "   Each . represents " << tick_len
+                                     << " bytes of output\n"
+                                        "    "
+                                     << std::flush);
   while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
     processOutput.DecodeText(data, length, strdata);
     for (char& cc : strdata) {
@@ -1115,8 +1118,7 @@
       if (tick % tick_line_len == 0 && tick > 0) {
         cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
                    "  Size: " << int((double(output.size()) / 1024.0) + 1)
-                              << "K" << std::endl
-                              << "    " << std::flush);
+                              << "K\n    " << std::flush);
       }
     }
     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
@@ -1324,18 +1326,14 @@
     if (output) {
       *output += outerr;
     }
-    cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
-               outerr << std::endl
-                      << std::flush);
+    cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
   } else if (result == cmsysProcess_State_Error) {
     std::string outerr = "\n*** ERROR executing: ";
     outerr += cmsysProcess_GetErrorString(cp);
     if (output) {
       *output += outerr;
     }
-    cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
-               outerr << std::endl
-                      << std::flush);
+    cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
   }
   cmsysProcess_Delete(cp);
 
@@ -1967,7 +1965,7 @@
   if (this->CheckArgument(arg, "-N", "--show-only")) {
     this->Impl->ShowOnly = true;
   }
-  if (cmSystemTools::StringStartsWith(arg.c_str(), "--show-only=")) {
+  if (cmHasLiteralPrefix(arg, "--show-only=")) {
     this->Impl->ShowOnly = true;
 
     // Check if a specific format is requested. Defaults to human readable
@@ -2229,7 +2227,7 @@
     // attempts are simply ignored since previous ctest versions ignore
     // this too. (As well as many other unknown command line args.)
     //
-    if (arg != "-D" && cmSystemTools::StringStartsWith(arg.c_str(), "-D")) {
+    if (arg != "-D" && cmHasLiteralPrefix(arg, "-D")) {
       std::string input = arg.substr(2);
       this->AddVariableDefinition(input);
     }
@@ -3077,11 +3075,11 @@
         } else {
           *this->Impl->OutputLogFile << cmCTestStringLogType[logType];
         }
-        *this->Impl->OutputLogFile << "] " << std::endl << std::flush;
+        *this->Impl->OutputLogFile << "] " << std::endl;
       }
       *this->Impl->OutputLogFile << msg << std::flush;
       if (logType != this->Impl->OutputLogFileLastTag) {
-        *this->Impl->OutputLogFile << std::endl << std::flush;
+        *this->Impl->OutputLogFile << std::endl;
         this->Impl->OutputLogFileLastTag = logType;
       }
     }
@@ -3194,7 +3192,7 @@
   if (!process_output.empty()) {
     test_outputs.append(process_output.data(), process_output.size());
   }
-  cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl << std::flush);
+  cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl);
 }
 
 bool cmCTest::CompressString(std::string& str)
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index d300c33..7f66378 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -10,7 +10,7 @@
 
 #include <chrono>
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <string>
 #include <time.h>
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 358f095..e8fc350 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -620,7 +620,7 @@
 
 std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
 {
-  return this->Properties.GetPropertyList();
+  return this->Properties.GetKeys();
 }
 
 const char* cmCacheManager::CacheEntry::GetProperty(
diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx
index f7a2244..9e152ff 100644
--- a/Source/cmCallVisualStudioMacro.cxx
+++ b/Source/cmCallVisualStudioMacro.cxx
@@ -4,6 +4,7 @@
 
 #include <sstream>
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #if defined(_MSC_VER)
@@ -328,8 +329,7 @@
   if (SUCCEEDED(hr)) {
     std::map<std::string, IUnknownPtr>::iterator it;
     for (it = mrot.begin(); it != mrot.end(); ++it) {
-      if (cmSystemTools::StringStartsWith(it->first.c_str(),
-                                          "!VisualStudio.DTE.")) {
+      if (cmHasLiteralPrefix(it->first, "!VisualStudio.DTE.")) {
         IDispatchPtr disp(it->second);
         if (disp != (IDispatch*)0) {
           std::string slnName;
diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx
index d349c91..0c2734e 100644
--- a/Source/cmCommand.cxx
+++ b/Source/cmCommand.cxx
@@ -2,11 +2,19 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCommand.h"
 
+#include <utility>
+
+#include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 
-class cmExecutionStatus;
 struct cmListFileArgument;
 
+void cmCommand::SetExecutionStatus(cmExecutionStatus* status)
+{
+  this->Status = status;
+  this->Makefile = &status->GetMakefile();
+}
+
 bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
                                   cmExecutionStatus& status)
 {
@@ -19,15 +27,33 @@
   return this->InitialPass(expandedArguments, status);
 }
 
-const char* cmCommand::GetError()
-{
-  if (this->Error.empty()) {
-    return "unknown error.";
-  }
-  return this->Error.c_str();
-}
-
 void cmCommand::SetError(const std::string& e)
 {
-  this->Error = e;
+  this->Status->SetError(e);
+}
+
+cmLegacyCommandWrapper::cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd)
+  : Command(std::move(cmd))
+{
+}
+
+cmLegacyCommandWrapper::cmLegacyCommandWrapper(
+  cmLegacyCommandWrapper const& other)
+  : Command(other.Command->Clone())
+{
+}
+
+cmLegacyCommandWrapper& cmLegacyCommandWrapper::operator=(
+  cmLegacyCommandWrapper const& other)
+{
+  this->Command = other.Command->Clone();
+  return *this;
+}
+
+bool cmLegacyCommandWrapper::operator()(
+  std::vector<cmListFileArgument> const& args, cmExecutionStatus& status) const
+{
+  auto cmd = this->Command->Clone();
+  cmd->SetExecutionStatus(&status);
+  return cmd->InvokeInitialPass(args, status);
 }
diff --git a/Source/cmCommand.h b/Source/cmCommand.h
index 9ccd773..bcb178d 100644
--- a/Source/cmCommand.h
+++ b/Source/cmCommand.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -41,16 +42,18 @@
   /**
    * Specify the makefile.
    */
-  void SetMakefile(cmMakefile* m) { this->Makefile = m; }
   cmMakefile* GetMakefile() { return this->Makefile; }
 
+  void SetExecutionStatus(cmExecutionStatus* s);
+  cmExecutionStatus* GetExecutionStatus() { return this->Status; };
+
   /**
    * This is called by the cmMakefile when the command is first
    * encountered in the CMakeLists.txt file.  It expands the command's
    * arguments and then invokes the InitialPass.
    */
-  virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                                 cmExecutionStatus& status);
+  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+                         cmExecutionStatus& status);
 
   /**
    * This is called when the command is first encountered in
@@ -60,27 +63,9 @@
                            cmExecutionStatus&) = 0;
 
   /**
-   * This is called at the end after all the information
-   * specified by the command is accumulated. Most commands do
-   * not implement this method.  At this point, reading and
-   * writing to the cache can be done.
-   */
-  virtual void FinalPass() {}
-
-  /**
-   * Does this command have a final pass?  Query after InitialPass.
-   */
-  virtual bool HasFinalPass() const { return false; }
-
-  /**
    * This is a virtual constructor for the command.
    */
-  virtual cmCommand* Clone() = 0;
-
-  /**
-   * Return the last error string.
-   */
-  const char* GetError();
+  virtual std::unique_ptr<cmCommand> Clone() = 0;
 
   /**
    * Set the error message
@@ -91,7 +76,25 @@
   cmMakefile* Makefile = nullptr;
 
 private:
-  std::string Error;
+  cmExecutionStatus* Status = nullptr;
+};
+
+class cmLegacyCommandWrapper
+{
+public:
+  explicit cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd);
+
+  cmLegacyCommandWrapper(cmLegacyCommandWrapper const& other);
+  cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper const& other);
+
+  cmLegacyCommandWrapper(cmLegacyCommandWrapper&&) = default;
+  cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper&&) = default;
+
+  bool operator()(std::vector<cmListFileArgument> const& args,
+                  cmExecutionStatus& status) const;
+
+private:
+  std::unique_ptr<cmCommand> Command;
 };
 
 #endif
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 63c5397..f351ff8 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -1,5 +1,8 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cm_memory.hxx"
+
 #include "cmCommands.h"
 #include "cmPolicies.h"
 #include "cmState.h"
@@ -17,6 +20,7 @@
 #include "cmBuildCommand.h"
 #include "cmCMakeMinimumRequired.h"
 #include "cmCMakePolicyCommand.h"
+#include "cmCommand.h"
 #include "cmConfigureFileCommand.h"
 #include "cmContinueCommand.h"
 #include "cmCreateTestSourceList.h"
@@ -112,52 +116,64 @@
 
 void GetScriptingCommands(cmState* state)
 {
-  state->AddBuiltinCommand("break", new cmBreakCommand);
+  state->AddBuiltinCommand("break", cm::make_unique<cmBreakCommand>());
   state->AddBuiltinCommand("cmake_minimum_required",
-                           new cmCMakeMinimumRequired);
-  state->AddBuiltinCommand("cmake_policy", new cmCMakePolicyCommand);
-  state->AddBuiltinCommand("configure_file", new cmConfigureFileCommand);
-  state->AddBuiltinCommand("continue", new cmContinueCommand);
-  state->AddBuiltinCommand("exec_program", new cmExecProgramCommand);
-  state->AddBuiltinCommand("execute_process", new cmExecuteProcessCommand);
-  state->AddBuiltinCommand("file", new cmFileCommand);
-  state->AddBuiltinCommand("find_file", new cmFindFileCommand);
-  state->AddBuiltinCommand("find_library", new cmFindLibraryCommand);
-  state->AddBuiltinCommand("find_package", new cmFindPackageCommand);
-  state->AddBuiltinCommand("find_path", new cmFindPathCommand);
-  state->AddBuiltinCommand("find_program", new cmFindProgramCommand);
-  state->AddBuiltinCommand("foreach", new cmForEachCommand);
-  state->AddBuiltinCommand("function", new cmFunctionCommand);
+                           cm::make_unique<cmCMakeMinimumRequired>());
+  state->AddBuiltinCommand("cmake_policy",
+                           cm::make_unique<cmCMakePolicyCommand>());
+  state->AddBuiltinCommand("configure_file",
+                           cm::make_unique<cmConfigureFileCommand>());
+  state->AddBuiltinCommand("continue", cm::make_unique<cmContinueCommand>());
+  state->AddBuiltinCommand("exec_program",
+                           cm::make_unique<cmExecProgramCommand>());
+  state->AddBuiltinCommand("execute_process",
+                           cm::make_unique<cmExecuteProcessCommand>());
+  state->AddBuiltinCommand("file", cm::make_unique<cmFileCommand>());
+  state->AddBuiltinCommand("find_file", cm::make_unique<cmFindFileCommand>());
+  state->AddBuiltinCommand("find_library",
+                           cm::make_unique<cmFindLibraryCommand>());
+  state->AddBuiltinCommand("find_package",
+                           cm::make_unique<cmFindPackageCommand>());
+  state->AddBuiltinCommand("find_path", cm::make_unique<cmFindPathCommand>());
+  state->AddBuiltinCommand("find_program",
+                           cm::make_unique<cmFindProgramCommand>());
+  state->AddBuiltinCommand("foreach", cm::make_unique<cmForEachCommand>());
+  state->AddBuiltinCommand("function", cm::make_unique<cmFunctionCommand>());
   state->AddBuiltinCommand("get_cmake_property",
-                           new cmGetCMakePropertyCommand);
+                           cm::make_unique<cmGetCMakePropertyCommand>());
   state->AddBuiltinCommand("get_directory_property",
-                           new cmGetDirectoryPropertyCommand);
+                           cm::make_unique<cmGetDirectoryPropertyCommand>());
   state->AddBuiltinCommand("get_filename_component",
-                           new cmGetFilenameComponentCommand);
-  state->AddBuiltinCommand("get_property", new cmGetPropertyCommand);
-  state->AddBuiltinCommand("if", new cmIfCommand);
-  state->AddBuiltinCommand("include", new cmIncludeCommand);
-  state->AddBuiltinCommand("include_guard", new cmIncludeGuardCommand);
-  state->AddBuiltinCommand("list", new cmListCommand);
-  state->AddBuiltinCommand("macro", new cmMacroCommand);
-  state->AddBuiltinCommand("make_directory", new cmMakeDirectoryCommand);
-  state->AddBuiltinCommand("mark_as_advanced", new cmMarkAsAdvancedCommand);
-  state->AddBuiltinCommand("math", new cmMathCommand);
-  state->AddBuiltinCommand("message", new cmMessageCommand);
-  state->AddBuiltinCommand("option", new cmOptionCommand);
+                           cm::make_unique<cmGetFilenameComponentCommand>());
+  state->AddBuiltinCommand("get_property",
+                           cm::make_unique<cmGetPropertyCommand>());
+  state->AddBuiltinCommand("if", cmIfCommand);
+  state->AddBuiltinCommand("include", cm::make_unique<cmIncludeCommand>());
+  state->AddBuiltinCommand("include_guard",
+                           cm::make_unique<cmIncludeGuardCommand>());
+  state->AddBuiltinCommand("list", cm::make_unique<cmListCommand>());
+  state->AddBuiltinCommand("macro", cm::make_unique<cmMacroCommand>());
+  state->AddBuiltinCommand("make_directory",
+                           cm::make_unique<cmMakeDirectoryCommand>());
+  state->AddBuiltinCommand("mark_as_advanced",
+                           cm::make_unique<cmMarkAsAdvancedCommand>());
+  state->AddBuiltinCommand("math", cm::make_unique<cmMathCommand>());
+  state->AddBuiltinCommand("message", cm::make_unique<cmMessageCommand>());
+  state->AddBuiltinCommand("option", cm::make_unique<cmOptionCommand>());
   state->AddBuiltinCommand("cmake_parse_arguments",
-                           new cmParseArgumentsCommand);
-  state->AddBuiltinCommand("return", new cmReturnCommand);
+                           cm::make_unique<cmParseArgumentsCommand>());
+  state->AddBuiltinCommand("return", cmReturnCommand);
   state->AddBuiltinCommand("separate_arguments",
-                           new cmSeparateArgumentsCommand);
-  state->AddBuiltinCommand("set", new cmSetCommand);
+                           cm::make_unique<cmSeparateArgumentsCommand>());
+  state->AddBuiltinCommand("set", cm::make_unique<cmSetCommand>());
   state->AddBuiltinCommand("set_directory_properties",
-                           new cmSetDirectoryPropertiesCommand);
-  state->AddBuiltinCommand("set_property", new cmSetPropertyCommand);
-  state->AddBuiltinCommand("site_name", new cmSiteNameCommand);
-  state->AddBuiltinCommand("string", new cmStringCommand);
-  state->AddBuiltinCommand("unset", new cmUnsetCommand);
-  state->AddBuiltinCommand("while", new cmWhileCommand);
+                           cm::make_unique<cmSetDirectoryPropertiesCommand>());
+  state->AddBuiltinCommand("set_property",
+                           cm::make_unique<cmSetPropertyCommand>());
+  state->AddBuiltinCommand("site_name", cm::make_unique<cmSiteNameCommand>());
+  state->AddBuiltinCommand("string", cm::make_unique<cmStringCommand>());
+  state->AddBuiltinCommand("unset", cm::make_unique<cmUnsetCommand>());
+  state->AddBuiltinCommand("while", cmWhileCommand);
 
   state->AddUnexpectedCommand(
     "else",
@@ -195,17 +211,21 @@
     "match the opening WHILE command.");
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-  state->AddBuiltinCommand("cmake_host_system_information",
-                           new cmCMakeHostSystemInformationCommand);
-  state->AddBuiltinCommand("remove", new cmRemoveCommand);
-  state->AddBuiltinCommand("variable_watch", new cmVariableWatchCommand);
-  state->AddBuiltinCommand("write_file", new cmWriteFileCommand);
+  state->AddBuiltinCommand(
+    "cmake_host_system_information",
+    cm::make_unique<cmCMakeHostSystemInformationCommand>());
+  state->AddBuiltinCommand("remove", cm::make_unique<cmRemoveCommand>());
+  state->AddBuiltinCommand("variable_watch",
+                           cm::make_unique<cmVariableWatchCommand>());
+  state->AddBuiltinCommand("write_file",
+                           cm::make_unique<cmWriteFileCommand>());
 
   state->AddDisallowedCommand(
-    "build_name", new cmBuildNameCommand, cmPolicies::CMP0036,
+    "build_name", cm::make_unique<cmBuildNameCommand>(), cmPolicies::CMP0036,
     "The build_name command should not be called; see CMP0036.");
   state->AddDisallowedCommand(
-    "use_mangled_mesa", new cmUseMangledMesaCommand, cmPolicies::CMP0030,
+    "use_mangled_mesa", cm::make_unique<cmUseMangledMesaCommand>(),
+    cmPolicies::CMP0030,
     "The use_mangled_mesa command should not be called; see CMP0030.");
 
 #endif
@@ -214,100 +234,130 @@
 void GetProjectCommands(cmState* state)
 {
   state->AddBuiltinCommand("add_custom_command",
-                           new cmAddCustomCommandCommand);
-  state->AddBuiltinCommand("add_custom_target", new cmAddCustomTargetCommand);
-  state->AddBuiltinCommand("add_definitions", new cmAddDefinitionsCommand);
-  state->AddBuiltinCommand("add_dependencies", new cmAddDependenciesCommand);
-  state->AddBuiltinCommand("add_executable", new cmAddExecutableCommand);
-  state->AddBuiltinCommand("add_library", new cmAddLibraryCommand);
-  state->AddBuiltinCommand("add_subdirectory", new cmAddSubDirectoryCommand);
-  state->AddBuiltinCommand("add_test", new cmAddTestCommand);
-  state->AddBuiltinCommand("build_command", new cmBuildCommand);
+                           cm::make_unique<cmAddCustomCommandCommand>());
+  state->AddBuiltinCommand("add_custom_target",
+                           cm::make_unique<cmAddCustomTargetCommand>());
+  state->AddBuiltinCommand("add_definitions",
+                           cm::make_unique<cmAddDefinitionsCommand>());
+  state->AddBuiltinCommand("add_dependencies",
+                           cm::make_unique<cmAddDependenciesCommand>());
+  state->AddBuiltinCommand("add_executable",
+                           cm::make_unique<cmAddExecutableCommand>());
+  state->AddBuiltinCommand("add_library",
+                           cm::make_unique<cmAddLibraryCommand>());
+  state->AddBuiltinCommand("add_subdirectory",
+                           cm::make_unique<cmAddSubDirectoryCommand>());
+  state->AddBuiltinCommand("add_test", cm::make_unique<cmAddTestCommand>());
+  state->AddBuiltinCommand("build_command", cm::make_unique<cmBuildCommand>());
   state->AddBuiltinCommand("create_test_sourcelist",
-                           new cmCreateTestSourceList);
-  state->AddBuiltinCommand("define_property", new cmDefinePropertyCommand);
-  state->AddBuiltinCommand("enable_language", new cmEnableLanguageCommand);
-  state->AddBuiltinCommand("enable_testing", new cmEnableTestingCommand);
+                           cm::make_unique<cmCreateTestSourceList>());
+  state->AddBuiltinCommand("define_property",
+                           cm::make_unique<cmDefinePropertyCommand>());
+  state->AddBuiltinCommand("enable_language",
+                           cm::make_unique<cmEnableLanguageCommand>());
+  state->AddBuiltinCommand("enable_testing", cmEnableTestingCommand);
   state->AddBuiltinCommand("get_source_file_property",
-                           new cmGetSourceFilePropertyCommand);
+                           cm::make_unique<cmGetSourceFilePropertyCommand>());
   state->AddBuiltinCommand("get_target_property",
-                           new cmGetTargetPropertyCommand);
-  state->AddBuiltinCommand("get_test_property", new cmGetTestPropertyCommand);
+                           cm::make_unique<cmGetTargetPropertyCommand>());
+  state->AddBuiltinCommand("get_test_property",
+                           cm::make_unique<cmGetTestPropertyCommand>());
   state->AddBuiltinCommand("include_directories",
-                           new cmIncludeDirectoryCommand);
-  state->AddBuiltinCommand("include_regular_expression",
-                           new cmIncludeRegularExpressionCommand);
-  state->AddBuiltinCommand("install", new cmInstallCommand);
-  state->AddBuiltinCommand("install_files", new cmInstallFilesCommand);
-  state->AddBuiltinCommand("install_targets", new cmInstallTargetsCommand);
-  state->AddBuiltinCommand("link_directories", new cmLinkDirectoriesCommand);
-  state->AddBuiltinCommand("project", new cmProjectCommand);
-  state->AddBuiltinCommand("set_source_files_properties",
-                           new cmSetSourceFilesPropertiesCommand);
+                           cm::make_unique<cmIncludeDirectoryCommand>());
+  state->AddBuiltinCommand(
+    "include_regular_expression",
+    cm::make_unique<cmIncludeRegularExpressionCommand>());
+  state->AddBuiltinCommand("install", cm::make_unique<cmInstallCommand>());
+  state->AddBuiltinCommand("install_files",
+                           cm::make_unique<cmInstallFilesCommand>());
+  state->AddBuiltinCommand("install_targets",
+                           cm::make_unique<cmInstallTargetsCommand>());
+  state->AddBuiltinCommand("link_directories",
+                           cm::make_unique<cmLinkDirectoriesCommand>());
+  state->AddBuiltinCommand("project", cm::make_unique<cmProjectCommand>());
+  state->AddBuiltinCommand(
+    "set_source_files_properties",
+    cm::make_unique<cmSetSourceFilesPropertiesCommand>());
   state->AddBuiltinCommand("set_target_properties",
-                           new cmSetTargetPropertiesCommand);
+                           cm::make_unique<cmSetTargetPropertiesCommand>());
   state->AddBuiltinCommand("set_tests_properties",
-                           new cmSetTestsPropertiesCommand);
-  state->AddBuiltinCommand("subdirs", new cmSubdirCommand);
-  state->AddBuiltinCommand("target_compile_definitions",
-                           new cmTargetCompileDefinitionsCommand);
+                           cm::make_unique<cmSetTestsPropertiesCommand>());
+  state->AddBuiltinCommand("subdirs", cm::make_unique<cmSubdirCommand>());
+  state->AddBuiltinCommand(
+    "target_compile_definitions",
+    cm::make_unique<cmTargetCompileDefinitionsCommand>());
   state->AddBuiltinCommand("target_compile_features",
-                           new cmTargetCompileFeaturesCommand);
+                           cm::make_unique<cmTargetCompileFeaturesCommand>());
   state->AddBuiltinCommand("target_compile_options",
-                           new cmTargetCompileOptionsCommand);
-  state->AddBuiltinCommand("target_include_directories",
-                           new cmTargetIncludeDirectoriesCommand);
+                           cm::make_unique<cmTargetCompileOptionsCommand>());
+  state->AddBuiltinCommand(
+    "target_include_directories",
+    cm::make_unique<cmTargetIncludeDirectoriesCommand>());
   state->AddBuiltinCommand("target_link_libraries",
-                           new cmTargetLinkLibrariesCommand);
-  state->AddBuiltinCommand("target_sources", new cmTargetSourcesCommand);
-  state->AddBuiltinCommand("try_compile", new cmTryCompileCommand);
-  state->AddBuiltinCommand("try_run", new cmTryRunCommand);
+                           cm::make_unique<cmTargetLinkLibrariesCommand>());
+  state->AddBuiltinCommand("target_sources",
+                           cm::make_unique<cmTargetSourcesCommand>());
+  state->AddBuiltinCommand("try_compile",
+                           cm::make_unique<cmTryCompileCommand>());
+  state->AddBuiltinCommand("try_run", cm::make_unique<cmTryRunCommand>());
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   state->AddBuiltinCommand("add_compile_definitions",
-                           new cmAddCompileDefinitionsCommand);
+                           cm::make_unique<cmAddCompileDefinitionsCommand>());
   state->AddBuiltinCommand("add_compile_options",
-                           new cmAddCompileOptionsCommand);
+                           cm::make_unique<cmAddCompileOptionsCommand>());
   state->AddBuiltinCommand("aux_source_directory",
-                           new cmAuxSourceDirectoryCommand);
-  state->AddBuiltinCommand("export", new cmExportCommand);
-  state->AddBuiltinCommand("fltk_wrap_ui", new cmFLTKWrapUICommand);
-  state->AddBuiltinCommand("include_external_msproject",
-                           new cmIncludeExternalMSProjectCommand);
-  state->AddBuiltinCommand("install_programs", new cmInstallProgramsCommand);
-  state->AddBuiltinCommand("add_link_options", new cmAddLinkOptionsCommand);
-  state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand);
+                           cm::make_unique<cmAuxSourceDirectoryCommand>());
+  state->AddBuiltinCommand("export", cm::make_unique<cmExportCommand>());
+  state->AddBuiltinCommand("fltk_wrap_ui",
+                           cm::make_unique<cmFLTKWrapUICommand>());
+  state->AddBuiltinCommand(
+    "include_external_msproject",
+    cm::make_unique<cmIncludeExternalMSProjectCommand>());
+  state->AddBuiltinCommand("install_programs",
+                           cm::make_unique<cmInstallProgramsCommand>());
+  state->AddBuiltinCommand("add_link_options",
+                           cm::make_unique<cmAddLinkOptionsCommand>());
+  state->AddBuiltinCommand("link_libraries",
+                           cm::make_unique<cmLinkLibrariesCommand>());
   state->AddBuiltinCommand("target_link_options",
-                           new cmTargetLinkOptionsCommand);
+                           cm::make_unique<cmTargetLinkOptionsCommand>());
   state->AddBuiltinCommand("target_link_directories",
-                           new cmTargetLinkDirectoriesCommand);
-  state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand);
-  state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand);
-  state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand);
+                           cm::make_unique<cmTargetLinkDirectoriesCommand>());
+  state->AddBuiltinCommand("load_cache",
+                           cm::make_unique<cmLoadCacheCommand>());
+  state->AddBuiltinCommand("qt_wrap_cpp",
+                           cm::make_unique<cmQTWrapCPPCommand>());
+  state->AddBuiltinCommand("qt_wrap_ui", cm::make_unique<cmQTWrapUICommand>());
   state->AddBuiltinCommand("remove_definitions",
-                           new cmRemoveDefinitionsCommand);
-  state->AddBuiltinCommand("source_group", new cmSourceGroupCommand);
+                           cm::make_unique<cmRemoveDefinitionsCommand>());
+  state->AddBuiltinCommand("source_group",
+                           cm::make_unique<cmSourceGroupCommand>());
 
   state->AddDisallowedCommand(
-    "export_library_dependencies", new cmExportLibraryDependenciesCommand,
-    cmPolicies::CMP0033,
+    "export_library_dependencies",
+    cm::make_unique<cmExportLibraryDependenciesCommand>(), cmPolicies::CMP0033,
     "The export_library_dependencies command should not be called; "
     "see CMP0033.");
   state->AddDisallowedCommand(
-    "load_command", new cmLoadCommandCommand, cmPolicies::CMP0031,
+    "load_command", cm::make_unique<cmLoadCommandCommand>(),
+    cmPolicies::CMP0031,
     "The load_command command should not be called; see CMP0031.");
   state->AddDisallowedCommand(
-    "output_required_files", new cmOutputRequiredFilesCommand,
+    "output_required_files", cm::make_unique<cmOutputRequiredFilesCommand>(),
     cmPolicies::CMP0032,
     "The output_required_files command should not be called; see CMP0032.");
   state->AddDisallowedCommand(
-    "subdir_depends", new cmSubdirDependsCommand, cmPolicies::CMP0029,
+    "subdir_depends", cm::make_unique<cmSubdirDependsCommand>(),
+    cmPolicies::CMP0029,
     "The subdir_depends command should not be called; see CMP0029.");
   state->AddDisallowedCommand(
-    "utility_source", new cmUtilitySourceCommand, cmPolicies::CMP0034,
+    "utility_source", cm::make_unique<cmUtilitySourceCommand>(),
+    cmPolicies::CMP0034,
     "The utility_source command should not be called; see CMP0034.");
   state->AddDisallowedCommand(
-    "variable_requires", new cmVariableRequiresCommand, cmPolicies::CMP0035,
+    "variable_requires", cm::make_unique<cmVariableRequiresCommand>(),
+    cmPolicies::CMP0035,
     "The variable_requires command should not be called; see CMP0035.");
 #endif
 }
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 66250f3..61880c2 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -6,7 +6,6 @@
 #include <sstream>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalCommonGenerator.h"
@@ -17,6 +16,7 @@
 #include "cmOutputConverter.h"
 #include "cmSourceFile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 
 cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
   : GeneratorTarget(gt)
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 186deb6..f8b78b4 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -11,6 +11,7 @@
 #include "cmMakefile.h"
 #include "cmRange.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmake.h"
@@ -23,6 +24,8 @@
 #include <string.h>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 /*
 
 This file computes an ordered list of link items to use when linking a
@@ -202,7 +205,6 @@
 cmComputeLinkDepends::~cmComputeLinkDepends()
 {
   cmDeleteAll(this->InferredDependSets);
-  delete this->CCG;
 }
 
 void cmComputeLinkDepends::SetOldLinkDirMode(bool b)
@@ -632,7 +634,8 @@
   // the same order in which the items were originally discovered in
   // the BFS.  This should preserve the original order when no
   // constraints disallow it.
-  this->CCG = new cmComputeComponentGraph(this->EntryConstraintGraph);
+  this->CCG =
+    cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph);
 
   // The component graph is guaranteed to be acyclic.  Start a DFS
   // from every entry to compute a topological order for the
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index dfaaf8b..839c27a 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -10,6 +10,7 @@
 #include "cmTargetLinkLibraryType.h"
 
 #include <map>
+#include <memory>
 #include <queue>
 #include <set>
 #include <string>
@@ -137,7 +138,7 @@
     std::set<int> Entries;
   };
   std::map<int, PendingComponent> PendingComponents;
-  cmComputeComponentGraph* CCG;
+  std::unique_ptr<cmComputeComponentGraph> CCG;
   std::vector<int> FinalLinkOrder;
   void DisplayComponents();
   void VisitComponent(unsigned int c);
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 44d8615..78cddf0 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmComputeLinkInformation.h"
 
-#include "cmAlgorithms.h"
 #include "cmComputeLinkDepends.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
@@ -14,6 +13,7 @@
 #include "cmPolicies.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmake.h"
@@ -268,10 +268,6 @@
     return;
   }
 
-  // Check whether we should use an import library for linking a target.
-  this->UseImportLibrary =
-    this->Makefile->IsDefinitionSet("CMAKE_IMPORT_LIBRARY_SUFFIX");
-
   // Check whether we should skip dependencies on shared library files.
   this->LinkDependsNoShared =
     this->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED");
@@ -280,7 +276,7 @@
   // to use when creating a plugin (module) that obtains symbols from
   // the program that will load it.
   this->LoaderFlag = nullptr;
-  if (!this->UseImportLibrary &&
+  if (!this->Target->IsDLLPlatform() &&
       this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
     std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
     loader_flag_var += this->LinkLanguage;
@@ -493,9 +489,7 @@
     std::set<cmGeneratorTarget const*> const& wrongItems =
       cld.GetOldWrongConfigItems();
     for (cmGeneratorTarget const* tgt : wrongItems) {
-      bool implib = (this->UseImportLibrary &&
-                     (tgt->GetType() == cmStateEnums::SHARED_LIBRARY));
-      cmStateEnums::ArtifactType artifact = implib
+      cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(this->Config)
         ? cmStateEnums::ImportLibraryArtifact
         : cmStateEnums::RuntimeBinaryArtifact;
       this->OldLinkDirItems.push_back(
@@ -578,7 +572,7 @@
   // Compute the proper name to use to link this library.
   const std::string& config = this->Config;
   bool impexe = (tgt && tgt->IsExecutableWithExports());
-  if (impexe && !this->UseImportLibrary && !this->LoaderFlag) {
+  if (impexe && !tgt->HasImportLibrary(config) && !this->LoaderFlag) {
     // Skip linking to executables on platforms with no import
     // libraries or loader flags.
     return;
@@ -592,7 +586,7 @@
       // platform.  Add it now.
       std::string linkItem;
       linkItem = this->LoaderFlag;
-      cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+      cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config)
         ? cmStateEnums::ImportLibraryArtifact
         : cmStateEnums::RuntimeBinaryArtifact;
 
@@ -616,15 +610,21 @@
       // Its object-files should already have been extracted for linking.
     } else {
       // Decide whether to use an import library.
-      bool implib =
-        (this->UseImportLibrary &&
-         (impexe || tgt->GetType() == cmStateEnums::SHARED_LIBRARY));
-      cmStateEnums::ArtifactType artifact = implib
+      cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config)
         ? cmStateEnums::ImportLibraryArtifact
         : cmStateEnums::RuntimeBinaryArtifact;
 
       // Pass the full path to the target file.
       std::string lib = tgt->GetFullPath(config, artifact, true);
+      if (tgt->Target->IsAIX() && cmHasLiteralSuffix(lib, "-NOTFOUND") &&
+          artifact == cmStateEnums::ImportLibraryArtifact) {
+        // This is an imported executable on AIX that has ENABLE_EXPORTS
+        // but not IMPORTED_IMPLIB.  CMake used to produce and accept such
+        // imported executables on AIX before we taught it to use linker
+        // import files.  For compatibility, simply skip linking to this
+        // executable as we did before.  It works with runtime linking.
+        return;
+      }
       if (!this->LinkDependsNoShared ||
           tgt->GetType() != cmStateEnums::SHARED_LIBRARY) {
         this->Depends.push_back(lib);
@@ -694,7 +694,7 @@
   // linked will be able to find it.
   std::string lib;
   if (tgt) {
-    cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+    cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(this->Config)
       ? cmStateEnums::ImportLibraryArtifact
       : cmStateEnums::RuntimeBinaryArtifact;
     lib = tgt->GetFullPath(this->Config, artifact);
@@ -1695,7 +1695,7 @@
     (for_install ||
      this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"));
   bool use_install_rpath =
-    (outputRuntime && this->Target->HaveInstallTreeRPATH() &&
+    (outputRuntime && this->Target->HaveInstallTreeRPATH(this->Config) &&
      linking_for_install);
   bool use_build_rpath =
     (outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
@@ -1715,15 +1715,17 @@
   // Construct the RPATH.
   std::set<std::string> emitted;
   if (use_install_rpath) {
-    const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH");
-    cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted);
+    std::string install_rpath;
+    this->Target->GetInstallRPATH(this->Config, install_rpath);
+    cmCLI_ExpandListUnique(install_rpath.c_str(), runtimeDirs, emitted);
   }
   if (use_build_rpath) {
     // Add directories explicitly specified by user
-    if (const char* build_rpath = this->Target->GetProperty("BUILD_RPATH")) {
+    std::string build_rpath;
+    if (this->Target->GetBuildRPATH(this->Config, build_rpath)) {
       // This will not resolve entries to use $ORIGIN, the user is expected to
       // do that if necessary.
-      cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted);
+      cmCLI_ExpandListUnique(build_rpath.c_str(), runtimeDirs, emitted);
     }
   }
   if (use_build_rpath || use_link_rpath) {
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 863639c..3be2c7f 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -179,7 +179,6 @@
   bool OldLinkDirMode;
   bool OpenBSD;
   bool LinkDependsNoShared;
-  bool UseImportLibrary;
   bool RuntimeUseChrpath;
   bool NoSONameUsesPath;
   bool LinkWithRuntimePath;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index e7e91c1..5b88807 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -4,6 +4,7 @@
 
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
+#include <functional>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -14,10 +15,10 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-class cmCommand;
 class cmTest;
 
 static std::string const keyAND = "AND";
@@ -452,7 +453,7 @@
       }
       // does a command exist
       if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) {
-        cmCommand* command =
+        cmState::Command command =
           this->Makefile.GetState()->GetCommand(argP1->c_str());
         this->HandlePredicate(command != nullptr, reducible, arg, newArgs,
                               argP1, argP2);
diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h
index 5603c50..b3a99d7 100644
--- a/Source/cmConfigureFileCommand.h
+++ b/Source/cmConfigureFileCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 #include "cmNewLineStyle.h"
 
@@ -16,7 +18,10 @@
 class cmConfigureFileCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmConfigureFileCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmConfigureFileCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmContinueCommand.h b/Source/cmContinueCommand.h
index d383d1d..a85010a 100644
--- a/Source/cmContinueCommand.h
+++ b/Source/cmContinueCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmContinueCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmContinueCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index f12ef0b..d2a4148 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -9,7 +9,6 @@
 #include <string.h>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmExportTryCompileFileGenerator.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
@@ -17,6 +16,7 @@
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmVersion.h"
@@ -932,7 +932,7 @@
                                      cmStateEnums::INTERNAL);
 
   if (!outputVariable.empty()) {
-    this->Makefile->AddDefinition(outputVariable, output.c_str());
+    this->Makefile->AddDefinition(outputVariable, output);
   }
 
   if (this->SrcFileSignature) {
@@ -961,8 +961,7 @@
     }
 
     if (!copyFileError.empty()) {
-      this->Makefile->AddDefinition(copyFileError,
-                                    copyFileErrorMessage.c_str());
+      this->Makefile->AddDefinition(copyFileError, copyFileErrorMessage);
     }
   }
   return res;
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index b78493f..427db72 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -125,16 +125,15 @@
   }
   if (!extraInclude.empty()) {
     this->Makefile->AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES",
-                                  extraInclude.c_str());
+                                  extraInclude);
   }
   if (!function.empty()) {
-    this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION",
-                                  function.c_str());
+    this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION", function);
   }
   this->Makefile->AddDefinition("CMAKE_FORWARD_DECLARE_TESTS",
-                                forwardDeclareCode.c_str());
+                                forwardDeclareCode);
   this->Makefile->AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES",
-                                functionMapCode.c_str());
+                                functionMapCode);
   bool res = true;
   if (!this->Makefile->ConfigureFile(configFile, driver, false, true, false)) {
     res = false;
@@ -154,6 +153,6 @@
     sourceListValue += *i;
   }
 
-  this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
+  this->Makefile->AddDefinition(sourceList, sourceListValue);
   return res;
 }
diff --git a/Source/cmCreateTestSourceList.h b/Source/cmCreateTestSourceList.h
index 005b32c..5aa6af4 100644
--- a/Source/cmCreateTestSourceList.h
+++ b/Source/cmCreateTestSourceList.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmCreateTestSourceList; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmCreateTestSourceList>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx
index d914eb1..5e919af 100644
--- a/Source/cmCryptoHash.cxx
+++ b/Source/cmCryptoHash.cxx
@@ -2,13 +2,13 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCryptoHash.h"
 
-#include "cmAlgorithms.h"
 #include "cm_kwiml.h"
 #include "cm_rhash.h"
 #include "cmsys/FStream.hxx"
+
 #include <string.h>
 
-#include <memory> // IWYU pragma: keep
+#include "cm_memory.hxx"
 
 static unsigned int const cmCryptoHashAlgoToId[] = {
   /* clang-format needs this comment to break after the opening brace */
diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h
index b712f09..c7d3377 100644
--- a/Source/cmCryptoHash.h
+++ b/Source/cmCryptoHash.h
@@ -5,7 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <stddef.h>
 #include <string>
 #include <vector>
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index fe228ff..758a69a 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -12,7 +12,7 @@
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <stddef.h>
 #include <utility>
 
diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h
index a9c1856..36f97df 100644
--- a/Source/cmDefinePropertyCommand.h
+++ b/Source/cmDefinePropertyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmDefinePropertyCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmDefinePropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmDefinePropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 5fafaf9..42e70d6 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -13,10 +13,12 @@
                                                      StackIter end, bool raise)
 {
   assert(begin != end);
-  MapType::iterator i = begin->Map.find(key);
-  if (i != begin->Map.end()) {
-    i->second.Used = true;
-    return i->second;
+  {
+    MapType::iterator it = begin->Map.find(key);
+    if (it != begin->Map.end()) {
+      it->second.Used = true;
+      return it->second;
+    }
   }
   StackIter it = begin;
   ++it;
@@ -27,14 +29,14 @@
   if (!raise) {
     return def;
   }
-  return begin->Map.insert(MapType::value_type(key, def)).first->second;
+  return begin->Map.emplace(key, def).first->second;
 }
 
 const std::string* cmDefinitions::Get(const std::string& key, StackIter begin,
                                       StackIter end)
 {
   Def const& def = cmDefinitions::GetInternal(key, begin, end, false);
-  return def.Exists ? &def : nullptr;
+  return def.Exists ? &def.Value : nullptr;
 }
 
 void cmDefinitions::Raise(const std::string& key, StackIter begin,
@@ -47,18 +49,21 @@
                            StackIter end)
 {
   for (StackIter it = begin; it != end; ++it) {
-    MapType::const_iterator i = it->Map.find(key);
-    if (i != it->Map.end()) {
+    if (it->Map.find(key) != it->Map.end()) {
       return true;
     }
   }
   return false;
 }
 
-void cmDefinitions::Set(const std::string& key, const char* value)
+void cmDefinitions::Set(const std::string& key, cm::string_view value)
 {
-  Def def(value);
-  this->Map[key] = def;
+  this->Map[key] = Def(value);
+}
+
+void cmDefinitions::Unset(const std::string& key)
+{
+  this->Map[key] = Def();
 }
 
 std::vector<std::string> cmDefinitions::UnusedKeys() const
@@ -98,8 +103,8 @@
 std::vector<std::string> cmDefinitions::ClosureKeys(StackIter begin,
                                                     StackIter end)
 {
-  std::set<std::string> bound;
   std::vector<std::string> defined;
+  std::set<std::string> bound;
 
   for (StackIter it = begin; it != end; ++it) {
     defined.reserve(defined.size() + it->Map.size());
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index 6c252be..4d8810a 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -5,12 +5,14 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cm_string_view.hxx"
+
+#include "cmLinkedTree.h"
+
 #include <string>
 #include <unordered_map>
 #include <vector>
 
-#include "cmLinkedTree.h"
-
 /** \class cmDefinitions
  * \brief Store a scope of variable definitions for CMake language.
  *
@@ -30,8 +32,11 @@
 
   static bool HasKey(const std::string& key, StackIter begin, StackIter end);
 
-  /** Set (or unset if null) a value associated with a key.  */
-  void Set(const std::string& key, const char* value);
+  /** Set a value associated with a key.  */
+  void Set(const std::string& key, cm::string_view value);
+
+  /** Unset a definition.  */
+  void Unset(const std::string& key);
 
   std::vector<std::string> UnusedKeys() const;
 
@@ -40,24 +45,17 @@
   static cmDefinitions MakeClosure(StackIter begin, StackIter end);
 
 private:
-  // String with existence boolean.
-  struct Def : public std::string
+  /** String with existence boolean.  */
+  struct Def
   {
-  private:
-    typedef std::string std_string;
-
   public:
     Def() = default;
-    Def(const char* v)
-      : std_string(v ? v : "")
-      , Exists(v ? true : false)
-    {
-    }
-    Def(const std_string& v)
-      : std_string(v)
+    Def(cm::string_view value)
+      : Value(value)
       , Exists(true)
     {
     }
+    std::string Value;
     bool Exists = false;
     bool Used = false;
   };
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 178e18b..764ba30 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -9,7 +9,6 @@
 #include <stdlib.h>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmFortranParser.h" /* Interface to parser object.  */
 #include "cmGeneratedFileStream.h"
 #include "cmLocalGenerator.h"
@@ -17,6 +16,7 @@
 #include "cmOutputConverter.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 // TODO: Test compiler for the case of the mod file.  Some always
diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx
index 418d98c..aa1f90b 100644
--- a/Source/cmDisallowedCommand.cxx
+++ b/Source/cmDisallowedCommand.cxx
@@ -24,8 +24,6 @@
       return true;
   }
 
-  this->Command->SetMakefile(this->GetMakefile());
-  bool const ret = this->Command->InitialPass(args, status);
-  this->SetError(this->Command->GetError());
-  return ret;
+  this->Command->SetExecutionStatus(this->GetExecutionStatus());
+  return this->Command->InitialPass(args, status);
 }
diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h
index d85c00f..e07f255 100644
--- a/Source/cmDisallowedCommand.h
+++ b/Source/cmDisallowedCommand.h
@@ -6,8 +6,11 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
+#include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 #include "cmPolicies.h"
 
@@ -16,31 +19,27 @@
 class cmDisallowedCommand : public cmCommand
 {
 public:
-  cmDisallowedCommand(cmCommand* command, cmPolicies::PolicyID policy,
-                      const char* message)
-    : Command(command)
+  cmDisallowedCommand(std::unique_ptr<cmCommand> command,
+                      cmPolicies::PolicyID policy, const char* message)
+    : Command(std::move(command))
     , Policy(policy)
     , Message(message)
   {
   }
 
-  ~cmDisallowedCommand() override { delete this->Command; }
+  ~cmDisallowedCommand() override = default;
 
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    return new cmDisallowedCommand(this->Command->Clone(), this->Policy,
-                                   this->Message);
+    return cm::make_unique<cmDisallowedCommand>(this->Command->Clone(),
+                                                this->Policy, this->Message);
   }
 
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 
-  void FinalPass() override { this->Command->FinalPass(); }
-
-  bool HasFinalPass() const override { return this->Command->HasFinalPass(); }
-
 private:
-  cmCommand* Command;
+  std::unique_ptr<cmCommand> Command;
   cmPolicies::PolicyID Policy;
   const char* Message;
 };
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 2226463..096016d 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -4,9 +4,10 @@
 
 #include "cmAlgorithms.h"
 #include "cm_kwiml.h"
+#include "cm_memory.hxx"
 #include "cmsys/FStream.hxx"
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <stddef.h>
 #include <utility>
@@ -109,10 +110,10 @@
   };
 
   // Construct and take ownership of the file stream object.
-  cmELFInternal(cmELF* external, std::unique_ptr<cmsys::ifstream>& fin,
+  cmELFInternal(cmELF* external, std::unique_ptr<std::istream> fin,
                 ByteOrderType order)
     : External(external)
-    , Stream(*fin.release())
+    , Stream(std::move(fin))
     , ByteOrder(order)
     , ELFType(cmELF::FileTypeInvalid)
   {
@@ -132,7 +133,7 @@
   }
 
   // Destruct and delete the file stream object.
-  virtual ~cmELFInternal() { delete &this->Stream; }
+  virtual ~cmELFInternal() = default;
 
   // Forward to the per-class implementation.
   virtual unsigned int GetNumberOfSections() const = 0;
@@ -171,7 +172,7 @@
   cmELF* External;
 
   // The stream from which to read.
-  std::istream& Stream;
+  std::unique_ptr<std::istream> Stream;
 
   // The byte order of the ELF file.
   ByteOrderType ByteOrder;
@@ -233,7 +234,7 @@
   typedef typename Types::tagtype tagtype;
 
   // Construct with a stream and byte swap indicator.
-  cmELFInternalImpl(cmELF* external, std::unique_ptr<cmsys::ifstream>& fin,
+  cmELFInternalImpl(cmELF* external, std::unique_ptr<std::istream> fin,
                     ByteOrderType order);
 
   // Return the number of sections as specified by the ELF header.
@@ -352,7 +353,7 @@
   bool Read(ELF_Ehdr& x)
   {
     // Read the header from the file.
-    if (!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x))) {
+    if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) {
       return false;
     }
 
@@ -382,26 +383,26 @@
   }
   bool Read(ELF_Shdr& x)
   {
-    if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
+    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
         this->NeedSwap) {
       ByteSwap(x);
     }
-    return !this->Stream.fail();
+    return !this->Stream->fail();
   }
   bool Read(ELF_Dyn& x)
   {
-    if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
+    if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
         this->NeedSwap) {
       ByteSwap(x);
     }
-    return !this->Stream.fail();
+    return !this->Stream->fail();
   }
 
   bool LoadSectionHeader(ELF_Half i)
   {
     // Read the section header from the file.
-    this->Stream.seekg(this->ELFHeader.e_shoff +
-                       this->ELFHeader.e_shentsize * i);
+    this->Stream->seekg(this->ELFHeader.e_shoff +
+                        this->ELFHeader.e_shentsize * i);
     if (!this->Read(this->SectionHeaders[i])) {
       return false;
     }
@@ -426,9 +427,10 @@
 };
 
 template <class Types>
-cmELFInternalImpl<Types>::cmELFInternalImpl(
-  cmELF* external, std::unique_ptr<cmsys::ifstream>& fin, ByteOrderType order)
-  : cmELFInternal(external, fin, order)
+cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
+                                            std::unique_ptr<std::istream> fin,
+                                            ByteOrderType order)
+  : cmELFInternal(external, std::move(fin), order)
 {
   // Read the main header.
   if (!this->Read(this->ELFHeader)) {
@@ -510,7 +512,7 @@
   // Read each entry.
   for (int j = 0; j < n; ++j) {
     // Seek to the beginning of the section entry.
-    this->Stream.seekg(sec.sh_offset + sec.sh_entsize * j);
+    this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j);
     ELF_Dyn& dyn = this->DynamicSectionEntries[j];
 
     // Try reading the entry.
@@ -630,7 +632,7 @@
       unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
       unsigned long last = first;
       unsigned long end = static_cast<unsigned long>(strtab.sh_size);
-      this->Stream.seekg(strtab.sh_offset + first);
+      this->Stream->seekg(strtab.sh_offset + first);
 
       // Read the string.  It may be followed by more than one NULL
       // terminator.  Count the total size of the region allocated to
@@ -639,7 +641,7 @@
       // assumption.
       bool terminated = false;
       char c;
-      while (last != end && this->Stream.get(c) && !(terminated && c)) {
+      while (last != end && this->Stream->get(c) && !(terminated && c)) {
         ++last;
         if (c) {
           se.Value += c;
@@ -649,7 +651,7 @@
       }
 
       // Make sure the whole value was read.
-      if (!this->Stream) {
+      if (!(*this->Stream)) {
         this->SetErrorMessage("Dynamic section specifies unreadable RPATH.");
         se.Value = "";
         return nullptr;
@@ -679,10 +681,9 @@
 #endif
 
 cmELF::cmELF(const char* fname)
-  : Internal(nullptr)
 {
   // Try to open the file.
-  std::unique_ptr<cmsys::ifstream> fin(new cmsys::ifstream(fname));
+  auto fin = cm::make_unique<cmsys::ifstream>(fname);
 
   // Quit now if the file could not be opened.
   if (!fin || !*fin) {
@@ -725,12 +726,14 @@
   // parser implementation.
   if (ident[EI_CLASS] == ELFCLASS32) {
     // 32-bit ELF
-    this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order);
+    this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>(
+      this, std::move(fin), order);
   }
 #ifndef _SCO_DS
   else if (ident[EI_CLASS] == ELFCLASS64) {
     // 64-bit ELF
-    this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
+    this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>(
+      this, std::move(fin), order);
   }
 #endif
   else {
@@ -739,10 +742,7 @@
   }
 }
 
-cmELF::~cmELF()
-{
-  delete this->Internal;
-}
+cmELF::~cmELF() = default;
 
 bool cmELF::Valid() const
 {
diff --git a/Source/cmELF.h b/Source/cmELF.h
index 987f0c3..afef654 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -6,6 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
+#include <memory>
 #include <string>
 #include <utility>
 #include <vector>
@@ -108,7 +109,7 @@
 private:
   friend class cmELFInternal;
   bool Valid() const;
-  cmELFInternal* Internal;
+  std::unique_ptr<cmELFInternal> Internal;
   std::string ErrorMessage;
 };
 
diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h
index 97645a9..dc43e34 100644
--- a/Source/cmEnableLanguageCommand.h
+++ b/Source/cmEnableLanguageCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -26,7 +28,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmEnableLanguageCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmEnableLanguageCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmEnableTestingCommand.cxx b/Source/cmEnableTestingCommand.cxx
index 6a64450..89212c8 100644
--- a/Source/cmEnableTestingCommand.cxx
+++ b/Source/cmEnableTestingCommand.cxx
@@ -2,15 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmEnableTestingCommand.h"
 
+#include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 
-class cmExecutionStatus;
-
-// we do this in the final pass so that we now the subdirs have all
-// been defined
-bool cmEnableTestingCommand::InitialPass(std::vector<std::string> const&,
-                                         cmExecutionStatus&)
+bool cmEnableTestingCommand(std::vector<std::string> const&,
+                            cmExecutionStatus& status)
 {
-  this->Makefile->AddDefinition("CMAKE_TESTING_ENABLED", "1");
+  status.GetMakefile().AddDefinition("CMAKE_TESTING_ENABLED", "1");
   return true;
 }
diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h
index 88a17b9..e4593f2 100644
--- a/Source/cmEnableTestingCommand.h
+++ b/Source/cmEnableTestingCommand.h
@@ -8,11 +8,9 @@
 #include <string>
 #include <vector>
 
-#include "cmCommand.h"
-
 class cmExecutionStatus;
 
-/** \class cmEnableTestingCommand
+/**
  * \brief Enable testing for this directory and below.
  *
  * Produce the output testfile. This produces a file in the build directory
@@ -25,20 +23,7 @@
  * Note that CTest expects to find this file in the build directory root;
  * therefore, this command should be in the source directory root too.
  */
-class cmEnableTestingCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  cmCommand* Clone() override { return new cmEnableTestingCommand; }
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override;
-};
+bool cmEnableTestingCommand(std::vector<std::string> const&,
+                            cmExecutionStatus&);
 
 #endif
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index 4b559e7..bc1d173 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -103,7 +103,7 @@
     }
 
     std::string coutput = std::string(output, first, last - first + 1);
-    this->Makefile->AddDefinition(output_variable, coutput.c_str());
+    this->Makefile->AddDefinition(output_variable, coutput);
   }
 
   if (!return_variable.empty()) {
diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h
index ae0fa9b..70f833a 100644
--- a/Source/cmExecProgramCommand.h
+++ b/Source/cmExecProgramCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 #include "cmProcessOutput.h"
 
@@ -27,7 +29,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmExecProgramCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmExecProgramCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 494afbb..465f4b3 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -4,16 +4,19 @@
 
 #include "cm_static_string_view.hxx"
 #include "cmsys/Process.h"
+
 #include <algorithm>
 #include <ctype.h> /* isspace */
 #include <iostream>
 #include <stdio.h>
+#include <vector>
 
 #include "cmAlgorithms.h"
 #include "cmArgumentParser.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -330,7 +333,7 @@
           }
         }
         this->Makefile->AddDefinition(arguments.ResultsVariable,
-                                      cmJoin(res, ";").c_str());
+                                      cmJoin(res, ";"));
       } break;
       case cmsysProcess_State_Exception:
         this->Makefile->AddDefinition(arguments.ResultsVariable,
diff --git a/Source/cmExecuteProcessCommand.h b/Source/cmExecuteProcessCommand.h
index b415deb..1d5445f 100644
--- a/Source/cmExecuteProcessCommand.h
+++ b/Source/cmExecuteProcessCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmExecuteProcessCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmExecuteProcessCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h
index 56199dd..bcacc2f 100644
--- a/Source/cmExecutionStatus.h
+++ b/Source/cmExecutionStatus.h
@@ -3,6 +3,11 @@
 #ifndef cmExecutionStatus_h
 #define cmExecutionStatus_h
 
+#include <cmConfigure.h> // IWYU pragma: keep
+#include <string>
+
+class cmMakefile;
+
 /** \class cmExecutionStatus
  * \brief Superclass for all command status classes
  *
@@ -11,14 +16,26 @@
 class cmExecutionStatus
 {
 public:
+  cmExecutionStatus(cmMakefile& makefile)
+    : Makefile(makefile)
+    , Error("unknown error.")
+  {
+  }
+
   void Clear()
   {
+    this->Error = "unknown error.";
     this->ReturnInvoked = false;
     this->BreakInvoked = false;
     this->ContinueInvoked = false;
     this->NestedError = false;
   }
 
+  cmMakefile& GetMakefile() { return this->Makefile; }
+
+  void SetError(std::string const& e) { this->Error = e; }
+  std::string const& GetError() const { return this->Error; }
+
   void SetReturnInvoked() { this->ReturnInvoked = true; }
   bool GetReturnInvoked() const { return this->ReturnInvoked; }
 
@@ -32,6 +49,8 @@
   bool GetNestedError() const { return this->NestedError; }
 
 private:
+  cmMakefile& Makefile;
+  std::string Error;
   bool ReturnInvoked = false;
   bool BreakInvoked = false;
   bool ContinueInvoked = false;
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index ced27c9..5edf7ca 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -3,17 +3,16 @@
 #include "cmExportBuildAndroidMKGenerator.h"
 
 #include <algorithm>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorTarget.h"
 #include "cmLinkItem.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 012355b..33806f2 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportBuildFileGenerator.h"
 
-#include "cmAlgorithms.h"
 #include "cmExportSet.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
@@ -12,7 +11,7 @@
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmStateTypes.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
 #include "cmTarget.h"
 #include "cmTargetExport.h"
 #include "cmake.h"
@@ -45,6 +44,7 @@
     std::string expectedTargets;
     std::string sep;
     std::vector<std::string> targets;
+    bool generatedInterfaceRequired = false;
     this->GetTargets(targets);
     for (std::string const& tei : targets) {
       cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei);
@@ -60,11 +60,13 @@
           this->LG->GetMakefile()->GetBacktrace());
         return false;
       }
-      if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
-        this->GenerateRequiredCMakeVersion(os, "3.0.0");
-      }
+      generatedInterfaceRequired |=
+        this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY;
     }
 
+    if (generatedInterfaceRequired) {
+      this->GenerateRequiredCMakeVersion(os, "3.0.0");
+    }
     this->GenerateExpectedTargetsCode(os, expectedTargets);
   }
 
@@ -234,14 +236,15 @@
     }
 
     // Add the import library for windows DLLs.
-    if (target->HasImportLibrary(config) &&
-        mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+    if (target->HasImportLibrary(config)) {
       std::string prop = "IMPORTED_IMPLIB";
       prop += suffix;
       std::string value =
         target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
-      target->GetImplibGNUtoMS(config, value, value,
-                               "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+      if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+        target->GetImplibGNUtoMS(config, value, value,
+                                 "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+      }
       properties[prop] = value;
     }
   }
@@ -256,11 +259,11 @@
     const std::string name = dependee->GetName();
     cmGlobalGenerator* gg =
       dependee->GetLocalGenerator()->GetGlobalGenerator();
-    std::vector<std::string> namespaces = this->FindNamespaces(gg, name);
+    auto exportInfo = this->FindBuildExportInfo(gg, name);
+    std::vector<std::string> const& exportFiles = exportInfo.first;
 
-    int targetOccurrences = static_cast<int>(namespaces.size());
-    if (targetOccurrences == 1) {
-      std::string missingTarget = namespaces[0];
+    if (exportFiles.size() == 1) {
+      std::string missingTarget = exportInfo.second;
 
       missingTarget += dependee->GetExportName();
       link_libs += missingTarget;
@@ -269,7 +272,7 @@
     }
     // We are not appending, so all exported targets should be
     // known here.  This is probably user-error.
-    this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
+    this->ComplainAboutMissingTarget(depender, dependee, exportFiles);
   }
   // Assume the target will be exported by another command.
   // Append it with the export namespace.
@@ -289,10 +292,12 @@
   targets = this->Targets;
 }
 
-std::vector<std::string> cmExportBuildFileGenerator::FindNamespaces(
-  cmGlobalGenerator* gg, const std::string& name)
+std::pair<std::vector<std::string>, std::string>
+cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
+                                                const std::string& name)
 {
-  std::vector<std::string> namespaces;
+  std::vector<std::string> exportFiles;
+  std::string ns;
 
   std::map<std::string, cmExportBuildFileGenerator*>& exportSets =
     gg->GetBuildExportSets();
@@ -302,31 +307,31 @@
     std::vector<std::string> targets;
     exportSet->GetTargets(targets);
     if (std::find(targets.begin(), targets.end(), name) != targets.end()) {
-      namespaces.push_back(exportSet->GetNamespace());
+      exportFiles.push_back(exp.first);
+      ns = exportSet->GetNamespace();
     }
   }
 
-  return namespaces;
+  return std::make_pair(exportFiles, ns);
 }
 
 void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
-  cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences)
+  cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+  std::vector<std::string> const& exportFiles)
 {
-  if (cmSystemTools::GetErrorOccuredFlag()) {
-    return;
-  }
-
   std::ostringstream e;
   e << "export called with target \"" << depender->GetName()
     << "\" which requires target \"" << dependee->GetName() << "\" ";
-  if (occurrences == 0) {
-    e << "that is not in the export set.\n";
+  if (exportFiles.empty()) {
+    e << "that is not in any export set.";
   } else {
-    e << "that is not in this export set, but " << occurrences
-      << " times in others.\n";
+    e << "that is not in this export set, but in multiple other export sets: "
+      << cmJoin(exportFiles, ", ") << ".\n";
+    e << "An exported target cannot depend upon another target which is "
+         "exported multiple times. Consider consolidating the exports of the "
+         "\""
+      << dependee->GetName() << "\" target to a single export.";
   }
-  e << "If the required target is not easy to reference in this call, "
-    << "consider using the APPEND option with multiple separate calls.";
 
   this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
     MessageType::FATAL_ERROR, e.str(),
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 0a1e755..e5b6597 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -11,6 +11,7 @@
 
 #include <iosfwd>
 #include <string>
+#include <utility>
 #include <vector>
 
 class cmExportSet;
@@ -64,7 +65,7 @@
 
   void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
                                   cmGeneratorTarget* dependee,
-                                  int occurrences);
+                                  std::vector<std::string> const& namespaces);
 
   /** Fill in properties indicating built file locations.  */
   void SetImportLocationProperty(const std::string& config,
@@ -75,8 +76,8 @@
   std::string InstallNameDir(cmGeneratorTarget* target,
                              const std::string& config) override;
 
-  std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg,
-                                          const std::string& name);
+  std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
+    cmGlobalGenerator* gg, const std::string& name);
 
   std::vector<std::string> Targets;
   cmExportSet* ExportSet;
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index 99f9932..50463af 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -18,7 +20,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmExportCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmExportCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index a12e0c4..87f9b4c 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportFileGenerator.h"
 
-#include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
@@ -12,20 +11,21 @@
 #include "cmMessageType.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
-#include "cmProperty.h"
 #include "cmPropertyMap.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetExport.h"
 
 #include "cmsys/FStream.hxx"
 #include <assert.h>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <string.h>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 static std::string cmExportFileGeneratorEscape(std::string const& str)
 {
   // Escape a property value for writing into a .cmake file.
@@ -1205,15 +1205,12 @@
   std::string& errorMessage)
 {
   auto& targetProperties = gte->Target->GetProperties();
-  const auto& exportProperties = targetProperties.find("EXPORT_PROPERTIES");
-  if (exportProperties != targetProperties.end()) {
-    std::vector<std::string> propsToExport;
-    cmSystemTools::ExpandListArgument(exportProperties->second.GetValue(),
-                                      propsToExport);
-    for (auto& prop : propsToExport) {
+  if (const char* exportProperties =
+        targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) {
+    for (auto& prop : cmSystemTools::ExpandedListArgument(exportProperties)) {
       /* Black list reserved properties */
-      if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") ||
-          cmSystemTools::StringStartsWith(prop, "INTERFACE_")) {
+      if (cmHasLiteralPrefix(prop, "IMPORTED_") ||
+          cmHasLiteralPrefix(prop, "INTERFACE_")) {
         std::ostringstream e;
         e << "Target \"" << gte->Target->GetName() << "\" contains property \""
           << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* "
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index f8bc0ab..ab4a62b 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportInstallFileGenerator.h"
 
-#include "cmAlgorithms.h"
 #include "cmExportSet.h"
 #include "cmExportSetMap.h"
 #include "cmGeneratedFileStream.h"
@@ -15,6 +14,7 @@
 #include "cmMakefile.h"
 #include "cmPolicies.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetExport.h"
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index b60a053..8f2fff5 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -4,10 +4,10 @@
 
 #include "cmsys/FStream.hxx"
 #include <map>
-#include <memory> // IWYU pragma: keep
 #include <utility>
 
-#include "cmAlgorithms.h"
+#include "cm_memory.hxx"
+
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
@@ -19,57 +19,31 @@
 
 class cmExecutionStatus;
 
-bool cmExportLibraryDependenciesCommand::InitialPass(
-  std::vector<std::string> const& args, cmExecutionStatus&)
-{
-  if (args.empty()) {
-    this->SetError("called with incorrect number of arguments");
-    return false;
-  }
-
-  // store the arguments for the final pass
-  this->Filename = args[0];
-  this->Append = false;
-  if (args.size() > 1) {
-    if (args[1] == "APPEND") {
-      this->Append = true;
-    }
-  }
-  return true;
-}
-
-void cmExportLibraryDependenciesCommand::FinalPass()
-{
-  // export_library_dependencies() shouldn't modify anything
-  // ensure this by calling a const method
-  this->ConstFinalPass();
-}
-
-void cmExportLibraryDependenciesCommand::ConstFinalPass() const
+static void FinalAction(cmMakefile& makefile, std::string const& filename,
+                        bool append)
 {
   // Use copy-if-different if not appending.
   std::unique_ptr<cmsys::ofstream> foutPtr;
-  if (this->Append) {
+  if (append) {
     const auto openmodeApp = std::ios::app;
-    foutPtr =
-      cm::make_unique<cmsys::ofstream>(this->Filename.c_str(), openmodeApp);
+    foutPtr = cm::make_unique<cmsys::ofstream>(filename.c_str(), openmodeApp);
   } else {
     std::unique_ptr<cmGeneratedFileStream> ap(
-      new cmGeneratedFileStream(this->Filename, true));
+      new cmGeneratedFileStream(filename, true));
     ap->SetCopyIfDifferent(true);
     foutPtr = std::move(ap);
   }
   std::ostream& fout = *foutPtr;
 
   if (!fout) {
-    cmSystemTools::Error("Error Writing " + this->Filename);
+    cmSystemTools::Error("Error Writing " + filename);
     cmSystemTools::ReportLastSystemError("");
     return;
   }
 
   // Collect dependency information about all library targets built in
   // the project.
-  cmake* cm = this->Makefile->GetCMakeInstance();
+  cmake* cm = makefile.GetCMakeInstance();
   cmGlobalGenerator* global = cm->GetGlobalGenerator();
   const std::vector<cmMakefile*>& locals = global->GetMakefiles();
   std::map<std::string, std::string> libDepsOld;
@@ -166,3 +140,20 @@
   }
   fout << "endif()\n";
 }
+
+bool cmExportLibraryDependenciesCommand::InitialPass(
+  std::vector<std::string> const& args, cmExecutionStatus&)
+{
+  if (args.empty()) {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+  }
+
+  std::string const& filename = args[0];
+  bool const append = args.size() > 1 && args[1] == "APPEND";
+  this->Makefile->AddFinalAction([filename, append](cmMakefile& makefile) {
+    FinalAction(makefile, filename, append);
+  });
+
+  return true;
+}
diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h
index 8414866..4817162 100644
--- a/Source/cmExportLibraryDependenciesCommand.h
+++ b/Source/cmExportLibraryDependenciesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,20 +17,12 @@
 class cmExportLibraryDependenciesCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    return new cmExportLibraryDependenciesCommand;
+    return cm::make_unique<cmExportLibraryDependenciesCommand>();
   }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
-
-  void FinalPass() override;
-  bool HasFinalPass() const override { return true; }
-
-private:
-  std::string Filename;
-  bool Append = false;
-  void ConstFinalPass() const;
 };
 
 #endif
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index c169032..a3c9802 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -13,7 +13,7 @@
 #include "cmTarget.h"
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <utility>
 
 cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 6fe8c14..30b3f0d 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -217,22 +217,21 @@
     case cmStateEnums::STATIC_LIBRARY:
     case cmStateEnums::SHARED_LIBRARY:
     case cmStateEnums::MODULE_LIBRARY: {
+      cmake const* cm = makefile->GetCMakeInstance();
       std::vector<cmSourceFile*> sources;
       gt->GetSourceFiles(sources,
                          makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
       for (cmSourceFile* s : sources) {
+        std::string const& fullPath = s->GetFullPath();
+        std::string const& extLower =
+          cmSystemTools::LowerCase(s->GetExtension());
         // check whether it is a source or a include file
         // then put it accordingly into one of the two containers
-        switch (cmSystemTools::GetFileFormat(s->GetExtension())) {
-          case cmSystemTools::C_FILE_FORMAT:
-          case cmSystemTools::CXX_FILE_FORMAT:
-          case cmSystemTools::CUDA_FILE_FORMAT:
-          case cmSystemTools::FORTRAN_FILE_FORMAT: {
-            cFiles[s->GetFullPath()] = s;
-          } break;
-          default: {
-            otherFiles.insert(s->GetFullPath());
-          }
+        if (cm->IsSourceExtension(extLower) || cm->IsCudaExtension(extLower) ||
+            cm->IsFortranExtension(extLower)) {
+          cFiles[fullPath] = s;
+        } else {
+          otherFiles.insert(fullPath);
         }
       }
     }
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index aece3bc..06709f1 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -44,6 +44,8 @@
 
 cmExtraEclipseCDT4Generator::cmExtraEclipseCDT4Generator()
 {
+  this->IsOutOfSourceBuild = false;
+  this->GenerateSourceProject = false;
   this->SupportsVirtualFolders = true;
   this->GenerateLinkedResources = true;
   this->SupportsGmakeErrorParser = true;
@@ -164,6 +166,29 @@
 
   // create a .cproject file
   this->CreateCProjectFile();
+
+  // create resource settings
+  this->CreateSettingsResourcePrefsFile();
+}
+
+void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile()
+{
+  cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+  cmMakefile* mf = lg->GetMakefile();
+
+  const std::string filename =
+    this->HomeOutputDirectory + "/.settings/org.eclipse.core.resources.prefs";
+
+  cmGeneratedFileStream fout(filename);
+  if (!fout) {
+    return;
+  }
+
+  fout << "eclipse.preferences.version=1" << std::endl;
+  const char* encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING");
+  if (encoding) {
+    fout << "encoding/<project>=" << encoding << std::endl;
+  }
 }
 
 void cmExtraEclipseCDT4Generator::CreateSourceProjectFile()
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index 5136660..ef038d9 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -43,6 +43,9 @@
   // create .project file in the source tree
   void CreateSourceProjectFile();
 
+  // create .settings/org.eclipse.core.resources.prefs
+  void CreateSettingsResourcePrefsFile();
+
   // create .project file
   void CreateProjectFile();
 
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index 89629c7..b7a2b27 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -13,6 +13,23 @@
 class cmExecutionStatus;
 class cmTarget;
 
+static void FinalAction(cmMakefile& makefile, std::string const& name)
+{
+  // people should add the srcs to the target themselves, but the old command
+  // didn't support that, so check and see if they added the files in and if
+  // they didn;t then print a warning and add then anyhow
+  cmTarget* target = makefile.FindLocalNonAliasTarget(name);
+  if (!target) {
+    std::string msg =
+      "FLTK_WRAP_UI was called with a target that was never created: ";
+    msg += name;
+    msg += ".  The problem was found while processing the source directory: ";
+    msg += makefile.GetCurrentSourceDirectory();
+    msg += ".  This FLTK_WRAP_UI call will be ignored.";
+    cmSystemTools::Message(msg, "Warning");
+  }
+}
+
 // cmFLTKWrapUICommand
 bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args,
                                       cmExecutionStatus&)
@@ -27,8 +44,8 @@
   std::string const& fluid_exe =
     this->Makefile->GetRequiredDefinition("FLTK_FLUID_EXECUTABLE");
 
-  // get parameter for the command
-  this->Target = args[0]; // Target that will use the generated files
+  // Target that will use the generated files
+  std::string const& target = args[0];
 
   // get the list of GUI files from which .cxx and .h will be generated
   std::string outputDirectory = this->Makefile->GetCurrentBinaryDirectory();
@@ -41,6 +58,9 @@
     this->Makefile->AddIncludeDirectories(outputDirectories);
   }
 
+  // List of produced files.
+  std::vector<cmSourceFile*> generatedSourcesClasses;
+
   for (std::string const& arg : cmMakeRange(args).advance(1)) {
     cmSourceFile* curr = this->Makefile->GetSource(arg);
     // if we should use the source GUI
@@ -84,40 +104,24 @@
       cmSourceFile* sf = this->Makefile->GetSource(cxxres);
       sf->AddDepend(hname);
       sf->AddDepend(origname);
-      this->GeneratedSourcesClasses.push_back(sf);
+      generatedSourcesClasses.push_back(sf);
     }
   }
 
   // create the variable with the list of sources in it
-  size_t lastHeadersClass = this->GeneratedSourcesClasses.size();
+  size_t lastHeadersClass = generatedSourcesClasses.size();
   std::string sourceListValue;
   for (size_t classNum = 0; classNum < lastHeadersClass; classNum++) {
     if (classNum) {
       sourceListValue += ";";
     }
-    sourceListValue += this->GeneratedSourcesClasses[classNum]->GetFullPath();
+    sourceListValue += generatedSourcesClasses[classNum]->GetFullPath();
   }
-  std::string varName = this->Target;
-  varName += "_FLTK_UI_SRCS";
-  this->Makefile->AddDefinition(varName, sourceListValue.c_str());
 
+  std::string const varName = target + "_FLTK_UI_SRCS";
+  this->Makefile->AddDefinition(varName, sourceListValue);
+
+  this->Makefile->AddFinalAction(
+    [target](cmMakefile& makefile) { FinalAction(makefile, target); });
   return true;
 }
-
-void cmFLTKWrapUICommand::FinalPass()
-{
-  // people should add the srcs to the target themselves, but the old command
-  // didn't support that, so check and see if they added the files in and if
-  // they didn;t then print a warning and add then anyhow
-  cmTarget* target = this->Makefile->FindLocalNonAliasTarget(this->Target);
-  if (!target) {
-    std::string msg =
-      "FLTK_WRAP_UI was called with a target that was never created: ";
-    msg += this->Target;
-    msg += ".  The problem was found while processing the source directory: ";
-    msg += this->Makefile->GetCurrentSourceDirectory();
-    msg += ".  This FLTK_WRAP_UI call will be ignored.";
-    cmSystemTools::Message(msg, "Warning");
-    return;
-  }
-}
diff --git a/Source/cmFLTKWrapUICommand.h b/Source/cmFLTKWrapUICommand.h
index 044755e..ea8d401 100644
--- a/Source/cmFLTKWrapUICommand.h
+++ b/Source/cmFLTKWrapUICommand.h
@@ -8,10 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
-class cmSourceFile;
 
 /** \class cmFLTKWrapUICommand
  * \brief Create .h and .cxx files rules for FLTK user interfaces files
@@ -25,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFLTKWrapUICommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFLTKWrapUICommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
@@ -33,27 +37,6 @@
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
-
-  /**
-   * This is called at the end after all the information
-   * specified by the command is accumulated. Most commands do
-   * not implement this method.  At this point, reading and
-   * writing to the cache can be done.
-   */
-  void FinalPass() override;
-  bool HasFinalPass() const override { return true; }
-
-private:
-  /**
-   * List of produced files.
-   */
-  std::vector<cmSourceFile*> GeneratedSourcesClasses;
-
-  /**
-   * List of Fluid files that provide the source
-   * generating .cxx and .h files
-   */
-  std::string Target;
 };
 
 #endif
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index ba42669..2594287 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -2,12 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFileAPI.h"
 
-#include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
 #include "cmFileAPICMakeFiles.h"
 #include "cmFileAPICache.h"
 #include "cmFileAPICodemodel.h"
 #include "cmGlobalGenerator.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"
 #include "cmake.h"
@@ -684,7 +684,6 @@
 
 Json::Value cmFileAPI::BuildCodeModel(Object const& object)
 {
-  using namespace std::placeholders;
   Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version);
   codemodel["kind"] = this->ObjectKindName(object.Kind);
 
@@ -719,7 +718,6 @@
 
 Json::Value cmFileAPI::BuildCache(Object const& object)
 {
-  using namespace std::placeholders;
   Json::Value cache = cmFileAPICacheDump(*this, object.Version);
   cache["kind"] = this->ObjectKindName(object.Kind);
 
@@ -754,7 +752,6 @@
 
 Json::Value cmFileAPI::BuildCMakeFiles(Object const& object)
 {
-  using namespace std::placeholders;
   Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version);
   cmakeFiles["kind"] = this->ObjectKindName(object.Kind);
 
diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h
index 602efa8..aa5a42f 100644
--- a/Source/cmFileAPI.h
+++ b/Source/cmFileAPI.h
@@ -10,7 +10,7 @@
 #include "cm_jsoncpp_writer.h"
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <unordered_set>
 #include <vector>
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 6025025..172897c 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -30,7 +30,11 @@
 
 #include <algorithm>
 #include <cassert>
+#include <cstddef>
+#include <functional>
+#include <limits>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -134,6 +138,40 @@
   return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
 }
 
+class JBTIndex
+{
+public:
+  JBTIndex() = default;
+  explicit operator bool() const { return Index != None; }
+  Json::ArrayIndex Index = None;
+  static Json::ArrayIndex const None = static_cast<Json::ArrayIndex>(-1);
+};
+
+template <typename T>
+class JBT
+{
+public:
+  JBT(T v = T(), JBTIndex bt = JBTIndex())
+    : Value(std::move(v))
+    , Backtrace(bt)
+  {
+  }
+  T Value;
+  JBTIndex Backtrace;
+  friend bool operator==(JBT<T> const& l, JBT<T> const& r)
+  {
+    return l.Value == r.Value && l.Backtrace.Index == r.Backtrace.Index;
+  }
+  static bool ValueEq(JBT<T> const& l, JBT<T> const& r)
+  {
+    return l.Value == r.Value;
+  }
+  static bool ValueLess(JBT<T> const& l, JBT<T> const& r)
+  {
+    return l.Value < r.Value;
+  }
+};
+
 class BacktraceData
 {
   std::string TopSource;
@@ -168,7 +206,7 @@
 
 public:
   BacktraceData(std::string topSource);
-  bool Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index);
+  JBTIndex Add(cmListFileBacktrace const& bt);
   Json::Value Dump();
 };
 
@@ -177,16 +215,17 @@
 {
 }
 
-bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index)
+JBTIndex BacktraceData::Add(cmListFileBacktrace const& bt)
 {
+  JBTIndex index;
   if (bt.Empty()) {
-    return false;
+    return index;
   }
   cmListFileContext const* top = &bt.Top();
   auto found = this->NodeMap.find(top);
   if (found != this->NodeMap.end()) {
-    index = found->second;
-    return true;
+    index.Index = found->second;
+    return index;
   }
   Json::Value entry = Json::objectValue;
   entry["file"] = this->AddFile(top->FilePath);
@@ -196,13 +235,12 @@
   if (!top->Name.empty()) {
     entry["command"] = this->AddCommand(top->Name);
   }
-  Json::ArrayIndex parent;
-  if (this->Add(bt.Pop(), parent)) {
-    entry["parent"] = parent;
+  if (JBTIndex parent = this->Add(bt.Pop())) {
+    entry["parent"] = parent.Index;
   }
-  index = this->NodeMap[top] = this->Nodes.size();
+  index.Index = this->NodeMap[top] = this->Nodes.size();
   this->Nodes.append(std::move(entry)); // NOLINT(*)
-  return true;
+  return index;
 }
 
 Json::Value BacktraceData::Dump()
@@ -221,32 +259,65 @@
 {
   struct IncludeEntry
   {
-    BT<std::string> Path;
+    JBT<std::string> Path;
     bool IsSystem = false;
-    IncludeEntry(BT<std::string> path, bool isSystem)
+    IncludeEntry(JBT<std::string> path, bool isSystem)
       : Path(std::move(path))
       , IsSystem(isSystem)
     {
     }
+    friend bool operator==(IncludeEntry const& l, IncludeEntry const& r)
+    {
+      return l.Path == r.Path && l.IsSystem == r.IsSystem;
+    }
   };
 
-  void SetDefines(std::set<BT<std::string>> const& defines);
-
   std::string Language;
   std::string Sysroot;
-  std::vector<BT<std::string>> Flags;
-  std::vector<BT<std::string>> Defines;
+  std::vector<JBT<std::string>> Flags;
+  std::vector<JBT<std::string>> Defines;
   std::vector<IncludeEntry> Includes;
-};
 
-void CompileData::SetDefines(std::set<BT<std::string>> const& defines)
-{
-  this->Defines.reserve(defines.size());
-  for (BT<std::string> const& d : defines) {
-    this->Defines.push_back(d);
+  friend bool operator==(CompileData const& l, CompileData const& r)
+  {
+    return (l.Language == r.Language && l.Sysroot == r.Sysroot &&
+            l.Flags == r.Flags && l.Defines == r.Defines &&
+            l.Includes == r.Includes);
   }
+};
 }
 
+namespace std {
+
+template <>
+struct hash<CompileData>
+{
+  std::size_t operator()(CompileData const& in) const
+  {
+    using std::hash;
+    size_t result =
+      hash<std::string>()(in.Language) ^ hash<std::string>()(in.Sysroot);
+    for (auto const& i : in.Includes) {
+      result = result ^
+        (hash<std::string>()(i.Path.Value) ^
+         hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
+         (i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
+    }
+    for (auto const& i : in.Flags) {
+      result = result ^ hash<std::string>()(i.Value) ^
+        hash<Json::ArrayIndex>()(i.Backtrace.Index);
+    }
+    for (auto const& i : in.Defines) {
+      result = result ^ hash<std::string>()(i.Value) ^
+        hash<Json::ArrayIndex>()(i.Backtrace.Index);
+    }
+    return result;
+  }
+};
+
+} // namespace std
+
+namespace {
 class Target
 {
   cmGeneratorTarget* GT;
@@ -271,24 +342,32 @@
 
   struct CompileGroup
   {
-    std::map<Json::Value, Json::ArrayIndex>::iterator Entry;
+    std::unordered_map<CompileData, Json::ArrayIndex>::iterator Entry;
     Json::Value SourceIndexes = Json::arrayValue;
   };
-  std::map<Json::Value, Json::ArrayIndex> CompileGroupMap;
+  std::unordered_map<CompileData, Json::ArrayIndex> CompileGroupMap;
   std::vector<CompileGroup> CompileGroups;
 
+  template <typename T>
+  JBT<T> ToJBT(BT<T> const& bt)
+  {
+    return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace));
+  }
+
   void ProcessLanguages();
   void ProcessLanguage(std::string const& lang);
 
   Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si);
   CompileData BuildCompileData(cmSourceFile* sf);
+  CompileData MergeCompileData(CompileData const& fd);
   Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf,
                                          Json::ArrayIndex si);
   void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
+  void AddBacktrace(Json::Value& object, JBTIndex bt);
   Json::Value DumpPaths();
-  Json::Value DumpCompileData(CompileData cd);
+  Json::Value DumpCompileData(CompileData const& cd);
   Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
-  Json::Value DumpDefine(BT<std::string> const& def);
+  Json::Value DumpDefine(JBT<std::string> const& def);
   Json::Value DumpSources();
   Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
                          Json::ArrayIndex si);
@@ -305,8 +384,8 @@
   Json::Value DumpLink();
   Json::Value DumpArchive();
   Json::Value DumpLinkCommandFragments();
-  Json::Value DumpCommandFragments(std::vector<BT<std::string>> const& frags);
-  Json::Value DumpCommandFragment(BT<std::string> const& frag,
+  Json::Value DumpCommandFragments(std::vector<JBT<std::string>> const& frags);
+  Json::Value DumpCommandFragment(JBT<std::string> const& frag,
                                   std::string const& role = std::string());
   Json::Value DumpDependencies();
   Json::Value DumpDependency(cmTargetDepend const& td);
@@ -721,16 +800,20 @@
     // which may need to be factored out.
     std::string flags;
     lg->GetTargetCompileFlags(this->GT, this->Config, lang, flags);
-    cd.Flags.emplace_back(std::move(flags), cmListFileBacktrace());
+    cd.Flags.emplace_back(std::move(flags), JBTIndex());
   }
   std::set<BT<std::string>> defines =
     lg->GetTargetDefines(this->GT, this->Config, lang);
-  cd.SetDefines(defines);
+  cd.Defines.reserve(defines.size());
+  for (BT<std::string> const& d : defines) {
+    cd.Defines.emplace_back(this->ToJBT(d));
+  }
   std::vector<BT<std::string>> includePathList =
     lg->GetIncludeDirectories(this->GT, lang, this->Config);
   for (BT<std::string> const& i : includePathList) {
     cd.Includes.emplace_back(
-      i, this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
+      this->ToJBT(i),
+      this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
   }
 }
 
@@ -757,26 +840,22 @@
   if (fd.Language.empty()) {
     return fd;
   }
-  CompileData const& cd = this->CompileDataMap.at(fd.Language);
-
-  fd.Sysroot = cd.Sysroot;
 
   cmLocalGenerator* lg = this->GT->GetLocalGenerator();
   cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT,
                                                     fd.Language);
 
-  fd.Flags = cd.Flags;
   const std::string COMPILE_FLAGS("COMPILE_FLAGS");
   if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) {
     std::string flags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
-    fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace());
+    fd.Flags.emplace_back(std::move(flags), JBTIndex());
   }
   const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
   if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) {
     std::string flags;
     lg->AppendCompileOptions(
       flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
-    fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace());
+    fd.Flags.emplace_back(std::move(flags), JBTIndex());
   }
 
   // Add include directories from source file properties.
@@ -795,8 +874,6 @@
       }
     }
   }
-  fd.Includes.insert(fd.Includes.end(), cd.Includes.begin(),
-                     cd.Includes.end());
 
   const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
   std::set<std::string> fileDefines;
@@ -813,27 +890,62 @@
       genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS));
   }
 
-  std::set<BT<std::string>> defines;
-  defines.insert(fileDefines.begin(), fileDefines.end());
-  defines.insert(cd.Defines.begin(), cd.Defines.end());
-
-  fd.SetDefines(defines);
+  fd.Defines.reserve(fileDefines.size());
+  for (std::string const& d : fileDefines) {
+    fd.Defines.emplace_back(d, JBTIndex());
+  }
 
   return fd;
 }
 
+CompileData Target::MergeCompileData(CompileData const& fd)
+{
+  CompileData cd;
+  cd.Language = fd.Language;
+  if (cd.Language.empty()) {
+    return cd;
+  }
+  CompileData const& td = this->CompileDataMap.at(cd.Language);
+
+  // All compile groups share the sysroot of the target.
+  cd.Sysroot = td.Sysroot;
+
+  // Use target-wide flags followed by source-specific flags.
+  cd.Flags.reserve(td.Flags.size() + fd.Flags.size());
+  cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end());
+  cd.Flags.insert(cd.Flags.end(), fd.Flags.begin(), fd.Flags.end());
+
+  // Use source-specific includes followed by target-wide includes.
+  cd.Includes.reserve(fd.Includes.size() + td.Includes.size());
+  cd.Includes.insert(cd.Includes.end(), fd.Includes.begin(),
+                     fd.Includes.end());
+  cd.Includes.insert(cd.Includes.end(), td.Includes.begin(),
+                     td.Includes.end());
+
+  // Use target-wide defines followed by source-specific defines.
+  cd.Defines.reserve(td.Defines.size() + fd.Defines.size());
+  cd.Defines.insert(cd.Defines.end(), td.Defines.begin(), td.Defines.end());
+  cd.Defines.insert(cd.Defines.end(), fd.Defines.begin(), fd.Defines.end());
+
+  // De-duplicate defines.
+  std::stable_sort(cd.Defines.begin(), cd.Defines.end(),
+                   JBT<std::string>::ValueLess);
+  auto end = std::unique(cd.Defines.begin(), cd.Defines.end(),
+                         JBT<std::string>::ValueEq);
+  cd.Defines.erase(end, cd.Defines.end());
+
+  return cd;
+}
+
 Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf,
                                                Json::ArrayIndex si)
 {
-  Json::Value compileDataJson =
-    this->DumpCompileData(this->BuildCompileData(sf));
-  std::map<Json::Value, Json::ArrayIndex>::iterator i =
-    this->CompileGroupMap.find(compileDataJson);
+  CompileData compileData = this->BuildCompileData(sf);
+  auto i = this->CompileGroupMap.find(compileData);
   if (i == this->CompileGroupMap.end()) {
     Json::ArrayIndex cgIndex =
       static_cast<Json::ArrayIndex>(this->CompileGroups.size());
-    i =
-      this->CompileGroupMap.emplace(std::move(compileDataJson), cgIndex).first;
+    i = this->CompileGroupMap.emplace(std::move(compileData), cgIndex).first;
     CompileGroup g;
     g.Entry = i;
     this->CompileGroups.push_back(std::move(g));
@@ -844,9 +956,15 @@
 
 void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt)
 {
-  Json::ArrayIndex backtrace;
-  if (this->Backtraces.Add(bt, backtrace)) {
-    object["backtrace"] = backtrace;
+  if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
+    object["backtrace"] = backtrace.Index;
+  }
+}
+
+void Target::AddBacktrace(Json::Value& object, JBTIndex bt)
+{
+  if (bt) {
+    object["backtrace"] = bt.Index;
   }
 }
 
@@ -914,7 +1032,7 @@
   return source;
 }
 
-Json::Value Target::DumpCompileData(CompileData cd)
+Json::Value Target::DumpCompileData(CompileData const& cd)
 {
   Json::Value result = Json::objectValue;
 
@@ -936,7 +1054,7 @@
   }
   if (!cd.Defines.empty()) {
     Json::Value defines = Json::arrayValue;
-    for (BT<std::string> const& d : cd.Defines) {
+    for (JBT<std::string> const& d : cd.Defines) {
       defines.append(this->DumpDefine(d));
     }
     result["defines"] = std::move(defines);
@@ -956,7 +1074,7 @@
   return include;
 }
 
-Json::Value Target::DumpDefine(BT<std::string> const& def)
+Json::Value Target::DumpDefine(JBT<std::string> const& def)
 {
   Json::Value define = Json::objectValue;
   define["define"] = def.Value;
@@ -992,7 +1110,8 @@
 
 Json::Value Target::DumpCompileGroup(CompileGroup& cg)
 {
-  Json::Value group = cg.Entry->first;
+  Json::Value group =
+    this->DumpCompileData(this->MergeCompileData(cg.Entry->first));
   group["sourceIndexes"] = std::move(cg.SourceIndexes);
   return group;
 }
@@ -1072,17 +1191,16 @@
   }
 
   // Add Windows-specific artifacts produced by the linker.
+  if (this->GT->HasImportLibrary(this->Config)) {
+    Json::Value artifact = Json::objectValue;
+    artifact["path"] =
+      RelativeIfUnder(this->TopBuild,
+                      this->GT->GetFullPath(
+                        this->Config, cmStateEnums::ImportLibraryArtifact));
+    artifacts.append(std::move(artifact)); // NOLINT(*)
+  }
   if (this->GT->IsDLLPlatform() &&
       this->GT->GetType() != cmStateEnums::STATIC_LIBRARY) {
-    if (this->GT->GetType() == cmStateEnums::SHARED_LIBRARY ||
-        this->GT->IsExecutableWithExports()) {
-      Json::Value artifact = Json::objectValue;
-      artifact["path"] =
-        RelativeIfUnder(this->TopBuild,
-                        this->GT->GetFullPath(
-                          this->Config, cmStateEnums::ImportLibraryArtifact));
-      artifacts.append(std::move(artifact)); // NOLINT(*)
-    }
     cmGeneratorTarget::OutputInfo const* output =
       this->GT->GetOutputInfo(this->Config);
     if (output && !output->PdbDir.empty()) {
@@ -1187,16 +1305,16 @@
 }
 
 Json::Value Target::DumpCommandFragments(
-  std::vector<BT<std::string>> const& frags)
+  std::vector<JBT<std::string>> const& frags)
 {
   Json::Value commandFragments = Json::arrayValue;
-  for (BT<std::string> const& f : frags) {
+  for (JBT<std::string> const& f : frags) {
     commandFragments.append(this->DumpCommandFragment(f));
   }
   return commandFragments;
 }
 
-Json::Value Target::DumpCommandFragment(BT<std::string> const& frag,
+Json::Value Target::DumpCommandFragment(JBT<std::string> const& frag,
                                         std::string const& role)
 {
   Json::Value fragment = Json::objectValue;
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 7a3954e..22f0d1f 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -12,13 +12,16 @@
 #include <assert.h>
 #include <cmath>
 #include <ctype.h>
-#include <memory> // IWYU pragma: keep
+#include <map>
+#include <set>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmArgumentParser.h"
 #include "cmCryptoHash.h"
@@ -34,6 +37,9 @@
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmRange.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"
 #include "cm_sys_stat.h"
@@ -184,6 +190,9 @@
   if (subCommand == "CREATE_LINK") {
     return this->HandleCreateLinkCommand(args);
   }
+  if (subCommand == "GET_RUNTIME_DEPENDENCIES") {
+    return this->HandleGetRuntimeDependenciesCommand(args);
+  }
 
   std::string e = "does not recognize sub-command " + subCommand;
   this->SetError(e);
@@ -357,7 +366,7 @@
       }
     }
   }
-  this->Makefile->AddDefinition(variable, output.c_str());
+  this->Makefile->AddDefinition(variable, output);
   return true;
 }
 
@@ -375,7 +384,7 @@
   if (hash) {
     std::string out = hash->HashFile(args[1]);
     if (!out.empty()) {
-      this->Makefile->AddDefinition(args[2], out.c_str());
+      this->Makefile->AddDefinition(args[2], out);
       return true;
     }
     std::ostringstream e;
@@ -743,7 +752,7 @@
   }
 
   // Save the output in a makefile variable.
-  this->Makefile->AddDefinition(outVar, output.c_str());
+  this->Makefile->AddDefinition(outVar, output);
   return true;
 }
 
@@ -930,7 +939,7 @@
 
   std::sort(files.begin(), files.end());
   files.erase(std::unique(files.begin(), files.end()), files.end());
-  this->Makefile->AddDefinition(variable, cmJoin(files, ";").c_str());
+  this->Makefile->AddDefinition(variable, cmJoin(files, ";"));
   return true;
 }
 
@@ -1063,6 +1072,7 @@
   std::string file;
   const char* oldRPath = nullptr;
   const char* newRPath = nullptr;
+  bool removeEnvironmentRPath = false;
   enum Doing
   {
     DoingNone,
@@ -1078,6 +1088,8 @@
       doing = DoingNew;
     } else if (args[i] == "FILE") {
       doing = DoingFile;
+    } else if (args[i] == "INSTALL_REMOVE_ENVIRONMENT_RPATH") {
+      removeEnvironmentRPath = true;
     } else if (doing == DoingFile) {
       file = args[i];
       doing = DoingNone;
@@ -1116,7 +1128,9 @@
   cmFileTimes const ft(file);
   std::string emsg;
   bool changed;
-  if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, &emsg, &changed)) {
+
+  if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath,
+                                  removeEnvironmentRPath, &emsg, &changed)) {
     std::ostringstream e;
     /* clang-format off */
     e << "RPATH_CHANGE could not write new RPATH:\n"
@@ -1290,14 +1304,14 @@
     if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
       std::string rpath(se_rpath->Value);
       std::replace(rpath.begin(), rpath.end(), ':', ';');
-      this->Makefile->AddDefinition(arguments.RPath, rpath.c_str());
+      this->Makefile->AddDefinition(arguments.RPath, rpath);
     }
   }
   if (!arguments.RunPath.empty()) {
     if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
       std::string runpath(se_runpath->Value);
       std::replace(runpath.begin(), runpath.end(), ':', ';');
-      this->Makefile->AddDefinition(arguments.RunPath, runpath.c_str());
+      this->Makefile->AddDefinition(arguments.RunPath, runpath);
     }
   }
 
@@ -1308,7 +1322,7 @@
     this->SetError(error);
     return false;
   }
-  this->Makefile->AddDefinition(arguments.Error, error.c_str());
+  this->Makefile->AddDefinition(arguments.Error, error);
   return true;
 #endif
 }
@@ -1346,7 +1360,7 @@
   }
 
   std::string res = cmSystemTools::RelativePath(directoryName, fileName);
-  this->Makefile->AddDefinition(outVar, res.c_str());
+  this->Makefile->AddDefinition(outVar, res);
   return true;
 }
 
@@ -1452,7 +1466,7 @@
 
   std::string value = cmJoin(
     cmMakeRange(path).transform(nativePath ? ToNativePath : ToCMakePath), ";");
-  this->Makefile->AddDefinition(args[2], value.c_str());
+  this->Makefile->AddDefinition(args[2], value);
   return true;
 }
 
@@ -1792,7 +1806,7 @@
       if (!statusVar.empty()) {
         std::ostringstream result;
         result << 0 << ";\"" << msg;
-        this->Makefile->AddDefinition(statusVar, result.str().c_str());
+        this->Makefile->AddDefinition(statusVar, result.str());
       }
       return true;
     }
@@ -1941,7 +1955,7 @@
     std::ostringstream result;
     result << static_cast<int>(res) << ";\"" << ::curl_easy_strerror(res)
            << "\"";
-    this->Makefile->AddDefinition(statusVar, result.str().c_str());
+    this->Makefile->AddDefinition(statusVar, result.str());
   }
 
   ::curl_global_cleanup();
@@ -1973,7 +1987,7 @@
         std::string status = "1;HASH mismatch: "
                              "expected: " +
           expectedHash + " actual: " + actualHash;
-        this->Makefile->AddDefinition(statusVar, status.c_str());
+        this->Makefile->AddDefinition(statusVar, status);
       }
 
       this->SetError(oss.str());
@@ -2228,7 +2242,7 @@
     std::ostringstream result;
     result << static_cast<int>(res) << ";\"" << ::curl_easy_strerror(res)
            << "\"";
-    this->Makefile->AddDefinition(statusVar, result.str().c_str());
+    this->Makefile->AddDefinition(statusVar, result.str());
   }
 
   ::curl_global_cleanup();
@@ -2253,7 +2267,7 @@
       log += "\n";
     }
 
-    this->Makefile->AddDefinition(logVar, log.c_str());
+    this->Makefile->AddDefinition(logVar, log);
   }
 
   return true;
@@ -2471,7 +2485,7 @@
   }
 
   if (!resultVariable.empty()) {
-    this->Makefile->AddDefinition(resultVariable, result.c_str());
+    this->Makefile->AddDefinition(resultVariable, result);
   }
 
   return true;
@@ -2520,7 +2534,7 @@
   cmTimestamp timestamp;
   std::string result =
     timestamp.FileModificationTime(filename.c_str(), formatString, utcFlag);
-  this->Makefile->AddDefinition(outputVariable, result.c_str());
+  this->Makefile->AddDefinition(outputVariable, result);
 
   return true;
 }
@@ -2548,8 +2562,7 @@
   }
 
   this->Makefile->AddDefinition(
-    outputVariable,
-    std::to_string(cmSystemTools::FileLength(filename)).c_str());
+    outputVariable, std::to_string(cmSystemTools::FileLength(filename)));
 
   return true;
 }
@@ -2576,7 +2589,7 @@
     return false;
   }
 
-  this->Makefile->AddDefinition(outputVariable, result.c_str());
+  this->Makefile->AddDefinition(outputVariable, result);
 
   return true;
 }
@@ -2622,7 +2635,7 @@
   if (fileName == newFileName) {
     result = "CREATE_LINK cannot use same file and newfile";
     if (!arguments.Result.empty()) {
-      this->Makefile->AddDefinition(arguments.Result, result.c_str());
+      this->Makefile->AddDefinition(arguments.Result, result);
       return true;
     }
     this->SetError(result);
@@ -2633,7 +2646,7 @@
   if (!arguments.Symbolic && !cmSystemTools::FileExists(fileName)) {
     result = "Cannot hard link \'" + fileName + "\' as it does not exist.";
     if (!arguments.Result.empty()) {
-      this->Makefile->AddDefinition(arguments.Result, result.c_str());
+      this->Makefile->AddDefinition(arguments.Result, result);
       return true;
     }
     this->SetError(result);
@@ -2650,7 +2663,7 @@
       << cmSystemTools::GetLastSystemError() << "\n";
 
     if (!arguments.Result.empty()) {
-      this->Makefile->AddDefinition(arguments.Result, e.str().c_str());
+      this->Makefile->AddDefinition(arguments.Result, e.str());
       return true;
     }
     this->SetError(e.str());
@@ -2685,8 +2698,174 @@
   }
 
   if (!arguments.Result.empty()) {
-    this->Makefile->AddDefinition(arguments.Result, result.c_str());
+    this->Makefile->AddDefinition(arguments.Result, result);
   }
 
   return true;
 }
+
+bool cmFileCommand::HandleGetRuntimeDependenciesCommand(
+  std::vector<std::string> const& args)
+{
+  static const std::set<std::string> supportedPlatforms = { "Windows", "Linux",
+                                                            "Darwin" };
+  std::string platform =
+    this->Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+  if (!supportedPlatforms.count(platform)) {
+    std::ostringstream e;
+    e << "GET_RUNTIME_DEPENDENCIES is not supported on system \"" << platform
+      << "\"";
+    this->SetError(e.str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+
+  if (this->Makefile->GetState()->GetMode() == cmState::Project) {
+    this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING,
+                                 "You have used file(GET_RUNTIME_DEPENDENCIES)"
+                                 " in project mode. This is probably not what "
+                                 "you intended to do. Instead, please consider"
+                                 " using it in an install(CODE) or "
+                                 "install(SCRIPT) command. For example:"
+                                 "\n  install(CODE [["
+                                 "\n    file(GET_RUNTIME_DEPENDENCIES"
+                                 "\n      # ..."
+                                 "\n      )"
+                                 "\n    ]])");
+  }
+
+  struct Arguments
+  {
+    std::string ResolvedDependenciesVar;
+    std::string UnresolvedDependenciesVar;
+    std::string ConflictingDependenciesPrefix;
+    std::string BundleExecutable;
+    std::vector<std::string> Executables;
+    std::vector<std::string> Libraries;
+    std::vector<std::string> Directories;
+    std::vector<std::string> Modules;
+    std::vector<std::string> PreIncludeRegexes;
+    std::vector<std::string> PreExcludeRegexes;
+    std::vector<std::string> PostIncludeRegexes;
+    std::vector<std::string> PostExcludeRegexes;
+  };
+
+  static auto const parser =
+    cmArgumentParser<Arguments>{}
+      .Bind("RESOLVED_DEPENDENCIES_VAR"_s, &Arguments::ResolvedDependenciesVar)
+      .Bind("UNRESOLVED_DEPENDENCIES_VAR"_s,
+            &Arguments::UnresolvedDependenciesVar)
+      .Bind("CONFLICTING_DEPENDENCIES_PREFIX"_s,
+            &Arguments::ConflictingDependenciesPrefix)
+      .Bind("BUNDLE_EXECUTABLE"_s, &Arguments::BundleExecutable)
+      .Bind("EXECUTABLES"_s, &Arguments::Executables)
+      .Bind("LIBRARIES"_s, &Arguments::Libraries)
+      .Bind("MODULES"_s, &Arguments::Modules)
+      .Bind("DIRECTORIES"_s, &Arguments::Directories)
+      .Bind("PRE_INCLUDE_REGEXES"_s, &Arguments::PreIncludeRegexes)
+      .Bind("PRE_EXCLUDE_REGEXES"_s, &Arguments::PreExcludeRegexes)
+      .Bind("POST_INCLUDE_REGEXES"_s, &Arguments::PostIncludeRegexes)
+      .Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes);
+
+  std::vector<std::string> unrecognizedArguments;
+  std::vector<std::string> keywordsMissingValues;
+  auto parsedArgs =
+    parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
+                 &keywordsMissingValues);
+  auto argIt = unrecognizedArguments.begin();
+  if (argIt != unrecognizedArguments.end()) {
+    std::ostringstream e;
+    e << "Unrecognized argument: \"" << *argIt << "\"";
+    this->SetError(e.str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+  argIt = keywordsMissingValues.begin();
+  if (argIt != keywordsMissingValues.end()) {
+    std::ostringstream e;
+    e << "Keyword missing value: " << *argIt;
+    this->SetError(e.str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+
+  cmRuntimeDependencyArchive archive(
+    this, parsedArgs.Directories, parsedArgs.BundleExecutable,
+    parsedArgs.PreIncludeRegexes, parsedArgs.PreExcludeRegexes,
+    parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes);
+  if (!archive.Prepare()) {
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+
+  if (!archive.GetRuntimeDependencies(
+        parsedArgs.Executables, parsedArgs.Libraries, parsedArgs.Modules)) {
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+
+  std::vector<std::string> deps, unresolvedDeps, conflictingDeps;
+  for (auto const& val : archive.GetResolvedPaths()) {
+    bool unique = true;
+    auto it = val.second.begin();
+    assert(it != val.second.end());
+    auto const& firstPath = *it;
+    while (++it != val.second.end()) {
+      if (!cmSystemTools::SameFile(firstPath, *it)) {
+        unique = false;
+        break;
+      }
+    }
+
+    if (unique) {
+      deps.push_back(firstPath);
+    } else if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
+      conflictingDeps.push_back(val.first);
+      std::vector<std::string> paths;
+      paths.insert(paths.begin(), val.second.begin(), val.second.end());
+      std::string varName =
+        parsedArgs.ConflictingDependenciesPrefix + "_" + val.first;
+      std::string pathsStr = cmJoin(paths, ";");
+      this->Makefile->AddDefinition(varName, pathsStr);
+    } else {
+      std::ostringstream e;
+      e << "Multiple conflicting paths found for " << val.first << ":";
+      for (auto const& path : val.second) {
+        e << "\n  " << path;
+      }
+      this->SetError(e.str());
+      cmSystemTools::SetFatalErrorOccured();
+      return false;
+    }
+  }
+  if (!archive.GetUnresolvedPaths().empty()) {
+    if (!parsedArgs.UnresolvedDependenciesVar.empty()) {
+      unresolvedDeps.insert(unresolvedDeps.begin(),
+                            archive.GetUnresolvedPaths().begin(),
+                            archive.GetUnresolvedPaths().end());
+    } else {
+      auto it = archive.GetUnresolvedPaths().begin();
+      assert(it != archive.GetUnresolvedPaths().end());
+      std::ostringstream e;
+      e << "Could not resolve file " << *it;
+      this->SetError(e.str());
+      cmSystemTools::SetFatalErrorOccured();
+      return false;
+    }
+  }
+
+  if (!parsedArgs.ResolvedDependenciesVar.empty()) {
+    std::string val = cmJoin(deps, ";");
+    this->Makefile->AddDefinition(parsedArgs.ResolvedDependenciesVar, val);
+  }
+  if (!parsedArgs.UnresolvedDependenciesVar.empty()) {
+    std::string val = cmJoin(unresolvedDeps, ";");
+    this->Makefile->AddDefinition(parsedArgs.UnresolvedDependenciesVar, val);
+  }
+  if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
+    std::string val = cmJoin(conflictingDeps, ";");
+    this->Makefile->AddDefinition(
+      parsedArgs.ConflictingDependenciesPrefix + "_FILENAMES", val);
+  }
+  return true;
+}
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 12c5115..d4b980e 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -22,7 +24,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFileCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFileCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
@@ -62,6 +67,8 @@
   bool HandleSizeCommand(std::vector<std::string> const& args);
   bool HandleReadSymlinkCommand(std::vector<std::string> const& args);
   bool HandleCreateLinkCommand(std::vector<std::string> const& args);
+  bool HandleGetRuntimeDependenciesCommand(
+    std::vector<std::string> const& args);
 
 private:
   void AddEvaluationFile(const std::string& inputName,
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 49e8cd5..4f1a158 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -174,11 +174,8 @@
     cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
     for (const auto& arg : items) {
       if (!this->CheckPermissions(arg, **mode)) {
-        std::ostringstream e;
-        e << this->FileCommand->GetError()
-          << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
-             "variable.";
-        this->FileCommand->SetError(e.str());
+        this->FileCommand->SetError(
+          " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.");
         return false;
       }
     }
diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx
index d4f76fd..9378439 100644
--- a/Source/cmFileInstaller.cxx
+++ b/Source/cmFileInstaller.cxx
@@ -38,7 +38,7 @@
 {
   // Save the updated install manifest.
   this->Makefile->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
-                                this->Manifest.c_str());
+                                this->Manifest);
 }
 
 void cmFileInstaller::ManifestAppend(std::string const& file)
diff --git a/Source/cmFileTimes.cxx b/Source/cmFileTimes.cxx
index fd4f679..3824e9b 100644
--- a/Source/cmFileTimes.cxx
+++ b/Source/cmFileTimes.cxx
@@ -2,11 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFileTimes.h"
 
-#include "cmAlgorithms.h"
 #include "cm_sys_stat.h"
 
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #if defined(_WIN32)
 #  include "cmSystemTools.h"
 #  include <windows.h>
diff --git a/Source/cmFileTimes.h b/Source/cmFileTimes.h
index cbf0fe2..191d89e 100644
--- a/Source/cmFileTimes.h
+++ b/Source/cmFileTimes.h
@@ -5,7 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 
 /** \class cmFileTimes
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index e590802..b1ccc83 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -13,6 +13,7 @@
 #include "cmSearchPath.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmFindBase::cmFindBase()
@@ -67,6 +68,9 @@
   }
   this->AlreadyInCache = false;
 
+  // Find what search path locations have been enabled/disable
+  this->SelectDefaultSearchModes();
+
   // Find the current root path mode.
   this->SelectDefaultRootPathMode();
 
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 954558f..a5937a0 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -3,6 +3,7 @@
 #include "cmFindCommon.h"
 
 #include <algorithm>
+#include <array>
 #include <string.h>
 #include <utility>
 
@@ -144,6 +145,26 @@
   }
 }
 
+void cmFindCommon::SelectDefaultSearchModes()
+{
+  const std::array<std::pair<bool&, std::string>, 5> search_paths = {
+    { { this->NoPackageRootPath, "CMAKE_FIND_USE_PACKAGE_ROOT_PATH" },
+      { this->NoCMakePath, "CMAKE_FIND_USE_CMAKE_PATH" },
+      { this->NoCMakeEnvironmentPath,
+        "CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH" },
+      { this->NoSystemEnvironmentPath,
+        "CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH" },
+      { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" } }
+  };
+
+  for (auto& path : search_paths) {
+    const char* def = this->Makefile->GetDefinition(path.second);
+    if (def) {
+      path.first = !cmSystemTools::IsOn(def);
+    }
+  }
+}
+
 void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
 {
 #if 0
diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h
index 89ff174..d95eeb1 100644
--- a/Source/cmFindCommon.h
+++ b/Source/cmFindCommon.h
@@ -90,6 +90,9 @@
   /** Compute the current default bundle/framework search policy.  */
   void SelectDefaultMacMode();
 
+  /** Compute the current default search modes based on global variables.  */
+  void SelectDefaultSearchModes();
+
   // Path arguments prior to path manipulation routines
   std::vector<std::string> UserHintsArgs;
   std::vector<std::string> UserGuessArgs;
diff --git a/Source/cmFindFileCommand.h b/Source/cmFindFileCommand.h
index 4309449..152b505 100644
--- a/Source/cmFindFileCommand.h
+++ b/Source/cmFindFileCommand.h
@@ -5,9 +5,10 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include "cmFindPathCommand.h"
+#include "cm_memory.hxx"
 
-class cmCommand;
+#include "cmCommand.h"
+#include "cmFindPathCommand.h"
 
 /** \class cmFindFileCommand
  * \brief Define a command to search for an executable program.
@@ -24,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFindFileCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFindFileCommand>();
+  }
 };
 
 #endif
diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h
index fb8a700..af17d60 100644
--- a/Source/cmFindLibraryCommand.h
+++ b/Source/cmFindLibraryCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmFindBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 
 /** \class cmFindLibraryCommand
@@ -27,7 +29,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFindLibraryCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFindLibraryCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 1d4a8ed..04fbbad 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -13,12 +13,13 @@
 #include <deque>
 #include <functional>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 #include <string.h>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
@@ -27,6 +28,7 @@
 #include "cmSearchPath.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmVersion.h"
 
 #if defined(__HAIKU__)
@@ -188,7 +190,12 @@
   }
 
   // Check if User Package Registry should be disabled
-  if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
+  // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has
+  // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
+  if (const char* def =
+        this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) {
+    this->NoUserRegistry = !cmSystemTools::IsOn(def);
+  } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
     this->NoUserRegistry = true;
   }
 
@@ -219,6 +226,9 @@
     this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec;
   }
 
+  // Find what search path locations have been enabled/disable
+  this->SelectDefaultSearchModes();
+
   // Find the current root path mode.
   this->SelectDefaultRootPathMode();
 
@@ -669,7 +679,9 @@
   } else {
     this->OriginalDefs[var].exists = false;
   }
-  this->Makefile->AddDefinition(var, val);
+  if (val) {
+    this->Makefile->AddDefinition(var, val);
+  }
 }
 
 void cmFindPackageCommand::RestoreFindDefinitions()
@@ -677,7 +689,7 @@
   for (auto const& i : this->OriginalDefs) {
     OriginalDef const& od = i.second;
     if (od.exists) {
-      this->Makefile->AddDefinition(i.first, od.value.c_str());
+      this->Makefile->AddDefinition(i.first, od.value);
     } else {
       this->Makefile->RemoveDefinition(i.first);
     }
@@ -732,12 +744,6 @@
 {
   this->ConsideredConfigs.clear();
 
-  // Support old capitalization behavior.
-  std::string upperDir = cmSystemTools::UpperCase(this->Name);
-  std::string upperFound = cmSystemTools::UpperCase(this->Name);
-  upperDir += "_DIR";
-  upperFound += "_FOUND";
-
   // Try to find the config file.
   const char* def = this->Makefile->GetDefinition(this->Variable);
 
@@ -957,7 +963,7 @@
   std::string fileVar = this->Name;
   fileVar += "_CONFIG";
   if (found) {
-    this->Makefile->AddDefinition(fileVar, this->FileFound.c_str());
+    this->Makefile->AddDefinition(fileVar, this->FileFound);
   } else {
     this->Makefile->RemoveDefinition(fileVar);
   }
@@ -979,11 +985,9 @@
     sep = ";";
   }
 
-  this->Makefile->AddDefinition(consideredConfigsVar,
-                                consideredConfigFiles.c_str());
+  this->Makefile->AddDefinition(consideredConfigsVar, consideredConfigFiles);
 
-  this->Makefile->AddDefinition(consideredVersionsVar,
-                                consideredVersions.c_str());
+  this->Makefile->AddDefinition(consideredVersionsVar, consideredVersions);
 
   return result;
 }
@@ -1612,8 +1616,8 @@
   this->Makefile->RemoveDefinition("PACKAGE_VERSION_EXACT");
 
   // Set the input variables.
-  this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name.c_str());
-  this->Makefile->AddDefinition("PACKAGE_FIND_VERSION", this->Version.c_str());
+  this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name);
+  this->Makefile->AddDefinition("PACKAGE_FIND_VERSION", this->Version);
   char buf[64];
   sprintf(buf, "%u", this->VersionMajor);
   this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MAJOR", buf);
@@ -1690,7 +1694,7 @@
   if (this->VersionFound.empty()) {
     this->Makefile->RemoveDefinition(ver);
   } else {
-    this->Makefile->AddDefinition(ver, this->VersionFound.c_str());
+    this->Makefile->AddDefinition(ver, this->VersionFound);
   }
 
   // Store the version components.
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index 316ca0f..f6645ae 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -3,6 +3,7 @@
 #ifndef cmFindPackageCommand_h
 #define cmFindPackageCommand_h
 
+#include "cmCommand.h"
 #include "cmConfigure.h" // IWYU pragma: keep
 #include "cmPolicies.h"
 
@@ -14,6 +15,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 // IWYU insists we should forward-declare instead of including <functional>,
 // but we cannot forward-declare reliably because some C++ standard libraries
 // put the template in an inline namespace.
@@ -27,7 +30,6 @@
 
 #include "cmFindCommon.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmSearchPath;
 
@@ -65,7 +67,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFindPackageCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFindPackageCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h
index cb0db4c..89e2cef 100644
--- a/Source/cmFindPathCommand.h
+++ b/Source/cmFindPathCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmFindBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 
 /** \class cmFindPathCommand
@@ -27,7 +29,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFindPathCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFindPathCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 782f746..8fcf1ac 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -4,6 +4,7 @@
 
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -71,7 +72,7 @@
   bool CheckDirectoryForName(std::string const& path, std::string const& name)
   {
     for (std::string const& ext : this->Extensions) {
-      if (!ext.empty() && cmSystemTools::StringEndsWith(name, ext.c_str())) {
+      if (!ext.empty() && cmHasSuffix(name, ext)) {
         continue;
       }
       this->TestNameExt = name;
diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h
index 147936c..40e455e 100644
--- a/Source/cmFindProgramCommand.h
+++ b/Source/cmFindProgramCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmFindBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 
 /** \class cmFindProgramCommand
@@ -28,7 +30,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFindProgramCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFindProgramCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 08003eb..06dce2c 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -2,12 +2,13 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmForEachCommand.h"
 
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
+#include <utility>
 
-#include "cmAlgorithms.h"
+#include "cm_memory.hxx"
+
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
@@ -52,21 +53,21 @@
 
       for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
         // set the variable to the loop value
-        mf.AddDefinition(this->Args[0], arg.c_str());
+        mf.AddDefinition(this->Args[0], arg);
         // Invoke all the functions that were collected in the block.
-        cmExecutionStatus status;
+        cmExecutionStatus status(mf);
         for (cmListFileFunction const& func : this->Functions) {
           status.Clear();
           mf.ExecuteCommand(func, status);
           if (status.GetReturnInvoked()) {
             inStatus.SetReturnInvoked();
             // restore the variable to its prior value
-            mf.AddDefinition(this->Args[0], oldDef.c_str());
+            mf.AddDefinition(this->Args[0], oldDef);
             return true;
           }
           if (status.GetBreakInvoked()) {
             // restore the variable to its prior value
-            mf.AddDefinition(this->Args[0], oldDef.c_str());
+            mf.AddDefinition(this->Args[0], oldDef);
             return true;
           }
           if (status.GetContinueInvoked()) {
@@ -79,7 +80,7 @@
       }
 
       // restore the variable to its prior value
-      mf.AddDefinition(this->Args[0], oldDef.c_str());
+      mf.AddDefinition(this->Args[0], oldDef);
       return true;
     }
     // close out a nested foreach
@@ -121,7 +122,7 @@
   }
 
   // create a function blocker
-  auto f = cm::make_unique<cmForEachFunctionBlocker>(this->Makefile);
+  auto fb = cm::make_unique<cmForEachFunctionBlocker>(this->Makefile);
   if (args.size() > 1) {
     if (args[1] == "RANGE") {
       int start = 0;
@@ -168,23 +169,22 @@
           break;
         }
       }
-      f->Args = range;
+      fb->Args = range;
     } else {
-      f->Args = args;
+      fb->Args = args;
     }
   } else {
-    f->Args = args;
+    fb->Args = args;
   }
-  this->Makefile->AddFunctionBlocker(f.release());
+  this->Makefile->AddFunctionBlocker(std::move(fb));
 
   return true;
 }
 
 bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
 {
-  std::unique_ptr<cmForEachFunctionBlocker> f(
-    new cmForEachFunctionBlocker(this->Makefile));
-  f->Args.push_back(args[0]);
+  auto fb = cm::make_unique<cmForEachFunctionBlocker>(this->Makefile);
+  fb->Args.push_back(args[0]);
 
   enum Doing
   {
@@ -195,7 +195,7 @@
   Doing doing = DoingNone;
   for (unsigned int i = 2; i < args.size(); ++i) {
     if (doing == DoingItems) {
-      f->Args.push_back(args[i]);
+      fb->Args.push_back(args[i]);
     } else if (args[i] == "LISTS") {
       doing = DoingLists;
     } else if (args[i] == "ITEMS") {
@@ -203,7 +203,7 @@
     } else if (doing == DoingLists) {
       const char* value = this->Makefile->GetDefinition(args[i]);
       if (value && *value) {
-        cmSystemTools::ExpandListArgument(value, f->Args, true);
+        cmSystemTools::ExpandListArgument(value, fb->Args, true);
       }
     } else {
       std::ostringstream e;
@@ -214,7 +214,7 @@
     }
   }
 
-  this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass unique_ptr
+  this->Makefile->AddFunctionBlocker(std::move(fb));
 
   return true;
 }
diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h
index 5131a4f..cd112b8 100644
--- a/Source/cmForEachCommand.h
+++ b/Source/cmForEachCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
@@ -39,7 +41,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmForEachCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmForEachCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 9067a5f..2809cf7 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -3,6 +3,7 @@
 #include "cmFunctionCommand.h"
 
 #include <sstream>
+#include <utility>
 
 #include "cmAlgorithms.h"
 #include "cmExecutionStatus.h"
@@ -10,37 +11,18 @@
 #include "cmPolicies.h"
 #include "cmRange.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 
 // define the class for function commands
-class cmFunctionHelperCommand : public cmCommand
+class cmFunctionHelperCommand
 {
 public:
   /**
-   * This is a virtual constructor for the command.
-   */
-  cmCommand* Clone() override
-  {
-    cmFunctionHelperCommand* newC = new cmFunctionHelperCommand;
-    // we must copy when we clone
-    newC->Args = this->Args;
-    newC->Functions = this->Functions;
-    newC->Policies = this->Policies;
-    newC->FilePath = this->FilePath;
-    return newC;
-  }
-
-  /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
+  bool operator()(std::vector<cmListFileArgument> const& args,
+                  cmExecutionStatus& inStatus) const;
 
   std::vector<std::string> Args;
   std::vector<cmListFileFunction> Functions;
@@ -48,12 +30,15 @@
   std::string FilePath;
 };
 
-bool cmFunctionHelperCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
+bool cmFunctionHelperCommand::operator()(
+  std::vector<cmListFileArgument> const& args,
+  cmExecutionStatus& inStatus) const
 {
+  cmMakefile& makefile = inStatus.GetMakefile();
+
   // Expand the argument list to the function.
   std::vector<std::string> expandedArgs;
-  this->Makefile->ExpandArguments(args, expandedArgs);
+  makefile.ExpandArguments(args, expandedArgs);
 
   // make sure the number of arguments passed is at least the number
   // required by the signature
@@ -61,30 +46,30 @@
     std::string errorMsg =
       "Function invoked with incorrect arguments for function named: ";
     errorMsg += this->Args[0];
-    this->SetError(errorMsg);
+    inStatus.SetError(errorMsg);
     return false;
   }
 
-  cmMakefile::FunctionPushPop functionScope(this->Makefile, this->FilePath,
+  cmMakefile::FunctionPushPop functionScope(&makefile, this->FilePath,
                                             this->Policies);
 
   // set the value of argc
   std::ostringstream strStream;
   strStream << expandedArgs.size();
-  this->Makefile->AddDefinition("ARGC", strStream.str().c_str());
-  this->Makefile->MarkVariableAsUsed("ARGC");
+  makefile.AddDefinition("ARGC", strStream.str());
+  makefile.MarkVariableAsUsed("ARGC");
 
   // set the values for ARGV0 ARGV1 ...
   for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
     std::ostringstream tmpStream;
     tmpStream << "ARGV" << t;
-    this->Makefile->AddDefinition(tmpStream.str(), expandedArgs[t].c_str());
-    this->Makefile->MarkVariableAsUsed(tmpStream.str());
+    makefile.AddDefinition(tmpStream.str(), expandedArgs[t]);
+    makefile.MarkVariableAsUsed(tmpStream.str());
   }
 
   // define the formal arguments
   for (unsigned int j = 1; j < this->Args.size(); ++j) {
-    this->Makefile->AddDefinition(this->Args[j], expandedArgs[j - 1].c_str());
+    makefile.AddDefinition(this->Args[j], expandedArgs[j - 1]);
   }
 
   // define ARGV and ARGN
@@ -92,17 +77,16 @@
   std::vector<std::string>::const_iterator eit =
     expandedArgs.begin() + (this->Args.size() - 1);
   std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";");
-  this->Makefile->AddDefinition("ARGV", argvDef.c_str());
-  this->Makefile->MarkVariableAsUsed("ARGV");
-  this->Makefile->AddDefinition("ARGN", argnDef.c_str());
-  this->Makefile->MarkVariableAsUsed("ARGN");
+  makefile.AddDefinition("ARGV", argvDef);
+  makefile.MarkVariableAsUsed("ARGV");
+  makefile.AddDefinition("ARGN", argnDef);
+  makefile.MarkVariableAsUsed("ARGN");
 
   // Invoke all the functions that were collected in the block.
   // for each function
   for (cmListFileFunction const& func : this->Functions) {
-    cmExecutionStatus status;
-    if (!this->Makefile->ExecuteCommand(func, status) ||
-        status.GetNestedError()) {
+    cmExecutionStatus status(makefile);
+    if (!makefile.ExecuteCommand(func, status) || status.GetNestedError()) {
       // The error message should have already included the call stack
       // so we do not need to report an error here.
       functionScope.Quiet();
@@ -129,12 +113,12 @@
     // if this is the endfunction for this function then execute
     if (!this->Depth) {
       // create a new command and add it to cmake
-      cmFunctionHelperCommand* f = new cmFunctionHelperCommand();
-      f->Args = this->Args;
-      f->Functions = this->Functions;
-      f->FilePath = this->GetStartingContext().FilePath;
-      mf.RecordPolicies(f->Policies);
-      mf.GetState()->AddScriptedCommand(this->Args[0], f);
+      cmFunctionHelperCommand f;
+      f.Args = this->Args;
+      f.Functions = this->Functions;
+      f.FilePath = this->GetStartingContext().FilePath;
+      mf.RecordPolicies(f.Policies);
+      mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
       // remove the function blocker now that the function is defined
       mf.RemoveFunctionBlocker(this, lff);
       return true;
@@ -176,8 +160,10 @@
   }
 
   // create a function blocker
-  cmFunctionFunctionBlocker* f = new cmFunctionFunctionBlocker();
-  cmAppend(f->Args, args);
-  this->Makefile->AddFunctionBlocker(f);
+  {
+    auto fb = cm::make_unique<cmFunctionFunctionBlocker>();
+    cmAppend(fb->Args, args);
+    this->Makefile->AddFunctionBlocker(std::move(fb));
+  }
   return true;
 }
diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h
index 8b37df0..449a180 100644
--- a/Source/cmFunctionCommand.h
+++ b/Source/cmFunctionCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
@@ -34,7 +36,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmFunctionCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmFunctionCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 175a26d..4d3a005 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -3,7 +3,7 @@
 #include "cmGeneratorExpression.h"
 
 #include "cmsys/RegularExpression.hxx"
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <utility>
 
 #include "assert.h"
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index fd36c4b..ef76651 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -8,7 +8,7 @@
 #include "cmListFileCache.h"
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <string>
 #include <utility>
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 728f2a4..df2227f 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -2,12 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGeneratorExpressionDAGChecker.h"
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpressionContext.h"
 #include "cmGeneratorExpressionEvaluator.h"
 #include "cmGeneratorTarget.h"
 #include "cmLocalGenerator.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmake.h"
 
 #include <sstream>
@@ -68,9 +68,7 @@
         return;
       }
     }
-    const_cast<cmGeneratorExpressionDAGChecker*>(top)
-      ->Seen[this->Target]
-      .insert(this->Property);
+    top->Seen[this->Target].insert(this->Property);
   }
 }
 
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index e1fba5e..6d7d6ef 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -88,7 +88,7 @@
   const cmGeneratorExpressionDAGChecker* const Parent;
   cmGeneratorTarget const* Target;
   const std::string Property;
-  std::map<cmGeneratorTarget const*, std::set<std::string>> Seen;
+  mutable std::map<cmGeneratorTarget const*, std::set<std::string>> Seen;
   const GeneratorExpressionContent* const Content;
   const cmListFileBacktrace Backtrace;
   Result CheckResult;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 326cb0e..11c2dcc 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -3,7 +3,7 @@
 #include "cmGeneratorExpressionEvaluationFile.h"
 
 #include "cmsys/FStream.hxx"
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <utility>
 
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 89a2390..06ebeac 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -6,7 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index a60c75c..14dc7b8 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -19,6 +19,7 @@
 #include "cmState.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cm_static_string_view.hxx"
@@ -33,7 +34,7 @@
 #include <errno.h>
 #include <iterator>
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <sstream>
 #include <stdlib.h>
@@ -1038,45 +1039,38 @@
   }
 } languageAndIdNode;
 
-#define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
-
-static const char* targetPropertyTransitiveWhitelist[] = {
-  nullptr CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
-};
-
-#undef TRANSITIVE_PROPERTY_NAME
-
-template <typename T>
 std::string getLinkedTargetsContent(
-  std::vector<T> const& libraries, cmGeneratorTarget const* target,
-  cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext* context,
-  cmGeneratorExpressionDAGChecker* dagChecker,
-  const std::string& interfacePropertyName)
+  cmGeneratorTarget const* target, std::string const& prop,
+  cmGeneratorExpressionContext* context,
+  cmGeneratorExpressionDAGChecker* dagChecker)
 {
-  std::string linkedTargetsContent;
-  std::string sep;
-  std::string depString;
-  for (T const& l : libraries) {
-    // Broken code can have a target in its own link interface.
-    // Don't follow such link interface entries so as not to create a
-    // self-referencing loop.
-    if (l.Target && l.Target != target) {
-      std::string uniqueName =
-        target->GetGlobalGenerator()->IndexGeneratorTargetUniquely(l.Target);
-      depString += sep + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," +
-        interfacePropertyName + ">";
-      sep = ";";
+  std::string result;
+  if (cmLinkImplementationLibraries const* impl =
+        target->GetLinkImplementationLibraries(context->Config)) {
+    for (cmLinkImplItem const& lib : impl->Libraries) {
+      if (lib.Target) {
+        // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
+        // caller's property and hand-evaluate it as if it were compiled.
+        // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+        cmGeneratorExpressionContext libContext(
+          target->GetLocalGenerator(), context->Config, context->Quiet, target,
+          target, context->EvaluateForBuildsystem, lib.Backtrace,
+          context->Language);
+        std::string libResult =
+          lib.Target->EvaluateInterfaceProperty(prop, &libContext, dagChecker);
+        if (!libResult.empty()) {
+          if (result.empty()) {
+            result = std::move(libResult);
+          } else {
+            result.reserve(result.size() + 1 + libResult.size());
+            result += ";";
+            result += libResult;
+          }
+        }
+      }
     }
   }
-  if (!depString.empty()) {
-    linkedTargetsContent =
-      cmGeneratorExpressionNode::EvaluateDependentExpression(
-        depString, target->GetLocalGenerator(), context, headTarget, target,
-        dagChecker);
-  }
-  linkedTargetsContent =
-    cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
-  return linkedTargetsContent;
+  return result;
 }
 
 static const struct TargetPropertyNode : public cmGeneratorExpressionNode
@@ -1205,67 +1199,6 @@
       return target->GetLinkerLanguage(context->Config);
     }
 
-    cmGeneratorExpressionDAGChecker dagChecker(
-      context->Backtrace, target, propertyName, content, dagCheckerParent);
-
-    switch (dagChecker.Check()) {
-      case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
-        dagChecker.ReportError(context, content->GetOriginalExpression());
-        return std::string();
-      case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
-        // No error. We just skip cyclic references.
-        return std::string();
-      case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
-        for (size_t i = 1; i < cm::size(targetPropertyTransitiveWhitelist);
-             ++i) {
-          if (targetPropertyTransitiveWhitelist[i] == propertyName) {
-            // No error. We're not going to find anything new here.
-            return std::string();
-          }
-        }
-      case cmGeneratorExpressionDAGChecker::DAG:
-        break;
-    }
-
-    std::string prop;
-    bool haveProp = false;
-    if (const char* p = target->GetProperty(propertyName)) {
-      prop = p;
-      haveProp = true;
-    }
-
-    if (dagCheckerParent) {
-      if (dagCheckerParent->EvaluatingGenexExpression() ||
-          dagCheckerParent->EvaluatingPICExpression()) {
-        // No check required.
-      } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
-#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY)                                 \
-  (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
-        if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(
-              TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(*)
-          reportError(
-            context, content->GetOriginalExpression(),
-            "$<TARGET_PROPERTY:...> expression in link libraries "
-            "evaluation depends on target property which is transitive "
-            "over the link libraries, creating a recursion.");
-          return std::string();
-        }
-#undef TRANSITIVE_PROPERTY_COMPARE
-
-        if (!haveProp) {
-          return std::string();
-        }
-      } else {
-#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
-
-        assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
-          ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
-#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
-      }
-    }
-
-    std::string linkedTargetsContent;
-
     std::string interfacePropertyName;
     bool isInterfaceProperty = false;
 
@@ -1287,32 +1220,64 @@
       }
     }
 #undef POPULATE_INTERFACE_PROPERTY_NAME
-    cmGeneratorTarget const* headTarget =
-      context->HeadTarget && isInterfaceProperty ? context->HeadTarget
-                                                 : target;
 
-    if (isInterfaceProperty) {
-      if (cmLinkInterfaceLibraries const* iface =
-            target->GetLinkInterfaceLibraries(context->Config, headTarget,
-                                              true)) {
-        linkedTargetsContent =
-          getLinkedTargetsContent(iface->Libraries, target, headTarget,
-                                  context, &dagChecker, interfacePropertyName);
-      }
-    } else if (!interfacePropertyName.empty()) {
-      if (cmLinkImplementationLibraries const* impl =
-            target->GetLinkImplementationLibraries(context->Config)) {
-        linkedTargetsContent =
-          getLinkedTargetsContent(impl->Libraries, target, target, context,
-                                  &dagChecker, interfacePropertyName);
+    bool evaluatingLinkLibraries = false;
+
+    if (dagCheckerParent) {
+      if (dagCheckerParent->EvaluatingGenexExpression() ||
+          dagCheckerParent->EvaluatingPICExpression()) {
+        // No check required.
+      } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
+        evaluatingLinkLibraries = true;
+        if (!interfacePropertyName.empty()) {
+          reportError(
+            context, content->GetOriginalExpression(),
+            "$<TARGET_PROPERTY:...> expression in link libraries "
+            "evaluation depends on target property which is transitive "
+            "over the link libraries, creating a recursion.");
+          return std::string();
+        }
+      } else {
+#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
+        assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
+          ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
+#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
       }
     }
 
-    if (!haveProp) {
-      if (target->IsImported() ||
-          target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
-        return linkedTargetsContent;
-      }
+    if (isInterfaceProperty) {
+      return target->EvaluateInterfaceProperty(propertyName, context,
+                                               dagCheckerParent);
+    }
+
+    cmGeneratorExpressionDAGChecker dagChecker(
+      context->Backtrace, target, propertyName, content, dagCheckerParent);
+
+    switch (dagChecker.Check()) {
+      case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+        dagChecker.ReportError(context, content->GetOriginalExpression());
+        return std::string();
+      case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+        // No error. We just skip cyclic references.
+        return std::string();
+      case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+        // We handle transitive properties above.  For non-transitive
+        // properties we accept repeats anyway.
+      case cmGeneratorExpressionDAGChecker::DAG:
+        break;
+    }
+
+    std::string result;
+    bool haveProp = false;
+    if (const char* p = target->GetProperty(propertyName)) {
+      result = p;
+      haveProp = true;
+    } else if (evaluatingLinkLibraries) {
+      return std::string();
+    }
+
+    if (!haveProp && !target->IsImported() &&
+        target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
       if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
                                                        context->Config)) {
         context->HadContextSensitiveCondition = true;
@@ -1345,8 +1310,6 @@
                                                              context->Config);
         return propContent ? propContent : "";
       }
-
-      return linkedTargetsContent;
     }
 
     if (!target->IsImported() && dagCheckerParent &&
@@ -1368,15 +1331,17 @@
         return propContent ? propContent : "";
       }
     }
+
     if (!interfacePropertyName.empty()) {
-      std::string result = this->EvaluateDependentExpression(
-        prop, context->LG, context, headTarget, target, &dagChecker);
+      result = this->EvaluateDependentExpression(result, context->LG, context,
+                                                 target, target, &dagChecker);
+      std::string linkedTargetsContent = getLinkedTargetsContent(
+        target, interfacePropertyName, context, &dagChecker);
       if (!linkedTargetsContent.empty()) {
         result += (result.empty() ? "" : ";") + linkedTargetsContent;
       }
-      return result;
     }
-    return prop;
+    return result;
   }
 } targetPropertyNode;
 
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 036a07d..7340bc2 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -7,7 +7,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <queue>
 #include <sstream>
 #include <stdio.h>
@@ -22,7 +22,9 @@
 #include "cmCustomCommandGenerator.h"
 #include "cmCustomCommandLines.h"
 #include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionContext.h"
 #include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpressionNode.h"
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
@@ -32,6 +34,7 @@
 #include "cmSourceFile.h"
 #include "cmSourceFileLocation.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetLinkLibraryType.h"
@@ -92,9 +95,6 @@
   virtual bool GetHadContextSensitiveCondition() const { return false; }
 
   cmLinkImplItem const& LinkImplItem;
-
-private:
-  cmListFileBacktrace Backtrace;
 };
 cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
 
@@ -209,6 +209,63 @@
   }
 }
 
+namespace {
+// Represent a target property entry after evaluating generator expressions
+// and splitting up lists.
+struct EvaluatedTargetPropertyEntry
+{
+  EvaluatedTargetPropertyEntry(cmLinkImplItem const& item,
+                               cmListFileBacktrace bt)
+    : LinkImplItem(item)
+    , Backtrace(std::move(bt))
+  {
+  }
+
+  // Move-only.
+  EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default;
+  EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete;
+  EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) =
+    delete;
+  EvaluatedTargetPropertyEntry& operator=(
+    EvaluatedTargetPropertyEntry const&) = delete;
+
+  cmLinkImplItem const& LinkImplItem;
+  cmListFileBacktrace Backtrace;
+  std::vector<std::string> Values;
+  bool ContextDependent = false;
+};
+
+EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
+  cmGeneratorTarget const* thisTarget, std::string const& config,
+  std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+  cmGeneratorTarget::TargetPropertyEntry* entry)
+{
+  EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace());
+  cmSystemTools::ExpandListArgument(
+    entry->Evaluate(thisTarget->GetLocalGenerator(), config, false, thisTarget,
+                    dagChecker, lang),
+    ee.Values);
+  if (entry->GetHadContextSensitiveCondition()) {
+    ee.ContextDependent = true;
+  }
+  return ee;
+}
+
+std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries(
+  cmGeneratorTarget const* thisTarget, std::string const& config,
+  std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+  std::vector<cmGeneratorTarget::TargetPropertyEntry*> const& in)
+{
+  std::vector<EvaluatedTargetPropertyEntry> out;
+  out.reserve(in.size());
+  for (cmGeneratorTarget::TargetPropertyEntry* entry : in) {
+    out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang,
+                                                 dagChecker, entry));
+  }
+  return out;
+}
+}
+
 cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
   : Target(t)
   , FortranModuleDirectoryCreated(false)
@@ -259,9 +316,6 @@
                                      t->GetSourceBacktraces(),
                                      this->SourceEntries, true);
 
-  this->DLLPlatform =
-    !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
-
   this->PolicyMap = t->GetPolicyMap();
 }
 
@@ -468,7 +522,7 @@
   const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   if (this->IsImported()) {
-    const char* prefix = this->GetFilePrefixInternal(artifact);
+    const char* prefix = this->GetFilePrefixInternal(config, artifact);
 
     return prefix ? prefix : std::string();
   }
@@ -481,7 +535,7 @@
   const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   if (this->IsImported()) {
-    const char* suffix = this->GetFileSuffixInternal(artifact);
+    const char* suffix = this->GetFileSuffixInternal(config, artifact);
 
     return suffix ? suffix : std::string();
   }
@@ -508,7 +562,8 @@
 }
 
 const char* cmGeneratorTarget::GetFilePrefixInternal(
-  cmStateEnums::ArtifactType artifact, const std::string& language) const
+  std::string const& config, cmStateEnums::ArtifactType artifact,
+  const std::string& language) const
 {
   // no prefix for non-main target types.
   if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
@@ -523,8 +578,7 @@
 
   // Return an empty prefix for the import library if this platform
   // does not support import libraries.
-  if (isImportedLibraryArtifact &&
-      !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+  if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
     return nullptr;
   }
 
@@ -558,7 +612,8 @@
   return targetPrefix;
 }
 const char* cmGeneratorTarget::GetFileSuffixInternal(
-  cmStateEnums::ArtifactType artifact, const std::string& language) const
+  std::string const& config, cmStateEnums::ArtifactType artifact,
+  const std::string& language) const
 {
   // no suffix for non-main target types.
   if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
@@ -573,8 +628,7 @@
 
   // Return an empty suffix for the import library if this platform
   // does not support import libraries.
-  if (isImportedLibraryArtifact &&
-      !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+  if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
     return nullptr;
   }
 
@@ -657,12 +711,14 @@
   return nullptr;
 }
 
-static void handleSystemIncludesDep(
-  cmLocalGenerator* lg, cmGeneratorTarget const* depTgt,
-  const std::string& config, cmGeneratorTarget const* headTarget,
-  cmGeneratorExpressionDAGChecker* dagChecker,
-  std::vector<std::string>& result, bool excludeImported,
-  std::string const& language)
+namespace {
+void handleSystemIncludesDep(cmLocalGenerator* lg,
+                             cmGeneratorTarget const* depTgt,
+                             const std::string& config,
+                             cmGeneratorTarget const* headTarget,
+                             cmGeneratorExpressionDAGChecker* dagChecker,
+                             std::vector<std::string>& result,
+                             bool excludeImported, std::string const& language)
 {
   if (const char* dirs =
         depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) {
@@ -685,6 +741,7 @@
       result);
   }
 }
+}
 
 /* clang-format off */
 #define IMPLEMENT_VISIT(KIND)                                                 \
@@ -1087,77 +1144,205 @@
   return this->Target->GetPropertyAsBool(prop);
 }
 
-static void AddInterfaceEntries(
-  cmGeneratorTarget const* thisTarget, std::string const& config,
-  std::string const& prop,
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
+bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
+  std::string const& prop, cmGeneratorExpressionContext* context) const
+{
+  std::string const key = prop + '@' + context->Config;
+  auto i = this->MaybeInterfacePropertyExists.find(key);
+  if (i == this->MaybeInterfacePropertyExists.end()) {
+    // Insert an entry now in case there is a cycle.
+    i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
+    bool& maybeInterfaceProp = i->second;
+
+    // If this target itself has a non-empty property value, we are done.
+    const char* p = this->GetProperty(prop);
+    maybeInterfaceProp = p && *p;
+
+    // Otherwise, recurse to interface dependencies.
+    if (!maybeInterfaceProp) {
+      cmGeneratorTarget const* headTarget =
+        context->HeadTarget ? context->HeadTarget : this;
+      if (cmLinkInterfaceLibraries const* iface =
+            this->GetLinkInterfaceLibraries(context->Config, headTarget,
+                                            true)) {
+        if (iface->HadHeadSensitiveCondition) {
+          // With a different head target we may get to a library with
+          // this interface property.
+          maybeInterfaceProp = true;
+        } else {
+          // The transitive interface libraries do not depend on the
+          // head target, so we can follow them.
+          for (cmLinkItem const& lib : iface->Libraries) {
+            if (lib.Target &&
+                lib.Target->MaybeHaveInterfaceProperty(prop, context)) {
+              maybeInterfaceProp = true;
+              break;
+            }
+          }
+        }
+      }
+    }
+  }
+  return i->second;
+}
+
+std::string cmGeneratorTarget::EvaluateInterfaceProperty(
+  std::string const& prop, cmGeneratorExpressionContext* context,
+  cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+{
+  std::string result;
+
+  // If the property does not appear transitively at all, we are done.
+  if (!this->MaybeHaveInterfaceProperty(prop, context)) {
+    return result;
+  }
+
+  // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled.  This is
+  // a subset of TargetPropertyNode::Evaluate without stringify/parse steps
+  // but sufficient for transitive interface properties.
+  cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop,
+                                             nullptr, dagCheckerParent);
+  switch (dagChecker.Check()) {
+    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+      dagChecker.ReportError(
+        context, "$<TARGET_PROPERTY:" + this->GetName() + "," + prop + ">");
+      return result;
+    case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+      // No error. We just skip cyclic references.
+      return result;
+    case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+      // No error. We have already seen this transitive property.
+      return result;
+    case cmGeneratorExpressionDAGChecker::DAG:
+      break;
+  }
+
+  cmGeneratorTarget const* headTarget =
+    context->HeadTarget ? context->HeadTarget : this;
+
+  if (const char* p = this->GetProperty(prop)) {
+    result = cmGeneratorExpressionNode::EvaluateDependentExpression(
+      p, context->LG, context, headTarget, this, &dagChecker);
+  }
+
+  if (cmLinkInterfaceLibraries const* iface =
+        this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) {
+    for (cmLinkItem const& lib : iface->Libraries) {
+      // Broken code can have a target in its own link interface.
+      // Don't follow such link interface entries so as not to create a
+      // self-referencing loop.
+      if (lib.Target && lib.Target != this) {
+        // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in the
+        // above property and hand-evaluate it as if it were compiled.
+        // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+        cmGeneratorExpressionContext libContext(
+          context->LG, context->Config, context->Quiet, headTarget, this,
+          context->EvaluateForBuildsystem, context->Backtrace,
+          context->Language);
+        std::string libResult = cmGeneratorExpression::StripEmptyListElements(
+          lib.Target->EvaluateInterfaceProperty(prop, &libContext,
+                                                &dagChecker));
+        if (!libResult.empty()) {
+          if (result.empty()) {
+            result = std::move(libResult);
+          } else {
+            result.reserve(result.size() + 1 + libResult.size());
+            result += ";";
+            result += libResult;
+          }
+        }
+        context->HadContextSensitiveCondition =
+          context->HadContextSensitiveCondition ||
+          libContext.HadContextSensitiveCondition;
+        context->HadHeadSensitiveCondition =
+          context->HadHeadSensitiveCondition ||
+          libContext.HadHeadSensitiveCondition;
+      }
+    }
+  }
+
+  return result;
+}
+
+namespace {
+void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
+                         std::string const& config, std::string const& prop,
+                         std::string const& lang,
+                         cmGeneratorExpressionDAGChecker* dagChecker,
+                         std::vector<EvaluatedTargetPropertyEntry>& entries)
 {
   if (cmLinkImplementationLibraries const* impl =
-        thisTarget->GetLinkImplementationLibraries(config)) {
+        headTarget->GetLinkImplementationLibraries(config)) {
     for (cmLinkImplItem const& lib : impl->Libraries) {
       if (lib.Target) {
-        std::string uniqueName =
-          thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
-            lib.Target);
-        std::string genex =
-          "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">";
-        cmGeneratorExpression ge(lib.Backtrace);
-        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
-        cge->SetEvaluateForBuildsystem(true);
-        entries.push_back(new TargetPropertyEntryGenex(std::move(cge), lib));
+        EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+        // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
+        // caller's property and hand-evaluate it as if it were compiled.
+        // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+        cmGeneratorExpressionContext context(
+          headTarget->GetLocalGenerator(), config, false, headTarget,
+          headTarget, true, lib.Backtrace, lang);
+        cmSystemTools::ExpandListArgument(
+          lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker),
+          ee.Values);
+        ee.ContextDependent = context.HadContextSensitiveCondition;
+        entries.emplace_back(std::move(ee));
       }
     }
   }
 }
 
-static void AddObjectEntries(
-  cmGeneratorTarget const* thisTarget, std::string const& config,
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
+void AddObjectEntries(cmGeneratorTarget const* headTarget,
+                      std::string const& config,
+                      cmGeneratorExpressionDAGChecker* dagChecker,
+                      std::vector<EvaluatedTargetPropertyEntry>& entries)
 {
   if (cmLinkImplementationLibraries const* impl =
-        thisTarget->GetLinkImplementationLibraries(config)) {
+        headTarget->GetLinkImplementationLibraries(config)) {
     for (cmLinkImplItem const& lib : impl->Libraries) {
       if (lib.Target &&
           lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
         std::string uniqueName =
-          thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
+          headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
             lib.Target);
         std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">";
         cmGeneratorExpression ge(lib.Backtrace);
         std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
         cge->SetEvaluateForBuildsystem(true);
-        entries.push_back(new TargetPropertyEntryGenex(std::move(cge), lib));
+
+        EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+        cmSystemTools::ExpandListArgument(
+          cge->Evaluate(headTarget->GetLocalGenerator(), config, false,
+                        headTarget, dagChecker),
+          ee.Values);
+        if (cge->GetHadContextSensitiveCondition()) {
+          ee.ContextDependent = true;
+        }
+        entries.emplace_back(std::move(ee));
       }
     }
   }
 }
 
-static bool processSources(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& srcs,
-  std::unordered_set<std::string>& uniqueSrcs,
-  cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config,
-  bool debugSources)
+bool processSources(cmGeneratorTarget const* tgt,
+                    std::vector<EvaluatedTargetPropertyEntry>& entries,
+                    std::vector<BT<std::string>>& srcs,
+                    std::unordered_set<std::string>& uniqueSrcs,
+                    bool debugSources)
 {
   cmMakefile* mf = tgt->Target->GetMakefile();
 
   bool contextDependent = false;
 
-  for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
-    cmLinkImplItem const& item = entry->LinkImplItem;
-    std::string const& targetName = item.AsStr();
-    std::vector<std::string> entrySources;
-    cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(),
-                                                      config, false, tgt, tgt,
-                                                      dagChecker),
-                                      entrySources);
-
-    if (entry->GetHadContextSensitiveCondition()) {
+  for (EvaluatedTargetPropertyEntry& entry : entries) {
+    if (entry.ContextDependent) {
       contextDependent = true;
     }
 
-    for (std::string& src : entrySources) {
+    cmLinkImplItem const& item = entry.LinkImplItem;
+    std::string const& targetName = item.AsStr();
+
+    for (std::string& src : entry.Values) {
       cmSourceFile* sf = mf->GetOrCreateSource(src);
       std::string e;
       std::string fullPath = sf->GetFullPath(&e);
@@ -1186,9 +1371,9 @@
       src = fullPath;
     }
     std::string usedSources;
-    for (std::string const& src : entrySources) {
+    for (std::string const& src : entry.Values) {
       if (uniqueSrcs.insert(src).second) {
-        srcs.emplace_back(src, entry->GetBacktrace());
+        srcs.emplace_back(src, entry.Backtrace);
         if (debugSources) {
           usedSources += " * " + src + "\n";
         }
@@ -1199,11 +1384,12 @@
         MessageType::LOG,
         std::string("Used sources for target ") + tgt->GetName() + ":\n" +
           usedSources,
-        entry->GetBacktrace());
+        entry.Backtrace);
     }
   }
   return contextDependent;
 }
+}
 
 std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
   std::string const& config) const
@@ -1251,28 +1437,28 @@
   cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr,
                                              nullptr);
 
+  std::vector<EvaluatedTargetPropertyEntry> entries =
+    EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker,
+                                  this->SourceEntries);
+
   std::unordered_set<std::string> uniqueSrcs;
   bool contextDependentDirectSources =
-    processSources(this, this->SourceEntries, files, uniqueSrcs, &dagChecker,
-                   config, debugSources);
+    processSources(this, entries, files, uniqueSrcs, debugSources);
 
   // Collect INTERFACE_SOURCES of all direct link-dependencies.
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
-    linkInterfaceSourcesEntries;
-  AddInterfaceEntries(this, config, "INTERFACE_SOURCES",
-                      linkInterfaceSourcesEntries);
+  std::vector<EvaluatedTargetPropertyEntry> linkInterfaceSourcesEntries;
+  AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(),
+                      &dagChecker, linkInterfaceSourcesEntries);
   std::vector<std::string>::size_type numFilesBefore = files.size();
-  bool contextDependentInterfaceSources =
-    processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs,
-                   &dagChecker, config, debugSources);
+  bool contextDependentInterfaceSources = processSources(
+    this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
 
   // Collect TARGET_OBJECTS of direct object link-dependencies.
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkObjectsEntries;
-  AddObjectEntries(this, config, linkObjectsEntries);
+  std::vector<EvaluatedTargetPropertyEntry> linkObjectsEntries;
+  AddObjectEntries(this, config, &dagChecker, linkObjectsEntries);
   std::vector<std::string>::size_type numFilesBefore2 = files.size();
   bool contextDependentObjects =
-    processSources(this, linkObjectsEntries, files, uniqueSrcs, &dagChecker,
-                   config, debugSources);
+    processSources(this, linkObjectsEntries, files, uniqueSrcs, debugSources);
 
   if (!contextDependentDirectSources &&
       !(contextDependentInterfaceSources && numFilesBefore < files.size()) &&
@@ -1280,8 +1466,6 @@
     this->LinkImplementationLanguageIsContextDependent = false;
   }
 
-  cmDeleteAll(linkInterfaceSourcesEntries);
-  cmDeleteAll(linkObjectsEntries);
   return files;
 }
 
@@ -1612,7 +1796,7 @@
   // will likely change between the build tree and install tree and
   // this target must be relinked.
   bool have_rpath =
-    this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH();
+    this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config);
   bool is_ninja =
     this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja";
 
@@ -1858,16 +2042,17 @@
   return this->GetLibraryNames(config).SharedObject;
 }
 
-static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
+namespace {
+bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
 {
   return level == cmGeneratorTarget::FullLevel;
 }
 
-static bool shouldAddContentLevel(
-  cmGeneratorTarget::BundleDirectoryLevel level)
+bool shouldAddContentLevel(cmGeneratorTarget::BundleDirectoryLevel level)
 {
   return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level);
 }
+}
 
 std::string cmGeneratorTarget::GetAppBundleDirectory(
   const std::string& config, BundleDirectoryLevel level) const
@@ -2357,7 +2542,7 @@
 
 bool cmGeneratorTarget::IsDLLPlatform() const
 {
-  return this->DLLPlatform;
+  return this->Target->IsDLLPlatform();
 }
 
 void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
@@ -2757,33 +2942,35 @@
     case cmStateEnums::MODULE_LIBRARY:
       return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
     case cmStateEnums::EXECUTABLE:
+      if (this->IsExecutableWithExports()) {
+        std::string linkExeWithExports =
+          "CMAKE_" + lang + "_LINK_EXECUTABLE_WITH_EXPORTS";
+        if (this->Makefile->IsDefinitionSet(linkExeWithExports)) {
+          return linkExeWithExports;
+        }
+      }
       return "CMAKE_" + lang + "_LINK_EXECUTABLE";
     default:
       break;
   }
   return "";
 }
-static void processIncludeDirectories(
+
+namespace {
+void processIncludeDirectories(
   cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
+  std::vector<EvaluatedTargetPropertyEntry>& entries,
   std::vector<BT<std::string>>& includes,
-  std::unordered_set<std::string>& uniqueIncludes,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  bool debugIncludes, const std::string& language)
+  std::unordered_set<std::string>& uniqueIncludes, bool debugIncludes)
 {
-  for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
-    cmLinkImplItem const& item = entry->LinkImplItem;
+  for (EvaluatedTargetPropertyEntry& entry : entries) {
+    cmLinkImplItem const& item = entry.LinkImplItem;
     std::string const& targetName = item.AsStr();
     bool const fromImported = item.Target && item.Target->IsImported();
     bool const checkCMP0027 = item.FromGenex;
-    std::vector<std::string> entryIncludes;
-    cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(),
-                                                      config, false, tgt,
-                                                      dagChecker, language),
-                                      entryIncludes);
 
     std::string usedIncludes;
-    for (std::string& entryInclude : entryIncludes) {
+    for (std::string& entryInclude : entry.Values) {
       if (fromImported && !cmSystemTools::FileExists(entryInclude)) {
         std::ostringstream e;
         MessageType messageType = MessageType::FATAL_ERROR;
@@ -2855,12 +3042,11 @@
       if (!cmSystemTools::IsOff(entryInclude)) {
         cmSystemTools::ConvertToUnixSlashes(entryInclude);
       }
-      std::string inc = entryInclude;
 
-      if (uniqueIncludes.insert(inc).second) {
-        includes.emplace_back(inc, entry->GetBacktrace());
+      if (uniqueIncludes.insert(entryInclude).second) {
+        includes.emplace_back(entryInclude, entry.Backtrace);
         if (debugIncludes) {
-          usedIncludes += " * " + inc + "\n";
+          usedIncludes += " * " + entryInclude + "\n";
         }
       }
     }
@@ -2869,10 +3055,11 @@
         MessageType::LOG,
         std::string("Used includes for target ") + tgt->GetName() + ":\n" +
           usedIncludes,
-        entry->GetBacktrace());
+        entry.Backtrace);
     }
   }
 }
+}
 
 std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
   const std::string& config, const std::string& lang) const
@@ -2898,14 +3085,12 @@
     this->DebugIncludesDone = true;
   }
 
-  processIncludeDirectories(this, this->IncludeDirectoriesEntries, includes,
-                            uniqueIncludes, &dagChecker, config, debugIncludes,
-                            lang);
+  std::vector<EvaluatedTargetPropertyEntry> entries =
+    EvaluateTargetPropertyEntries(this, config, lang, &dagChecker,
+                                  this->IncludeDirectoriesEntries);
 
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
-    linkInterfaceIncludeDirectoriesEntries;
-  AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES",
-                      linkInterfaceIncludeDirectoriesEntries);
+  AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
+                      &dagChecker, entries);
 
   if (this->Makefile->IsOn("APPLE")) {
     cmLinkImplementationLibraries const* impl =
@@ -2921,16 +3106,14 @@
 
       libDir = frameworkCheck.match(1);
 
-      linkInterfaceIncludeDirectoriesEntries.push_back(
-        CreateTargetPropertyEntry(libDir));
+      EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace());
+      ee.Values.emplace_back(std::move(libDir));
+      entries.emplace_back(std::move(ee));
     }
   }
 
-  processIncludeDirectories(this, linkInterfaceIncludeDirectoriesEntries,
-                            includes, uniqueIncludes, &dagChecker, config,
-                            debugIncludes, lang);
-
-  cmDeleteAll(linkInterfaceIncludeDirectoriesEntries);
+  processIncludeDirectories(this, entries, includes, uniqueIncludes,
+                            debugIncludes);
 
   return includes;
 }
@@ -2941,33 +3124,26 @@
   Shell
 };
 
-static void processOptionsInternal(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& options,
-  std::unordered_set<std::string>& uniqueOptions,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  bool debugOptions, const char* logName, std::string const& language,
-  OptionsParse parse)
+namespace {
+void processOptions(cmGeneratorTarget const* tgt,
+                    std::vector<EvaluatedTargetPropertyEntry> const& entries,
+                    std::vector<BT<std::string>>& options,
+                    std::unordered_set<std::string>& uniqueOptions,
+                    bool debugOptions, const char* logName, OptionsParse parse)
 {
-  for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
-    std::vector<std::string> entryOptions;
-    cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(),
-                                                      config, false, tgt,
-                                                      dagChecker, language),
-                                      entryOptions);
+  for (EvaluatedTargetPropertyEntry const& entry : entries) {
     std::string usedOptions;
-    for (std::string const& opt : entryOptions) {
+    for (std::string const& opt : entry.Values) {
       if (uniqueOptions.insert(opt).second) {
         if (parse == OptionsParse::Shell &&
             cmHasLiteralPrefix(opt, "SHELL:")) {
           std::vector<std::string> tmp;
           cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
           for (std::string& o : tmp) {
-            options.emplace_back(std::move(o), entry->GetBacktrace());
+            options.emplace_back(std::move(o), entry.Backtrace);
           }
         } else {
-          options.emplace_back(opt, entry->GetBacktrace());
+          options.emplace_back(opt, entry.Backtrace);
         }
         if (debugOptions) {
           usedOptions += " * " + opt + "\n";
@@ -2979,22 +3155,10 @@
         MessageType::LOG,
         std::string("Used ") + logName + std::string(" for target ") +
           tgt->GetName() + ":\n" + usedOptions,
-        entry->GetBacktrace());
+        entry.Backtrace);
     }
   }
 }
-
-static void processCompileOptions(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& options,
-  std::unordered_set<std::string>& uniqueOptions,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  bool debugOptions, std::string const& language)
-{
-  processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
-                         config, debugOptions, "compile options", language,
-                         OptionsParse::Shell);
 }
 
 void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
@@ -3032,37 +3196,19 @@
     this->DebugCompileOptionsDone = true;
   }
 
-  processCompileOptions(this, this->CompileOptionsEntries, result,
-                        uniqueOptions, &dagChecker, config, debugOptions,
-                        language);
+  std::vector<EvaluatedTargetPropertyEntry> entries =
+    EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+                                  this->CompileOptionsEntries);
 
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
-    linkInterfaceCompileOptionsEntries;
+  AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language,
+                      &dagChecker, entries);
 
-  AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS",
-                      linkInterfaceCompileOptionsEntries);
+  processOptions(this, entries, result, uniqueOptions, debugOptions,
+                 "compile options", OptionsParse::Shell);
 
-  processCompileOptions(this, linkInterfaceCompileOptionsEntries, result,
-                        uniqueOptions, &dagChecker, config, debugOptions,
-                        language);
-
-  cmDeleteAll(linkInterfaceCompileOptionsEntries);
   return result;
 }
 
-static void processCompileFeatures(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& options,
-  std::unordered_set<std::string>& uniqueOptions,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  bool debugOptions)
-{
-  processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
-                         config, debugOptions, "compile features",
-                         std::string(), OptionsParse::None);
-}
-
 void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
                                            const std::string& config) const
 {
@@ -3097,34 +3243,19 @@
     this->DebugCompileFeaturesDone = true;
   }
 
-  processCompileFeatures(this, this->CompileFeaturesEntries, result,
-                         uniqueFeatures, &dagChecker, config, debugFeatures);
+  std::vector<EvaluatedTargetPropertyEntry> entries =
+    EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker,
+                                  this->CompileFeaturesEntries);
 
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
-    linkInterfaceCompileFeaturesEntries;
   AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES",
-                      linkInterfaceCompileFeaturesEntries);
+                      std::string(), &dagChecker, entries);
 
-  processCompileFeatures(this, linkInterfaceCompileFeaturesEntries, result,
-                         uniqueFeatures, &dagChecker, config, debugFeatures);
+  processOptions(this, entries, result, uniqueFeatures, debugFeatures,
+                 "compile features", OptionsParse::None);
 
-  cmDeleteAll(linkInterfaceCompileFeaturesEntries);
   return result;
 }
 
-static void processCompileDefinitions(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& options,
-  std::unordered_set<std::string>& uniqueOptions,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  bool debugOptions, std::string const& language)
-{
-  processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
-                         config, debugOptions, "compile definitions", language,
-                         OptionsParse::None);
-}
-
 void cmGeneratorTarget::GetCompileDefinitions(
   std::vector<std::string>& result, const std::string& config,
   const std::string& language) const
@@ -3161,14 +3292,13 @@
     this->DebugCompileDefinitionsDone = true;
   }
 
-  processCompileDefinitions(this, this->CompileDefinitionsEntries, list,
-                            uniqueOptions, &dagChecker, config, debugDefines,
-                            language);
+  std::vector<EvaluatedTargetPropertyEntry> entries =
+    EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+                                  this->CompileDefinitionsEntries);
 
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
-    linkInterfaceCompileDefinitionsEntries;
-  AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS",
-                      linkInterfaceCompileDefinitionsEntries);
+  AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language,
+                      &dagChecker, entries);
+
   if (!config.empty()) {
     std::string configPropName =
       "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
@@ -3183,8 +3313,10 @@
           CM_FALLTHROUGH;
         }
         case cmPolicies::OLD: {
-          linkInterfaceCompileDefinitionsEntries.push_back(
+          std::unique_ptr<TargetPropertyEntry> entry(
             CreateTargetPropertyEntry(configProp));
+          entries.emplace_back(EvaluateTargetPropertyEntry(
+            this, config, language, &dagChecker, entry.get()));
         } break;
         case cmPolicies::NEW:
         case cmPolicies::REQUIRED_ALWAYS:
@@ -3194,29 +3326,12 @@
     }
   }
 
-  processCompileDefinitions(this, linkInterfaceCompileDefinitionsEntries, list,
-                            uniqueOptions, &dagChecker, config, debugDefines,
-                            language);
+  processOptions(this, entries, list, uniqueOptions, debugDefines,
+                 "compile definitions", OptionsParse::None);
 
-  cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
   return list;
 }
 
-namespace {
-void processLinkOptions(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& options,
-  std::unordered_set<std::string>& uniqueOptions,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  bool debugOptions, std::string const& language)
-{
-  processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
-                         config, debugOptions, "link options", language,
-                         OptionsParse::Shell);
-}
-}
-
 void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
                                        const std::string& config,
                                        const std::string& language) const
@@ -3252,20 +3367,15 @@
     this->DebugLinkOptionsDone = true;
   }
 
-  processLinkOptions(this, this->LinkOptionsEntries, result, uniqueOptions,
-                     &dagChecker, config, debugOptions, language);
+  std::vector<EvaluatedTargetPropertyEntry> entries =
+    EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+                                  this->LinkOptionsEntries);
 
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
-    linkInterfaceLinkOptionsEntries;
+  AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language,
+                      &dagChecker, entries);
 
-  AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS",
-                      linkInterfaceLinkOptionsEntries);
-
-  processLinkOptions(this, linkInterfaceLinkOptionsEntries, result,
-                     uniqueOptions, &dagChecker, config, debugOptions,
-                     language);
-
-  cmDeleteAll(linkInterfaceLinkOptionsEntries);
+  processOptions(this, entries, result, uniqueOptions, debugOptions,
+                 "link options", OptionsParse::Shell);
 
   // Last step: replace "LINKER:" prefixed elements by
   // actual linker wrapper
@@ -3371,21 +3481,6 @@
   return result;
 }
 
-namespace {
-void processStaticLibraryLinkOptions(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& options,
-  std::unordered_set<std::string>& uniqueOptions,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  std::string const& language)
-{
-  processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
-                         config, false, "static library link options",
-                         language, OptionsParse::Shell);
-}
-}
-
 void cmGeneratorTarget::GetStaticLibraryLinkOptions(
   std::vector<std::string>& result, const std::string& config,
   const std::string& language) const
@@ -3402,47 +3497,41 @@
   std::string const& config, std::string const& language) const
 {
   std::vector<BT<std::string>> result;
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
   std::unordered_set<std::string> uniqueOptions;
 
   cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS",
                                              nullptr, nullptr);
 
+  std::vector<EvaluatedTargetPropertyEntry> entries;
   if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
     std::vector<std::string> options;
     cmSystemTools::ExpandListArgument(linkOptions, options);
     for (const auto& option : options) {
-      entries.push_back(CreateTargetPropertyEntry(option));
+      std::unique_ptr<TargetPropertyEntry> entry(
+        CreateTargetPropertyEntry(option));
+      entries.emplace_back(EvaluateTargetPropertyEntry(
+        this, config, language, &dagChecker, entry.get()));
     }
   }
-  processStaticLibraryLinkOptions(this, entries, result, uniqueOptions,
-                                  &dagChecker, config, language);
+  processOptions(this, entries, result, uniqueOptions, false,
+                 "static library link options", OptionsParse::Shell);
 
-  cmDeleteAll(entries);
   return result;
 }
 
 namespace {
-void processLinkDirectories(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& directories,
-  std::unordered_set<std::string>& uniqueDirectories,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  bool debugDirectories, std::string const& language)
+void processLinkDirectories(cmGeneratorTarget const* tgt,
+                            std::vector<EvaluatedTargetPropertyEntry>& entries,
+                            std::vector<BT<std::string>>& directories,
+                            std::unordered_set<std::string>& uniqueDirectories,
+                            bool debugDirectories)
 {
-  for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
-    cmLinkImplItem const& item = entry->LinkImplItem;
+  for (EvaluatedTargetPropertyEntry& entry : entries) {
+    cmLinkImplItem const& item = entry.LinkImplItem;
     std::string const& targetName = item.AsStr();
 
-    std::vector<std::string> entryDirectories;
-    cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(),
-                                                      config, false, tgt,
-                                                      dagChecker, language),
-                                      entryDirectories);
-
     std::string usedDirectories;
-    for (std::string& entryDirectory : entryDirectories) {
+    for (std::string& entryDirectory : entry.Values) {
       if (!cmSystemTools::FileIsFullPath(entryDirectory)) {
         std::ostringstream e;
         bool noMessage = false;
@@ -3495,7 +3584,7 @@
         MessageType::LOG,
         std::string("Used link directories for target ") + tgt->GetName() +
           ":\n" + usedDirectories,
-        entry->GetBacktrace());
+        entry.Backtrace);
     }
   }
 }
@@ -3537,39 +3626,19 @@
     this->DebugLinkDirectoriesDone = true;
   }
 
-  processLinkDirectories(this, this->LinkDirectoriesEntries, result,
-                         uniqueDirectories, &dagChecker, config,
-                         debugDirectories, language);
+  std::vector<EvaluatedTargetPropertyEntry> entries =
+    EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+                                  this->LinkDirectoriesEntries);
 
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*>
-    linkInterfaceLinkDirectoriesEntries;
+  AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language,
+                      &dagChecker, entries);
 
-  AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES",
-                      linkInterfaceLinkDirectoriesEntries);
+  processLinkDirectories(this, entries, result, uniqueDirectories,
+                         debugDirectories);
 
-  processLinkDirectories(this, linkInterfaceLinkDirectoriesEntries, result,
-                         uniqueDirectories, &dagChecker, config,
-                         debugDirectories, language);
-
-  cmDeleteAll(linkInterfaceLinkDirectoriesEntries);
   return result;
 }
 
-namespace {
-void processLinkDepends(
-  cmGeneratorTarget const* tgt,
-  const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<BT<std::string>>& options,
-  std::unordered_set<std::string>& uniqueOptions,
-  cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
-  std::string const& language)
-{
-  processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
-                         config, false, "link depends", language,
-                         OptionsParse::None);
-}
-}
-
 void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
                                        const std::string& config,
                                        const std::string& language) const
@@ -3585,24 +3654,27 @@
   std::string const& config, std::string const& language) const
 {
   std::vector<BT<std::string>> result;
-  std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries;
   std::unordered_set<std::string> uniqueOptions;
   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
                                              nullptr);
 
+  std::vector<EvaluatedTargetPropertyEntry> entries;
   if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) {
     std::vector<std::string> depends;
     cmSystemTools::ExpandListArgument(linkDepends, depends);
     for (const auto& depend : depends) {
-      linkDependsEntries.push_back(CreateTargetPropertyEntry(depend));
+      std::unique_ptr<TargetPropertyEntry> entry(
+        CreateTargetPropertyEntry(depend));
+      entries.emplace_back(EvaluateTargetPropertyEntry(
+        this, config, language, &dagChecker, entry.get()));
     }
   }
-  AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS",
-                      linkDependsEntries);
-  processLinkDepends(this, linkDependsEntries, result, uniqueOptions,
-                     &dagChecker, config, language);
+  AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language,
+                      &dagChecker, entries);
 
-  cmDeleteAll(linkDependsEntries);
+  processOptions(this, entries, result, uniqueOptions, false, "link depends",
+                 OptionsParse::None);
+
   return result;
 }
 
@@ -3924,8 +3996,7 @@
 
   // Return an empty name for the import library if this platform
   // does not support import libraries.
-  if (isImportedLibraryArtifact &&
-      !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+  if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
     outPrefix.clear();
     outBase.clear();
     outSuffix.clear();
@@ -3934,8 +4005,8 @@
 
   // retrieve prefix and suffix
   std::string ll = this->GetLinkerLanguage(config);
-  const char* targetPrefix = this->GetFilePrefixInternal(artifact, ll);
-  const char* targetSuffix = this->GetFileSuffixInternal(artifact, ll);
+  const char* targetPrefix = this->GetFilePrefixInternal(config, artifact, ll);
+  const char* targetSuffix = this->GetFileSuffixInternal(config, artifact, ll);
 
   // The implib option is only allowed for shared libraries, module
   // libraries, and executables.
@@ -4121,7 +4192,7 @@
         if (stripResources) {
           flags.MacFolder = "";
         }
-      } else if (cmSystemTools::StringStartsWith(location, "Resources/")) {
+      } else if (cmHasLiteralPrefix(location, "Resources/")) {
         flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource;
         if (stripResources) {
           flags.MacFolder += strlen("Resources/");
@@ -4343,8 +4414,9 @@
   }
 }
 
-static std::string intersect(const std::set<std::string>& s1,
-                             const std::set<std::string>& s2)
+namespace {
+std::string intersect(const std::set<std::string>& s1,
+                      const std::set<std::string>& s2)
 {
   std::set<std::string> intersect;
   std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
@@ -4355,9 +4427,9 @@
   return "";
 }
 
-static std::string intersect(const std::set<std::string>& s1,
-                             const std::set<std::string>& s2,
-                             const std::set<std::string>& s3)
+std::string intersect(const std::set<std::string>& s1,
+                      const std::set<std::string>& s2,
+                      const std::set<std::string>& s3)
 {
   std::string result;
   result = intersect(s1, s2);
@@ -4371,10 +4443,10 @@
   return intersect(s2, s3);
 }
 
-static std::string intersect(const std::set<std::string>& s1,
-                             const std::set<std::string>& s2,
-                             const std::set<std::string>& s3,
-                             const std::set<std::string>& s4)
+std::string intersect(const std::set<std::string>& s1,
+                      const std::set<std::string>& s2,
+                      const std::set<std::string>& s3,
+                      const std::set<std::string>& s4)
 {
   std::string result;
   result = intersect(s1, s2);
@@ -4391,6 +4463,7 @@
   }
   return intersect(s2, s3, s4);
 }
+}
 
 void cmGeneratorTarget::CheckPropertyCompatibility(
   cmComputeLinkInformation* info, const std::string& config) const
@@ -5032,13 +5105,7 @@
 
 std::vector<std::string> cmGeneratorTarget::GetPropertyKeys() const
 {
-  cmPropertyMap const& propsObject = this->Target->GetProperties();
-  std::vector<std::string> props;
-  props.reserve(propsObject.size());
-  for (auto const& it : propsObject) {
-    props.push_back(it.first);
-  }
-  return props;
+  return this->Target->GetProperties().GetKeys();
 }
 
 void cmGeneratorTarget::ReportPropertyOrigin(
@@ -5485,13 +5552,41 @@
   return true;
 }
 
-bool cmGeneratorTarget::HaveInstallTreeRPATH() const
+bool cmGeneratorTarget::HaveInstallTreeRPATH(const std::string& config) const
 {
-  const char* install_rpath = this->GetProperty("INSTALL_RPATH");
-  return (install_rpath && *install_rpath) &&
+  std::string install_rpath;
+  this->GetInstallRPATH(config, install_rpath);
+  return !install_rpath.empty() &&
     !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
 }
 
+bool cmGeneratorTarget::GetBuildRPATH(const std::string& config,
+                                      std::string& rpath) const
+{
+  return this->GetRPATH(config, "BUILD_RPATH", rpath);
+}
+
+bool cmGeneratorTarget::GetInstallRPATH(const std::string& config,
+                                        std::string& rpath) const
+{
+  return this->GetRPATH(config, "INSTALL_RPATH", rpath);
+}
+
+bool cmGeneratorTarget::GetRPATH(const std::string& config,
+                                 const std::string& prop,
+                                 std::string& rpath) const
+{
+  const char* value = this->GetProperty(prop);
+  if (!value) {
+    return false;
+  }
+
+  cmGeneratorExpression ge;
+  rpath = ge.Parse(value)->Evaluate(this->LocalGenerator, config);
+
+  return true;
+}
+
 void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
   const std::string& config, cmOptionalLinkInterface& iface,
   cmGeneratorTarget const* headTarget, bool usage_requirements_only) const
@@ -6091,7 +6186,8 @@
   if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
     return false;
   }
-  if (this->GetProperty("BUILD_RPATH")) {
+  std::string build_rpath;
+  if (this->GetBuildRPATH(config, build_rpath)) {
     return true;
   }
   if (cmLinkImplementationLibraries const* impl =
@@ -6337,7 +6433,18 @@
            this->IsExecutableWithExports()) &&
           // Assemblies which have only managed code do not have
           // import libraries.
-          this->GetManagedType(config) != ManagedType::Managed);
+          this->GetManagedType(config) != ManagedType::Managed) ||
+    (this->Target->IsAIX() && this->IsExecutableWithExports());
+}
+
+bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const
+{
+  return this->HasImportLibrary(config) ||
+    // On DLL platforms we always generate the import library name
+    // just in case the sources have export markup.
+    (this->IsDLLPlatform() &&
+     (this->GetType() == cmStateEnums::EXECUTABLE ||
+      this->GetType() == cmStateEnums::MODULE_LIBRARY));
 }
 
 std::string cmGeneratorTarget::GetSupportDirectory() const
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 0e0ee6a..3874738 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -14,6 +14,7 @@
 #include <set>
 #include <stddef.h>
 #include <string>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -25,6 +26,9 @@
 class cmSourceFile;
 class cmTarget;
 
+struct cmGeneratorExpressionContext;
+struct cmGeneratorExpressionDAGChecker;
+
 class cmGeneratorTarget
 {
 public:
@@ -674,7 +678,14 @@
 
   class TargetPropertyEntry;
 
-  bool HaveInstallTreeRPATH() const;
+  std::string EvaluateInterfaceProperty(
+    std::string const& prop, cmGeneratorExpressionContext* context,
+    cmGeneratorExpressionDAGChecker* dagCheckerParent) const;
+
+  bool HaveInstallTreeRPATH(const std::string& config) const;
+
+  bool GetBuildRPATH(const std::string& config, std::string& rpath) const;
+  bool GetInstallRPATH(const std::string& config, std::string& rpath) const;
 
   /** Whether this library has \@rpath and platform supports it.  */
   bool HasMacOSXRpathInstallNameDir(const std::string& config) const;
@@ -740,9 +751,13 @@
 
   mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
 
-  const char* GetFilePrefixInternal(cmStateEnums::ArtifactType artifact,
+  bool NeedImportLibraryName(std::string const& config) const;
+
+  const char* GetFilePrefixInternal(std::string const& config,
+                                    cmStateEnums::ArtifactType artifact,
                                     const std::string& language = "") const;
-  const char* GetFileSuffixInternal(cmStateEnums::ArtifactType artifact,
+  const char* GetFileSuffixInternal(std::string const& config,
+                                    cmStateEnums::ArtifactType artifact,
                                     const std::string& language = "") const;
 
   std::string GetFullNameInternal(const std::string& config,
@@ -842,6 +857,10 @@
   mutable std::vector<AllConfigSource> AllConfigSources;
   void ComputeAllConfigSources() const;
 
+  mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists;
+  bool MaybeHaveInterfaceProperty(std::string const& prop,
+                                  cmGeneratorExpressionContext* context) const;
+
   std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
   std::vector<TargetPropertyEntry*> CompileOptionsEntries;
   std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
@@ -906,13 +925,15 @@
   mutable bool DebugSourcesDone;
   mutable bool LinkImplementationLanguageIsContextDependent;
   mutable bool UtilityItemsDone;
-  bool DLLPlatform;
 
   bool ComputePDBOutputDir(const std::string& kind, const std::string& config,
                            std::string& out) const;
 
   ManagedType CheckManagedType(std::string const& propval) const;
 
+  bool GetRPATH(const std::string& config, const std::string& prop,
+                std::string& rpath) const;
+
 public:
   const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
     const std::string& config) const;
diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx
index fc82fee..38fee28 100644
--- a/Source/cmGetCMakePropertyCommand.cxx
+++ b/Source/cmGetCMakePropertyCommand.cxx
@@ -4,10 +4,10 @@
 
 #include <set>
 
-#include "cmAlgorithms.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 
 class cmExecutionStatus;
 
@@ -46,7 +46,7 @@
     }
   }
 
-  this->Makefile->AddDefinition(variable, output.c_str());
+  this->Makefile->AddDefinition(variable, output);
 
   return true;
 }
diff --git a/Source/cmGetCMakePropertyCommand.h b/Source/cmGetCMakePropertyCommand.h
index 1f29c78..7790a6b 100644
--- a/Source/cmGetCMakePropertyCommand.h
+++ b/Source/cmGetCMakePropertyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmGetCMakePropertyCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmGetCMakePropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmGetCMakePropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index a92eb71..98ccb0a 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -66,7 +66,7 @@
       return false;
     }
     std::string const& output = dir->GetSafeDefinition(*i);
-    this->Makefile->AddDefinition(variable, output.c_str());
+    this->Makefile->AddDefinition(variable, output);
     return true;
   }
 
@@ -97,9 +97,5 @@
 void cmGetDirectoryPropertyCommand::StoreResult(std::string const& variable,
                                                 const char* prop)
 {
-  if (prop) {
-    this->Makefile->AddDefinition(variable, prop);
-    return;
-  }
-  this->Makefile->AddDefinition(variable, "");
+  this->Makefile->AddDefinition(variable, prop ? prop : "");
 }
diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h
index 02ea056..63a198a 100644
--- a/Source/cmGetDirectoryPropertyCommand.h
+++ b/Source/cmGetDirectoryPropertyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmGetDirectoryPropertyCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmGetDirectoryPropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmGetDirectoryPropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index 163b4c8..fc82535 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -128,9 +128,9 @@
       args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
   } else {
     if (!programArgs.empty() && !storeArgs.empty()) {
-      this->Makefile->AddDefinition(storeArgs, programArgs.c_str());
+      this->Makefile->AddDefinition(storeArgs, programArgs);
     }
-    this->Makefile->AddDefinition(args.front(), result.c_str());
+    this->Makefile->AddDefinition(args.front(), result);
   }
 
   return true;
diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h
index 8c26655..1780b96 100644
--- a/Source/cmGetFilenameComponentCommand.h
+++ b/Source/cmGetFilenameComponentCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmGetFilenameComponentCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmGetFilenameComponentCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 039f439..de462ed 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -121,7 +121,7 @@
     } else {
       output = "NOTFOUND";
     }
-    this->Makefile->AddDefinition(this->Variable, output.c_str());
+    this->Makefile->AddDefinition(this->Variable, output);
   } else if (this->InfoType == OutFullDoc) {
     // Lookup full documentation.
     std::string output;
@@ -132,7 +132,7 @@
     } else {
       output = "NOTFOUND";
     }
-    this->Makefile->AddDefinition(this->Variable, output.c_str());
+    this->Makefile->AddDefinition(this->Variable, output);
   } else if (this->InfoType == OutDefined) {
     // Lookup if the property is defined
     if (this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h
index c3f653e..50e4014 100644
--- a/Source/cmGetPropertyCommand.h
+++ b/Source/cmGetPropertyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -17,7 +19,10 @@
 public:
   cmGetPropertyCommand();
 
-  cmCommand* Clone() override { return new cmGetPropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmGetPropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx
index 75879a5..a16076d 100644
--- a/Source/cmGetSourceFilePropertyCommand.cxx
+++ b/Source/cmGetSourceFilePropertyCommand.cxx
@@ -25,7 +25,7 @@
   }
   if (sf) {
     if (args[2] == "LANGUAGE") {
-      this->Makefile->AddDefinition(var, sf->GetLanguage().c_str());
+      this->Makefile->AddDefinition(var, sf->GetLanguage());
       return true;
     }
     const char* prop = nullptr;
diff --git a/Source/cmGetSourceFilePropertyCommand.h b/Source/cmGetSourceFilePropertyCommand.h
index 43bc330..387a7f4 100644
--- a/Source/cmGetSourceFilePropertyCommand.h
+++ b/Source/cmGetSourceFilePropertyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmGetSourceFilePropertyCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmGetSourceFilePropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmGetSourceFilePropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index fc0e9c6..07aaf02 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -75,9 +75,9 @@
     }
   }
   if (prop_exists) {
-    this->Makefile->AddDefinition(var, prop.c_str());
+    this->Makefile->AddDefinition(var, prop);
     return true;
   }
-  this->Makefile->AddDefinition(var, (var + "-NOTFOUND").c_str());
+  this->Makefile->AddDefinition(var, var + "-NOTFOUND");
   return true;
 }
diff --git a/Source/cmGetTargetPropertyCommand.h b/Source/cmGetTargetPropertyCommand.h
index 63ee5fd..1a53195 100644
--- a/Source/cmGetTargetPropertyCommand.h
+++ b/Source/cmGetTargetPropertyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmGetTargetPropertyCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmGetTargetPropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmGetTargetPropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGetTestPropertyCommand.h b/Source/cmGetTestPropertyCommand.h
index 4a74f59..a53a7f7 100644
--- a/Source/cmGetTestPropertyCommand.h
+++ b/Source/cmGetTestPropertyCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmGetTestPropertyCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmGetTestPropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmGetTestPropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index b80da72..997595b 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -22,9 +22,11 @@
 #include "cmTarget.h"
 
 #include <algorithm>
+#include <memory>
 #include <ostream>
 #include <set>
 #include <utility>
+#include <vector>
 
 cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target)
   : GeneratorTarget(target)
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 4eba4ff..88da5eb 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -92,7 +92,6 @@
   // how long to let try compiles run
   this->TryCompileTimeout = cmDuration::zero();
 
-  this->ExtraGenerator = nullptr;
   this->CurrentConfigureMakefile = nullptr;
   this->TryCompileOuterMakefile = nullptr;
 
@@ -113,7 +112,6 @@
 cmGlobalGenerator::~cmGlobalGenerator()
 {
   this->ClearGeneratorMembers();
-  delete this->ExtraGenerator;
 }
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -339,15 +337,16 @@
   bool failed = false;
   for (cmLocalGenerator* generator : this->LocalGenerators) {
     for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) {
-      std::vector<std::string> configs;
-      target->Makefile->GetConfigurations(configs);
-      if (configs.empty()) {
-        configs.emplace_back();
-      }
+      if (target->GetType() == cmStateEnums::EXECUTABLE &&
+          target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
+        std::vector<std::string> configs;
+        target->Makefile->GetConfigurations(configs);
+        if (configs.empty()) {
+          configs.emplace_back();
+        }
 
-      for (std::string const& config : configs) {
-        if (target->GetLinkerLanguage(config) == "Swift") {
-          if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
+        for (std::string const& config : configs) {
+          if (target->GetLinkerLanguage(config) == "Swift") {
             this->GetCMakeInstance()->IssueMessage(
               MessageType::FATAL_ERROR,
               "WIN32_EXECUTABLE property is not supported on Swift "
@@ -513,7 +512,7 @@
 
   bool fatalError = false;
 
-  mf->AddDefinition("RUN_CONFIGURE", true);
+  mf->AddDefinitionBool("RUN_CONFIGURE", true);
   std::string rootBin = this->CMakeInstance->GetHomeOutputDirectory();
   rootBin += "/CMakeFiles";
 
@@ -527,7 +526,7 @@
   rootBin += cmVersion::GetCMakeVersion();
 
   // set the dir for parent files so they can be used by modules
-  mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR", rootBin.c_str());
+  mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR", rootBin);
 
   if (!this->CMakeInstance->GetIsInTryCompile()) {
     // Keep a mark in the cache to indicate that we've initialized the
@@ -587,8 +586,7 @@
     windowsVersionString << osviex.dwMajorVersion << "."
                          << osviex.dwMinorVersion << "."
                          << osviex.dwBuildNumber;
-    mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
-                      windowsVersionString.str().c_str());
+    mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", windowsVersionString.str());
 #endif
     // Read the DetermineSystem file
     std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
@@ -1499,7 +1497,7 @@
 
   this->WriteSummary();
 
-  if (this->ExtraGenerator != nullptr) {
+  if (this->ExtraGenerator) {
     this->ExtraGenerator->Generate();
   }
 
@@ -2721,8 +2719,8 @@
 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
   cmExternalMakefileProjectGenerator* extraGenerator)
 {
-  this->ExtraGenerator = extraGenerator;
-  if (this->ExtraGenerator != nullptr) {
+  this->ExtraGenerator.reset(extraGenerator);
+  if (this->ExtraGenerator) {
     this->ExtraGenerator->SetGlobalGenerator(this);
   }
 }
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index db96489..ea40ebc 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -7,6 +7,7 @@
 
 #include <iosfwd>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -18,6 +19,7 @@
 #include "cmDuration.h"
 #include "cmExportSetMap.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetDepend.h"
@@ -618,7 +620,7 @@
 
   void ComputeBuildFileGenerators();
 
-  cmExternalMakefileProjectGenerator* ExtraGenerator;
+  std::unique_ptr<cmExternalMakefileProjectGenerator> ExtraGenerator;
 
   // track files replaced during a Generate
   std::vector<std::string> FilesReplacedDuringGenerate;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index b69dea0..7cfbea6 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -111,7 +111,7 @@
   mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(),
                          "build program to use", cmStateEnums::INTERNAL, true);
 
-  mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp.c_str());
+  mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp);
 
   return true;
 }
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index 7b58389..483d4ab 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -69,9 +69,9 @@
     rc = trc;
   }
   mf->AddDefinition("MSYS", "1");
-  mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str());
-  mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str());
-  mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str());
+  mf->AddDefinition("CMAKE_GENERATOR_CC", gcc);
+  mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx);
+  mf->AddDefinition("CMAKE_GENERATOR_RC", rc);
   this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
 
   if (!mf->IsSet("CMAKE_AR") && !this->CMakeInstance->GetIsInTryCompile() &&
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index e218b4b..d9fc505 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -44,9 +44,9 @@
   if (!trc.empty()) {
     rc = trc;
   }
-  mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str());
-  mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str());
-  mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str());
+  mf->AddDefinition("CMAKE_GENERATOR_CC", gcc);
+  mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx);
+  mf->AddDefinition("CMAKE_GENERATOR_RC", rc);
   this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
 }
 
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 2d52356..0b68966 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -9,10 +9,11 @@
 #include <algorithm>
 #include <ctype.h>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmDocumentationEntry.h"
 #include "cmFortranParser.h"
@@ -31,6 +32,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetDepend.h"
@@ -413,14 +415,6 @@
 
 cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm)
   : cmGlobalCommonGenerator(cm)
-  , UsingGCCOnWindows(false)
-  , ComputingUnknownDependencies(false)
-  , PolicyCMP0058(cmPolicies::WARN)
-  , NinjaSupportsConsolePool(false)
-  , NinjaSupportsImplicitOuts(false)
-  , NinjaSupportsManifestRestat(false)
-  , NinjaSupportsMultilineDepfile(false)
-  , NinjaSupportsDyndeps(0)
 {
 #ifdef _WIN32
   cm->GetState()->SetWindowsShell(true);
@@ -554,14 +548,22 @@
   this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare(
     cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
     RequiredNinjaVersionForMultilineDepfile().c_str());
-  {
+  this->NinjaSupportsDyndeps = !cmSystemTools::VersionCompare(
+    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+    RequiredNinjaVersionForDyndeps().c_str());
+  if (!this->NinjaSupportsDyndeps) {
+    // The ninja version number is not new enough to have upstream support.
     // Our ninja branch adds ".dyndep-#" to its version number,
     // where '#' is a feature-specific version number.  Extract it.
     static std::string const k_DYNDEP_ = ".dyndep-";
     std::string::size_type pos = this->NinjaVersion.find(k_DYNDEP_);
     if (pos != std::string::npos) {
       const char* fv = &this->NinjaVersion[pos + k_DYNDEP_.size()];
-      cmSystemTools::StringToULong(fv, &this->NinjaSupportsDyndeps);
+      unsigned long dyndep = 0;
+      cmSystemTools::StringToULong(fv, &dyndep);
+      if (dyndep == 1) {
+        this->NinjaSupportsDyndeps = true;
+      }
     }
   }
 }
@@ -578,37 +580,25 @@
 
 bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
 {
-  if (this->NinjaSupportsDyndeps == 1) {
+  if (this->NinjaSupportsDyndeps) {
     return true;
   }
 
   std::ostringstream e;
-  if (this->NinjaSupportsDyndeps == 0) {
-    /* clang-format off */
-    e <<
-      "The Ninja generator does not support Fortran using Ninja version\n"
-      "  " + this->NinjaVersion + "\n"
-      "due to lack of required features.  "
-      "Kitware has implemented the required features but as of this version "
-      "of CMake they have not been integrated to upstream ninja.  "
-      "Pending integration, Kitware maintains a branch at:\n"
-      "  https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n"
-      "with the required features.  "
-      "One may build ninja from that branch to get support for Fortran."
-      ;
-    /* clang-format on */
-  } else {
-    /* clang-format off */
-    e <<
-      "The Ninja generator in this version of CMake does not support Fortran "
-      "using Ninja version\n"
-      "  " + this->NinjaVersion + "\n"
-      "because its 'dyndep' feature version is " <<
-      this->NinjaSupportsDyndeps << ".  "
-      "This version of CMake is aware only of 'dyndep' feature version 1."
-      ;
-    /* clang-format on */
-  }
+  /* clang-format off */
+  e <<
+    "The Ninja generator does not support Fortran using Ninja version\n"
+    "  " + this->NinjaVersion + "\n"
+    "due to lack of required features.  "
+    "Kitware has implemented the required features and they have been "
+    "merged to upstream ninja for inclusion in Ninja 1.10 and higher.  "
+    "As of this version of CMake, Ninja 1.10 has not been released.  "
+    "Meanwhile, Kitware maintains a branch of Ninja at:\n"
+    "  https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n"
+    "with the required features.  "
+    "One may build ninja from that branch to get support for Fortran."
+    ;
+  /* clang-format on */
   mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
   cmSystemTools::SetFatalErrorOccured();
   return false;
@@ -638,7 +628,9 @@
         (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") ||
         (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") ||
         (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") ||
-        (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang")))) {
+        (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") ||
+        (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "QCC") ||
+        (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "QCC")))) {
     this->UsingGCCOnWindows = true;
   }
 #endif
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 15dd404..db64031 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -7,7 +7,7 @@
 
 #include <iosfwd>
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -322,6 +322,7 @@
   {
     return "1.9";
   }
+  static std::string RequiredNinjaVersionForDyndeps() { return "1.10"; }
   bool SupportsConsolePool() const;
   bool SupportsImplicitOuts() const;
   bool SupportsManifestRestat() const;
@@ -402,7 +403,7 @@
   /// The set of dependencies to add to the "all" target.
   cmNinjaDeps AllDependencies;
 
-  bool UsingGCCOnWindows;
+  bool UsingGCCOnWindows = false;
 
   /// The set of custom commands we have seen.
   std::set<cmCustomCommand const*> CustomCommands;
@@ -412,8 +413,8 @@
 
   /// Whether we are collecting known build outputs and needed
   /// dependencies to determine unknown dependencies.
-  bool ComputingUnknownDependencies;
-  cmPolicies::PolicyStatus PolicyCMP0058;
+  bool ComputingUnknownDependencies = false;
+  cmPolicies::PolicyStatus PolicyCMP0058 = cmPolicies::WARN;
 
   /// The combined explicit dependencies of custom build commands
   std::set<std::string> CombinedCustomCommandExplicitDependencies;
@@ -435,11 +436,11 @@
 
   std::string NinjaCommand;
   std::string NinjaVersion;
-  bool NinjaSupportsConsolePool;
-  bool NinjaSupportsImplicitOuts;
-  bool NinjaSupportsManifestRestat;
-  bool NinjaSupportsMultilineDepfile;
-  unsigned long NinjaSupportsDyndeps;
+  bool NinjaSupportsConsolePool = false;
+  bool NinjaSupportsImplicitOuts = false;
+  bool NinjaSupportsManifestRestat = false;
+  bool NinjaSupportsMultilineDepfile = false;
+  bool NinjaSupportsDyndeps = false;
 
 private:
   void InitOutputPathPrefix();
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index aa584ad..35af0e1 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -7,6 +7,8 @@
 #include <sstream>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmDocumentationEntry.h"
 #include "cmGeneratedFileStream.h"
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 55374a4..4a3cadd 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -445,7 +445,7 @@
     this->DefaultPlatformName = "Tegra-Android";
     this->DefaultPlatformToolset = "Default";
     this->NsightTegraVersion = v;
-    mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v.c_str());
+    mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v);
   }
 
   return true;
@@ -659,8 +659,7 @@
   if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) {
     return false;
   }
-  mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND",
-                    this->GetMSBuildCommand().c_str());
+  mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND", this->GetMSBuildCommand());
   return true;
 }
 
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index 6509b56..cd48474 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -182,7 +182,7 @@
     mf->DisplayStatus(e.str(), -1);
   }
   mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION",
-                    this->WindowsTargetPlatformVersion.c_str());
+                    this->WindowsTargetPlatformVersion);
 }
 
 bool cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset(
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 8764ee4..bead0e3 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -8,7 +8,9 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmUuid.h"
+#include "cm_string_view.hxx"
 #include "cmake.h"
 #include "cmsys/Encoding.hxx"
 
@@ -121,8 +123,7 @@
   if (!this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf)) {
     return false;
   }
-  mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND",
-                    this->GetDevEnvCommand().c_str());
+  mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND", this->GetDevEnvCommand());
   return true;
 }
 
@@ -268,7 +269,7 @@
                                                    cmMakefile* mf)
 {
   mf->AddDefinition("CMAKE_VS_INTEL_Fortran_PROJECT_VERSION",
-                    this->GetIntelProjectVersion().c_str());
+                    this->GetIntelProjectVersion());
   return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf);
 }
 
@@ -433,16 +434,15 @@
 
 void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout)
 {
-  const char* prefix = "CMAKE_FOLDER_GUID_";
-  const std::string::size_type skip_prefix = strlen(prefix);
+  cm::string_view const prefix = "CMAKE_FOLDER_GUID_";
   std::string guidProjectTypeFolder = "2150E333-8FDC-42A3-9474-1A3956D46DE8";
   for (auto const& iter : VisualStudioFolders) {
     std::string fullName = iter.first;
     std::string guid = this->GetGUID(fullName);
 
     std::replace(fullName.begin(), fullName.end(), '/', '\\');
-    if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix)) {
-      fullName = fullName.substr(skip_prefix);
+    if (cmHasPrefix(fullName, prefix)) {
+      fullName = fullName.substr(prefix.size());
     }
 
     std::string nameOnly = cmSystemTools::GetFilenameName(fullName);
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 85ddc85..cc6e421 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -54,8 +54,7 @@
 void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
 {
   if (this->TargetsWindowsCE()) {
-    mf->AddDefinition("CMAKE_VS_WINCE_VERSION",
-                      this->WindowsCEVersion.c_str());
+    mf->AddDefinition("CMAKE_VS_WINCE_VERSION", this->WindowsCEVersion);
   }
 }
 
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index cd0355f..ba541a9 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -57,7 +57,7 @@
   std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
 {
   mf->AddDefinition("CMAKE_VS_PLATFORM_NAME_DEFAULT",
-                    this->DefaultPlatformName.c_str());
+                    this->DefaultPlatformName);
   this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
 }
 
@@ -69,7 +69,7 @@
   } else if (this->GetPlatformName() == "Itanium") {
     mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE");
   }
-  mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str());
+  mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
   return this->cmGlobalGenerator::SetGeneratorPlatform(p, mf);
 }
 
@@ -488,7 +488,7 @@
   // directly instead of needing a helper module to do it, so we
   // do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
   if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
-    mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetVSMakeProgram().c_str());
+    mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetVSMakeProgram());
   }
   return true;
 }
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 7c2bcd3..8f4ae62 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -5,11 +5,12 @@
 #include "cmsys/RegularExpression.hxx"
 #include <assert.h>
 #include <iomanip>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 #include <string.h>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmCustomCommand.h"
@@ -240,8 +241,7 @@
   // directly instead of needing a helper module to do it, so we
   // do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
   if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
-    mf->AddDefinition("CMAKE_MAKE_PROGRAM",
-                      this->GetXcodeBuildCommand().c_str());
+    mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetXcodeBuildCommand());
   }
   return true;
 }
@@ -282,8 +282,7 @@
   }
   this->GeneratorToolset = ts;
   if (!this->GeneratorToolset.empty()) {
-    mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
-                      this->GeneratorToolset.c_str());
+    mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset);
   }
   return true;
 }
@@ -292,7 +291,7 @@
   std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
 {
   mf->AddDefinition("XCODE", "1");
-  mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str());
+  mf->AddDefinition("XCODE_VERSION", this->VersionString);
   if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
     mf->AddCacheDefinition(
       "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index a75d8a9..9befb78 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -4,7 +4,7 @@
 
 #include <cstddef>
 #include <iostream>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <utility>
 
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index d1f8f58..385022c 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmIfCommand.h"
 
+#include "cm_memory.hxx"
+
 #include "cmConditionEvaluator.h"
 #include "cmExecutionStatus.h"
 #include "cmExpandedCommandArgument.h"
@@ -11,7 +13,8 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#include <memory> // IWYU pragma: keep
+#include <string>
+#include <utility>
 
 static std::string cmIfCommandError(
   std::vector<cmExpandedCommandArgument> const& args)
@@ -45,7 +48,7 @@
       }
 
       // execute the functions for the true parts of the if statement
-      cmExecutionStatus status;
+      cmExecutionStatus status(mf);
       int scopeDepth = 0;
       for (cmListFileFunction const& func : this->Functions) {
         // keep track of scope depth
@@ -174,19 +177,19 @@
 }
 
 //=========================================================================
-bool cmIfCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
+bool cmIfCommand(std::vector<cmListFileArgument> const& args,
+                 cmExecutionStatus& inStatus)
 {
+  cmMakefile& makefile = inStatus.GetMakefile();
   std::string errorString;
 
   std::vector<cmExpandedCommandArgument> expandedArguments;
-  this->Makefile->ExpandArguments(args, expandedArguments);
+  makefile.ExpandArguments(args, expandedArguments);
 
   MessageType status;
 
   cmConditionEvaluator conditionEvaluator(
-    *(this->Makefile), this->Makefile->GetExecutionContext(),
-    this->Makefile->GetBacktrace());
+    makefile, makefile.GetExecutionContext(), makefile.GetBacktrace());
 
   bool isTrue =
     conditionEvaluator.IsTrue(expandedArguments, errorString, status);
@@ -195,22 +198,24 @@
     std::string err = "if " + cmIfCommandError(expandedArguments);
     err += errorString;
     if (status == MessageType::FATAL_ERROR) {
-      this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err);
+      makefile.IssueMessage(MessageType::FATAL_ERROR, err);
       cmSystemTools::SetFatalErrorOccured();
       return true;
     }
-    this->Makefile->IssueMessage(status, err);
+    makefile.IssueMessage(status, err);
   }
 
-  cmIfFunctionBlocker* f = new cmIfFunctionBlocker();
-  // if is isn't true block the commands
-  f->ScopeDepth = 1;
-  f->IsBlocking = !isTrue;
-  if (isTrue) {
-    f->HasRun = true;
+  {
+    auto fb = cm::make_unique<cmIfFunctionBlocker>();
+    // if is isn't true block the commands
+    fb->ScopeDepth = 1;
+    fb->IsBlocking = !isTrue;
+    if (isTrue) {
+      fb->HasRun = true;
+    }
+    fb->Args = args;
+    makefile.AddFunctionBlocker(std::move(fb));
   }
-  f->Args = args;
-  this->Makefile->AddFunctionBlocker(f);
 
   return true;
 }
diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h
index d34ed02..775e609 100644
--- a/Source/cmIfCommand.h
+++ b/Source/cmIfCommand.h
@@ -5,15 +5,12 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
 #include <vector>
 
-#include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
 
 class cmExecutionStatus;
-class cmExpandedCommandArgument;
 class cmMakefile;
 
 class cmIfFunctionBlocker : public cmFunctionBlocker
@@ -32,34 +29,7 @@
 };
 
 /// Starts an if block
-class cmIfCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  cmCommand* Clone() override { return new cmIfCommand; }
-
-  /**
-   * This overrides the default InvokeInitialPass implementation.
-   * It records the arguments before expansion.
-   */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
-
-  // Filter the given variable definition based on policy CMP0054.
-  static const char* GetDefinitionIfUnquoted(
-    const cmMakefile* mf, cmExpandedCommandArgument const& argument);
-};
+bool cmIfCommand(std::vector<cmListFileArgument> const& args,
+                 cmExecutionStatus& status);
 
 #endif
diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h
index 3b843b2..94d3fbd 100644
--- a/Source/cmIncludeCommand.h
+++ b/Source/cmIncludeCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmIncludeCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmIncludeCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h
index 01d98db..4df94eb 100644
--- a/Source/cmIncludeDirectoryCommand.h
+++ b/Source/cmIncludeDirectoryCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmIncludeDirectoryCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmIncludeDirectoryCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h
index 945acdc..9f76576 100644
--- a/Source/cmIncludeExternalMSProjectCommand.h
+++ b/Source/cmIncludeExternalMSProjectCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmIncludeExternalMSProjectCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmIncludeExternalMSProjectCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx
index 505b07c..3b126b0 100644
--- a/Source/cmIncludeGuardCommand.cxx
+++ b/Source/cmIncludeGuardCommand.cxx
@@ -85,7 +85,7 @@
         status.SetReturnInvoked();
         return true;
       }
-      mf->AddDefinition(includeGuardVar, true);
+      mf->AddDefinitionBool(includeGuardVar, true);
       break;
     case DIRECTORY:
       if (CheckIncludeGuardIsSet(mf, includeGuardVar)) {
diff --git a/Source/cmIncludeGuardCommand.h b/Source/cmIncludeGuardCommand.h
index eaad9b8..4306c4c 100644
--- a/Source/cmIncludeGuardCommand.h
+++ b/Source/cmIncludeGuardCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmIncludeGuardCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmIncludeGuardCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmIncludeRegularExpressionCommand.h b/Source/cmIncludeRegularExpressionCommand.h
index 8da991d..1723c8b 100644
--- a/Source/cmIncludeRegularExpressionCommand.h
+++ b/Source/cmIncludeRegularExpressionCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmIncludeRegularExpressionCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmIncludeRegularExpressionCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index c9e6923..5349a9d 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -9,7 +9,6 @@
 #include <stddef.h>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmArgumentParser.h"
 #include "cmExportSet.h"
 #include "cmExportSetMap.h"
@@ -27,6 +26,7 @@
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetExport.h"
@@ -391,10 +391,6 @@
     return true;
   }
 
-  // Check whether this is a DLL platform.
-  bool dll_platform =
-    !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
-
   for (std::string const& tgt : targetList) {
 
     if (this->Makefile->IsAlias(tgt)) {
@@ -474,7 +470,7 @@
         // Shared libraries are handled differently on DLL and non-DLL
         // platforms.  All windows platforms are DLL platforms including
         // cygwin.  Currently no other platform is a DLL platform.
-        if (dll_platform) {
+        if (target.IsDLLPlatform()) {
           // When in namelink only mode skip all libraries on Windows.
           if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
             continue;
@@ -643,7 +639,8 @@
         // On DLL platforms an executable may also have an import
         // library.  Install it to the archive destination if it
         // exists.
-        if (dll_platform && !archiveArgs.GetDestination().empty() &&
+        if ((target.IsDLLPlatform() || target.IsAIX()) &&
+            !archiveArgs.GetDestination().empty() &&
             target.IsExecutableWithExports()) {
           // The import library uses the ARCHIVE properties.
           archiveGenerator = CreateInstallTargetGenerator(
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 202c438..28bf443 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmInstallCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmInstallCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index 14288f6..c8ebc8c 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -8,7 +8,7 @@
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 
 cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
   std::vector<std::string> const& dirs, const char* dest,
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index efbcb67..4522669 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallFilesCommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallFilesGenerator.h"
@@ -13,7 +12,13 @@
 
 class cmExecutionStatus;
 
-// cmExecutableCommand
+static std::string FindInstallSource(cmMakefile& makefile, const char* name);
+static void CreateInstallGenerator(cmMakefile& makefile,
+                                   std::string const& dest,
+                                   std::vector<std::string> const& files);
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+                        std::vector<std::string> const& args);
+
 bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args,
                                         cmExecutionStatus&)
 {
@@ -25,18 +30,20 @@
   // Enable the install target.
   this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
 
-  this->Destination = args[0];
+  std::string const& dest = args[0];
 
   if ((args.size() > 1) && (args[1] == "FILES")) {
-    this->IsFilesForm = true;
+    std::vector<std::string> files;
     for (std::string const& arg : cmMakeRange(args).advance(2)) {
       // Find the source location for each file listed.
-      this->Files.push_back(this->FindInstallSource(arg.c_str()));
+      files.push_back(FindInstallSource(*this->Makefile, arg.c_str()));
     }
-    this->CreateInstallGenerator();
+    CreateInstallGenerator(*this->Makefile, dest, files);
   } else {
-    this->IsFilesForm = false;
-    cmAppend(this->FinalArgs, args.begin() + 1, args.end());
+    std::vector<std::string> finalArgs(args.begin() + 1, args.end());
+    this->Makefile->AddFinalAction([dest, finalArgs](cmMakefile& makefile) {
+      FinalAction(makefile, dest, finalArgs);
+    });
   }
 
   this->Makefile->GetGlobalGenerator()->AddInstallComponent(
@@ -45,23 +52,20 @@
   return true;
 }
 
-void cmInstallFilesCommand::FinalPass()
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+                        std::vector<std::string> const& args)
 {
-  // No final pass for "FILES" form of arguments.
-  if (this->IsFilesForm) {
-    return;
-  }
-
   std::string testf;
-  std::string const& ext = this->FinalArgs[0];
+  std::string const& ext = args[0];
+  std::vector<std::string> installFiles;
 
   // two different options
-  if (this->FinalArgs.size() > 1) {
+  if (args.size() > 1) {
     // now put the files into the list
-    std::vector<std::string>::iterator s = this->FinalArgs.begin();
+    std::vector<std::string>::const_iterator s = args.begin();
     ++s;
     // for each argument, get the files
-    for (; s != this->FinalArgs.end(); ++s) {
+    for (; s != args.end(); ++s) {
       // replace any variables
       std::string const& temps = *s;
       if (!cmSystemTools::GetFilenamePath(temps).empty()) {
@@ -72,30 +76,31 @@
       }
 
       // add to the result
-      this->Files.push_back(this->FindInstallSource(testf.c_str()));
+      installFiles.push_back(FindInstallSource(makefile, testf.c_str()));
     }
   } else // reg exp list
   {
     std::vector<std::string> files;
-    std::string const& regex = this->FinalArgs[0];
-    cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(), regex,
-                        files);
+    std::string const& regex = args[0];
+    cmSystemTools::Glob(makefile.GetCurrentSourceDirectory(), regex, files);
 
     std::vector<std::string>::iterator s = files.begin();
     // for each argument, get the files
     for (; s != files.end(); ++s) {
-      this->Files.push_back(this->FindInstallSource(s->c_str()));
+      installFiles.push_back(FindInstallSource(makefile, s->c_str()));
     }
   }
 
-  this->CreateInstallGenerator();
+  CreateInstallGenerator(makefile, dest, installFiles);
 }
 
-void cmInstallFilesCommand::CreateInstallGenerator() const
+static void CreateInstallGenerator(cmMakefile& makefile,
+                                   std::string const& dest,
+                                   std::vector<std::string> const& files)
 {
   // Construct the destination.  This command always installs under
   // the prefix.  We skip the leading slash given by the user.
-  std::string destination = this->Destination.substr(1);
+  std::string destination = dest.substr(1);
   cmSystemTools::ConvertToUnixSlashes(destination);
   if (destination.empty()) {
     destination = ".";
@@ -106,12 +111,12 @@
   const char* no_rename = "";
   bool no_exclude_from_all = false;
   std::string no_component =
-    this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+    makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
   std::vector<std::string> no_configurations;
   cmInstallGenerator::MessageLevel message =
-    cmInstallGenerator::SelectMessageLevel(this->Makefile);
-  this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator(
-    this->Files, destination.c_str(), false, no_permissions, no_configurations,
+    cmInstallGenerator::SelectMessageLevel(&makefile);
+  makefile.AddInstallGenerator(new cmInstallFilesGenerator(
+    files, destination.c_str(), false, no_permissions, no_configurations,
     no_component.c_str(), message, no_exclude_from_all, no_rename));
 }
 
@@ -121,7 +126,7 @@
  * present in the build tree.  If a full path is given, it is just
  * returned.
  */
-std::string cmInstallFilesCommand::FindInstallSource(const char* name) const
+static std::string FindInstallSource(cmMakefile& makefile, const char* name)
 {
   if (cmSystemTools::FileIsFullPath(name) ||
       cmGeneratorExpression::Find(name) == 0) {
@@ -130,10 +135,10 @@
   }
 
   // This is a relative path.
-  std::string tb = this->Makefile->GetCurrentBinaryDirectory();
+  std::string tb = makefile.GetCurrentBinaryDirectory();
   tb += "/";
   tb += name;
-  std::string ts = this->Makefile->GetCurrentSourceDirectory();
+  std::string ts = makefile.GetCurrentSourceDirectory();
   ts += "/";
   ts += name;
 
diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h
index a52f45e..f9b84fd 100644
--- a/Source/cmInstallFilesCommand.h
+++ b/Source/cmInstallFilesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmInstallFilesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmInstallFilesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
@@ -32,25 +37,6 @@
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
-
-  /**
-   * This is called at the end after all the information
-   * specified by the command is accumulated. Most commands do
-   * not implement this method.  At this point, reading and
-   * writing to the cache can be done.
-   */
-  void FinalPass() override;
-  bool HasFinalPass() const override { return !this->IsFilesForm; }
-
-protected:
-  void CreateInstallGenerator() const;
-  std::string FindInstallSource(const char* name) const;
-
-private:
-  std::vector<std::string> FinalArgs;
-  bool IsFilesForm = false;
-  std::string Destination;
-  std::vector<std::string> Files;
 };
 
 #endif
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index 2ed9f73..e8e82cc 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -6,7 +6,7 @@
 #include "cmInstallType.h"
 #include "cmSystemTools.h"
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 
 class cmLocalGenerator;
 
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index a58f875..6ec02e7 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallProgramsCommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallFilesGenerator.h"
@@ -12,6 +11,10 @@
 
 class cmExecutionStatus;
 
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+                        std::vector<std::string> const& args);
+static std::string FindInstallSource(cmMakefile& makefile, const char* name);
+
 // cmExecutableCommand
 bool cmInstallProgramsCommand::InitialPass(
   std::vector<std::string> const& args, cmExecutionStatus&)
@@ -24,51 +27,55 @@
   // Enable the install target.
   this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
 
-  this->Destination = args[0];
-
-  cmAppend(this->FinalArgs, args.begin() + 1, args.end());
-
   this->Makefile->GetGlobalGenerator()->AddInstallComponent(
     this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
 
+  std::string const& dest = args[0];
+  std::vector<std::string> const finalArgs(args.begin() + 1, args.end());
+  this->Makefile->AddFinalAction([dest, finalArgs](cmMakefile& makefile) {
+    FinalAction(makefile, dest, finalArgs);
+  });
   return true;
 }
 
-void cmInstallProgramsCommand::FinalPass()
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+                        std::vector<std::string> const& args)
 {
   bool files_mode = false;
-  if (!this->FinalArgs.empty() && this->FinalArgs[0] == "FILES") {
+  if (!args.empty() && args[0] == "FILES") {
     files_mode = true;
   }
 
+  std::vector<std::string> files;
+
   // two different options
-  if (this->FinalArgs.size() > 1 || files_mode) {
+  if (args.size() > 1 || files_mode) {
     // for each argument, get the programs
-    std::vector<std::string>::iterator s = this->FinalArgs.begin();
+    std::vector<std::string>::const_iterator s = args.begin();
     if (files_mode) {
       // Skip the FILES argument in files mode.
       ++s;
     }
-    for (; s != this->FinalArgs.end(); ++s) {
+    for (; s != args.end(); ++s) {
       // add to the result
-      this->Files.push_back(this->FindInstallSource(s->c_str()));
+      files.push_back(FindInstallSource(makefile, s->c_str()));
     }
   } else // reg exp list
   {
     std::vector<std::string> programs;
-    cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(),
-                        this->FinalArgs[0], programs);
+    cmSystemTools::Glob(makefile.GetCurrentSourceDirectory(), args[0],
+                        programs);
 
     std::vector<std::string>::iterator s = programs.begin();
     // for each argument, get the programs
     for (; s != programs.end(); ++s) {
-      this->Files.push_back(this->FindInstallSource(s->c_str()));
+      files.push_back(FindInstallSource(makefile, s->c_str()));
     }
   }
 
   // Construct the destination.  This command always installs under
   // the prefix.  We skip the leading slash given by the user.
-  std::string destination = this->Destination.substr(1);
+  std::string destination = dest.substr(1);
   cmSystemTools::ConvertToUnixSlashes(destination);
   if (destination.empty()) {
     destination = ".";
@@ -79,12 +86,12 @@
   const char* no_rename = "";
   bool no_exclude_from_all = false;
   std::string no_component =
-    this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+    makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
   std::vector<std::string> no_configurations;
   cmInstallGenerator::MessageLevel message =
-    cmInstallGenerator::SelectMessageLevel(this->Makefile);
-  this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator(
-    this->Files, destination.c_str(), true, no_permissions, no_configurations,
+    cmInstallGenerator::SelectMessageLevel(&makefile);
+  makefile.AddInstallGenerator(new cmInstallFilesGenerator(
+    files, destination.c_str(), true, no_permissions, no_configurations,
     no_component.c_str(), message, no_exclude_from_all, no_rename));
 }
 
@@ -94,7 +101,7 @@
  * present in the build tree.  If a full path is given, it is just
  * returned.
  */
-std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const
+static std::string FindInstallSource(cmMakefile& makefile, const char* name)
 {
   if (cmSystemTools::FileIsFullPath(name) ||
       cmGeneratorExpression::Find(name) == 0) {
@@ -103,10 +110,10 @@
   }
 
   // This is a relative path.
-  std::string tb = this->Makefile->GetCurrentBinaryDirectory();
+  std::string tb = makefile.GetCurrentBinaryDirectory();
   tb += "/";
   tb += name;
-  std::string ts = this->Makefile->GetCurrentSourceDirectory();
+  std::string ts = makefile.GetCurrentSourceDirectory();
   ts += "/";
   ts += name;
 
diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h
index 5c705eb..ccd621d 100644
--- a/Source/cmInstallProgramsCommand.h
+++ b/Source/cmInstallProgramsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmInstallProgramsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmInstallProgramsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
@@ -32,24 +37,6 @@
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
-
-  /**
-   * This is called at the end after all the information
-   * specified by the command is accumulated. Most commands do
-   * not implement this method.  At this point, reading and
-   * writing to the cache can be done.
-   */
-  void FinalPass() override;
-
-  bool HasFinalPass() const override { return true; }
-
-protected:
-  std::string FindInstallSource(const char* name) const;
-
-private:
-  std::vector<std::string> FinalArgs;
-  std::string Destination;
-  std::vector<std::string> Files;
 };
 
 #endif
diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx
index 5832d27..b7b7817 100644
--- a/Source/cmInstallScriptGenerator.cxx
+++ b/Source/cmInstallScriptGenerator.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallScriptGenerator.h"
 
+#include <memory>
 #include <ostream>
 #include <vector>
 
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 7c5a55b..a61239e 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -4,6 +4,7 @@
 
 #include <assert.h>
 #include <map>
+#include <memory>
 #include <set>
 #include <sstream>
 #include <utility>
@@ -16,6 +17,8 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -632,17 +635,34 @@
     return;
   }
 
-  // Get the install RPATH from the link information.
-  std::string newRpath = cli->GetChrpathString();
-
   // Write a rule to remove the installed file if its rpath is not the
   // new rpath.  This is needed for existing build/install trees when
   // the installed rpath changes but the file is not rebuilt.
-  /* clang-format off */
   os << indent << "file(RPATH_CHECK\n"
-     << indent << "     FILE \"" << toDestDirPath << "\"\n"
-     << indent << "     RPATH \"" << newRpath << "\")\n";
-  /* clang-format on */
+     << indent << "     FILE \"" << toDestDirPath << "\"\n";
+
+  // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
+  // CMake install script.
+  switch (this->Target->GetPolicyStatusCMP0095()) {
+    case cmPolicies::WARN:
+      // No author warning needed here, we warn later in
+      // cmInstallTargetGenerator::AddChrpathPatchRule().
+      CM_FALLTHROUGH;
+    case cmPolicies::OLD: {
+      // Get the install RPATH from the link information.
+      std::string newRpath = cli->GetChrpathString();
+      os << indent << "     RPATH \"" << newRpath << "\")\n";
+      break;
+    }
+    default: {
+      // Get the install RPATH from the link information and
+      // escape any CMake syntax in the install RPATH.
+      std::string escapedNewRpath =
+        cmOutputConverter::EscapeForCMake(cli->GetChrpathString());
+      os << indent << "     RPATH " << escapedNewRpath << ")\n";
+      break;
+    }
+  }
 }
 
 void cmInstallTargetGenerator::AddChrpathPatchRule(
@@ -731,11 +751,34 @@
       return;
     }
 
+    // Escape any CMake syntax in the RPATHs.
+    std::string escapedOldRpath = cmOutputConverter::EscapeForCMake(oldRpath);
+    std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath);
+
     // Write a rule to run chrpath to set the install-tree RPATH
     os << indent << "file(RPATH_CHANGE\n"
        << indent << "     FILE \"" << toDestDirPath << "\"\n"
-       << indent << "     OLD_RPATH \"" << oldRpath << "\"\n"
-       << indent << "     NEW_RPATH \"" << newRpath << "\")\n";
+       << indent << "     OLD_RPATH " << escapedOldRpath << "\n";
+
+    // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
+    // CMake install script.
+    switch (this->Target->GetPolicyStatusCMP0095()) {
+      case cmPolicies::WARN:
+        this->IssueCMP0095Warning(newRpath);
+        CM_FALLTHROUGH;
+      case cmPolicies::OLD:
+        os << indent << "     NEW_RPATH \"" << newRpath << "\"";
+        break;
+      default:
+        os << indent << "     NEW_RPATH " << escapedNewRpath;
+        break;
+    }
+
+    if (this->Target->GetPropertyAsBool("INSTALL_REMOVE_ENVIRONMENT_RPATH")) {
+      os << "\n" << indent << "     INSTALL_REMOVE_ENVIRONMENT_RPATH)\n";
+    } else {
+      os << indent << ")\n";
+    }
   }
 }
 
@@ -838,3 +881,26 @@
      << "\"" << this->Target->Target->GetName() << "\" "
      << "\"" << toDestDirPath << "\")\n";
 }
+
+void cmInstallTargetGenerator::IssueCMP0095Warning(
+  const std::string& unescapedRpath)
+{
+  // Reduce warning noise to cases where used RPATHs may actually be affected
+  // by CMP0095. This filter is meant to skip warnings in cases when
+  // non-curly-braces syntax (e.g. $ORIGIN) or no keyword is used which has
+  // worked already before CMP0095. We intend to issue a warning in all cases
+  // with curly-braces syntax, even if the workaround of double-escaping is in
+  // place, since we deprecate the need for it with CMP0095.
+  const bool potentially_affected(unescapedRpath.find("${") !=
+                                  std::string::npos);
+
+  if (potentially_affected) {
+    std::ostringstream w;
+    w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0095) << "\n";
+    w << "RPATH entries for target '" << this->Target->GetName() << "' "
+      << "will not be escaped in the intermediary "
+      << "cmake_install.cmake script.";
+    this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+      MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+  }
+}
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index ed3ab52..9ccad63 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -104,6 +104,7 @@
                      const std::string& toDestDirPath);
   void AddUniversalInstallRule(std::ostream& os, Indent indent,
                                const std::string& toDestDirPath);
+  void IssueCMP0095Warning(const std::string& unescapedRpath);
 
   std::string TargetName;
   cmGeneratorTarget* Target;
diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h
index 9950fb7..55e69ba 100644
--- a/Source/cmInstallTargetsCommand.h
+++ b/Source/cmInstallTargetsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmInstallTargetsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmInstallTargetsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h
index b7d602e..eb827be 100644
--- a/Source/cmInstalledFile.h
+++ b/Source/cmInstalledFile.h
@@ -8,7 +8,7 @@
 #include "cmGeneratorExpression.h"
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx
index 636a8e1..2423faf 100644
--- a/Source/cmJsonObjects.cxx
+++ b/Source/cmJsonObjects.cxx
@@ -14,7 +14,6 @@
 #include "cmLinkLineComputer.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
-#include "cmProperty.h"
 #include "cmPropertyMap.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
@@ -32,6 +31,7 @@
 #include <functional>
 #include <limits>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -363,12 +363,12 @@
 
   // Build up the list of properties that may have been specified
   Json::Value properties = Json::arrayValue;
-  for (auto& prop : testInfo->GetProperties()) {
+  for (auto& prop : testInfo->GetProperties().GetList()) {
     Json::Value entry = Json::objectValue;
     entry[kKEY_KEY] = prop.first;
 
     // Remove config variables from the value too.
-    auto cge_value = ge.Parse(prop.second.GetValue());
+    auto cge_value = ge.Parse(prop.second);
     const std::string& processed_value = cge_value->Evaluate(lg, config);
     entry[kVALUE_KEY] = processed_value;
     properties.append(entry);
@@ -516,9 +516,11 @@
     Json::Value artifacts = Json::arrayValue;
     artifacts.append(
       target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
-    if (target->IsDLLPlatform()) {
+    if (target->HasImportLibrary(config)) {
       artifacts.append(
         target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
+    }
+    if (target->IsDLLPlatform()) {
       const cmGeneratorTarget::OutputInfo* output =
         target->GetOutputInfo(config);
       if (output && !output->PdbDir.empty()) {
diff --git a/Source/cmLDConfigLDConfigTool.cxx b/Source/cmLDConfigLDConfigTool.cxx
new file mode 100644
index 0000000..586ea96
--- /dev/null
+++ b/Source/cmLDConfigLDConfigTool.cxx
@@ -0,0 +1,70 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmLDConfigLDConfigTool.h"
+#include "cmMakefile.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmSystemTools.h"
+#include "cmUVProcessChain.h"
+
+#include "cmsys/RegularExpression.hxx"
+
+#include <istream>
+#include <string>
+#include <vector>
+
+cmLDConfigLDConfigTool::cmLDConfigLDConfigTool(
+  cmRuntimeDependencyArchive* archive)
+  : cmLDConfigTool(archive)
+{
+}
+
+bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths)
+{
+  std::string ldConfigPath =
+    this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_COMMAND");
+  if (ldConfigPath.empty()) {
+    ldConfigPath = cmSystemTools::FindProgram(
+      "ldconfig", { "/sbin", "/usr/sbin", "/usr/local/sbin" });
+    if (ldConfigPath.empty()) {
+      this->Archive->SetError("Could not find ldconfig");
+      return false;
+    }
+  }
+
+  std::vector<std::string> ldConfigCommand;
+  cmSystemTools::ExpandListArgument(ldConfigPath, ldConfigCommand);
+  ldConfigCommand.emplace_back("-v");
+  ldConfigCommand.emplace_back("-N"); // Don't rebuild the cache.
+  ldConfigCommand.emplace_back("-X"); // Don't update links.
+
+  cmUVProcessChainBuilder builder;
+  builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
+    .AddCommand(ldConfigCommand);
+  auto process = builder.Start();
+  if (!process.Valid()) {
+    this->Archive->SetError("Failed to start ldconfig process");
+    return false;
+  }
+
+  std::string line;
+  static const cmsys::RegularExpression regex("^([^\t:]*):");
+  while (std::getline(*process.OutputStream(), line)) {
+    cmsys::RegularExpressionMatch match;
+    if (regex.find(line.c_str(), match)) {
+      paths.push_back(match.match(1));
+    }
+  }
+
+  if (!process.Wait()) {
+    this->Archive->SetError("Failed to wait on ldconfig process");
+    return false;
+  }
+  auto status = process.GetStatus();
+  if (!status[0] || status[0]->ExitStatus != 0) {
+    this->Archive->SetError("Failed to run ldconfig");
+    return false;
+  }
+
+  return true;
+}
diff --git a/Source/cmLDConfigLDConfigTool.h b/Source/cmLDConfigLDConfigTool.h
new file mode 100644
index 0000000..d945a9b
--- /dev/null
+++ b/Source/cmLDConfigLDConfigTool.h
@@ -0,0 +1,22 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmLDConfigLDConfigTool_h
+#define cmLDConfigLDConfigTool_h
+
+#include "cmLDConfigTool.h"
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmLDConfigLDConfigTool : public cmLDConfigTool
+{
+public:
+  cmLDConfigLDConfigTool(cmRuntimeDependencyArchive* archive);
+
+  bool GetLDConfigPaths(std::vector<std::string>& paths) override;
+};
+
+#endif
diff --git a/Source/cmLDConfigTool.cxx b/Source/cmLDConfigTool.cxx
new file mode 100644
index 0000000..8d5d563
--- /dev/null
+++ b/Source/cmLDConfigTool.cxx
@@ -0,0 +1,9 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmLDConfigTool.h"
+
+cmLDConfigTool::cmLDConfigTool(cmRuntimeDependencyArchive* archive)
+  : Archive(archive)
+{
+}
diff --git a/Source/cmLDConfigTool.h b/Source/cmLDConfigTool.h
new file mode 100644
index 0000000..c816562
--- /dev/null
+++ b/Source/cmLDConfigTool.h
@@ -0,0 +1,24 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmLDConfigTool_h
+#define cmLDConfigTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmLDConfigTool
+{
+public:
+  cmLDConfigTool(cmRuntimeDependencyArchive* archive);
+  virtual ~cmLDConfigTool() = default;
+
+  virtual bool GetLDConfigPaths(std::vector<std::string>& paths) = 0;
+
+protected:
+  cmRuntimeDependencyArchive* Archive;
+};
+
+#endif
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index 7850977..a278925 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -4,11 +4,11 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h
index ae4fb7f..1a439de 100644
--- a/Source/cmLinkDirectoriesCommand.h
+++ b/Source/cmLinkDirectoriesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -26,7 +28,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmLinkDirectoriesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmLinkDirectoriesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
index 5b635b5..6450c62 100644
--- a/Source/cmLinkItem.h
+++ b/Source/cmLinkItem.h
@@ -58,6 +58,9 @@
 {
   // Libraries listed in the interface.
   std::vector<cmLinkItem> Libraries;
+
+  // Whether the list depends on a genex referencing the head target.
+  bool HadHeadSensitiveCondition = false;
 };
 
 struct cmLinkInterface : public cmLinkInterfaceLibraries
@@ -84,7 +87,6 @@
   bool LibrariesDone = false;
   bool AllDone = false;
   bool Exists = false;
-  bool HadHeadSensitiveCondition = false;
   const char* ExplicitLibraries = nullptr;
 };
 
diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h
index af25fba..484ab0a 100644
--- a/Source/cmLinkLibrariesCommand.h
+++ b/Source/cmLinkLibrariesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmLinkLibrariesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmLinkLibrariesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index 469faca..8746b35 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -110,8 +110,7 @@
       if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
           target->GetType() == cmStateEnums::SHARED_LIBRARY) {
         cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact;
-        if (target->GetType() == cmStateEnums::SHARED_LIBRARY &&
-            target->IsDLLPlatform()) {
+        if (target->HasImportLibrary(cli.GetConfig())) {
           type = cmStateEnums::ImportLibraryArtifact;
         }
 
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 8d2add6..656907a 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -9,7 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
@@ -17,6 +16,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmOutputConverter;
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 1b01ea2..8c14596 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -13,6 +13,9 @@
 #include <stdio.h>
 #include <stdlib.h> // required for atoi
 #include <utility>
+#include <vector>
+
+#include "cm_memory.hxx"
 
 #include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
@@ -20,6 +23,7 @@
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmStringReplaceHelper.h"
 #include "cmSystemTools.h"
 
@@ -219,7 +223,7 @@
     value += varArgsExpanded[item];
   }
 
-  this->Makefile->AddDefinition(variableName, value.c_str());
+  this->Makefile->AddDefinition(variableName, value);
   return true;
 }
 
@@ -243,7 +247,7 @@
     std::string::size_type(listString.empty() || args.empty());
   listString += &";"[offset] + cmJoin(cmMakeRange(args).advance(2), ";");
 
-  this->Makefile->AddDefinition(listName, listString.c_str());
+  this->Makefile->AddDefinition(listName, listString);
   return true;
 }
 
@@ -268,7 +272,7 @@
   listString.insert(0,
                     cmJoin(cmMakeRange(args).advance(2), ";") + &";"[offset]);
 
-  this->Makefile->AddDefinition(listName, listString.c_str());
+  this->Makefile->AddDefinition(listName, listString);
   return true;
 }
 
@@ -296,7 +300,7 @@
       // Ok, assign elements to be removed to the given variables
       for (; !varArgsExpanded.empty() && ai != args.cend(); ++ai) {
         assert(!ai->empty());
-        this->Makefile->AddDefinition(*ai, varArgsExpanded.back().c_str());
+        this->Makefile->AddDefinition(*ai, varArgsExpanded.back());
         varArgsExpanded.pop_back();
       }
       // Undefine the rest variables if the list gets empty earlier...
@@ -305,8 +309,7 @@
       }
     }
 
-    this->Makefile->AddDefinition(listName,
-                                  cmJoin(varArgsExpanded, ";").c_str());
+    this->Makefile->AddDefinition(listName, cmJoin(varArgsExpanded, ";"));
 
   } else if (ai !=
              args.cend()) { // The list is empty, but some args were given
@@ -344,7 +347,7 @@
       auto vi = varArgsExpanded.begin();
       for (; vi != varArgsExpanded.end() && ai != args.cend(); ++ai, ++vi) {
         assert(!ai->empty());
-        this->Makefile->AddDefinition(*ai, vi->c_str());
+        this->Makefile->AddDefinition(*ai, *vi);
       }
       varArgsExpanded.erase(varArgsExpanded.begin(), vi);
       // Undefine the rest variables if the list gets empty earlier...
@@ -353,8 +356,7 @@
       }
     }
 
-    this->Makefile->AddDefinition(listName,
-                                  cmJoin(varArgsExpanded, ";").c_str());
+    this->Makefile->AddDefinition(listName, cmJoin(varArgsExpanded, ";"));
 
   } else if (ai !=
              args.cend()) { // The list is empty, but some args were given
@@ -388,7 +390,7 @@
   if (it != varArgsExpanded.end()) {
     std::ostringstream indexStream;
     indexStream << std::distance(varArgsExpanded.begin(), it);
-    this->Makefile->AddDefinition(variableName, indexStream.str().c_str());
+    this->Makefile->AddDefinition(variableName, indexStream.str());
     return true;
   }
 
@@ -434,7 +436,7 @@
                          args.end());
 
   std::string value = cmJoin(varArgsExpanded, ";");
-  this->Makefile->AddDefinition(listName, value.c_str());
+  this->Makefile->AddDefinition(listName, value);
   return true;
 }
 
@@ -462,7 +464,7 @@
   std::string value =
     cmJoin(cmMakeRange(varArgsExpanded.begin(), varArgsExpanded.end()), glue);
 
-  this->Makefile->AddDefinition(variableName, value.c_str());
+  this->Makefile->AddDefinition(variableName, value);
   return true;
 }
 
@@ -491,7 +493,7 @@
     cmRemoveMatching(varArgsExpanded, cmMakeRange(remBegin, remEnd));
   std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
   std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
-  this->Makefile->AddDefinition(listName, value.c_str());
+  this->Makefile->AddDefinition(listName, value);
   return true;
 }
 
@@ -512,7 +514,7 @@
 
   std::string value = cmJoin(cmReverseRange(varArgsExpanded), ";");
 
-  this->Makefile->AddDefinition(listName, value.c_str());
+  this->Makefile->AddDefinition(listName, value);
   return true;
 }
 
@@ -537,7 +539,7 @@
   std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
   std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
 
-  this->Makefile->AddDefinition(listName, value.c_str());
+  this->Makefile->AddDefinition(listName, value);
   return true;
 }
 
@@ -1088,7 +1090,7 @@
   }
 
   this->Makefile->AddDefinition(command.OutputName,
-                                cmJoin(varArgsExpanded, ";").c_str());
+                                cmJoin(varArgsExpanded, ";"));
 
   return true;
 }
@@ -1297,7 +1299,7 @@
   }
 
   std::string value = cmJoin(varArgsExpanded, ";");
-  this->Makefile->AddDefinition(listName, value.c_str());
+  this->Makefile->AddDefinition(listName, value);
   return true;
 }
 
@@ -1346,7 +1348,7 @@
     : size_type(start + length);
   std::vector<std::string> sublist(varArgsExpanded.begin() + start,
                                    varArgsExpanded.begin() + end);
-  this->Makefile->AddDefinition(variableName, cmJoin(sublist, ";").c_str());
+  this->Makefile->AddDefinition(variableName, cmJoin(sublist, ";"));
   return true;
 }
 
@@ -1403,7 +1405,7 @@
   std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
   std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
 
-  this->Makefile->AddDefinition(listName, value.c_str());
+  this->Makefile->AddDefinition(listName, value);
   return true;
 }
 
@@ -1497,6 +1499,6 @@
     std::remove_if(argsBegin, argsEnd, MatchesRegex(regex, includeMatches));
 
   std::string value = cmJoin(cmMakeRange(argsBegin, newArgsEnd), ";");
-  this->Makefile->AddDefinition(listName, value.c_str());
+  this->Makefile->AddDefinition(listName, value);
   return true;
 }
diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h
index ea3d643..70c7f4e 100644
--- a/Source/cmListCommand.h
+++ b/Source/cmListCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -22,7 +24,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmListCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmListCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 9457415..5de1a74 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -6,7 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <stddef.h>
 #include <string>
 #include <utility>
diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx
index b1fee8d..3fd7343 100644
--- a/Source/cmLoadCacheCommand.cxx
+++ b/Source/cmLoadCacheCommand.cxx
@@ -153,7 +153,7 @@
       // prefix.
       var = this->Prefix + var;
       if (!value.empty()) {
-        this->Makefile->AddDefinition(var, value.c_str());
+        this->Makefile->AddDefinition(var, value);
       } else {
         this->Makefile->RemoveDefinition(var);
       }
diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h
index e0f6e4f..45e52f0 100644
--- a/Source/cmLoadCacheCommand.h
+++ b/Source/cmLoadCacheCommand.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmLoadCacheCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmLoadCacheCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 69751b6..5ae660a 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -3,10 +3,14 @@
 #include "cmLoadCommandCommand.h"
 
 #include <signal.h>
+
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <utility>
+
+#include "cm_memory.hxx"
 
 #include "cmCPluginAPI.cxx"
 #include "cmCPluginAPI.h"
@@ -21,30 +25,98 @@
 #  include <malloc.h> /* for malloc/free on QNX */
 #endif
 
-extern "C" void TrapsForSignalsCFunction(int sig);
+namespace {
+
+const char* LastName = nullptr;
+
+extern "C" void TrapsForSignals(int sig)
+{
+  fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
+          LastName, sig);
+}
+
+struct SignalHandlerGuard
+{
+  explicit SignalHandlerGuard(const char* name)
+  {
+    LastName = name != nullptr ? name : "????";
+
+    signal(SIGSEGV, TrapsForSignals);
+#ifdef SIGBUS
+    signal(SIGBUS, TrapsForSignals);
+#endif
+    signal(SIGILL, TrapsForSignals);
+  }
+
+  ~SignalHandlerGuard()
+  {
+    signal(SIGSEGV, nullptr);
+#ifdef SIGBUS
+    signal(SIGBUS, nullptr);
+#endif
+    signal(SIGILL, nullptr);
+  }
+
+  SignalHandlerGuard(SignalHandlerGuard const&) = delete;
+  SignalHandlerGuard& operator=(SignalHandlerGuard const&) = delete;
+};
+
+struct LoadedCommandImpl : cmLoadedCommandInfo
+{
+  explicit LoadedCommandImpl(CM_INIT_FUNCTION init)
+    : cmLoadedCommandInfo{ 0,       0,       &cmStaticCAPI, 0,
+                           nullptr, nullptr, nullptr,       nullptr,
+                           nullptr, nullptr, nullptr,       nullptr }
+  {
+    init(this);
+  }
+
+  ~LoadedCommandImpl()
+  {
+    if (this->Destructor) {
+      SignalHandlerGuard guard(this->Name);
+      this->Destructor(this);
+    }
+    if (this->Error != nullptr) {
+      free(this->Error);
+    }
+  }
+
+  LoadedCommandImpl(LoadedCommandImpl const&) = delete;
+  LoadedCommandImpl& operator=(LoadedCommandImpl const&) = delete;
+
+  int DoInitialPass(cmMakefile* mf, int argc, char* argv[])
+  {
+    SignalHandlerGuard guard(this->Name);
+    return this->InitialPass(this, mf, argc, argv);
+  }
+
+  void DoFinalPass(cmMakefile* mf)
+  {
+    SignalHandlerGuard guard(this->Name);
+    this->FinalPass(this, mf);
+  }
+};
 
 // a class for loadabple commands
 class cmLoadedCommand : public cmCommand
 {
 public:
-  cmLoadedCommand()
+  cmLoadedCommand() = default;
+  explicit cmLoadedCommand(CM_INIT_FUNCTION init)
+    : Impl(std::make_shared<LoadedCommandImpl>(init))
   {
-    memset(&this->info, 0, sizeof(this->info));
-    this->info.CAPI = &cmStaticCAPI;
   }
 
-  //! clean up any memory allocated by the plugin
-  ~cmLoadedCommand() override;
-
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override
+  std::unique_ptr<cmCommand> Clone() override
   {
-    cmLoadedCommand* newC = new cmLoadedCommand;
+    auto newC = cm::make_unique<cmLoadedCommand>();
     // we must copy when we clone
-    memcpy(&newC->info, &this->info, sizeof(info));
-    return newC;
+    newC->Impl = this->Impl;
+    return std::unique_ptr<cmCommand>(std::move(newC));
   }
 
   /**
@@ -54,66 +126,20 @@
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus&) override;
 
-  /**
-   * This is called at the end after all the information
-   * specified by the command is accumulated. Most commands do
-   * not implement this method.  At this point, reading and
-   * writing to the cache can be done.
-   */
-  void FinalPass() override;
-  bool HasFinalPass() const override
-  {
-    return this->info.FinalPass != nullptr;
-  }
-
-  static const char* LastName;
-  static void TrapsForSignals(int sig)
-  {
-    fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
-            cmLoadedCommand::LastName, sig);
-  }
-  static void InstallSignalHandlers(const char* name, int remove = 0)
-  {
-    cmLoadedCommand::LastName = name;
-    if (!name) {
-      cmLoadedCommand::LastName = "????";
-    }
-
-    if (!remove) {
-      signal(SIGSEGV, TrapsForSignalsCFunction);
-#ifdef SIGBUS
-      signal(SIGBUS, TrapsForSignalsCFunction);
-#endif
-      signal(SIGILL, TrapsForSignalsCFunction);
-    } else {
-      signal(SIGSEGV, nullptr);
-#ifdef SIGBUS
-      signal(SIGBUS, nullptr);
-#endif
-      signal(SIGILL, nullptr);
-    }
-  }
-
-  cmLoadedCommandInfo info;
+private:
+  std::shared_ptr<LoadedCommandImpl> Impl;
 };
 
-extern "C" void TrapsForSignalsCFunction(int sig)
-{
-  cmLoadedCommand::TrapsForSignals(sig);
-}
-
-const char* cmLoadedCommand::LastName = nullptr;
-
 bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args,
                                   cmExecutionStatus&)
 {
-  if (!info.InitialPass) {
+  if (!this->Impl->InitialPass) {
     return true;
   }
 
   // clear the error string
-  if (this->info.Error) {
-    free(this->info.Error);
+  if (this->Impl->Error) {
+    free(this->Impl->Error);
   }
 
   // create argc and argv and then invoke the command
@@ -126,42 +152,26 @@
   for (i = 0; i < argc; ++i) {
     argv[i] = strdup(args[i].c_str());
   }
-  cmLoadedCommand::InstallSignalHandlers(info.Name);
-  int result = info.InitialPass(&info, this->Makefile, argc, argv);
-  cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
+  int result = this->Impl->DoInitialPass(this->Makefile, argc, argv);
   cmFreeArguments(argc, argv);
 
   if (result) {
+    if (this->Impl->FinalPass) {
+      auto impl = this->Impl;
+      this->Makefile->AddFinalAction(
+        [impl](cmMakefile& makefile) { impl->DoFinalPass(&makefile); });
+    }
     return true;
   }
 
   /* Initial Pass must have failed so set the error string */
-  if (this->info.Error) {
-    this->SetError(this->info.Error);
+  if (this->Impl->Error) {
+    this->SetError(this->Impl->Error);
   }
   return false;
 }
 
-void cmLoadedCommand::FinalPass()
-{
-  if (this->info.FinalPass) {
-    cmLoadedCommand::InstallSignalHandlers(info.Name);
-    this->info.FinalPass(&this->info, this->Makefile);
-    cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
-  }
-}
-
-cmLoadedCommand::~cmLoadedCommand()
-{
-  if (this->info.Destructor) {
-    cmLoadedCommand::InstallSignalHandlers(info.Name);
-    this->info.Destructor(&this->info);
-    cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
-  }
-  if (this->info.Error) {
-    free(this->info.Error);
-  }
-}
+} // namespace
 
 // cmLoadCommandCommand
 bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
@@ -220,7 +230,7 @@
   }
 
   // Report what file was loaded for this command.
-  this->Makefile->AddDefinition(reportVar, fullPath.c_str());
+  this->Makefile->AddDefinition(reportVar, fullPath);
 
   // find the init function
   std::string initFuncName = args[0] + "Init";
@@ -236,10 +246,9 @@
   // if the symbol is found call it to set the name on the
   // function blocker
   if (initFunction) {
-    // create a function blocker and set it up
-    cmLoadedCommand* f = new cmLoadedCommand();
-    (*initFunction)(&f->info);
-    this->Makefile->GetState()->AddScriptedCommand(args[0], f);
+    this->Makefile->GetState()->AddScriptedCommand(
+      args[0],
+      cmLegacyCommandWrapper(cm::make_unique<cmLoadedCommand>(initFunction)));
     return true;
   }
   this->SetError("Attempt to load command failed. "
diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h
index 021e6c7..d81cefb 100644
--- a/Source/cmLoadCommandCommand.h
+++ b/Source/cmLoadCommandCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmLoadCommandCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmLoadCommandCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmLoadCommandCommand>();
+  }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 };
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3abf2dd..28ae82e 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -21,27 +21,30 @@
 #include "cmState.h"
 #include "cmStateDirectory.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTestGenerator.h"
 #include "cmVersion.h"
 #include "cmake.h"
+#include "cmsys/RegularExpression.hxx"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #  define CM_LG_ENCODE_OBJECT_NAMES
 #  include "cmCryptoHash.h"
 #endif
 
-#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
 #include <initializer_list>
 #include <iterator>
+#include <memory>
 #include <sstream>
 #include <stdio.h>
 #include <string.h>
 #include <unordered_set>
 #include <utility>
+#include <vector>
 
 #if defined(__HAIKU__)
 #  include <FindDirectory.h>
@@ -1017,7 +1020,7 @@
     }
 
     for (std::string const& i : impDirVec) {
-      if (implicitSet.insert(i).second) {
+      if (implicitSet.insert(cmSystemTools::GetRealPath(i)).second) {
         implicitDirs.emplace_back(i);
       }
     }
@@ -1028,7 +1031,8 @@
                       &lang](std::string const& dir) {
     return (
       // Do not exclude directories that are not in an excluded set.
-      ((implicitSet.find(dir) == implicitSet.end()) &&
+      ((implicitSet.find(cmSystemTools::GetRealPath(dir)) ==
+        implicitSet.end()) &&
        (implicitExclude.find(dir) == implicitExclude.end()))
       // Do not exclude entries of the CPATH environment variable even though
       // they are implicitly searched by the compiler.  They are meant to be
@@ -1082,7 +1086,8 @@
   if (!stripImplicitDirs) {
     // Append implicit directories that were requested by the user only
     for (BT<std::string> const& udr : userDirs) {
-      if (implicitSet.find(udr.Value) != implicitSet.end()) {
+      if (implicitSet.find(cmSystemTools::GetRealPath(udr.Value)) !=
+          implicitSet.end()) {
         emitBT(udr);
       }
     }
@@ -1130,11 +1135,13 @@
                                              std::string const& linkLanguage,
                                              cmGeneratorTarget* target)
 {
-  this->AppendFlags(
-    flags, this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"));
-  if (!config.empty()) {
-    std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config;
-    this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name));
+  if (linkLanguage != "Swift") {
+    this->AppendFlags(
+      flags, this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"));
+    if (!config.empty()) {
+      std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config;
+      this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name));
+    }
   }
   this->AppendFlags(flags, target->GetProperty("STATIC_LIBRARY_FLAGS"));
   if (!config.empty()) {
@@ -1511,8 +1518,10 @@
         }
         CM_FALLTHROUGH;
       case cmPolicies::OLD:
-        // OLD behavior is to always add the flags
-        add_shlib_flags = true;
+        // OLD behavior is to always add the flags, except on AIX where
+        // we compute symbol exports if ENABLE_EXPORTS is on.
+        add_shlib_flags =
+          !(tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS"));
         break;
       case cmPolicies::REQUIRED_IF_USED:
       case cmPolicies::REQUIRED_ALWAYS:
@@ -1521,8 +1530,10 @@
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065));
         CM_FALLTHROUGH;
       case cmPolicies::NEW:
-        // NEW behavior is to only add the flags if ENABLE_EXPORTS is on
-        add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS");
+        // NEW behavior is to only add the flags if ENABLE_EXPORTS is on,
+        // except on AIX where we compute symbol exports.
+        add_shlib_flags =
+          !tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS");
         break;
     }
 
@@ -2963,7 +2974,7 @@
   // back to the directory-level values set by the user.
   cmMakefile* mf = this->Makefile;
   cmMakefile::ScopePushPop varScope(mf);
-  mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName.c_str());
+  mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName);
   cmLGInfoProp(mf, target, "MACOSX_BUNDLE_INFO_STRING");
   cmLGInfoProp(mf, target, "MACOSX_BUNDLE_ICON_FILE");
   cmLGInfoProp(mf, target, "MACOSX_BUNDLE_GUI_IDENTIFIER");
@@ -3002,7 +3013,7 @@
   // back to the directory-level values set by the user.
   cmMakefile* mf = this->Makefile;
   cmMakefile::ScopePushPop varScope(mf);
-  mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName.c_str());
+  mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName);
   cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_ICON_FILE");
   cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER");
   cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING");
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 81cafa3..248f4a6 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -5,7 +5,7 @@
 #include <algorithm>
 #include <assert.h>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <stdio.h>
 #include <utility>
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index c392e97..713c985 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -5,11 +5,12 @@
 #include "cmsys/FStream.hxx"
 #include "cmsys/Terminal.h"
 #include <algorithm>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmCustomCommand.h" // IWYU pragma: keep
 #include "cmCustomCommandGenerator.h"
@@ -31,6 +32,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 #include "cmake.h"
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 3fdafd2..585eb3c 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -6,7 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 
 #include "cmGlobalVisualStudioGenerator.h"
diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx
index d4af1e0..bec3ad8 100644
--- a/Source/cmMachO.cxx
+++ b/Source/cmMachO.cxx
@@ -2,12 +2,15 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMachO.h"
 
+#include "cmAlgorithms.h"
 #include "cmsys/FStream.hxx"
-#include <algorithm>
-#include <stddef.h>
+
+#include <cstddef>
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 // Include the Mach-O format information system header.
 #include <mach-o/fat.h>
 #include <mach-o/loader.h>
@@ -120,7 +123,7 @@
 
 // Implementation for reading Mach-O header and load commands.
 // This is 32 or 64 bit arch specific.
-template <class T>
+template <typename T>
 class cmMachOHeaderAndLoadCommandsImpl : public cmMachOHeaderAndLoadCommands
 {
 public:
@@ -306,15 +309,11 @@
 // External class implementation.
 
 cmMachO::cmMachO(const char* fname)
-  : Internal(nullptr)
+  : Internal(cm::make_unique<cmMachOInternal>(fname))
 {
-  this->Internal = new cmMachOInternal(fname);
 }
 
-cmMachO::~cmMachO()
-{
-  delete this->Internal;
-}
+cmMachO::~cmMachO() = default;
 
 std::string const& cmMachO::GetErrorMessage() const
 {
diff --git a/Source/cmMachO.h b/Source/cmMachO.h
index 5482465..0c44b55 100644
--- a/Source/cmMachO.h
+++ b/Source/cmMachO.h
@@ -41,7 +41,7 @@
 private:
   friend class cmMachOInternal;
   bool Valid() const;
-  cmMachOInternal* Internal;
+  std::unique_ptr<cmMachOInternal> Internal;
 };
 
 #endif
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index e9c6aea..1f2b5b2 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -6,44 +6,27 @@
 #include <stdio.h>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmPolicies.h"
 #include "cmRange.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 // define the class for macro commands
-class cmMacroHelperCommand : public cmCommand
+class cmMacroHelperCommand
 {
 public:
   /**
-   * This is a virtual constructor for the command.
-   */
-  cmCommand* Clone() override
-  {
-    cmMacroHelperCommand* newC = new cmMacroHelperCommand;
-    // we must copy when we clone
-    newC->Args = this->Args;
-    newC->Functions = this->Functions;
-    newC->FilePath = this->FilePath;
-    newC->Policies = this->Policies;
-    return newC;
-  }
-
-  /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
+  bool operator()(std::vector<cmListFileArgument> const& args,
+                  cmExecutionStatus& inStatus) const;
 
   std::vector<std::string> Args;
   std::vector<cmListFileFunction> Functions;
@@ -51,12 +34,15 @@
   std::string FilePath;
 };
 
-bool cmMacroHelperCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
+bool cmMacroHelperCommand::operator()(
+  std::vector<cmListFileArgument> const& args,
+  cmExecutionStatus& inStatus) const
 {
+  cmMakefile& makefile = inStatus.GetMakefile();
+
   // Expand the argument list to the macro.
   std::vector<std::string> expandedArgs;
-  this->Makefile->ExpandArguments(args, expandedArgs);
+  makefile.ExpandArguments(args, expandedArgs);
 
   // make sure the number of arguments passed is at least the number
   // required by the signature
@@ -64,11 +50,11 @@
     std::string errorMsg =
       "Macro invoked with incorrect arguments for macro named: ";
     errorMsg += this->Args[0];
-    this->SetError(errorMsg);
+    inStatus.SetError(errorMsg);
     return false;
   }
 
-  cmMakefile::MacroPushPop macroScope(this->Makefile, this->FilePath,
+  cmMakefile::MacroPushPop macroScope(&makefile, this->FilePath,
                                       this->Policies);
 
   // set the value of argc
@@ -130,9 +116,8 @@
       arg.Line = k.Line;
       newLFF.Arguments.push_back(std::move(arg));
     }
-    cmExecutionStatus status;
-    if (!this->Makefile->ExecuteCommand(newLFF, status) ||
-        status.GetNestedError()) {
+    cmExecutionStatus status(makefile);
+    if (!makefile.ExecuteCommand(newLFF, status) || status.GetNestedError()) {
       // The error message should have already included the call stack
       // so we do not need to report an error here.
       macroScope.Quiet();
@@ -164,12 +149,12 @@
     if (!this->Depth) {
       mf.AppendProperty("MACROS", this->Args[0].c_str());
       // create a new command and add it to cmake
-      cmMacroHelperCommand* f = new cmMacroHelperCommand();
-      f->Args = this->Args;
-      f->Functions = this->Functions;
-      f->FilePath = this->GetStartingContext().FilePath;
-      mf.RecordPolicies(f->Policies);
-      mf.GetState()->AddScriptedCommand(this->Args[0], f);
+      cmMacroHelperCommand f;
+      f.Args = this->Args;
+      f.Functions = this->Functions;
+      f.FilePath = this->GetStartingContext().FilePath;
+      mf.RecordPolicies(f.Policies);
+      mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
       // remove the function blocker now that the macro is defined
       mf.RemoveFunctionBlocker(this, lff);
       return true;
@@ -211,8 +196,10 @@
   }
 
   // create a function blocker
-  cmMacroFunctionBlocker* f = new cmMacroFunctionBlocker();
-  cmAppend(f->Args, args);
-  this->Makefile->AddFunctionBlocker(f);
+  {
+    auto fb = cm::make_unique<cmMacroFunctionBlocker>();
+    cmAppend(fb->Args, args);
+    this->Makefile->AddFunctionBlocker(std::move(fb));
+  }
   return true;
 }
diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h
index b54ed66..3ebd959 100644
--- a/Source/cmMacroCommand.h
+++ b/Source/cmMacroCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
@@ -34,7 +36,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmMacroCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmMacroCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h
index d2637f3..b1fb49b 100644
--- a/Source/cmMakeDirectoryCommand.h
+++ b/Source/cmMakeDirectoryCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -27,7 +29,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmMakeDirectoryCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmMakeDirectoryCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index e0f69cb..8188ffa 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -9,14 +9,13 @@
 #include <cstring>
 #include <ctype.h>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <utility>
 
 #include "cmAlgorithms.h"
-#include "cmCommand.h"
 #include "cmCommandArgumentParserHelper.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
@@ -118,8 +117,6 @@
   cmDeleteAll(this->SourceFiles);
   cmDeleteAll(this->Tests);
   cmDeleteAll(this->ImportedTargetsOwned);
-  cmDeleteAll(this->FinalPassCommands);
-  cmDeleteAll(this->FunctionBlockers);
   cmDeleteAll(this->EvaluationFiles);
 }
 
@@ -390,12 +387,8 @@
   }
 
   // Lookup the command prototype.
-  if (cmCommand* proto =
+  if (cmState::Command command =
         this->GetState()->GetCommandByExactName(lff.Name.Lower)) {
-    // Clone the prototype.
-    std::unique_ptr<cmCommand> pcmd(proto->Clone());
-    pcmd->SetMakefile(this);
-
     // Decide whether to invoke the command.
     if (!cmSystemTools::GetFatalErrorOccured()) {
       // if trace is enabled, print out invoke information
@@ -403,22 +396,19 @@
         this->PrintCommandTrace(lff);
       }
       // Try invoking the command.
-      bool invokeSucceeded = pcmd->InvokeInitialPass(lff.Arguments, status);
+      bool invokeSucceeded = command(lff.Arguments, status);
       bool hadNestedError = status.GetNestedError();
       if (!invokeSucceeded || hadNestedError) {
         if (!hadNestedError) {
           // The command invocation requested that we report an error.
           std::string const error =
-            std::string(lff.Name.Original) + " " + pcmd->GetError();
+            std::string(lff.Name.Original) + " " + status.GetError();
           this->IssueMessage(MessageType::FATAL_ERROR, error);
         }
         result = false;
         if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) {
           cmSystemTools::SetFatalErrorOccured();
         }
-      } else if (pcmd->HasFinalPass()) {
-        // use the command
-        this->FinalPassCommands.push_back(pcmd.release());
       }
     }
   } else {
@@ -567,8 +557,9 @@
 bool cmMakefile::ReadDependentFile(const std::string& filename,
                                    bool noPolicyScope)
 {
-  this->AddDefinition("CMAKE_PARENT_LIST_FILE",
-                      this->GetDefinition("CMAKE_CURRENT_LIST_FILE"));
+  if (const char* def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) {
+    this->AddDefinition("CMAKE_PARENT_LIST_FILE", def);
+  }
   std::string filenametoread = cmSystemTools::CollapseFullPath(
     filename, this->GetCurrentSourceDirectory());
 
@@ -651,9 +642,9 @@
     this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
   std::string currentFile = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
 
-  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread.c_str());
+  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread);
   this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
-                      cmSystemTools::GetFilenamePath(filenametoread).c_str());
+                      cmSystemTools::GetFilenamePath(filenametoread));
 
   this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
   this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
@@ -662,7 +653,7 @@
   // Run the parsed commands.
   const size_t numberFunctions = listFile.Functions.size();
   for (size_t i = 0; i < numberFunctions; ++i) {
-    cmExecutionStatus status;
+    cmExecutionStatus status(*this);
     this->ExecuteCommand(listFile.Functions[i], status);
     if (cmSystemTools::GetFatalErrorOccured()) {
       break;
@@ -674,10 +665,10 @@
   }
   this->CheckForUnusedVariables();
 
-  this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
-  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
+  this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile);
+  this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile);
   this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
-                      cmSystemTools::GetFilenamePath(currentFile).c_str());
+                      cmSystemTools::GetFilenamePath(currentFile));
   this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
   this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
   this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
@@ -769,6 +760,11 @@
 };
 }
 
+void cmMakefile::AddFinalAction(FinalAction action)
+{
+  this->FinalActions.push_back(std::move(action));
+}
+
 void cmMakefile::FinalPass()
 {
   // do all the variable expansions here
@@ -776,8 +772,8 @@
 
   // give all the commands a chance to do something
   // after the file has been parsed before generation
-  for (cmCommand* fpCommand : this->FinalPassCommands) {
-    fpCommand->FinalPass();
+  for (FinalAction& action : this->FinalActions) {
+    action(*this);
   }
 
   // go through all configured files and see which ones still exist.
@@ -1540,7 +1536,7 @@
   cmSystemTools::MakeDirectory(filesDir);
 
   assert(cmSystemTools::FileExists(currentStart, true));
-  this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str());
+  this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart);
 
   cmListFile listFile;
   if (!listFile.ParseFile(currentStart.c_str(), this->GetMessenger(),
@@ -1788,12 +1784,8 @@
   }
 }
 
-void cmMakefile::AddDefinition(const std::string& name, const char* value)
+void cmMakefile::AddDefinition(const std::string& name, cm::string_view value)
 {
-  if (!value) {
-    return;
-  }
-
   if (this->VariableInitialized(name)) {
     this->LogUnused("changing definition", name);
   }
@@ -1803,11 +1795,16 @@
   cmVariableWatch* vv = this->GetVariableWatch();
   if (vv) {
     vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
-                         value, this);
+                         value.data(), this);
   }
 #endif
 }
 
+void cmMakefile::AddDefinitionBool(const std::string& name, bool value)
+{
+  this->AddDefinition(name, value ? "ON" : "OFF");
+}
+
 void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
                                     const char* doc,
                                     cmStateEnums::CacheEntryType type,
@@ -1853,23 +1850,6 @@
   this->StateSnapshot.RemoveDefinition(name);
 }
 
-void cmMakefile::AddDefinition(const std::string& name, bool value)
-{
-  if (this->VariableInitialized(name)) {
-    this->LogUnused("changing definition", name);
-  }
-
-  this->StateSnapshot.SetDefinition(name, value ? "ON" : "OFF");
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
-  cmVariableWatch* vv = this->GetVariableWatch();
-  if (vv) {
-    vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
-                         value ? "ON" : "OFF", this);
-  }
-#endif
-}
-
 void cmMakefile::CheckForUnusedVariables() const
 {
   if (!this->WarnUnused) {
@@ -3077,19 +3057,11 @@
                                    cmExecutionStatus& status)
 {
   // if there are no blockers get out of here
-  if (this->FunctionBlockers.begin() == this->FunctionBlockers.end()) {
+  if (this->FunctionBlockers.empty()) {
     return false;
   }
 
-  // loop over all function blockers to see if any block this command
-  // evaluate in reverse, this is critical for balanced IF statements etc
-  for (cmFunctionBlocker* pos : cmReverseRange(this->FunctionBlockers)) {
-    if (pos->IsFunctionBlocked(lff, *this, status)) {
-      return true;
-    }
-  }
-
-  return false;
+  return this->FunctionBlockers.top()->IsFunctionBlocked(lff, *this, status);
 }
 
 void cmMakefile::PushFunctionBlockerBarrier()
@@ -3103,8 +3075,9 @@
   FunctionBlockersType::size_type barrier =
     this->FunctionBlockerBarriers.back();
   while (this->FunctionBlockers.size() > barrier) {
-    std::unique_ptr<cmFunctionBlocker> fb(this->FunctionBlockers.back());
-    this->FunctionBlockers.pop_back();
+    std::unique_ptr<cmFunctionBlocker> fb(
+      std::move(this->FunctionBlockers.top()));
+    this->FunctionBlockers.pop();
     if (reportError) {
       // Report the context in which the unclosed block was opened.
       cmListFileContext const& lfc = fb->GetStartingContext();
@@ -3228,54 +3201,43 @@
   return !cmSystemTools::GetFatalErrorOccured();
 }
 
-void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb)
+void cmMakefile::AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb)
 {
   if (!this->ExecutionStatusStack.empty()) {
     // Record the context in which the blocker is created.
     fb->SetStartingContext(this->GetExecutionContext());
   }
 
-  this->FunctionBlockers.push_back(fb);
+  this->FunctionBlockers.push(std::move(fb));
 }
 
 std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker(
   cmFunctionBlocker* fb, const cmListFileFunction& lff)
 {
-  // Find the function blocker stack barrier for the current scope.
-  // We only remove a blocker whose index is not less than the barrier.
-  FunctionBlockersType::size_type barrier = 0;
-  if (!this->FunctionBlockerBarriers.empty()) {
-    barrier = this->FunctionBlockerBarriers.back();
+  assert(!this->FunctionBlockers.empty());
+  assert(this->FunctionBlockers.top().get() == fb);
+  assert(this->FunctionBlockerBarriers.empty() ||
+         this->FunctionBlockers.size() > this->FunctionBlockerBarriers.back());
+
+  // Warn if the arguments do not match, but always remove.
+  if (!fb->ShouldRemove(lff, *this)) {
+    cmListFileContext const& lfc = fb->GetStartingContext();
+    cmListFileContext closingContext =
+      cmListFileContext::FromCommandContext(lff, lfc.FilePath);
+    std::ostringstream e;
+    /* clang-format off */
+    e << "A logical block opening on the line\n"
+      << "  " << lfc << "\n"
+      << "closes on the line\n"
+      << "  " << closingContext << "\n"
+      << "with mis-matching arguments.";
+    /* clang-format on */
+    this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
   }
 
-  // Search for the function blocker whose scope this command ends.
-  for (FunctionBlockersType::size_type i = this->FunctionBlockers.size();
-       i > barrier; --i) {
-    std::vector<cmFunctionBlocker*>::iterator pos =
-      this->FunctionBlockers.begin() + (i - 1);
-    if (*pos == fb) {
-      // Warn if the arguments do not match, but always remove.
-      if (!(*pos)->ShouldRemove(lff, *this)) {
-        cmListFileContext const& lfc = fb->GetStartingContext();
-        cmListFileContext closingContext =
-          cmListFileContext::FromCommandContext(lff, lfc.FilePath);
-        std::ostringstream e;
-        /* clang-format off */
-        e << "A logical block opening on the line\n"
-          << "  " << lfc << "\n"
-          << "closes on the line\n"
-          << "  " << closingContext << "\n"
-          << "with mis-matching arguments.";
-        /* clang-format on */
-        this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
-      }
-      cmFunctionBlocker* b = *pos;
-      this->FunctionBlockers.erase(pos);
-      return std::unique_ptr<cmFunctionBlocker>(b);
-    }
-  }
-
-  return std::unique_ptr<cmFunctionBlocker>();
+  auto b = std::move(this->FunctionBlockers.top());
+  this->FunctionBlockers.pop();
+  return b;
 }
 
 std::string const& cmMakefile::GetHomeDirectory() const
@@ -3290,20 +3252,20 @@
 
 void cmMakefile::SetScriptModeFile(std::string const& scriptfile)
 {
-  this->AddDefinition("CMAKE_SCRIPT_MODE_FILE", scriptfile.c_str());
+  this->AddDefinition("CMAKE_SCRIPT_MODE_FILE", scriptfile);
 }
 
 void cmMakefile::SetArgcArgv(const std::vector<std::string>& args)
 {
   std::ostringstream strStream;
   strStream << args.size();
-  this->AddDefinition("CMAKE_ARGC", strStream.str().c_str());
+  this->AddDefinition("CMAKE_ARGC", strStream.str());
   // this->MarkVariableAsUsed("CMAKE_ARGC");
 
   for (unsigned int t = 0; t < args.size(); ++t) {
     std::ostringstream tmpStream;
     tmpStream << "CMAKE_ARGV" << t;
-    this->AddDefinition(tmpStream.str(), args[t].c_str());
+    this->AddDefinition(tmpStream.str(), args[t]);
     // this->MarkVariableAsUsed(tmpStream.str().c_str());
   }
 }
@@ -3384,8 +3346,9 @@
 void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
                                 bool optional)
 {
-  this->AddDefinition("CMAKE_CFG_INTDIR",
-                      this->GetGlobalGenerator()->GetCMakeCFGIntDir());
+  if (const char* def = this->GetGlobalGenerator()->GetCMakeCFGIntDir()) {
+    this->AddDefinition("CMAKE_CFG_INTDIR", def);
+  }
   // If RC is explicitly listed we need to do it after other languages.
   // On some platforms we enable RC implicitly while enabling others.
   // Do not let that look like recursive enable_language(RC).
@@ -4237,7 +4200,7 @@
     std::string const& m = re.match(i);
     if (!m.empty()) {
       std::string const& var = matchVariables[i];
-      this->AddDefinition(var, m.c_str());
+      this->AddDefinition(var, m);
       this->MarkVariableAsUsed(var);
       highest = static_cast<char>('0' + i);
     }
@@ -4300,7 +4263,7 @@
 
   // Deprecate old policies, especially those that require a lot
   // of code to maintain the old behavior.
-  if (status == cmPolicies::OLD && id <= cmPolicies::CMP0066 &&
+  if (status == cmPolicies::OLD && id <= cmPolicies::CMP0067 &&
       !(this->GetCMakeInstance()->GetIsInTryCompile() &&
         (
           // Policies set by cmCoreTryCompile::TryCompileCode.
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index d223347..dc196ac 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -7,8 +7,9 @@
 
 #include "cmsys/RegularExpression.hxx"
 #include <deque>
+#include <functional>
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <stack>
 #include <stddef.h>
@@ -16,6 +17,8 @@
 #include <unordered_map>
 #include <vector>
 
+#include "cm_string_view.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmListFileCache.h"
 #include "cmMessageType.h"
@@ -24,13 +27,13 @@
 #include "cmSourceFileLocationKind.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmTarget.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #  include "cmSourceGroup.h"
 #endif
 
-class cmCommand;
 class cmCompiledGeneratorExpression;
 class cmCustomCommandLines;
 class cmExecutionStatus;
@@ -95,7 +98,7 @@
   /**
    * Add a function blocker to this makefile
    */
-  void AddFunctionBlocker(cmFunctionBlocker* fb);
+  void AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb);
 
   /// @return whether we are processing the top CMakeLists.txt file.
   bool IsRootMakefile() const;
@@ -125,6 +128,13 @@
   bool EnforceUniqueName(std::string const& name, std::string& msg,
                          bool isCustom = false) const;
 
+  using FinalAction = std::function<void(cmMakefile&)>;
+
+  /**
+   * Register an action that is executed during FinalPass
+   */
+  void AddFinalAction(FinalAction action);
+
   /**
    * Perform FinalPass, Library dependency analysis etc before output of the
    * makefile.
@@ -132,7 +142,7 @@
   void ConfigureFinalPass();
 
   /**
-   * run the final pass on all commands.
+   * run all FinalActions.
    */
   void FinalPass();
 
@@ -256,18 +266,17 @@
    * Add a variable definition to the build. This variable
    * can be used in CMake to refer to lists, directories, etc.
    */
-  void AddDefinition(const std::string& name, const char* value);
+  void AddDefinition(const std::string& name, cm::string_view value);
+  /**
+   * Add bool variable definition to the build.
+   */
+  void AddDefinitionBool(const std::string& name, bool);
   //! Add a definition to this makefile and the global cmake cache.
   void AddCacheDefinition(const std::string& name, const char* value,
                           const char* doc, cmStateEnums::CacheEntryType type,
                           bool force = false);
 
   /**
-   * Add bool variable definition to the build.
-   */
-  void AddDefinition(const std::string& name, bool);
-
-  /**
    * Remove a variable definition from the build.  This is not valid
    * for cache entries, and will only affect the current makefile.
    */
@@ -937,7 +946,7 @@
   size_t ObjectLibrariesSourceGroupIndex;
 #endif
 
-  std::vector<cmCommand*> FinalPassCommands;
+  std::vector<FinalAction> FinalActions;
   cmGlobalGenerator* GlobalGenerator;
   bool IsFunctionBlocked(const cmListFileFunction& lff,
                          cmExecutionStatus& status);
@@ -955,7 +964,9 @@
   bool EnforceUniqueDir(const std::string& srcPath,
                         const std::string& binPath) const;
 
-  typedef std::vector<cmFunctionBlocker*> FunctionBlockersType;
+  using FunctionBlockerPtr = std::unique_ptr<cmFunctionBlocker>;
+  using FunctionBlockersType =
+    std::stack<FunctionBlockerPtr, std::vector<FunctionBlockerPtr>>;
   FunctionBlockersType FunctionBlockers;
   std::vector<FunctionBlockersType::size_type> FunctionBlockerBarriers;
   void PushFunctionBlockerBarrier();
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 6b9b9c7..a7f2a97 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -2,13 +2,14 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMakefileExecutableTargetGenerator.h"
 
-#include <memory> // IWYU pragma: keep
 #include <set>
 #include <sstream>
 #include <string>
 #include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
@@ -482,9 +483,8 @@
 
   // Construct the main link rule.
   std::vector<std::string> real_link_commands;
-  std::string linkRuleVar = "CMAKE_";
-  linkRuleVar += linkLanguage;
-  linkRuleVar += "_LINK_EXECUTABLE";
+  std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable(
+    linkLanguage, this->ConfigName);
   std::string linkRule = this->GetLinkRule(linkRuleVar);
   std::vector<std::string> commands1;
   cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index b9f7c6d..bdde4b8 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -2,13 +2,14 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMakefileLibraryTargetGenerator.h"
 
-#include <memory> // IWYU pragma: keep
 #include <set>
 #include <sstream>
 #include <stddef.h>
 #include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index b3bab4b..008248c 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMakefileTargetGenerator.h"
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <stdio.h>
 #include <utility>
@@ -28,6 +28,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index c570a7c..9eeeed0 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -7,6 +7,7 @@
 
 #include <iosfwd>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index 4236995..8ed6be5 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -7,7 +7,8 @@
 #include <utility>
 #include <vector>
 
-#include "cmAlgorithms.h"
+#include "cm_memory.hxx"
+
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalUnixMakefileGenerator3.h"
diff --git a/Source/cmMarkAsAdvancedCommand.h b/Source/cmMarkAsAdvancedCommand.h
index 5dd198f..e367c46 100644
--- a/Source/cmMarkAsAdvancedCommand.h
+++ b/Source/cmMarkAsAdvancedCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmMarkAsAdvancedCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmMarkAsAdvancedCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h
index 0c6c76b..23633d3 100644
--- a/Source/cmMathCommand.h
+++ b/Source/cmMathCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -19,7 +21,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmMathCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmMathCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 5320ec5..66d3c88 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -2,11 +2,11 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMessageCommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmMessenger.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -25,7 +25,6 @@
   auto i = args.cbegin();
 
   auto type = MessageType::MESSAGE;
-  auto status = false;
   auto fatal = false;
   auto level = cmake::LogLevel::LOG_UNDEFINED;
   if (*i == "SEND_ERROR") {
@@ -55,19 +54,15 @@
     }
     ++i;
   } else if (*i == "STATUS") {
-    status = true;
     level = cmake::LogLevel::LOG_STATUS;
     ++i;
   } else if (*i == "VERBOSE") {
-    status = true;
     level = cmake::LogLevel::LOG_VERBOSE;
     ++i;
   } else if (*i == "DEBUG") {
-    status = true;
     level = cmake::LogLevel::LOG_DEBUG;
     ++i;
   } else if (*i == "TRACE") {
-    status = true;
     level = cmake::LogLevel::LOG_TRACE;
     ++i;
   } else if (*i == "DEPRECATION") {
@@ -105,17 +100,46 @@
 
   auto message = cmJoin(cmMakeRange(i, args.cend()), "");
 
-  if (type != MessageType::MESSAGE) {
-    // we've overridden the message type, above, so display it directly
-    cmMessenger* m = this->Makefile->GetMessenger();
-    m->DisplayMessage(type, message, this->Makefile->GetBacktrace());
-  } else {
-    if (status) {
-      this->Makefile->DisplayStatus(message, -1);
-    } else {
-      cmSystemTools::Message(message);
-    }
+  if (cmake::LogLevel::LOG_NOTICE <= level) {
+    // Check if any indentation has requested:
+    // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces
+    // to be joined and prepended to the message lines.
+    auto indent =
+      cmJoin(cmSystemTools::ExpandedListArgument(
+               this->Makefile->GetSafeDefinition("CMAKE_MESSAGE_INDENT")),
+             "");
+    // Make every line of the `message` indented
+    // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted`
+    // here cuz it appends `\n` to the EOM ;-(
+    cmSystemTools::ReplaceString(message, "\n", "\n" + indent);
+    message = indent + message;
   }
+
+  switch (level) {
+    case cmake::LogLevel::LOG_ERROR:
+    case cmake::LogLevel::LOG_WARNING:
+      // we've overridden the message type, above, so display it directly
+      this->Makefile->GetMessenger()->DisplayMessage(
+        type, message, this->Makefile->GetBacktrace());
+      break;
+
+    case cmake::LogLevel::LOG_NOTICE:
+      cmSystemTools::Message(message);
+      break;
+
+    case cmake::LogLevel::LOG_STATUS:
+    case cmake::LogLevel::LOG_VERBOSE:
+    case cmake::LogLevel::LOG_DEBUG:
+    case cmake::LogLevel::LOG_TRACE:
+      this->Makefile->DisplayStatus(message, -1);
+      break;
+
+    default:
+      assert("Unexpected log level! Review the `cmMessageCommand.cxx`." &&
+             false);
+      break;
+  }
+
   if (fatal) {
     cmSystemTools::SetFatalErrorOccured();
   }
diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h
index 819ebda..ef89d59 100644
--- a/Source/cmMessageCommand.h
+++ b/Source/cmMessageCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -22,7 +24,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmMessageCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmMessageCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index 1d790e2..07d011e 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMessenger.h"
 
-#include "cmAlgorithms.h"
 #include "cmDocumentationFormatter.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -100,8 +100,7 @@
            "it.";
   } else if (t == MessageType::AUTHOR_ERROR) {
     msg << "This error is for project developers. Use -Wno-error=dev to "
-           "suppress "
-           "it.";
+           "suppress it.";
   }
 
   // Add a terminating blank line.
diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx
index 3f6523e..1ff741e 100644
--- a/Source/cmNewLineStyle.cxx
+++ b/Source/cmNewLineStyle.cxx
@@ -41,7 +41,7 @@
   return true;
 }
 
-const std::string cmNewLineStyle::GetCharacters() const
+std::string cmNewLineStyle::GetCharacters() const
 {
   switch (NewLineStyle) {
     case Invalid:
diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h
index f1a7bc6..ab9002e 100644
--- a/Source/cmNewLineStyle.h
+++ b/Source/cmNewLineStyle.h
@@ -30,7 +30,7 @@
   bool ReadFromArguments(const std::vector<std::string>& args,
                          std::string& errorString);
 
-  const std::string GetCharacters() const;
+  std::string GetCharacters() const;
 
 private:
   Style NewLineStyle = Invalid;
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index f65abc8..cd84c03 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -6,11 +6,12 @@
 #include <assert.h>
 #include <iterator>
 #include <map>
-#include <memory> // IWYU pragma: keep
 #include <set>
 #include <sstream>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmCustomCommand.h" // IWYU pragma: keep
 #include "cmCustomCommandGenerator.h"
@@ -32,6 +33,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 2139a45..8b0a6ba 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -8,10 +8,11 @@
 #include <assert.h>
 #include <iterator>
 #include <map>
-#include <memory> // IWYU pragma: keep
 #include <ostream>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmCustomCommandGenerator.h"
@@ -30,6 +31,7 @@
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -909,8 +911,8 @@
   this->GetBuildFileStream() << "\n";
 
   if (!this->SwiftOutputMap.empty()) {
-    std::string const mapFilePath = this->ConvertToNinjaPath(
-      this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json");
+    std::string const mapFilePath =
+      this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json";
     std::string const targetSwiftDepsPath = [this]() -> std::string {
       cmGeneratorTarget const* target = this->GeneratorTarget;
       if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) {
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 3055e18..a99d8e7 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -13,7 +13,7 @@
 #include "cmOSXBundleGenerator.h"
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index 52f63a3..3724ba7 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -4,13 +4,13 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmState.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
diff --git a/Source/cmOptionCommand.h b/Source/cmOptionCommand.h
index 34e0e6f..eddab03 100644
--- a/Source/cmOptionCommand.h
+++ b/Source/cmOptionCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmOptionCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmOptionCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 585db42..2d055ff 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -13,6 +13,7 @@
 #include <assert.h>
 #include <functional>
 #include <sstream>
+#include <vector>
 
 /*
 Directory ordering computation.
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 7d88b08..da7f8bc 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -6,7 +6,6 @@
 #include <assert.h>
 #include <ctype.h>
 #include <set>
-#include <string.h>
 #include <vector>
 
 #include "cmState.h"
@@ -38,10 +37,10 @@
   return this->ConvertToOutputFormat(remote, format);
 }
 
-std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
+std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
                                                      OutputFormat output) const
 {
-  std::string result = source;
+  std::string result(source);
   // Convert it to an output path.
   if (output == SHELL || output == WATCOMQUOTE) {
     result = this->ConvertDirectorySeparatorsForShell(source);
@@ -53,9 +52,9 @@
 }
 
 std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
-  const std::string& source) const
+  cm::string_view source) const
 {
-  std::string result = source;
+  std::string result(source);
   // For the MSYS shell convert drive letters to posix paths, so
   // that c:/some/path becomes /c/some/path.  This is needed to
   // avoid problems with the shell path translation.
@@ -71,33 +70,21 @@
   return result;
 }
 
-static bool cmOutputConverterIsShellOperator(const std::string& str)
+static bool cmOutputConverterIsShellOperator(cm::string_view str)
 {
-  static std::set<std::string> shellOperators;
-  if (shellOperators.empty()) {
-    shellOperators.insert("<");
-    shellOperators.insert(">");
-    shellOperators.insert("<<");
-    shellOperators.insert(">>");
-    shellOperators.insert("|");
-    shellOperators.insert("||");
-    shellOperators.insert("&&");
-    shellOperators.insert("&>");
-    shellOperators.insert("1>");
-    shellOperators.insert("2>");
-    shellOperators.insert("2>&1");
-    shellOperators.insert("1>&2");
-  }
-  return shellOperators.count(str) > 0;
+  static std::set<cm::string_view> const shellOperators{
+    "<", ">", "<<", ">>", "|", "||", "&&", "&>", "1>", "2>", "2>&1", "1>&2"
+  };
+  return (shellOperators.count(str) != 0);
 }
 
-std::string cmOutputConverter::EscapeForShell(const std::string& str,
+std::string cmOutputConverter::EscapeForShell(cm::string_view str,
                                               bool makeVars, bool forEcho,
                                               bool useWatcomQuote) const
 {
   // Do not escape shell operators.
   if (cmOutputConverterIsShellOperator(str)) {
-    return str;
+    return std::string(str);
   }
 
   // Compute the flags for the target shell environment.
@@ -129,46 +116,44 @@
     flags |= Shell_Flag_IsUnix;
   }
 
-  return Shell__GetArgument(str.c_str(), flags);
+  return Shell__GetArgument(str, flags);
 }
 
-std::string cmOutputConverter::EscapeForCMake(const std::string& str)
+std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
 {
   // Always double-quote the argument to take care of most escapes.
   std::string result = "\"";
-  for (const char* c = str.c_str(); *c; ++c) {
-    if (*c == '"') {
+  for (const char c : str) {
+    if (c == '"') {
       // Escape the double quote to avoid ending the argument.
       result += "\\\"";
-    } else if (*c == '$') {
+    } else if (c == '$') {
       // Escape the dollar to avoid expanding variables.
       result += "\\$";
-    } else if (*c == '\\') {
+    } else if (c == '\\') {
       // Escape the backslash to avoid other escapes.
       result += "\\\\";
     } else {
       // Other characters will be parsed correctly.
-      result += *c;
+      result += c;
     }
   }
   result += "\"";
   return result;
 }
 
-std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg,
+std::string cmOutputConverter::EscapeWindowsShellArgument(cm::string_view arg,
                                                           int shell_flags)
 {
   return Shell__GetArgument(arg, shell_flags);
 }
 
 cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
-  const char* value)
+  cm::string_view value)
 {
   FortranFormat format = FortranFormatNone;
-  if (value && *value) {
-    std::vector<std::string> fmt;
-    cmSystemTools::ExpandListArgument(value, fmt);
-    for (std::string const& fi : fmt) {
+  if (!value.empty()) {
+    for (std::string const& fi : cmSystemTools::ExpandedListArgument(value)) {
       if (fi == "FIXED") {
         format = FortranFormatFixed;
       }
@@ -180,6 +165,15 @@
   return format;
 }
 
+cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
+  const char* value)
+{
+  if (!value) {
+    return FortranFormatNone;
+  }
+  return GetFortranFormat(cm::string_view(value));
+}
+
 void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
 {
   this->LinkScriptShell = linkScriptShell;
@@ -225,12 +219,12 @@
 */
 
 /* Some helpers to identify character classes */
-static int Shell__CharIsWhitespace(char c)
+static bool Shell__CharIsWhitespace(char c)
 {
   return ((c == ' ') || (c == '\t'));
 }
 
-static int Shell__CharNeedsQuotesOnUnix(char c)
+static bool Shell__CharNeedsQuotesOnUnix(char c)
 {
   return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
           (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -238,51 +232,52 @@
           (c == '\\'));
 }
 
-static int Shell__CharNeedsQuotesOnWindows(char c)
+static bool Shell__CharNeedsQuotesOnWindows(char c)
 {
   return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
           (c == '>') || (c == '|') || (c == '^'));
 }
 
-static int Shell__CharIsMakeVariableName(char c)
+static bool Shell__CharIsMakeVariableName(char c)
 {
   return c && (c == '_' || isalpha((static_cast<int>(c))));
 }
 
-int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
+bool cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
 {
   /* On Windows the built-in command shell echo never needs quotes.  */
   if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) {
-    return 0;
+    return false;
   }
 
   /* On all platforms quotes are needed to preserve whitespace.  */
   if (Shell__CharIsWhitespace(c)) {
-    return 1;
+    return true;
   }
 
   if (flags & Shell_Flag_IsUnix) {
     /* On UNIX several special characters need quotes to preserve them.  */
     if (Shell__CharNeedsQuotesOnUnix(c)) {
-      return 1;
+      return true;
     }
   } else {
     /* On Windows several special characters need quotes to preserve them.  */
     if (Shell__CharNeedsQuotesOnWindows(c)) {
-      return 1;
+      return true;
     }
   }
-  return 0;
+  return false;
 }
 
-const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
+cm::string_view::iterator cmOutputConverter::Shell__SkipMakeVariables(
+  cm::string_view::iterator c, cm::string_view::iterator end)
 {
-  while (*c == '$' && *(c + 1) == '(') {
-    const char* skip = c + 2;
-    while (Shell__CharIsMakeVariableName(*skip)) {
+  while ((c != end && (c + 1) != end) && (*c == '$' && *(c + 1) == '(')) {
+    cm::string_view::iterator skip = c + 2;
+    while ((skip != end) && Shell__CharIsMakeVariableName(*skip)) {
       ++skip;
     }
-    if (*skip == ')') {
+    if ((skip != end) && *skip == ')') {
       c = skip + 1;
     } else {
       break;
@@ -314,63 +309,60 @@
 */
 #define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0
 
-int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags)
+bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
+                                                   int flags)
 {
   /* The empty string needs quotes.  */
-  if (!*in) {
-    return 1;
+  if (in.empty()) {
+    return true;
   }
 
   /* Scan the string for characters that require quoting.  */
-  {
-    const char* c;
-    for (c = in; *c; ++c) {
-      /* Look for $(MAKEVAR) syntax if requested.  */
-      if (flags & Shell_Flag_AllowMakeVariables) {
+  for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+       cit != cend; ++cit) {
+    /* Look for $(MAKEVAR) syntax if requested.  */
+    if (flags & Shell_Flag_AllowMakeVariables) {
 #if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES
-        const char* skip = Shell__SkipMakeVariables(c);
-        if (skip != c) {
-          /* We need to quote make variable references to preserve the
-             string with contents substituted in its place.  */
-          return 1;
-        }
+      cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+      if (skip != cit) {
+        /* We need to quote make variable references to preserve the
+           string with contents substituted in its place.  */
+        return true;
+      }
 #else
-        /* Skip over the make variable references if any are present.  */
-        c = Shell__SkipMakeVariables(c);
+      /* Skip over the make variable references if any are present.  */
+      cit = Shell__SkipMakeVariables(cit, cend);
 
-        /* Stop if we have reached the end of the string.  */
-        if (!*c) {
-          break;
-        }
+      /* Stop if we have reached the end of the string.  */
+      if (cit == cend) {
+        break;
+      }
 #endif
-      }
+    }
 
-      /* Check whether this character needs quotes.  */
-      if (Shell__CharNeedsQuotes(*c, flags)) {
-        return 1;
-      }
+    /* Check whether this character needs quotes.  */
+    if (Shell__CharNeedsQuotes(*cit, flags)) {
+      return true;
     }
   }
 
   /* On Windows some single character arguments need quotes.  */
-  if (flags & Shell_Flag_IsUnix && *in && !*(in + 1)) {
-    char c = *in;
+  if (flags & Shell_Flag_IsUnix && in.size() == 1) {
+    char c = in[0];
     if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) {
-      return 1;
+      return true;
     }
   }
 
-  return 0;
+  return false;
 }
 
-std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
+std::string cmOutputConverter::Shell__GetArgument(cm::string_view in,
+                                                  int flags)
 {
   /* Output will be at least as long as input string.  */
   std::string out;
-  out.reserve(strlen(in));
-
-  /* String iterator.  */
-  const char* c;
+  out.reserve(in.size());
 
   /* Keep track of how many backslashes have been encountered in a row.  */
   int windows_backslashes = 0;
@@ -390,14 +382,15 @@
   }
 
   /* Scan the string for characters that require escaping or quoting.  */
-  for (c = in; *c; ++c) {
+  for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+       cit != cend; ++cit) {
     /* Look for $(MAKEVAR) syntax if requested.  */
     if (flags & Shell_Flag_AllowMakeVariables) {
-      const char* skip = Shell__SkipMakeVariables(c);
-      if (skip != c) {
+      cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+      if (skip != cit) {
         /* Copy to the end of the make variable references.  */
-        while (c != skip) {
-          out += *c++;
+        while (cit != skip) {
+          out += *cit++;
         }
 
         /* The make variable reference eliminates any escaping needed
@@ -405,7 +398,7 @@
         windows_backslashes = 0;
 
         /* Stop if we have reached the end of the string.  */
-        if (!*c) {
+        if (cit == cend) {
           break;
         }
       }
@@ -415,7 +408,7 @@
     if (flags & Shell_Flag_IsUnix) {
       /* On Unix a few special characters need escaping even inside a
          quoted argument.  */
-      if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
+      if (*cit == '\\' || *cit == '"' || *cit == '`' || *cit == '$') {
         /* This character needs a backslash to escape it.  */
         out += '\\';
       }
@@ -423,10 +416,10 @@
       /* On Windows the built-in command shell echo never needs escaping.  */
     } else {
       /* On Windows only backslashes and double-quotes need escaping.  */
-      if (*c == '\\') {
+      if (*cit == '\\') {
         /* Found a backslash.  It may need to be escaped later.  */
         ++windows_backslashes;
-      } else if (*c == '"') {
+      } else if (*cit == '"') {
         /* Found a double-quote.  Escape all immediately preceding
            backslashes.  */
         while (windows_backslashes > 0) {
@@ -444,7 +437,7 @@
     }
 
     /* Check whether this character needs escaping for a make tool.  */
-    if (*c == '$') {
+    if (*cit == '$') {
       if (flags & Shell_Flag_Make) {
         /* In Makefiles a dollar is written $$.  The make tool will
            replace it with just $ before passing it to the shell.  */
@@ -461,7 +454,7 @@
         /* Otherwise a dollar is written just $. */
         out += '$';
       }
-    } else if (*c == '#') {
+    } else if (*cit == '#') {
       if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
         /* In Watcom WMake makefiles a pound is written $#.  The make
            tool will replace it with just # before passing it to the
@@ -471,7 +464,7 @@
         /* Otherwise a pound is written just #. */
         out += '#';
       }
-    } else if (*c == '%') {
+    } else if (*cit == '%') {
       if ((flags & Shell_Flag_VSIDE) ||
           ((flags & Shell_Flag_Make) &&
            ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
@@ -481,7 +474,7 @@
         /* Otherwise a percent is written just %. */
         out += '%';
       }
-    } else if (*c == ';') {
+    } else if (*cit == ';') {
       if (flags & Shell_Flag_VSIDE) {
         /* In a VS IDE a semicolon is written ";".  If this is written
            in an un-quoted argument it starts a quoted segment,
@@ -495,7 +488,7 @@
       }
     } else {
       /* Store this character.  */
-      out += *c;
+      out += *cit;
     }
   }
 
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index deca767..671efe7 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -5,9 +5,10 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
-
 #include "cmStateSnapshot.h"
+#include "cm_string_view.hxx"
+
+#include <string>
 
 class cmState;
 
@@ -22,10 +23,9 @@
     WATCOMQUOTE,
     RESPONSE
   };
-  std::string ConvertToOutputFormat(const std::string& source,
+  std::string ConvertToOutputFormat(cm::string_view source,
                                     OutputFormat output) const;
-  std::string ConvertDirectorySeparatorsForShell(
-    const std::string& source) const;
+  std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const;
 
   //! for existing files convert to output path and short path if spaces
   std::string ConvertToOutputForExisting(const std::string& remote,
@@ -72,15 +72,15 @@
     Shell_Flag_IsUnix = (1 << 8)
   };
 
-  std::string EscapeForShell(const std::string& str, bool makeVars = false,
+  std::string EscapeForShell(cm::string_view str, bool makeVars = false,
                              bool forEcho = false,
                              bool useWatcomQuote = false) const;
 
-  static std::string EscapeForCMake(const std::string& str);
+  static std::string EscapeForCMake(cm::string_view str);
 
   /** Compute an escaped version of the given argument for use in a
       windows shell.  */
-  static std::string EscapeWindowsShellArgument(const char* arg,
+  static std::string EscapeWindowsShellArgument(cm::string_view arg,
                                                 int shell_flags);
 
   enum FortranFormat
@@ -89,15 +89,17 @@
     FortranFormatFixed,
     FortranFormatFree
   };
+  static FortranFormat GetFortranFormat(cm::string_view value);
   static FortranFormat GetFortranFormat(const char* value);
 
 private:
   cmState* GetState() const;
 
-  static int Shell__CharNeedsQuotes(char c, int flags);
-  static const char* Shell__SkipMakeVariables(const char* c);
-  static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
-  static std::string Shell__GetArgument(const char* in, int flags);
+  static bool Shell__CharNeedsQuotes(char c, int flags);
+  static cm::string_view::iterator Shell__SkipMakeVariables(
+    cm::string_view::iterator begin, cm::string_view::iterator end);
+  static bool Shell__ArgumentNeedsQuotes(cm::string_view in, int flags);
+  static std::string Shell__GetArgument(cm::string_view in, int flags);
 
 private:
   cmStateSnapshot StateSnapshot;
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index f3276ec..a66af5a 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -11,6 +11,7 @@
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h
index 09e622b..faffabd 100644
--- a/Source/cmOutputRequiredFilesCommand.h
+++ b/Source/cmOutputRequiredFilesCommand.h
@@ -10,6 +10,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmDependInformation;
@@ -18,7 +20,10 @@
 class cmOutputRequiredFilesCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmOutputRequiredFilesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmOutputRequiredFilesCommand>();
+  }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 5213432..04fa0fb 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -7,11 +7,11 @@
 #include <sstream>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmArgumentParser.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cm_string_view.hxx"
 
@@ -75,7 +75,7 @@
 
   for (auto const& iter : singleValArgs) {
     if (!iter.second.empty()) {
-      makefile.AddDefinition(prefix + iter.first, iter.second.c_str());
+      makefile.AddDefinition(prefix + iter.first, iter.second);
     } else {
       makefile.RemoveDefinition(prefix + iter.first);
     }
@@ -84,7 +84,7 @@
   for (auto const& iter : multiValArgs) {
     if (!iter.second.empty()) {
       makefile.AddDefinition(prefix + iter.first,
-                             JoinList(iter.second, parseFromArgV).c_str());
+                             JoinList(iter.second, parseFromArgV));
     } else {
       makefile.RemoveDefinition(prefix + iter.first);
     }
@@ -92,15 +92,14 @@
 
   if (!unparsed.empty()) {
     makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
-                           JoinList(unparsed, parseFromArgV).c_str());
+                           JoinList(unparsed, parseFromArgV));
   } else {
     makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
   }
 
   if (!keywordsMissingValues.empty()) {
-    makefile.AddDefinition(
-      prefix + "KEYWORDS_MISSING_VALUES",
-      cmJoin(cmMakeRange(keywordsMissingValues), ";").c_str());
+    makefile.AddDefinition(prefix + "KEYWORDS_MISSING_VALUES",
+                           cmJoin(cmMakeRange(keywordsMissingValues), ";"));
   } else {
     makefile.RemoveDefinition(prefix + "KEYWORDS_MISSING_VALUES");
   }
diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h
index b8ba61d..692ea64 100644
--- a/Source/cmParseArgumentsCommand.h
+++ b/Source/cmParseArgumentsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -21,7 +23,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmParseArgumentsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmParseArgumentsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index ec40136..51a61dc 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -1,10 +1,10 @@
 #include "cmPolicies.h"
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index b705119..92c80bb 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -279,7 +279,18 @@
   SELECT(POLICY, CMP0094,                                                     \
          "FindPython3,  FindPython2 and FindPyton use "                       \
          "LOCATION for lookup strategy.",                                     \
-         3, 15, 0, cmPolicies::WARN)
+         3, 15, 0, cmPolicies::WARN)                                          \
+  SELECT(POLICY, CMP0095,                                                     \
+         "RPATH entries are properly escaped in the intermediary CMake "      \
+         "install script.",                                                   \
+         3, 16, 0, cmPolicies::WARN)                                          \
+  SELECT(POLICY, CMP0096,                                                     \
+         "project() preserves leading zeros in version components.", 3, 16,   \
+         0, cmPolicies::WARN)                                                 \
+  SELECT(POLICY, CMP0097,                                                     \
+         "ExternalProject_Add with GIT_SUBMODULES \"\" initializes no "       \
+         "submodules.",                                                       \
+         3, 16, 0, cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
@@ -307,7 +318,8 @@
   F(CMP0073)                                                                  \
   F(CMP0076)                                                                  \
   F(CMP0081)                                                                  \
-  F(CMP0083)
+  F(CMP0083)                                                                  \
+  F(CMP0095)
 
 /** \class cmPolicies
  * \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 8615ecc..96d9843 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -3,15 +3,18 @@
 #include "cmProjectCommand.h"
 
 #include "cmsys/RegularExpression.hxx"
+#include <array>
+#include <cstdio>
 #include <functional>
+#include <limits>
 #include <sstream>
-#include <stdio.h>
+#include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -33,27 +36,21 @@
 
   this->Makefile->SetProjectName(projectName);
 
-  std::string bindir = projectName;
-  bindir += "_BINARY_DIR";
-  std::string srcdir = projectName;
-  srcdir += "_SOURCE_DIR";
-
   this->Makefile->AddCacheDefinition(
-    bindir, this->Makefile->GetCurrentBinaryDirectory().c_str(),
+    projectName + "_BINARY_DIR",
+    this->Makefile->GetCurrentBinaryDirectory().c_str(),
     "Value Computed by CMake", cmStateEnums::STATIC);
   this->Makefile->AddCacheDefinition(
-    srcdir, this->Makefile->GetCurrentSourceDirectory().c_str(),
+    projectName + "_SOURCE_DIR",
+    this->Makefile->GetCurrentSourceDirectory().c_str(),
     "Value Computed by CMake", cmStateEnums::STATIC);
 
-  bindir = "PROJECT_BINARY_DIR";
-  srcdir = "PROJECT_SOURCE_DIR";
+  this->Makefile->AddDefinition("PROJECT_BINARY_DIR",
+                                this->Makefile->GetCurrentBinaryDirectory());
+  this->Makefile->AddDefinition("PROJECT_SOURCE_DIR",
+                                this->Makefile->GetCurrentSourceDirectory());
 
-  this->Makefile->AddDefinition(
-    bindir, this->Makefile->GetCurrentBinaryDirectory().c_str());
-  this->Makefile->AddDefinition(
-    srcdir, this->Makefile->GetCurrentSourceDirectory().c_str());
-
-  this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str());
+  this->Makefile->AddDefinition("PROJECT_NAME", projectName);
 
   // Set the CMAKE_PROJECT_NAME variable to be the highest-level
   // project name in the tree. If there are two project commands
@@ -63,7 +60,7 @@
   // will work.
   if (!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") ||
       (this->Makefile->IsRootMakefile())) {
-    this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName.c_str());
+    this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName);
     this->Makefile->AddCacheDefinition(
       "CMAKE_PROJECT_NAME", projectName.c_str(), "Value Computed by CMake",
       cmStateEnums::STATIC);
@@ -205,7 +202,7 @@
     languages.emplace_back("NONE");
   }
 
-  cmPolicies::PolicyStatus cmp0048 =
+  cmPolicies::PolicyStatus const cmp0048 =
     this->Makefile->GetPolicyStatus(cmPolicies::CMP0048);
   if (haveVersion) {
     // Set project VERSION variables to given values
@@ -220,64 +217,87 @@
     cmsys::RegularExpression vx(
       R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)");
     if (!vx.find(version)) {
-      std::string e = "VERSION \"" + version + "\" format invalid.";
+      std::string e = R"(VERSION ")" + version + R"(" format invalid.)";
       this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
       cmSystemTools::SetFatalErrorOccured();
       return true;
     }
 
-    std::string vs;
-    const char* sep = "";
-    char vb[4][64];
-    unsigned int v[4] = { 0, 0, 0, 0 };
-    int vc =
-      sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1], &v[2], &v[3]);
-    for (int i = 0; i < 4; ++i) {
-      if (i < vc) {
-        sprintf(vb[i], "%u", v[i]);
-        vs += sep;
-        vs += vb[i];
-        sep = ".";
-      } else {
-        vb[i][0] = 0;
+    cmPolicies::PolicyStatus const cmp0096 =
+      this->Makefile->GetPolicyStatus(cmPolicies::CMP0096);
+
+    constexpr std::size_t MAX_VERSION_COMPONENTS = 4u;
+    std::string version_string;
+    std::array<std::string, MAX_VERSION_COMPONENTS> version_components;
+
+    if (cmp0096 == cmPolicies::OLD || cmp0096 == cmPolicies::WARN) {
+      char vb[MAX_VERSION_COMPONENTS][std::numeric_limits<unsigned>::digits10];
+      unsigned v[MAX_VERSION_COMPONENTS] = { 0, 0, 0, 0 };
+      const int vc = std::sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1],
+                                 &v[2], &v[3]);
+      for (auto i = 0u; i < MAX_VERSION_COMPONENTS; ++i) {
+        if (int(i) < vc) {
+          std::sprintf(vb[i], "%u", v[i]);
+          version_string += &"."[std::size_t(i == 0)];
+          version_string += vb[i];
+          version_components[i] = vb[i];
+        } else {
+          vb[i][0] = '\x00';
+        }
+      }
+    } else {
+      // The regex above verified that we have a .-separated string of
+      // non-negative integer components.  Keep the original string.
+      version_string = std::move(version);
+      // Split the integer components.
+      auto components = cmSystemTools::SplitString(version_string, '.');
+      for (auto i = 0u; i < components.size(); ++i) {
+        version_components[i] = std::move(components[i]);
       }
     }
 
     std::string vv;
     vv = projectName + "_VERSION";
-    this->Makefile->AddDefinition("PROJECT_VERSION", vs.c_str());
-    this->Makefile->AddDefinition(vv, vs.c_str());
+    this->Makefile->AddDefinition("PROJECT_VERSION", version_string);
+    this->Makefile->AddDefinition(vv, version_string);
     vv = projectName + "_VERSION_MAJOR";
-    this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", vb[0]);
-    this->Makefile->AddDefinition(vv, vb[0]);
+    this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR",
+                                  version_components[0]);
+    this->Makefile->AddDefinition(vv, version_components[0]);
     vv = projectName + "_VERSION_MINOR";
-    this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", vb[1]);
-    this->Makefile->AddDefinition(vv, vb[1]);
+    this->Makefile->AddDefinition("PROJECT_VERSION_MINOR",
+                                  version_components[1]);
+    this->Makefile->AddDefinition(vv, version_components[1]);
     vv = projectName + "_VERSION_PATCH";
-    this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", vb[2]);
-    this->Makefile->AddDefinition(vv, vb[2]);
+    this->Makefile->AddDefinition("PROJECT_VERSION_PATCH",
+                                  version_components[2]);
+    this->Makefile->AddDefinition(vv, version_components[2]);
     vv = projectName + "_VERSION_TWEAK";
-    this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]);
-    this->Makefile->AddDefinition(vv, vb[3]);
+    this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK",
+                                  version_components[3]);
+    this->Makefile->AddDefinition(vv, version_components[3]);
     // Also, try set top level variables
-    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION", vs.c_str());
-    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MAJOR", vb[0]);
-    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MINOR", vb[1]);
-    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_PATCH", vb[2]);
-    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_TWEAK", vb[3]);
+    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION", version_string.c_str());
+    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MAJOR",
+                            version_components[0].c_str());
+    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MINOR",
+                            version_components[1].c_str());
+    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_PATCH",
+                            version_components[2].c_str());
+    TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_TWEAK",
+                            version_components[3].c_str());
   } else if (cmp0048 != cmPolicies::OLD) {
     // Set project VERSION variables to empty
-    std::vector<std::string> vv;
-    vv.emplace_back("PROJECT_VERSION");
-    vv.emplace_back("PROJECT_VERSION_MAJOR");
-    vv.emplace_back("PROJECT_VERSION_MINOR");
-    vv.emplace_back("PROJECT_VERSION_PATCH");
-    vv.emplace_back("PROJECT_VERSION_TWEAK");
-    vv.push_back(projectName + "_VERSION");
-    vv.push_back(projectName + "_VERSION_MAJOR");
-    vv.push_back(projectName + "_VERSION_MINOR");
-    vv.push_back(projectName + "_VERSION_PATCH");
-    vv.push_back(projectName + "_VERSION_TWEAK");
+    std::vector<std::string> vv = { "PROJECT_VERSION",
+                                    "PROJECT_VERSION_MAJOR",
+                                    "PROJECT_VERSION_MINOR",
+                                    "PROJECT_VERSION_PATCH",
+                                    "PROJECT_VERSION_TWEAK",
+                                    projectName + "_VERSION",
+                                    projectName + "_VERSION_MAJOR",
+                                    projectName + "_VERSION_MINOR",
+                                    projectName + "_VERSION_PATCH",
+                                    projectName + "_VERSION_TWEAK" };
     if (this->Makefile->IsRootMakefile()) {
       vv.emplace_back("CMAKE_PROJECT_VERSION");
       vv.emplace_back("CMAKE_PROJECT_VERSION_MAJOR");
@@ -287,7 +307,7 @@
     }
     std::string vw;
     for (std::string const& i : vv) {
-      const char* v = this->Makefile->GetDefinition(i);
+      const char* const v = this->Makefile->GetDefinition(i);
       if (v && *v) {
         if (cmp0048 == cmPolicies::WARN) {
           if (!injectedProjectCommand) {
@@ -307,20 +327,17 @@
     }
   }
 
-  this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
-  this->Makefile->AddDefinition(projectName + "_DESCRIPTION",
-                                description.c_str());
+  this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description);
+  this->Makefile->AddDefinition(projectName + "_DESCRIPTION", description);
   TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str());
 
-  this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str());
-  this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL",
-                                homepage.c_str());
+  this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage);
+  this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL", homepage);
   TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str());
 
   if (languages.empty()) {
     // if no language is specified do c and c++
-    languages.emplace_back("C");
-    languages.emplace_back("CXX");
+    languages = { "C", "CXX" };
   }
   this->Makefile->EnableLanguage(languages, false);
 
@@ -337,7 +354,7 @@
 
 bool cmProjectCommand::IncludeByVariable(const std::string& variable)
 {
-  const char* include = this->Makefile->GetDefinition(variable);
+  const char* const include = this->Makefile->GetDefinition(variable);
   if (!include) {
     return true;
   }
diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h
index f1d03e7..8b9bcc8 100644
--- a/Source/cmProjectCommand.h
+++ b/Source/cmProjectCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -26,7 +28,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmProjectCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmProjectCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx
deleted file mode 100644
index 27f0ecd..0000000
--- a/Source/cmProperty.cxx
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmProperty.h"
-
-void cmProperty::Set(const char* value)
-{
-  this->Value = value;
-  this->ValueHasBeenSet = true;
-}
-
-void cmProperty::Append(const char* value, bool asString)
-{
-  if (!this->Value.empty() && *value && !asString) {
-    this->Value += ";";
-  }
-  this->Value += value;
-  this->ValueHasBeenSet = true;
-}
-
-const char* cmProperty::GetValue() const
-{
-  if (this->ValueHasBeenSet) {
-    return this->Value.c_str();
-  }
-  return nullptr;
-}
diff --git a/Source/cmProperty.h b/Source/cmProperty.h
index d11c5ef..80f131a 100644
--- a/Source/cmProperty.h
+++ b/Source/cmProperty.h
@@ -5,8 +5,6 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
-
 class cmProperty
 {
 public:
@@ -22,22 +20,6 @@
     CACHED_VARIABLE,
     INSTALL
   };
-
-  // set this property
-  void Set(const char* value);
-
-  // append to this property
-  void Append(const char* value, bool asString = false);
-
-  // get the value
-  const char* GetValue() const;
-
-  // construct with the value not set
-  cmProperty() { this->ValueHasBeenSet = false; }
-
-protected:
-  std::string Value;
-  bool ValueHasBeenSet;
 };
 
 #endif
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index 3f6d7c8..3ed4c05 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -3,40 +3,21 @@
 #include "cmPropertyMap.h"
 
 #include <algorithm>
-#include <assert.h>
 #include <utility>
 
-cmProperty* cmPropertyMap::GetOrCreateProperty(const std::string& name)
+void cmPropertyMap::Clear()
 {
-  cmPropertyMap::iterator it = this->find(name);
-  cmProperty* prop;
-  if (it == this->end()) {
-    prop = &(*this)[name];
-  } else {
-    prop = &(it->second);
-  }
-  return prop;
-}
-
-std::vector<std::string> cmPropertyMap::GetPropertyList() const
-{
-  std::vector<std::string> keyList;
-  for (auto const& i : *this) {
-    keyList.push_back(i.first);
-  }
-  std::sort(keyList.begin(), keyList.end());
-  return keyList;
+  Map_.clear();
 }
 
 void cmPropertyMap::SetProperty(const std::string& name, const char* value)
 {
   if (!value) {
-    this->erase(name);
+    Map_.erase(name);
     return;
   }
 
-  cmProperty* prop = this->GetOrCreateProperty(name);
-  prop->Set(value);
+  Map_[name] = value;
 }
 
 void cmPropertyMap::AppendProperty(const std::string& name, const char* value,
@@ -47,17 +28,53 @@
     return;
   }
 
-  cmProperty* prop = this->GetOrCreateProperty(name);
-  prop->Append(value, asString);
+  {
+    std::string& pVal = Map_[name];
+    if (!pVal.empty() && !asString) {
+      pVal += ';';
+    }
+    pVal += value;
+  }
+}
+
+void cmPropertyMap::RemoveProperty(const std::string& name)
+{
+  Map_.erase(name);
 }
 
 const char* cmPropertyMap::GetPropertyValue(const std::string& name) const
 {
-  assert(!name.empty());
-
-  cmPropertyMap::const_iterator it = this->find(name);
-  if (it == this->end()) {
-    return nullptr;
+  {
+    auto it = Map_.find(name);
+    if (it != Map_.end()) {
+      return it->second.c_str();
+    }
   }
-  return it->second.GetValue();
+  return nullptr;
+}
+
+std::vector<std::string> cmPropertyMap::GetKeys() const
+{
+  std::vector<std::string> keyList;
+  keyList.reserve(Map_.size());
+  for (auto const& item : Map_) {
+    keyList.push_back(item.first);
+  }
+  std::sort(keyList.begin(), keyList.end());
+  return keyList;
+}
+
+std::vector<std::pair<std::string, std::string>> cmPropertyMap::GetList() const
+{
+  typedef std::pair<std::string, std::string> StringPair;
+  std::vector<StringPair> kvList;
+  kvList.reserve(Map_.size());
+  for (auto const& item : Map_) {
+    kvList.emplace_back(item.first, item.second);
+  }
+  std::sort(kvList.begin(), kvList.end(),
+            [](StringPair const& a, StringPair const& b) {
+              return a.first < b.first;
+            });
+  return kvList;
 }
diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h
index 5a05150..9aed349 100644
--- a/Source/cmPropertyMap.h
+++ b/Source/cmPropertyMap.h
@@ -5,25 +5,47 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include "cmProperty.h"
-
-#include <map>
 #include <string>
+#include <unordered_map>
+#include <utility>
 #include <vector>
 
-class cmPropertyMap : public std::map<std::string, cmProperty>
+/** \class cmPropertyMap
+ * \brief String property map.
+ */
+class cmPropertyMap
 {
 public:
-  cmProperty* GetOrCreateProperty(const std::string& name);
+  // -- General
 
-  std::vector<std::string> GetPropertyList() const;
+  //! Clear property list
+  void Clear();
 
+  // -- Properties
+
+  //! Set the property value
   void SetProperty(const std::string& name, const char* value);
 
+  //! Append to the property value
   void AppendProperty(const std::string& name, const char* value,
                       bool asString = false);
 
+  //! Get the property value
   const char* GetPropertyValue(const std::string& name) const;
+
+  //! Remove the property @a name from the map
+  void RemoveProperty(const std::string& name);
+
+  // -- Lists
+
+  //! Get a sorted list of property keys
+  std::vector<std::string> GetKeys() const;
+
+  //! Get a sorted by key list of property key,value pairs
+  std::vector<std::pair<std::string, std::string>> GetList() const;
+
+private:
+  std::unordered_map<std::string, std::string> Map_;
 };
 
 #endif
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index 9a764c6..f5852a9 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -89,6 +89,6 @@
   }
 
   // Store the final list of source files.
-  this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
+  this->Makefile->AddDefinition(sourceList, sourceListValue);
   return true;
 }
diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h
index c1dcd54..88a2210 100644
--- a/Source/cmQTWrapCPPCommand.h
+++ b/Source/cmQTWrapCPPCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmQTWrapCPPCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmQTWrapCPPCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index 2223e2d..361d7b3 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -132,7 +132,7 @@
   }
 
   // Store the final list of source files and headers.
-  this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
-  this->Makefile->AddDefinition(headerList, headerListValue.c_str());
+  this->Makefile->AddDefinition(sourceList, sourceListValue);
+  this->Makefile->AddDefinition(headerList, headerListValue);
   return true;
 }
diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h
index 15cab40..6a346d4 100644
--- a/Source/cmQTWrapUICommand.h
+++ b/Source/cmQTWrapUICommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmQTWrapUICommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmQTWrapUICommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 3683edd..712e22c 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -5,6 +5,7 @@
 #include "cmAlgorithms.h"
 #include "cmDuration.h"
 #include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmsys/FStream.hxx"
 #include "cmsys/RegularExpression.hxx"
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 9c52129..619fff1 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -5,7 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index ef8a56b..f172b77 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -4,7 +4,6 @@
 #include "cmQtAutoGen.h"
 #include "cmQtAutoGenInitializer.h"
 
-#include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmDuration.h"
 #include "cmGeneratorTarget.h"
@@ -17,9 +16,10 @@
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
-#include <memory>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 cmQtAutoGenGlobalInitializer::Keywords::Keywords()
   : AUTOMOC("AUTOMOC")
   , AUTOUIC("AUTOUIC")
diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h
index d56153a..d7f4cc6 100644
--- a/Source/cmQtAutoGenGlobalInitializer.h
+++ b/Source/cmQtAutoGenGlobalInitializer.h
@@ -8,7 +8,7 @@
 #include "cmQtAutoGen.h"
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <unordered_map>
 #include <vector>
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 9985f93..da6094d 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -4,7 +4,6 @@
 #include "cmQtAutoGen.h"
 #include "cmQtAutoGenGlobalInitializer.h"
 
-#include "cmAlgorithms.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
 #include "cmFilePathChecksum.h"
@@ -23,6 +22,7 @@
 #include "cmSourceGroup.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmake.h"
@@ -38,6 +38,8 @@
 #include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 static std::size_t GetParallelCPUCount()
 {
   static std::size_t count = 0;
@@ -620,6 +622,7 @@
 bool cmQtAutoGenInitializer::InitScanFiles()
 {
   cmMakefile* makefile = this->Target->Target->GetMakefile();
+  cmake const* cm = makefile->GetCMakeInstance();
   auto const& kw = this->GlobalInitializer->kw();
 
   auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,
@@ -665,25 +668,21 @@
       if (!pathError.empty() || fullPath.empty()) {
         continue;
       }
-      std::string const& ext = sf->GetExtension();
+      std::string const& extLower =
+        cmSystemTools::LowerCase(sf->GetExtension());
 
       // Register files that will be scanned by moc or uic
       if (this->MocOrUicEnabled()) {
-        switch (cmSystemTools::GetFileFormat(ext)) {
-          case cmSystemTools::HEADER_FILE_FORMAT:
-            addMUFile(makeMUFile(sf, fullPath, true), true);
-            break;
-          case cmSystemTools::CXX_FILE_FORMAT:
-            addMUFile(makeMUFile(sf, fullPath, true), false);
-            break;
-          default:
-            break;
+        if (cm->IsHeaderExtension(extLower)) {
+          addMUFile(makeMUFile(sf, fullPath, true), true);
+        } else if (cm->IsSourceExtension(extLower)) {
+          addMUFile(makeMUFile(sf, fullPath, true), false);
         }
       }
 
       // Register rcc enabled files
       if (this->Rcc.Enabled) {
-        if ((ext == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
+        if ((extLower == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
             !sf->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
           // Register qrc file
           Qrc qrc;
@@ -715,7 +714,7 @@
     extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2);
     // Header search suffixes and extensions
     std::array<std::string, 2> const suffixes{ { "", "_p" } };
-    auto const& exts = makefile->GetCMakeInstance()->GetHeaderExtensions();
+    auto const& exts = cm->GetHeaderExtensions();
     // Scan through sources
     for (auto const& pair : this->AutogenTarget.Sources) {
       MUFile const& muf = *pair.second;
@@ -784,10 +783,10 @@
       if (!pathError.empty() || fullPath.empty()) {
         continue;
       }
-      std::string const& ext = sf->GetExtension();
+      std::string const& extLower =
+        cmSystemTools::LowerCase(sf->GetExtension());
 
-      auto const fileFormat = cmSystemTools::GetFileFormat(ext);
-      if (fileFormat == cmSystemTools::HEADER_FILE_FORMAT) {
+      if (cm->IsHeaderExtension(extLower)) {
         if (this->AutogenTarget.Headers.find(sf) ==
             this->AutogenTarget.Headers.end()) {
           auto muf = makeMUFile(sf, fullPath, false);
@@ -795,7 +794,7 @@
             this->AutogenTarget.Headers.emplace(sf, std::move(muf));
           }
         }
-      } else if (fileFormat == cmSystemTools::CXX_FILE_FORMAT) {
+      } else if (cm->IsSourceExtension(extLower)) {
         if (this->AutogenTarget.Sources.find(sf) ==
             this->AutogenTarget.Sources.end()) {
           auto muf = makeMUFile(sf, fullPath, false);
@@ -803,7 +802,7 @@
             this->AutogenTarget.Sources.emplace(sf, std::move(muf));
           }
         }
-      } else if (this->Uic.Enabled && (ext == kw.ui)) {
+      } else if (this->Uic.Enabled && (extLower == kw.ui)) {
         // .ui file
         std::string realPath = cmSystemTools::GetRealPath(fullPath);
         bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index aa073d1..eb0d35e 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -8,7 +8,7 @@
 #include "cmQtAutoGen.h"
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <ostream>
 #include <set>
 #include <string>
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index e1c435b..2516d84 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -5,7 +5,8 @@
 
 #include "cmsys/FStream.hxx"
 
-#include "cmAlgorithms.h"
+#include "cm_memory.hxx"
+
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmState.h"
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 889f47d..0801c24 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -5,16 +5,18 @@
 #include <algorithm>
 #include <array>
 #include <list>
-#include <memory>
 #include <set>
 #include <sstream>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
 #include "cmGeneratedFileStream.h"
 #include "cmMakefile.h"
 #include "cmQtAutoGen.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 #include "cmsys/FStream.hxx"
@@ -1892,7 +1894,7 @@
           std::list<std::string>::iterator it = includes.begin();
           while (it != includes.end()) {
             std::string const& path = *it;
-            if (cmSystemTools::StringStartsWith(path, ppath->c_str())) {
+            if (cmHasPrefix(path, *ppath)) {
               MocConst_.IncludePaths.push_back(path);
               it = includes.erase(it);
             } else {
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 8061c13..dc18328 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -14,7 +14,7 @@
 #include <atomic>
 #include <cstddef>
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_map>
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index 20885df..59f632d 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -11,6 +11,7 @@
 #include "cmFileLockResult.h"
 #include "cmMakefile.h"
 #include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 // -- Class methods
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 2064275..a329f7d 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -4,6 +4,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 
diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx
index a64ad8c..d0ee4d4 100644
--- a/Source/cmRemoveCommand.cxx
+++ b/Source/cmRemoveCommand.cxx
@@ -52,7 +52,7 @@
   }
 
   // add the definition
-  this->Makefile->AddDefinition(variable, value.c_str());
+  this->Makefile->AddDefinition(variable, value);
 
   return true;
 }
diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h
index 7b11849..088d8ad 100644
--- a/Source/cmRemoveCommand.h
+++ b/Source/cmRemoveCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmRemoveCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmRemoveCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmRemoveDefinitionsCommand.h b/Source/cmRemoveDefinitionsCommand.h
index a5cb204..85d01d4 100644
--- a/Source/cmRemoveDefinitionsCommand.h
+++ b/Source/cmRemoveDefinitionsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmRemoveDefinitionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmRemoveDefinitionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx
index ceea8b4..5905669 100644
--- a/Source/cmReturnCommand.cxx
+++ b/Source/cmReturnCommand.cxx
@@ -5,8 +5,8 @@
 #include "cmExecutionStatus.h"
 
 // cmReturnCommand
-bool cmReturnCommand::InitialPass(std::vector<std::string> const&,
-                                  cmExecutionStatus& status)
+bool cmReturnCommand(std::vector<std::string> const&,
+                     cmExecutionStatus& status)
 {
   status.SetReturnInvoked();
   return true;
diff --git a/Source/cmReturnCommand.h b/Source/cmReturnCommand.h
index ef39614..2404a36 100644
--- a/Source/cmReturnCommand.h
+++ b/Source/cmReturnCommand.h
@@ -8,29 +8,10 @@
 #include <string>
 #include <vector>
 
-#include "cmCommand.h"
-
 class cmExecutionStatus;
 
-/** \class cmReturnCommand
- * \brief Return from a directory or function
- *
- * cmReturnCommand returns from a directory or function
- */
-class cmReturnCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  cmCommand* Clone() override { return new cmReturnCommand; }
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const& args,
-                   cmExecutionStatus& status) override;
-};
+/// Return from a directory or function
+bool cmReturnCommand(std::vector<std::string> const& args,
+                     cmExecutionStatus& status);
 
 #endif
diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx
new file mode 100644
index 0000000..45aff69
--- /dev/null
+++ b/Source/cmRuntimeDependencyArchive.cxx
@@ -0,0 +1,376 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmRuntimeDependencyArchive.h"
+
+#include "cmBinUtilsLinuxELFLinker.h"
+#include "cmBinUtilsMacOSMachOLinker.h"
+#include "cmBinUtilsWindowsPELinker.h"
+#include "cmCommand.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+
+#if defined(_WIN32)
+#  include "cmGlobalGenerator.h"
+#  ifdef CMAKE_BUILD_WITH_CMAKE
+#    include "cmGlobalVisualStudioVersionedGenerator.h"
+#  endif
+#  include "cmVSSetupHelper.h"
+#  include "cmsys/Glob.hxx"
+#endif
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cm_memory.hxx"
+
+#if defined(_WIN32)
+static void AddVisualStudioPath(std::vector<std::string>& paths,
+                                const std::string& prefix,
+                                unsigned int version, cmGlobalGenerator* gg)
+{
+  // If generating for the VS IDE, use the same instance.
+  std::string vsloc;
+  bool found = false;
+#  ifdef CMAKE_BUILD_WITH_CMAKE
+  if (gg->GetName().find(prefix) == 0) {
+    cmGlobalVisualStudioVersionedGenerator* vsgen =
+      static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
+    if (vsgen->GetVSInstance(vsloc)) {
+      found = true;
+    }
+  }
+#  endif
+
+  // Otherwise, find a VS instance ourselves.
+  if (!found) {
+    cmVSSetupAPIHelper vsSetupAPIHelper(version);
+    if (vsSetupAPIHelper.GetVSInstanceInfo(vsloc)) {
+      cmSystemTools::ConvertToUnixSlashes(vsloc);
+      found = true;
+    }
+  }
+
+  if (found) {
+    cmsys::Glob glob;
+    glob.SetListDirs(true);
+    glob.FindFiles(vsloc + "/VC/Tools/MSVC/*");
+    for (auto const& vcdir : glob.GetFiles()) {
+      paths.push_back(vcdir + "/bin/Hostx64/x64");
+      paths.push_back(vcdir + "/bin/Hostx86/x64");
+      paths.push_back(vcdir + "/bin/Hostx64/x86");
+      paths.push_back(vcdir + "/bin/Hostx86/x86");
+    }
+  }
+}
+
+static void AddRegistryPath(std::vector<std::string>& paths,
+                            const std::string& path, cmMakefile* mf)
+{
+  // We should view the registry as the target application would view
+  // it.
+  cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
+  cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
+  if (mf->PlatformIs64Bit()) {
+    view = cmSystemTools::KeyWOW64_64;
+    other_view = cmSystemTools::KeyWOW64_32;
+  }
+
+  // Expand using the view of the target application.
+  std::string expanded = path;
+  cmSystemTools::ExpandRegistryValues(expanded, view);
+  cmSystemTools::GlobDirs(expanded, paths);
+
+  // Executables can be either 32-bit or 64-bit, so expand using the
+  // alternative view.
+  expanded = path;
+  cmSystemTools::ExpandRegistryValues(expanded, other_view);
+  cmSystemTools::GlobDirs(expanded, paths);
+}
+
+static void AddEnvPath(std::vector<std::string>& paths, const std::string& var,
+                       const std::string& suffix)
+{
+  std::string value;
+  if (cmSystemTools::GetEnv(var, value)) {
+    paths.push_back(value + suffix);
+  }
+}
+#endif
+
+static cmsys::RegularExpression TransformCompile(const std::string& str)
+{
+  return cmsys::RegularExpression(str);
+}
+
+cmRuntimeDependencyArchive::cmRuntimeDependencyArchive(
+  cmCommand* command, std::vector<std::string> searchDirectories,
+  std::string bundleExecutable,
+  const std::vector<std::string>& preIncludeRegexes,
+  const std::vector<std::string>& preExcludeRegexes,
+  const std::vector<std::string>& postIncludeRegexes,
+  const std::vector<std::string>& postExcludeRegexes)
+  : Command(command)
+  , SearchDirectories(std::move(searchDirectories))
+  , BundleExecutable(std::move(bundleExecutable))
+  , PreIncludeRegexes(preIncludeRegexes.size())
+  , PreExcludeRegexes(preExcludeRegexes.size())
+  , PostIncludeRegexes(postIncludeRegexes.size())
+  , PostExcludeRegexes(postExcludeRegexes.size())
+{
+  std::transform(preIncludeRegexes.begin(), preIncludeRegexes.end(),
+                 this->PreIncludeRegexes.begin(), TransformCompile);
+  std::transform(preExcludeRegexes.begin(), preExcludeRegexes.end(),
+                 this->PreExcludeRegexes.begin(), TransformCompile);
+  std::transform(postIncludeRegexes.begin(), postIncludeRegexes.end(),
+                 this->PostIncludeRegexes.begin(), TransformCompile);
+  std::transform(postExcludeRegexes.begin(), postExcludeRegexes.end(),
+                 this->PostExcludeRegexes.begin(), TransformCompile);
+}
+
+bool cmRuntimeDependencyArchive::Prepare()
+{
+  std::string platform = this->GetMakefile()->GetSafeDefinition(
+    "CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM");
+  if (platform.empty()) {
+    std::string systemName =
+      this->GetMakefile()->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+    if (systemName == "Windows") {
+      platform = "windows+pe";
+    } else if (systemName == "Darwin") {
+      platform = "macos+macho";
+    } else if (systemName == "Linux") {
+      platform = "linux+elf";
+    }
+  }
+  if (platform == "linux+elf") {
+    this->Linker = cm::make_unique<cmBinUtilsLinuxELFLinker>(this);
+  } else if (platform == "windows+pe") {
+    this->Linker = cm::make_unique<cmBinUtilsWindowsPELinker>(this);
+  } else if (platform == "macos+macho") {
+    this->Linker = cm::make_unique<cmBinUtilsMacOSMachOLinker>(this);
+  } else {
+    std::ostringstream e;
+    e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM: "
+      << platform;
+    this->SetError(e.str());
+    return false;
+  }
+
+  return this->Linker->Prepare();
+}
+
+bool cmRuntimeDependencyArchive::GetRuntimeDependencies(
+  const std::vector<std::string>& executables,
+  const std::vector<std::string>& libraries,
+  const std::vector<std::string>& modules)
+{
+  for (auto const& exe : executables) {
+    if (!this->Linker->ScanDependencies(exe, cmStateEnums::EXECUTABLE)) {
+      return false;
+    }
+  }
+  for (auto const& lib : libraries) {
+    if (!this->Linker->ScanDependencies(lib, cmStateEnums::SHARED_LIBRARY)) {
+      return false;
+    }
+  }
+  for (auto const& mod : modules) {
+    if (!this->Linker->ScanDependencies(mod, cmStateEnums::MODULE_LIBRARY)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void cmRuntimeDependencyArchive::SetError(const std::string& e)
+{
+  this->Command->SetError(e);
+}
+
+std::string cmRuntimeDependencyArchive::GetBundleExecutable()
+{
+  return this->BundleExecutable;
+}
+
+const std::vector<std::string>&
+cmRuntimeDependencyArchive::GetSearchDirectories()
+{
+  return this->SearchDirectories;
+}
+
+std::string cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool()
+{
+  return this->GetMakefile()->GetSafeDefinition(
+    "CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL");
+}
+
+bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
+  const std::string& search, std::vector<std::string>& command)
+{
+  // First see if it was supplied by the user
+  std::string toolCommand = this->GetMakefile()->GetSafeDefinition(
+    "CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND");
+  if (!toolCommand.empty()) {
+    cmSystemTools::ExpandListArgument(toolCommand, command);
+    return true;
+  }
+
+  // Now go searching for it
+  std::vector<std::string> paths;
+#ifdef _WIN32
+  cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator();
+
+  // Add newer Visual Studio paths
+  AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg);
+  AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg);
+
+  // Add older Visual Studio paths
+  AddRegistryPath(
+    paths,
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0;InstallDir]/"
+    "../../VC/bin",
+    this->GetMakefile());
+  AddEnvPath(paths, "VS140COMNTOOLS", "/../../VC/bin");
+  paths.push_back(
+    "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin");
+  AddRegistryPath(
+    paths,
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0;InstallDir]/"
+    "../../VC/bin",
+    this->GetMakefile());
+  AddEnvPath(paths, "VS120COMNTOOLS", "/../../VC/bin");
+  paths.push_back(
+    "C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin");
+  AddRegistryPath(
+    paths,
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0;InstallDir]/"
+    "../../VC/bin",
+    this->GetMakefile());
+  AddEnvPath(paths, "VS110COMNTOOLS", "/../../VC/bin");
+  paths.push_back(
+    "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin");
+  AddRegistryPath(
+    paths,
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0;InstallDir]/"
+    "../../VC/bin",
+    this->GetMakefile());
+  AddEnvPath(paths, "VS100COMNTOOLS", "/../../VC/bin");
+  paths.push_back(
+    "C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin");
+  AddRegistryPath(
+    paths,
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]/"
+    "../../VC/bin",
+    this->GetMakefile());
+  AddEnvPath(paths, "VS90COMNTOOLS", "/../../VC/bin");
+  paths.push_back("C:/Program Files/Microsoft Visual Studio 9.0/VC/bin");
+  paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin");
+  AddRegistryPath(
+    paths,
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]/"
+    "../../VC/bin",
+    this->GetMakefile());
+  AddEnvPath(paths, "VS80COMNTOOLS", "/../../VC/bin");
+  paths.push_back("C:/Program Files/Microsoft Visual Studio 8/VC/BIN");
+  paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN");
+  AddRegistryPath(
+    paths,
+    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1;InstallDir]/"
+    "../../VC7/bin",
+    this->GetMakefile());
+  AddEnvPath(paths, "VS71COMNTOOLS", "/../../VC7/bin");
+  paths.push_back(
+    "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN");
+  paths.push_back(
+    "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN");
+#endif
+
+  std::string program = cmSystemTools::FindProgram(search, paths);
+  if (!program.empty()) {
+    command = { program };
+    return true;
+  }
+
+  // Couldn't find it
+  return false;
+}
+
+bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name)
+{
+  cmsys::RegularExpressionMatch match;
+
+  for (auto const& regex : this->PreIncludeRegexes) {
+    if (regex.find(name.c_str(), match)) {
+      return false;
+    }
+  }
+
+  for (auto const& regex : this->PreExcludeRegexes) {
+    if (regex.find(name.c_str(), match)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name)
+{
+  cmsys::RegularExpressionMatch match;
+
+  for (auto const& regex : this->PostIncludeRegexes) {
+    if (regex.find(name.c_str(), match)) {
+      return false;
+    }
+  }
+
+  for (auto const& regex : this->PostExcludeRegexes) {
+    if (regex.find(name.c_str(), match)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name,
+                                                 const std::string& path,
+                                                 bool& unique)
+{
+  auto it = this->ResolvedPaths.emplace(name, std::set<std::string>{}).first;
+  unique = true;
+  for (auto const& other : it->second) {
+    if (cmSystemTools::SameFile(path, other)) {
+      unique = false;
+      break;
+    }
+  }
+  it->second.insert(path);
+}
+
+void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name)
+{
+  this->UnresolvedPaths.insert(name);
+}
+
+cmMakefile* cmRuntimeDependencyArchive::GetMakefile()
+{
+  return this->Command->GetMakefile();
+}
+
+const std::map<std::string, std::set<std::string>>&
+cmRuntimeDependencyArchive::GetResolvedPaths()
+{
+  return this->ResolvedPaths;
+}
+
+const std::set<std::string>& cmRuntimeDependencyArchive::GetUnresolvedPaths()
+{
+  return this->UnresolvedPaths;
+}
diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h
new file mode 100644
index 0000000..67efec7
--- /dev/null
+++ b/Source/cmRuntimeDependencyArchive.h
@@ -0,0 +1,70 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmRuntimeDependencyArchive_h
+#define cmRuntimeDependencyArchive_h
+
+#include "cmBinUtilsLinker.h"
+
+#include "cmsys/RegularExpression.hxx"
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmCommand;
+class cmMakefile;
+
+class cmRuntimeDependencyArchive
+{
+public:
+  explicit cmRuntimeDependencyArchive(
+    cmCommand* command, std::vector<std::string> searchDirectories,
+    std::string bundleExecutable,
+    const std::vector<std::string>& preIncludeRegexes,
+    const std::vector<std::string>& preExcludeRegexes,
+    const std::vector<std::string>& postIncludeRegexes,
+    const std::vector<std::string>& postExcludeRegexes);
+  bool Prepare();
+  bool GetRuntimeDependencies(const std::vector<std::string>& executables,
+                              const std::vector<std::string>& libraries,
+                              const std::vector<std::string>& modules);
+
+  void SetError(const std::string& e);
+
+  std::string GetBundleExecutable();
+  const std::vector<std::string>& GetSearchDirectories();
+  std::string GetGetRuntimeDependenciesTool();
+  bool GetGetRuntimeDependenciesCommand(const std::string& search,
+                                        std::vector<std::string>& command);
+  bool IsPreExcluded(const std::string& name);
+  bool IsPostExcluded(const std::string& name);
+
+  void AddResolvedPath(const std::string& name, const std::string& path,
+                       bool& unique);
+  void AddUnresolvedPath(const std::string& name);
+
+  cmMakefile* GetMakefile();
+  const std::map<std::string, std::set<std::string>>& GetResolvedPaths();
+  const std::set<std::string>& GetUnresolvedPaths();
+
+private:
+  cmCommand* Command;
+  std::unique_ptr<cmBinUtilsLinker> Linker;
+
+  std::string GetRuntimeDependenciesTool;
+  std::vector<std::string> GetRuntimeDependenciesCommand;
+
+  std::vector<std::string> SearchDirectories;
+  std::string BundleExecutable;
+  std::vector<cmsys::RegularExpression> PreIncludeRegexes;
+  std::vector<cmsys::RegularExpression> PreExcludeRegexes;
+  std::vector<cmsys::RegularExpression> PostIncludeRegexes;
+  std::vector<cmsys::RegularExpression> PostExcludeRegexes;
+  std::map<std::string, std::set<std::string>> ResolvedPaths;
+  std::set<std::string> UnresolvedPaths;
+};
+
+#endif // cmRuntimeDependencyArchive_h
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index f98984e..879cc95 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -6,9 +6,9 @@
 #include <cassert>
 #include <utility>
 
-#include "cmAlgorithms.h"
 #include "cmFindCommon.h"
 #include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx
index 28cbdc0..ab4a0c7 100644
--- a/Source/cmSeparateArgumentsCommand.cxx
+++ b/Source/cmSeparateArgumentsCommand.cxx
@@ -69,7 +69,7 @@
     if (const char* def = this->Makefile->GetDefinition(var)) {
       std::string value = def;
       std::replace(value.begin(), value.end(), ' ', ';');
-      this->Makefile->AddDefinition(var, value.c_str());
+      this->Makefile->AddDefinition(var, value);
     }
   } else {
     // Parse the command line.
@@ -97,7 +97,7 @@
         value += si;
       }
     }
-    this->Makefile->AddDefinition(var, value.c_str());
+    this->Makefile->AddDefinition(var, value);
   }
 
   return true;
diff --git a/Source/cmSeparateArgumentsCommand.h b/Source/cmSeparateArgumentsCommand.h
index 988ad23..76e2002 100644
--- a/Source/cmSeparateArgumentsCommand.h
+++ b/Source/cmSeparateArgumentsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmSeparateArgumentsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSeparateArgumentsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index 1903fd9..9df1883 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmServer.h"
 
-#include "cmAlgorithms.h"
 #include "cmConnection.h"
 #include "cmFileMonitor.h"
 #include "cmJsonObjectDictionary.h"
@@ -18,10 +17,11 @@
 #include <cassert>
 #include <cstdint>
 #include <iostream>
-#include <memory>
 #include <mutex>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 void on_signal(uv_signal_t* signal, int signum)
 {
   auto conn = static_cast<cmServerBase*>(signal->data);
diff --git a/Source/cmServer.h b/Source/cmServer.h
index aba4924..ab2ad23 100644
--- a/Source/cmServer.h
+++ b/Source/cmServer.h
@@ -10,7 +10,7 @@
 
 #include "cmUVHandlePtr.h"
 
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index 558391f..8fcb710 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmServerProtocol.h"
 
-#include "cmAlgorithms.h"
 #include "cmExternalMakefileProjectGenerator.h"
 #include "cmFileMonitor.h"
 #include "cmGlobalGenerator.h"
@@ -19,11 +18,12 @@
 #include <algorithm>
 #include <cassert>
 #include <functional>
-#include <memory>
 #include <string>
 #include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 // Get rid of some windows macros:
 #undef max
 
@@ -378,8 +378,7 @@
   SendSignal(kFILE_CHANGE_SIGNAL, obj);
 }
 
-const cmServerResponse cmServerProtocol1::Process(
-  const cmServerRequest& request)
+cmServerResponse cmServerProtocol1::Process(const cmServerRequest& request)
 {
   assert(this->m_State >= STATE_ACTIVE);
 
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index 2f55a20..5da4344 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -80,7 +80,7 @@
 
   virtual std::pair<int, int> ProtocolVersion() const = 0;
   virtual bool IsExperimental() const = 0;
-  virtual const cmServerResponse Process(const cmServerRequest& request) = 0;
+  virtual cmServerResponse Process(const cmServerRequest& request) = 0;
 
   bool Activate(cmServer* server, const cmServerRequest& request,
                 std::string* errorMessage);
@@ -106,7 +106,7 @@
 public:
   std::pair<int, int> ProtocolVersion() const override;
   bool IsExperimental() const override;
-  const cmServerResponse Process(const cmServerRequest& request) override;
+  cmServerResponse Process(const cmServerRequest& request) override;
 
 private:
   bool DoActivate(const cmServerRequest& request,
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index 41555e8..1a12785 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -2,12 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSetCommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmRange.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -154,7 +154,7 @@
                                        type, force);
   } else {
     // add the definition
-    this->Makefile->AddDefinition(variable, value.c_str());
+    this->Makefile->AddDefinition(variable, value);
   }
   return true;
 }
diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h
index 76e3eae..1c5a435 100644
--- a/Source/cmSetCommand.h
+++ b/Source/cmSetCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmSetCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSetCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h
index 473347c..5416127 100644
--- a/Source/cmSetDirectoryPropertiesCommand.h
+++ b/Source/cmSetDirectoryPropertiesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -16,7 +18,10 @@
 class cmSetDirectoryPropertiesCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmSetDirectoryPropertiesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSetDirectoryPropertiesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h
index f1126bb..4051e48 100644
--- a/Source/cmSetPropertyCommand.h
+++ b/Source/cmSetPropertyCommand.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -22,7 +24,10 @@
 public:
   cmSetPropertyCommand();
 
-  cmCommand* Clone() override { return new cmSetPropertyCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSetPropertyCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSetSourceFilesPropertiesCommand.h b/Source/cmSetSourceFilesPropertiesCommand.h
index afb19f6..6fd6c41 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.h
+++ b/Source/cmSetSourceFilesPropertiesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -16,7 +18,10 @@
 class cmSetSourceFilesPropertiesCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmSetSourceFilesPropertiesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSetSourceFilesPropertiesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index c9755da..7e4606e 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -16,7 +18,10 @@
 class cmSetTargetPropertiesCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmSetTargetPropertiesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSetTargetPropertiesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSetTestsPropertiesCommand.h b/Source/cmSetTestsPropertiesCommand.h
index 84b2645..d73e95a 100644
--- a/Source/cmSetTestsPropertiesCommand.h
+++ b/Source/cmSetTestsPropertiesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -16,7 +18,10 @@
 class cmSetTestsPropertiesCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmSetTestsPropertiesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSetTestsPropertiesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSiteNameCommand.h b/Source/cmSiteNameCommand.h
index 2d8dc17..0190abb 100644
--- a/Source/cmSiteNameCommand.h
+++ b/Source/cmSiteNameCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmSiteNameCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSiteNameCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index acacba2..6e2e820 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -2,10 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSourceFileLocation.h"
 
-#include "cmAlgorithms.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -146,8 +146,7 @@
   // adding an extension.
   if (!(this->Name.size() > loc.Name.size() &&
         this->Name[loc.Name.size()] == '.' &&
-        cmHasLiteralPrefixImpl(this->Name.c_str(), loc.Name.c_str(),
-                               loc.Name.size()))) {
+        cmHasPrefix(this->Name, loc.Name))) {
     return false;
   }
 
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 5cdacaa..ffdd0ce 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -9,6 +9,7 @@
 
 #include "cmMakefile.h"
 #include "cmSourceGroup.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 namespace {
@@ -54,7 +55,7 @@
                   const std::vector<std::string>& files, std::string& error)
 {
   for (std::string const& file : files) {
-    if (!cmSystemTools::StringStartsWith(file, root.c_str())) {
+    if (!cmHasPrefix(file, root)) {
       error = "ROOT: " + root + " is not a prefix of file: " + file;
       return false;
     }
@@ -63,15 +64,6 @@
   return true;
 }
 
-std::string prepareFilePathForTree(const std::string& path,
-                                   const std::string& currentSourceDir)
-{
-  if (!cmSystemTools::FileIsFullPath(path)) {
-    return cmSystemTools::CollapseFullPath(currentSourceDir + "/" + path);
-  }
-  return cmSystemTools::CollapseFullPath(path);
-}
-
 std::vector<std::string> prepareFilesPathsForTree(
   const std::vector<std::string>& filesPaths,
   const std::string& currentSourceDir)
@@ -80,9 +72,11 @@
   prepared.reserve(filesPaths.size());
 
   for (auto const& filePath : filesPaths) {
+    std::string fullPath =
+      cmSystemTools::CollapseFullPath(filePath, currentSourceDir);
     // If provided file path is actually not a file, silently ignore it.
-    if (cmSystemTools::FileExists(filePath, /*isFile=*/true)) {
-      prepared.push_back(prepareFilePathForTree(filePath, currentSourceDir));
+    if (cmSystemTools::FileExists(fullPath, /*isFile=*/true)) {
+      prepared.emplace_back(std::move(fullPath));
     }
   }
 
diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h
index ec5ad32..eec4ec0 100644
--- a/Source/cmSourceGroupCommand.h
+++ b/Source/cmSourceGroupCommand.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmSourceGroupCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSourceGroupCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index fa7df0b..1ea72e1 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -5,35 +5,33 @@
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
+#include <stdlib.h>
 #include <string.h>
 #include <utility>
 
-#include "cmAlgorithms.h"
+#include "cm_memory.hxx"
+
 #include "cmCacheManager.h"
 #include "cmCommand.h"
 #include "cmDefinitions.h"
 #include "cmDisallowedCommand.h"
+#include "cmExecutionStatus.h"
 #include "cmGlobVerificationManager.h"
 #include "cmListFileCache.h"
+#include "cmMakefile.h"
 #include "cmStatePrivate.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
-#include "cmUnexpectedCommand.h"
 #include "cmake.h"
 
 cmState::cmState()
 {
-  this->CacheManager = new cmCacheManager;
-  this->GlobVerificationManager = new cmGlobVerificationManager;
+  this->CacheManager = cm::make_unique<cmCacheManager>();
+  this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>();
 }
 
-cmState::~cmState()
-{
-  delete this->CacheManager;
-  delete this->GlobVerificationManager;
-  cmDeleteAll(this->BuiltinCommands);
-  cmDeleteAll(this->ScriptedCommands);
-}
+cmState::~cmState() = default;
 
 const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType)
 {
@@ -267,7 +265,7 @@
 
 cmStateSnapshot cmState::Reset()
 {
-  this->GlobalProperties.clear();
+  this->GlobalProperties.Clear();
   this->PropertyDefinitions.clear();
   this->GlobVerificationManager->Reset();
 
@@ -289,7 +287,7 @@
     it->LinkDirectoriesBacktraces.clear();
     it->DirectoryEnd = pos;
     it->NormalTargetNames.clear();
-    it->Properties.clear();
+    it->Properties.Clear();
     it->Children.clear();
   }
 
@@ -310,8 +308,8 @@
     pos->Parent = this->VarTree.Root();
     pos->Root = this->VarTree.Root();
 
-    pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str());
-    pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str());
+    pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir);
+    pos->Vars->Set("CMAKE_BINARY_DIR", binDir);
   }
 
   this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "",
@@ -421,61 +419,82 @@
   this->IsGeneratorMultiConfig = b;
 }
 
-void cmState::AddBuiltinCommand(std::string const& name, cmCommand* command)
+void cmState::AddBuiltinCommand(std::string const& name,
+                                std::unique_ptr<cmCommand> command)
+{
+  this->AddBuiltinCommand(name, cmLegacyCommandWrapper(std::move(command)));
+}
+
+void cmState::AddBuiltinCommand(std::string const& name, Command command)
 {
   assert(name == cmSystemTools::LowerCase(name));
   assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
-  this->BuiltinCommands.insert(std::make_pair(name, command));
+  this->BuiltinCommands.emplace(name, std::move(command));
 }
 
-void cmState::AddDisallowedCommand(std::string const& name, cmCommand* command,
+void cmState::AddBuiltinCommand(std::string const& name,
+                                BuiltinCommand command)
+{
+  this->AddBuiltinCommand(
+    name,
+    [command](const std::vector<cmListFileArgument>& args,
+              cmExecutionStatus& status) -> bool {
+      std::vector<std::string> expandedArguments;
+      if (!status.GetMakefile().ExpandArguments(args, expandedArguments)) {
+        // There was an error expanding arguments.  It was already
+        // reported, so we can skip this command without error.
+        return true;
+      }
+      return command(expandedArguments, status);
+    });
+}
+
+void cmState::AddDisallowedCommand(std::string const& name,
+                                   std::unique_ptr<cmCommand> command,
                                    cmPolicies::PolicyID policy,
                                    const char* message)
 {
-  this->AddBuiltinCommand(name,
-                          new cmDisallowedCommand(command, policy, message));
+  this->AddBuiltinCommand(
+    name,
+    cm::make_unique<cmDisallowedCommand>(std::move(command), policy, message));
 }
 
 void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
 {
-  this->AddBuiltinCommand(name, new cmUnexpectedCommand(name, error));
+  this->AddBuiltinCommand(
+    name,
+    [name, error](std::vector<cmListFileArgument> const&,
+                  cmExecutionStatus& status) -> bool {
+      const char* versionValue =
+        status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
+      if (name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) {
+        return true;
+      }
+      status.SetError(error);
+      return false;
+    });
 }
 
-void cmState::AddScriptedCommand(std::string const& name, cmCommand* command)
+void cmState::AddScriptedCommand(std::string const& name, Command command)
 {
   std::string sName = cmSystemTools::LowerCase(name);
 
   // if the command already exists, give a new name to the old command.
-  if (cmCommand* oldCmd = this->GetCommand(sName)) {
-    std::string const newName = "_" + sName;
-    std::map<std::string, cmCommand*>::iterator pos =
-      this->ScriptedCommands.find(newName);
-    if (pos != this->ScriptedCommands.end()) {
-      delete pos->second;
-      this->ScriptedCommands.erase(pos);
-    }
-    this->ScriptedCommands.insert(std::make_pair(newName, oldCmd->Clone()));
+  if (Command oldCmd = this->GetCommand(sName)) {
+    this->ScriptedCommands["_" + sName] = oldCmd;
   }
 
-  // if the command already exists, free the old one
-  std::map<std::string, cmCommand*>::iterator pos =
-    this->ScriptedCommands.find(sName);
-  if (pos != this->ScriptedCommands.end()) {
-    delete pos->second;
-    this->ScriptedCommands.erase(pos);
-  }
-  this->ScriptedCommands.insert(std::make_pair(sName, command));
+  this->ScriptedCommands[sName] = std::move(command);
 }
 
-cmCommand* cmState::GetCommand(std::string const& name) const
+cmState::Command cmState::GetCommand(std::string const& name) const
 {
   return GetCommandByExactName(cmSystemTools::LowerCase(name));
 }
 
-cmCommand* cmState::GetCommandByExactName(std::string const& name) const
+cmState::Command cmState::GetCommandByExactName(std::string const& name) const
 {
-  std::map<std::string, cmCommand*>::const_iterator pos;
-  pos = this->ScriptedCommands.find(name);
+  auto pos = this->ScriptedCommands.find(name);
   if (pos != this->ScriptedCommands.end()) {
     return pos->second;
   }
@@ -506,16 +525,11 @@
 void cmState::RemoveBuiltinCommand(std::string const& name)
 {
   assert(name == cmSystemTools::LowerCase(name));
-  std::map<std::string, cmCommand*>::iterator i =
-    this->BuiltinCommands.find(name);
-  assert(i != this->BuiltinCommands.end());
-  delete i->second;
-  this->BuiltinCommands.erase(i);
+  this->BuiltinCommands.erase(name);
 }
 
 void cmState::RemoveUserDefinedCommands()
 {
-  cmDeleteAll(this->ScriptedCommands);
   this->ScriptedCommands.clear();
 }
 
diff --git a/Source/cmState.h b/Source/cmState.h
index 6abe71c..8847f3b 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -5,7 +5,9 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <functional>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -26,6 +28,7 @@
 class cmPropertyDefinition;
 class cmStateSnapshot;
 class cmMessenger;
+class cmExecutionStatus;
 
 class cmState
 {
@@ -140,16 +143,25 @@
   bool GetIsGeneratorMultiConfig() const;
   void SetIsGeneratorMultiConfig(bool b);
 
-  // Returns a command from its name, case insensitive, or nullptr
-  cmCommand* GetCommand(std::string const& name) const;
-  // Returns a command from its name, or nullptr
-  cmCommand* GetCommandByExactName(std::string const& name) const;
+  using Command = std::function<bool(std::vector<cmListFileArgument> const&,
+                                     cmExecutionStatus&)>;
+  using BuiltinCommand = bool (*)(std::vector<std::string> const&,
+                                  cmExecutionStatus&);
 
-  void AddBuiltinCommand(std::string const& name, cmCommand* command);
-  void AddDisallowedCommand(std::string const& name, cmCommand* command,
+  // Returns a command from its name, case insensitive, or nullptr
+  Command GetCommand(std::string const& name) const;
+  // Returns a command from its name, or nullptr
+  Command GetCommandByExactName(std::string const& name) const;
+
+  void AddBuiltinCommand(std::string const& name,
+                         std::unique_ptr<cmCommand> command);
+  void AddBuiltinCommand(std::string const& name, Command command);
+  void AddBuiltinCommand(std::string const& name, BuiltinCommand command);
+  void AddDisallowedCommand(std::string const& name,
+                            std::unique_ptr<cmCommand> command,
                             cmPolicies::PolicyID policy, const char* message);
   void AddUnexpectedCommand(std::string const& name, const char* error);
-  void AddScriptedCommand(std::string const& name, cmCommand* command);
+  void AddScriptedCommand(std::string const& name, Command command);
   void RemoveBuiltinCommand(std::string const& name);
   void RemoveUserDefinedCommands();
   std::vector<std::string> GetCommandNames() const;
@@ -208,11 +220,11 @@
 
   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
   std::vector<std::string> EnabledLanguages;
-  std::map<std::string, cmCommand*> BuiltinCommands;
-  std::map<std::string, cmCommand*> ScriptedCommands;
+  std::map<std::string, Command> BuiltinCommands;
+  std::map<std::string, Command> ScriptedCommands;
   cmPropertyMap GlobalProperties;
-  cmCacheManager* CacheManager;
-  cmGlobVerificationManager* GlobVerificationManager;
+  std::unique_ptr<cmCacheManager> CacheManager;
+  std::unique_ptr<cmGlobVerificationManager> GlobVerificationManager;
 
   cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>
     BuildsystemDirectory;
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 182d3fe..3f70ed3 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -6,7 +6,7 @@
 #include <algorithm>
 #include <assert.h>
 #include <iterator>
-#include <utility>
+#include <vector>
 
 #include "cmAlgorithms.h"
 #include "cmProperty.h"
@@ -667,12 +667,7 @@
 
 std::vector<std::string> cmStateDirectory::GetPropertyKeys() const
 {
-  std::vector<std::string> keys;
-  keys.reserve(this->DirectoryState->Properties.size());
-  for (auto const& it : this->DirectoryState->Properties) {
-    keys.push_back(it.first);
-  }
-  return keys;
+  return this->DirectoryState->Properties.GetKeys();
 }
 
 void cmStateDirectory::AddNormalTargetName(std::string const& name)
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index 6956594..fe15563 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -14,6 +14,7 @@
 #include "cmListFileCache.h"
 #include "cmStatePrivate.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 
 class cmStateDirectory
 {
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index 63bec71..110ec56 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -222,14 +222,14 @@
 }
 
 void cmStateSnapshot::SetDefinition(std::string const& name,
-                                    std::string const& value)
+                                    cm::string_view value)
 {
-  this->Position->Vars->Set(name, value.c_str());
+  this->Position->Vars->Set(name, value);
 }
 
 void cmStateSnapshot::RemoveDefinition(std::string const& name)
 {
-  this->Position->Vars->Set(name, nullptr);
+  this->Position->Vars->Unset(name);
 }
 
 std::vector<std::string> cmStateSnapshot::UnusedKeys() const
@@ -264,7 +264,11 @@
   cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root);
 
   // Now update the definition in the parent scope.
-  this->Position->Parent->Set(var, varDef);
+  if (varDef) {
+    this->Position->Parent->Set(var, varDef);
+  } else {
+    this->Position->Parent->Unset(var);
+  }
   return true;
 }
 
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
index c315f48..da39127 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_string_view.hxx"
+
 #include "cmLinkedTree.h"
 #include "cmPolicies.h"
 #include "cmStateTypes.h"
@@ -24,7 +26,7 @@
 
   std::string const* GetDefinition(std::string const& name) const;
   bool IsInitialized(std::string const& name) const;
-  void SetDefinition(std::string const& name, std::string const& value);
+  void SetDefinition(std::string const& name, cm::string_view value);
   void RemoveDefinition(std::string const& name);
   std::vector<std::string> UnusedKeys() const;
   std::vector<std::string> ClosureKeys() const;
diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx
new file mode 100644
index 0000000..5deb9b0
--- /dev/null
+++ b/Source/cmStringAlgorithms.cxx
@@ -0,0 +1,73 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmStringAlgorithms.h"
+
+#include <algorithm>
+#include <cstdio>
+
+namespace {
+template <std::size_t N, typename T>
+inline void MakeDigits(cm::string_view& view, char (&digits)[N],
+                       const char* pattern, T value)
+{
+  int res = std::snprintf(digits, N, pattern, value);
+  if (res > 0 && res < static_cast<int>(N)) {
+    view = cm::string_view(digits, static_cast<std::size_t>(res));
+  }
+}
+} // unnamed namespace
+
+cmAlphaNum::cmAlphaNum(int val)
+{
+  MakeDigits(View_, Digits_, "%i", val);
+}
+
+cmAlphaNum::cmAlphaNum(unsigned int val)
+{
+  MakeDigits(View_, Digits_, "%u", val);
+}
+
+cmAlphaNum::cmAlphaNum(long int val)
+{
+  MakeDigits(View_, Digits_, "%li", val);
+}
+
+cmAlphaNum::cmAlphaNum(unsigned long int val)
+{
+  MakeDigits(View_, Digits_, "%lu", val);
+}
+
+cmAlphaNum::cmAlphaNum(long long int val)
+{
+  MakeDigits(View_, Digits_, "%lli", val);
+}
+
+cmAlphaNum::cmAlphaNum(unsigned long long int val)
+{
+  MakeDigits(View_, Digits_, "%llu", val);
+}
+
+cmAlphaNum::cmAlphaNum(float val)
+{
+  MakeDigits(View_, Digits_, "%g", static_cast<double>(val));
+}
+
+cmAlphaNum::cmAlphaNum(double val)
+{
+  MakeDigits(View_, Digits_, "%g", val);
+}
+
+std::string cmCatViews(std::initializer_list<cm::string_view> views)
+{
+  std::size_t total_size = 0;
+  for (cm::string_view const& view : views) {
+    total_size += view.size();
+  }
+
+  std::string result(total_size, '\0');
+  std::string::iterator sit = result.begin();
+  for (cm::string_view const& view : views) {
+    sit = std::copy_n(view.data(), view.size(), sit);
+  }
+  return result;
+}
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
new file mode 100644
index 0000000..cdb494f
--- /dev/null
+++ b/Source/cmStringAlgorithms.h
@@ -0,0 +1,177 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmStringAlgorithms_h
+#define cmStringAlgorithms_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmRange.h"
+#include "cm_string_view.hxx"
+#include <initializer_list>
+#include <sstream>
+#include <string.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+/** String range type.  */
+typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange;
+
+/** Callable string comparison struct.  */
+struct cmStrCmp
+{
+  cmStrCmp(std::string str)
+    : Test_(std::move(str))
+  {
+  }
+
+  bool operator()(cm::string_view sv) const { return Test_ == sv; }
+
+private:
+  std::string const Test_;
+};
+
+/** Joins elements of a range with separator into a single string.  */
+template <typename Range>
+std::string cmJoin(Range const& rng, cm::string_view separator)
+{
+  if (rng.empty()) {
+    return std::string();
+  }
+
+  std::ostringstream os;
+  auto it = rng.begin();
+  auto const end = rng.end();
+  os << *it;
+  while (++it != end) {
+    os << separator << *it;
+  }
+  return os.str();
+}
+
+/** Concatenate string pieces into a single string.  */
+std::string cmCatViews(std::initializer_list<cm::string_view> views);
+
+/** Utility class for cmStrCat.  */
+class cmAlphaNum
+{
+public:
+  cmAlphaNum(cm::string_view view)
+    : View_(view)
+  {
+  }
+  cmAlphaNum(std::string const& str)
+    : View_(str)
+  {
+  }
+  cmAlphaNum(const char* str)
+    : View_(str)
+  {
+  }
+  cmAlphaNum(char ch)
+    : View_(Digits_, 1)
+  {
+    Digits_[0] = ch;
+  }
+  cmAlphaNum(int val);
+  cmAlphaNum(unsigned int val);
+  cmAlphaNum(long int val);
+  cmAlphaNum(unsigned long int val);
+  cmAlphaNum(long long int val);
+  cmAlphaNum(unsigned long long int val);
+  cmAlphaNum(float val);
+  cmAlphaNum(double val);
+
+  cm::string_view View() const { return View_; }
+
+private:
+  cm::string_view View_;
+  char Digits_[32];
+};
+
+/** Concatenate string pieces and numbers into a single string.  */
+template <typename... AV>
+inline std::string cmStrCat(cmAlphaNum const& a, cmAlphaNum const& b,
+                            AV const&... args)
+{
+  return cmCatViews(
+    { a.View(), b.View(), static_cast<cmAlphaNum const&>(args).View()... });
+}
+
+/** Joins wrapped elements of a range with separator into a single string.  */
+template <typename Range>
+std::string cmWrap(cm::string_view prefix, Range const& rng,
+                   cm::string_view suffix, cm::string_view sep)
+{
+  if (rng.empty()) {
+    return std::string();
+  }
+  return cmCatViews(
+    { prefix, cmJoin(rng, cmCatViews({ suffix, sep, prefix })), suffix });
+}
+
+/** Joins wrapped elements of a range with separator into a single string.  */
+template <typename Range>
+std::string cmWrap(char prefix, Range const& rng, char suffix,
+                   cm::string_view sep)
+{
+  return cmWrap(cm::string_view(&prefix, 1), rng, cm::string_view(&suffix, 1),
+                sep);
+}
+
+/** Returns true if string @a str starts with the character @a prefix.  */
+inline bool cmHasPrefix(cm::string_view str, char prefix)
+{
+  return !str.empty() && (str.front() == prefix);
+}
+
+/** Returns true if string @a str starts with string @a prefix.  */
+inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix)
+{
+  return str.compare(0, prefix.size(), prefix) == 0;
+}
+
+/** Returns true if string @a str starts with string @a prefix.  */
+template <size_t N>
+inline bool cmHasLiteralPrefix(cm::string_view str, const char (&prefix)[N])
+{
+  return cmHasPrefix(str, cm::string_view(prefix, N - 1));
+}
+
+/** Returns true if string @a str ends with the character @a suffix.  */
+inline bool cmHasSuffix(cm::string_view str, char suffix)
+{
+  return !str.empty() && (str.back() == suffix);
+}
+
+/** Returns true if string @a str ends with string @a suffix.  */
+inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix)
+{
+  return str.size() >= suffix.size() &&
+    str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+}
+
+/** Returns true if string @a str ends with string @a suffix.  */
+template <size_t N>
+inline bool cmHasLiteralSuffix(cm::string_view str, const char (&suffix)[N])
+{
+  return cmHasSuffix(str, cm::string_view(suffix, N - 1));
+}
+
+/** Removes an existing suffix character of from the string @a str.  */
+inline void cmStripSuffixIfExists(std::string& str, char suffix)
+{
+  if (cmHasSuffix(str, suffix)) {
+    str.pop_back();
+  }
+}
+
+/** Removes an existing suffix string of from the string @a str.  */
+inline void cmStripSuffixIfExists(std::string& str, cm::string_view suffix)
+{
+  if (cmHasSuffix(str, suffix)) {
+    str.resize(str.size() - suffix.size());
+  }
+}
+
+#endif
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 998f904..8b3b1e3 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -8,7 +8,6 @@
 #include <algorithm>
 #include <ctype.h>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -19,6 +18,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmStringReplaceHelper.h"
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"
@@ -124,7 +124,7 @@
   std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str()));
   if (hash) {
     std::string out = hash->HashString(args[2]);
-    this->Makefile->AddDefinition(args[1], out.c_str());
+    this->Makefile->AddDefinition(args[1], out);
     return true;
   }
   return false;
@@ -154,7 +154,7 @@
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output.c_str());
+  this->Makefile->AddDefinition(outvar, output);
   return true;
 }
 
@@ -180,7 +180,7 @@
     }
   }
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output.c_str());
+  this->Makefile->AddDefinition(outvar, output);
   return true;
 }
 
@@ -217,7 +217,7 @@
   this->Makefile->ConfigureString(args[1], output, atOnly, escapeQuotes);
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(args[2], output.c_str());
+  this->Makefile->AddDefinition(args[2], output);
 
   return true;
 }
@@ -296,7 +296,7 @@
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output.c_str());
+  this->Makefile->AddDefinition(outvar, output);
   return true;
 }
 
@@ -343,7 +343,7 @@
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output.c_str());
+  this->Makefile->AddDefinition(outvar, output);
   return true;
 }
 
@@ -384,7 +384,7 @@
   }
 
   // Store the output in the provided variable.
-  this->Makefile->AddDefinition(outvar, output.c_str());
+  this->Makefile->AddDefinition(outvar, output);
   return true;
 }
 
@@ -431,7 +431,7 @@
   if (std::string::npos != pos) {
     std::ostringstream s;
     s << pos;
-    this->Makefile->AddDefinition(outvar, s.str().c_str());
+    this->Makefile->AddDefinition(outvar, s.str());
     return true;
   }
 
@@ -506,7 +506,7 @@
   cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
                                     replaceExpression.c_str());
 
-  this->Makefile->AddDefinition(variableName, input.c_str());
+  this->Makefile->AddDefinition(variableName, input);
   return true;
 }
 
@@ -539,8 +539,7 @@
     return false;
   }
 
-  this->Makefile->AddDefinition(variableName,
-                                stringValue.substr(begin, end).c_str());
+  this->Makefile->AddDefinition(variableName, stringValue.substr(begin, end));
   return true;
 }
 
@@ -582,7 +581,7 @@
     value = oldValue;
   }
   value += cmJoin(cmMakeRange(args).advance(2), std::string());
-  this->Makefile->AddDefinition(variable, value.c_str());
+  this->Makefile->AddDefinition(variable, value);
   return true;
 }
 
@@ -606,7 +605,7 @@
   if (oldValue) {
     value += oldValue;
   }
-  this->Makefile->AddDefinition(variable, value.c_str());
+  this->Makefile->AddDefinition(variable, value);
   return true;
 }
 
@@ -638,7 +637,7 @@
   // both `CONCAT` and `JOIN` sub-commands.
   std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue);
 
-  this->Makefile->AddDefinition(variableName, value.c_str());
+  this->Makefile->AddDefinition(variableName, value);
   return true;
 }
 
@@ -654,7 +653,7 @@
   const std::string& variableName = args[2];
 
   this->Makefile->AddDefinition(variableName,
-                                cmSystemTools::MakeCidentifier(input).c_str());
+                                cmSystemTools::MakeCidentifier(input));
   return true;
 }
 
@@ -673,7 +672,7 @@
 
   const std::string& variableName = args[2];
 
-  this->Makefile->AddDefinition(variableName, result.c_str());
+  this->Makefile->AddDefinition(variableName, result);
   return true;
 }
 
@@ -712,8 +711,8 @@
     outLength = endPos - startPos + 1;
   }
 
-  this->Makefile->AddDefinition(
-    variableName, stringValue.substr(startPos, outLength).c_str());
+  this->Makefile->AddDefinition(variableName,
+                                stringValue.substr(startPos, outLength));
   return true;
 }
 
@@ -766,7 +765,7 @@
       break;
   }
 
-  this->Makefile->AddDefinition(variableName, result.c_str());
+  this->Makefile->AddDefinition(variableName, result);
   return true;
 }
 
@@ -872,7 +871,7 @@
 
   cmTimestamp timestamp;
   std::string result = timestamp.CurrentTime(formatString, utcFlag);
-  this->Makefile->AddDefinition(outputVariable, result.c_str());
+  this->Makefile->AddDefinition(outputVariable, result);
 
   return true;
 }
@@ -955,7 +954,7 @@
     uuid = cmSystemTools::UpperCase(uuid);
   }
 
-  this->Makefile->AddDefinition(outputVariable, uuid.c_str());
+  this->Makefile->AddDefinition(outputVariable, uuid);
   return true;
 #else
   std::ostringstream e;
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index acde605..f48ea17 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmStringCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmStringCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h
index adab757..3499c46 100644
--- a/Source/cmSubdirCommand.h
+++ b/Source/cmSubdirCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -25,7 +27,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmSubdirCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSubdirCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h
index 2db28c6..64c28b9 100644
--- a/Source/cmSubdirDependsCommand.h
+++ b/Source/cmSubdirDependsCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmSubdirDependsCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmSubdirDependsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmSubdirDependsCommand>();
+  }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 };
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 1501481..5f4e1fc 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -6,6 +6,7 @@
 #include "cmDuration.h"
 #include "cmProcessOutput.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cm_uv.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -176,36 +177,37 @@
 }
 #endif
 
-std::string cmSystemTools::EscapeQuotes(const std::string& str)
+std::string cmSystemTools::EscapeQuotes(cm::string_view str)
 {
   std::string result;
   result.reserve(str.size());
-  for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
-    if (*ch == '"') {
+  for (const char ch : str) {
+    if (ch == '"') {
       result += '\\';
     }
-    result += *ch;
+    result += ch;
   }
   return result;
 }
 
-std::string cmSystemTools::HelpFileName(std::string name)
+std::string cmSystemTools::HelpFileName(cm::string_view str)
 {
+  std::string name(str);
   cmSystemTools::ReplaceString(name, "<", "");
   cmSystemTools::ReplaceString(name, ">", "");
   return name;
 }
 
-std::string cmSystemTools::TrimWhitespace(const std::string& s)
+std::string cmSystemTools::TrimWhitespace(cm::string_view str)
 {
-  std::string::const_iterator start = s.begin();
-  while (start != s.end() && cm_isspace(*start)) {
+  auto start = str.begin();
+  while (start != str.end() && cm_isspace(*start)) {
     ++start;
   }
-  if (start == s.end()) {
-    return "";
+  if (start == str.end()) {
+    return std::string();
   }
-  std::string::const_iterator stop = s.end() - 1;
+  auto stop = str.end() - 1;
   while (cm_isspace(*stop)) {
     --stop;
   }
@@ -282,115 +284,85 @@
   cmSystemTools::Error(m);
 }
 
-bool cmSystemTools::IsInternallyOn(const char* val)
+bool cmSystemTools::IsInternallyOn(cm::string_view val)
 {
-  if (!val) {
-    return false;
-  }
-  std::string v = val;
-  if (v.size() > 4) {
-    return false;
-  }
-
-  for (char& c : v) {
-    c = static_cast<char>(toupper(c));
-  }
-  return v == "I_ON";
+  return (val.size() == 4) &&           //
+    (val[0] == 'I' || val[0] == 'i') && //
+    (val[1] == '_') &&                  //
+    (val[2] == 'O' || val[2] == 'o') && //
+    (val[3] == 'N' || val[3] == 'n');
 }
 
-bool cmSystemTools::IsOn(const char* val)
+bool cmSystemTools::IsOn(cm::string_view val)
 {
-  if (!val) {
-    return false;
+  switch (val.size()) {
+    case 1:
+      return val[0] == '1' || val[0] == 'Y' || val[0] == 'y';
+    case 2:
+      return                                //
+        (val[0] == 'O' || val[0] == 'o') && //
+        (val[1] == 'N' || val[1] == 'n');
+    case 3:
+      return                                //
+        (val[0] == 'Y' || val[0] == 'y') && //
+        (val[1] == 'E' || val[1] == 'e') && //
+        (val[2] == 'S' || val[2] == 's');
+    case 4:
+      return                                //
+        (val[0] == 'T' || val[0] == 't') && //
+        (val[1] == 'R' || val[1] == 'r') && //
+        (val[2] == 'U' || val[2] == 'u') && //
+        (val[3] == 'E' || val[3] == 'e');
+    default:
+      break;
   }
-  /* clang-format off */
-  // "1"
-  if (val[0] == '1' && val[1] == '\0') {
-    return true;
-  }
-  // "ON"
-  if ((val[0] == 'O' || val[0] == 'o') &&
-      (val[1] == 'N' || val[1] == 'n') && val[2] == '\0') {
-    return true;
-  }
-  // "Y", "YES"
-  if ((val[0] == 'Y' || val[0] == 'y') && (val[1] == '\0' || (
-      (val[1] == 'E' || val[1] == 'e') &&
-      (val[2] == 'S' || val[2] == 's') && val[3] == '\0'))) {
-    return true;
-  }
-  // "TRUE"
-  if ((val[0] == 'T' || val[0] == 't') &&
-      (val[1] == 'R' || val[1] == 'r') &&
-      (val[2] == 'U' || val[2] == 'u') &&
-      (val[3] == 'E' || val[3] == 'e') && val[4] == '\0') {
-    return true;
-  }
-  /* clang-format on */
+
   return false;
 }
 
-bool cmSystemTools::IsOn(const std::string& val)
+bool cmSystemTools::IsNOTFOUND(cm::string_view val)
 {
-  return cmSystemTools::IsOn(val.c_str());
+  return (val == "NOTFOUND") || cmHasLiteralSuffix(val, "-NOTFOUND");
 }
 
-bool cmSystemTools::IsNOTFOUND(const char* val)
+bool cmSystemTools::IsOff(cm::string_view val)
 {
-  if (strcmp(val, "NOTFOUND") == 0) {
-    return true;
+  switch (val.size()) {
+    case 0:
+      return true;
+    case 1:
+      return val[0] == '0' || val[0] == 'N' || val[0] == 'n';
+    case 2:
+      return                                //
+        (val[0] == 'N' || val[0] == 'n') && //
+        (val[1] == 'O' || val[1] == 'o');
+    case 3:
+      return                                //
+        (val[0] == 'O' || val[0] == 'o') && //
+        (val[1] == 'F' || val[1] == 'f') && //
+        (val[2] == 'F' || val[2] == 'f');
+    case 5:
+      return                                //
+        (val[0] == 'F' || val[0] == 'f') && //
+        (val[1] == 'A' || val[1] == 'a') && //
+        (val[2] == 'L' || val[2] == 'l') && //
+        (val[3] == 'S' || val[3] == 's') && //
+        (val[4] == 'E' || val[4] == 'e');
+    case 6:
+      return                                //
+        (val[0] == 'I' || val[0] == 'i') && //
+        (val[1] == 'G' || val[1] == 'g') && //
+        (val[2] == 'N' || val[2] == 'n') && //
+        (val[3] == 'O' || val[3] == 'o') && //
+        (val[4] == 'R' || val[4] == 'r') && //
+        (val[5] == 'E' || val[5] == 'e');
+    default:
+      break;
   }
-  return cmHasLiteralSuffix(val, "-NOTFOUND");
-}
 
-bool cmSystemTools::IsOff(const char* val)
-{
-  // ""
-  if (!val || val[0] == '\0') {
-    return true;
-  }
-  /* clang-format off */
-  // "0"
-  if (val[0] == '0' && val[1] == '\0') {
-    return true;
-  }
-  // "OFF"
-  if ((val[0] == 'O' || val[0] == 'o') &&
-      (val[1] == 'F' || val[1] == 'f') &&
-      (val[2] == 'F' || val[2] == 'f') && val[3] == '\0') {
-    return true;
-  }
-  // "N", "NO"
-  if ((val[0] == 'N' || val[0] == 'n') && (val[1] == '\0' || (
-      (val[1] == 'O' || val[1] == 'o') && val[2] == '\0'))) {
-    return true;
-  }
-  // "FALSE"
-  if ((val[0] == 'F' || val[0] == 'f') &&
-      (val[1] == 'A' || val[1] == 'a') &&
-      (val[2] == 'L' || val[2] == 'l') &&
-      (val[3] == 'S' || val[3] == 's') &&
-      (val[4] == 'E' || val[4] == 'e') && val[5] == '\0') {
-    return true;
-  }
-  // "IGNORE"
-  if ((val[0] == 'I' || val[0] == 'i') &&
-      (val[1] == 'G' || val[1] == 'g') &&
-      (val[2] == 'N' || val[2] == 'n') &&
-      (val[3] == 'O' || val[3] == 'o') &&
-      (val[4] == 'R' || val[4] == 'r') &&
-      (val[5] == 'E' || val[5] == 'e') && val[6] == '\0') {
-    return true;
-  }
-  /* clang-format on */
   return cmSystemTools::IsNOTFOUND(val);
 }
 
-bool cmSystemTools::IsOff(const std::string& val)
-{
-  return cmSystemTools::IsOff(val.c_str());
-}
-
 void cmSystemTools::ParseWindowsCommandLine(const char* command,
                                             std::vector<std::string>& args)
 {
@@ -1151,7 +1123,7 @@
   }
 }
 
-void cmSystemTools::ExpandListArgument(const std::string& arg,
+void cmSystemTools::ExpandListArgument(cm::string_view arg,
                                        std::vector<std::string>& argsOut,
                                        bool emptyArgs)
 {
@@ -1159,25 +1131,29 @@
   if (!emptyArgs && arg.empty()) {
     return;
   }
+
   // if there are no ; in the name then just copy the current string
-  if (arg.find(';') == std::string::npos) {
-    argsOut.push_back(arg);
+  if (arg.find(';') == cm::string_view::npos) {
+    argsOut.emplace_back(arg);
     return;
   }
+
   std::string newArg;
-  const char* last = arg.c_str();
   // Break the string at non-escaped semicolons not nested in [].
   int squareNesting = 0;
-  for (const char* c = last; *c; ++c) {
+  cm::string_view::iterator last = arg.begin();
+  cm::string_view::iterator const cend = arg.end();
+  for (cm::string_view::iterator c = last; c != cend; ++c) {
     switch (*c) {
       case '\\': {
         // We only want to allow escaping of semicolons.  Other
         // escapes should not be processed here.
-        const char* next = c + 1;
-        if (*next == ';') {
-          newArg.append(last, c - last);
+        cm::string_view::iterator cnext = c + 1;
+        if ((cnext != cend) && *cnext == ';') {
+          newArg.append(last, c);
           // Skip over the escape character
-          last = c = next;
+          last = cnext;
+          c = cnext;
         }
       } break;
       case '[': {
@@ -1190,7 +1166,7 @@
         // Break the string here if we are not nested inside square
         // brackets.
         if (squareNesting == 0) {
-          newArg.append(last, c - last);
+          newArg.append(last, c);
           // Skip over the semicolon
           last = c + 1;
           if (!newArg.empty() || emptyArgs) {
@@ -1205,15 +1181,15 @@
       } break;
     }
   }
-  newArg.append(last);
+  newArg.append(last, cend);
   if (!newArg.empty() || emptyArgs) {
     // Add the last argument if the string is not empty.
-    argsOut.push_back(newArg);
+    argsOut.push_back(std::move(newArg));
   }
 }
 
 std::vector<std::string> cmSystemTools::ExpandedListArgument(
-  const std::string& arg, bool emptyArgs)
+  cm::string_view arg, bool emptyArgs)
 {
   std::vector<std::string> argsOut;
   ExpandListArgument(arg, argsOut, emptyArgs);
@@ -1264,65 +1240,6 @@
   return res;
 }
 
-cmSystemTools::FileFormat cmSystemTools::GetFileFormat(std::string const& ext)
-{
-  if (ext.empty()) {
-    return cmSystemTools::NO_FILE_FORMAT;
-  }
-  if (ext == "c" || ext == ".c" || ext == "m" || ext == ".m") {
-    return cmSystemTools::C_FILE_FORMAT;
-  }
-  if (ext == "C" || ext == ".C" || ext == "M" || ext == ".M" || ext == "c++" ||
-      ext == ".c++" || ext == "cc" || ext == ".cc" || ext == "cpp" ||
-      ext == ".cpp" || ext == "cxx" || ext == ".cxx" || ext == "mm" ||
-      ext == ".mm") {
-    return cmSystemTools::CXX_FILE_FORMAT;
-  }
-  if (ext == "f" || ext == ".f" || ext == "F" || ext == ".F" || ext == "f77" ||
-      ext == ".f77" || ext == "f90" || ext == ".f90" || ext == "for" ||
-      ext == ".for" || ext == "f95" || ext == ".f95") {
-    return cmSystemTools::FORTRAN_FILE_FORMAT;
-  }
-  if (ext == "java" || ext == ".java") {
-    return cmSystemTools::JAVA_FILE_FORMAT;
-  }
-  if (ext == "cu" || ext == ".cu") {
-    return cmSystemTools::CUDA_FILE_FORMAT;
-  }
-  if (ext == "H" || ext == ".H" || ext == "h" || ext == ".h" || ext == "h++" ||
-      ext == ".h++" || ext == "hm" || ext == ".hm" || ext == "hpp" ||
-      ext == ".hpp" || ext == "hxx" || ext == ".hxx" || ext == "in" ||
-      ext == ".in" || ext == "txx" || ext == ".txx") {
-    return cmSystemTools::HEADER_FILE_FORMAT;
-  }
-  if (ext == "rc" || ext == ".rc") {
-    return cmSystemTools::RESOURCE_FILE_FORMAT;
-  }
-  if (ext == "def" || ext == ".def") {
-    return cmSystemTools::DEFINITION_FILE_FORMAT;
-  }
-  if (ext == "lib" || ext == ".lib" || ext == "a" || ext == ".a") {
-    return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT;
-  }
-  if (ext == "o" || ext == ".o" || ext == "obj" || ext == ".obj") {
-    return cmSystemTools::OBJECT_FILE_FORMAT;
-  }
-#ifdef __APPLE__
-  if (ext == "dylib" || ext == ".dylib") {
-    return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT;
-  }
-  if (ext == "so" || ext == ".so" || ext == "bundle" || ext == ".bundle") {
-    return cmSystemTools::MODULE_FILE_FORMAT;
-  }
-#else  // __APPLE__
-  if (ext == "so" || ext == ".so" || ext == "sl" || ext == ".sl" ||
-      ext == "dll" || ext == ".dll") {
-    return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT;
-  }
-#endif // __APPLE__
-  return cmSystemTools::UNKNOWN_FILE_FORMAT;
-}
-
 std::string cmSystemTools::ConvertToOutputPath(std::string const& path)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -2456,7 +2373,8 @@
 #if defined(CMAKE_USE_ELF_PARSER)
 bool cmSystemTools::ChangeRPath(std::string const& file,
                                 std::string const& oldRPath,
-                                std::string const& newRPath, std::string* emsg,
+                                std::string const& newRPath,
+                                bool removeEnvironmentRPath, std::string* emsg,
                                 bool* changed)
 {
   if (changed) {
@@ -2543,7 +2461,9 @@
 
       // Construct the new value which preserves the part of the path
       // not being changed.
-      rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
+      if (!removeEnvironmentRPath) {
+        rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
+      }
       rp[rp_count].Value += newRPath;
       rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length());
 
@@ -2629,6 +2549,7 @@
 bool cmSystemTools::ChangeRPath(std::string const& /*file*/,
                                 std::string const& /*oldRPath*/,
                                 std::string const& /*newRPath*/,
+                                bool /*removeEnvironmentRPath*/,
                                 std::string* /*emsg*/, bool* /*changed*/)
 {
   return false;
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 016c266..ac1aa80 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -8,6 +8,7 @@
 #include "cmCryptoHash.h"
 #include "cmDuration.h"
 #include "cmProcessOutput.h"
+#include "cm_string_view.hxx"
 #include "cmsys/Process.h"
 #include "cmsys/SystemTools.hxx" // IWYU pragma: export
 #include <functional>
@@ -31,7 +32,7 @@
    * Expand the ; separated string @a arg into multiple arguments.
    * All found arguments are appended to @a argsOut.
    */
-  static void ExpandListArgument(const std::string& arg,
+  static void ExpandListArgument(cm::string_view arg,
                                  std::vector<std::string>& argsOut,
                                  bool emptyArgs = false);
 
@@ -53,7 +54,7 @@
    * Same as ExpandListArgument but a new vector is created containing
    * the expanded arguments from the string @a arg.
    */
-  static std::vector<std::string> ExpandedListArgument(const std::string& arg,
+  static std::vector<std::string> ExpandedListArgument(cm::string_view arg,
                                                        bool emptyArgs = false);
 
   /**
@@ -77,15 +78,15 @@
                                    KeyWOW64 view = KeyWOW64_Default);
 
   //! Escape quotes in a string.
-  static std::string EscapeQuotes(const std::string& str);
+  static std::string EscapeQuotes(cm::string_view str);
 
   /** Map help document name to file name.  */
-  static std::string HelpFileName(std::string);
+  static std::string HelpFileName(cm::string_view);
 
   /**
    * Returns a string that has whitespace removed from the start and the end.
    */
-  static std::string TrimWhitespace(const std::string& s);
+  static std::string TrimWhitespace(cm::string_view str);
 
   using MessageCallback = std::function<void(const std::string&, const char*)>;
   /**
@@ -149,26 +150,45 @@
    * forced this value. This is not the same as On, but this
    * may be considered as "internally switched on".
    */
-  static bool IsInternallyOn(const char* val);
-  /**
-   * does a string indicate a true or on value ? This is not the same
-   * as ifdef.
-   */
-  static bool IsOn(const char* val);
-  static bool IsOn(const std::string& val);
+  static bool IsInternallyOn(cm::string_view val);
+  static inline bool IsInternallyOn(const char* val)
+  {
+    if (!val) {
+      return false;
+    }
+    return IsInternallyOn(cm::string_view(val));
+  }
 
   /**
-   * does a string indicate a false or off value ? Note that this is
+   * Does a string indicate a true or on value? This is not the same as ifdef.
+   */
+  static bool IsOn(cm::string_view val);
+  inline static bool IsOn(const char* val)
+  {
+    if (!val) {
+      return false;
+    }
+    return IsOn(cm::string_view(val));
+  }
+
+  /**
+   * Does a string indicate a false or off value ? Note that this is
    * not the same as !IsOn(...) because there are a number of
    * ambiguous values such as "/usr/local/bin" a path will result in
    * IsON and IsOff both returning false. Note that the special path
    * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
    */
-  static bool IsOff(const char* val);
-  static bool IsOff(const std::string& val);
+  static bool IsOff(cm::string_view val);
+  inline static bool IsOff(const char* val)
+  {
+    if (!val) {
+      return true;
+    }
+    return IsOff(cm::string_view(val));
+  }
 
   //! Return true if value is NOTFOUND or ends in -NOTFOUND.
-  static bool IsNOTFOUND(const char* value);
+  static bool IsNOTFOUND(cm::string_view val);
   //! Return true if the path is a framework
   static bool IsPathToFramework(const std::string& value);
 
@@ -299,27 +319,6 @@
   static void EnableRunCommandOutput() { s_DisableRunCommandOutput = false; }
   static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; }
 
-  /**
-   * Some constants for different file formats.
-   */
-  enum FileFormat
-  {
-    NO_FILE_FORMAT = 0,
-    C_FILE_FORMAT,
-    CXX_FILE_FORMAT,
-    FORTRAN_FILE_FORMAT,
-    JAVA_FILE_FORMAT,
-    CUDA_FILE_FORMAT,
-    HEADER_FILE_FORMAT,
-    RESOURCE_FILE_FORMAT,
-    DEFINITION_FILE_FORMAT,
-    STATIC_LIBRARY_FILE_FORMAT,
-    SHARED_LIBRARY_FILE_FORMAT,
-    MODULE_FILE_FORMAT,
-    OBJECT_FILE_FORMAT,
-    UNKNOWN_FILE_FORMAT
-  };
-
   enum CompareOp
   {
     OP_EQUAL = 1,
@@ -350,11 +349,6 @@
    */
   static int strverscmp(std::string const& lhs, std::string const& rhs);
 
-  /**
-   * Determine the file type based on the extension
-   */
-  static FileFormat GetFileFormat(std::string const& ext);
-
   /** Windows if this is true, the CreateProcess in RunCommand will
    *  not show new console windows when running programs.
    */
@@ -499,6 +493,7 @@
   /** Try to set the RPATH in an ELF binary.  */
   static bool ChangeRPath(std::string const& file, std::string const& oldRPath,
                           std::string const& newRPath,
+                          bool removeEnvironmentRPath,
                           std::string* emsg = nullptr,
                           bool* changed = nullptr);
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index a67122c..7ca2391 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -12,6 +12,8 @@
 #include <string.h>
 #include <unordered_set>
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmCustomCommand.h"
 #include "cmGeneratorExpression.h"
@@ -168,7 +170,8 @@
   cmPropertyMap Properties;
   bool IsGeneratorProvided;
   bool HaveInstallRule;
-  bool DLLPlatform;
+  bool IsDLLPlatform;
+  bool IsAIX;
   bool IsAndroid;
   bool IsImportedTarget;
   bool ImportedGloballyVisible;
@@ -217,7 +220,8 @@
   impl->Name = name;
   impl->IsGeneratorProvided = false;
   impl->HaveInstallRule = false;
-  impl->DLLPlatform = false;
+  impl->IsDLLPlatform = false;
+  impl->IsAIX = false;
   impl->IsAndroid = false;
   impl->IsImportedTarget =
     (vis == VisibilityImported || vis == VisibilityImportedGlobally);
@@ -225,21 +229,32 @@
   impl->BuildInterfaceIncludesAppended = false;
 
   // Check whether this is a DLL platform.
-  impl->DLLPlatform =
+  impl->IsDLLPlatform =
     !impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
 
+  // Check whether we are targeting AIX.
+  impl->IsAIX =
+    (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "AIX");
+
   // Check whether we are targeting an Android platform.
   impl->IsAndroid =
     (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
 
-  std::string gKey;
-  gKey.reserve(128);
-  gKey += "CMAKE_";
-  auto InitProperty = [this, mf, &gKey](const std::string& property,
-                                        const char* default_value) {
+  std::string defKey;
+  defKey.reserve(128);
+  defKey += "CMAKE_";
+  auto initProp = [this, mf, &defKey](const std::string& property) {
     // Replace everything after "CMAKE_"
-    gKey.replace(gKey.begin() + 6, gKey.end(), property);
-    if (const char* value = mf->GetDefinition(gKey)) {
+    defKey.replace(defKey.begin() + 6, defKey.end(), property);
+    if (const char* value = mf->GetDefinition(defKey)) {
+      this->SetProperty(property, value);
+    }
+  };
+  auto initPropValue = [this, mf, &defKey](const std::string& property,
+                                           const char* default_value) {
+    // Replace everything after "CMAKE_"
+    defKey.replace(defKey.begin() + 6, defKey.end(), property);
+    if (const char* value = mf->GetDefinition(defKey)) {
       this->SetProperty(property, value);
     } else if (default_value) {
       this->SetProperty(property, default_value);
@@ -249,107 +264,108 @@
   // Setup default property values.
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
       this->GetType() != cmStateEnums::UTILITY) {
-    InitProperty("ANDROID_API", nullptr);
-    InitProperty("ANDROID_API_MIN", nullptr);
-    InitProperty("ANDROID_ARCH", nullptr);
-    InitProperty("ANDROID_STL_TYPE", nullptr);
-    InitProperty("ANDROID_SKIP_ANT_STEP", nullptr);
-    InitProperty("ANDROID_PROCESS_MAX", nullptr);
-    InitProperty("ANDROID_PROGUARD", nullptr);
-    InitProperty("ANDROID_PROGUARD_CONFIG_PATH", nullptr);
-    InitProperty("ANDROID_SECURE_PROPS_PATH", nullptr);
-    InitProperty("ANDROID_NATIVE_LIB_DIRECTORIES", nullptr);
-    InitProperty("ANDROID_NATIVE_LIB_DEPENDENCIES", nullptr);
-    InitProperty("ANDROID_JAVA_SOURCE_DIR", nullptr);
-    InitProperty("ANDROID_JAR_DIRECTORIES", nullptr);
-    InitProperty("ANDROID_JAR_DEPENDENCIES", nullptr);
-    InitProperty("ANDROID_ASSETS_DIRECTORIES", nullptr);
-    InitProperty("ANDROID_ANT_ADDITIONAL_OPTIONS", nullptr);
-    InitProperty("BUILD_RPATH", nullptr);
-    InitProperty("BUILD_RPATH_USE_ORIGIN", nullptr);
-    InitProperty("INSTALL_NAME_DIR", nullptr);
-    InitProperty("INSTALL_RPATH", "");
-    InitProperty("INSTALL_RPATH_USE_LINK_PATH", "OFF");
-    InitProperty("INTERPROCEDURAL_OPTIMIZATION", nullptr);
-    InitProperty("SKIP_BUILD_RPATH", "OFF");
-    InitProperty("BUILD_WITH_INSTALL_RPATH", "OFF");
-    InitProperty("ARCHIVE_OUTPUT_DIRECTORY", nullptr);
-    InitProperty("LIBRARY_OUTPUT_DIRECTORY", nullptr);
-    InitProperty("RUNTIME_OUTPUT_DIRECTORY", nullptr);
-    InitProperty("PDB_OUTPUT_DIRECTORY", nullptr);
-    InitProperty("COMPILE_PDB_OUTPUT_DIRECTORY", nullptr);
-    InitProperty("FRAMEWORK", nullptr);
-    InitProperty("Fortran_FORMAT", nullptr);
-    InitProperty("Fortran_MODULE_DIRECTORY", nullptr);
-    InitProperty("Fortran_COMPILER_LAUNCHER", nullptr);
-    InitProperty("GNUtoMS", nullptr);
-    InitProperty("OSX_ARCHITECTURES", nullptr);
-    InitProperty("IOS_INSTALL_COMBINED", nullptr);
-    InitProperty("AUTOMOC", nullptr);
-    InitProperty("AUTOUIC", nullptr);
-    InitProperty("AUTORCC", nullptr);
-    InitProperty("AUTOGEN_ORIGIN_DEPENDS", nullptr);
-    InitProperty("AUTOGEN_PARALLEL", nullptr);
-    InitProperty("AUTOMOC_COMPILER_PREDEFINES", nullptr);
-    InitProperty("AUTOMOC_DEPEND_FILTERS", nullptr);
-    InitProperty("AUTOMOC_MACRO_NAMES", nullptr);
-    InitProperty("AUTOMOC_MOC_OPTIONS", nullptr);
-    InitProperty("AUTOUIC_OPTIONS", nullptr);
-    InitProperty("AUTOUIC_SEARCH_PATHS", nullptr);
-    InitProperty("AUTORCC_OPTIONS", nullptr);
-    InitProperty("LINK_DEPENDS_NO_SHARED", nullptr);
-    InitProperty("LINK_INTERFACE_LIBRARIES", nullptr);
-    InitProperty("MSVC_RUNTIME_LIBRARY", nullptr);
-    InitProperty("WIN32_EXECUTABLE", nullptr);
-    InitProperty("MACOSX_BUNDLE", nullptr);
-    InitProperty("MACOSX_RPATH", nullptr);
-    InitProperty("NO_SYSTEM_FROM_IMPORTED", nullptr);
-    InitProperty("BUILD_WITH_INSTALL_NAME_DIR", nullptr);
-    InitProperty("C_CLANG_TIDY", nullptr);
-    InitProperty("C_COMPILER_LAUNCHER", nullptr);
-    InitProperty("C_CPPLINT", nullptr);
-    InitProperty("C_CPPCHECK", nullptr);
-    InitProperty("C_INCLUDE_WHAT_YOU_USE", nullptr);
-    InitProperty("LINK_WHAT_YOU_USE", nullptr);
-    InitProperty("C_STANDARD", nullptr);
-    InitProperty("C_STANDARD_REQUIRED", nullptr);
-    InitProperty("C_EXTENSIONS", nullptr);
-    InitProperty("CXX_CLANG_TIDY", nullptr);
-    InitProperty("CXX_COMPILER_LAUNCHER", nullptr);
-    InitProperty("CXX_CPPLINT", nullptr);
-    InitProperty("CXX_CPPCHECK", nullptr);
-    InitProperty("CXX_INCLUDE_WHAT_YOU_USE", nullptr);
-    InitProperty("CXX_STANDARD", nullptr);
-    InitProperty("CXX_STANDARD_REQUIRED", nullptr);
-    InitProperty("CXX_EXTENSIONS", nullptr);
-    InitProperty("CUDA_STANDARD", nullptr);
-    InitProperty("CUDA_STANDARD_REQUIRED", nullptr);
-    InitProperty("CUDA_EXTENSIONS", nullptr);
-    InitProperty("CUDA_COMPILER_LAUNCHER", nullptr);
-    InitProperty("CUDA_SEPARABLE_COMPILATION", nullptr);
-    InitProperty("LINK_SEARCH_START_STATIC", nullptr);
-    InitProperty("LINK_SEARCH_END_STATIC", nullptr);
-    InitProperty("FOLDER", nullptr);
-    InitProperty("Swift_MODULE_DIRECTORY", nullptr);
-    InitProperty("VS_JUST_MY_CODE_DEBUGGING", nullptr);
+    initProp("ANDROID_API");
+    initProp("ANDROID_API_MIN");
+    initProp("ANDROID_ARCH");
+    initProp("ANDROID_STL_TYPE");
+    initProp("ANDROID_SKIP_ANT_STEP");
+    initProp("ANDROID_PROCESS_MAX");
+    initProp("ANDROID_PROGUARD");
+    initProp("ANDROID_PROGUARD_CONFIG_PATH");
+    initProp("ANDROID_SECURE_PROPS_PATH");
+    initProp("ANDROID_NATIVE_LIB_DIRECTORIES");
+    initProp("ANDROID_NATIVE_LIB_DEPENDENCIES");
+    initProp("ANDROID_JAVA_SOURCE_DIR");
+    initProp("ANDROID_JAR_DIRECTORIES");
+    initProp("ANDROID_JAR_DEPENDENCIES");
+    initProp("ANDROID_ASSETS_DIRECTORIES");
+    initProp("ANDROID_ANT_ADDITIONAL_OPTIONS");
+    initProp("BUILD_RPATH");
+    initProp("BUILD_RPATH_USE_ORIGIN");
+    initProp("INSTALL_NAME_DIR");
+    initProp("INSTALL_REMOVE_ENVIRONMENT_RPATH");
+    initPropValue("INSTALL_RPATH", "");
+    initPropValue("INSTALL_RPATH_USE_LINK_PATH", "OFF");
+    initProp("INTERPROCEDURAL_OPTIMIZATION");
+    initPropValue("SKIP_BUILD_RPATH", "OFF");
+    initPropValue("BUILD_WITH_INSTALL_RPATH", "OFF");
+    initProp("ARCHIVE_OUTPUT_DIRECTORY");
+    initProp("LIBRARY_OUTPUT_DIRECTORY");
+    initProp("RUNTIME_OUTPUT_DIRECTORY");
+    initProp("PDB_OUTPUT_DIRECTORY");
+    initProp("COMPILE_PDB_OUTPUT_DIRECTORY");
+    initProp("FRAMEWORK");
+    initProp("Fortran_FORMAT");
+    initProp("Fortran_MODULE_DIRECTORY");
+    initProp("Fortran_COMPILER_LAUNCHER");
+    initProp("GNUtoMS");
+    initProp("OSX_ARCHITECTURES");
+    initProp("IOS_INSTALL_COMBINED");
+    initProp("AUTOMOC");
+    initProp("AUTOUIC");
+    initProp("AUTORCC");
+    initProp("AUTOGEN_ORIGIN_DEPENDS");
+    initProp("AUTOGEN_PARALLEL");
+    initProp("AUTOMOC_COMPILER_PREDEFINES");
+    initProp("AUTOMOC_DEPEND_FILTERS");
+    initProp("AUTOMOC_MACRO_NAMES");
+    initProp("AUTOMOC_MOC_OPTIONS");
+    initProp("AUTOUIC_OPTIONS");
+    initProp("AUTOUIC_SEARCH_PATHS");
+    initProp("AUTORCC_OPTIONS");
+    initProp("LINK_DEPENDS_NO_SHARED");
+    initProp("LINK_INTERFACE_LIBRARIES");
+    initProp("MSVC_RUNTIME_LIBRARY");
+    initProp("WIN32_EXECUTABLE");
+    initProp("MACOSX_BUNDLE");
+    initProp("MACOSX_RPATH");
+    initProp("NO_SYSTEM_FROM_IMPORTED");
+    initProp("BUILD_WITH_INSTALL_NAME_DIR");
+    initProp("C_CLANG_TIDY");
+    initProp("C_COMPILER_LAUNCHER");
+    initProp("C_CPPLINT");
+    initProp("C_CPPCHECK");
+    initProp("C_INCLUDE_WHAT_YOU_USE");
+    initProp("LINK_WHAT_YOU_USE");
+    initProp("C_STANDARD");
+    initProp("C_STANDARD_REQUIRED");
+    initProp("C_EXTENSIONS");
+    initProp("CXX_CLANG_TIDY");
+    initProp("CXX_COMPILER_LAUNCHER");
+    initProp("CXX_CPPLINT");
+    initProp("CXX_CPPCHECK");
+    initProp("CXX_INCLUDE_WHAT_YOU_USE");
+    initProp("CXX_STANDARD");
+    initProp("CXX_STANDARD_REQUIRED");
+    initProp("CXX_EXTENSIONS");
+    initProp("CUDA_STANDARD");
+    initProp("CUDA_STANDARD_REQUIRED");
+    initProp("CUDA_EXTENSIONS");
+    initProp("CUDA_COMPILER_LAUNCHER");
+    initProp("CUDA_SEPARABLE_COMPILATION");
+    initProp("LINK_SEARCH_START_STATIC");
+    initProp("LINK_SEARCH_END_STATIC");
+    initProp("FOLDER");
+    initProp("Swift_MODULE_DIRECTORY");
+    initProp("VS_JUST_MY_CODE_DEBUGGING");
 #ifdef __APPLE__
     if (this->GetGlobalGenerator()->IsXcode()) {
-      InitProperty("XCODE_GENERATE_SCHEME", nullptr);
-      InitProperty("XCODE_SCHEME_ADDRESS_SANITIZER", nullptr);
-      InitProperty("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN", nullptr);
-      InitProperty("XCODE_SCHEME_THREAD_SANITIZER", nullptr);
-      InitProperty("XCODE_SCHEME_THREAD_SANITIZER_STOP", nullptr);
-      InitProperty("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER", nullptr);
-      InitProperty("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP", nullptr);
-      InitProperty("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER", nullptr);
-      InitProperty("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP", nullptr);
-      InitProperty("XCODE_SCHEME_MALLOC_SCRIBBLE", nullptr);
-      InitProperty("XCODE_SCHEME_MALLOC_GUARD_EDGES", nullptr);
-      InitProperty("XCODE_SCHEME_GUARD_MALLOC", nullptr);
-      InitProperty("XCODE_SCHEME_ZOMBIE_OBJECTS", nullptr);
-      InitProperty("XCODE_SCHEME_MALLOC_STACK", nullptr);
-      InitProperty("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE", nullptr);
-      InitProperty("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS", nullptr);
+      initProp("XCODE_GENERATE_SCHEME");
+      initProp("XCODE_SCHEME_ADDRESS_SANITIZER");
+      initProp("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN");
+      initProp("XCODE_SCHEME_THREAD_SANITIZER");
+      initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP");
+      initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
+      initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
+      initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER");
+      initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP");
+      initProp("XCODE_SCHEME_MALLOC_SCRIBBLE");
+      initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES");
+      initProp("XCODE_SCHEME_GUARD_MALLOC");
+      initProp("XCODE_SCHEME_ZOMBIE_OBJECTS");
+      initProp("XCODE_SCHEME_MALLOC_STACK");
+      initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
+      initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS");
     }
 #endif
   }
@@ -377,7 +393,7 @@
         }
         std::string property = prop;
         property += configUpper;
-        InitProperty(property, nullptr);
+        initProp(property);
       }
 
       // Initialize per-configuration name postfix property from the
@@ -389,7 +405,7 @@
           impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
         std::string property = cmSystemTools::UpperCase(configName);
         property += "_POSTFIX";
-        InitProperty(property, nullptr);
+        initProp(property);
       }
     }
   }
@@ -428,16 +444,16 @@
 
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
       this->GetType() != cmStateEnums::UTILITY) {
-    InitProperty("C_VISIBILITY_PRESET", nullptr);
-    InitProperty("CXX_VISIBILITY_PRESET", nullptr);
-    InitProperty("CUDA_VISIBILITY_PRESET", nullptr);
-    InitProperty("VISIBILITY_INLINES_HIDDEN", nullptr);
+    initProp("C_VISIBILITY_PRESET");
+    initProp("CXX_VISIBILITY_PRESET");
+    initProp("CUDA_VISIBILITY_PRESET");
+    initProp("VISIBILITY_INLINES_HIDDEN");
   }
 
   if (impl->TargetType == cmStateEnums::EXECUTABLE) {
-    InitProperty("ANDROID_GUI", nullptr);
-    InitProperty("CROSSCOMPILING_EMULATOR", nullptr);
-    InitProperty("ENABLE_EXPORTS", nullptr);
+    initProp("ANDROID_GUI");
+    initProp("CROSSCOMPILING_EMULATOR");
+    initProp("ENABLE_EXPORTS");
   }
   if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
       impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
@@ -445,12 +461,12 @@
   }
   if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
       impl->TargetType == cmStateEnums::EXECUTABLE) {
-    InitProperty("WINDOWS_EXPORT_ALL_SYMBOLS", nullptr);
+    initProp("WINDOWS_EXPORT_ALL_SYMBOLS");
   }
 
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
       this->GetType() != cmStateEnums::UTILITY) {
-    InitProperty("POSITION_INDEPENDENT_CODE", nullptr);
+    initProp("POSITION_INDEPENDENT_CODE");
   }
 
   // Record current policies for later use.
@@ -466,12 +482,12 @@
 
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
       this->GetType() != cmStateEnums::UTILITY) {
-    InitProperty("JOB_POOL_COMPILE", nullptr);
-    InitProperty("JOB_POOL_LINK", nullptr);
+    initProp("JOB_POOL_COMPILE");
+    initProp("JOB_POOL_LINK");
   }
 
   if (impl->TargetType <= cmStateEnums::UTILITY) {
-    InitProperty("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr);
+    initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
   }
 
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
@@ -492,7 +508,7 @@
           if (assignment != std::string::npos) {
             const std::string propName = vsGlobal + i.substr(0, assignment);
             const std::string propValue = i.substr(assignment + 1);
-            InitProperty(propName, propValue.c_str());
+            initPropValue(propName, propValue.c_str());
           }
         }
       }
@@ -1496,7 +1512,6 @@
 
 const char* cmTarget::GetProperty(const std::string& prop) const
 {
-  static std::unordered_set<std::string> specialProps;
 #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
   MAKE_STATIC_PROP(LINK_LIBRARIES);
   MAKE_STATIC_PROP(TYPE);
@@ -1514,23 +1529,23 @@
   MAKE_STATIC_PROP(SOURCE_DIR);
   MAKE_STATIC_PROP(SOURCES);
 #undef MAKE_STATIC_PROP
-  if (specialProps.empty()) {
-    specialProps.insert(propLINK_LIBRARIES);
-    specialProps.insert(propTYPE);
-    specialProps.insert(propINCLUDE_DIRECTORIES);
-    specialProps.insert(propCOMPILE_FEATURES);
-    specialProps.insert(propCOMPILE_OPTIONS);
-    specialProps.insert(propCOMPILE_DEFINITIONS);
-    specialProps.insert(propLINK_OPTIONS);
-    specialProps.insert(propLINK_DIRECTORIES);
-    specialProps.insert(propIMPORTED);
-    specialProps.insert(propIMPORTED_GLOBAL);
-    specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES);
-    specialProps.insert(propNAME);
-    specialProps.insert(propBINARY_DIR);
-    specialProps.insert(propSOURCE_DIR);
-    specialProps.insert(propSOURCES);
-  }
+  static std::unordered_set<std::string> const specialProps{
+    propLINK_LIBRARIES,
+    propTYPE,
+    propINCLUDE_DIRECTORIES,
+    propCOMPILE_FEATURES,
+    propCOMPILE_OPTIONS,
+    propCOMPILE_DEFINITIONS,
+    propLINK_OPTIONS,
+    propLINK_DIRECTORIES,
+    propIMPORTED,
+    propIMPORTED_GLOBAL,
+    propMANUALLY_ADDED_DEPENDENCIES,
+    propNAME,
+    propBINARY_DIR,
+    propSOURCE_DIR,
+    propSOURCES
+  };
   if (specialProps.count(prop)) {
     if (prop == propLINK_LIBRARIES) {
       if (impl->LinkImplementationPropertyEntries.empty()) {
@@ -1663,6 +1678,16 @@
   return impl->Properties;
 }
 
+bool cmTarget::IsDLLPlatform() const
+{
+  return impl->IsDLLPlatform;
+}
+
+bool cmTarget::IsAIX() const
+{
+  return impl->IsAIX;
+}
+
 bool cmTarget::IsImported() const
 {
   return impl->IsImportedTarget;
@@ -1704,7 +1729,8 @@
                     ? "CMAKE_SHARED_LIBRARY_SUFFIX"
                     : "CMAKE_EXECUTABLE_SUFFIX");
         case cmStateEnums::ImportLibraryArtifact:
-          return "CMAKE_IMPORT_LIBRARY_SUFFIX";
+          return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_SUFFIX"
+                              : "CMAKE_IMPORT_LIBRARY_SUFFIX");
       }
       break;
     default:
@@ -1744,7 +1770,8 @@
                     ? "CMAKE_SHARED_LIBRARY_PREFIX"
                     : "");
         case cmStateEnums::ImportLibraryArtifact:
-          return "CMAKE_IMPORT_LIBRARY_PREFIX";
+          return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_PREFIX"
+                              : "CMAKE_IMPORT_LIBRARY_PREFIX");
       }
       break;
     default:
@@ -1878,9 +1905,10 @@
   // If we needed to find one of the mapped configurations but did not
   // On a DLL platform there may be only IMPORTED_IMPLIB for a shared
   // library or an executable with exports.
-  bool allowImp = (impl->DLLPlatform &&
+  bool allowImp = (this->IsDLLPlatform() &&
                    (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
-                    this->IsExecutableWithExports()));
+                    this->IsExecutableWithExports())) ||
+    (this->IsAIX() && this->IsExecutableWithExports());
 
   // If a mapping was found, check its configurations.
   for (std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 2bd9e6d..2b75879 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -6,7 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <string>
 #include <utility>
@@ -16,6 +16,7 @@
 #include "cmListFileCache.h"
 #include "cmPolicies.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmTargetLinkLibraryType.h"
 
 class cmCustomCommand;
@@ -181,6 +182,12 @@
   //! Get all properties
   cmPropertyMap const& GetProperties() const;
 
+  //! Return whether or not the target is for a DLL platform.
+  bool IsDLLPlatform() const;
+
+  //! Return whether or not we are targeting AIX.
+  bool IsAIX() const;
+
   bool IsImported() const;
   bool IsImportedGloballyVisible() const;
 
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index c4dc838..b64646a 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -4,9 +4,9 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmTarget.h"
 
 class cmExecutionStatus;
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index d41483a..25af21d 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmTargetPropCommandBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmTarget;
 
@@ -20,7 +22,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTargetCompileDefinitionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetCompileDefinitionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index c9e394b..976c8cb 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -4,9 +4,9 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 
 class cmExecutionStatus;
 class cmTarget;
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
index 45240a5..07948fa 100644
--- a/Source/cmTargetCompileFeaturesCommand.h
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -8,15 +8,20 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmTargetPropCommandBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmTarget;
 
 class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
 {
-  cmCommand* Clone() override { return new cmTargetCompileFeaturesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetCompileFeaturesCommand>();
+  }
 
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 8b4763a..7dadb82 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -4,10 +4,10 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmTarget.h"
 
 class cmExecutionStatus;
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index 6fb151a..a571cfb 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmTargetPropCommandBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmTarget;
 
@@ -20,7 +22,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTargetCompileOptionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetCompileOptionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index 5ea0085..4ca78fa 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -31,7 +31,7 @@
   operator cmGeneratorTarget const*() const { return this->Target; }
   cmGeneratorTarget const* operator->() const { return this->Target; }
   cmGeneratorTarget const& operator*() const { return *this->Target; }
-  friend bool operator<(cmTargetDepend l, cmTargetDepend r)
+  friend bool operator<(cmTargetDepend const& l, cmTargetDepend const& r)
   {
     return l.Target < r.Target;
   }
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index 57bf8fc..6defab2 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmTargetPropCommandBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmTarget;
 
@@ -20,7 +22,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTargetIncludeDirectoriesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetIncludeDirectoriesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx
index 269f751..435c392 100644
--- a/Source/cmTargetLinkDirectoriesCommand.cxx
+++ b/Source/cmTargetLinkDirectoriesCommand.cxx
@@ -4,11 +4,11 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
diff --git a/Source/cmTargetLinkDirectoriesCommand.h b/Source/cmTargetLinkDirectoriesCommand.h
index 52c75a0..a2fcfa9 100644
--- a/Source/cmTargetLinkDirectoriesCommand.h
+++ b/Source/cmTargetLinkDirectoriesCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmTargetPropCommandBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmTarget;
 
@@ -20,7 +22,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTargetLinkDirectoriesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetLinkDirectoriesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index 54f8cf4..6698ce0 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 #include "cmTargetLinkLibraryType.h"
 
@@ -30,7 +32,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTargetLinkLibrariesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetLinkLibrariesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx
index 5366486..2866cf1 100644
--- a/Source/cmTargetLinkOptionsCommand.cxx
+++ b/Source/cmTargetLinkOptionsCommand.cxx
@@ -4,10 +4,10 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmListFileCache.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmTarget.h"
 
 class cmExecutionStatus;
diff --git a/Source/cmTargetLinkOptionsCommand.h b/Source/cmTargetLinkOptionsCommand.h
index a1fc9fc..3710739 100644
--- a/Source/cmTargetLinkOptionsCommand.h
+++ b/Source/cmTargetLinkOptionsCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmTargetPropCommandBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmTarget;
 
@@ -20,7 +22,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTargetLinkOptionsCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetLinkOptionsCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 1b8ee81..3aa845c 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -32,12 +32,13 @@
     this->HandleMissingTarget(args[0]);
     return false;
   }
-  if ((this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
+  if ((this->Target->GetType() != cmStateEnums::EXECUTABLE) &&
       (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) &&
-      (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
+      (this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
       (this->Target->GetType() != cmStateEnums::MODULE_LIBRARY) &&
+      (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
       (this->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
-      (this->Target->GetType() != cmStateEnums::EXECUTABLE)) {
+      (this->Target->GetType() != cmStateEnums::UNKNOWN_LIBRARY)) {
     this->SetError("called with non-compilable target type");
     return false;
   }
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index 3f763af..baab8da 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -11,6 +11,7 @@
 #include "cmMessenger.h"
 #include "cmPolicies.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 
 bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
   std::string const& tgtName, cmMessenger* messenger,
@@ -56,22 +57,21 @@
   if (std::islower(prop[0])) {
     return true;
   }
-  static std::unordered_set<std::string> builtIns;
-  if (builtIns.empty()) {
-    builtIns.insert("COMPATIBLE_INTERFACE_BOOL");
-    builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MAX");
-    builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MIN");
-    builtIns.insert("COMPATIBLE_INTERFACE_STRING");
-    builtIns.insert("EXPORT_NAME");
-    builtIns.insert("EXPORT_PROPERTIES");
-    builtIns.insert("IMPORTED");
-    builtIns.insert("IMPORTED_GLOBAL");
-    builtIns.insert("MANUALLY_ADDED_DEPENDENCIES");
-    builtIns.insert("NAME");
-    builtIns.insert("PRIVATE_HEADER");
-    builtIns.insert("PUBLIC_HEADER");
-    builtIns.insert("TYPE");
-  }
+  static std::unordered_set<std::string> const builtIns{
+    "COMPATIBLE_INTERFACE_BOOL",
+    "COMPATIBLE_INTERFACE_NUMBER_MAX",
+    "COMPATIBLE_INTERFACE_NUMBER_MIN",
+    "COMPATIBLE_INTERFACE_STRING",
+    "EXPORT_NAME",
+    "EXPORT_PROPERTIES",
+    "IMPORTED",
+    "IMPORTED_GLOBAL",
+    "MANUALLY_ADDED_DEPENDENCIES",
+    "NAME",
+    "PRIVATE_HEADER",
+    "PUBLIC_HEADER",
+    "TYPE"
+  };
 
   if (builtIns.count(prop)) {
     return true;
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index efbf95f..3b11acd 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -7,9 +7,9 @@
 
 #include <string>
 
-#include "cmAlgorithms.h"
 #include "cmListFileCache.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmMessenger;
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 11e288f..eb5f37c 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -4,11 +4,11 @@
 
 #include <sstream>
 
-#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h
index b01e3ca..90fd45f 100644
--- a/Source/cmTargetSourcesCommand.h
+++ b/Source/cmTargetSourcesCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmTargetPropCommandBase.h"
 
-class cmCommand;
 class cmExecutionStatus;
 class cmTarget;
 
@@ -20,7 +22,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTargetSourcesCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTargetSourcesCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index 7d45cf5..01f2b96 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -8,7 +8,8 @@
 #include "cmSystemTools.h"
 
 cmTest::cmTest(cmMakefile* mf)
-  : Backtrace(mf->GetBacktrace())
+  : CommandExpandLists(false)
+  , Backtrace(mf->GetBacktrace())
 {
   this->Makefile = mf;
   this->OldStyle = true;
@@ -59,3 +60,13 @@
 {
   this->Properties.AppendProperty(prop, value, asString);
 }
+
+bool cmTest::GetCommandExpandLists() const
+{
+  return this->CommandExpandLists;
+}
+
+void cmTest::SetCommandExpandLists(bool b)
+{
+  this->CommandExpandLists = b;
+}
diff --git a/Source/cmTest.h b/Source/cmTest.h
index 88dc730..02d8f46 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -51,10 +51,15 @@
   bool GetOldStyle() const { return this->OldStyle; }
   void SetOldStyle(bool b) { this->OldStyle = b; }
 
+  /** Set/Get whether lists in command lines should be expanded. */
+  bool GetCommandExpandLists() const;
+  void SetCommandExpandLists(bool b);
+
 private:
   cmPropertyMap Properties;
   std::string Name;
   std::vector<std::string> Command;
+  bool CommandExpandLists;
 
   bool OldStyle;
 
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 571cd09..916784c 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -2,15 +2,16 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmTestGenerator.h"
 
+#include <memory>
 #include <ostream>
 #include <utility>
+#include <vector>
 
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmListFileCache.h"
 #include "cmLocalGenerator.h"
 #include "cmOutputConverter.h"
-#include "cmProperty.h"
 #include "cmPropertyMap.h"
 #include "cmRange.h"
 #include "cmStateTypes.h"
@@ -76,12 +77,22 @@
   // Start the test command.
   os << indent << "add_test(" << this->Test->GetName() << " ";
 
-  // Get the test command line to be executed.
-  std::vector<std::string> const& command = this->Test->GetCommand();
+  // Evaluate command line arguments
+  std::vector<std::string> argv =
+    EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config);
+
+  // Expand arguments if COMMAND_EXPAND_LISTS is set
+  if (this->Test->GetCommandExpandLists()) {
+    argv = cmSystemTools::ExpandedLists(argv.begin(), argv.end());
+    // Expanding lists on an empty command may have left it empty
+    if (argv.empty()) {
+      argv.emplace_back();
+    }
+  }
 
   // Check whether the command executable is a target whose name is to
   // be translated.
-  std::string exe = command[0];
+  std::string exe = argv[0];
   cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(exe);
   if (target && target->GetType() == cmStateEnums::EXECUTABLE) {
     // Use the target file on disk.
@@ -101,29 +112,26 @@
     }
   } else {
     // Use the command name given.
-    exe = ge.Parse(exe)->Evaluate(this->LG, config);
     cmSystemTools::ConvertToUnixSlashes(exe);
   }
 
   // Generate the command line with full escapes.
   os << cmOutputConverter::EscapeForCMake(exe);
-  for (std::string const& arg : cmMakeRange(command).advance(1)) {
-    os << " "
-       << cmOutputConverter::EscapeForCMake(
-            ge.Parse(arg)->Evaluate(this->LG, config));
+
+  for (auto const& arg : cmMakeRange(argv).advance(1)) {
+    os << " " << cmOutputConverter::EscapeForCMake(arg);
   }
 
   // Finish the test command.
   os << ")\n";
 
   // Output properties for the test.
-  cmPropertyMap& pm = this->Test->GetProperties();
   os << indent << "set_tests_properties(" << this->Test->GetName()
      << " PROPERTIES ";
-  for (auto const& i : pm) {
+  for (auto const& i : this->Test->GetProperties().GetList()) {
     os << " " << i.first << " "
        << cmOutputConverter::EscapeForCMake(
-            ge.Parse(i.second.GetValue())->Evaluate(this->LG, config));
+            ge.Parse(i.second)->Evaluate(this->LG, config));
   }
   this->GenerateInternalProperties(os);
   os << ")" << std::endl;
@@ -173,12 +181,11 @@
   fout << ")" << std::endl;
 
   // Output properties for the test.
-  cmPropertyMap& pm = this->Test->GetProperties();
   fout << indent << "set_tests_properties(" << this->Test->GetName()
        << " PROPERTIES ";
-  for (auto const& i : pm) {
+  for (auto const& i : this->Test->GetProperties().GetList()) {
     fout << " " << i.first << " "
-         << cmOutputConverter::EscapeForCMake(i.second.GetValue());
+         << cmOutputConverter::EscapeForCMake(i.second);
   }
   this->GenerateInternalProperties(fout);
   fout << ")" << std::endl;
@@ -208,3 +215,16 @@
 
   os << "\"";
 }
+
+std::vector<std::string> cmTestGenerator::EvaluateCommandLineArguments(
+  const std::vector<std::string>& argv, cmGeneratorExpression& ge,
+  const std::string& config) const
+{
+  // Evaluate executable name and arguments
+  auto evaluatedRange =
+    cmMakeRange(argv).transform([&](const std::string& arg) {
+      return ge.Parse(arg)->Evaluate(this->LG, config);
+    });
+
+  return { evaluatedRange.begin(), evaluatedRange.end() };
+}
diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h
index 8b9cf78..7ac68eb 100644
--- a/Source/cmTestGenerator.h
+++ b/Source/cmTestGenerator.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+class cmGeneratorExpression;
 class cmLocalGenerator;
 class cmTest;
 
@@ -38,6 +39,9 @@
 
 private:
   void GenerateInternalProperties(std::ostream& os);
+  std::vector<std::string> EvaluateCommandLineArguments(
+    const std::vector<std::string>& argv, cmGeneratorExpression& ge,
+    const std::string& config) const;
 
 protected:
   void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index 8237878..ec9f8b8 100644
--- a/Source/cmTryCompileCommand.h
+++ b/Source/cmTryCompileCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmCoreTryCompile.h"
 
-class cmCommand;
 class cmExecutionStatus;
 
 /** \class cmTryCompileCommand
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTryCompileCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTryCompileCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index a92c2a0..ed944ac 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -137,7 +137,7 @@
       // now put the output into the variables
       if (!this->RunOutputVariable.empty()) {
         this->Makefile->AddDefinition(this->RunOutputVariable,
-                                      runOutputContents.c_str());
+                                      runOutputContents);
       }
 
       if (!this->OutputVariable.empty()) {
@@ -148,8 +148,7 @@
         if (compileOutput) {
           runOutputContents = compileOutput + runOutputContents;
         }
-        this->Makefile->AddDefinition(this->OutputVariable,
-                                      runOutputContents.c_str());
+        this->Makefile->AddDefinition(this->OutputVariable, runOutputContents);
       }
     }
   }
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index c54622c..bacfcdb 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -8,9 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
+#include "cmCommand.h"
 #include "cmCoreTryCompile.h"
 
-class cmCommand;
 class cmExecutionStatus;
 
 /** \class cmTryRunCommand
@@ -24,7 +26,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmTryRunCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmTryRunCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx
index 90ece0b..56d6c09 100644
--- a/Source/cmUVProcessChain.cxx
+++ b/Source/cmUVProcessChain.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmUVProcessChain.h"
 
-#include "cmAlgorithms.h"
 #include "cmGetPipes.h"
 #include "cmUVHandlePtr.h"
 #include "cmUVStreambuf.h"
@@ -10,10 +9,12 @@
 
 #include <assert.h>
 
+#include <istream> // IWYU pragma: keep
 #include <iterator>
-#include <memory>
 #include <utility>
 
+#include "cm_memory.hxx"
+
 struct cmUVProcessChain::InternalData
 {
   struct BasicStreamData
diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h
index 2b33520..75f8f66 100644
--- a/Source/cmUVProcessChain.h
+++ b/Source/cmUVProcessChain.h
@@ -7,7 +7,7 @@
 
 #include <array>
 #include <iosfwd>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/Source/cmUnexpectedCommand.cxx b/Source/cmUnexpectedCommand.cxx
deleted file mode 100644
index a8de9e6..0000000
--- a/Source/cmUnexpectedCommand.cxx
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmUnexpectedCommand.h"
-
-#include <stdlib.h>
-
-#include "cmMakefile.h"
-
-class cmExecutionStatus;
-
-bool cmUnexpectedCommand::InitialPass(std::vector<std::string> const&,
-                                      cmExecutionStatus&)
-{
-  const char* versionValue =
-    this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
-  if (this->Name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) {
-    return true;
-  }
-
-  this->SetError(this->Error);
-  return false;
-}
diff --git a/Source/cmUnexpectedCommand.h b/Source/cmUnexpectedCommand.h
deleted file mode 100644
index 33d6bdc..0000000
--- a/Source/cmUnexpectedCommand.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmUnexpectedCommand_h
-#define cmUnexpectedCommand_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "cmCommand.h"
-
-class cmExecutionStatus;
-
-class cmUnexpectedCommand : public cmCommand
-{
-public:
-  cmUnexpectedCommand(std::string name, const char* error)
-    : Name(std::move(name))
-    , Error(error)
-  {
-  }
-
-  cmCommand* Clone() override
-  {
-    return new cmUnexpectedCommand(this->Name, this->Error);
-  }
-
-  bool InitialPass(std::vector<std::string> const& args,
-                   cmExecutionStatus& status) override;
-
-private:
-  std::string Name;
-  const char* Error;
-};
-
-#endif
diff --git a/Source/cmUnsetCommand.cxx b/Source/cmUnsetCommand.cxx
index cfaa1fd2..0e903c7 100644
--- a/Source/cmUnsetCommand.cxx
+++ b/Source/cmUnsetCommand.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmUnsetCommand.h"
 
-#include "cmAlgorithms.h"
 #include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
diff --git a/Source/cmUnsetCommand.h b/Source/cmUnsetCommand.h
index 4e1208a..9b78d44 100644
--- a/Source/cmUnsetCommand.h
+++ b/Source/cmUnsetCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,7 +25,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmUnsetCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmUnsetCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h
index e2f1d9b..1c01596 100644
--- a/Source/cmUseMangledMesaCommand.h
+++ b/Source/cmUseMangledMesaCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmUseMangledMesaCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmUseMangledMesaCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmUseMangledMesaCommand>();
+  }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 
diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h
index 165ecef..cef7fed 100644
--- a/Source/cmUtilitySourceCommand.h
+++ b/Source/cmUtilitySourceCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmUtilitySourceCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmUtilitySourceCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmUtilitySourceCommand>();
+  }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 };
diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx
index c02157a..9878ff1 100644
--- a/Source/cmVariableRequiresCommand.cxx
+++ b/Source/cmVariableRequiresCommand.cxx
@@ -42,7 +42,7 @@
   // if reqVar is set to true, but requirementsMet is false , then
   // set reqVar to false.
   if (!reqVar || (!requirementsMet && this->Makefile->IsOn(reqVar))) {
-    this->Makefile->AddDefinition(resultVariable, requirementsMet);
+    this->Makefile->AddDefinitionBool(resultVariable, requirementsMet);
   }
 
   if (!requirementsMet) {
diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h
index 94970c5..38e7490 100644
--- a/Source/cmVariableRequiresCommand.h
+++ b/Source/cmVariableRequiresCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -15,7 +17,10 @@
 class cmVariableRequiresCommand : public cmCommand
 {
 public:
-  cmCommand* Clone() override { return new cmVariableRequiresCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmVariableRequiresCommand>();
+  }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
 };
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 1230101..acac2c1 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -6,7 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 5fe55bd..83a774d 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -3,6 +3,7 @@
 #include "cmVariableWatchCommand.h"
 
 #include <sstream>
+#include <utility>
 
 #include "cmExecutionStatus.h"
 #include "cmListFileCache.h"
@@ -54,7 +55,7 @@
     newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999);
     newLFF.Name = data->Command;
     newLFF.Line = 9999;
-    cmExecutionStatus status;
+    cmExecutionStatus status(*makefile);
     if (!makefile->ExecuteCommand(newLFF, status)) {
       std::ostringstream error;
       error << "Error in cmake code at\nUnknown:0:\n"
@@ -84,15 +85,39 @@
   delete data;
 }
 
-cmVariableWatchCommand::cmVariableWatchCommand() = default;
-
-cmVariableWatchCommand::~cmVariableWatchCommand()
+/** This command does not really have a final pass but it needs to
+    stay alive since it owns variable watch callback information. */
+class FinalAction
 {
-  for (std::string const& wv : this->WatchedVariables) {
-    this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
-      wv, cmVariableWatchCommandVariableAccessed);
+public:
+  FinalAction(cmMakefile* makefile, std::string variable)
+    : Action(std::make_shared<Impl>(makefile, std::move(variable)))
+  {
   }
-}
+
+  void operator()(cmMakefile&) const {}
+
+private:
+  struct Impl
+  {
+    Impl(cmMakefile* makefile, std::string variable)
+      : Makefile(makefile)
+      , Variable(std::move(variable))
+    {
+    }
+
+    ~Impl()
+    {
+      this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
+        this->Variable, cmVariableWatchCommandVariableAccessed);
+    }
+
+    cmMakefile* Makefile;
+    std::string Variable;
+  };
+
+  std::shared_ptr<Impl const> Action;
+};
 
 bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
                                          cmExecutionStatus&)
@@ -118,7 +143,6 @@
   data->InCallback = false;
   data->Command = command;
 
-  this->WatchedVariables.insert(variable);
   if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
         variable, cmVariableWatchCommandVariableAccessed, data,
         deleteVariableWatchCallbackData)) {
@@ -126,5 +150,6 @@
     return false;
   }
 
+  this->Makefile->AddFinalAction(FinalAction(this->Makefile, variable));
   return true;
 }
diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h
index 6a8115d..221269f 100644
--- a/Source/cmVariableWatchCommand.h
+++ b/Source/cmVariableWatchCommand.h
@@ -5,10 +5,11 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <set>
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -23,13 +24,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmVariableWatchCommand; }
-
-  //! Default constructor
-  cmVariableWatchCommand();
-
-  //! Destructor.
-  ~cmVariableWatchCommand() override;
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmVariableWatchCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
@@ -37,13 +35,6 @@
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) override;
-
-  /** This command does not really have a final pass but it needs to
-      stay alive since it owns variable watch callback information. */
-  bool HasFinalPass() const override { return true; }
-
-protected:
-  std::set<std::string> WatchedVariables;
 };
 
 #endif
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 8c6ba4e..ed6e4d9 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -19,9 +19,10 @@
 #include "windows.h"
 
 #include <iterator>
-#include <memory> // IWYU pragma: keep
 #include <set>
 
+#include "cm_memory.hxx"
+
 static void ConvertToWindowsSlash(std::string& s);
 
 static std::string cmVS10EscapeXML(std::string arg)
@@ -505,6 +506,11 @@
         if (targetFrameworkVersion) {
           e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
         }
+        if (this->ProjectType == vcxproj &&
+            this->GlobalGenerator->TargetsWindowsCE()) {
+          e1.Element("EnableRedirectPlatform", "true");
+          e1.Element("RedirectPlatformValue", this->Platform);
+        }
         if (this->ProjectType == csproj &&
             this->GlobalGenerator->TargetsWindowsCE()) {
           const char* targetFrameworkId = this->GeneratorTarget->GetProperty(
@@ -774,11 +780,11 @@
     cmSystemTools::ExpandListArgument(vsDotNetReferences, references);
   }
   cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
-  for (auto const& i : props) {
+  for (auto const& i : props.GetList()) {
     if (i.first.find("VS_DOTNET_REFERENCE_") == 0) {
       std::string name = i.first.substr(20);
       if (!name.empty()) {
-        std::string path = i.second.GetValue();
+        std::string path = i.second;
         if (!cmsys::SystemTools::FileIsFullPath(path)) {
           path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
         }
@@ -870,10 +876,10 @@
   typedef std::map<std::string, std::string> CustomTags;
   CustomTags tags;
   cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
-  for (const auto& i : props) {
+  for (const auto& i : props.GetList()) {
     if (i.first.find(refPropFullPrefix) == 0) {
       std::string refTag = i.first.substr(refPropFullPrefix.length());
-      std::string refVal = i.second.GetValue();
+      std::string refVal = i.second;
       if (!refTag.empty() && !refVal.empty()) {
         tags[refTag] = refVal;
       }
@@ -967,12 +973,12 @@
           }
         }
         const cmPropertyMap& props = oi->GetProperties();
-        for (const auto& p : props) {
+        for (const std::string& p : props.GetKeys()) {
           static const std::string propNamePrefix = "VS_CSHARP_";
-          if (p.first.find(propNamePrefix) == 0) {
-            std::string tagName = p.first.substr(propNamePrefix.length());
+          if (p.find(propNamePrefix) == 0) {
+            std::string tagName = p.substr(propNamePrefix.length());
             if (!tagName.empty()) {
-              std::string value = props.GetPropertyValue(p.first);
+              std::string value = props.GetPropertyValue(p);
               if (!value.empty()) {
                 e2.Element(tagName.c_str(), value);
               }
@@ -1229,8 +1235,11 @@
   if (this->IPOEnabledConfigurations.count(config) > 0) {
     e1.Element("WholeProgramOptimization", "true");
   }
-  if (this->SpectreMitigationConfigurations.count(config) > 0) {
-    e1.Element("SpectreMitigation", "Spectre");
+  {
+    auto s = this->SpectreMitigation.find(config);
+    if (s != this->SpectreMitigation.end()) {
+      e1.Element("SpectreMitigation", s->second);
+    }
   }
 }
 
@@ -2760,8 +2769,8 @@
     }
   }
 
-  if (clOptions.HasFlag("SpectreMitigation")) {
-    this->SpectreMitigationConfigurations.insert(configName);
+  if (const char* s = clOptions.GetFlag("SpectreMitigation")) {
+    this->SpectreMitigation[configName] = s;
     clOptions.RemoveFlag("SpectreMitigation");
   }
 
@@ -3247,15 +3256,32 @@
 
   std::vector<cmSourceFile const*> manifest_srcs;
   this->GeneratorTarget->GetManifests(manifest_srcs, config);
-  if (!manifest_srcs.empty()) {
-    std::ostringstream oss;
-    for (cmSourceFile const* mi : manifest_srcs) {
-      std::string m = this->ConvertPath(mi->GetFullPath(), false);
-      ConvertToWindowsSlash(m);
-      oss << m << ";";
-    }
+
+  const char* dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE");
+
+  if (!manifest_srcs.empty() || dpiAware) {
     Elem e2(e1, "Manifest");
-    e2.Element("AdditionalManifestFiles", oss.str());
+    if (!manifest_srcs.empty()) {
+      std::ostringstream oss;
+      for (cmSourceFile const* mi : manifest_srcs) {
+        std::string m = this->ConvertPath(mi->GetFullPath(), false);
+        ConvertToWindowsSlash(m);
+        oss << m << ";";
+      }
+      e2.Element("AdditionalManifestFiles", oss.str());
+    }
+    if (dpiAware) {
+      if (!strcmp(dpiAware, "PerMonitor")) {
+        e2.Element("EnableDpiAwareness", "PerMonitorHighDPIAware");
+      } else if (cmSystemTools::IsOn(dpiAware)) {
+        e2.Element("EnableDpiAwareness", "true");
+      } else if (cmSystemTools::IsOff(dpiAware)) {
+        e2.Element("EnableDpiAwareness", "false");
+      } else {
+        cmSystemTools::Error("Bad parameter for VS_DPI_AWARE: " +
+                             std::string(dpiAware));
+      }
+    }
   }
 }
 
@@ -4676,12 +4702,12 @@
 {
   if (this->ProjectType == csproj) {
     const cmPropertyMap& props = sf->GetProperties();
-    for (auto const& p : props) {
+    for (const std::string& p : props.GetKeys()) {
       static const std::string propNamePrefix = "VS_CSHARP_";
-      if (p.first.find(propNamePrefix) == 0) {
-        std::string tagName = p.first.substr(propNamePrefix.length());
+      if (p.find(propNamePrefix) == 0) {
+        std::string tagName = p.substr(propNamePrefix.length());
         if (!tagName.empty()) {
-          const std::string val = props.GetPropertyValue(p.first);
+          const std::string val = props.GetPropertyValue(p);
           if (!val.empty()) {
             tags[tagName] = val;
           } else {
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 860b809..6607e77 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -215,7 +215,7 @@
   unsigned int NsightTegraVersion[4];
   bool TargetCompileAsWinRT;
   std::set<std::string> IPOEnabledConfigurations;
-  std::set<std::string> SpectreMitigationConfigurations;
+  std::map<std::string, std::string> SpectreMitigation;
   cmGlobalVisualStudio10Generator* const GlobalGenerator;
   cmLocalVisualStudio10Generator* const LocalGenerator;
   std::set<std::string> CSharpCustomCommandNames;
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
index 9353276..3e7e142 100644
--- a/Source/cmVisualStudioSlnParser.cxx
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmVisualStudioSlnParser.h"
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVisualStudioSlnData.h"
 #include "cmsys/FStream.hxx"
@@ -192,8 +193,8 @@
   assert(!line.IsComment());
   switch (this->Stack.top()) {
     case FileStateStart:
-      if (!cmSystemTools::StringStartsWith(
-            line.GetTag().c_str(), "Microsoft Visual Studio Solution File")) {
+      if (!cmHasLiteralPrefix(line.GetTag(),
+                              "Microsoft Visual Studio Solution File")) {
         result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
         return false;
       }
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index a01fa6f..37d1c74 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmWhileCommand.h"
 
+#include "cm_memory.hxx"
+
 #include "cmConditionEvaluator.h"
 #include "cmExecutionStatus.h"
 #include "cmExpandedCommandArgument.h"
@@ -9,7 +11,8 @@
 #include "cmMessageType.h"
 #include "cmSystemTools.h"
 
-#include <memory> // IWYU pragma: keep
+#include <string>
+#include <utility>
 
 cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
   : Makefile(mf)
@@ -80,7 +83,7 @@
 
         // Invoke all the functions that were collected in the block.
         for (cmListFileFunction const& fn : this->Functions) {
-          cmExecutionStatus status;
+          cmExecutionStatus status(mf);
           mf.ExecuteCommand(fn, status);
           if (status.GetReturnInvoked()) {
             inStatus.SetReturnInvoked();
@@ -127,18 +130,20 @@
   return false;
 }
 
-bool cmWhileCommand::InvokeInitialPass(
-  const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
+bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
+                    cmExecutionStatus& status)
 {
   if (args.empty()) {
-    this->SetError("called with incorrect number of arguments");
+    status.SetError("called with incorrect number of arguments");
     return false;
   }
 
   // create a function blocker
-  cmWhileFunctionBlocker* f = new cmWhileFunctionBlocker(this->Makefile);
-  f->Args = args;
-  this->Makefile->AddFunctionBlocker(f);
-
+  {
+    cmMakefile& makefile = status.GetMakefile();
+    auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile);
+    fb->Args = args;
+    makefile.AddFunctionBlocker(std::move(fb));
+  }
   return true;
 }
diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h
index 6f6d405..2257799 100644
--- a/Source/cmWhileCommand.h
+++ b/Source/cmWhileCommand.h
@@ -5,10 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
 #include <vector>
 
-#include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmListFileCache.h"
 
@@ -33,30 +31,7 @@
 };
 
 /// \brief Starts a while loop
-class cmWhileCommand : public cmCommand
-{
-public:
-  /**
-   * This is a virtual constructor for the command.
-   */
-  cmCommand* Clone() override { return new cmWhileCommand; }
-
-  /**
-   * This overrides the default InvokeInitialPass implementation.
-   * It records the arguments before expansion.
-   */
-  bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
-                         cmExecutionStatus&) override;
-
-  /**
-   * This is called when the command is first encountered in
-   * the CMakeLists.txt file.
-   */
-  bool InitialPass(std::vector<std::string> const&,
-                   cmExecutionStatus&) override
-  {
-    return false;
-  }
-};
+bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
+                    cmExecutionStatus& status);
 
 #endif
diff --git a/Source/cmWorkerPool.cxx b/Source/cmWorkerPool.cxx
index cbf070e..974100b 100644
--- a/Source/cmWorkerPool.cxx
+++ b/Source/cmWorkerPool.cxx
@@ -16,6 +16,8 @@
 #include <stddef.h>
 #include <thread>
 
+#include "cm_memory.hxx"
+
 /**
  * @brief libuv pipe buffer class
  */
diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h
index f08bb4f..d708118 100644
--- a/Source/cmWorkerPool.h
+++ b/Source/cmWorkerPool.h
@@ -5,14 +5,13 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include "cmAlgorithms.h" // IWYU pragma: keep
-
-#include <memory> // IWYU pragma: keep
 #include <stdint.h>
 #include <string>
 #include <utility>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 // -- Types
 class cmWorkerPoolInternal;
 
diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h
index 9028f84..3961898 100644
--- a/Source/cmWriteFileCommand.h
+++ b/Source/cmWriteFileCommand.h
@@ -8,6 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "cm_memory.hxx"
+
 #include "cmCommand.h"
 
 class cmExecutionStatus;
@@ -22,7 +24,10 @@
   /**
    * This is a virtual constructor for the command.
    */
-  cmCommand* Clone() override { return new cmWriteFileCommand; }
+  std::unique_ptr<cmCommand> Clone() override
+  {
+    return cm::make_unique<cmWriteFileCommand>();
+  }
 
   /**
    * This is called when the command is first encountered in
diff --git a/Source/cm_memory.hxx b/Source/cm_memory.hxx
new file mode 100644
index 0000000..9f5e678
--- /dev/null
+++ b/Source/cm_memory.hxx
@@ -0,0 +1,31 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cm_memory_hxx
+#define cm_memory_hxx
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <memory> // IWYU pragma: export
+#if !defined(CMake_HAVE_CXX_MAKE_UNIQUE)
+#  include <utility>
+#endif
+
+namespace cm {
+
+#if defined(CMake_HAVE_CXX_MAKE_UNIQUE)
+
+using std::make_unique;
+
+#else
+
+template <typename T, typename... Args>
+std::unique_ptr<T> make_unique(Args&&... args)
+{
+  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 3772f09..309efd3 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmake.h"
 
+#include "cm_memory.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmCommands.h"
 #include "cmDocumentation.h"
@@ -19,6 +21,7 @@
 #include "cmMessenger.h"
 #include "cmState.h"
 #include "cmStateDirectory.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetLinkLibraryType.h"
@@ -104,8 +107,6 @@
 #include <cstring>
 #include <initializer_list>
 #include <iostream>
-#include <iterator>
-#include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -122,9 +123,9 @@
 static bool cmakeCheckStampFile(const std::string& stampName);
 static bool cmakeCheckStampList(const std::string& stampList);
 
-void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
-                            void* ctx, const char* /*unused*/,
-                            const cmMakefile* /*unused*/)
+static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
+                                   void* ctx, const char* /*unused*/,
+                                   const cmMakefile* /*unused*/)
 {
   cmake* cm = reinterpret_cast<cmake*>(ctx);
   cm->MarkCliAsUsed(variable);
@@ -141,12 +142,12 @@
   this->DebugOutput = false;
   this->DebugTryCompile = false;
   this->ClearBuildSystem = false;
-  this->FileTimeCache = new cmFileTimeCache;
+  this->FileTimeCache = cm::make_unique<cmFileTimeCache>();
 
-  this->State = new cmState;
+  this->State = cm::make_unique<cmState>();
   this->State->SetMode(mode);
   this->CurrentSnapshot = this->State->CreateBaseSnapshot();
-  this->Messenger = new cmMessenger;
+  this->Messenger = cm::make_unique<cmMessenger>();
 
 #ifdef __APPLE__
   struct rlimit rlp;
@@ -165,7 +166,7 @@
   this->CurrentWorkingMode = NORMAL_MODE;
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
-  this->VariableWatch = new cmVariableWatch;
+  this->VariableWatch = cm::make_unique<cmVariableWatch>();
 #endif
 
   this->AddDefaultGenerators();
@@ -184,55 +185,45 @@
   // Make sure we can capture the build tool output.
   cmSystemTools::EnableVSConsoleOutput();
 
-  // Set up a list of source and header extensions
-  // these are used to find files when the extension
-  // is not given
-  // The "c" extension MUST precede the "C" extension.
-  this->SourceFileExtensions.emplace_back("c");
-  this->SourceFileExtensions.emplace_back("C");
+  // Set up a list of source and header extensions.
+  // These are used to find files when the extension is not given.
+  {
+    auto fillExts = [](FileExtensions& exts,
+                       std::initializer_list<const char*> extList) {
+      // Fill ordered vector
+      exts.ordered.reserve(extList.size());
+      for (const char* ext : extList) {
+        exts.ordered.emplace_back(ext);
+      };
+      // Fill unordered set
+      exts.unordered.insert(exts.ordered.begin(), exts.ordered.end());
+    };
 
-  this->SourceFileExtensions.emplace_back("c++");
-  this->SourceFileExtensions.emplace_back("cc");
-  this->SourceFileExtensions.emplace_back("cpp");
-  this->SourceFileExtensions.emplace_back("cxx");
-  this->SourceFileExtensions.emplace_back("cu");
-  this->SourceFileExtensions.emplace_back("m");
-  this->SourceFileExtensions.emplace_back("M");
-  this->SourceFileExtensions.emplace_back("mm");
+    // Source extensions
+    // The "c" extension MUST precede the "C" extension.
+    fillExts(this->SourceFileExtensions,
+             { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" });
 
-  std::copy(this->SourceFileExtensions.begin(),
-            this->SourceFileExtensions.end(),
-            std::inserter(this->SourceFileExtensionsSet,
-                          this->SourceFileExtensionsSet.end()));
+    // Header extensions
+    fillExts(this->HeaderFileExtensions,
+             { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" });
 
-  this->HeaderFileExtensions.emplace_back("h");
-  this->HeaderFileExtensions.emplace_back("hh");
-  this->HeaderFileExtensions.emplace_back("h++");
-  this->HeaderFileExtensions.emplace_back("hm");
-  this->HeaderFileExtensions.emplace_back("hpp");
-  this->HeaderFileExtensions.emplace_back("hxx");
-  this->HeaderFileExtensions.emplace_back("in");
-  this->HeaderFileExtensions.emplace_back("txx");
+    // Cuda extensions
+    fillExts(this->CudaFileExtensions, { "cu" });
 
-  std::copy(this->HeaderFileExtensions.begin(),
-            this->HeaderFileExtensions.end(),
-            std::inserter(this->HeaderFileExtensionsSet,
-                          this->HeaderFileExtensionsSet.end()));
+    // Fortran extensions
+    fillExts(this->FortranFileExtensions,
+             { "f", "F", "for", "f77", "f90", "f95", "f03" });
+  }
 }
 
 cmake::~cmake()
 {
-  delete this->State;
-  delete this->Messenger;
   if (this->GlobalGenerator) {
     delete this->GlobalGenerator;
     this->GlobalGenerator = nullptr;
   }
   cmDeleteAll(this->Generators);
-#ifdef CMAKE_BUILD_WITH_CMAKE
-  delete this->VariableWatch;
-#endif
-  delete this->FileTimeCache;
 }
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -460,7 +451,7 @@
         return false;
       }
       // Register fake project commands that hint misuse in script mode.
-      GetProjectCommandsInScriptMode(this->State);
+      GetProjectCommandsInScriptMode(this->GetState());
       this->ReadListFile(args, path);
     } else if (arg.find("--find-package", 0) == 0) {
       findPackageMode = true;
@@ -629,7 +620,7 @@
     this->EnvironmentGenerator = envGenVar;
   }
 
-  auto readGeneratorVar = [&](std::string name, std::string& key) {
+  auto readGeneratorVar = [&](std::string const& name, std::string& key) {
     std::string varValue;
     if (cmSystemTools::GetEnv(name, varValue)) {
       if (hasEnvironmentGenerator) {
@@ -1898,12 +1889,12 @@
 
 void cmake::AddScriptingCommands()
 {
-  GetScriptingCommands(this->State);
+  GetScriptingCommands(this->GetState());
 }
 
 void cmake::AddProjectCommands()
 {
-  GetProjectCommands(this->State);
+  GetProjectCommands(this->GetState());
 }
 
 void cmake::AddDefaultGenerators()
@@ -2040,8 +2031,7 @@
   for (cmGlobalGeneratorFactory* g : this->Generators) {
     cmDocumentationEntry e;
     g->GetDocumentation(e);
-    if (!foundDefaultOne &&
-        cmSystemTools::StringStartsWith(e.Name, defaultName.c_str())) {
+    if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) {
       e.CustomNamePrefix = '*';
       foundDefaultOne = true;
     }
@@ -2607,11 +2597,6 @@
   return configs;
 }
 
-cmMessenger* cmake::GetMessenger() const
-{
-  return this->Messenger;
-}
-
 int cmake::Build(int jobs, const std::string& dir,
                  const std::vector<std::string>& targets,
                  const std::string& config,
diff --git a/Source/cmake.h b/Source/cmake.h
index fa4409a..6aa00e1 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -7,7 +7,7 @@
 
 #include <functional>
 #include <map>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_set>
@@ -121,6 +121,17 @@
     bool isAlias;
   };
 
+  struct FileExtensions
+  {
+    bool Test(std::string const& ext) const
+    {
+      return (this->unordered.find(ext) != this->unordered.end());
+    }
+
+    std::vector<std::string> ordered;
+    std::unordered_set<std::string> unordered;
+  };
+
   typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
 
   static const int NO_BUILD_PARALLEL_LEVEL = -1;
@@ -233,24 +244,42 @@
 
   const std::vector<std::string>& GetSourceExtensions() const
   {
-    return this->SourceFileExtensions;
+    return this->SourceFileExtensions.ordered;
   }
 
   bool IsSourceExtension(const std::string& ext) const
   {
-    return this->SourceFileExtensionsSet.find(ext) !=
-      this->SourceFileExtensionsSet.end();
+    return this->SourceFileExtensions.Test(ext);
   }
 
   const std::vector<std::string>& GetHeaderExtensions() const
   {
-    return this->HeaderFileExtensions;
+    return this->HeaderFileExtensions.ordered;
   }
 
   bool IsHeaderExtension(const std::string& ext) const
   {
-    return this->HeaderFileExtensionsSet.find(ext) !=
-      this->HeaderFileExtensionsSet.end();
+    return this->HeaderFileExtensions.Test(ext);
+  }
+
+  const std::vector<std::string>& GetCudaExtensions() const
+  {
+    return this->CudaFileExtensions.ordered;
+  }
+
+  bool IsCudaExtension(const std::string& ext) const
+  {
+    return this->CudaFileExtensions.Test(ext);
+  }
+
+  const std::vector<std::string>& GetFortranExtensions() const
+  {
+    return this->FortranFileExtensions.ordered;
+  }
+
+  bool IsFortranExtension(const std::string& ext) const
+  {
+    return this->FortranFileExtensions.Test(ext);
   }
 
   // Strips the extension (if present and known) from a filename
@@ -307,7 +336,7 @@
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   //! Get the variable watch object
-  cmVariableWatch* GetVariableWatch() { return this->VariableWatch; }
+  cmVariableWatch* GetVariableWatch() { return this->VariableWatch.get(); }
 #endif
 
   std::vector<cmDocumentationEntry> GetGeneratorsDocumentation();
@@ -348,18 +377,18 @@
   /**
    * Get the file comparison class
    */
-  cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache; }
+  cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache.get(); }
 
-  // Get the selected log level for `message()` commands during the cmake run.
+  //! Get the selected log level for `message()` commands during the cmake run.
   LogLevel GetLogLevel() const { return this->MessageLogLevel; }
   void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; }
   static LogLevel StringToLogLevel(const std::string& levelStr);
 
-  // Do we want debug output during the cmake run.
+  //! Do we want debug output during the cmake run.
   bool GetDebugOutput() { return this->DebugOutput; }
   void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
 
-  // Do we want trace output during the cmake run.
+  //! Do we want trace output during the cmake run.
   bool GetTrace() { return this->Trace; }
   void SetTrace(bool b) { this->Trace = b; }
   bool GetTraceExpand() { return this->TraceExpand; }
@@ -396,31 +425,31 @@
     return this->CMakeEditCommand;
   }
 
-  cmMessenger* GetMessenger() const;
+  cmMessenger* GetMessenger() const { return this->Messenger.get(); }
 
-  /*
+  /**
    * Get the state of the suppression of developer (author) warnings.
    * Returns false, by default, if developer warnings should be shown, true
    * otherwise.
    */
   bool GetSuppressDevWarnings() const;
-  /*
+  /**
    * Set the state of the suppression of developer (author) warnings.
    */
   void SetSuppressDevWarnings(bool v);
 
-  /*
+  /**
    * Get the state of the suppression of deprecated warnings.
    * Returns false, by default, if deprecated warnings should be shown, true
    * otherwise.
    */
   bool GetSuppressDeprecatedWarnings() const;
-  /*
+  /**
    * Set the state of the suppression of deprecated warnings.
    */
   void SetSuppressDeprecatedWarnings(bool v);
 
-  /*
+  /**
    * Get the state of treating developer (author) warnings as errors.
    * Returns false, by default, if warnings should not be treated as errors,
    * true otherwise.
@@ -431,7 +460,7 @@
    */
   void SetDevWarningsAsErrors(bool v);
 
-  /*
+  /**
    * Get the state of treating deprecated warnings as errors.
    * Returns false, by default, if warnings should not be treated as errors,
    * true otherwise.
@@ -459,7 +488,7 @@
   void UnwatchUnusedCli(const std::string& var);
   void WatchUnusedCli(const std::string& var);
 
-  cmState* GetState() const { return this->State; }
+  cmState* GetState() const { return this->State.get(); }
   void SetCurrentSnapshot(cmStateSnapshot const& snapshot)
   {
     this->CurrentSnapshot = snapshot;
@@ -531,24 +560,24 @@
   std::string CheckStampList;
   std::string VSSolutionFile;
   std::string EnvironmentGenerator;
-  std::vector<std::string> SourceFileExtensions;
-  std::unordered_set<std::string> SourceFileExtensionsSet;
-  std::vector<std::string> HeaderFileExtensions;
-  std::unordered_set<std::string> HeaderFileExtensionsSet;
+  FileExtensions SourceFileExtensions;
+  FileExtensions HeaderFileExtensions;
+  FileExtensions CudaFileExtensions;
+  FileExtensions FortranFileExtensions;
   bool ClearBuildSystem;
   bool DebugTryCompile;
-  cmFileTimeCache* FileTimeCache;
+  std::unique_ptr<cmFileTimeCache> FileTimeCache;
   std::string GraphVizFile;
   InstalledFilesMap InstalledFiles;
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-  cmVariableWatch* VariableWatch;
+  std::unique_ptr<cmVariableWatch> VariableWatch;
   std::unique_ptr<cmFileAPI> FileAPI;
 #endif
 
-  cmState* State;
+  std::unique_ptr<cmState> State;
   cmStateSnapshot CurrentSnapshot;
-  cmMessenger* Messenger;
+  std::unique_ptr<cmMessenger> Messenger;
 
   std::vector<std::string> TraceOnlyThisSources;
 
@@ -556,7 +585,7 @@
 
   void UpdateConversionPathTable();
 
-  // Print a list of valid generators to stderr.
+  //! Print a list of valid generators to stderr.
   void PrintGeneratorList();
 
   std::unique_ptr<cmGlobalGenerator> EvaluateDefaultGlobalGenerator();
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index a6348b3..10a6825 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -7,6 +7,7 @@
 #include "cmMakefile.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 #include "cmcmd.h"
@@ -31,13 +32,14 @@
 #include <string>
 #include <vector>
 
+namespace {
 #ifdef CMAKE_BUILD_WITH_CMAKE
-static const char* cmDocumentationName[][2] = {
+const char* cmDocumentationName[][2] = {
   { nullptr, "  cmake - Cross-Platform Makefile Generator." },
   { nullptr, nullptr }
 };
 
-static const char* cmDocumentationUsage[][2] = {
+const char* cmDocumentationUsage[][2] = {
   { nullptr,
     "  cmake [options] <path-to-source>\n"
     "  cmake [options] <path-to-existing-build>\n"
@@ -49,40 +51,12 @@
   { nullptr, nullptr }
 };
 
-static const char* cmDocumentationUsageNote[][2] = {
+const char* cmDocumentationUsageNote[][2] = {
   { nullptr, "Run 'cmake --help' for more information." },
   { nullptr, nullptr }
 };
 
-#  define CMAKE_BUILD_OPTIONS                                                 \
-    "  <dir>          = Project binary directory to be built.\n"              \
-    "  --parallel [<jobs>], -j [<jobs>]\n"                                    \
-    "                 = Build in parallel using the given number of jobs. \n" \
-    "                   If <jobs> is omitted the native build tool's \n"      \
-    "                   default number is used.\n"                            \
-    "                   The CMAKE_BUILD_PARALLEL_LEVEL environment "          \
-    "variable\n"                                                              \
-    "                   specifies a default parallel level when this "        \
-    "option\n"                                                                \
-    "                   is not given.\n"                                      \
-    "  --target <tgt>..., -t <tgt>... \n"                                     \
-    "                 = Build <tgt> instead of default targets.\n"            \
-    "  --config <cfg> = For multi-configuration tools, choose <cfg>.\n"       \
-    "  --clean-first  = Build target 'clean' first, then build.\n"            \
-    "                   (To clean only, use --target 'clean'.)\n"             \
-    "  --verbose, -v  = Enable verbose output - if supported - including\n"   \
-    "                   the build commands to be executed. \n"                \
-    "  --             = Pass remaining options to the native tool.\n"
-
-#  define CMAKE_INSTALL_OPTIONS                                               \
-    "  <dir>              = Project binary directory to install.\n"           \
-    "  --config <cfg>     = For multi-configuration tools, choose <cfg>.\n"   \
-    "  --component <comp> = Component-based install. Only install <comp>.\n"  \
-    "  --prefix <prefix>  = The installation prefix CMAKE_INSTALL_PREFIX.\n"  \
-    "  --strip            = Performing install/strip.\n"                      \
-    "  -v --verbose       = Enable verbose output.\n"
-
-static const char* cmDocumentationOptions[][2] = {
+const char* cmDocumentationOptions[][2] = {
   CMAKE_STANDARD_OPTIONS_TABLE,
   { "-E", "CMake command mode." },
   { "-L[A][H]", "List non-advanced cached variables." },
@@ -117,7 +91,7 @@
 
 #endif
 
-static int do_command(int ac, char const* const* av)
+int do_command(int ac, char const* const* av)
 {
   std::vector<std::string> args;
   args.reserve(ac - 1);
@@ -126,12 +100,7 @@
   return cmcmd::ExecuteCMakeCommand(args);
 }
 
-int do_cmake(int ac, char const* const* av);
-static int do_build(int ac, char const* const* av);
-static int do_install(int ac, char const* const* av);
-static int do_open(int ac, char const* const* av);
-
-static cmMakefile* cmakemainGetMakefile(cmake* cm)
+cmMakefile* cmakemainGetMakefile(cmake* cm)
 {
   if (cm && cm->GetDebugOutput()) {
     cmGlobalGenerator* gg = cm->GetGlobalGenerator();
@@ -142,7 +111,7 @@
   return nullptr;
 }
 
-static std::string cmakemainGetStack(cmake* cm)
+std::string cmakemainGetStack(cmake* cm)
 {
   std::string msg;
   cmMakefile* mf = cmakemainGetMakefile(cm);
@@ -156,14 +125,13 @@
   return msg;
 }
 
-static void cmakemainMessageCallback(const std::string& m,
-                                     const char* /*unused*/, cmake* cm)
+void cmakemainMessageCallback(const std::string& m, const char* /*unused*/,
+                              cmake* cm)
 {
-  std::cerr << m << cmakemainGetStack(cm) << std::endl << std::flush;
+  std::cerr << m << cmakemainGetStack(cm) << std::endl;
 }
 
-static void cmakemainProgressCallback(const std::string& m, float prog,
-                                      cmake* cm)
+void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm)
 {
   cmMakefile* mf = cmakemainGetMakefile(cm);
   std::string dir;
@@ -178,48 +146,6 @@
   if ((prog < 0) || (!dir.empty())) {
     std::cout << "-- " << m << dir << cmakemainGetStack(cm) << std::endl;
   }
-
-  std::cout.flush();
-}
-
-int main(int ac, char const* const* av)
-{
-  cmSystemTools::EnsureStdPipes();
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-  // Replace streambuf so we can output Unicode to console
-  cmsys::ConsoleBuf::Manager consoleOut(std::cout);
-  consoleOut.SetUTF8Pipes();
-  cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
-  consoleErr.SetUTF8Pipes();
-#endif
-  cmsys::Encoding::CommandLineArguments args =
-    cmsys::Encoding::CommandLineArguments::Main(ac, av);
-  ac = args.argc();
-  av = args.argv();
-
-  cmSystemTools::EnableMSVCDebugHook();
-  cmSystemTools::InitializeLibUV();
-  cmSystemTools::FindCMakeResources(av[0]);
-  if (ac > 1) {
-    if (strcmp(av[1], "--build") == 0) {
-      return do_build(ac, av);
-    }
-    if (strcmp(av[1], "--install") == 0) {
-      return do_install(ac, av);
-    }
-    if (strcmp(av[1], "--open") == 0) {
-      return do_open(ac, av);
-    }
-    if (strcmp(av[1], "-E") == 0) {
-      return do_command(ac, av);
-    }
-  }
-  int ret = do_cmake(ac, av);
-#ifdef CMAKE_BUILD_WITH_CMAKE
-  cmDynamicLoader::FlushCache();
-#endif
-  uv_loop_close(uv_default_loop());
-  return ret;
 }
 
 int do_cmake(int ac, char const* const* av)
@@ -381,7 +307,6 @@
   return 0;
 }
 
-namespace {
 int extract_job_number(int& index, char const* current, char const* next,
                        int len_of_flag)
 {
@@ -411,9 +336,8 @@
   }
   return jobs;
 }
-}
 
-static int do_build(int ac, char const* const* av)
+int do_build(int ac, char const* const* av)
 {
 #ifndef CMAKE_BUILD_WITH_CMAKE
   std::cerr << "This cmake does not support --build\n";
@@ -541,7 +465,24 @@
     std::cerr <<
       "Usage: cmake --build <dir> [options] [-- [native-options]]\n"
       "Options:\n"
-      CMAKE_BUILD_OPTIONS
+      "  <dir>          = Project binary directory to be built.\n"
+      "  --parallel [<jobs>], -j [<jobs>]\n"
+      "                 = Build in parallel using the given number of jobs. \n"
+      "                   If <jobs> is omitted the native build tool's \n"
+      "                   default number is used.\n"
+      "                   The CMAKE_BUILD_PARALLEL_LEVEL environment "
+      "variable\n"
+      "                   specifies a default parallel level when this "
+      "option\n"
+      "                   is not given.\n"
+      "  --target <tgt>..., -t <tgt>... \n"
+      "                 = Build <tgt> instead of default targets.\n"
+      "  --config <cfg> = For multi-configuration tools, choose <cfg>.\n"
+      "  --clean-first  = Build target 'clean' first, then build.\n"
+      "                   (To clean only, use --target 'clean'.)\n"
+      "  --verbose, -v  = Enable verbose output - if supported - including\n"
+      "                   the build commands to be executed. \n"
+      "  --             = Pass remaining options to the native tool.\n"
       ;
     /* clang-format on */
     return 1;
@@ -560,7 +501,7 @@
 #endif
 }
 
-static int do_install(int ac, char const* const* av)
+int do_install(int ac, char const* const* av)
 {
 #ifndef CMAKE_BUILD_WITH_CMAKE
   std::cerr << "This cmake does not support --install\n";
@@ -627,8 +568,18 @@
   }
 
   if (dir.empty()) {
-    std::cerr << "Usage: cmake --install <dir> "
-                 "[options]\nOptions:\n" CMAKE_INSTALL_OPTIONS;
+    /* clang-format off */
+    std::cerr <<
+      "Usage: cmake --install <dir> [options]\n"
+      "Options:\n"
+      "  <dir>              = Project binary directory to install.\n"
+      "  --config <cfg>     = For multi-configuration tools, choose <cfg>.\n"
+      "  --component <comp> = Component-based install. Only install <comp>.\n"
+      "  --prefix <prefix>  = The installation prefix CMAKE_INSTALL_PREFIX.\n"
+      "  --strip            = Performing install/strip.\n"
+      "  -v --verbose       = Enable verbose output.\n"
+      ;
+    /* clang-format on */
     return 1;
   }
 
@@ -671,7 +622,7 @@
 #endif
 }
 
-static int do_open(int ac, char const* const* av)
+int do_open(int ac, char const* const* av)
 {
 #ifndef CMAKE_BUILD_WITH_CMAKE
   std::cerr << "This cmake does not support --open\n";
@@ -713,3 +664,44 @@
   return cm.Open(dir, false) ? 0 : 1;
 #endif
 }
+} // namespace
+
+int main(int ac, char const* const* av)
+{
+  cmSystemTools::EnsureStdPipes();
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+  // Replace streambuf so we can output Unicode to console
+  cmsys::ConsoleBuf::Manager consoleOut(std::cout);
+  consoleOut.SetUTF8Pipes();
+  cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
+  consoleErr.SetUTF8Pipes();
+#endif
+  cmsys::Encoding::CommandLineArguments args =
+    cmsys::Encoding::CommandLineArguments::Main(ac, av);
+  ac = args.argc();
+  av = args.argv();
+
+  cmSystemTools::EnableMSVCDebugHook();
+  cmSystemTools::InitializeLibUV();
+  cmSystemTools::FindCMakeResources(av[0]);
+  if (ac > 1) {
+    if (strcmp(av[1], "--build") == 0) {
+      return do_build(ac, av);
+    }
+    if (strcmp(av[1], "--install") == 0) {
+      return do_install(ac, av);
+    }
+    if (strcmp(av[1], "--open") == 0) {
+      return do_open(ac, av);
+    }
+    if (strcmp(av[1], "-E") == 0) {
+      return do_command(ac, av);
+    }
+  }
+  int ret = do_cmake(ac, av);
+#ifdef CMAKE_BUILD_WITH_CMAKE
+  cmDynamicLoader::FlushCache();
+#endif
+  uv_loop_close(uv_default_loop());
+  return ret;
+}
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 86082e5..aecc978 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -13,6 +13,7 @@
 #include "cmState.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmUtils.hxx"
 #include "cmVersion.h"
@@ -41,7 +42,7 @@
 #include <array>
 #include <iostream>
 #include <iterator>
-#include <memory> // IWYU pragma: keep
+#include <memory>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -114,6 +115,8 @@
     << "  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"
+    << "  true                      - do nothing with an exit code of 0\n"
+    << "  false                     - do nothing with an exit code of 1\n"
 #if defined(_WIN32) && !defined(__CYGWIN__)
     << "Available on Windows only:\n"
     << "  delete_regv key           - delete registry value\n"
@@ -891,6 +894,16 @@
       return 0;
     }
 
+    // Command to do nothing with an exit code of 0.
+    if (args[1] == "true") {
+      return 0;
+    }
+
+    // Command to do nothing with an exit code of 1.
+    if (args[1] == "false") {
+      return 1;
+    }
+
     // Internal CMake shared library support.
     if (args[1] == "cmake_symlink_library" && args.size() == 5) {
       return cmcmd::SymlinkLibrary(args);
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
index a97f7a8..dc9f01d 100644
--- a/Source/kwsys/CommandLineArguments.cxx
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -67,10 +67,10 @@
 {
 public:
   CommandLineArgumentsInternal()
+    : UnknownArgumentCallback{ KWSYS_NULLPTR }
+    , ClientData{ KWSYS_NULLPTR }
+    , LastArgument{ 0 }
   {
-    this->UnknownArgumentCallback = KWSYS_NULLPTR;
-    this->ClientData = KWSYS_NULLPTR;
-    this->LastArgument = 0;
   }
 
   typedef CommandLineArgumentsVectorOfStrings VectorOfStrings;
diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx
index 5f84b19..3e10765 100644
--- a/Source/kwsys/RegularExpression.cxx
+++ b/Source/kwsys/RegularExpression.cxx
@@ -337,7 +337,6 @@
 {
   const char* scan;
   const char* longest;
-  size_t len;
   int flags;
 
   if (exp == KWSYS_NULLPTR) {
@@ -412,7 +411,7 @@
     //
     if (flags & SPSTART) {
       longest = KWSYS_NULLPTR;
-      len = 0;
+      size_t len = 0;
       for (; scan != KWSYS_NULLPTR; scan = regnext(scan))
         if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
           longest = OPERAND(scan);
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
index b7b93f9..ed86418 100644
--- a/Source/kwsys/RegularExpression.hxx.in
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -407,8 +407,12 @@
  * Create an empty regular expression.
  */
 inline RegularExpression::RegularExpression()
+  : regstart{}
+  , reganch{}
+  , regmust{}
+  , program{ 0 }
+  , progsize{}
 {
-  this->program = 0;
 }
 
 /**
@@ -416,8 +420,12 @@
  * compiles s.
  */
 inline RegularExpression::RegularExpression(const char* s)
+  : regstart{}
+  , reganch{}
+  , regmust{}
+  , program{ 0 }
+  , progsize{}
 {
-  this->program = 0;
   if (s) {
     this->compile(s);
   }
@@ -428,8 +436,12 @@
  * compiles s.
  */
 inline RegularExpression::RegularExpression(const std::string& s)
+  : regstart{}
+  , reganch{}
+  , regmust{}
+  , program{ 0 }
+  , progsize{}
 {
-  this->program = 0;
   this->compile(s);
 }
 
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index ae7a18a..36f24c7 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -3403,11 +3403,7 @@
         out_components.emplace_back(std::move(*i));
       }
     } else if (!i->empty() && *i != cur) {
-#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
-      out_components.push_back(std::move(*i));
-#else
-      out_components.push_back(*i);
-#endif
+      out_components.emplace_back(std::move(*i));
     }
   }
 }
@@ -4743,7 +4739,7 @@
       // Test progressively shorter logical-to-physical mappings.
       std::string cwd_str = cwd;
       std::string pwd_path;
-      Realpath(pwd_str.c_str(), pwd_path);
+      Realpath(pwd_str, pwd_path);
       while (cwd_str == pwd_path && cwd_str != pwd_str) {
         // The current pair of paths is a working logical mapping.
         cwd_changed = cwd_str;
@@ -4753,7 +4749,7 @@
         // mapping still works.
         pwd_str = SystemTools::GetFilenamePath(pwd_str);
         cwd_str = SystemTools::GetFilenamePath(cwd_str);
-        Realpath(pwd_str.c_str(), pwd_path);
+        Realpath(pwd_str, pwd_path);
       }
 
       // Add the translation to keep the logical path name.
diff --git a/Tests/Assembler/CMakeLists.txt b/Tests/Assembler/CMakeLists.txt
index fb17ebb..21b265c 100644
--- a/Tests/Assembler/CMakeLists.txt
+++ b/Tests/Assembler/CMakeLists.txt
@@ -7,9 +7,10 @@
 
 # (at least) the following toolchains can process assembler files directly
 # and also generate assembler files from C:
-if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode" AND
+if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode|Ninja" AND
     NOT CMAKE_OSX_ARCHITECTURES)
-  if((CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang|HP|SunPro|XL)$") OR (CMAKE_C_COMPILER_ID STREQUAL "Intel"  AND  UNIX))
+  if((CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang|HP|SunPro|XL)$") OR (CMAKE_C_COMPILER_ID STREQUAL "Intel"  AND  UNIX)
+     AND NOT (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC"))
     set(C_FLAGS "${CMAKE_C_FLAGS}")
     separate_arguments(C_FLAGS)
     if(CMAKE_OSX_SYSROOT AND CMAKE_C_SYSROOT_FLAG AND NOT ";${C_FLAGS};" MATCHES ";${CMAKE_C_SYSROOT_FLAG};")
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index a25f25a..cd4dbc8 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -10,6 +10,7 @@
   testRST.cxx
   testRange.cxx
   testString.cxx
+  testStringAlgorithms.cxx
   testSystemTools.cxx
   testUTF8.cxx
   testXMLParser.cxx
diff --git a/Tests/CMakeLib/testStringAlgorithms.cxx b/Tests/CMakeLib/testStringAlgorithms.cxx
new file mode 100644
index 0000000..95616ff
--- /dev/null
+++ b/Tests/CMakeLib/testStringAlgorithms.cxx
@@ -0,0 +1,134 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include "cm_string_view.hxx"
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "cmStringAlgorithms.h"
+
+int testStringAlgorithms(int /*unused*/, char* /*unused*/ [])
+{
+  int failed = 0;
+
+  auto assert_ok = [&failed](bool test, cm::string_view title) {
+    if (test) {
+      std::cout << "Passed: " << title << "\n";
+    } else {
+      std::cout << "Failed: " << title << "\n";
+      ++failed;
+    }
+  };
+
+  auto assert_string = [&failed](cm::string_view generated,
+                                 cm::string_view expected,
+                                 cm::string_view title) {
+    if (generated == expected) {
+      std::cout << "Passed: " << title << "\n";
+    } else {
+      std::cout << "Failed: " << title << "\n";
+      std::cout << "Expected: " << expected << "\n";
+      std::cout << "Got: " << generated << "\n";
+      ++failed;
+    }
+  };
+
+  // ----------------------------------------------------------------------
+  // Test cmJoin
+  {
+    typedef std::string ST;
+    typedef std::vector<std::string> VT;
+    assert_string(cmJoin(ST("abc"), ";"), "a;b;c", "cmJoin std::string");
+    assert_string(cmJoin(VT{}, ";"), "", "cmJoin std::vector empty");
+    assert_string(cmJoin(VT{ "a" }, ";"), "a", "cmJoin std::vector single");
+    assert_string(cmJoin(VT{ "a", "b", "c" }, ";"), "a;b;c",
+                  "cmJoin std::vector multiple");
+    assert_string(cmJoin(VT{ "a", "b", "c" }, "<=>"), "a<=>b<=>c",
+                  "cmJoin std::vector long sep");
+  }
+
+  // ----------------------------------------------------------------------
+  // Test cmStrCat
+  {
+    int ni = -1100;
+    unsigned int nui = 1100u;
+    long int nli = -12000l;
+    unsigned long int nuli = 12000ul;
+    long long int nlli = -130000ll;
+    unsigned long long int nulli = 130000ull;
+    std::string val =
+      cmStrCat("<test>", ni, ',', nui, ',', nli, ",", nuli, ", ", nlli,
+               std::string(", "), nulli, cm::string_view("</test>"));
+    std::string expect =
+      "<test>-1100,1100,-12000,12000, -130000, 130000</test>";
+    assert_string(val, expect, "cmStrCat strings and integers");
+  }
+  {
+    float const val = 1.5f;
+    float const div = 0.00001f;
+    float f = 0.0f;
+    std::istringstream(cmStrCat("", val)) >> f;
+    f -= val;
+    assert_ok((f < div) && (f > -div), "cmStrCat float");
+  }
+  {
+    double const val = 1.5;
+    double const div = 0.00001;
+    double d = 0.0;
+    std::istringstream(cmStrCat("", val)) >> d;
+    d -= val;
+    assert_ok((d < div) && (d > -div), "cmStrCat double");
+  }
+
+  // ----------------------------------------------------------------------
+  // Test cmWrap
+  {
+    typedef std::vector<std::string> VT;
+    assert_string(cmWrap("<", VT{}, ">", "; "), //
+                  "",                           //
+                  "cmWrap empty, string prefix and suffix");
+    assert_string(cmWrap("<", VT{ "abc" }, ">", "; "), //
+                  "<abc>",                             //
+                  "cmWrap single, string prefix and suffix");
+    assert_string(cmWrap("<", VT{ "a1", "a2", "a3" }, ">", "; "), //
+                  "<a1>; <a2>; <a3>",                             //
+                  "cmWrap multiple, string prefix and suffix");
+
+    assert_string(cmWrap('<', VT{}, '>', "; "), //
+                  "",                           //
+                  "cmWrap empty, char prefix and suffix");
+    assert_string(cmWrap('<', VT{ "abc" }, '>', "; "), //
+                  "<abc>",                             //
+                  "cmWrap single, char prefix and suffix");
+    assert_string(cmWrap('<', VT{ "a1", "a2", "a3" }, '>', "; "), //
+                  "<a1>; <a2>; <a3>",                             //
+                  "cmWrap multiple, char prefix and suffix");
+  }
+
+  // ----------------------------------------------------------------------
+  // Test cmHas(Literal)Prefix and cmHas(Literal)Suffix
+  {
+    std::string str("abc");
+    assert_ok(cmHasPrefix(str, 'a'), "cmHasPrefix char");
+    assert_ok(!cmHasPrefix(str, 'c'), "cmHasPrefix char not");
+    assert_ok(cmHasPrefix(str, "ab"), "cmHasPrefix string");
+    assert_ok(!cmHasPrefix(str, "bc"), "cmHasPrefix string not");
+    assert_ok(cmHasPrefix(str, str), "cmHasPrefix complete string");
+    assert_ok(cmHasLiteralPrefix(str, "ab"), "cmHasLiteralPrefix string");
+    assert_ok(!cmHasLiteralPrefix(str, "bc"), "cmHasLiteralPrefix string not");
+
+    assert_ok(cmHasSuffix(str, 'c'), "cmHasSuffix char");
+    assert_ok(!cmHasSuffix(str, 'a'), "cmHasSuffix char not");
+    assert_ok(cmHasSuffix(str, "bc"), "cmHasSuffix string");
+    assert_ok(!cmHasSuffix(str, "ab"), "cmHasSuffix string not");
+    assert_ok(cmHasSuffix(str, str), "cmHasSuffix complete string");
+    assert_ok(cmHasLiteralSuffix(str, "bc"), "cmHasLiteralSuffix string");
+    assert_ok(!cmHasLiteralSuffix(str, "ab"), "cmHasLiteralPrefix string not");
+  }
+
+  return failed;
+}
diff --git a/Tests/CMakeLib/testUVProcessChain.cxx b/Tests/CMakeLib/testUVProcessChain.cxx
index 72ae602..63c9943 100644
--- a/Tests/CMakeLib/testUVProcessChain.cxx
+++ b/Tests/CMakeLib/testUVProcessChain.cxx
@@ -1,6 +1,5 @@
 #include "cmUVProcessChain.h"
 
-#include "cmAlgorithms.h"
 #include "cmGetPipes.h"
 #include "cmUVHandlePtr.h"
 #include "cmUVStreambuf.h"
@@ -16,6 +15,8 @@
 
 #include <csignal>
 
+#include "cm_memory.hxx"
+
 struct ExpectedStatus
 {
   bool Finished;
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index e73b277..5b8f255 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -14,8 +14,8 @@
     ${build_generator_args}
     --build-project ${proj}
     ${${NAME}_CTEST_OPTIONS}
-    --build-options ${build_options}
-    ${${NAME}_BUILD_OPTIONS}
+    --build-options
+      ${${NAME}_BUILD_OPTIONS}
     ${_test_command})
   unset(_test_command)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${dir}")
@@ -127,9 +127,10 @@
       )
   endif()
 
-  set(build_options)
   if(CMake_TEST_EXPLICIT_MAKE_PROGRAM)
-    list(APPEND build_options -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM})
+    list(APPEND build_generator_args
+      --build-makeprogram ${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
+      )
   endif()
 
   # Look for rpmbuild to use for tests.
@@ -528,7 +529,6 @@
       "${CMake_BINARY_DIR}/Tests/BundleUtilities"
       ${build_generator_args}
       --build-project BundleUtilities
-      --build-options ${build_options}
       )
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleUtilities")
 
@@ -541,9 +541,9 @@
         "${CMake_BINARY_DIR}/Tests/Qt4Deploy"
         ${build_generator_args}
         --build-project Qt4Deploy
-        --build-options ${build_options}
-        -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-        -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
+        --build-options
+          -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+          -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
         )
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Deploy")
     endif()
@@ -590,7 +590,7 @@
     --build-project ExternalDataTest
     --build-noclean
     --force-new-ctest-process
-    --build-options ${build_options}
+    --build-options
       -DMAKE_SUPPORTS_SPACES=${MAKE_SUPPORTS_SPACES}
     --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} -V
     )
@@ -633,7 +633,6 @@
       "${CMake_BINARY_DIR}/Tests/Visibility"
       ${build_generator_args}
       --build-project Visibility
-      --build-options ${build_options}
     )
     list(APPEND TEST_BUILD_DIRS
       "${CMake_BINARY_DIR}/Tests/Visibility"
@@ -648,7 +647,7 @@
     ${build_generator_args}
     --build-project LinkFlags
     --build-target LinkFlags
-    --build-options ${build_options}
+    --build-options
       -DTEST_CONFIG=\${CTEST_CONFIGURATION_TYPE}
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LinkFlags")
@@ -709,7 +708,6 @@
           --build-generator-platform "${CMAKE_GENERATOR_PLATFORM}"
           --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}"
           --build-project Simple
-          --build-options ${build_options}
           --test-command Simple)
         list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${extraGeneratorTestName}")
       endif ()
@@ -729,7 +727,6 @@
       --build-project SubProject
       ${build_generator_args}
       --build-target car
-      --build-options ${build_options}
       --test-command car
       )
 
@@ -755,7 +752,6 @@
       --build-project foo
       --build-target foo
       --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubProject/foo"
-      --build-options ${build_options}
       --test-command foo
       )
     set_tests_properties ( SubProject-Stage2 PROPERTIES DEPENDS SubProject)
@@ -797,7 +793,7 @@
     --build-two-config
     ${build_generator_args}
     --build-project Framework
-    --build-options ${build_options}
+    --build-options
     "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/Framework/Install"
     --test-command bar)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Framework")
@@ -809,7 +805,6 @@
     --build-two-config
     ${build_generator_args}
     --build-project TargetName
-    --build-options ${build_options}
     --test-command ${CMAKE_CMAKE_COMMAND} -E compare_files
     ${CMake_SOURCE_DIR}/Tests/TargetName/scripts/hello_world
     ${CMake_BINARY_DIR}/Tests/TargetName/scripts/hello_world)
@@ -823,7 +818,6 @@
     ${build_generator_args}
     --build-project LibName
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/LibName/lib"
-    --build-options ${build_options}
     --test-command foobar
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LibName")
@@ -836,7 +830,6 @@
     ${build_generator_args}
     --build-project CustComDepend
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/CustComDepend/bin"
-    --build-options ${build_options}
     --test-command foo bar.c
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustComDepend")
@@ -848,7 +841,6 @@
     ${build_generator_args}
     --build-project ArgumentExpansion
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/ArgumentExpansion/bin"
-    --build-options ${build_options}
     )
   set_tests_properties(ArgumentExpansion PROPERTIES
     FAIL_REGULAR_EXPRESSION "Unexpected: ")
@@ -861,7 +853,7 @@
     "${CMake_BINARY_DIR}/Tests/GeneratorExpression"
     ${build_generator_args}
     --build-project GeneratorExpression
-    --build-options ${build_options}
+    --build-options
       -DCMAKE_BUILD_TYPE=\${CTEST_CONFIGURATION_TYPE}
     --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} -V
     )
@@ -875,7 +867,7 @@
     ${build_generator_args}
     --build-project CustomCommand
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/CustomCommand/bin"
-    --build-options ${build_options}
+    --build-options
     --test-command CustomCommand
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustomCommand")
@@ -893,7 +885,6 @@
     --build-two-config
     ${build_generator_args}
     --build-project TestWorkingDir
-    --build-options ${build_options}
     --test-command working
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustomCommandWorkingDirectory")
@@ -905,7 +896,6 @@
     ${build_generator_args}
     --build-project OutOfSource
     --build-two-config
-    --build-options ${build_options}
     --test-command
     "${CMake_BINARY_DIR}/Tests/OutOfSource/SubDir/OutOfSourceSubdir/simple")
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/OutOfSource")
@@ -918,7 +908,6 @@
     "${CMake_BINARY_DIR}/Tests/BuildDepends"
     ${build_generator_args}
     --build-project BuildDepends
-    --build-options ${build_options}
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BuildDepends")
 
@@ -931,7 +920,7 @@
     ${build_generator_args}
     --build-project TestMissingInstall
     --build-two-config
-    --build-options ${build_options}
+    --build-options
     "-DCMAKE_INSTALL_PREFIX:PATH=${MissingInstallInstallDir}")
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/MissingInstall")
 
@@ -977,7 +966,7 @@
         "${CMake_BINARY_DIR}/Tests/CPackWiXGenerator"
         ${build_generator_args}
         --build-project CPackWiXGenerator
-        --build-options ${build_options}
+        --build-options
         --test-command ${CMAKE_CMAKE_COMMAND}
           "-DCPackWiXGenerator_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/CPackWiXGenerator"
           "-Dconfig=\${CTEST_CONFIGURATION_TYPE}"
@@ -997,7 +986,7 @@
       ${build_generator_args}
       --build-project CPackUseDefaultVersion
       --build-two-config
-      --build-options ${build_options}
+      --build-options
         ${CPackUseDefaultVersion_BUILD_OPTIONS})
     set_tests_properties(CPackUseDefaultVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=0\\.1\\.1")
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseDefaultVersion")
@@ -1009,7 +998,7 @@
       ${build_generator_args}
       --build-project CPackUseProjectVersion
       --build-two-config
-      --build-options ${build_options}
+      --build-options
         ${CPackUseProjectVersion_BUILD_OPTIONS})
     set_tests_properties(CPackUseProjectVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=1\\.2\\.3")
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseProjectVersion")
@@ -1021,7 +1010,7 @@
       ${build_generator_args}
       --build-project CPackUseShortProjectVersion
       --build-two-config
-      --build-options ${build_options}
+      --build-options
         ${CPackUseProjectVersion_BUILD_OPTIONS})
     set_tests_properties(CPackUseShortProjectVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=2")
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseShortProjectVersion")
@@ -1049,7 +1038,7 @@
       --build-project CPackComponents
       --build-two-config
       --build-target package
-      --build-options ${build_options}
+      --build-options
         -DCPACK_BINARY_DEB:BOOL=${CPACK_BINARY_DEB}
         -DCPACK_BINARY_RPM:BOOL=${CPACK_BINARY_RPM}
         ${CPackComponents_BUILD_OPTIONS}
@@ -1109,7 +1098,7 @@
           "${CMake_BINARY_DIR}/Tests/CPackComponentsForAll/build${CPackGen}-${CPackComponentWay}"
           ${build_generator_args}
           --build-project CPackComponentsForAll
-          --build-options ${build_options}
+          --build-options
              -DCPACK_GENERATOR:STRING=${CPACK_GENERATOR_STRING_${CPackGen}}
              -DCPACK_BINARY_${CPackGen}:BOOL=ON
              ${CPackRun_CPackComponentWay}
@@ -1148,7 +1137,7 @@
               "${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}"
               ${build_generator_args}
           --build-project CPackComponentsDEB
-          --build-options ${build_options}
+          --build-options
               -DCPACK_GENERATOR:STRING=${CPackGen}
               -DCPACK_BINARY_${CPackGen}:BOOL=ON
               ${CPackRun_CPackDEBConfiguration}
@@ -1188,7 +1177,6 @@
       "${CMake_BINARY_DIR}/Tests/CPackTestAllGenerators"
       ${build_generator_args}
       --build-project CPackTestAllGenerators
-      --build-options ${build_options}
       --test-command
       ${CMAKE_CMAKE_COMMAND}
         -D dir=${CMake_BINARY_DIR}/Tests/CPackTestAllGenerators
@@ -1219,7 +1207,7 @@
       --build-project CPackComponentsPrefix
       --build-two-config
       --build-target package
-      --build-options ${build_options}
+      --build-options
         -DCPACK_BINARY_DEB:BOOL=${CPACK_BINARY_DEB}
         -DCPACK_BINARY_RPM:BOOL=${CPACK_BINARY_RPM}
         -DCPACK_BINARY_ZIP:BOOL=ON
@@ -1242,7 +1230,6 @@
     --build-project UseX11
     --build-two-config
     ${X11_build_target_arg}
-    --build-options ${build_options}
     --test-command  UseX11)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/X11")
 
@@ -1285,7 +1272,6 @@
       "${CMake_BINARY_DIR}/Tests/LoadCommandOneConfig"
       ${build_generator_args}
       --build-project LoadCommand
-      --build-options ${build_options}
       --test-command  LoadedCommand
       )
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LoadCommandOneConfig")
@@ -1300,7 +1286,6 @@
     ${build_generator_args}
     --build-project Complex
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Complex/bin"
-    --build-options ${build_options}
     -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
     --test-command complex
     )
@@ -1313,7 +1298,6 @@
     ${build_generator_args}
     --build-project Complex
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/ComplexOneConfig/bin"
-    --build-options ${build_options}
     -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
     --test-command complex)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ComplexOneConfig")
@@ -1328,7 +1312,6 @@
     --build-project EnvironmentProj
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Environment"
     --force-new-ctest-process
-    --build-options ${build_options}
     --test-command ${CMAKE_CTEST_COMMAND} -V
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Environment")
@@ -1339,7 +1322,7 @@
     "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt"
     ${build_generator_args}
     --build-project QtAutomocNoQt
-    --build-options ${build_options}
+    --build-options
       -DCMAKE_BUILD_TYPE=\${CTEST_CONFIGURATION_TYPE}
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt")
@@ -1364,7 +1347,7 @@
       --build-project Qt4Targets
       --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4Targets"
       --force-new-ctest-process
-      --build-options ${build_options}
+      --build-options
         -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
       --test-command ${CMAKE_CTEST_COMMAND} -V
       )
@@ -1379,7 +1362,6 @@
         --build-project Qt4And5Automoc
         --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocForward"
         --force-new-ctest-process
-        --build-options ${build_options}
         --test-command ${CMAKE_CTEST_COMMAND} -V
         )
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocForward")
@@ -1391,191 +1373,73 @@
         --build-project Qt4And5Automoc
         --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocReverse"
         --force-new-ctest-process
-        --build-options ${build_options} -DQT_REVERSE_FIND_ORDER=1
+        --build-options -DQT_REVERSE_FIND_ORDER=1
         --test-command ${CMAKE_CTEST_COMMAND} -V
         )
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocReverse")
     endif()
   endif()
 
-  if(CMake_TEST_FindALSA)
-    add_subdirectory(FindALSA)
-  endif()
+  # test for Find modules, simple cases
+  foreach(_mod IN ITEMS
+            ALSA
+            Boost
+            BZip2
+            CURL
+            Cups
+            Doxygen
+            EnvModules
+            EXPAT
+            Fontconfig
+            Freetype
+            GDAL
+            GIF
+            Git
+            GLEW
+            GSL
+            GTK2
+            Iconv
+            ICU
+            JPEG
+            JsonCpp
+            LibLZMA
+            LibRHash
+            Libinput
+            LibUV
+            LibXml2
+            LTTngUST
+            ODBC
+            OpenCL
+            OpenGL
+            OpenMP
+            OpenSSL
+            MPI
+            PNG
+            Patch
+            PostgreSQL
+            Protobuf
+            SQLite3
+            TIFF
+            Vulkan
+            X11
+            XalanC
+            XercesC
+         )
+    if(CMake_TEST_Find${_mod})
+      add_subdirectory(Find${_mod})
+    endif()
+  endforeach()
 
   if(CMake_TEST_CUDA)
     add_subdirectory(Cuda)
     add_subdirectory(CudaOnly)
   endif()
 
-  if(CMake_TEST_FindBoost)
-    add_subdirectory(FindBoost)
-  endif()
-
-  if(CMake_TEST_FindBZip2)
-    add_subdirectory(FindBZip2)
-  endif()
-
-  if(CMake_TEST_FindCURL)
-    add_subdirectory(FindCURL)
-  endif()
-
-  if(CMake_TEST_FindCups)
-    add_subdirectory(FindCups)
-  endif()
-
-  if(CMake_TEST_FindDoxygen)
-    add_subdirectory(FindDoxygen)
-  endif()
-
-  if(CMake_TEST_FindEnvModules)
-    add_subdirectory(FindEnvModules)
-  endif()
-
-  if(CMake_TEST_FindEXPAT)
-    add_subdirectory(FindEXPAT)
-  endif()
-
-  if(CMake_TEST_FindFontconfig)
-    add_subdirectory(FindFontconfig)
-  endif()
-
-  if(CMake_TEST_FindFreetype)
-    add_subdirectory(FindFreetype)
-  endif()
-
-  if(CMake_TEST_FindGDAL)
-    add_subdirectory(FindGDAL)
-  endif()
-
-  if(CMake_TEST_FindGIF)
-    add_subdirectory(FindGIF)
-  endif()
-
-  if(CMake_TEST_FindGit)
-    add_subdirectory(FindGit)
-  endif()
-
-  if(CMake_TEST_FindGLEW)
-    add_subdirectory(FindGLEW)
-  endif()
-
-  if(CMake_TEST_FindGSL)
-    add_subdirectory(FindGSL)
-  endif()
-
   if(CMake_TEST_FindGTest)
     add_subdirectory(FindGTest)
     add_subdirectory(GoogleTest)
   endif()
 
-  if(CMake_TEST_FindGTK2)
-    add_subdirectory(FindGTK2)
-  endif()
-
-  if(CMake_TEST_FindIconv)
-    add_subdirectory(FindIconv)
-  endif()
-
-  if(CMake_TEST_FindICU)
-    add_subdirectory(FindICU)
-  endif()
-
-  if(CMake_TEST_FindJPEG)
-    add_subdirectory(FindJPEG)
-  endif()
-
-  if(CMake_TEST_FindJsonCpp)
-    add_subdirectory(FindJsonCpp)
-  endif()
-
-  if(CMake_TEST_FindLibLZMA)
-    add_subdirectory(FindLibLZMA)
-  endif()
-
-  if(CMake_TEST_FindLibRHash)
-    add_subdirectory(FindLibRHash)
-  endif()
-
-  if(CMake_TEST_FindLibinput)
-    add_subdirectory(FindLibinput)
-  endif()
-
-  if(CMake_TEST_FindLibUV)
-    add_subdirectory(FindLibUV)
-  endif()
-
-  if(CMake_TEST_FindLibXml2)
-    add_subdirectory(FindLibXml2)
-  endif()
-
-  if(CMake_TEST_FindLTTngUST)
-    add_subdirectory(FindLTTngUST)
-  endif()
-
-  if(CMake_TEST_FindODBC)
-    add_subdirectory(FindODBC)
-  endif()
-
-  if(CMake_TEST_FindOpenCL)
-    add_subdirectory(FindOpenCL)
-  endif()
-
-  if(CMake_TEST_FindOpenGL)
-    add_subdirectory(FindOpenGL)
-  endif()
-
-  if(CMake_TEST_FindOpenMP)
-    add_subdirectory(FindOpenMP)
-  endif()
-
-  if(CMake_TEST_FindOpenSSL)
-    add_subdirectory(FindOpenSSL)
-  endif()
-
-  if(CMake_TEST_FindMPI)
-    add_subdirectory(FindMPI)
-  endif()
-
-  if(CMake_TEST_FindPNG)
-    add_subdirectory(FindPNG)
-  endif()
-
-  if(CMake_TEST_FindPatch)
-    add_subdirectory(FindPatch)
-  endif()
-
-  if(CMake_TEST_FindPostgreSQL)
-    add_subdirectory(FindPostgreSQL)
-  endif()
-
-  if(CMake_TEST_FindProtobuf)
-    add_subdirectory(FindProtobuf)
-  endif()
-
-  if(CMake_TEST_FindSQLite3)
-    add_subdirectory(FindSQLite3)
-  endif()
-
-  if(CMake_TEST_FindTIFF)
-    add_subdirectory(FindTIFF)
-  endif()
-
-  if(CMake_TEST_FindVulkan)
-    add_subdirectory(FindVulkan)
-  endif()
-
-  if(CMake_TEST_FindX11)
-    add_subdirectory(FindX11)
-  endif()
-
-  if(CMake_TEST_FindXalanC)
-    add_subdirectory(FindXalanC)
-  endif()
-
-  if(CMake_TEST_FindXercesC)
-    add_subdirectory(FindXercesC)
-  endif()
-
   if(CMake_TEST_FindPython OR CMake_TEST_FindPython_NumPy)
     add_subdirectory(FindPython)
   endif()
@@ -1591,16 +1455,16 @@
   # CMake_TEST_FindMatlab_ROOT_DIR: indicates an optional root directory for Matlab, allows to select a version.
   # CMake_TEST_FindMatlab_MCR: indicates the MCR is installed
   # CMake_TEST_FindMatlab_MCR_ROOT_DIR: indicates an optional root directory for the MCR, required on Linux
-  if(CMake_TEST_FindMatlab OR (NOT "${CMake_TEST_FindMatlab_ROOT_DIR}" STREQUAL "") OR
-     CMake_TEST_FindMatlab_MCR OR (NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL ""))
+  if(CMake_TEST_FindMatlab OR CMake_TEST_FindMatlab_ROOT_DIR OR
+     CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR)
     set(FindMatlab_additional_test_options )
-    if(CMake_TEST_FindMatlab_MCR OR NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")
+    if(CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR)
       set(FindMatlab_additional_test_options -DIS_MCR=TRUE)
     endif()
-    if(NOT "${CMake_TEST_FindMatlab_ROOT_DIR}" STREQUAL "")
+    if(CMake_TEST_FindMatlab_ROOT_DIR)
       set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMatlab_ROOT_DIR=${CMake_TEST_FindMatlab_ROOT_DIR}")
     endif()
-    if(NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")
+    if(CMake_TEST_FindMatlab_MCR_ROOT_DIR)
       set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMCR_ROOT:FILEPATH=${CMake_TEST_FindMatlab_MCR_ROOT_DIR}")
     endif()
     set(FindMatlab.basic_checks_BUILD_OPTIONS ${FindMatlab_additional_test_options})
@@ -1623,7 +1487,6 @@
     --build-project ExternalProjectTest
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/ExternalProject"
     --force-new-ctest-process
-    --build-options ${build_options}
     --test-command ${CMAKE_CTEST_COMMAND} -V
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProject")
@@ -1639,7 +1502,6 @@
     ${build_generator_args}
     --build-project ExternalProjectSubdir
     --force-new-ctest-process
-    --build-options ${build_options}
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSubdir")
 
@@ -1651,7 +1513,6 @@
     ${build_generator_args}
     --build-project ExternalProjectSourceSubdir
     --force-new-ctest-process
-    --build-options ${build_options}
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdir")
 
@@ -1663,7 +1524,6 @@
     ${build_generator_args}
     --build-project ExternalProjectSourceSubdirNotCMake
     --force-new-ctest-process
-    --build-options ${build_options}
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdirNotCMake")
 
@@ -1675,7 +1535,6 @@
     --build-project ExternalProjectLocalTest
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/ExternalProjectLocal"
     --force-new-ctest-process
-    --build-options ${build_options}
     --test-command ${CMAKE_CTEST_COMMAND} -V
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectLocal")
@@ -1691,7 +1550,6 @@
     --build-project ExternalProjectUpdateTest
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate"
     --force-new-ctest-process
-    --build-options ${build_options}
     --test-command ${CMAKE_CTEST_COMMAND} -V
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate")
@@ -1729,11 +1587,11 @@
     endif()
     add_test(${tutorial_test_name} ${CMAKE_CTEST_COMMAND}
       --build-and-test
-      "${CMake_SOURCE_DIR}/Tests/Tutorial/${step_name}"
+      "${CMake_SOURCE_DIR}/Help/guide/tutorial/${step_name}"
       ${tutorial_build_dir}_Build
       ${build_generator_args}
       --build-project Tutorial
-      --build-options ${build_options} ${tutorial_build_options}
+      --build-options ${tutorial_build_options}
       --test-command Tutorial 25.0)
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/${tutorial_build_dir}_Build")
   endfunction()
@@ -1755,7 +1613,6 @@
     "${CMake_BINARY_DIR}/Tests/Testing"
     ${build_generator_args}
     --build-project Testing
-    --build-options ${build_options}
     --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE}
     )
   set_tests_properties(testing PROPERTIES PASS_REGULAR_EXPRESSION "Passed")
@@ -1768,7 +1625,6 @@
     ${build_generator_args}
     --build-project Wrapping
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
-    --build-options ${build_options}
     --test-command wrapping
     )
   add_test(qtwrapping  ${CMAKE_CTEST_COMMAND}
@@ -1778,7 +1634,6 @@
     ${build_generator_args}
     --build-project Wrapping
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
-    --build-options ${build_options}
       --test-command qtwrapping
       )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Wrapping")
@@ -1790,7 +1645,6 @@
     ${build_generator_args}
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
     --build-project TestDriverTest
-    --build-options ${build_options}
     --test-command TestDriverTest test1
     )
 
@@ -1801,7 +1655,6 @@
     ${build_generator_args}
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
     --build-project TestDriverTest
-    --build-options ${build_options}
     --test-command TestDriverTest test2
     )
 
@@ -1812,7 +1665,6 @@
     ${build_generator_args}
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin"
     --build-project TestDriverTest
-    --build-options ${build_options}
     --test-command TestDriverTest subdir/test3
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver")
@@ -1824,7 +1676,6 @@
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/Dependency/Exec"
     ${build_generator_args}
     --build-project Dependency
-    --build-options ${build_options}
     --test-command exec
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Dependency")
@@ -1854,8 +1705,8 @@
       --build-exe-dir "${CMake_BINARY_DIR}/Tests/Jump/WithLibOut/Executable"
       --build-project Jump
       ${build_generator_args}
-      --build-options ${build_options}
-      -DLIBRARY_OUTPUT_PATH:PATH=${CMake_BINARY_DIR}/Tests/Jump/WithLibOut/Lib
+      --build-options
+        -DLIBRARY_OUTPUT_PATH:PATH=${CMake_BINARY_DIR}/Tests/Jump/WithLibOut/Lib
       --test-command jumpExecutable
       )
 
@@ -1867,7 +1718,6 @@
       --build-run-dir "${CMake_BINARY_DIR}/Tests/Jump/NoLibOut/Executable"
       --build-project Jump
       ${build_generator_args}
-      --build-options ${build_options}
       --test-command jumpExecutable
       )
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Jump")
@@ -1879,7 +1729,6 @@
       ${build_generator_args}
       --build-project Plugin
       --build-two-config
-      --build-options ${build_options}
       --test-command bin/example)
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Plugin")
 
@@ -1895,7 +1744,7 @@
       "${CMake_BINARY_DIR}/Tests/MacRuntimePath"
       ${build_generator_args}
       --build-project MacRuntimePath
-      --build-options ${build_options}
+      --build-options
         -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
       )
   endif()
@@ -1913,7 +1762,6 @@
     "${CMake_BINARY_DIR}/Tests/LinkLineOrder"
     ${build_generator_args}
     --build-project LinkLineOrder
-    --build-options ${build_options}
     --test-command Exec1
     )
 
@@ -1923,7 +1771,6 @@
     "${CMake_BINARY_DIR}/Tests/LinkLineOrder"
     ${build_generator_args}
     --build-project LinkLineOrder
-    --build-options ${build_options}
     --test-command Exec2
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LinkLineOrder")
@@ -1943,7 +1790,7 @@
       "${CMake_BINARY_DIR}/Tests/LinkStatic"
       ${build_generator_args}
       --build-project LinkStatic
-      --build-options ${build_options}
+      --build-options
         -DMATH_LIBRARY:FILEPATH=/usr/lib/libm.a
       --test-command LinkStatic
       )
@@ -1958,7 +1805,6 @@
       "${CMake_BINARY_DIR}/Tests/SubDirSpaces/Executable Sources"
       ${build_generator_args}
       --build-project SUBDIR
-      --build-options ${build_options}
       --test-command test
       "${CMake_BINARY_DIR}/Tests/SubDirSpaces/ShouldBeHere"
       "${CMake_BINARY_DIR}/Tests/SubDirSpaces/testfromsubdir.obj"
@@ -1974,7 +1820,6 @@
       --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubDir/Executable"
       ${build_generator_args}
       --build-project SUBDIR
-      --build-options ${build_options}
       --test-command test
       "${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere"
       "${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.obj"
@@ -1987,7 +1832,6 @@
       --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubDir/Executable"
       ${build_generator_args}
       --build-project SUBDIR
-      --build-options ${build_options}
       --test-command test
       "${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere"
       "${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.o"
@@ -1995,9 +1839,11 @@
   endif ()
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubDir")
 
-  if(MSVC)
-    ADD_TEST_MACRO(ForceInclude foo)
+  if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC"))
     ADD_TEST_MACRO(PDBDirectoryAndName myexe)
+    if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" OR NOT "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+      ADD_TEST_MACRO(ForceInclude foo)
+    endif()
     if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
       ADD_TEST_MACRO(PrecompiledHeader foo)
     endif()
@@ -2023,7 +1869,6 @@
       ${build_generator_args}
       --build-project MakeClean
       --build-exe-dir "${CMake_BINARY_DIR}/MakeClean"
-      --build-options ${build_options}
       --test-command check_clean
       )
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/MakeClean")
@@ -2132,7 +1977,6 @@
       --build-two-config
       ${build_generator_args}
       --build-project mfc_driver
-      --build-options ${build_options}
       --test-command ${CMAKE_CTEST_COMMAND}
         -C \${CTEST_CONFIGURATION_TYPE} -VV)
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/MFC")
@@ -2162,7 +2006,6 @@
       --build-two-config
       ${build_generator_args}
       --build-project VSExternalInclude
-      --build-options ${build_options}
       --test-command VSExternalInclude)
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSExternalInclude")
 
@@ -2173,7 +2016,6 @@
       --build-two-config
       ${build_generator_args}
       --build-project VSMidl
-      --build-options ${build_options}
       --test-command VSMidl)
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSMidl")
 
@@ -2291,7 +2133,7 @@
       foreach(STP RANGE 1 4)
         add_test(NAME "TutorialStep${STP}.${name}" COMMAND ${CMAKE_CTEST_COMMAND}
           --build-and-test
-          "${CMake_SOURCE_DIR}/Tests/Tutorial/Step${STP}"
+          "${CMake_SOURCE_DIR}/Help/guide/tutorial/Step${STP}"
           "${CMake_BINARY_DIR}/Tests/Tutorial/Step${STP}_${name}"
           --build-generator "${generator}"
           --build-project Tutorial
@@ -2460,7 +2302,7 @@
         --build-project BundleTest
         --build-target install
 #       --build-target package
-        --build-options ${build_options}
+        --build-options
         "-DCMAKE_INSTALL_PREFIX:PATH=${BundleTestInstallDir}"
         "-DCMake_SOURCE_DIR:PATH=${CMake_SOURCE_DIR}"
         --test-command
@@ -2475,7 +2317,6 @@
         ${build_generator_args}
         --build-project CFBundleTest
         --build-config $<CONFIGURATION>
-        --build-options ${build_options}
         --test-command
         ${CMAKE_CMAKE_COMMAND} -DCTEST_CONFIGURATION_TYPE=$<CONFIGURATION>
         -Ddir=${CMake_BINARY_DIR}/Tests/CFBundleTest
@@ -2496,7 +2337,7 @@
       ${build_generator_args}
       --build-project BundleGeneratorTest
       --build-target package
-      --build-options ${build_options}
+      --build-options
         "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/BundleGeneratorTest/InstallDirectory"
       )
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleGeneratorTest")
@@ -2509,7 +2350,7 @@
     ${build_generator_args}
     --build-noclean
     --build-project WarnUnusedUnusedViaSet
-    --build-options ${build_options}
+    --build-options
       "--warn-unused-vars")
   set_tests_properties(WarnUnusedUnusedViaSet PROPERTIES
     PASS_REGULAR_EXPRESSION "unused variable \\(changing definition\\) 'UNUSED_VARIABLE'")
@@ -2524,7 +2365,7 @@
     ${build_generator_args}
     --build-noclean
     --build-project WarnUnusedUnusedViaUnset
-    --build-options ${build_options}
+    --build-options
       "--warn-unused-vars")
   set_tests_properties(WarnUnusedUnusedViaUnset PROPERTIES
     PASS_REGULAR_EXPRESSION "CMake Warning \\(dev\\) at CMakeLists.txt:7 \\(set\\):")
@@ -2538,7 +2379,7 @@
     "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused"
     ${build_generator_args}
     --build-project WarnUnusedCliUnused
-    --build-options ${build_options}
+    --build-options
       "-DUNUSED_CLI_VARIABLE=Unused")
   set_tests_properties(WarnUnusedCliUnused PROPERTIES
     PASS_REGULAR_EXPRESSION "CMake Warning:.*Manually-specified variables were not used by the project:.*  UNUSED_CLI_VARIABLE")
@@ -2551,7 +2392,7 @@
     ${build_generator_args}
     --build-noclean
     --build-project WarnUnusedCliUsed
-    --build-options ${build_options}
+    --build-options
       "-DUSED_VARIABLE=Usage proven")
   set_tests_properties(WarnUnusedCliUsed PROPERTIES
     PASS_REGULAR_EXPRESSION "Usage proven")
@@ -2566,7 +2407,7 @@
     ${build_generator_args}
     --build-noclean
     --build-project WarnUninitialized
-    --build-options ${build_options}
+    --build-options
       "--warn-uninitialized")
   set_tests_properties(WarnUninitialized PROPERTIES
     PASS_REGULAR_EXPRESSION "uninitialized variable 'USED_VARIABLE'")
@@ -2581,7 +2422,6 @@
     --build-project TestsWorkingDirectoryProj
     --build-exe-dir "${CMake_BINARY_DIR}/Tests/TestsWorkingDirectory"
     --force-new-ctest-process
-    --build-options ${build_options}
     --test-command ${CMAKE_CTEST_COMMAND} -V -C \${CTEST_CONFIGURATION_TYPE}
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestsWorkingDirectory")
@@ -3379,7 +3219,6 @@
       ${build_generator_args}
       --build-project testf
       --build-two-config
-      --build-options ${build_options}
       --test-command testf)
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Fortran")
 
@@ -3390,7 +3229,7 @@
         "${CMake_BINARY_DIR}/Tests/FortranModules"
         ${build_generator_args}
         --build-project FortranModules
-        --build-options ${build_options}
+        --build-options
           -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
           -DCMake_TEST_Fortran_SUBMODULES:BOOL=${CMake_TEST_Fortran_SUBMODULES}
           ${CMake_TEST_FortranModules_BUILD_OPTIONS}
@@ -3413,7 +3252,6 @@
         ${build_generator_args}
         --build-project FortranC
         --build-two-config
-        --build-options ${build_options}
         --test-command CMakeFiles/FortranCInterface/FortranCInterface)
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/FortranC")
     endif()
@@ -3442,7 +3280,6 @@
           --build-target hello
           --build-two-config
           --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/"
-          --build-options ${build_options}
           --test-command ${JAVA_RUNTIME} -classpath hello.jar HelloWorld)
         list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar")
         add_test(Java.JarSourceList ${CMAKE_CTEST_COMMAND}
@@ -3454,7 +3291,6 @@
           --build-target hello2
           --build-two-config
           --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJarSourceList/"
-          --build-options ${build_options}
           --test-command ${JAVA_RUNTIME} -classpath hello2.jar HelloWorld)
         list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceList")
         add_test(Java.JarSourceListAndOutput ${CMAKE_CTEST_COMMAND}
@@ -3466,7 +3302,6 @@
           --build-target hello3
           --build-two-config
           --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput/hello3"
-          --build-options ${build_options}
           --test-command ${JAVA_RUNTIME} -classpath hello3.jar HelloWorld)
         list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput")
 
@@ -3492,7 +3327,6 @@
               --build-project helloJavah
               --build-two-config
               --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/"
-              --build-options ${build_options}
               --test-command ${JAVA_RUNTIME} -Djava.library.path=${JAVAH_LIBRARY_PATH} -classpath hello3.jar HelloWorld2)
             list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah")
           endif()
@@ -3511,7 +3345,6 @@
               --build-project helloJavaNativeHeaders
               --build-two-config
               --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/"
-              --build-options ${build_options}
               --test-command ${JAVA_RUNTIME} -Djava.library.path=${JAVANATIVEHEADERS_LIBRARY_PATH} -classpath hello4.jar HelloWorld3)
             list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders")
           endif()
@@ -3533,9 +3366,9 @@
         "${CMake_BINARY_DIR}/Tests/SimpleCOnly_sdcc"
         ${build_generator_args}
         --build-project SimpleC
-        --build-options ${build_options}
-        "-DCMAKE_SYSTEM_NAME=Generic"
-        "-DCMAKE_C_COMPILER=${SDCC_EXECUTABLE}")
+        --build-options
+          "-DCMAKE_SYSTEM_NAME=Generic"
+          "-DCMAKE_C_COMPILER=${SDCC_EXECUTABLE}")
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SimpleCOnly_sdcc")
     endif()
 
@@ -3551,11 +3384,11 @@
         "${CMake_BINARY_DIR}/Tests/Simple_Mingw_Linux2Win"
         ${build_generator_args}
         --build-project Simple
-        --build-options ${build_options}
-        "-DCMAKE_SYSTEM_NAME=Windows"
-        "-DCMAKE_C_COMPILER=${MINGW_CC_LINUX2WIN_EXECUTABLE}"
-        "-DCMAKE_CXX_COMPILER=${MINGW_CXX_LINUX2WIN_EXECUTABLE}"
-        "-DCMAKE_RC_COMPILER=${MINGW_RC_LINUX2WIN_EXECUTABLE}"
+        --build-options
+          "-DCMAKE_SYSTEM_NAME=Windows"
+          "-DCMAKE_C_COMPILER=${MINGW_CC_LINUX2WIN_EXECUTABLE}"
+          "-DCMAKE_CXX_COMPILER=${MINGW_CXX_LINUX2WIN_EXECUTABLE}"
+          "-DCMAKE_RC_COMPILER=${MINGW_RC_LINUX2WIN_EXECUTABLE}"
         )
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Simple_Mingw_Linux2Win")
     endif()
@@ -3641,7 +3474,6 @@
     --build-two-config
     ${build_generator_args}
     --build-project IncludeDirectories
-    --build-options ${build_options}
     --test-command IncludeDirectories)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/IncludeDirectories")
 
@@ -3655,8 +3487,7 @@
       "${CMake_BINARY_DIR}/Tests/IncludeDirectoriesCPATH"
       --build-two-config
       ${build_generator_args}
-      --build-project IncludeDirectoriesCPATH
-      --build-options ${build_options})
+      --build-project IncludeDirectoriesCPATH)
     list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/IncludeDirectoriesCPATH")
     set_tests_properties(IncludeDirectoriesCPATH
       PROPERTIES
@@ -3670,7 +3501,6 @@
     --build-two-config
     ${build_generator_args}
     --build-project InterfaceLinkLibraries
-    --build-options ${build_options}
     --test-command InterfaceLinkLibraries)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InterfaceLinkLibraries")
 
diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt
index 1aeab8b..19f3f79 100644
--- a/Tests/CMakeOnly/CMakeLists.txt
+++ b/Tests/CMakeOnly/CMakeLists.txt
@@ -84,5 +84,5 @@
 endfunction()
 
 add_major_test(PythonLibs VERSIONS 2 3 VERSION_VAR PYTHONLIBS_VERSION_STRING)
-add_major_test(PythonInterp NOLANG VERSIONS 2 3 VERSION_VAR PYTHON_VERSION_STRING)
+add_major_test(PythonInterp NOLANG VERSIONS 3 VERSION_VAR PYTHON_VERSION_STRING)
 add_major_test(Qt VERSIONS 3 4 VERSION_VAR QT_VERSION_STRING)
diff --git a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
index f058c19..2028a13 100644
--- a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
@@ -49,6 +49,15 @@
   message(STATUS "errno found in <cerrno>")
 endif ()
 
+check_cxx_symbol_exists("std::fopen" "cstdio" CSE_RESULT_FOPEN)
+if (NOT CSE_RESULT_FOPEN)
+  if(NOT ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10))
+    message(SEND_ERROR "CheckCXXSymbolExists did not find std::fopen in <cstdio>")
+  endif()
+else()
+  message(STATUS "std::fopen found in <cstdio>")
+endif()
+
 if (CMAKE_COMPILER_IS_GNUCXX)
   string(APPEND CMAKE_CXX_FLAGS " -O3")
   unset(CSE_RESULT_O3 CACHE)
@@ -60,3 +69,8 @@
     message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol as existing with optimization -O3")
   endif ()
 endif ()
+
+check_cxx_symbol_exists("std::non_existent_function_for_symbol_test<int*>" "algorithm" CSE_RESULT_NON_SYMBOL)
+if (CSE_RESULT_NON_SYMBOL)
+  message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol.")
+endif()
diff --git a/Tests/CMakeServerLib/testServerBuffering.cpp b/Tests/CMakeServerLib/testServerBuffering.cpp
index 7330ead..8b0b89b 100644
--- a/Tests/CMakeServerLib/testServerBuffering.cpp
+++ b/Tests/CMakeServerLib/testServerBuffering.cpp
@@ -1,6 +1,8 @@
 #include "cmConnection.h"
 #include "cmServerConnection.h"
+
 #include <iostream>
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/Tests/CMakeTests/ELFTest.cmake.in b/Tests/CMakeTests/ELFTest.cmake.in
index 4635778..85c2360 100644
--- a/Tests/CMakeTests/ELFTest.cmake.in
+++ b/Tests/CMakeTests/ELFTest.cmake.in
@@ -25,11 +25,36 @@
   # Change the RPATH.
   file(RPATH_CHANGE FILE "${f}"
     OLD_RPATH "/sample/rpath"
-    NEW_RPATH "/rpath/sample")
+    NEW_RPATH "/path1:/path2")
+  set(rpath)
+  file(STRINGS "${f}" rpath REGEX "/path1:/path2" LIMIT_COUNT 1)
+  if(NOT rpath)
+    message(FATAL_ERROR "RPATH not changed in ${f}")
+  endif()
+
+  # Change the RPATH without compiler defined rpath removed
+  file(RPATH_CHANGE FILE "${f}"
+    OLD_RPATH "/path2"
+    NEW_RPATH "/path3")
+  set(rpath)
+  file(STRINGS "${f}" rpath REGEX "/path1:/path3" LIMIT_COUNT 1)
+  if(NOT rpath)
+    message(FATAL_ERROR "RPATH not updated in ${f}")
+  endif()
+
+  # Change the RPATH with compiler defined rpath removed
+  file(RPATH_CHANGE FILE "${f}"
+    OLD_RPATH "/path3"
+    NEW_RPATH "/rpath/sample"
+    INSTALL_REMOVE_ENVIRONMENT_RPATH)
   set(rpath)
   file(STRINGS "${f}" rpath REGEX "/rpath/sample" LIMIT_COUNT 1)
   if(NOT rpath)
-    message(FATAL_ERROR "RPATH not changed in ${f}")
+    message(FATAL_ERROR "RPATH not updated in ${f}")
+  endif()
+  file(STRINGS "${f}" rpath REGEX "/path1" LIMIT_COUNT 1)
+  if(rpath)
+    message(FATAL_ERROR "RPATH not removed in ${f}")
   endif()
 
   # Remove the RPATH.
diff --git a/Tests/CPackComponentsDEB/CMakeLists.txt b/Tests/CPackComponentsDEB/CMakeLists.txt
index 9d4b5e9..bc5b6a9 100644
--- a/Tests/CPackComponentsDEB/CMakeLists.txt
+++ b/Tests/CPackComponentsDEB/CMakeLists.txt
@@ -4,8 +4,8 @@
 # application (mylibapp). We create a binary installer (a CPack Generator)
 # which supports CPack components.
 
-cmake_minimum_required(VERSION 2.8.3.20101130 FATAL_ERROR)
-project(CPackComponentsDEB)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
+project(CPackComponentsDEB VERSION 1.0.3)
 
 # Use GNUInstallDirs in order to enforce lib64 if needed
 include(GNUInstallDirs)
@@ -44,10 +44,6 @@
 set(CPACK_PACKAGE_CONTACT "None")
 set(CPACK_PACKAGE_VENDOR "CMake.org")
 set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyLib - CPack Component Installation Example")
-set(CPACK_PACKAGE_VERSION "1.0.2")
-set(CPACK_PACKAGE_VERSION_MAJOR "1")
-set(CPACK_PACKAGE_VERSION_MINOR "0")
-set(CPACK_PACKAGE_VERSION_PATCH "2")
 set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example")
 set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/license.txt)
 
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake
index 73fd0ab..beccc46 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake
@@ -6,7 +6,7 @@
 
 
 # expected results
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
 set(expected_count 3)
 
 
@@ -36,7 +36,6 @@
 # dpkg-deb checks for the dependencies of the packages
 find_program(DPKGDEB_EXECUTABLE dpkg-deb)
 if(DPKGDEB_EXECUTABLE)
-  set(dpkgdeb_output_errors_all "")
   foreach(_f IN LISTS actual_output)
 
     # extracts the metadata from the package
@@ -54,32 +53,23 @@
 
     message(STATUS "package='${dpkg_package_name}', dependencies='${dpkg_depends}'")
 
-    if("${dpkg_package_name}" STREQUAL "mylib-applications")
-      if(NOT "${dpkg_depends}" STREQUAL "depend-application")
-        set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
-                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-application'\n")
+    if(dpkg_package_name STREQUAL "mylib-applications")
+      if(NOT dpkg_depends STREQUAL "depend-application")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-application'\n")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-headers")
-      if(NOT "${dpkg_depends}" STREQUAL "mylib-libraries (= 1.0.2), depend-headers")
-        set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
-                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.2), depend-headers'\n")
+    elseif(dpkg_package_name STREQUAL "mylib-headers")
+      if(NOT dpkg_depends STREQUAL "mylib-libraries (= 1.0.3), depend-headers")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.3), depend-headers'\n")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-libraries")
-      if(NOT "${dpkg_depends}" STREQUAL "depend-default")
-        set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
-                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n")
+    elseif(dpkg_package_name STREQUAL "mylib-libraries")
+      if(NOT dpkg_depends STREQUAL "depend-default")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n")
       endif()
     else()
-      set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
-                                    "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n")
+      message(SEND_ERROR "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n")
     endif()
 
   endforeach()
-
-
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
-    message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
-  endif()
 else()
   message("dpkg-deb executable not found - skipping dpkg-deb test")
 endif()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake
index 81dbbc5..88f3248 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake
@@ -6,7 +6,7 @@
 
 
 # expected results
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
 set(expected_count 3)
 
 set(config_verbose -V)
@@ -36,7 +36,6 @@
 # dpkg-deb checks for the summary of the packages
 find_program(DPKGDEB_EXECUTABLE dpkg-deb)
 if(DPKGDEB_EXECUTABLE)
-  set(dpkgdeb_output_errors_all "")
   foreach(_f IN LISTS actual_output)
 
     # extracts the metadata from the package
@@ -54,13 +53,11 @@
 
     message(STATUS "package='${dpkg_package_name}', dependencies='${dpkg_depends}'")
 
-    if("${dpkg_package_name}" STREQUAL "mylib-applications")
+    if(dpkg_package_name STREQUAL "mylib-applications")
       find_program(DPKG_SHLIBDEP_EXECUTABLE dpkg-shlibdeps)
       if(DPKG_SHLIBDEP_EXECUTABLE)
-        string(FIND "${dpkg_depends}" "lib" index_libwhatever)
-        if(NOT index_libwhatever GREATER "-1")
-          set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                        "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does not contain any 'lib'\n")
+        if(NOT dpkg_depends MATCHES "lib")
+          message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does not contain any 'lib'\n")
         endif()
       else()
         message("dpkg-shlibdeps executable not found - skipping dpkg-shlibdeps test")
@@ -69,29 +66,20 @@
       # should not contain the default
       string(FIND "${dpkg_depends}" "depend-default" index_default)
       if(index_default GREATER "0")
-        set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does contains 'depend-default'\n")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does contains 'depend-default'\n")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-headers")
-      if(NOT "${dpkg_depends}" STREQUAL "mylib-libraries (= 1.0.2), depend-headers")
-        set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.2), depend-headers'\n")
+    elseif(dpkg_package_name STREQUAL "mylib-headers")
+      if(NOT dpkg_depends STREQUAL "mylib-libraries (= 1.0.3), depend-headers")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.3), depend-headers'\n")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-libraries")
-      if(NOT "${dpkg_depends}" STREQUAL "depend-default")
-        set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                      "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n")
+    elseif(dpkg_package_name STREQUAL "mylib-libraries")
+      if(NOT dpkg_depends STREQUAL "depend-default")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n")
       endif()
     else()
-      set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                    "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n")
+      message(SEND_ERROR "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n")
     endif()
-
   endforeach()
-
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
-    message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
-  endif()
 else()
   message("dpkg-deb executable not found - skipping dpkg-deb test")
 endif()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake
index ad52f56..f74137c 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake
@@ -6,7 +6,7 @@
 
 
 # expected results
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
 set(expected_count 3)
 
 
@@ -54,18 +54,18 @@
 
     message(STATUS "package='${dpkg_package_name}', description='${dpkg_description}'")
 
-    if("${dpkg_package_name}" STREQUAL "mylib-applications")
+    if(dpkg_package_name STREQUAL "mylib-applications")
       if(NOT "${dpkg_description}" STREQUAL "applications_description")
         set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
                                       "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != applications_description")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-headers")
-      if(NOT "${dpkg_description}" STREQUAL "headers_description")
+    elseif(dpkg_package_name STREQUAL "mylib-headers")
+      if(NOT dpkg_description STREQUAL "headers_description")
         set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
                                       "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != headers_description")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-libraries")
-      if(NOT "${dpkg_description}" STREQUAL "main description")
+    elseif(dpkg_package_name STREQUAL "mylib-libraries")
+      if(NOT dpkg_description STREQUAL "main description")
         set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
                                       "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != 'main description'")
       endif()
@@ -77,7 +77,7 @@
   endforeach()
 
 
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
+  if(NOT dpkgdeb_output_errors_all STREQUAL "")
     message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
   endif()
 else()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake
index af27c51..241dda5 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake
@@ -7,7 +7,7 @@
 
 
 # expected results
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
 set(expected_count 3)
 
 
@@ -54,18 +54,18 @@
 
     message(STATUS "package='${dpkg_package_name}', description='${dpkg_description}'")
 
-    if("${dpkg_package_name}" STREQUAL "mylib-applications")
-      if(NOT "${dpkg_description}" STREQUAL "main description 2")
+    if(dpkg_package_name STREQUAL "mylib-applications")
+      if(NOT dpkg_description STREQUAL "main description 2")
         set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
                                       "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != applications_description")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-headers")
-      if(NOT "${dpkg_description}" STREQUAL "main description 2")
+    elseif(dpkg_package_name STREQUAL "mylib-headers")
+      if(NOT dpkg_description STREQUAL "main description 2")
         set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
                                       "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != headers_description")
       endif()
-    elseif("${dpkg_package_name}" STREQUAL "mylib-libraries")
-      if(NOT "${dpkg_description}" STREQUAL "library description")
+    elseif(dpkg_package_name STREQUAL "mylib-libraries")
+      if(NOT dpkg_description STREQUAL "library description")
         set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
                                       "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != 'main description'")
       endif()
@@ -77,7 +77,7 @@
   endforeach()
 
 
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
+  if(NOT dpkgdeb_output_errors_all STREQUAL "")
     message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
   endif()
 else()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake
index ec75d61..7cfbb16 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake
@@ -5,7 +5,7 @@
 include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake)
 
 # TODO: currently debian doesn't produce lower cased names
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
 set(expected_count 3)
 
 
@@ -44,7 +44,7 @@
     string(APPEND lintian_output_errors_all "${lintian_output_errors}")
   endforeach()
 
-  if(NOT "${lintian_output_errors_all}" STREQUAL "")
+  if(NOT lintian_output_errors_all STREQUAL "")
     message(FATAL_ERROR "Lintian checks failed:\n${lintian_output_errors_all}")
   endif()
 else()
@@ -64,13 +64,13 @@
                                       DPKGDEB_OUTPUT "${dpkg_output}"
                                       METAENTRY "Maintainer:")
 
-    if(NOT "${dpkgentry}" STREQUAL "None")
+    if(NOT dpkgentry STREQUAL "None")
       set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
           "dpkg-deb: ${_f}: Incorrect value for Maintainer: ${dpkgentry} != None\n")
     endif()
   endforeach()
 
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
+  if(NOT dpkgdeb_output_errors_all STREQUAL "")
     message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
   endif()
 else()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake
index e57488c..6eff3db 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake
@@ -9,7 +9,7 @@
 # requirements
 
 # debian now produces lower case names
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
 set(expected_count 3)
 
 
@@ -39,7 +39,7 @@
 # dpkg-deb checks for the summary of the packages
 find_program(DPKGDEB_EXECUTABLE dpkg-deb)
 if(DPKGDEB_EXECUTABLE)
-  set(dpkgdeb_output_errors_all)
+  set(dpkgdeb_output_errors_all "")
   foreach(_f IN LISTS actual_output)
 
     # extracts the metadata from the package
@@ -53,11 +53,11 @@
 
     message(STATUS "package='${dpkg_package_name}'")
 
-    if("${dpkg_package_name}" STREQUAL "mylib-applications")
+    if(dpkg_package_name STREQUAL "mylib-applications")
       # pass
-    elseif("${dpkg_package_name}" STREQUAL "mylib-headers")
+    elseif(dpkg_package_name STREQUAL "mylib-headers")
       # pass
-    elseif("${dpkg_package_name}" STREQUAL "mylib-libraries")
+    elseif(dpkg_package_name STREQUAL "mylib-libraries")
       # pass
     else()
       set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
@@ -67,7 +67,7 @@
   endforeach()
 
 
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
+  if(NOT dpkgdeb_output_errors_all STREQUAL "")
     message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
   endif()
 else()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake
index 5ee057a..3454dca 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake
@@ -6,7 +6,7 @@
 
 
 # expected results
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
 set(expected_count 3)
 
 set(config_verbose -V)
@@ -36,7 +36,6 @@
 # dpkg-deb checks for the summary of the packages
 find_program(DPKGDEB_EXECUTABLE dpkg-deb)
 if(DPKGDEB_EXECUTABLE)
-  set(dpkgdeb_output_errors_all "")
   foreach(_f IN LISTS actual_output)
 
     # extracts the metadata from the package
@@ -54,22 +53,16 @@
 
     message(STATUS "package='${_f}', source='${dpkg_package_source}'")
 
-    if(NOT ("${dpkg_package_name}" STREQUAL "mylib-applications"))
-      if(NOT ("${dpkg_package_source}" STREQUAL "test-source"))
-          set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                        "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-source'\n")
+    if(NOT dpkg_package_name STREQUAL "mylib-applications")
+      if(NOT dpkg_package_source STREQUAL "test-source")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-source'\n")
       endif()
     else()
-      if(NOT ("${dpkg_package_source}" STREQUAL "test-other-source"))
-          set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                        "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-other-source'\n")
+      if(NOT dpkg_package_source STREQUAL "test-other-source")
+        message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-other-source'\n")
       endif()
     endif()
   endforeach()
-
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
-    message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
-  endif()
 else()
   message("dpkg-deb executable not found - skipping dpkg-deb test")
 endif()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake
index 8c0bc4b..764fe9d 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake
@@ -5,7 +5,7 @@
 include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake)
 
 # TODO: currently debian doesn't produce lower cased names
-set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib_1.0.2_*.deb")
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib_1.0.3_*.deb")
 set(expected_count 1)
 
 set(actual_output)
@@ -33,22 +33,16 @@
 # dpkg-deb checks
 find_program(DPKGDEB_EXECUTABLE dpkg-deb)
 if(DPKGDEB_EXECUTABLE)
-  set(dpkgdeb_output_errors_all "")
   foreach(_f IN LISTS actual_output)
     run_dpkgdeb(dpkg_output
                 FILENAME "${_f}"
                 )
 
     # message(FATAL_ERROR "output = '${dpkg_output}'")
-    if("${dpkg_output}" STREQUAL "")
-      set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}"
-                                    "dpkg-deb: ${_f}: empty content returned by dpkg-deb")
+    if(dpkg_output STREQUAL "")
+      message(SEND_ERROR "dpkg-deb: ${_f}: empty content returned by dpkg-deb")
     endif()
   endforeach()
-
-  if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "")
-    message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
-  endif()
 else()
   message("dpkg-deb executable not found - skipping dpkg-deb test")
 endif()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
index 2f9e2fc..2093e7e 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
@@ -119,13 +119,13 @@
   # regex to avoid
   foreach(_s IN LISTS lintian_check_specific_errors_deb_ERROR_REGEX_STRINGS)
 
-    if("${_s}" STREQUAL "")
+    if(_s STREQUAL "")
        continue()
     endif()
 
     string(REGEX MATCHALL "${_s}" "_TMP_CHECK_ERROR" "${lintian_output}")
 
-    if(NOT "${_TMP_CHECK_ERROR}" STREQUAL "")
+    if(NOT _TMP_CHECK_ERROR STREQUAL "")
       string(APPEND ERROR_ACC "\nlintian: ${_f}: output contains an undesirable regex:\n\t${_TMP_CHECK_ERROR}")
     endif()
   endforeach()
@@ -167,7 +167,7 @@
       ERROR_VARIABLE DPKGDEB_ERROR
       OUTPUT_STRIP_TRAILING_WHITESPACE )
 
-    if(NOT ("${DPKGDEB_RESULT}" EQUAL "0"))
+    if(NOT DPKGDEB_RESULT EQUAL "0")
       message(FATAL_ERROR "Error '${DPKGDEB_RESULT}' returned by dpkg-deb: '${DPKGDEB_ERROR}'")
     endif()
 
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index 5adcbd9..093391e 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -421,7 +421,7 @@
 
   set(local_git_repo "../../LocalRepositories/GIT-with-submodules")
 
-  set(proj TS1-GIT-no-GIT_SUBMODULES)
+  set(proj TS1-GIT-all-GIT_SUBMODULES)
   ExternalProject_Add(${proj}
     GIT_REPOSITORY "${local_git_repo}"
     CMAKE_GENERATOR "${CMAKE_GENERATOR}"
@@ -435,7 +435,8 @@
   )
   set_property(TARGET ${proj} PROPERTY FOLDER "GIT")
 
-  set(proj TS1-GIT-empty-GIT_SUBMODULES)
+  set(proj TS1-GIT-all-GIT_SUBMODULES-via-CMP0097-OLD)
+  cmake_policy(SET CMP0097 OLD)
   ExternalProject_Add(${proj}
     GIT_REPOSITORY "${local_git_repo}"
     GIT_SUBMODULES ""
@@ -450,6 +451,22 @@
   )
   set_property(TARGET ${proj} PROPERTY FOLDER "GIT")
 
+  set(proj TS1-GIT-no-GIT_SUBMODULES)
+  cmake_policy(SET CMP0097 NEW)
+  ExternalProject_Add(${proj}
+    GIT_REPOSITORY "${local_git_repo}"
+    GIT_SUBMODULES ""
+    CMAKE_GENERATOR "${CMAKE_GENERATOR}"
+    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
+               -DWITH_m1:BOOL=OFF
+               -DWITH_m2:BOOL=OFF
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    DEPENDS "SetupLocalGITRepository"
+            "SetupLocalGITRepositoryWithSubmodules"
+  )
+  set_property(TARGET ${proj} PROPERTY FOLDER "GIT")
+
   set(proj TS1-GIT-some-GIT_SUBMODULES)
   ExternalProject_Add(${proj}
     GIT_REPOSITORY "${local_git_repo}"
diff --git a/Tests/FindMatlab/basic_checks/CMakeLists.txt b/Tests/FindMatlab/basic_checks/CMakeLists.txt
index c5be1ea..c0c752a 100644
--- a/Tests/FindMatlab/basic_checks/CMakeLists.txt
+++ b/Tests/FindMatlab/basic_checks/CMakeLists.txt
@@ -71,3 +71,15 @@
         )
     set_tests_properties(${PROJECT_NAME}_matlabtest-4 PROPERTIES WILL_FAIL TRUE)
 endif()
+
+
+# checking correct flags passed
+# EXCLUDE_FROM_ALL appears after a multiargs (like SRC)
+matlab_add_mex(
+    # target name
+    NAME cmake_matlab_test_exclude_from_all
+    # output name
+    OUTPUT_NAME cmake_matlab_mex_dummy
+    SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper_failure.cpp
+    EXCLUDE_FROM_ALL
+    )
diff --git a/Tests/FindMatlab/matlab_wrapper_failure.cpp b/Tests/FindMatlab/matlab_wrapper_failure.cpp
new file mode 100644
index 0000000..3fe437b
--- /dev/null
+++ b/Tests/FindMatlab/matlab_wrapper_failure.cpp
@@ -0,0 +1,13 @@
+// This should not link, as the mex function is missing.
+// This is mostly for checking we are passing the right arguments to the
+// add_library
+
+#include <algorithm>
+
+#include "mex.h"
+
+void mexFunctionXX(const int nlhs, mxArray* plhs[], const int nrhs,
+                   const mxArray* prhs[])
+{
+  mexErrMsgTxt("Should not be running");
+}
diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt
index da79f5d..519608c 100644
--- a/Tests/FindPackageTest/CMakeLists.txt
+++ b/Tests/FindPackageTest/CMakeLists.txt
@@ -391,16 +391,44 @@
 message(STATUS "Searching for export(PACKAGE) test project")
 set(CMakeTestExportPackage_DIR "" CACHE FILEPATH
   "Wipe out find results for testing." FORCE)
-find_package(CMakeTestExportPackage 1.${version} EXACT REQUIRED)
 
-message(STATUS "Searching for export(PACKAGE) test project with CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=TRUE")
+message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_USE_PACKAGE_REGISTRY=TRUE")
+set(CMAKE_FIND_USE_PACKAGE_REGISTRY TRUE)
+find_package(CMakeTestExportPackage 1.${version} EXACT REQUIRED)
+if(NOT CMakeTestExportPackage_FOUND)
+  message(SEND_ERROR "CMakeTestExportPackage should be FOUND!")
+endif()
+unset(CMAKE_FIND_USE_PACKAGE_REGISTRY)
+
+message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=FALSE")
+set(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY FALSE)
+find_package(CMakeTestExportPackage 1.${version} EXACT REQUIRED)
+if(NOT CMakeTestExportPackage_FOUND)
+  message(SEND_ERROR "CMakeTestExportPackage should be FOUND!")
+endif()
+unset(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY)
+
+message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_USE_PACKAGE_REGISTRY=TRUE and CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=TRUE")
+set(CMAKE_FIND_USE_PACKAGE_REGISTRY TRUE)
 set(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY TRUE)
+set(CMakeTestExportPackage_DIR FALSE)
+find_package(CMakeTestExportPackage 1.${version} EXACT REQUIRED)
+if(NOT CMakeTestExportPackage_FOUND)
+  message(SEND_ERROR "CMakeTestExportPackage should be FOUND!")
+endif()
+unset(CMAKE_FIND_USE_PACKAGE_REGISTRY)
+unset(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY)
+
+message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_USE_PACKAGE_REGISTRY=FALSE and CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=FALSE")
+set(CMAKE_FIND_USE_PACKAGE_REGISTRY FALSE)
+set(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY FALSE)
 set(CMakeTestExportPackage_DIR "" CACHE FILEPATH
   "Wipe out find results for testing." FORCE)
-find_package(CMakeTestExportPackage  1.${version} EXACT QUIET)
+find_package(CMakeTestExportPackage 1.${version} EXACT QUIET)
 if(CMakeTestExportPackage_FOUND)
-  message(SEND_ERROR "CMakeTestExportPackage should not be FOUND!")
+  message(SEND_ERROR "CMakeTestExportPackage should be not FOUND!")
 endif()
+unset(CMAKE_FIND_USE_PACKAGE_REGISTRY)
 unset(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY)
 
 message(STATUS "Remove export(PACKAGE) test project")
diff --git a/Tests/FindProtobuf/Test/CMakeLists.txt b/Tests/FindProtobuf/Test/CMakeLists.txt
index bc89190..fc6b37e 100644
--- a/Tests/FindProtobuf/Test/CMakeLists.txt
+++ b/Tests/FindProtobuf/Test/CMakeLists.txt
@@ -29,6 +29,7 @@
 add_executable(test_var_protoc main-protoc.cxx)
 target_include_directories(test_var_protoc PRIVATE ${Protobuf_INCLUDE_DIRS})
 target_link_libraries(test_var_protoc PRIVATE ${Protobuf_PROTOC_LIBRARIES})
+target_compile_features(test_var_protoc PRIVATE cxx_std_11)
 add_test(NAME test_var_protoc COMMAND test_var_protoc)
 
 add_test(NAME test_tgt_protoc_version COMMAND protobuf::protoc --version)
@@ -37,14 +38,17 @@
 PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER msgs/example.proto)
 PROTOBUF_GENERATE_CPP(DESC_PROTO_SRC DESC_PROTO_HEADER DESCRIPTORS DESC_PROTO_DESC msgs/example_desc.proto)
 add_library(msgs ${PROTO_SRC} ${PROTO_HEADER})
+target_compile_features(msgs PRIVATE cxx_std_11)
 
 add_executable(test_generate main-generate.cxx ${PROTO_SRC})
 target_include_directories(test_generate PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 target_link_libraries(test_generate msgs ${Protobuf_LIBRARIES})
+target_compile_features(test_generate PRIVATE cxx_std_11)
 add_test(NAME test_generate COMMAND test_generate)
 
 add_executable(test_desc main-desc.cxx ${DESC_PROTO_SRC})
 target_compile_features(test_desc PRIVATE cxx_std_11)
 target_include_directories(test_desc PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 target_link_libraries(test_desc msgs ${Protobuf_LIBRARIES})
+target_compile_features(test_desc PRIVATE cxx_std_11)
 add_test(NAME test_desc COMMAND test_desc ${DESC_PROTO_DESC})
diff --git a/Tests/FindPython/FindPythonScript.cmake b/Tests/FindPython/FindPythonScript.cmake
index 9450092..bc7e0d1 100644
--- a/Tests/FindPython/FindPythonScript.cmake
+++ b/Tests/FindPython/FindPythonScript.cmake
@@ -1 +1,9 @@
-find_package(${PYTHON_PACKAGE_NAME} REQUIRED QUIET)
+
+if (PYTHON_MUST_NOT_BE_FOUND)
+  find_package(${PYTHON_PACKAGE_NAME} QUIET)
+  if (${PYTHON_PACKAGE_NAME}_FOUND)
+    message(FATAL_ERROR "${PYTHON_PACKAGE_NAME}: unexpectedly founded.")
+  endif()
+else()
+  find_package(${PYTHON_PACKAGE_NAME} REQUIRED QUIET)
+endif()
diff --git a/Tests/FindPython/Python2/CMakeLists.txt b/Tests/FindPython/Python2/CMakeLists.txt
index 274745a..cf77ca2 100644
--- a/Tests/FindPython/Python2/CMakeLists.txt
+++ b/Tests/FindPython/Python2/CMakeLists.txt
@@ -34,4 +34,5 @@
 
 add_test(NAME findpython2_script
          COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python2
+         -DPython2_FIND_STRATEGY=${Python2_FIND_STRATEGY}
          -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake")
diff --git a/Tests/FindPython/Python3/CMakeLists.txt b/Tests/FindPython/Python3/CMakeLists.txt
index b21a15b..6691a48 100644
--- a/Tests/FindPython/Python3/CMakeLists.txt
+++ b/Tests/FindPython/Python3/CMakeLists.txt
@@ -34,4 +34,57 @@
 
 add_test(NAME findpython3_script
          COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python3
+         -DPython3_FIND_STRATEGY=${Python3_FIND_STRATEGY}
+         -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake")
+
+
+## Try a new search specifying only expected ABI
+# retrieve ABI of python interpreter
+execute_process (COMMAND "${Python3_EXECUTABLE}" -c
+                         "import sys; sys.stdout.write(sys.abiflags)"
+                 RESULT_VARIABLE result
+                 OUTPUT_VARIABLE abi
+                 ERROR_QUIET
+                 OUTPUT_STRIP_TRAILING_WHITESPACE)
+if (result)
+  # assume ABI is not supported
+  set (abi "")
+endif()
+
+# define FIND_ABI variable
+if (abi MATCHES "d")
+  set (Python3_VALID_ABI "ON")
+else()
+  set (Python3_VALID_ABI "OFF")
+endif()
+if (abi MATCHES "m")
+  list (APPEND Python3_VALID_ABI "ON")
+else()
+  list (APPEND Python3_VALID_ABI "OFF")
+endif()
+if (abi MATCHES "u")
+  list (APPEND Python3_VALID_ABI "ON")
+else()
+  list (APPEND Python3_VALID_ABI "OFF")
+endif()
+# build an invalid pattern for ABI
+set (Python3_INVALID_ABI)
+foreach (abi IN LISTS Python3_VALID_ABI)
+  if (abi)
+    list (APPEND Python3_INVALID_ABI "OFF")
+  else()
+    list (APPEND Python3_INVALID_ABI "ON")
+  endif()
+endforeach()
+
+add_test(NAME python3_find_valid_abi
+         COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python3
+         -DPython3_FIND_STRATEGY=${Python3_FIND_STRATEGY}
+         "-DPython3_FIND_ABI=${Python3_VALID_ABI}"
+         -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake")
+add_test(NAME python3_find_invalid_abi
+         COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python3
+         -DPYTHON_MUST_NOT_BE_FOUND=ON
+         -DPython3_FIND_STRATEGY=${Python3_FIND_STRATEGY}
+         "-DPython3_FIND_ABI=${Python3_INVALID_ABI}"
          -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake")
diff --git a/Tests/MathTest/CMakeLists.txt b/Tests/MathTest/CMakeLists.txt
index 5403d29..396f633 100644
--- a/Tests/MathTest/CMakeLists.txt
+++ b/Tests/MathTest/CMakeLists.txt
@@ -16,6 +16,8 @@
   "1000 -12*5"
   "1000 +12*-5"
   "1000 -12*-5"
+  "~~1"
+  "1000 & ~0"
   )
 
 set(FILE_EXPRESSIONS "extern void test_expression(int x, int y, const char * text);\n")
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
index 6d8d6cc..44194ca 100644
--- a/Tests/PDBDirectoryAndName/CMakeLists.txt
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -3,8 +3,8 @@
 project(PDBDirectoryAndName C)
 
 # Make sure the proper compiler is in use.
-if(NOT MSVC AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
-  message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel")
+if(NOT MSVC AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
+  message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC, Clang or Intel")
 endif()
 
 # Intel 11.1 does not support /Fd but Intel 14.0 does.
diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt
index 588af03..bce1b3f 100644
--- a/Tests/Preprocess/CMakeLists.txt
+++ b/Tests/Preprocess/CMakeLists.txt
@@ -29,7 +29,10 @@
   set(PP_VS 1)
 endif()
 if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND
-   "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" AND
+   "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
+   set(CLANG_MSVC_WINDOWS 1)
+endif()
+if(CLANG_MSVC_WINDOWS AND
    "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
    set(CLANG_GNULIKE_WINDOWS 1)
 endif()
@@ -106,7 +109,7 @@
 set(EXPR_OP1 "/")
 if((NOT MSVC OR PP_NMAKE) AND
    NOT CMAKE_C_COMPILER_ID STREQUAL "Intel" AND
-   NOT CLANG_GNULIKE_WINDOWS)
+   NOT CLANG_MSVC_WINDOWS)
   # MSVC cl, Intel icl: %
   # When the cl compiler is invoked from the command line then % must
   # be written %% (to distinguish from %ENV% syntax).  However cl does
diff --git a/Tests/QtAutogen/SameName/CMakeLists.txt b/Tests/QtAutogen/SameName/CMakeLists.txt
index 0a80d5e..1919cc7 100644
--- a/Tests/QtAutogen/SameName/CMakeLists.txt
+++ b/Tests/QtAutogen/SameName/CMakeLists.txt
@@ -18,9 +18,11 @@
   ccc/data.qrc
   item.cpp
   object.h
+  object.hh
   object.h++
   object.hpp
   object.hxx
+  object_upper_ext.H
   data.qrc
   main.cpp
 )
diff --git a/Tests/QtAutogen/SameName/main.cpp b/Tests/QtAutogen/SameName/main.cpp
index 92f15cd..725f4cd 100644
--- a/Tests/QtAutogen/SameName/main.cpp
+++ b/Tests/QtAutogen/SameName/main.cpp
@@ -6,8 +6,10 @@
 #include "item.hpp"
 #include "object.h"
 #include "object.h++"
+#include "object.hh"
 #include "object.hpp"
 #include "object.hxx"
+#include "object_upper_ext.H"
 
 int main(int argv, char** args)
 {
@@ -20,8 +22,10 @@
   ::ccc::Item ccc_item;
   // Object instances
   ::Object_h obj_h;
+  ::Object_hh obj_hh;
   ::Object_hplpl obj_hplpl;
   ::Object_hpp obj_hpp;
   ::Object_hxx obj_hxx;
+  ::Object_Upper_Ext_H obj_upper_ext_h;
   return 0;
 }
diff --git a/Tests/QtAutogen/SameName/object.hh b/Tests/QtAutogen/SameName/object.hh
new file mode 100644
index 0000000..3e16f83
--- /dev/null
+++ b/Tests/QtAutogen/SameName/object.hh
@@ -0,0 +1,13 @@
+#ifndef OBJECT_HH
+#define OBJECT_HH
+
+#include <QObject>
+
+class Object_hh : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go(){};
+};
+
+#endif
diff --git a/Tests/QtAutogen/SameName/object_upper_ext.H b/Tests/QtAutogen/SameName/object_upper_ext.H
new file mode 100644
index 0000000..3266087
--- /dev/null
+++ b/Tests/QtAutogen/SameName/object_upper_ext.H
@@ -0,0 +1,13 @@
+#ifndef OBJECT_UPPER_EXT_H
+#define OBJECT_UPPER_EXT_H
+
+#include <QObject>
+
+class Object_Upper_Ext_H : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go(){};
+};
+
+#endif
diff --git a/Tests/RunCMake/Android/common.cmake b/Tests/RunCMake/Android/common.cmake
index aaa7c89..d96ab86 100644
--- a/Tests/RunCMake/Android/common.cmake
+++ b/Tests/RunCMake/Android/common.cmake
@@ -6,8 +6,6 @@
 endif()
 
 foreach(f
-    "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}"
-    "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}g++${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
     "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ar${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
     "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ld${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
     )
@@ -51,23 +49,26 @@
   endif()
 endif()
 
-execute_process(
-  COMMAND "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}" -dumpmachine
-  OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE
-  ERROR_VARIABLE _err
-  RESULT_VARIABLE _res
-  )
-if(NOT _res EQUAL 0)
-  message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}")
-endif()
-string(REPLACE "--" "-" _out_check "${_out}")
-if(NOT _out_check STREQUAL "${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
-    AND NOT (_out STREQUAL "arm--linux-android" AND CMAKE_C_ANDROID_TOOLCHAIN_MACHINE STREQUAL "arm-linux-androideabi"))
-  message(SEND_ERROR "'gcc -dumpmachine' produced:\n"
-    " ${_out}\n"
-    "which does not match CMAKE_C_ANDROID_TOOLCHAIN_MACHINE:\n"
-    " ${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
+set(gcc ${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX})
+if(EXISTS "${gcc}")
+  execute_process(
+    COMMAND "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}" -dumpmachine
+    OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE
+    ERROR_VARIABLE _err
+    RESULT_VARIABLE _res
     )
+  if(NOT _res EQUAL 0)
+    message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}")
+  endif()
+  string(REPLACE "--" "-" _out_check "${_out}")
+  if(NOT _out_check STREQUAL "${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
+      AND NOT (_out STREQUAL "arm--linux-android" AND CMAKE_C_ANDROID_TOOLCHAIN_MACHINE STREQUAL "arm-linux-androideabi"))
+    message(SEND_ERROR "'gcc -dumpmachine' produced:\n"
+      " ${_out}\n"
+      "which does not match CMAKE_C_ANDROID_TOOLCHAIN_MACHINE:\n"
+      " ${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
+      )
+  endif()
 endif()
 
 if(CMAKE_ANDROID_STL_TYPE STREQUAL "none")
diff --git a/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt b/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt
index 8d0bdc2..a228ccc 100644
--- a/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm64', ABI 'arm64-v8a', and processor 'aarch64'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt
index 3741da3..72ec00e 100644
--- a/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt
@@ -1,3 +1,3 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi', and processor 'armv5te'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
 .*-- CMAKE_ANDROID_ARM_MODE=1
diff --git a/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt
index ac2bfd5..8bd87fa 100644
--- a/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt
@@ -1,3 +1,3 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi-v7a', and processor 'armv7-a'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
 .*-- CMAKE_ANDROID_ARM_NEON=1
diff --git a/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt
index 0edb4f7..554548e 100644
--- a/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt
@@ -1,3 +1,3 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi-v7a', and processor 'armv7-a'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
 .*-- CMAKE_ANDROID_ARM_NEON=0
diff --git a/Tests/RunCMake/Android/ndk-badver-stderr.txt b/Tests/RunCMake/Android/ndk-badver-stderr.txt
index df2c5e6..ce6bc4e 100644
--- a/Tests/RunCMake/Android/ndk-badver-stderr.txt
+++ b/Tests/RunCMake/Android/ndk-badver-stderr.txt
@@ -1,11 +1,12 @@
 ^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):
-  Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value 'badver' is not one
+  Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value 'badver' is not(
+  supported by this NDK.  It must be 'clang' or not set at all\.| one
   of the allowed forms:
 
     <major>.<minor>       = GCC of specified version
     clang<major>.<minor>  = Clang of specified version
     clang                 = Clang of most recent available version
-
+)
 Call Stack \(most recent call first\):
 .*
   ndk-badver.cmake:1 \(enable_language\)
diff --git a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
index adacaf1..aec91d9 100644
--- a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
+++ b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
@@ -1,4 +1,6 @@
-^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):
+^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):(
+  Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value '1.0' is not
+  supported by this NDK.  It must be 'clang' or not set at all.|
   Android: No toolchain for ABI 'armeabi(-v7a)?' found in the NDK:
 
     .*
@@ -6,7 +8,7 @@
   of the version specified by CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION:
 
     1\.0
-
+)
 Call Stack \(most recent call first\):
 .*
   ndk-badvernum.cmake:1 \(enable_language\)
diff --git a/Tests/RunCMake/Android/ndk-mips-stdout.txt b/Tests/RunCMake/Android/ndk-mips-stdout.txt
index c744683..8ce544d 100644
--- a/Tests/RunCMake/Android/ndk-mips-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-mips-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'mips', ABI 'mips', and processor 'mips'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-mips64-stdout.txt b/Tests/RunCMake/Android/ndk-mips64-stdout.txt
index 839ddfd..1d7edea 100644
--- a/Tests/RunCMake/Android/ndk-mips64-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-mips64-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'mips64', ABI 'mips64', and processor 'mips64'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-x86-stdout.txt b/Tests/RunCMake/Android/ndk-x86-stdout.txt
index 2dbb2f0..8d710fe 100644
--- a/Tests/RunCMake/Android/ndk-x86-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-x86-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'x86', ABI 'x86', and processor 'i686'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-x86_64-stdout.txt b/Tests/RunCMake/Android/ndk-x86_64-stdout.txt
index a7ae91d..695a088 100644
--- a/Tests/RunCMake/Android/ndk-x86_64-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-x86_64-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'x86_64', ABI 'x86_64', and processor 'x86_64'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/CMP0065/RunCMakeTest.cmake b/Tests/RunCMake/CMP0065/RunCMakeTest.cmake
index 254a4ec..e86b50e 100644
--- a/Tests/RunCMake/CMP0065/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMP0065/RunCMakeTest.cmake
@@ -1,8 +1,11 @@
 include(RunCMake)
 
 run_cmake(OLDBad1)
-run_cmake(OLDBad2)
-run_cmake(NEWBad)
+if(NOT CMAKE_SYSTEM_NAME STREQUAL "AIX")
+  # Tests with ENABLE_EXPORTS ON.  For AIX we do not use the flags at all.
+  run_cmake(OLDBad2)
+  run_cmake(NEWBad)
+endif()
 run_cmake(NEWGood)
 run_cmake(WARN-OFF)
 run_cmake(WARN-ON)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 69f8162..c952b1a 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -120,7 +120,7 @@
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
 # generators ignore.  The policy will have no effect on those generators.
 if(NOT CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
-  add_RunCMake_test(CMP0065)
+  add_RunCMake_test(CMP0065 -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
 endif()
 if(CMAKE_GENERATOR MATCHES "Make")
   add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU})
@@ -408,7 +408,12 @@
   set(NO_NAMELINK 0)
 endif()
 
-add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN})
+add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
+  -DCMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN=${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}
+  -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
+  -DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG}
+  -DCMAKE_EXECUTABLE_FORMAT=${CMAKE_EXECUTABLE_FORMAT})
+
 add_RunCMake_test(CPackCommandLine)
 add_RunCMake_test(CPackConfig)
 add_RunCMake_test(CPackInstallProperties)
@@ -565,3 +570,5 @@
   add_RunCMake_test(CSharpCustomCommand)
   add_RunCMake_test(CSharpReferenceImport)
 endif()
+
+add_RunCMake_test("CTestCommandExpandLists")
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 37df57c..d93f280 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -33,6 +33,6 @@
 unset(ENVIRONMENT)
 run_cpack_test(USER_FILELIST "RPM.USER_FILELIST" false "MONOLITHIC")
 run_cpack_test(MD5SUMS "DEB.MD5SUMS" false "MONOLITHIC;COMPONENT")
-run_cpack_test(CPACK_INSTALL_SCRIPT "ZIP" false "MONOLITHIC")
+run_cpack_test_subtests(CPACK_INSTALL_SCRIPTS "singular;plural;both" "ZIP" false "MONOLITHIC")
 run_cpack_test(DEB_PACKAGE_VERSION_BACK_COMPATIBILITY "DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY" false "MONOLITHIC;COMPONENT")
 run_cpack_test_subtests(EXTERNAL "none;good;good_multi;bad_major;bad_minor;invalid_good;invalid_bad;stage_and_package" "External" false "MONOLITHIC;COMPONENT")
diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/test.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/test.cmake
deleted file mode 100644
index e3fe0ca..0000000
--- a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/test.cmake
+++ /dev/null
@@ -1,11 +0,0 @@
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/abc.txt" "test content")
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/user-script.cmake"
-  "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/foo\"
-    TYPE FILE FILES \"${CMAKE_CURRENT_BINARY_DIR}/abc.txt\")")
-set(CPACK_INSTALL_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/user-script.cmake")
-
-function(run_after_include_cpack)
-  file(READ "${CPACK_OUTPUT_CONFIG_FILE}" conf_file_)
-  string(REGEX REPLACE "SET\\(CPACK_INSTALL_CMAKE_PROJECTS [^)]*\\)" "" conf_file_ "${conf_file_}")
-  file(WRITE "${CPACK_OUTPUT_CONFIG_FILE}" "${conf_file_}")
-endfunction()
diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/ExpectedFiles.cmake
similarity index 100%
rename from Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake
rename to Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/ExpectedFiles.cmake
diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/both-stderr.txt b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/both-stderr.txt
new file mode 100644
index 0000000..666030e
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/both-stderr.txt
@@ -0,0 +1 @@
+CPack Warning: Both CPACK_INSTALL_SCRIPTS and CPACK_INSTALL_SCRIPT are set, the latter will be ignored.
diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/test.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/test.cmake
new file mode 100644
index 0000000..249d2e6
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/test.cmake
@@ -0,0 +1,26 @@
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/abc.txt" "test content")
+set(user_script_ "${CMAKE_CURRENT_BINARY_DIR}/user-script.cmake")
+file(WRITE "${user_script_}"
+  "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/foo\"
+    TYPE FILE FILES \"${CMAKE_CURRENT_BINARY_DIR}/abc.txt\")")
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "both")
+    set(CPACK_INSTALL_SCRIPT "${user_script_}")
+    set(CPACK_INSTALL_SCRIPTS "${CPACK_INSTALL_SCRIPT}")
+
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "singular")
+    set(CPACK_INSTALL_SCRIPT "${user_script_}")
+
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "plural")
+    set(CPACK_INSTALL_SCRIPTS "${user_script_}")
+
+else()
+    message(FATAL_ERROR "Unexpected subtest name: ${RunCMake_SUBTEST_SUFFIX}")
+
+endif()
+
+function(run_after_include_cpack)
+  file(READ "${CPACK_OUTPUT_CONFIG_FILE}" conf_file_)
+  string(REGEX REPLACE "SET\\(CPACK_INSTALL_CMAKE_PROJECTS [^)]*\\)" "" conf_file_ "${conf_file_}")
+  file(WRITE "${CPACK_OUTPUT_CONFIG_FILE}" "${conf_file_}")
+endfunction()
diff --git a/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt
new file mode 100644
index 0000000..3e470a2
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.14)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt.in b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt.in
new file mode 100644
index 0000000..7d56c90
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt.in
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.14)
+project(@CASE_NAME@ NONE)
+include("@RunCMake_SOURCE_DIR@/@CASE_NAME@.cmake")
diff --git a/Tests/RunCMake/CTestCommandExpandLists/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandExpandLists/RunCMakeTest.cmake
new file mode 100644
index 0000000..7c3779e
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCTest)
+
+run_ctest(expandGeneratorExpressionResult)
+run_ctest(expandEmptyCommand)
+run_cmake(multipleExpandOptions)
diff --git a/Tests/RunCMake/CTestCommandExpandLists/compare_options.cmake b/Tests/RunCMake/CTestCommandExpandLists/compare_options.cmake
new file mode 100644
index 0000000..a32e579
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/compare_options.cmake
@@ -0,0 +1,14 @@
+set(range 1 2 3 4 5 6 7 8 9 10)
+set(aargs "")
+set(bargs "")
+foreach(n IN LISTS range)
+  set(aval "${A${n}ARG}")
+  set(bval "${B${n}ARG}")
+  if(aval OR bval)
+    list(APPEND aargs "\"${aval}\"")
+    list(APPEND bargs "\"${bval}\"")
+  endif()
+endforeach()
+if(NOT "${aargs}" STREQUAL "${bargs}")
+  message(FATAL_ERROR "COMPARE_OPTIONS: \n\t${aargs} != \n\t${bargs}")
+endif()
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-result.txt b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stderr.txt b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stderr.txt
new file mode 100644
index 0000000..c656b4c
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stderr.txt
@@ -0,0 +1 @@
+Unable to find executable:
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stdout.txt b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stdout.txt
new file mode 100644
index 0000000..0752580
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stdout.txt
@@ -0,0 +1,13 @@
+Test project .*/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-build
+.* +Start 1: CommandExpandEmptyList
+Could not find executable +
+Looked in the following places:
+.*
+1/1 Test #1: CommandExpandEmptyList +\.+\*\*\*Not Run +[0-9.]+ sec
++
+0% tests passed, 1 tests failed out of 1
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests FAILED:
+.* +1 - CommandExpandEmptyList \(Not Run\)$
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand.cmake b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand.cmake
new file mode 100644
index 0000000..b75828e
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand.cmake
@@ -0,0 +1,10 @@
+include(CTest)
+
+set(argv /bin/true)
+list(POP_BACK argv)
+
+add_test(
+  NAME CommandExpandEmptyList
+  COMMAND "$<JOIN:${argv},;>"
+  COMMAND_EXPAND_LISTS
+)
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-result.txt b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt
new file mode 100644
index 0000000..2f21592
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt
@@ -0,0 +1,7 @@
+Test project .*/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-build
+.* +Start 1: CommandExpandList
+1/1 Test #1: CommandExpandList +\.+ +Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 1
++
+Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult.cmake b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult.cmake
new file mode 100644
index 0000000..20608ae
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult.cmake
@@ -0,0 +1,19 @@
+include(CTest)
+
+
+set(cmp_args "1ARG=COMMAND_EXPAND_LISTS" "2ARG=test" "3ARG=outfile"
+  "4ARG=content")
+set(AARGS "")
+foreach(arg IN LISTS cmp_args)
+  list(APPEND AARGS "-DA${arg}")
+endforeach()
+
+
+
+add_test(
+  NAME CommandExpandList
+  COMMAND ${CMAKE_COMMAND} ${AARGS} -V
+  "-DB$<JOIN:${cmp_args},;-DB>"
+  "-P" "${CMAKE_CURRENT_LIST_DIR}/compare_options.cmake"
+  COMMAND_EXPAND_LISTS
+)
diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-result.txt b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stderr.txt b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stderr.txt
new file mode 100644
index 0000000..e48513f
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at multipleExpandOptions\.cmake:3 \(add_test\):
+ +add_test may be given at most one COMMAND_EXPAND_LISTS\.
diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stdout.txt b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stdout.txt
new file mode 100644
index 0000000..55bb894
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stdout.txt
@@ -0,0 +1,2 @@
+-- Configuring incomplete, errors occurred!
+See also ".*/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-build/CMakeFiles/CMakeOutput\.log".
diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions.cmake b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions.cmake
new file mode 100644
index 0000000..dcf2dc4
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions.cmake
@@ -0,0 +1,8 @@
+include(CTest)
+
+add_test(
+  NAME MultipleExpandOptions
+  COMMAND /bin/true
+  COMMAND_EXPAND_LISTS
+  COMMAND_EXPAND_LISTS
+)
diff --git a/Tests/RunCMake/CTestCommandExpandLists/test.cmake.in b/Tests/RunCMake/CTestCommandExpandLists/test.cmake.in
new file mode 100644
index 0000000..d9a8ccb
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandExpandLists/test.cmake.in
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.14)
+
+set(CTEST_SITE                          "test-site")
+set(CTEST_BUILD_NAME                    "test-build-name")
+set(CTEST_SOURCE_DIRECTORY              "@RunCMake_BINARY_DIR@/@CASE_NAME@")
+set(CTEST_BINARY_DIRECTORY              "@RunCMake_BINARY_DIR@/@CASE_NAME@-build")
+set(CTEST_CMAKE_GENERATOR               "@RunCMake_GENERATOR@")
+set(CTEST_CMAKE_GENERATOR_PLATFORM      "@RunCMake_GENERATOR_PLATFORM@")
+set(CTEST_CMAKE_GENERATOR_TOOLSET       "@RunCMake_GENERATOR_TOOLSET@")
+set(CTEST_BUILD_CONFIGURATION           "$ENV{CMAKE_CONFIG_TYPE}")
+
+ctest_start(Experimental)
+ctest_configure()
+ctest_build()
+ctest_test()
diff --git a/Tests/RunCMake/CTestCommandLine/FailRegexFound-check.cmake b/Tests/RunCMake/CTestCommandLine/FailRegexFound-check.cmake
new file mode 100644
index 0000000..1097788
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/FailRegexFound-check.cmake
@@ -0,0 +1,13 @@
+set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log")
+if(EXISTS "${last_test_log}")
+  file(READ "${last_test_log}" last_test_log_content)
+  string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}")
+  if(NOT last_test_log_content MATCHES "
+Test Pass Reason:
+Error regular expression found in output. Regex=[[]test1]")
+    string(REPLACE "\n" "\n  " last_test_log_content "  ${last_test_log_content}")
+    set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}")
+  endif()
+else()
+  set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}")
+endif()
diff --git a/Tests/RunCMake/CTestCommandLine/RequiredRegexFound-check.cmake b/Tests/RunCMake/CTestCommandLine/RequiredRegexFound-check.cmake
new file mode 100644
index 0000000..bde60d1
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/RequiredRegexFound-check.cmake
@@ -0,0 +1,13 @@
+set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log")
+if(EXISTS "${last_test_log}")
+  file(READ "${last_test_log}" last_test_log_content)
+  string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}")
+  if(NOT last_test_log_content MATCHES "
+Test Pass Reason:
+Required regular expression found. Regex=[[]test1]")
+    string(REPLACE "\n" "\n  " last_test_log_content "  ${last_test_log_content}")
+    set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}")
+  endif()
+else()
+  set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}")
+endif()
diff --git a/Tests/RunCMake/CTestCommandLine/RequiredRegexNotFound-check.cmake b/Tests/RunCMake/CTestCommandLine/RequiredRegexNotFound-check.cmake
new file mode 100644
index 0000000..6d420f3
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/RequiredRegexNotFound-check.cmake
@@ -0,0 +1,16 @@
+set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log")
+if(EXISTS "${last_test_log}")
+  file(READ "${last_test_log}" last_test_log_content)
+  string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}")
+  if(NOT last_test_log_content MATCHES "
+Test Pass Reason:
+Required regular expression not found. Regex=[[]foo
+toast1
+bar
+]")
+    string(REPLACE "\n" "\n  " last_test_log_content "  ${last_test_log_content}")
+    set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}")
+  endif()
+else()
+  set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}")
+endif()
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index d524f41..3fee79c 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -78,6 +78,62 @@
 
 run_LabelCount()
 
+function(run_RequiredRegexFoundTest)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RequiredRegexFound)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\")
+set_tests_properties(test1 PROPERTIES PASS_REGULAR_EXPRESSION \"foo;test1;bar\")
+")
+
+  run_cmake_command(RequiredRegexFound ${CMAKE_CTEST_COMMAND} -V)
+endfunction()
+run_RequiredRegexFoundTest()
+
+function(run_RequiredRegexNotFoundTest)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RequiredRegexNotFound)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\")
+set_tests_properties(test1 PROPERTIES PASS_REGULAR_EXPRESSION \"foo;toast1;bar\" WILL_FAIL True)
+")
+
+  run_cmake_command(RequiredRegexNotFound ${CMAKE_CTEST_COMMAND} -V)
+endfunction()
+run_RequiredRegexNotFoundTest()
+
+function(run_FailRegexFoundTest)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/FailRegexFound)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\")
+set_tests_properties(test1 PROPERTIES FAIL_REGULAR_EXPRESSION \"foo;test1;bar\" WILL_FAIL True)
+")
+
+  run_cmake_command(FailRegexFound ${CMAKE_CTEST_COMMAND} -V)
+endfunction()
+run_FailRegexFoundTest()
+
+function(run_SkipRegexFoundTest)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SkipRegexFound)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\")
+set_tests_properties(test1 PROPERTIES SKIP_REGULAR_EXPRESSION \"test1\")
+")
+
+  run_cmake_command(SkipRegexFound ${CMAKE_CTEST_COMMAND} -V)
+endfunction()
+run_SkipRegexFoundTest()
+
 function(run_SerialFailed)
   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SerialFailed)
   set(RunCMake_TEST_NO_CLEAN 1)
diff --git a/Tests/RunCMake/CTestCommandLine/SkipRegexFound-check.cmake b/Tests/RunCMake/CTestCommandLine/SkipRegexFound-check.cmake
new file mode 100644
index 0000000..1a2dfa3
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/SkipRegexFound-check.cmake
@@ -0,0 +1,13 @@
+set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log")
+if(EXISTS "${last_test_log}")
+  file(READ "${last_test_log}" last_test_log_content)
+  string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}")
+  if(NOT last_test_log_content MATCHES "
+Test Pass Reason:
+Skip regular expression found in output. Regex=[[]test1]")
+    string(REPLACE "\n" "\n  " last_test_log_content "  ${last_test_log_content}")
+    set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}")
+  endif()
+else()
+  set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}")
+endif()
diff --git a/Tests/RunCMake/CommandLine/E_false-extraargs-result.txt b/Tests/RunCMake/CommandLine/E_false-extraargs-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_false-extraargs-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_false-result.txt b/Tests/RunCMake/CommandLine/E_false-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_false-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index c9d3a4d..4e19871 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -26,6 +26,10 @@
 run_cmake_command(E_rename-no-arg ${CMAKE_COMMAND} -E rename)
 run_cmake_command(E_server-arg ${CMAKE_COMMAND} -E server --extra-arg)
 run_cmake_command(E_server-pipe ${CMAKE_COMMAND} -E server --pipe=)
+run_cmake_command(E_true ${CMAKE_COMMAND} -E true)
+run_cmake_command(E_true-extraargs ${CMAKE_COMMAND} -E true ignored)
+run_cmake_command(E_false ${CMAKE_COMMAND} -E false)
+run_cmake_command(E_false-extraargs ${CMAKE_COMMAND} -E false ignored)
 
 run_cmake_command(E_touch_nocreate-no-arg ${CMAKE_COMMAND} -E touch_nocreate)
 run_cmake_command(E_touch-nonexistent-dir ${CMAKE_COMMAND} -E touch "${RunCMake_BINARY_DIR}/touch-nonexistent-dir/foo")
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index 3096358..89f63d0 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -979,6 +979,11 @@
                     "_dllExtra": False,
                 },
                 {
+                    "path": "^lib/my_interface_exe\\.imp$",
+                    "_aixExtra": True,
+                    "_dllExtra": False,
+                },
+                {
                     "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?my_interface_exe\\.(dll\\.a|lib)$",
                     "_dllExtra": True,
                 },
@@ -4928,6 +4933,10 @@
         for e in expected:
             e["artifacts"] = filter_list(lambda a: not a["_dllExtra"], e["artifacts"])
 
+    if "aix" not in sys.platform:
+        for e in expected:
+            e["artifacts"] = filter_list(lambda a: not a.get("_aixExtra", False), e["artifacts"])
+
     return expected
 
 def check_targets(c, g, inSource):
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake
index 34e500a..f52776e 100644
--- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake
@@ -38,7 +38,7 @@
 
 string (APPEND GENERATE_CONTENT
 "\ncheck_value (\"TARGET_FILE_PREFIX executable custom\" \"$<TARGET_FILE_PREFIX:exec2>\" \"exec2_prefix\")
-check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_prefix,exec2_prefix>\")
+check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_prefix,exec2_prefix>\")
 check_value (\"TARGET_FILE_PREFIX shared custom\" \"$<TARGET_FILE_PREFIX:shared2>\" \"shared2_prefix\")
 check_value (\"TARGET_LINKER_FILE_PREFIX shared linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_prefix,shared2_prefix>\")
 check_value (\"TARGET_FILE_PREFIX static custom\" \"$<TARGET_FILE_PREFIX:static2>\" \"static2_prefix\")
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake
index 6bb1e44..bef7bbf 100644
--- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake
@@ -38,7 +38,7 @@
 
 string (APPEND GENERATE_CONTENT
 "\ncheck_value (\"TARGET_FILE_PREFIX executable custom\" \"$<TARGET_FILE_PREFIX:exec2>\" \"exec2_prefix\")
-check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_prefix,exec2_prefix>\")
+check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_prefix,exec2_prefix>\")
 check_value (\"TARGET_FILE_PREFIX shared custom\" \"$<TARGET_FILE_PREFIX:shared2>\" \"shared2_prefix\")
 check_value (\"TARGET_LINKER_FILE_PREFIX shared linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_prefix,shared2_prefix>\")
 check_value (\"TARGET_FILE_PREFIX static custom\" \"$<TARGET_FILE_PREFIX:static2>\" \"static2_prefix\")
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake
index e1b7654..cefeb86 100644
--- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake
@@ -38,7 +38,7 @@
 
 string (APPEND GENERATE_CONTENT
 "\ncheck_value (\"TARGET_FILE_SUFFIX executable custom\" \"$<TARGET_FILE_SUFFIX:exec2>\" \"exec2_suffix\")
-check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_suffix,exec2_suffix>\")
+check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_suffix,exec2_suffix>\")
 check_value (\"TARGET_FILE_SUFFIX shared custom\" \"$<TARGET_FILE_SUFFIX:shared2>\" \"shared2_suffix\")
 check_value (\"TARGET_LINKER_FILE_SUFFIX shared linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_suffix,shared2_suffix>\")
 check_value (\"TARGET_FILE_SUFFIX static custom\" \"$<TARGET_FILE_SUFFIX:static2>\" \"static2_suffix\")
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake
index 78afecd..39e39fd 100644
--- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake
@@ -38,7 +38,7 @@
 
 string (APPEND GENERATE_CONTENT
 "\ncheck_value (\"TARGET_FILE_SUFFIX executable custom\" \"$<TARGET_FILE_SUFFIX:exec2>\" \"exec2_suffix\")
-check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_suffix,exec2_suffix>\")
+check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_suffix,exec2_suffix>\")
 check_value (\"TARGET_FILE_SUFFIX shared custom\" \"$<TARGET_FILE_SUFFIX:shared2>\" \"shared2_suffix\")
 check_value (\"TARGET_LINKER_FILE_SUFFIX shared linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_suffix,shared2_suffix>\")
 check_value (\"TARGET_FILE_SUFFIX static custom\" \"$<TARGET_FILE_SUFFIX:static2>\" \"static2_suffix\")
diff --git a/Tests/RunCMake/README.rst b/Tests/RunCMake/README.rst
index d8b43fe..ebe40cf 100644
--- a/Tests/RunCMake/README.rst
+++ b/Tests/RunCMake/README.rst
@@ -55,6 +55,12 @@
    ``<SubTest>-check.cmake``
     Custom result check.
 
+  Note that when a specific platform expects differing stdout or stderr that
+  can be done by adding a platform specific output file. These follow the
+  naming convention of:
+   ``<SubTest>-stdout-<platform_lower_case>.txt``
+   ``<SubTest>-stderr-<platform_lower_case>.txt``
+
    Note that trailing newlines will be stripped from actual and expected
    test output before matching against the stdout and stderr expressions.
    The code in ``<SubTest>-check.cmake`` may use variables
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index ad3f8f6..568bdf8 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -21,10 +21,20 @@
   else()
     set(expect_result 0)
   endif()
+
+  string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} platform_name)
+  if(platform_name MATCHES cygwin)
+    #remove all additional bits from cygwin name
+    set(platform_name cygwin)
+  endif()
+
   foreach(o out err)
     if(RunCMake-std${o}-file AND EXISTS ${top_src}/${RunCMake-std${o}-file})
       file(READ ${top_src}/${RunCMake-std${o}-file} expect_std${o})
       string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}")
+    elseif(EXISTS ${top_src}/${test}-std${o}-${platform_name}.txt)
+      file(READ ${top_src}/${test}-std${o}-${platform_name}.txt expect_std${o})
+      string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}")
     elseif(EXISTS ${top_src}/${test}-std${o}.txt)
       file(READ ${top_src}/${test}-std${o}.txt expect_std${o})
       string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}")
@@ -134,8 +144,6 @@
     "|Error kstat returned"
     "|Hit xcodebuild bug"
     "|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type"
-    "|ld: 0711-224 WARNING: Duplicate symbol: .__init_aix_libgcc_cxa_atexit"
-    "|ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information"
     "|[^\n]*is a member of multiple groups"
     "|[^\n]*from Time Machine by path"
     "|[^\n]*Bullseye Testing Technology"
diff --git a/Tests/RunCMake/RuntimePath/Genex.cmake b/Tests/RunCMake/RuntimePath/Genex.cmake
new file mode 100644
index 0000000..152238a
--- /dev/null
+++ b/Tests/RunCMake/RuntimePath/Genex.cmake
@@ -0,0 +1,29 @@
+enable_language(C)
+
+add_library(A STATIC A.c)
+
+add_executable(buildge main.c)
+target_link_libraries(buildge A)
+set_target_properties(buildge PROPERTIES
+  BUILD_RPATH $<1:/opt/foo/lib>
+  )
+
+add_executable(buildnoge main.c)
+target_link_libraries(buildnoge A)
+set_target_properties(buildnoge PROPERTIES
+  BUILD_RPATH /opt/foo/lib
+  )
+
+add_executable(installge main.c)
+target_link_libraries(installge A)
+set_target_properties(installge PROPERTIES
+  INSTALL_RPATH $<1:/opt/foo/lib>
+  BUILD_WITH_INSTALL_RPATH 1
+  )
+
+add_executable(installnoge main.c)
+target_link_libraries(installnoge A)
+set_target_properties(installnoge PROPERTIES
+  INSTALL_RPATH /opt/foo/lib
+  BUILD_WITH_INSTALL_RPATH 1
+  )
diff --git a/Tests/RunCMake/RuntimePath/GenexCheck.cmake b/Tests/RunCMake/RuntimePath/GenexCheck.cmake
new file mode 100644
index 0000000..07dc496
--- /dev/null
+++ b/Tests/RunCMake/RuntimePath/GenexCheck.cmake
@@ -0,0 +1,7 @@
+file(GLOB_RECURSE files "${dir}/*")
+
+foreach(file IN LISTS files)
+  if(file MATCHES "/(build|install)(no)?ge$")
+    file(RPATH_CHANGE FILE "${file}" OLD_RPATH "/opt/foo/lib" NEW_RPATH "/opt/bar/lib")
+  endif()
+endforeach()
diff --git a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake
index 6f1baa1..4c9ddcd 100644
--- a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake
+++ b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake
@@ -1,32 +1,26 @@
 include(RunCMake)
 
 
-function(run_SymlinkImplicit)
+function(run_RuntimePath name)
   # Use a single build tree for a few tests without cleaning.
-  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SymlinkImplicit-build)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
   set(RunCMake_TEST_NO_CLEAN 1)
   if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
     set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
   endif()
   file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
   file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
-  run_cmake(SymlinkImplicit)
-  run_cmake_command(SymlinkImplicit-build ${CMAKE_COMMAND} --build . --config Debug)
-  run_cmake_command(SymlinkImplicitCheck
-    ${CMAKE_COMMAND} -Ddir=${RunCMake_TEST_BINARY_DIR} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake)
+  run_cmake(${name})
+  run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug)
 endfunction()
-run_SymlinkImplicit()
 
-function(run_Relative)
-  # Use a single build tree for a few tests without cleaning.
-  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Relative-build)
-  set(RunCMake_TEST_NO_CLEAN 1)
-  if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
-    set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
-  endif()
-  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
-  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
-  run_cmake(Relative)
-  run_cmake_command(Relative-build ${CMAKE_COMMAND} --build . --config Debug)
-endfunction()
-run_Relative()
+run_RuntimePath(SymlinkImplicit)
+run_cmake_command(SymlinkImplicitCheck
+  ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake)
+
+run_RuntimePath(Relative)
+# FIXME: Run RelativeCheck (appears to be broken currently)
+
+run_RuntimePath(Genex)
+run_cmake_command(GenexCheck
+  ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/Genex-build -P ${RunCMake_SOURCE_DIR}/GenexCheck.cmake)
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 0bcf886..6d72fac 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -27,6 +27,7 @@
    \* CMP0076
    \* CMP0081
    \* CMP0083
+   \* CMP0095
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index 55ca9ea..1cb4ce5 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -22,7 +22,13 @@
 run_cmake(VsGlobals)
 run_cmake(VsProjectImport)
 run_cmake(VsPackageReferences)
+run_cmake(VsDpiAware)
+run_cmake(VsDpiAwareBadParam)
 
 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
   run_cmake(VsJustMyCode)
 endif()
+
+if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.20)
+  run_cmake(VsSpectreMitigation)
+endif()
diff --git a/Tests/RunCMake/VS10Project/VsDpiAware-check.cmake b/Tests/RunCMake/VS10Project/VsDpiAware-check.cmake
new file mode 100644
index 0000000..fbb64f0
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsDpiAware-check.cmake
@@ -0,0 +1,41 @@
+macro(VSDpiAware_check tgt dpiaware_match_expect)
+  set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${tgt}.vcxproj")
+  if(NOT EXISTS "${vcProjectFile}")
+    set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not exist.")
+    return()
+  endif()
+
+  set(HAVE_DPIAWARE_MATCH 0)
+  set(IN_MANIFEST_SETTINGS 0)
+
+  file(STRINGS "${vcProjectFile}" lines)
+  foreach(line IN LISTS lines)
+    if(line MATCHES "^ *<Manifest>")
+      set(IN_MANIFEST_SETTINGS 1)
+    elseif(line MATCHES "^ *</Manifest>")
+      set(IN_MANIFEST_SETTINGS 0)
+    elseif(IN_MANIFEST_SETTINGS AND (line MATCHES "^ *<EnableDpiAwareness>([^<>]+)</EnableDpiAwareness>"))
+      set(dpiaware_match_actual "${CMAKE_MATCH_1}")
+      if(NOT "${dpiaware_match_actual}" STREQUAL "${dpiaware_match_expect}")
+        set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has <EnableDpiAwareness> '${dpiaware_match_actual}', not '${dpiaware_match_expect}'.")
+        return()
+      endif()
+      set(HAVE_DPIAWARE_MATCH 1)
+      break()
+    endif()
+  endforeach()
+
+  if(NOT HAVE_DPIAWARE_MATCH AND NOT "${dpiaware_match_expect}" STREQUAL "")
+    set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a <EnableDpiAwareness> property group.")
+    return()
+  endif()
+endmacro()
+
+VSDpiAware_check(DPIAWARE-default-C "")
+VSDpiAware_check(DPIAWARE-default-CXX "")
+VSDpiAware_check(DPIAWARE-TGT-PERMONITOR-C "PerMonitorHighDPIAware")
+VSDpiAware_check(DPIAWARE-TGT-PERMONITOR-CXX "PerMonitorHighDPIAware")
+VSDpiAware_check(DPIAWARE-TGT-ON-C "true")
+VSDpiAware_check(DPIAWARE-TGT-ON-CXX "true")
+VSDpiAware_check(DPIAWARE-TGT-OFF-C "false")
+VSDpiAware_check(DPIAWARE-TGT-OFF-CXX "false")
diff --git a/Tests/RunCMake/VS10Project/VsDpiAware.cmake b/Tests/RunCMake/VS10Project/VsDpiAware.cmake
new file mode 100644
index 0000000..74e3d21
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsDpiAware.cmake
@@ -0,0 +1,19 @@
+set(CMAKE_CONFIGURATION_TYPES Debug)
+enable_language(C)
+enable_language(CXX)
+
+add_executable(DPIAWARE-default-C empty.c)
+add_executable(DPIAWARE-default-CXX empty.cxx)
+
+add_executable(DPIAWARE-TGT-PERMONITOR-C empty.c)
+set_property(TARGET DPIAWARE-TGT-PERMONITOR-C PROPERTY VS_DPI_AWARE "PerMonitor")
+add_executable(DPIAWARE-TGT-PERMONITOR-CXX empty.cxx)
+set_property(TARGET DPIAWARE-TGT-PERMONITOR-CXX PROPERTY VS_DPI_AWARE "PerMonitor")
+add_executable(DPIAWARE-TGT-ON-C empty.c)
+set_property(TARGET DPIAWARE-TGT-ON-C PROPERTY VS_DPI_AWARE ON)
+add_executable(DPIAWARE-TGT-ON-CXX empty.cxx)
+set_property(TARGET DPIAWARE-TGT-ON-CXX PROPERTY VS_DPI_AWARE ON)
+add_executable(DPIAWARE-TGT-OFF-C empty.c)
+set_property(TARGET DPIAWARE-TGT-OFF-C PROPERTY VS_DPI_AWARE OFF)
+add_executable(DPIAWARE-TGT-OFF-CXX empty.cxx)
+set_property(TARGET DPIAWARE-TGT-OFF-CXX PROPERTY VS_DPI_AWARE OFF)
diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-result.txt b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt
new file mode 100644
index 0000000..95fc5ca
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error: Bad parameter for VS_DPI_AWARE: Bar
+CMake Error: Bad parameter for VS_DPI_AWARE: Foo
+CMake Generate step failed.  Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam.cmake b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam.cmake
new file mode 100644
index 0000000..e05452b
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam.cmake
@@ -0,0 +1,8 @@
+set(CMAKE_CONFIGURATION_TYPES Debug)
+enable_language(C)
+enable_language(CXX)
+
+add_executable(DPIAWARE-TGT-BADPARAM-C empty.c)
+set_property(TARGET DPIAWARE-TGT-BADPARAM-C PROPERTY VS_DPI_AWARE "Foo")
+add_executable(DPIAWARE-TGT-BADPARAM-CXX empty.cxx)
+set_property(TARGET DPIAWARE-TGT-BADPARAM-CXX PROPERTY VS_DPI_AWARE "Bar")
diff --git a/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake b/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake
index 4ff5327..512a1c9 100644
--- a/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake
+++ b/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake
@@ -25,7 +25,7 @@
       if(line MATCHES "^ *<PackageReference .* Version=\"${testVersion}\".*>$")
         set(Library${i}Found TRUE)
         message(STATUS "foo.vcxproj is using package reference ${testLibrary} with version ${testVersion}")
-      elseif()
+      else()
         message(STATUS "foo.vcxproj failed to define reference ${testLibrary} with version ${testVersion}")
         set(Library${i}Found FALSE)
       endif()
diff --git a/Tests/RunCMake/VS10Project/VsSpectreMitigation-check.cmake b/Tests/RunCMake/VS10Project/VsSpectreMitigation-check.cmake
new file mode 100644
index 0000000..6117763
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsSpectreMitigation-check.cmake
@@ -0,0 +1,30 @@
+macro(VsSpectreMitigation_check tgt spectre_expect)
+  set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${tgt}.vcxproj")
+  if(NOT EXISTS "${vcProjectFile}")
+    set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not exist.")
+    return()
+  endif()
+
+  set(HAVE_SpectreMitigation 0)
+
+  file(STRINGS "${vcProjectFile}" lines)
+  foreach(line IN LISTS lines)
+    if(line MATCHES "^ *<SpectreMitigation>([^<>]+)</SpectreMitigation>")
+      set(spectre_actual "${CMAKE_MATCH_1}")
+      if(NOT "${spectre_actual}" STREQUAL "${spectre_expect}")
+        set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has <SpectreMitigation> '${spectre_actual}', not '${spectre_expect}'.")
+        return()
+      endif()
+      set(HAVE_SpectreMitigation 1)
+      break()
+    endif()
+  endforeach()
+
+  if(NOT HAVE_SpectreMitigation AND NOT "${spectre_expect}" STREQUAL "")
+    set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a <SpectreMitigation> field.")
+    return()
+  endif()
+endmacro()
+
+VsSpectreMitigation_check(SpectreMitigationOn-C "Spectre")
+VsSpectreMitigation_check(SpectreMitigationOff-C "false")
diff --git a/Tests/RunCMake/VS10Project/VsSpectreMitigation.cmake b/Tests/RunCMake/VS10Project/VsSpectreMitigation.cmake
new file mode 100644
index 0000000..b3779d7
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsSpectreMitigation.cmake
@@ -0,0 +1,8 @@
+set(CMAKE_CONFIGURATION_TYPES Debug)
+enable_language(C)
+
+add_library(SpectreMitigationOn-C empty.c)
+target_compile_options(SpectreMitigationOn-C PRIVATE -Qspectre)
+
+add_library(SpectreMitigationOff-C empty.c)
+target_compile_options(SpectreMitigationOff-C PRIVATE -Qspectre-)
diff --git a/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake b/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake
index dab1c33..b1deb99 100644
--- a/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake
+++ b/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake
@@ -14,6 +14,9 @@
 set(FoundCEAdditionalFiles FALSE)
 set(FoundRemoteDirectory FALSE)
 set(FoundToolsVersion4 FALSE)
+set(FoundEnableRedirectPlatform FALSE)
+set(FoundRedirectPlatformValue FALSE)
+
 
 file(STRINGS "${vcProjectFile}" lines)
 foreach(line IN LISTS lines)
@@ -23,6 +26,10 @@
     set(FoundRemoteDirectory TRUE)
   elseif(line MATCHES " *<Project +.*ToolsVersion=\"4.0\".*> *$")
     set(FoundToolsVersion4 TRUE)
+  elseif(line MATCHES "^ *<EnableRedirectPlatform>true</EnableRedirectPlatform> *$")
+    set(FoundEnableRedirectPlatform TRUE)
+  elseif(line MATCHES "^ *<RedirectPlatformValue>.+</RedirectPlatformValue> *$")
+    set(FoundRedirectPlatformValue TRUE)
   endif()
 endforeach()
 
@@ -41,6 +48,16 @@
   return()
 endif()
 
+if(NOT FoundEnableRedirectPlatform)
+  set(RunCMake_TEST_FAILED "Failed to find EnableRedirectPlatform true property.")
+  return()
+endif()
+
+if(NOT FoundRedirectPlatformValue)
+  set(RunCMake_TEST_FAILED "Failed to find RedirectPlatformValue property.")
+  return()
+endif()
+
 #
 # Test solution file deployment items.
 #
diff --git a/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt b/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt
index e332281..838992b 100644
--- a/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt
+++ b/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt
@@ -1,4 +1,4 @@
 ^CMake Error at UNKNOWNwithOnlyObjectSources.cmake:[0-9]+ \(target_sources\):
-  target_sources called with non-compilable target type
+  target_sources may only set INTERFACE properties on IMPORTED targets
 Call Stack \(most recent call first\):
   CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/export/DependOnDoubleExport-result.txt b/Tests/RunCMake/export/DependOnDoubleExport-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/export/DependOnDoubleExport-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/export/DependOnDoubleExport-stderr.txt b/Tests/RunCMake/export/DependOnDoubleExport-stderr.txt
new file mode 100644
index 0000000..b78c7e4
--- /dev/null
+++ b/Tests/RunCMake/export/DependOnDoubleExport-stderr.txt
@@ -0,0 +1,13 @@
+CMake Error in CMakeLists.txt:
+  export called with target "exported" which requires target "doubleexported"
+  that is not in this export set, but in multiple other export sets:
+  .*/Tests/RunCMake/export/DependOnDoubleExport-build/exportset.cmake,
+  .*/Tests/RunCMake/export/DependOnDoubleExport-build/manual.cmake.
+
+
+  An exported target cannot depend upon another target which is exported
+  multiple times.  Consider consolidating the exports of the "doubleexported"
+  target to a single export.
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/export/DependOnDoubleExport.cmake b/Tests/RunCMake/export/DependOnDoubleExport.cmake
new file mode 100644
index 0000000..8d108d7
--- /dev/null
+++ b/Tests/RunCMake/export/DependOnDoubleExport.cmake
@@ -0,0 +1,7 @@
+add_library(doubleexported INTERFACE)
+install(TARGETS doubleexported EXPORT exportset)
+export(TARGETS doubleexported FILE "${CMAKE_CURRENT_BINARY_DIR}/manual.cmake")
+export(EXPORT exportset FILE "${CMAKE_CURRENT_BINARY_DIR}/exportset.cmake")
+add_library(exported INTERFACE)
+target_link_libraries(exported INTERFACE doubleexported)
+export(TARGETS exported FILE "${CMAKE_CURRENT_BINARY_DIR}/exports.cmake")
diff --git a/Tests/RunCMake/export/DependOnNotExport-result.txt b/Tests/RunCMake/export/DependOnNotExport-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/export/DependOnNotExport-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/export/DependOnNotExport-stderr.txt b/Tests/RunCMake/export/DependOnNotExport-stderr.txt
new file mode 100644
index 0000000..80f5758
--- /dev/null
+++ b/Tests/RunCMake/export/DependOnNotExport-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error in CMakeLists.txt:
+  export called with target "exported" which requires target "notexported"
+  that is not in any export set.
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/export/DependOnNotExport.cmake b/Tests/RunCMake/export/DependOnNotExport.cmake
new file mode 100644
index 0000000..06c1ad9
--- /dev/null
+++ b/Tests/RunCMake/export/DependOnNotExport.cmake
@@ -0,0 +1,4 @@
+add_library(notexported INTERFACE)
+add_library(exported INTERFACE)
+target_link_libraries(exported INTERFACE notexported)
+export(TARGETS exported FILE "${CMAKE_CURRENT_BINARY_DIR}/exports.cmake")
diff --git a/Tests/RunCMake/export/RunCMakeTest.cmake b/Tests/RunCMake/export/RunCMakeTest.cmake
index 97a0ca6..4d2f217 100644
--- a/Tests/RunCMake/export/RunCMakeTest.cmake
+++ b/Tests/RunCMake/export/RunCMakeTest.cmake
@@ -10,3 +10,5 @@
 run_cmake(ForbiddenToExportImportedProperties)
 run_cmake(ForbiddenToExportPropertyWithGenExp)
 run_cmake(ExportPropertiesUndefined)
+run_cmake(DependOnNotExport)
+run_cmake(DependOnDoubleExport)
diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout-cygwin.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout-cygwin.txt
new file mode 100644
index 0000000..6912bdf
--- /dev/null
+++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout-cygwin.txt
@@ -0,0 +1,9 @@
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout-windows.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout-windows.txt
new file mode 100644
index 0000000..6912bdf
--- /dev/null
+++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout-windows.txt
@@ -0,0 +1,9 @@
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout.txt
new file mode 100644
index 0000000..27a83ad
--- /dev/null
+++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout.txt
@@ -0,0 +1,9 @@
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/FromPATHEnv.cmake b/Tests/RunCMake/find_file/FromPATHEnv.cmake
new file mode 100644
index 0000000..9f058dd
--- /dev/null
+++ b/Tests/RunCMake/find_file/FromPATHEnv.cmake
@@ -0,0 +1,24 @@
+set(ENV_PATH "$ENV{PATH}")
+foreach(path "/does_not_exist" "/include" "")
+  unset(PrefixInPATH_File CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_file(PrefixInPATH_File NAMES PrefixInPATH.h)
+  message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'")
+endforeach()
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
+foreach(path "/does_not_exist" "/include" "")
+  unset(PrefixInPATH_File CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_file(PrefixInPATH_File NAMES PrefixInPATH.h)
+  message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'")
+endforeach()
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON)
+foreach(path "/does_not_exist" "/include" "")
+  unset(PrefixInPATH_File CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_file(PrefixInPATH_File NAMES PrefixInPATH.h NO_SYSTEM_ENVIRONMENT_PATH)
+  message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'")
+endforeach()
+set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_file/FromPrefixPath-stdout.txt b/Tests/RunCMake/find_file/FromPrefixPath-stdout.txt
new file mode 100644
index 0000000..4bd24aa
--- /dev/null
+++ b/Tests/RunCMake/find_file/FromPrefixPath-stdout.txt
@@ -0,0 +1,6 @@
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
+-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/FromPrefixPath.cmake b/Tests/RunCMake/find_file/FromPrefixPath.cmake
new file mode 100644
index 0000000..63c6a07
--- /dev/null
+++ b/Tests/RunCMake/find_file/FromPrefixPath.cmake
@@ -0,0 +1,19 @@
+set(ENV_PATH "$ENV{PATH}")
+set(ENV{PATH} "")
+foreach(path "/does_not_exist" "/include" "")
+  unset(PrefixInPATH_File CACHE)
+  set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_file(PrefixInPATH_File NAMES PrefixInPATH.h)
+  message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'")
+endforeach()
+
+set(CMAKE_FIND_USE_CMAKE_PATH OFF)
+set(CMAKE_PREFIX_PATH )
+foreach(path "/does_not_exist" "/include" "")
+  unset(PrefixInPATH_File CACHE)
+  set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_file(PrefixInPATH_File NAMES PrefixInPATH.h)
+  message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'")
+endforeach()
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON)
+set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout-cygwin.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout-cygwin.txt
new file mode 100644
index 0000000..d73bc1d
--- /dev/null
+++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout-cygwin.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout-windows.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout-windows.txt
new file mode 100644
index 0000000..d73bc1d
--- /dev/null
+++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout-windows.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt
index d73bc1d..947a900 100644
--- a/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt
+++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt
@@ -1,4 +1,4 @@
 -- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
--- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
--- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
--- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake
index 5ce96e0..9f56a57 100644
--- a/Tests/RunCMake/find_file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake
@@ -1,5 +1,5 @@
 include(RunCMake)
 
-if(WIN32 OR CYGWIN)
-  run_cmake(PrefixInPATH)
-endif()
+run_cmake(FromPATHEnv)
+run_cmake(FromPrefixPath)
+run_cmake(PrefixInPATH)
diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout-cygwin.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout-cygwin.txt
new file mode 100644
index 0000000..01e2720
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout-cygwin.txt
@@ -0,0 +1,6 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout-windows.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout-windows.txt
new file mode 100644
index 0000000..01e2720
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout-windows.txt
@@ -0,0 +1,6 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout.txt
new file mode 100644
index 0000000..4e570a6
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout.txt
@@ -0,0 +1,6 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/FromPATHEnv.cmake b/Tests/RunCMake/find_library/FromPATHEnv.cmake
new file mode 100644
index 0000000..fec041d
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromPATHEnv.cmake
@@ -0,0 +1,22 @@
+list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
+list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
+set(ENV_PATH "$ENV{PATH}")
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib/libcreated.a" "created")
+
+foreach(path "/does_not_exist" "/lib" "")
+  unset(CREATED_LIBRARY CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_BINARY_DIR}${path}")
+  find_library(CREATED_LIBRARY NAMES created)
+  message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+endforeach()
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
+foreach(path "/does_not_exist" "/lib" "")
+  unset(CREATED_LIBRARY CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_BINARY_DIR}${path}")
+  find_library(CREATED_LIBRARY NAMES created)
+  message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+endforeach()
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON)
+set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_library/FromPrefixPath-stdout.txt b/Tests/RunCMake/find_library/FromPrefixPath-stdout.txt
new file mode 100644
index 0000000..de3df1a
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromPrefixPath-stdout.txt
@@ -0,0 +1,6 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPrefixPath-build/lib/libcreated.a'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPrefixPath-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/FromPrefixPath.cmake b/Tests/RunCMake/find_library/FromPrefixPath.cmake
new file mode 100644
index 0000000..04763a9
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromPrefixPath.cmake
@@ -0,0 +1,24 @@
+list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
+list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
+set(ENV_PATH "$ENV{PATH}")
+set(ENV{PATH} "")
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib/libcreated.a" "created")
+
+foreach(path "/does_not_exist" "/lib" "")
+  unset(CREATED_LIBRARY CACHE)
+  set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}${path}")
+  find_library(CREATED_LIBRARY NAMES created)
+  message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+endforeach()
+
+set(CMAKE_FIND_USE_CMAKE_PATH OFF)
+set(CMAKE_PREFIX_PATH )
+foreach(path "/does_not_exist" "/lib" "")
+  unset(CREATED_LIBRARY CACHE)
+  set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}${path}")
+  find_library(CREATED_LIBRARY NAMES created)
+  message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+endforeach()
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON)
+set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout-cygwin.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout-cygwin.txt
new file mode 100644
index 0000000..1ab884c
--- /dev/null
+++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout-cygwin.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout-windows.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout-windows.txt
new file mode 100644
index 0000000..1ab884c
--- /dev/null
+++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout-windows.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt
index 1ab884c..c6ff513 100644
--- a/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt
+++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt
@@ -1,4 +1,4 @@
 -- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND'
--- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
--- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
--- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND'
+-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND'
+-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake
index e7e8db3..643a5b9 100644
--- a/Tests/RunCMake/find_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake
@@ -1,9 +1,9 @@
 include(RunCMake)
 
 run_cmake(Created)
+run_cmake(FromPrefixPath)
+run_cmake(FromPATHEnv)
 if(CMAKE_HOST_UNIX)
   run_cmake(LibArchLink)
 endif()
-if(WIN32 OR CYGWIN)
-  run_cmake(PrefixInPATH)
-endif()
+run_cmake(PrefixInPATH)
diff --git a/Tests/RunCMake/find_package/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_package/FromPATHEnv-stdout.txt
new file mode 100644
index 0000000..2ead349
--- /dev/null
+++ b/Tests/RunCMake/find_package/FromPATHEnv-stdout.txt
@@ -0,0 +1,9 @@
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='1'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
diff --git a/Tests/RunCMake/find_package/FromPATHEnv.cmake b/Tests/RunCMake/find_package/FromPATHEnv.cmake
new file mode 100644
index 0000000..4822b13
--- /dev/null
+++ b/Tests/RunCMake/find_package/FromPATHEnv.cmake
@@ -0,0 +1,27 @@
+set(ENV_PATH "$ENV{PATH}")
+foreach(path "/does_not_exist" "/PackageRoot" "")
+  unset(Resolved_FOUND CACHE)
+  set(Resolved_DIR "")
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_package(Resolved QUIET)
+  message(STATUS "Resolved_FOUND='${Resolved_FOUND}'")
+endforeach()
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
+foreach(path "/does_not_exist" "/PackageRoot" "")
+  unset(Resolved_FOUND CACHE)
+  set(Resolved_DIR "")
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_package(Resolved QUIET)
+  message(STATUS "Resolved_FOUND='${Resolved_FOUND}'")
+endforeach()
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON)
+foreach(path "/does_not_exist" "/PackageRoot" "")
+  unset(Resolved_FOUND CACHE)
+  set(Resolved_DIR "")
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_package(Resolved NO_SYSTEM_ENVIRONMENT_PATH QUIET)
+  message(STATUS "Resolved_FOUND='${Resolved_FOUND}'")
+endforeach()
+set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_package/FromPrefixPath-stdout.txt b/Tests/RunCMake/find_package/FromPrefixPath-stdout.txt
new file mode 100644
index 0000000..2ead349
--- /dev/null
+++ b/Tests/RunCMake/find_package/FromPrefixPath-stdout.txt
@@ -0,0 +1,9 @@
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='1'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
+-- Resolved_FOUND='0'
diff --git a/Tests/RunCMake/find_package/FromPrefixPath.cmake b/Tests/RunCMake/find_package/FromPrefixPath.cmake
new file mode 100644
index 0000000..be853c1
--- /dev/null
+++ b/Tests/RunCMake/find_package/FromPrefixPath.cmake
@@ -0,0 +1,29 @@
+set(ENV_PATH "$ENV{PATH}")
+set(ENV{PATH} "")
+foreach(path "/does_not_exist" "/PackageRoot" "")
+  unset(Resolved_FOUND CACHE)
+  set(Resolved_DIR "")
+  set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_package(Resolved QUIET)
+  message(STATUS "Resolved_FOUND='${Resolved_FOUND}'")
+endforeach()
+
+set(CMAKE_FIND_USE_CMAKE_PATH OFF)
+set(CMAKE_PREFIX_PATH )
+foreach(path "/does_not_exist" "/PackageRoot" "")
+  unset(Resolved_FOUND CACHE)
+  set(Resolved_DIR "")
+  set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_package(Resolved QUIET)
+  message(STATUS "Resolved_FOUND='${Resolved_FOUND}'")
+endforeach()
+
+set(CMAKE_FIND_USE_CMAKE_PATH ON)
+foreach(path "/does_not_exist" "/PackageRoot" "")
+  unset(Resolved_FOUND CACHE)
+  set(Resolved_DIR "")
+  set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_package(Resolved NO_CMAKE_PATH QUIET)
+  message(STATUS "Resolved_FOUND='${Resolved_FOUND}'")
+endforeach()
+set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index 066523e..208f83c 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -3,6 +3,8 @@
 run_cmake(CMP0074-WARN)
 run_cmake(CMP0074-OLD)
 run_cmake(ComponentRequiredAndOptional)
+run_cmake(FromPATHEnv)
+run_cmake(FromPrefixPath)
 run_cmake(MissingNormal)
 run_cmake(MissingNormalRequired)
 run_cmake(MissingNormalVersion)
diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout-cygwin.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout-cygwin.txt
new file mode 100644
index 0000000..8f3e7ca
--- /dev/null
+++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout-cygwin.txt
@@ -0,0 +1,9 @@
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include'
+-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout-windows.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout-windows.txt
new file mode 100644
index 0000000..8f3e7ca
--- /dev/null
+++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout-windows.txt
@@ -0,0 +1,9 @@
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include'
+-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout.txt
new file mode 100644
index 0000000..fd41bf4
--- /dev/null
+++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout.txt
@@ -0,0 +1,9 @@
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
+-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND'
diff --git a/Tests/RunCMake/find_path/FromPATHEnv.cmake b/Tests/RunCMake/find_path/FromPATHEnv.cmake
new file mode 100644
index 0000000..af13d09
--- /dev/null
+++ b/Tests/RunCMake/find_path/FromPATHEnv.cmake
@@ -0,0 +1,25 @@
+set(ENV_PATH "$ENV{PATH}")
+foreach(path "/does_not_exist" "/include" "")
+  unset(PATH_IN_ENV_PATH CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_path(PATH_IN_ENV_PATH NAMES PrefixInPATH.h)
+  message(STATUS "PATH_IN_ENV_PATH='${PATH_IN_ENV_PATH}'")
+endforeach()
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
+foreach(path "/does_not_exist" "/include" "")
+  unset(PATH_IN_ENV_PATH CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_path(PATH_IN_ENV_PATH NAMES PrefixInPATH.h)
+  message(STATUS "PATH_IN_ENV_PATH='${PATH_IN_ENV_PATH}'")
+endforeach()
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON)
+foreach(path "/does_not_exist" "/include" "")
+  unset(PATH_IN_ENV_PATH CACHE)
+  set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}")
+  find_path(PATH_IN_ENV_PATH NAMES PrefixInPATH.h NO_SYSTEM_ENVIRONMENT_PATH)
+  message(STATUS "PATH_IN_ENV_PATH='${PATH_IN_ENV_PATH}'")
+endforeach()
+
+set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout-cygwin.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout-cygwin.txt
new file mode 100644
index 0000000..bb2ceb7
--- /dev/null
+++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout-cygwin.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout-windows.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout-windows.txt
new file mode 100644
index 0000000..bb2ceb7
--- /dev/null
+++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout-windows.txt
@@ -0,0 +1,4 @@
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
+-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt
index bb2ceb7..947a900 100644
--- a/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt
+++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt
@@ -1,4 +1,4 @@
 -- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
--- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
--- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
--- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include'
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
+-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND'
diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake
index bf0fa89..8b5b5b7 100644
--- a/Tests/RunCMake/find_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake
@@ -1,8 +1,7 @@
 include(RunCMake)
 
-if(WIN32 OR CYGWIN)
-  run_cmake(PrefixInPATH)
-endif()
+run_cmake(FromPATHEnv)
+run_cmake(PrefixInPATH)
 
 if(APPLE)
   run_cmake(FrameworksWithSubdirs)
diff --git a/Tests/RunCMake/find_program/EnvAndHints-stdout.txt b/Tests/RunCMake/find_program/EnvAndHints-stdout.txt
index 39329b2..0051636 100644
--- a/Tests/RunCMake/find_program/EnvAndHints-stdout.txt
+++ b/Tests/RunCMake/find_program/EnvAndHints-stdout.txt
@@ -1 +1,4 @@
 -- PROG='[^']*/Tests/RunCMake/find_program/A/testAandB'
+-- PROG='PROG-NOTFOUND'
+-- PROG='[^']*/Tests/RunCMake/find_program/B/testAandB'
+-- PROG='[^']*/Tests/RunCMake/find_program/A/testAandB'
diff --git a/Tests/RunCMake/find_program/EnvAndHints.cmake b/Tests/RunCMake/find_program/EnvAndHints.cmake
index 14ebd6e..0f12eff 100644
--- a/Tests/RunCMake/find_program/EnvAndHints.cmake
+++ b/Tests/RunCMake/find_program/EnvAndHints.cmake
@@ -1,8 +1,31 @@
+
 set(ENV_PATH "$ENV{PATH}")
 set(ENV{PATH} ${CMAKE_CURRENT_SOURCE_DIR}/A)
 find_program(PROG
   NAMES testAandB
+  )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
+
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
+find_program(PROG
+  NAMES testAandB
+  )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
+
+find_program(PROG
+  NAMES testAandB
+  HINTS ${CMAKE_CURRENT_SOURCE_DIR}/B ${CMAKE_CURRENT_SOURCE_DIR}/A
+  )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
+set(ENV{PATH} "${ENV_PATH}")
+
+find_program(PROG
+  NAMES testAandB
   HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B
   )
 message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
 set(ENV{PATH} "${ENV_PATH}")
diff --git a/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt b/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt
index cb3c99f..d2312e7 100644
--- a/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt
+++ b/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt
@@ -1,6 +1,8 @@
 -- PROG_ABS='PROG_ABS-NOTFOUND'
 -- PROG_ABS_NPD='PROG_ABS_NPD-NOTFOUND'
 -- PROG_CWD='PROG_CWD-NOTFOUND'
+-- PROG_CWD='PROG_CWD-NOTFOUND'
+-- PROG_CWD='[^']*/Tests/RunCMake/find_program/testCWD'
 -- PROG_CWD_NPD='PROG_CWD_NPD-NOTFOUND'
 -- PROG_CWD_DOT='[^']*/Tests/RunCMake/find_program/testCWD'
 -- PROG_CWD_DOT_NPD='[^']*/Tests/RunCMake/find_program/testCWD'
diff --git a/Tests/RunCMake/find_program/RelAndAbsPath.cmake b/Tests/RunCMake/find_program/RelAndAbsPath.cmake
index 9a42c5e..6b61980 100644
--- a/Tests/RunCMake/find_program/RelAndAbsPath.cmake
+++ b/Tests/RunCMake/find_program/RelAndAbsPath.cmake
@@ -10,7 +10,6 @@
 
 strip_windows_path_prefix("${CMAKE_CURRENT_SOURCE_DIR}" srcdir)
 
-file(MAKE_DIRECTORY "tmp${srcdir}")
 configure_file(testCWD "tmp${srcdir}/testNoSuchFile" COPYONLY)
 
 find_program(PROG_ABS
@@ -38,6 +37,28 @@
   )
 message(STATUS "PROG_CWD='${PROG_CWD}'")
 
+
+set(CMAKE_PREFIX_PATH ".")
+# On some platforms / dashboards the current working
+# directory can be in PATH or other search locations
+# so disable all searching to make sure this fails
+set(CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH OFF)
+set(CMAKE_FIND_USE_CMAKE_PATH OFF)
+set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH OFF)
+set(CMAKE_FIND_USE_PACKAGE_ROOT_PATH OFF)
+set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF)
+find_program(PROG_CWD
+  NAMES testCWD
+  )
+message(STATUS "PROG_CWD='${PROG_CWD}'")
+
+set(CMAKE_PREFIX_PATH ".")
+set(CMAKE_FIND_USE_CMAKE_PATH ON)
+find_program(PROG_CWD
+  NAMES testCWD
+  )
+message(STATUS "PROG_CWD='${PROG_CWD}'")
+
 find_program(PROG_CWD_NPD
   NAMES testCWD
   NAMES_PER_DIR
diff --git a/Tests/RunCMake/install/CMakeLists.txt b/Tests/RunCMake/install/CMakeLists.txt
index 6dd8cdf..c7e99ad 100644
--- a/Tests/RunCMake/install/CMakeLists.txt
+++ b/Tests/RunCMake/install/CMakeLists.txt
@@ -1,3 +1,6 @@
 cmake_minimum_required(VERSION 3.4)
+if(RunCMake_TEST MATCHES "^file-GET_RUNTIME_DEPENDENCIES")
+  cmake_policy(SET CMP0087 NEW)
+endif()
 project(${RunCMake_TEST} NONE)
 include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index c637db1..21c320b 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -48,6 +48,22 @@
   endif()
 endfunction()
 
+# Wrapper for run_cmake() that skips platforms that are non-ELF or have no RPATH support
+function(run_cmake_ELFRPATH_only case)
+  if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+    run_cmake(${case})
+  else()
+    # Sanity check against a platform known to be ELF-based
+    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+      message(FATAL_ERROR "Expected platform Linux to advertize itself as ELF-based, but it did not.")
+    else()
+      message(STATUS "${case} - SKIPPED (No ELF-based platform found)")
+    endif()
+  endif()
+endfunction()
+
+run_cmake(TARGETS-FILE_RPATH_CHANGE-old_rpath)
+run_cmake_ELFRPATH_only(TARGETS-FILE_RPATH_CHANGE-new_rpath)
 run_cmake(DIRECTORY-MESSAGE_NEVER)
 run_cmake(DIRECTORY-PATTERN-MESSAGE_NEVER)
 run_cmake(DIRECTORY-message)
@@ -139,6 +155,36 @@
 run_install_test(TARGETS-RPATH)
 run_install_test(InstallRequiredSystemLibraries)
 
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-unresolved)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-conflict)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-notfile)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-project)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2)
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-unresolved)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-conflict)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-notfile)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-project)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2)
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+  if(NOT CMAKE_C_COMPILER_ID MATCHES "^XL")
+    run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux)
+  endif()
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-unresolved)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-conflict)
+  run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-notfile)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-project)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1)
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2)
+else()
+  run_cmake(file-GET_RUNTIME_DEPENDENCIES-unsupported)
+endif()
+
 set(run_install_test_components 1)
 run_install_test(FILES-EXCLUDE_FROM_ALL)
 run_install_test(TARGETS-EXCLUDE_FROM_ALL)
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake
new file mode 100644
index 0000000..673fdde
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake
@@ -0,0 +1,30 @@
+file(READ ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake install_script)
+#message(STATUS ${install_script})
+
+set(wsnl " *[\n\r]+ *") # whitespace + single newline + whitespace
+set(wssl " *[\n\r]+[^\n\r]*[\n\r]+ *") # ws nl skipline nl ws
+string(CONCAT prefix [[file\(RPATH_CHANGE]])
+set(_msg "cmake_install.cmake does not match ")
+
+macro(check)
+  if(NOT install_script MATCHES "${regex}")
+    message(STATUS "${test} - check \"${target}\" - FAILED:")
+    string(CONCAT RunCMake_TEST_FAILED "${_msg}" ">>>${regex}<<<")
+    return()
+  else()
+    message(STATUS "${test} - check \"${target}\" - PASSED")
+  endif()
+endmacro()
+
+macro(skip_without_rpath_change_rule)
+# Not all platforms generate a file(RPATH_CHANGE) rule
+  if(NOT install_script MATCHES [[file\(RPATH_CHANGE]])
+    # Sanity check against a platform known to generate a file(RPATH_CHANGE) rule
+    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+      message(FATAL_ERROR "Expected generated file(RPATH_CHANGE) rule on platform Linux.")
+    else()
+      message(STATUS "${test} - All checks skipped. No file(RPATH_CHANGE) rule found on this platform.")
+      return()
+    endif()
+  endif()
+endmacro()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake
new file mode 100644
index 0000000..930ef70
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake
@@ -0,0 +1,63 @@
+include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake)
+skip_without_rpath_change_rule()
+string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]])
+
+set(target "exe1_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar]])
+check()
+
+set(target "exe1_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar]])
+check()
+
+set(target "exe1_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar]])
+check()
+
+set(target "exe2_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\$ORIGIN/../lib]])
+check()
+
+set(target "exe2_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\$ORIGIN/../lib]])
+check()
+
+set(target "exe2_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\\\$ORIGIN/../lib]])
+check()
+
+set(target "exe3_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\${ORIGIN}/../lib]])
+check()
+
+set(target "exe3_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\${ORIGIN}/../lib]])
+check()
+
+set(target "exe3_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\\\${ORIGIN}/../lib]])
+check()
+
+set(target "exe4_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar/\${PLATFORM}]])
+check()
+
+set(target "exe4_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar/\${PLATFORM}]])
+check()
+
+set(target "exe4_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar/\\\${PLATFORM}]])
+check()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt
new file mode 100644
index 0000000..1e123f6
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt
@@ -0,0 +1,23 @@
+^CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\):
+  Policy CMP0095 is not set: RPATH entries are properly escaped in the
+  intermediary CMake install script\.  Run "cmake --help-policy CMP0095" for
+  policy details\.  Use the cmake_policy command to set the policy and
+  suppress this warning\.
+
+  RPATH entries for target 'exe3_cmp0095_warn' will not be escaped in the
+  intermediary cmake_install\.cmake script\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\):
+  Policy CMP0095 is not set: RPATH entries are properly escaped in the
+  intermediary CMake install script\.  Run "cmake --help-policy CMP0095" for
+  policy details\.  Use the cmake_policy command to set the policy and
+  suppress this warning\.
+
+  RPATH entries for target 'exe4_cmp0095_warn' will not be escaped in the
+  intermediary cmake_install\.cmake script\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake
new file mode 100644
index 0000000..cba04b2
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake
@@ -0,0 +1,72 @@
+cmake_minimum_required(VERSION 3.14)
+enable_language(C)
+
+# test matrix
+#
+# A :=
+#                        | no cmake syntax | cmake syntax |
+# -----------------------+-----------------+--------------+
+# absolute install RPATH |       exe1      |     exe4     |
+# relative install RPATH |       exe2      |     exe3     |
+#
+# all := A * CMP005_OLD + A * CMP0095_WARN + A * CMP0095_NEW
+
+add_library(utils SHARED obj1.c)
+set(targets utils)
+
+set(exe1_install_rpath "/foo/bar")
+set(exe2_install_rpath "\$ORIGIN/../lib")
+set(exe3_install_rpath "\${ORIGIN}/../lib")
+set(exe4_install_rpath "/foo/bar/\${PLATFORM}")
+
+macro(A_CMP0095 policy_value)
+  cmake_policy(PUSH)
+  if(NOT "x${policy_value}x" STREQUAL "xWARNx")
+    cmake_policy(SET CMP0095 ${policy_value})
+  endif()
+  string(TOLOWER "${policy_value}" p)
+
+  # exe1: absolute install RPATH, no cmake syntax
+  set(case "exe1")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  # exe2: relative install RPATH, no cmake syntax
+  set(case "exe2")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  # exe3: relative install RPATH, cmake syntax
+  set(case "exe3")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  # exe4: absolute install RPATH, cmake syntax
+  set(case "exe4")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  cmake_policy(POP)
+endmacro()
+
+A_CMP0095("OLD")
+A_CMP0095("WARN") # exe3 and exe4 are expected to issue an author warning
+A_CMP0095("NEW")
+
+install(TARGETS ${targets})
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake
new file mode 100644
index 0000000..814f405
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake
@@ -0,0 +1,15 @@
+include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake)
+skip_without_rpath_change_rule()
+string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]])
+
+set(target "exe1")
+string(CONCAT regex "${prefix}${target}\"${wsnl}"
+              [[OLD_RPATH "]] "${RunCMake_BINARY_DIR}")
+check()
+
+if("x${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}" STREQUAL "x\$ORIGIN")
+  set(target "exe2")
+  string(CONCAT regex "${prefix}${target}\"${wsnl}"
+                [[OLD_RPATH "\\\$ORIGIN]])
+  check()
+endif()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake
new file mode 100644
index 0000000..43ae787
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.14)
+enable_language(C)
+
+add_library(utils SHARED obj1.c)
+
+# exe1: absolute build RPATH, no cmake syntax
+set(CMAKE_BUILD_RPATH_USE_ORIGIN OFF)
+set(CMAKE_INSTALL_RPATH "/foo/bar")
+add_executable(exe1 main.c)
+target_link_libraries(exe1 PRIVATE utils)
+
+# exe2: relative build RPATH, no cmake syntax
+set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
+set(CMAKE_INSTALL_RPATH "/foo/bar")
+add_executable(exe2 main.c)
+target_link_libraries(exe2 PRIVATE utils)
+
+install(TARGETS utils exe1 exe2)
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-stderr.txt
new file mode 100644
index 0000000..b66d1fe
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-stderr.txt
@@ -0,0 +1,18 @@
+^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-badargs1\.cmake:[0-9]+ \(file\):
+  You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\.  This is
+  probably not what you intended to do\.  Instead, please consider using it in
+  an install\(CODE\) or install\(SCRIPT\) command\.  For example:
+
+    install\(CODE \[\[
+      file\(GET_RUNTIME_DEPENDENCIES
+        # \.\.\.
+        \)
+      ]]\)
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+
+CMake Error at file-GET_RUNTIME_DEPENDENCIES-badargs1\.cmake:[0-9]+ \(file\):
+  file Unrecognized argument: "invalid"
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1.cmake
new file mode 100644
index 0000000..f3b8ce4
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1.cmake
@@ -0,0 +1,2 @@
+file(GET_RUNTIME_DEPENDENCIES invalid)
+message(FATAL_ERROR "This message should not be displayed")
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-stderr.txt
new file mode 100644
index 0000000..94f0f46
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-stderr.txt
@@ -0,0 +1,18 @@
+^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-badargs2\.cmake:[0-9]+ \(file\):
+  You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\.  This is
+  probably not what you intended to do\.  Instead, please consider using it in
+  an install\(CODE\) or install\(SCRIPT\) command\.  For example:
+
+    install\(CODE \[\[
+      file\(GET_RUNTIME_DEPENDENCIES
+        # \.\.\.
+        \)
+      ]]\)
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+
+CMake Error at file-GET_RUNTIME_DEPENDENCIES-badargs2\.cmake:[0-9]+ \(file\):
+  file Keyword missing value: BUNDLE_EXECUTABLE
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2.cmake
new file mode 100644
index 0000000..138ab95
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2.cmake
@@ -0,0 +1,2 @@
+file(GET_RUNTIME_DEPENDENCIES BUNDLE_EXECUTABLE)
+message(FATAL_ERROR "This message should not be displayed")
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-check.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-check.cmake
new file mode 100644
index 0000000..ab630f0
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-check.cmake
@@ -0,0 +1,44 @@
+function(check_contents filename contents_regex)
+  if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
+    file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
+    if(NOT contents MATCHES "${contents_regex}")
+      string(APPEND RunCMake_TEST_FAILED "File contents:
+  ${contents}
+do not match what we expected:
+  ${contents_regex}
+in file:
+  ${CMAKE_INSTALL_PREFIX}/${filename}\n")
+      set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+    endif()
+  else()
+    string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
+    set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+  endif()
+endfunction()
+
+set(_check
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/libtest_rpath\.so]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/libtest_runpath\.so]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath/librpath\.so]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_parent/librpath_parent\.so]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search/librpath_search\.so]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath/librunpath\.so]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search/librunpath_search\.so]]
+  )
+check_contents(deps/deps1.txt "^${_check}$")
+check_contents(deps/deps2.txt "^${_check}$")
+check_contents(deps/deps3.txt "^${_check}$")
+set(_check
+  [[librpath_unresolved\.so]]
+  [[librunpath_parent_unresolved\.so]]
+  [[librunpath_unresolved\.so]]
+  )
+check_contents(deps/udeps1.txt "^${_check}$")
+check_contents(deps/udeps2.txt "^${_check}$")
+check_contents(deps/udeps3.txt "^${_check}$")
+set(_check
+  "^libconflict\\.so:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/conflict/libconflict\\.so;[^;]*/Tests/RunCMake/install/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}")
+check_contents(deps/cdeps3.txt "${_check}")
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-stderr.txt
new file mode 100644
index 0000000..123ae48
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-stderr.txt
@@ -0,0 +1,119 @@
+^CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librpath_search_postexcluded\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librpath_search\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librunpath_search_postexcluded\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librunpath_search\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librpath_search_postexcluded\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librpath_search\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librunpath_search_postexcluded\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librunpath_search\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librpath_search_postexcluded\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librpath_search\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librunpath_search_postexcluded\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
+
+*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
+  Dependency librunpath_search\.so found in search directory:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search
+
+  See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
+Call Stack \(most recent call first\):
+  cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-stderr.txt
new file mode 100644
index 0000000..1692348
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Multiple conflicting paths found for librpath\.so:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-build/root-all/lib/rpath1/librpath\.so
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-build/root-all/lib/rpath2/librpath\.so$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict.cmake
new file mode 100644
index 0000000..f719499
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict.cmake
@@ -0,0 +1,54 @@
+enable_language(C)
+
+set(test1_names rpath)
+set(test2_names rpath)
+
+file(WRITE "${CMAKE_BINARY_DIR}/rpath.c" "void rpath(void) {}\n")
+add_library(rpath SHARED "${CMAKE_BINARY_DIR}/rpath.c")
+install(TARGETS rpath DESTINATION lib/rpath1)
+install(TARGETS rpath DESTINATION lib/rpath2)
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test1.c")
+add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c")
+foreach(name ${test1_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "void test1(void)\n{\n")
+foreach(name ${test1_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n")
+
+target_link_libraries(test1 PRIVATE ${test1_names})
+set_property(TARGET test1 PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath1"
+  )
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test2.c")
+add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c")
+foreach(name ${test2_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "void test2(void)\n{\n")
+foreach(name ${test2_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n")
+
+target_link_libraries(test2 PRIVATE ${test2_names})
+set_property(TARGET test2 PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath2"
+  )
+
+install(TARGETS test1 test2 DESTINATION lib)
+
+install(CODE [[
+  file(GET_RUNTIME_DEPENDENCIES
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test1>"
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test2>"
+    PRE_INCLUDE_REGEXES "^librpath\\.so$"
+    PRE_EXCLUDE_REGEXES ".*"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-stderr.txt
new file mode 100644
index 0000000..83a87c9
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Failed to run objdump on:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-build/root-all/bin/\.\./lib/libtest\.so$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake
new file mode 100644
index 0000000..6567438
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake
@@ -0,0 +1,30 @@
+enable_language(C)
+cmake_policy(SET CMP0095 NEW)
+
+file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n")
+file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void);
+
+int main(void)
+{
+  test();
+  return 0;
+}
+]])
+
+add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c")
+add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
+target_link_libraries(exe PRIVATE test)
+set_property(TARGET exe PROPERTY INSTALL_RPATH "\${ORIGIN}/../lib")
+
+install(TARGETS exe DESTINATION bin)
+
+install(CODE [[
+  file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>")
+  file(GET_RUNTIME_DEPENDENCIES
+    EXECUTABLES
+      "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
+    PRE_INCLUDE_REGEXES "^libtest\\.so$"
+    PRE_EXCLUDE_REGEXES ".*"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-stderr.txt
new file mode 100644
index 0000000..eaca512
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Could not resolve file libunresolved\.so$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved.cmake
new file mode 100644
index 0000000..3efa305
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+
+file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "extern void unresolved(void);\nvoid testlib(void)\n{\n  unresolved();\n}\n")
+add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
+file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "void unresolved(void) {}\n")
+add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c")
+target_link_libraries(testlib PRIVATE unresolved)
+install(TARGETS testlib DESTINATION lib)
+
+install(CODE [[
+  file(GET_RUNTIME_DEPENDENCIES
+    PRE_INCLUDE_REGEXES "^libunresolved\\.so$"
+    PRE_EXCLUDE_REGEXES ".*"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake
new file mode 100644
index 0000000..bd0f9f1
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake
@@ -0,0 +1,169 @@
+enable_language(C)
+cmake_policy(SET CMP0095 NEW)
+
+set(test_rpath_names
+  preexcluded
+  rpath_postexcluded
+  rpath
+  rpath_parent_postexcluded
+  rpath_parent
+  rpath_origin_postexcluded
+  rpath_origin
+  rpath_search_postexcluded
+  rpath_search
+  rpath_unresolved
+  conflict
+  )
+set(test_runpath_names
+  runpath_postexcluded
+  runpath
+  runpath_origin_postexcluded
+  runpath_origin
+  runpath_parent_unresolved
+  runpath_search_postexcluded
+  runpath_search
+  runpath_unresolved
+  )
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test_rpath.c")
+add_library(test_rpath SHARED "${CMAKE_BINARY_DIR}/test_rpath.c")
+foreach(name ${test_rpath_names})
+  file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n")
+  add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
+
+  file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "void test_rpath(void)\n{\n")
+foreach(name ${test_rpath_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "}\n")
+
+install(TARGETS rpath_postexcluded DESTINATION lib/rpath_postexcluded)
+install(TARGETS rpath DESTINATION lib/rpath)
+install(TARGETS rpath_origin_postexcluded DESTINATION lib/rpath_origin_postexcluded)
+install(TARGETS rpath_origin DESTINATION lib/rpath_origin)
+install(TARGETS rpath_parent_postexcluded DESTINATION lib/rpath_parent_postexcluded)
+install(TARGETS rpath rpath_origin rpath_parent DESTINATION lib/rpath_parent)
+install(TARGETS rpath_search_postexcluded DESTINATION lib/rpath_search_postexcluded)
+install(TARGETS rpath rpath_origin rpath_parent rpath_search DESTINATION lib/rpath_search)
+install(TARGETS conflict DESTINATION lib/conflict)
+
+target_link_libraries(test_rpath PRIVATE ${test_rpath_names})
+set_property(TARGET test_rpath PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath_postexcluded"
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath"
+  "\$ORIGIN/rpath_origin_postexcluded"
+  "\${ORIGIN}/rpath_origin"
+  "${CMAKE_BINARY_DIR}/root-all/lib/conflict"
+  )
+target_link_options(test_rpath PRIVATE -Wl,--disable-new-dtags)
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test_runpath.c")
+add_library(test_runpath SHARED "${CMAKE_BINARY_DIR}/test_runpath.c")
+foreach(name ${test_runpath_names} rpath conflict)
+  file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n")
+  if(NOT name MATCHES "^(rpath|conflict)$")
+    add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
+  endif()
+
+  file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "void test_runpath(void)\n{\n")
+foreach(name ${test_runpath_names} rpath conflict)
+  file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "}\n")
+
+install(TARGETS runpath_postexcluded DESTINATION lib/runpath_postexcluded)
+install(TARGETS runpath DESTINATION lib/runpath)
+install(TARGETS runpath_origin_postexcluded DESTINATION lib/runpath_origin_postexcluded)
+install(TARGETS runpath_origin DESTINATION lib/runpath_origin)
+install(TARGETS runpath_parent_unresolved DESTINATION lib/runpath_parent_unresolved)
+install(TARGETS runpath_search_postexcluded DESTINATION lib/runpath_search_postexcluded)
+install(TARGETS runpath runpath_origin runpath_search DESTINATION lib/runpath_search)
+install(TARGETS conflict DESTINATION lib/conflict2)
+
+target_link_libraries(test_runpath PRIVATE ${test_runpath_names} rpath conflict)
+set_property(TARGET test_runpath PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/lib/runpath/../rpath" # Ensure that files that don't conflict are treated correctly
+  "${CMAKE_BINARY_DIR}/root-all/lib/runpath_postexcluded"
+  "${CMAKE_BINARY_DIR}/root-all/lib/runpath"
+  "\${ORIGIN}/runpath_origin_postexcluded"
+  "\$ORIGIN/runpath_origin"
+  "${CMAKE_BINARY_DIR}/root-all/lib/conflict2"
+  )
+target_link_options(test_runpath PRIVATE -Wl,--enable-new-dtags)
+
+set_property(TARGET test_rpath ${test_rpath_names} test_runpath ${test_runpath_names} PROPERTY LIBRARY_OUTPUT_DIRECTORY lib)
+install(TARGETS test_rpath test_runpath DESTINATION lib)
+
+add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c)
+add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c)
+add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c)
+target_link_libraries(topexe PRIVATE test_rpath test_runpath)
+target_link_libraries(toplib PRIVATE test_rpath test_runpath)
+target_link_libraries(topmod PRIVATE test_rpath test_runpath)
+set_property(TARGET topexe toplib topmod PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/lib"
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath_parent_postexcluded"
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath_parent"
+  "${CMAKE_BINARY_DIR}/root-all/lib/runpath_parent_unresolved"
+  )
+target_link_options(topexe PRIVATE -Wl,--disable-new-dtags)
+target_link_options(toplib PRIVATE -Wl,--disable-new-dtags)
+target_link_options(topmod PRIVATE -Wl,--disable-new-dtags)
+
+install(TARGETS topexe toplib RUNTIME DESTINATION bin LIBRARY DESTINATION lib)
+install(TARGETS topmod LIBRARY DESTINATION lib/modules)
+
+install(CODE [[
+  function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile)
+    file(GET_RUNTIME_DEPENDENCIES
+      RESOLVED_DEPENDENCIES_VAR deps
+      UNRESOLVED_DEPENDENCIES_VAR udeps
+      CONFLICTING_DEPENDENCIES_PREFIX cdeps
+      PRE_INCLUDE_REGEXES
+        "^lib(test_rpath|rpath_postexcluded|rpath|rpath_parent_postexcluded|rpath_parent|rpath_origin_postexcluded|rpath_origin|rpath_search_postexcluded|rpath_search|rpath_unresolved|test_runpath|runpath_postexcluded|runpath|runpath_origin_postexcluded|runpath_origin|runpath_parent_unresolved|runpath_search_postexcluded|runpath_search|runpath_unresolved|conflict)\\.so$"
+        "^libc\\.so"
+      PRE_EXCLUDE_REGEXES ".*"
+      POST_INCLUDE_REGEXES "^.*/(libtest_rpath|rpath/librpath|rpath_parent/librpath_parent|rpath_search/librpath_search|libtest_runpath|runpath/librunpath|runpath_origin_postexcluded|runpath_origin|runpath_search/librunpath_search|conflict2?/libconflict)\\.so$"
+      POST_EXCLUDE_REGEXES ".*"
+      DIRECTORIES
+        "${CMAKE_INSTALL_PREFIX}/lib/rpath_search_postexcluded"
+        "${CMAKE_INSTALL_PREFIX}/lib/rpath_search"
+        "${CMAKE_INSTALL_PREFIX}/lib/runpath_search_postexcluded"
+        "${CMAKE_INSTALL_PREFIX}/lib/runpath_search"
+      ${ARGN}
+      )
+    list(SORT deps)
+    list(SORT udeps)
+    list(SORT cdeps_FILENAMES)
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}")
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}")
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "")
+    foreach(cdep IN LISTS cdeps_FILENAMES)
+      set(cdep_values ${cdeps_${cdep}})
+      list(SORT cdep_values)
+      file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n")
+    endforeach()
+  endfunction()
+
+  exec_get_runtime_dependencies(
+    deps1.txt udeps1.txt cdeps1.txt
+    EXECUTABLES
+      "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topexe>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps2.txt udeps2.txt cdeps2.txt
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:toplib>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps3.txt udeps3.txt cdeps3.txt
+    MODULES
+      "${CMAKE_INSTALL_PREFIX}/lib/modules/$<TARGET_FILE_NAME:topmod>"
+    )
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c
new file mode 100644
index 0000000..d196afe
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c
@@ -0,0 +1,9 @@
+extern void test_rpath(void);
+extern void test_runpath(void);
+
+int main(void)
+{
+  test_rpath();
+  test_runpath();
+  return 0;
+}
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c
new file mode 100644
index 0000000..040e591
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c
@@ -0,0 +1,8 @@
+extern void test_rpath(void);
+extern void test_runpath(void);
+
+void toplib(void)
+{
+  test_rpath();
+  test_runpath();
+}
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-all-check.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-all-check.cmake
new file mode 100644
index 0000000..4d6dde1
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-all-check.cmake
@@ -0,0 +1,157 @@
+function(check_contents filename contents_regex)
+  if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
+    file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
+    if(NOT contents MATCHES "${contents_regex}")
+      string(APPEND RunCMake_TEST_FAILED "File contents:
+  ${contents}
+do not match what we expected:
+  ${contents_regex}
+in file:
+  ${CMAKE_INSTALL_PREFIX}/${filename}\n")
+      set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+    endif()
+  else()
+    string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
+    set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+  endif()
+endfunction()
+
+set(_check
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/executable_path/libexecutable_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/rpath_executable_path/librpath_executable_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
+  [[/usr/lib/libSystem\.B\.dylib]]
+  )
+check_contents(deps/deps1.txt "^${_check}$")
+
+set(_check
+  [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
+  [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
+  [[@rpath/librpath_executable_path_bundle\.dylib]]
+  [[@rpath/librpath_loader_path_unresolved\.dylib]]
+  [[@rpath/librpath_unresolved\.dylib]]
+  )
+check_contents(deps/udeps1.txt "^${_check}$")
+
+set(_check
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
+  [[/usr/lib/libSystem\.B\.dylib]]
+  )
+check_contents(deps/deps2.txt "^${_check}$")
+
+set(_check
+  [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
+  [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
+  [[@executable_path/../lib/executable_path_postexcluded/libexecutable_path_postexcluded\.dylib]]
+  [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
+  [[@rpath/librpath_executable_path\.dylib]]
+  [[@rpath/librpath_executable_path_bundle\.dylib]]
+  [[@rpath/librpath_executable_path_postexcluded\.dylib]]
+  [[@rpath/librpath_loader_path_unresolved\.dylib]]
+  [[@rpath/librpath_unresolved\.dylib]]
+  )
+check_contents(deps/udeps2.txt "^${_check}$")
+
+set(_check
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
+  [[/usr/lib/libSystem\.B\.dylib]]
+  )
+check_contents(deps/deps3.txt "^${_check}$")
+
+set(_check
+  [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
+  [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
+  [[@executable_path/../lib/executable_path_postexcluded/libexecutable_path_postexcluded\.dylib]]
+  [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
+  [[@rpath/librpath_executable_path\.dylib]]
+  [[@rpath/librpath_executable_path_bundle\.dylib]]
+  [[@rpath/librpath_executable_path_postexcluded\.dylib]]
+  [[@rpath/librpath_loader_path_unresolved\.dylib]]
+  [[@rpath/librpath_unresolved\.dylib]]
+  )
+check_contents(deps/udeps3.txt "^${_check}$")
+
+set(_check
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/executable_path/libexecutable_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/rpath_executable_path/librpath_executable_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
+  [[/usr/lib/libSystem\.B\.dylib]]
+  )
+check_contents(deps/deps4.txt "^${_check}$")
+
+set(_check
+  [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
+  [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
+  [[@rpath/librpath_executable_path_bundle\.dylib]]
+  [[@rpath/librpath_loader_path_unresolved\.dylib]]
+  [[@rpath/librpath_unresolved\.dylib]]
+  )
+check_contents(deps/udeps4.txt "^${_check}$")
+
+set(_check
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/bundle_executable/bin/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
+  [[/usr/lib/libSystem\.B\.dylib]]
+  )
+check_contents(deps/deps5.txt "^${_check}$")
+
+set(_check
+  [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
+  [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
+  [[@rpath/librpath_executable_path\.dylib]]
+  [[@rpath/librpath_executable_path_bundle\.dylib]]
+  [[@rpath/librpath_loader_path_unresolved\.dylib]]
+  [[@rpath/librpath_unresolved\.dylib]]
+  )
+check_contents(deps/udeps5.txt "^${_check}$")
+
+set(_check
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/bundle_executable/bin/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
+  [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
+  [[/usr/lib/libSystem\.B\.dylib]]
+  )
+check_contents(deps/deps6.txt "^${_check}$")
+
+set(_check
+  [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
+  [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
+  [[@rpath/librpath_executable_path\.dylib]]
+  [[@rpath/librpath_executable_path_bundle\.dylib]]
+  [[@rpath/librpath_loader_path_unresolved\.dylib]]
+  [[@rpath/librpath_unresolved\.dylib]]
+  )
+check_contents(deps/udeps6.txt "^${_check}$")
+
+set(_check
+  "^libconflict\\.dylib:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/conflict/libconflict\\.dylib;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/conflict2/libconflict\\.dylib\n$"
+  )
+check_contents(deps/cdeps1.txt "${_check}")
+check_contents(deps/cdeps2.txt "${_check}")
+check_contents(deps/cdeps3.txt "${_check}")
+check_contents(deps/cdeps4.txt "${_check}")
+check_contents(deps/cdeps5.txt "${_check}")
+check_contents(deps/cdeps6.txt "${_check}")
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-stderr.txt
new file mode 100644
index 0000000..bc9e97a
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Multiple conflicting paths found for librpath\.dylib:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-build/root-all/lib/rpath1/librpath\.dylib
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-build/root-all/lib/rpath2/librpath\.dylib$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict.cmake
new file mode 100644
index 0000000..a8446fe
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict.cmake
@@ -0,0 +1,55 @@
+enable_language(C)
+
+set(test1_names rpath)
+set(test2_names rpath)
+
+file(WRITE "${CMAKE_BINARY_DIR}/rpath.c" "void rpath(void) {}\n")
+add_library(rpath SHARED "${CMAKE_BINARY_DIR}/rpath.c")
+set_property(TARGET rpath PROPERTY INSTALL_NAME_DIR @rpath)
+install(TARGETS rpath DESTINATION lib/rpath1)
+install(TARGETS rpath DESTINATION lib/rpath2)
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test1.c")
+add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c")
+foreach(name ${test1_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "void test1(void)\n{\n")
+foreach(name ${test1_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n")
+
+target_link_libraries(test1 PRIVATE ${test1_names})
+set_property(TARGET test1 PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath1"
+  )
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test2.c")
+add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c")
+foreach(name ${test2_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "void test2(void)\n{\n")
+foreach(name ${test2_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n")
+
+target_link_libraries(test2 PRIVATE ${test2_names})
+set_property(TARGET test2 PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/lib/rpath2"
+  )
+
+install(TARGETS test1 test2 DESTINATION lib)
+
+install(CODE [[
+  file(GET_RUNTIME_DEPENDENCIES
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test1>"
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test2>"
+    PRE_INCLUDE_REGEXES "^@rpath/librpath\\.dylib$"
+    PRE_EXCLUDE_REGEXES ".*"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-stderr.txt
new file mode 100644
index 0000000..73ab9f1
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Failed to run otool on:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-build/root-all/bin/\.\./lib/libtest\.dylib$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile.cmake
new file mode 100644
index 0000000..3e4c434
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile.cmake
@@ -0,0 +1,30 @@
+enable_language(C)
+
+file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n")
+file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void);
+
+int main(void)
+{
+  test();
+  return 0;
+}
+]])
+
+add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c")
+set_property(TARGET test PROPERTY INSTALL_NAME_DIR @rpath)
+add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
+target_link_libraries(exe PRIVATE test)
+set_property(TARGET exe PROPERTY INSTALL_RPATH "@loader_path/../lib")
+
+install(TARGETS exe DESTINATION bin)
+
+install(CODE [[
+  file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>")
+  file(GET_RUNTIME_DEPENDENCIES
+    EXECUTABLES
+      "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
+    PRE_INCLUDE_REGEXES "^@rpath/libtest\\.dylib$"
+    PRE_EXCLUDE_REGEXES ".*"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-stderr.txt
new file mode 100644
index 0000000..01762b4
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Could not resolve file @rpath/libunresolved\.dylib$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved.cmake
new file mode 100644
index 0000000..c9b6c95
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+
+file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "extern void unresolved(void);\nvoid testlib(void)\n{\n  unresolved();\n}\n")
+add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
+file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "void unresolved(void) {}\n")
+add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c")
+target_link_libraries(testlib PRIVATE unresolved)
+install(TARGETS testlib DESTINATION lib)
+
+install(CODE [[
+  file(GET_RUNTIME_DEPENDENCIES
+    PRE_INCLUDE_REGEXES "^@rpath/libunresolved\\.dylib$"
+    PRE_EXCLUDE_REGEXES ".*"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake
new file mode 100644
index 0000000..6db05b3
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake
@@ -0,0 +1,216 @@
+enable_language(C)
+
+set(testlib_names
+  preexcluded
+  executable_path
+  executable_path_bundle
+  executable_path_postexcluded
+  loader_path
+  loader_path_unresolved
+  loader_path_postexcluded
+  rpath
+  rpath_unresolved
+  rpath_postexcluded
+  rpath_executable_path
+  rpath_executable_path_bundle
+  rpath_executable_path_postexcluded
+  rpath_loader_path
+  rpath_loader_path_unresolved
+  rpath_loader_path_postexcluded
+  normal
+  normal_unresolved
+  normal_postexcluded
+  conflict
+  )
+
+file(REMOVE "${CMAKE_BINARY_DIR}/testlib.c")
+add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
+foreach(name ${testlib_names})
+  if(name STREQUAL "normal")
+    file(WRITE "${CMAKE_BINARY_DIR}/normal.c" "extern void rpath(void);\nvoid normal(void)\n{\n  rpath();\n}\n")
+  else()
+    file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n")
+  endif()
+  add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
+
+  file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "void testlib(void)\n{\n")
+foreach(name ${testlib_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "}\n")
+set_property(TARGET ${testlib_names} PROPERTY BUILD_WITH_INSTALL_NAME_DIR 1)
+target_link_libraries(normal PRIVATE rpath)
+set_property(TARGET normal PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/executable/lib/normal/../rpath"
+  )
+
+file(WRITE "${CMAKE_BINARY_DIR}/testlib_conflict.c" "extern void conflict(void);\nvoid testlib_conflict(void)\n{\n  conflict();\n}\n")
+add_library(testlib_conflict SHARED "${CMAKE_BINARY_DIR}/testlib_conflict.c")
+target_link_libraries(testlib_conflict PRIVATE conflict)
+
+set_property(TARGET testlib PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath"
+  "${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath_unresolved"
+  "${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath_postexcluded"
+  "${CMAKE_BINARY_DIR}/root-all/executable/lib/conflict"
+  @executable_path/../lib/rpath_executable_path
+  @executable_path/../lib/rpath_executable_path_unresolved
+  @executable_path/../lib/rpath_executable_path_postexcluded
+  @loader_path/rpath_loader_path
+  @loader_path/rpath_loader_path_unresolved
+  @loader_path/rpath_loader_path_postexcluded
+  )
+set_property(TARGET testlib_conflict PROPERTY INSTALL_RPATH
+  "${CMAKE_BINARY_DIR}/root-all/executable/lib/conflict2"
+  )
+
+foreach(t
+  executable_path
+  executable_path_postexcluded
+  loader_path
+  loader_path_postexcluded
+  rpath
+  rpath_postexcluded
+  rpath_executable_path
+  rpath_executable_path_postexcluded
+  rpath_loader_path
+  rpath_loader_path_postexcluded
+  conflict
+  )
+  install(TARGETS ${t} DESTINATION executable/lib/${t})
+endforeach()
+install(TARGETS conflict DESTINATION executable/lib/conflict2)
+
+foreach(t
+  executable_path_bundle
+  executable_path_postexcluded
+  loader_path_postexcluded
+  rpath_postexcluded
+  rpath_executable_path_bundle
+  rpath_executable_path_postexcluded
+  rpath_loader_path_postexcluded
+  )
+  install(TARGETS ${t} DESTINATION bundle_executable/lib/${t})
+endforeach()
+
+foreach(t executable_path executable_path_bundle executable_path_postexcluded)
+  set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @executable_path/../lib/${t})
+endforeach()
+
+foreach(t loader_path loader_path_unresolved loader_path_postexcluded)
+  set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @loader_path/${t})
+endforeach()
+
+foreach(t
+  rpath
+  rpath_unresolved
+  rpath_postexcluded
+  rpath_executable_path
+  rpath_executable_path_bundle
+  rpath_executable_path_postexcluded
+  rpath_loader_path
+  rpath_loader_path_unresolved
+  rpath_loader_path_postexcluded
+  conflict
+  )
+  set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @rpath)
+endforeach()
+
+foreach(t normal normal_unresolved normal_postexcluded)
+  set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR "${CMAKE_BINARY_DIR}/root-all/executable/lib/${t}")
+  if(NOT t STREQUAL "normal_unresolved")
+    install(TARGETS ${t} DESTINATION executable/lib/${t})
+  endif()
+endforeach()
+
+target_link_libraries(testlib PRIVATE ${testlib_names})
+
+add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c)
+add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c)
+add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c)
+target_link_libraries(topexe PRIVATE testlib)
+target_link_libraries(toplib PRIVATE testlib)
+target_link_libraries(topmod PRIVATE testlib)
+
+set_property(TARGET topexe toplib topmod PROPERTY INSTALL_RPATH "${CMAKE_BINARY_DIR}/root-all/executable/lib")
+
+install(TARGETS topexe toplib topmod testlib testlib_conflict RUNTIME DESTINATION executable/bin LIBRARY DESTINATION executable/lib)
+install(TARGETS topexe toplib topmod testlib testlib_conflict RUNTIME DESTINATION bundle_executable/bin LIBRARY DESTINATION bundle_executable/lib)
+
+install(CODE [[
+  function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile)
+    file(GET_RUNTIME_DEPENDENCIES
+      RESOLVED_DEPENDENCIES_VAR deps
+      UNRESOLVED_DEPENDENCIES_VAR udeps
+      CONFLICTING_DEPENDENCIES_PREFIX cdeps
+      PRE_INCLUDE_REGEXES "^.*/lib(testlib|executable_path|executable_path_bundle|executable_path_postexcluded|loader_path|loader_path_unresolved|loader_path_postexcluded|rpath|rpath_unresolved|rpath_postexcluded|rpath_executable_path|rpath_executable_path_bundle|rpath_executable_path_postexcluded|rpath_loader_path|rpath_loader_path_unresolved|rpath_loader_path_postexcluded|normal|normal_unresolved|normal_postexcluded|conflict|System\\.B)\\.dylib$"
+      PRE_EXCLUDE_REGEXES ".*"
+      POST_INCLUDE_REGEXES "^.*/lib(testlib|executable_path|executable_path_bundle|loader_path|rpath|rpath_executable_path|rpath_executable_path_bundle|rpath_loader_path|normal|conflict|System\\.B)\\.dylib$"
+      POST_EXCLUDE_REGEXES ".*"
+      ${ARGN}
+      )
+    list(SORT deps)
+    list(SORT udeps)
+    list(SORT cdeps_FILENAMES)
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}")
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}")
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "")
+    foreach(cdep IN LISTS cdeps_FILENAMES)
+      set(cdep_values ${cdeps_${cdep}})
+      list(SORT cdep_values)
+      file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n")
+    endforeach()
+  endfunction()
+
+  exec_get_runtime_dependencies(
+    deps1.txt udeps1.txt cdeps1.txt
+    EXECUTABLES
+      "${CMAKE_INSTALL_PREFIX}/executable/bin/$<TARGET_FILE_NAME:topexe>"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps2.txt udeps2.txt cdeps2.txt
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:toplib>"
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps3.txt udeps3.txt cdeps3.txt
+    MODULES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:topmod>"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps4.txt udeps4.txt cdeps4.txt
+    EXECUTABLES
+      "${CMAKE_INSTALL_PREFIX}/executable/bin/$<TARGET_FILE_NAME:topexe>"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
+    BUNDLE_EXECUTABLE
+      "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps5.txt udeps5.txt cdeps5.txt
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:toplib>"
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
+    BUNDLE_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps6.txt udeps6.txt cdeps6.txt
+    MODULES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:topmod>"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
+    BUNDLE_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>"
+    )
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c
new file mode 100644
index 0000000..20c6087
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c
@@ -0,0 +1,7 @@
+extern void testlib(void);
+
+int main(void)
+{
+  testlib();
+  return 0;
+}
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c
new file mode 100644
index 0000000..cff1bff
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c
@@ -0,0 +1,6 @@
+extern void testlib(void);
+
+void toplib(void)
+{
+  testlib();
+}
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project-stderr.txt
new file mode 100644
index 0000000..d506645
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project-stderr.txt
@@ -0,0 +1,13 @@
+^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-project\.cmake:[0-9]+ \(file\):
+  You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\.  This is
+  probably not what you intended to do\.  Instead, please consider using it in
+  an install\(CODE\) or install\(SCRIPT\) command\.  For example:
+
+    install\(CODE \[\[
+      file\(GET_RUNTIME_DEPENDENCIES
+        # \.\.\.
+        \)
+      ]]\)
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project.cmake
new file mode 100644
index 0000000..842d7ab
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project.cmake
@@ -0,0 +1 @@
+file(GET_RUNTIME_DEPENDENCIES RESOLVED_DEPENDENCIES_VAR deps)
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-stderr.txt
new file mode 100644
index 0000000..3db835c
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at file-GET_RUNTIME_DEPENDENCIES-unsupported\.cmake:[0-9]+ \(file\):
+  file GET_RUNTIME_DEPENDENCIES is not supported on system "[^
+ ]+"
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported.cmake
new file mode 100644
index 0000000..b91eefe
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported.cmake
@@ -0,0 +1,2 @@
+file(GET_RUNTIME_DEPENDENCIES RESOLVED_DEPENDENCIES_VAR deps)
+message(FATAL_ERROR "This message should not be displayed")
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-all-check.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-all-check.cmake
new file mode 100644
index 0000000..c120ce4
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-all-check.cmake
@@ -0,0 +1,38 @@
+function(check_contents filename contents_regex)
+  if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
+    file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
+    if(NOT contents MATCHES "${contents_regex}")
+      string(APPEND RunCMake_TEST_FAILED "File contents:
+  ${contents}
+do not match what we expected:
+  ${contents_regex}
+in file:
+  ${CMAKE_INSTALL_PREFIX}/${filename}\n")
+      set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+    endif()
+  else()
+    string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
+    set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+  endif()
+endfunction()
+
+set(_check
+  [=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\.conflict/\.\./(lib)?libdir\.dll]=]
+  [=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\.search/(lib)?search\.dll]=]
+  [=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/(lib)?testlib\.dll]=]
+  )
+check_contents(deps/deps1.txt "^${_check}$")
+check_contents(deps/deps2.txt "^${_check}$")
+check_contents(deps/deps3.txt "^${_check}$")
+set(_check
+  [=[(lib)?unresolved\.dll]=]
+  )
+check_contents(deps/udeps1.txt "^${_check}$")
+check_contents(deps/udeps2.txt "^${_check}$")
+check_contents(deps/udeps3.txt "^${_check}$")
+set(_check
+  "^(lib)?conflict\\.dll:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\\.conflict/(lib)?conflict\\.dll;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/(lib)?conflict\\.dll\n$"
+  )
+check_contents(deps/cdeps1.txt "${_check}")
+check_contents(deps/cdeps2.txt "${_check}")
+check_contents(deps/cdeps3.txt "${_check}")
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-stderr.txt
new file mode 100644
index 0000000..66ecb93
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Multiple conflicting paths found for (lib)?path\.dll:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-build/root-all/lib/test1/(lib)?path\.dll
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-build/root-all/lib/test2/(lib)?path\.dll$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict.cmake
new file mode 100644
index 0000000..d413443
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict.cmake
@@ -0,0 +1,47 @@
+enable_language(C)
+
+set(test1_names path)
+set(test2_names path)
+
+file(WRITE "${CMAKE_BINARY_DIR}/path.c" "__declspec(dllexport) void path(void) {}\n")
+add_library(path SHARED "${CMAKE_BINARY_DIR}/path.c")
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test1.c")
+add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c")
+foreach(name ${test1_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "__declspec(dllimport) extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "__declspec(dllexport) void test1(void)\n{\n")
+foreach(name ${test1_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n")
+
+target_link_libraries(test1 PRIVATE ${test1_names})
+
+file(REMOVE "${CMAKE_BINARY_DIR}/test2.c")
+add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c")
+foreach(name ${test2_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "__declspec(dllimport) extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "__declspec(dllexport) void test2(void)\n{\n")
+foreach(name ${test2_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n")
+
+target_link_libraries(test2 PRIVATE ${test2_names})
+
+install(TARGETS test1 path DESTINATION lib/test1)
+install(TARGETS test2 path DESTINATION lib/test2)
+
+install(CODE [[
+  file(GET_RUNTIME_DEPENDENCIES
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/lib/test1/$<TARGET_FILE_NAME:test1>"
+      "${CMAKE_INSTALL_PREFIX}/lib/test2/$<TARGET_FILE_NAME:test2>"
+    PRE_INCLUDE_REGEXES "^(lib)?path\\.dll$"
+    PRE_EXCLUDE_REGEXES ".*"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-stderr.txt
new file mode 100644
index 0000000..f921409
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Failed to run (dumpbin|objdump) on:
+
+    [^
+]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-build/root-all/bin/(lib)?test\.dll$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile.cmake
new file mode 100644
index 0000000..6665a3b
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile.cmake
@@ -0,0 +1,28 @@
+enable_language(C)
+
+file(WRITE "${CMAKE_BINARY_DIR}/test.c" "__declspec(dllexport) void test(void) {}\n")
+file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[__declspec(dllimport) extern void test(void);
+
+int main(void)
+{
+  test();
+  return 0;
+}
+]])
+
+add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c")
+add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
+target_link_libraries(exe PRIVATE test)
+
+install(TARGETS exe DESTINATION bin)
+
+install(CODE [[
+  file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:test>")
+  file(GET_RUNTIME_DEPENDENCIES
+    EXECUTABLES
+      "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
+    PRE_INCLUDE_REGEXES "^(lib)?test\\.dll$"
+    PRE_EXCLUDE_REGEXES ".*"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-stderr.txt
new file mode 100644
index 0000000..a20654c
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
+  file Could not resolve file (lib)?unresolved\.dll$
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved.cmake
new file mode 100644
index 0000000..4cc74c7
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+
+file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllimport) extern void unresolved(void);\n__declspec(dllexport) void testlib(void)\n{\n  unresolved();\n}\n")
+add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
+file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "__declspec(dllexport) void unresolved(void) {}\n")
+add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c")
+target_link_libraries(testlib PRIVATE unresolved)
+install(TARGETS testlib DESTINATION lib)
+
+install(CODE [[
+  file(GET_RUNTIME_DEPENDENCIES
+    PRE_INCLUDE_REGEXES "^(lib)?unresolved\\.dll$"
+    PRE_EXCLUDE_REGEXES ".*"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>"
+    )
+  message(FATAL_ERROR "This message should not be displayed")
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows.cmake
new file mode 100644
index 0000000..19288d8
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows.cmake
@@ -0,0 +1,114 @@
+enable_language(C)
+
+set(testlib_names
+  preexcluded
+  libdir_postexcluded
+  libdir
+  search_postexcluded
+  search
+  unresolved
+  conflict
+  )
+
+file(REMOVE "${CMAKE_BINARY_DIR}/testlib.c")
+add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
+foreach(name ${testlib_names})
+  file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "__declspec(dllexport) void ${name}(void) {}\n")
+  add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
+
+  file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllimport) extern void ${name}(void);\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllexport) void testlib(void)\n{\n")
+foreach(name ${testlib_names})
+  file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "  ${name}();\n")
+endforeach()
+file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "}\n")
+
+target_link_libraries(testlib PRIVATE ${testlib_names})
+
+file(WRITE "${CMAKE_BINARY_DIR}/testlib_conflict.c" "__declspec(dllimport) extern void conflict(void);\n__declspec(dllexport) void testlib_conflict(void)\n{\n  conflict();\n}\n")
+add_library(testlib_conflict SHARED "${CMAKE_BINARY_DIR}/testlib_conflict.c")
+target_link_libraries(testlib_conflict PRIVATE conflict)
+
+file(WRITE "${CMAKE_BINARY_DIR}/testlib_noconflict.c" "__declspec(dllimport) extern void libdir(void);\n__declspec(dllexport) void testlib_noconflict(void)\n{\n  libdir();\n}\n")
+add_library(testlib_noconflict SHARED "${CMAKE_BINARY_DIR}/testlib_noconflict.c")
+target_link_libraries(testlib_noconflict PRIVATE libdir)
+
+install(TARGETS testlib libdir_postexcluded libdir conflict testlib_noconflict DESTINATION bin)
+install(TARGETS libdir search_postexcluded search DESTINATION bin/.search) # Prefixing with "." ensures it is the first item after list(SORT)
+install(TARGETS testlib_conflict conflict DESTINATION bin/.conflict)
+
+add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c)
+add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c)
+add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c)
+target_link_libraries(topexe PRIVATE testlib)
+target_link_libraries(toplib PRIVATE testlib)
+target_link_libraries(topmod PRIVATE testlib)
+
+install(TARGETS topexe toplib topmod DESTINATION bin)
+
+install(CODE [[
+  function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile)
+    file(GET_RUNTIME_DEPENDENCIES
+      RESOLVED_DEPENDENCIES_VAR deps
+      UNRESOLVED_DEPENDENCIES_VAR udeps
+      CONFLICTING_DEPENDENCIES_PREFIX cdeps
+      PRE_INCLUDE_REGEXES
+        "^(lib)?testlib\\.dll$"
+        "^(lib)?libdir_postexcluded\\.dll$"
+        "^(lib)?libdir\\.dll$"
+        "^(lib)?search_postexcluded\\.dll$"
+        "^(lib)?search\\.dll$"
+        "^(lib)?unresolved\\.dll$"
+        "^(lib)?conflict\\.dll$"
+        "^kernel32\\.dll$"
+      PRE_EXCLUDE_REGEXES ".*"
+      POST_INCLUDE_REGEXES
+        "^.*/(lib)?testlib\\.dll$"
+        "^.*/(lib)?libdir\\.dll$"
+        "^.*/(lib)?search\\.dll$"
+        "^.*/(lib)?conflict\\.dll$"
+      POST_EXCLUDE_REGEXES ".*"
+      DIRECTORIES
+        "${CMAKE_INSTALL_PREFIX}/bin/.search"
+      ${ARGN}
+      )
+    list(SORT deps)
+    list(SORT udeps)
+    list(SORT cdeps_FILENAMES)
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}")
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}")
+    file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "")
+    foreach(cdep IN LISTS cdeps_FILENAMES)
+      set(cdep_values ${cdeps_${cdep}})
+      list(SORT cdep_values)
+      file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n")
+    endforeach()
+  endfunction()
+
+  exec_get_runtime_dependencies(
+    deps1.txt udeps1.txt cdeps1.txt
+    EXECUTABLES
+      "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topexe>"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>"
+      "${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps2.txt udeps2.txt cdeps2.txt
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:toplib>"
+      "${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>"
+      "${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>"
+    )
+
+  exec_get_runtime_dependencies(
+    deps3.txt udeps3.txt cdeps3.txt
+    MODULES
+      "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topmod>"
+    LIBRARIES
+      "${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>"
+      "${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>"
+    )
+  ]])
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c
new file mode 100644
index 0000000..713b8eb
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c
@@ -0,0 +1,7 @@
+__declspec(dllimport) extern void testlib(void);
+
+int main(void)
+{
+  testlib();
+  return 0;
+}
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c
new file mode 100644
index 0000000..6997175
--- /dev/null
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c
@@ -0,0 +1,6 @@
+__declspec(dllimport) extern void testlib(void);
+
+__declspec(dllexport) void toplib(void)
+{
+  testlib();
+}
diff --git a/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt b/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt
index 9e73ed5..22226f2 100644
--- a/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt
+++ b/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt
@@ -1,5 +1,5 @@
 ^CMake Error at MATH-InvalidExpression.cmake:1 \(math\):
-  math cannot parse the expression: "INVALID": syntax error, unexpected \$end,
-  expecting exp_PLUS or exp_MINUS or exp_OPENPARENT or exp_NUMBER \(7\).
+  math cannot parse the expression: "INVALID": syntax error, unexpected \$end
+  \(7\).
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake
index cecfc7f..3c7e51c 100644
--- a/Tests/RunCMake/message/RunCMakeTest.cmake
+++ b/Tests/RunCMake/message/RunCMakeTest.cmake
@@ -52,3 +52,12 @@
     message-loglevel-trace
     ${CMAKE_COMMAND} --loglevel=trace -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
   )
+
+run_cmake_command(
+    message-indent
+    ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent.cmake
+  )
+run_cmake_command(
+    message-indent-multiline
+    ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent-multiline.cmake
+  )
diff --git a/Tests/RunCMake/message/message-indent-multiline-stderr.txt b/Tests/RunCMake/message/message-indent-multiline-stderr.txt
new file mode 100644
index 0000000..5853a31
--- /dev/null
+++ b/Tests/RunCMake/message/message-indent-multiline-stderr.txt
@@ -0,0 +1,3 @@
+ >This is
+ >the multiline
+ >message
diff --git a/Tests/RunCMake/message/message-indent-multiline-stdout.txt b/Tests/RunCMake/message/message-indent-multiline-stdout.txt
new file mode 100644
index 0000000..ae0c72e
--- /dev/null
+++ b/Tests/RunCMake/message/message-indent-multiline-stdout.txt
@@ -0,0 +1,8 @@
+--  >This is
+ >the multiline
+ >message
+ >
+ >
+--  >This is
+ >the multiline
+ >message
diff --git a/Tests/RunCMake/message/message-indent-multiline.cmake b/Tests/RunCMake/message/message-indent-multiline.cmake
new file mode 100644
index 0000000..0f789bf
--- /dev/null
+++ b/Tests/RunCMake/message/message-indent-multiline.cmake
@@ -0,0 +1,13 @@
+# NOTE Use non-space indent string, to check indentation
+# of line endings and "empty" lines.
+# ALERT Do not put any space characters after the non-space!
+list(APPEND CMAKE_MESSAGE_INDENT " >")
+set(msg [[This is
+the multiline
+message]]) # No `\n` at the end!
+# NOTE Two empty lines after the text
+message(STATUS "${msg}\n\n")
+message(STATUS "${msg}")
+# This is just to make sure NOTICE messages are also get indented:
+# https://gitlab.kitware.com/cmake/cmake/issues/19418#note_588011
+message(NOTICE "${msg}")
diff --git a/Tests/RunCMake/message/message-indent-stdout.txt b/Tests/RunCMake/message/message-indent-stdout.txt
new file mode 100644
index 0000000..b2c3c60
--- /dev/null
+++ b/Tests/RunCMake/message/message-indent-stdout.txt
@@ -0,0 +1,13 @@
+-- COUNTING:
+--    COUNTING_ENGLISH:
+--       one
+--       two
+--       three
+--       four
+--       five
+--    COUNTING_BAHASA:
+--       satu
+--       dua
+--       tiga
+--       empat
+--       lima
diff --git a/Tests/RunCMake/message/message-indent.cmake b/Tests/RunCMake/message/message-indent.cmake
new file mode 100644
index 0000000..c07ff45
--- /dev/null
+++ b/Tests/RunCMake/message/message-indent.cmake
@@ -0,0 +1,19 @@
+function(debug_list LIST_VAR)
+  message(STATUS "${LIST_VAR}:")
+  list(APPEND CMAKE_MESSAGE_INDENT "   ")
+  foreach(_item IN LISTS ${LIST_VAR})
+    list(LENGTH ${_item} _item_len)
+    if(_item_len GREATER 1)
+      debug_list(${_item})
+    else()
+      message(STATUS "${_item}")
+    endif()
+  endforeach()
+endfunction()
+
+list(APPEND COUNTING_ENGLISH one two three four five)
+list(APPEND COUNTING_BAHASA satu dua tiga empat lima)
+
+list(APPEND COUNTING COUNTING_ENGLISH COUNTING_BAHASA)
+
+debug_list(COUNTING)
diff --git a/Tests/RunCMake/project/CMP0048-NEW.cmake b/Tests/RunCMake/project/CMP0048-NEW.cmake
index 7e16b70..b6e80ac 100644
--- a/Tests/RunCMake/project/CMP0048-NEW.cmake
+++ b/Tests/RunCMake/project/CMP0048-NEW.cmake
@@ -1,9 +1,4 @@
-macro(print_versions name)
-  foreach(v "" _MAJOR _MINOR _PATCH _TWEAK)
-    message(STATUS "PROJECT_VERSION${v}='${PROJECT_VERSION${v}}'")
-    message(STATUS "${name}_VERSION${v}='${${name}_VERSION${v}}'")
-  endforeach()
-endmacro()
+include(PrintVersions.cmake)
 
 cmake_policy(SET CMP0048 NEW)
 
diff --git a/Tests/RunCMake/project/CMP0096-NEW-stdout.txt b/Tests/RunCMake/project/CMP0096-NEW-stdout.txt
new file mode 100644
index 0000000..f6b999a
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0096-NEW-stdout.txt
@@ -0,0 +1,30 @@
+-- PROJECT_VERSION='2019.07.06'
+-- DateVersion_VERSION='2019.07.06'
+-- PROJECT_VERSION_MAJOR='2019'
+-- DateVersion_VERSION_MAJOR='2019'
+-- PROJECT_VERSION_MINOR='07'
+-- DateVersion_VERSION_MINOR='07'
+-- PROJECT_VERSION_PATCH='06'
+-- DateVersion_VERSION_PATCH='06'
+-- PROJECT_VERSION_TWEAK=''
+-- DateVersion_VERSION_TWEAK=''
+-- PROJECT_VERSION='4294967297'
+-- LongVersion_VERSION='4294967297'
+-- PROJECT_VERSION_MAJOR='4294967297'
+-- LongVersion_VERSION_MAJOR='4294967297'
+-- PROJECT_VERSION_MINOR=''
+-- LongVersion_VERSION_MINOR=''
+-- PROJECT_VERSION_PATCH=''
+-- LongVersion_VERSION_PATCH=''
+-- PROJECT_VERSION_TWEAK=''
+-- LongVersion_VERSION_TWEAK=''
+-- PROJECT_VERSION='0009999999999.0009999999999.0009999999999.0009999999999'
+-- VeryLongVersion_VERSION='0009999999999.0009999999999.0009999999999.0009999999999'
+-- PROJECT_VERSION_MAJOR='0009999999999'
+-- VeryLongVersion_VERSION_MAJOR='0009999999999'
+-- PROJECT_VERSION_MINOR='0009999999999'
+-- VeryLongVersion_VERSION_MINOR='0009999999999'
+-- PROJECT_VERSION_PATCH='0009999999999'
+-- VeryLongVersion_VERSION_PATCH='0009999999999'
+-- PROJECT_VERSION_TWEAK='0009999999999'
+-- VeryLongVersion_VERSION_TWEAK='0009999999999'
diff --git a/Tests/RunCMake/project/CMP0096-NEW.cmake b/Tests/RunCMake/project/CMP0096-NEW.cmake
new file mode 100644
index 0000000..e2cdd20
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0096-NEW.cmake
@@ -0,0 +1,6 @@
+cmake_policy(SET CMP0048 NEW)
+cmake_policy(SET CMP0096 NEW)
+include(CMP0096-common.cmake)
+
+project(VeryLongVersion VERSION 0009999999999.0009999999999.0009999999999.0009999999999 LANGUAGES NONE)
+print_versions(VeryLongVersion)
diff --git a/Tests/RunCMake/project/CMP0096-OLD-stdout.txt b/Tests/RunCMake/project/CMP0096-OLD-stdout.txt
new file mode 100644
index 0000000..6a945ce
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0096-OLD-stdout.txt
@@ -0,0 +1,20 @@
+-- PROJECT_VERSION='2019.7.6'
+-- DateVersion_VERSION='2019.7.6'
+-- PROJECT_VERSION_MAJOR='2019'
+-- DateVersion_VERSION_MAJOR='2019'
+-- PROJECT_VERSION_MINOR='7'
+-- DateVersion_VERSION_MINOR='7'
+-- PROJECT_VERSION_PATCH='6'
+-- DateVersion_VERSION_PATCH='6'
+-- PROJECT_VERSION_TWEAK=''
+-- DateVersion_VERSION_TWEAK=''
+-- PROJECT_VERSION='(1|4294967295)'
+-- LongVersion_VERSION='(1|4294967295)'
+-- PROJECT_VERSION_MAJOR='(1|4294967295)'
+-- LongVersion_VERSION_MAJOR='(1|4294967295)'
+-- PROJECT_VERSION_MINOR=''
+-- LongVersion_VERSION_MINOR=''
+-- PROJECT_VERSION_PATCH=''
+-- LongVersion_VERSION_PATCH=''
+-- PROJECT_VERSION_TWEAK=''
+-- LongVersion_VERSION_TWEAK=''
diff --git a/Tests/RunCMake/project/CMP0096-OLD.cmake b/Tests/RunCMake/project/CMP0096-OLD.cmake
new file mode 100644
index 0000000..25a3b19
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0096-OLD.cmake
@@ -0,0 +1,3 @@
+cmake_policy(SET CMP0048 NEW)
+cmake_policy(SET CMP0096 OLD)
+include(CMP0096-common.cmake)
diff --git a/Tests/RunCMake/project/CMP0096-WARN-stdout.txt b/Tests/RunCMake/project/CMP0096-WARN-stdout.txt
new file mode 100644
index 0000000..6a945ce
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0096-WARN-stdout.txt
@@ -0,0 +1,20 @@
+-- PROJECT_VERSION='2019.7.6'
+-- DateVersion_VERSION='2019.7.6'
+-- PROJECT_VERSION_MAJOR='2019'
+-- DateVersion_VERSION_MAJOR='2019'
+-- PROJECT_VERSION_MINOR='7'
+-- DateVersion_VERSION_MINOR='7'
+-- PROJECT_VERSION_PATCH='6'
+-- DateVersion_VERSION_PATCH='6'
+-- PROJECT_VERSION_TWEAK=''
+-- DateVersion_VERSION_TWEAK=''
+-- PROJECT_VERSION='(1|4294967295)'
+-- LongVersion_VERSION='(1|4294967295)'
+-- PROJECT_VERSION_MAJOR='(1|4294967295)'
+-- LongVersion_VERSION_MAJOR='(1|4294967295)'
+-- PROJECT_VERSION_MINOR=''
+-- LongVersion_VERSION_MINOR=''
+-- PROJECT_VERSION_PATCH=''
+-- LongVersion_VERSION_PATCH=''
+-- PROJECT_VERSION_TWEAK=''
+-- LongVersion_VERSION_TWEAK=''
diff --git a/Tests/RunCMake/project/CMP0096-WARN.cmake b/Tests/RunCMake/project/CMP0096-WARN.cmake
new file mode 100644
index 0000000..7fe0861
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0096-WARN.cmake
@@ -0,0 +1,3 @@
+cmake_policy(SET CMP0048 NEW)
+
+include(CMP0096-common.cmake)
diff --git a/Tests/RunCMake/project/CMP0096-common.cmake b/Tests/RunCMake/project/CMP0096-common.cmake
new file mode 100644
index 0000000..8d26d30
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0096-common.cmake
@@ -0,0 +1,9 @@
+include(PrintVersions.cmake)
+
+# Test leading zeros motivating this policy.
+project(DateVersion VERSION 2019.07.06 LANGUAGES NONE)
+print_versions(DateVersion)
+
+# Overflow version component in OLD behavior.
+project(LongVersion VERSION 4294967297 #[[ uint32_max + 2 ]] LANGUAGES NONE)
+print_versions(LongVersion)
diff --git a/Tests/RunCMake/project/PrintVersions.cmake b/Tests/RunCMake/project/PrintVersions.cmake
new file mode 100644
index 0000000..ce1b25d
--- /dev/null
+++ b/Tests/RunCMake/project/PrintVersions.cmake
@@ -0,0 +1,6 @@
+macro(print_versions name)
+  foreach(v "" _MAJOR _MINOR _PATCH _TWEAK)
+    message(STATUS "PROJECT_VERSION${v}='${PROJECT_VERSION${v}}'")
+    message(STATUS "${name}_VERSION${v}='${${name}_VERSION${v}}'")
+  endforeach()
+endmacro()
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index 3a8ad4b..8f43a51 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -27,3 +27,7 @@
 run_cmake(CMP0048-OLD-VERSION)
 run_cmake(CMP0048-WARN)
 run_cmake(CMP0048-NEW)
+
+run_cmake(CMP0096-WARN)
+run_cmake(CMP0096-OLD)
+run_cmake(CMP0096-NEW)
diff --git a/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake
index b67c598..a419cc9 100644
--- a/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake
@@ -1,3 +1,4 @@
 include(RunCMake)
 
 run_cmake(empty_keyword_args)
+run_cmake(unknown_imported_target)
diff --git a/Tests/RunCMake/target_compile_definitions/unknown_imported_target.cmake b/Tests/RunCMake/target_compile_definitions/unknown_imported_target.cmake
new file mode 100644
index 0000000..4ae1c0d
--- /dev/null
+++ b/Tests/RunCMake/target_compile_definitions/unknown_imported_target.cmake
@@ -0,0 +1,11 @@
+# Test that target_compile_definitions works on UNKNOWN IMPORTED target
+add_library(imported UNKNOWN IMPORTED)
+target_compile_definitions(imported INTERFACE FOO)
+
+get_target_property(IMPORTED_INTERFACE_CDS imported INTERFACE_COMPILE_DEFINITIONS)
+
+if (NOT FOO IN_LIST IMPORTED_INTERFACE_CDS)
+  message(
+    FATAL_ERROR "FOO should be in INTERFACE_COMPILE_DEFINITIONS.\n"
+    "Actual INTERFACE_COMPILE_DEFINITIONS: " ${IMPORTED_INTERFACE_CDS})
+endif()
diff --git a/Tests/RunCMake/try_compile/CMP0067-stderr.txt b/Tests/RunCMake/try_compile/CMP0067-stderr.txt
index e2677ed..d955dda 100644
--- a/Tests/RunCMake/try_compile/CMP0067-stderr.txt
+++ b/Tests/RunCMake/try_compile/CMP0067-stderr.txt
@@ -19,6 +19,17 @@
 This warning is for project developers.  Use -Wno-dev to suppress it.
 
 after try_compile with CMP0067 WARN-enabled
+CMake Deprecation Warning at CMP0067.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0067 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
 before try_compile with CMP0067 OLD
 after try_compile with CMP0067 OLD
 before try_compile with CMP0067 NEW
diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt
index e5f8588..f4cbac2 100644
--- a/Tests/SwiftOnly/CMakeLists.txt
+++ b/Tests/SwiftOnly/CMakeLists.txt
@@ -8,3 +8,6 @@
 endif()
 
 add_executable(SwiftOnly main.swift)
+
+# Dummy to make sure generation works with such targets.
+add_library(SwiftIface INTERFACE)
diff --git a/Tests/Tutorial/Consumer/directions.txt b/Tests/Tutorial/Consumer/directions.txt
deleted file mode 100644
index 6a70aab..0000000
--- a/Tests/Tutorial/Consumer/directions.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# Import a CMake Project#
-
-This examples shows how a project can find other CMake packages that
-generated Config.cmake files.
-
-It also shows how to state a projects external dependencies when generating a Config.cmake.
diff --git a/Tests/Tutorial/MultiPackage/CMakeLists.txt b/Tests/Tutorial/MultiPackage/CMakeLists.txt
deleted file mode 100644
index 067e807..0000000
--- a/Tests/Tutorial/MultiPackage/CMakeLists.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-cmake_minimum_required(VERSION 3.3)
-project(Tutorial)
-
-# control how we mark up Debug libraries compared to Release libraries
-set(CMAKE_DEBUG_POSTFIX "-d")
-
-# control where the static and shared libraries are built so that on windows
-# we don't need to tinker with the path to run the executable
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-
-option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
-
-# the version number.
-set(Tutorial_VERSION_MAJOR 1)
-set(Tutorial_VERSION_MINOR 0)
-
-# configure a header file to pass the version number only
-configure_file(
-  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
-  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  )
-
-# add the MathFunctions library
-add_subdirectory(MathFunctions)
-
-# add the executable
-add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial MathFunctions)
-
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-target_include_directories(Tutorial PUBLIC
-                           "${PROJECT_BINARY_DIR}"
-                           )
-
-# add the install targets
-install(TARGETS Tutorial DESTINATION bin)
-install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  DESTINATION include
-  )
-
-# enable testing
-enable_testing()
-
-# does the application run
-add_test(NAME Runs COMMAND Tutorial 25)
-
-# does the usage message work?
-add_test(NAME Usage COMMAND Tutorial)
-set_tests_properties(Usage
-  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
-  )
-
-# define a function to simplify adding tests
-function(do_test target arg result)
-  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
-  set_tests_properties(Comp${arg}
-    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
-    )
-endfunction(do_test)
-
-# do a bunch of result based tests
-do_test(Tutorial 4 "4 is 2")
-do_test(Tutorial 9 "9 is 3")
-do_test(Tutorial 5 "5 is 2.236")
-do_test(Tutorial 7 "7 is 2.645")
-do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
-do_test(Tutorial 0.0001 "0.0001 is 0.01")
-
-include(InstallRequiredSystemLibraries)
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-include(CPack)
-
-# install the configuration targets
-install(EXPORT MathFunctionsTargets
-  FILE MathFunctionsTargets.cmake
-  DESTINATION lib/cmake/MathFunctions
-)
-
-include(CMakePackageConfigHelpers)
-# generate the config file that is includes the exports
-configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
-  "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
-  INSTALL_DESTINATION "lib/cmake/example"
-  NO_SET_AND_CHECK_MACRO
-  NO_CHECK_REQUIRED_COMPONENTS_MACRO
-  )
-# generate the version file for the config file
-write_basic_package_version_file(
-  "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
-  VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
-  COMPATIBILITY AnyNewerVersion
-)
-
-# install the configuration file
-install(FILES
-  ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
-  DESTINATION lib/cmake/MathFunctions
-  )
-
-# generate the export targets for the build tree
-# needs to be after the install(TARGETS ) command
-export(EXPORT MathFunctionsTargets
-  FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
-)
diff --git a/Tests/Tutorial/MultiPackage/directions.txt b/Tests/Tutorial/MultiPackage/directions.txt
deleted file mode 100644
index c3102bb..0000000
--- a/Tests/Tutorial/MultiPackage/directions.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-# Packaging Debug and Release #
-
-By default CMake is model is that a build directory only contains a single
-configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo.
-
-But it is possible to setup CPack to bundle multiple build directories at the same
-time to build a package that contains multiple configurations of the same project.
-
-First we need to ahead and construct a directory called 'multi_config' this
-will contain all the builds that we want to package together.
-
-Second create a 'debug' and 'release' directory underneath 'multi_config'. At
-the end you should have a layout that looks like:
-
-─ multi_config
-    ├── debug
-    └── release
-
-Now we need to setup debug and release builds, which would roughly entail
-the following:
-
-  cd debug
-  cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/
-  cmake --build .
-  cd ../release
-  cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/
-  cmake --build .
-  cd ..
-
-
-Now that both the debug and release builds are complete we can now use
-the custom MultiCPackConfig to package both builds into a single release.
-
-  cpack --config ../../MultiPackage/MultiCPackConfig.cmake
diff --git a/Tests/Tutorial/MultiPackage/tutorial.cxx b/Tests/Tutorial/MultiPackage/tutorial.cxx
deleted file mode 100644
index 443d195..0000000
--- a/Tests/Tutorial/MultiPackage/tutorial.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// A simple program that computes the square root of a number
-#include <iostream>
-#include <sstream>
-#include <string>
-
-#include "MathFunctions.h"
-#include "TutorialConfig.h"
-
-int main(int argc, char* argv[])
-{
-  if (argc < 2) {
-    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
-    std::cout << "Usage: " << argv[0] << " number" << std::endl;
-    return 1;
-  }
-
-  double inputValue = std::stod(argv[1]);
-
-  const double outputValue = mathfunctions::sqrt(inputValue);
-
-  std::cout << "The square root of " << inputValue << " is " << outputValue
-            << std::endl;
-  return 0;
-}
diff --git a/Tests/Tutorial/Readme.txt b/Tests/Tutorial/Readme.txt
deleted file mode 100644
index 74eb01a..0000000
--- a/Tests/Tutorial/Readme.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-
-Step 0: A Starting Point
-Step 1: Configure a File and C++11 Controls
-Step 2: Adding a Library
-Step 3: Usage Requirements for Library
-Step 4: Installing and Testing
-Step 5: System Introspection
-Step 6: Custom Command and Generated File
-Step 7: Building an Installer
-Step 8: CDash submission
-Step 9: Mixing Static and Shared
-Step 10: Generator Expressions
-Step 11: Adding Export Configuration
-Complete: End result of Step 11
-Consumer: Example of Import Packages
-MultiPackage: How to package Debug and Release versions
diff --git a/Tests/Tutorial/Step1/directions.txt b/Tests/Tutorial/Step1/directions.txt
deleted file mode 100644
index 827d775..0000000
--- a/Tests/Tutorial/Step1/directions.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-# Adding a Version Number and Configured Header File #
-
-The first feature we will add is to provide our executable and project with a
-version number. While we could do this exclusively in the source code, using
-CMakeLists provides more flexibility.
-
-To add a version number we modify the CMakeLists file as follows:
-
-  cmake_minimum_required(VERSION 3.3)
-  project(Tutorial)
-
-  # the version number.
-  set(Tutorial_VERSION_MAJOR 1)
-  set(Tutorial_VERSION_MINOR 0)
-
-  # configure a header file to pass some of the CMake settings
-  # to the source code
-  configure_file(
-    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
-    "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-    )
-
-  # add the executable
-  add_executable(Tutorial tutorial.cxx)
-
-  # add the binary tree to the search path for include files
-  # so that we will find TutorialConfig.h
-  target_include_directories(Tutorial PUBLIC
-                             "${PROJECT_BINARY_DIR}"
-                             )
-
-
-We then create a TutorialConfig.h.in file in the source tree with the
-following contents:
-
-  // the configured options and settings for Tutorial
-  #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
-  #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-
-When CMake configures this header file the values for @Tutorial_VERSION_MAJOR@
-and @Tutorial_VERSION_MINOR@ will be replaced by the values from the CMakeLists
-file. Next we modify tutorial.cxx to include the configured header file and to
-make use of the version numbers. The resulting source code is listed below.
-
-  // A simple program that computes the square root of a number
-  #include <cmath>
-  #include <iostream>
-  #include <string>
-  #include <sstream>
-
-  #include "TutorialConfig.h"
-
-  int main (int argc, char *argv[])
-  {
-    if (argc < 2) {
-      std::cout << argv[0] << " Version "
-                << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR
-                << std::endl;
-      std::cout << "Usage: " << argv[0] << " number" << std::endl;
-      return 1;
-    }
-
-    double inputValue = atof(argv[1]);
-
-    double outputValue = sqrt(inputValue);
-    std::cout << "The square root of "
-              << inputValue << " is " << outputValue << std::endl;
-    return 0;
-  }
-
-# Adding C++11 support #
-
-Let's add some C++11 features to our project. We will need to explicitly state
-in the CMake code that it should use the correct flags. The easiest way to
-enable C++11 support for CMake is by using the CMAKE_CXX_STANDARD
-and CMAKE_CXX_STANDARD_REQUIRED variables.
-
-First, replace `atof` with `std::stod` in tutorial.cxx.
-
-Then, add the CMAKE_CXX_STANDARD and CMAKE_CXX_STANDARD_REQUIRED variables to
-the CMakeLists file. The STANADARD value should be set to 11, and REQUIRED
-should be set to True.
-
-
-# Build and Test #
-
-Run cmake or cmake-gui to configure the project and then build it with your
-chosen build tool
-
-cd to the directory where Tutorial was built (likely the make directory or
-a Debug or Release build configuration subdirectory) and run these commands:
-
-  Tutorial 4294967296
-  Tutorial 10
-  Tutorial
diff --git a/Tests/Tutorial/Step10/directions.txt b/Tests/Tutorial/Step10/directions.txt
deleted file mode 100644
index 5317b54..0000000
--- a/Tests/Tutorial/Step10/directions.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-# Adding Generator Expressions #
-
-Generator expressions are evaluated during build system generation to produce
-information specific to each build configuration.
-
-Generator expressions are allowed in the context of many target properties, such
-as LINK_LIBRARIES, INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS and others. They may
-also be used when using commands to populate those properties, such as
-target_link_libraries(), target_include_directories(),
-target_compile_definitions() and others.
-
-Generator expressions may to used to enable conditional linking, conditional
-definitions used when compiling, and conditional include directories and more.
-The conditions may be based on the build configuration, target properties,
-platform information or any other queryable information.
-
-There are different types of generator expressions including Logical,
-Informational, and Output expressions.
-
-Logical expressions are used to create conditional output. The basic expressions
-are the 0 and 1 expressions. A "$<0:...>" results in the empty string, and
-"$<1:...>" results in the content of "...".  They can also be nested.
-For example:
-
-  if(HAVE_LOG AND HAVE_EXP)
-    target_compile_definitions(SqrtLibrary
-                               PRIVATE "HAVE_LOG" "HAVE_EXP")
-  endif()
-
-Can be rewritten with generator expressions:
-
-  target_compile_definitions(SqrtLibrary PRIVATE
-                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
-                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
-                            )
-
-Note that "${HAVE_LOG}" is evaluated at CMake configure time while
-"$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>" is evaluated at build system generation time.
diff --git a/Tests/Tutorial/Step10/tutorial.cxx b/Tests/Tutorial/Step10/tutorial.cxx
deleted file mode 100644
index 443d195..0000000
--- a/Tests/Tutorial/Step10/tutorial.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// A simple program that computes the square root of a number
-#include <iostream>
-#include <sstream>
-#include <string>
-
-#include "MathFunctions.h"
-#include "TutorialConfig.h"
-
-int main(int argc, char* argv[])
-{
-  if (argc < 2) {
-    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
-    std::cout << "Usage: " << argv[0] << " number" << std::endl;
-    return 1;
-  }
-
-  double inputValue = std::stod(argv[1]);
-
-  const double outputValue = mathfunctions::sqrt(inputValue);
-
-  std::cout << "The square root of " << inputValue << " is " << outputValue
-            << std::endl;
-  return 0;
-}
diff --git a/Tests/Tutorial/Step11/CMakeLists.txt b/Tests/Tutorial/Step11/CMakeLists.txt
deleted file mode 100644
index b1d46c4..0000000
--- a/Tests/Tutorial/Step11/CMakeLists.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-cmake_minimum_required(VERSION 3.3)
-project(Tutorial)
-
-# control where the static and shared libraries are built so that on windows
-# we don't need to tinker with the path to run the executable
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-
-option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
-
-# the version number.
-set(Tutorial_VERSION_MAJOR 1)
-set(Tutorial_VERSION_MINOR 0)
-
-# configure a header file to pass the version number only
-configure_file(
-  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
-  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  )
-
-# add the MathFunctions library
-add_subdirectory(MathFunctions)
-
-# add the executable
-add_executable(Tutorial tutorial.cxx)
-target_link_libraries(Tutorial MathFunctions)
-
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-target_include_directories(Tutorial PUBLIC
-                           "${PROJECT_BINARY_DIR}"
-                           )
-
-# add the install targets
-install(TARGETS Tutorial DESTINATION bin)
-install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  DESTINATION include
-  )
-
-# enable testing
-enable_testing()
-
-# does the application run
-add_test(NAME Runs COMMAND Tutorial 25)
-
-# does the usage message work?
-add_test(NAME Usage COMMAND Tutorial)
-set_tests_properties(Usage
-  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
-  )
-
-# define a function to simplify adding tests
-function(do_test target arg result)
-  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
-  set_tests_properties(Comp${arg}
-    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
-    )
-endfunction(do_test)
-
-# do a bunch of result based tests
-do_test(Tutorial 4 "4 is 2")
-do_test(Tutorial 9 "9 is 3")
-do_test(Tutorial 5 "5 is 2.236")
-do_test(Tutorial 7 "7 is 2.645")
-do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
-do_test(Tutorial 0.0001 "0.0001 is 0.01")
-
-include(InstallRequiredSystemLibraries)
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-include(CPack)
diff --git a/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt
deleted file mode 100644
index 760d6a5..0000000
--- a/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-
-# add the library that runs
-add_library(MathFunctions MathFunctions.cxx)
-
-# state that anybody linking to us needs to include the current source dir
-# to find MathFunctions.h, while we don't.
-target_include_directories(MathFunctions
-                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
-                           )
-
-# should we use our own math functions
-option(USE_MYMATH "Use tutorial provided math implementation" ON)
-if(USE_MYMATH)
-
-  # does this system provide the log and exp functions?
-  include(CheckSymbolExists)
-  set(CMAKE_REQUIRED_LIBRARIES "m")
-  check_symbol_exists(log "math.h" HAVE_LOG)
-  check_symbol_exists(exp "math.h" HAVE_EXP)
-
-  # first we add the executable that generates the table
-  add_executable(MakeTable MakeTable.cxx)
-
-  # add the command to generate the source code
-  add_custom_command(
-    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-    DEPENDS MakeTable
-    )
-
-  # library that just does sqrt
-  add_library(SqrtLibrary STATIC
-              mysqrt.cxx
-              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-              )
-
-  # state that we depend on our binary dir to find Table.h
-  target_include_directories(SqrtLibrary PRIVATE
-                             ${CMAKE_CURRENT_BINARY_DIR}
-                             )
-
-  set_target_properties(SqrtLibrary PROPERTIES
-                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
-                        )
-
-  target_compile_definitions(SqrtLibrary PRIVATE
-                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
-                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
-                             )
-  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
-endif()
-
-target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
-
-# define the symbol stating we are using the declspec(dllexport) when
-#building on windows
-target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
-
-install(TARGETS MathFunctions DESTINATION lib)
-install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step11/directions.txt b/Tests/Tutorial/Step11/directions.txt
deleted file mode 100644
index ebb5def..0000000
--- a/Tests/Tutorial/Step11/directions.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-# Adding Export Configuration #
-
-During Step 4 of the tutorial we added the ability for CMake to install the
-library and headers of the project. During Step 7 we added the ability
-to package up this information so it could be distributed to other people.
-
-The next step is to add the necessary information so that other CMake projects
-can use our project, be it from a build directory, a local install or when
-packaged.
-
-The first step is to update our install(TARGETS) commands to not only specify
-a DESTINATION but also an EXPORT. The EXPORT keyword generates and installs a
-CMake file containing code to import all targets listed in the install command
-from the installation tree. So let's go ahead and explicitly EXPORT the
-MathFunctions library by updating the install command in
-MathFunctions/CMakeLists.txt to look like:
-
-  install(TARGETS MathFunctions DESTINATION lib EXPORT MathFunctionsTargets)
-
-Now that we have MathFunctions being exported, we also need to explicitly install
-the generated MathFunctionsTargets.cmake file. This is done by adding
-the following to the bottom of the top-level CMakeLists.txt:
-
-  # install the configuration targets
-  install(EXPORT MathFunctionsTargets
-    FILE MathFunctionsTargets.cmake
-    DESTINATION lib/cmake/MathFunctions
-  )
-
-At this point you should try and run CMake. If everything is setup properly
-you will see that CMake will generate an error that looks like:
-
-  Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
-  path:
-
-    "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
-
-  which is prefixed in the source directory.
-
-What CMake is trying to say is that during generating the export information
-it will export a path that is intrinsically tied to the current machine and
-will not be valid on other machines. The solution to this is to update the
-MathFunctions target_include_directories to understand that it needs different
-INTERFACE locations when being used from within the build directory and from an
-install / package. This means converting the target_include_directories
-call for MathFunctions to look like:
-
-  target_include_directories(MathFunctions
-                             INTERFACE
-                              $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
-                              $<INSTALL_INTERFACE:include>
-                             )
-
-Once this has been updated, we can re-run CMake and see verify that it doesn't
-warn anymore.
-
-At this point, we have CMake properly packaging the target information that is
-required but we will still need to generate a MathFunctionsConfig.cmake, so
-that the CMake find_package command can find our project. So let's go ahead and
-add a new file to the top-level of the project called Config.cmake.in with the
-following contents:
-
-  @PACKAGE_INIT@
-
-  include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )
-
-Then, to properly configure and install that file, add the following to the
-bottom of the top-level CMakeLists:
-
-  include(CMakePackageConfigHelpers)
-  # generate the config file that is includes the exports
-  configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
-    "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
-    INSTALL_DESTINATION "lib/cmake/example"
-    NO_SET_AND_CHECK_MACRO
-    NO_CHECK_REQUIRED_COMPONENTS_MACRO
-    )
-  # generate the version file for the config file
-  write_basic_package_version_file(
-    "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
-    VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
-    COMPATIBILITY AnyNewerVersion
-  )
-
-  # install the configuration file
-  install(FILES
-    ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
-    DESTINATION lib/cmake/MathFunctions
-    )
-
-At this point, we have generated a relocatable CMake Configuration for our project
-that can be used after the project has been installed or packaged. If we want
-our project to also be used from a build directory we only have to add
-the following to the bottom of the top level CMakeLists:
-
-  # generate the export targets for the build tree
-  # needs to be after the install(TARGETS ) command
-  export(EXPORT MathFunctionsTargets
-    FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
-  )
-
-With this export call we now generate a Targets.cmake, allowing the configured
-MathFunctionsConfig.cmake in the build directory to be used by other projects,
-without needing it to be installed.
diff --git a/Tests/Tutorial/Step2/directions.txt b/Tests/Tutorial/Step2/directions.txt
deleted file mode 100644
index bb6662c..0000000
--- a/Tests/Tutorial/Step2/directions.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-# Adding a Library #
-
-Now we will add a library to our project. This library will contain our own
-implementation for computing the square root of a number. The executable can
-then use this library instead of the standard square root function provided by
-the compiler.
-
-For this tutorial we will put the library into a subdirectory
-called MathFunctions. It will have the following one line CMakeLists file:
-
-  add_library(MathFunctions mysqrt.cxx)
-
-The source file mysqrt.cxx has one function called mysqrt that provides similar
-functionality to the compiler’s sqrt function. To make use of the new library
-we add an add_subdirectory call in the top-level CMakeLists file so that the
-library will get built. We add the new library to the executable, and add the
-MathFunctions as an include directory so that mqsqrt.h header file can be
-found. The last few lines of the top-level CMakeLists file now look like:
-
-
-  add_subdirectory(MathFunctions)
-
-  #add the executable
-  add_executable(Tutorial tutorial.cxx)
-
-  target_link_libraries(Tutorial ${EXTRA_LIBS})
-
-
-Now let us make the MathFunctions library optional. While for the tutorial
-there really isn’t any need to do so, but with larger projects this is a common
-occurrence. The first step is to add an option to the top-level CMakeLists file.
-
-  option (USE_MYMATH
-          "Use tutorial provided math implementation" ON)
-
-This will show up in CMake GUI and ccmake with a default value of ON that can
-be changed by the user. This setting will be stored so that the user does not
-need to set the value each time they run CMake on this build directory.
-
-The next change is to make building and linking the MathFunctions library
-conditional. To do this we change the top-level CMakeLists file to look like
-the following:
-
-  cmake_minimum_required(VERSION 3.3)
-  project(Tutorial)
-
-  set(CMAKE_CXX_STANDARD 11)
-  set(CMAKE_CXX_STANDARD_REQUIRED True)
-
-  # the version number.
-  set(Tutorial_VERSION_MAJOR 1)
-  set(Tutorial_VERSION_MINOR 0)
-
-  # configure a header file to pass some of the CMake settings
-  # to the source code
-  configure_file(
-    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
-    "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-    )
-
-  # should we use our own math functions
-  option(USE_MYMATH "Use tutorial provided math implementation" ON)
-
-  # add the MathFunctions library?
-  if(USE_MYMATH)
-    add_subdirectory(MathFunctions)
-    list(APPEND EXTRA_LIBS MathFunctions)
-    list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
-  endif(USE_MYMATH)
-
-  # add the executable
-  add_executable(Tutorial tutorial.cxx)
-
-  target_link_libraries(Tutorial ${EXTRA_LIBS})
-
-  # add the binary tree to the search path for include files
-  # so that we will find TutorialConfig.h
-  target_include_directories(Tutorial PUBLIC
-                             "${PROJECT_BINARY_DIR}"
-                             ${EXTRA_INCLUDES}
-                             )
-
-Note the use of the variables EXTRA_LIBS, and EXTRA_INCLUDES to collect
-up any optional libraries to later be linked into the executable. This is a
-classic approach when dealing with many optional components, we will cover the
-modern approach in the next step. For now the corresponding changes to the
-source code are fairly straightforward and leave us with:
-
-  #ifdef USE_MYMATH
-    double outputValue = mysqrt(inputValue);
-  #else
-    double outputValue = sqrt(inputValue);
-  #endif
-
-Since the source code now requires USE_MYMATH we can add it to the
-TutorialConfig.h.in. Simply add the following line:
-  #cmakedefine USE_MYMATH
-
-Run cmake or cmake-gui to configure the project and then build it with your
-chosen build tool and then run the built Tutorial executable.
-
-Which function gives better results, Step1’s sqrt or Step2’s mysqrt?
diff --git a/Tests/Tutorial/Step3/directions.txt b/Tests/Tutorial/Step3/directions.txt
deleted file mode 100644
index 54d0318..0000000
--- a/Tests/Tutorial/Step3/directions.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-# Adding Usage Requirements for Library #
-
-Usage requirements allow for far better control over a library / executable's
-link and include line. While also giving more control over the transitive
-property of targets inside CMake. The primary commands that leverage usage
-requirements are:
-
-  - target_compile_definitions
-  - target_compile_options
-  - target_include_directories
-  - target_link_libraries
-
-First up is MathFunctions. We first state that anybody linking to MathFunctions
-needs to include the current source directory, while MathFunctions itself
-doesn't. So this can become an INTERFACE usage requirement.
-
-Remember INTERFACE means things that consumers require but the producer doesn't.
-
-  target_include_directories(MathFunctions
-            INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
-
-Now that we've specified usage requirements for MathFunctions we can safely remove
-our uses of the EXTRA_INCLUDES variable.
-
-Run cmake or cmake-gui to configure the project and then build it with your
-chosen build tool.
diff --git a/Tests/Tutorial/Step4/directions.txt b/Tests/Tutorial/Step4/directions.txt
deleted file mode 100644
index 91e4043..0000000
--- a/Tests/Tutorial/Step4/directions.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-# Installing and Testing #
-
-Now we can start adding testing support and install rules to our project.
-
-The install rules are fairly simple; for MathFunctions we install the library
-and header file, for the application we install the executable and configured
-header.
-
-So to MathFunctions/CMakeLists.txt we add:
-
-  install (TARGETS MathFunctions DESTINATION bin)
-  install (FILES MathFunctions.h DESTINATION include)
-
-And the to top-level CMakeLists.txt we add:
-
-  install(TARGETS Tutorial DESTINATION bin)
-  install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-          DESTINATION include
-          )
-
-That is all that is needed to create a basic local install of the tutorial.
-
-Run cmake or cmake-gui to configure the project and then build it with your
-chosen build tool. Then build the “install” target by typing 'make install'
-from the command line or build the INSTALL target from an IDE. This will
-install the appropriate header files, libraries, and executables.
-
-Verify that the installed Tutorial runs. Note: The CMake variable
-CMAKE_INSTALL_PREFIX is used to determine the root of where the files will
-be installed.
-
-Next let's test our application. Adding testing is an easy process. At the
-end of the top-level CMakeLists file we can add a number of basic tests to
-verify that the application is working correctly.
-
-  # enable testing
-  enable_testing()
-
-  # does the application run
-  add_test(NAME Runs COMMAND Tutorial 25)
-
-  # does the usage message work?
-  add_test(NAME Usage COMMAND Tutorial)
-  set_tests_properties(Usage
-    PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
-    )
-
-  # define a function to simplify adding tests
-  function(do_test target arg result)
-    add_test(NAME Comp${arg} COMMAND ${target} ${arg})
-    set_tests_properties(Comp${arg}
-      PROPERTIES PASS_REGULAR_EXPRESSION ${result}
-      )
-  endfunction(do_test)
-
-  # do a bunch of result based tests
-  do_test(Tutorial 25 "25 is 5")
-  do_test(Tutorial -25 "-25 is [-nan|nan|0]")
-  do_test(Tutorial 0.0001 "0.0001 is 0.01")
-
-The first test simply verifies that the application runs, does not segfault or
-otherwise crash, and has a zero return value. This is the basic form of a CTest
-test.
-
-The Usage test uses a regular expression to verify that the usage message
-is printed when an incorrect number of arguments are provided.
-
-Lastly, we have a function called do_test that simplifies running the
-application and verifying that the computed square root is correct for given
-input.
-
-To run tests, cd to the binary directory and run “ctest -N” and “ctest -VV”.
diff --git a/Tests/Tutorial/Step4/tutorial.cxx b/Tests/Tutorial/Step4/tutorial.cxx
deleted file mode 100644
index 1d5742d..0000000
--- a/Tests/Tutorial/Step4/tutorial.cxx
+++ /dev/null
@@ -1,32 +0,0 @@
-// A simple program that computes the square root of a number
-#include <cmath>
-#include <iostream>
-#include <string>
-
-#include "TutorialConfig.h"
-
-#ifdef USE_MYMATH
-#  include "MathFunctions.h"
-#endif
-
-int main(int argc, char* argv[])
-{
-  if (argc < 2) {
-    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
-    std::cout << "Usage: " << argv[0] << " number" << std::endl;
-    return 1;
-  }
-
-  double inputValue = std::stod(argv[1]);
-
-#ifdef USE_MYMATH
-  double outputValue = mysqrt(inputValue);
-#else
-  double outputValue = sqrt(inputValue);
-#endif
-
-  std::cout << "The square root of " << inputValue << " is " << outputValue
-            << std::endl;
-  return 0;
-}
diff --git a/Tests/Tutorial/Step5/directions.txt b/Tests/Tutorial/Step5/directions.txt
deleted file mode 100644
index e6f5197..0000000
--- a/Tests/Tutorial/Step5/directions.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-# Adding System Introspection #
-
-Let us consider adding some code to our project that depends on features the
-target platform may not have. For this example, we will add some code that
-depends on whether or not the target platform has the log and exp functions. Of
-course almost every platform has these functions but for this tutorial assume
-that they are not common.
-
-If the platform has log and exp then we will use them to compute the square
-root in the mysqrt function. We first test for the availability of these
-functions using the CheckSymbolExists.cmake macro in the top-level CMakeLists
-file as follows:
-
-  # does this system provide the log and exp functions?
-  include(CheckSymbolExists)
-  set(CMAKE_REQUIRED_LIBRARIES "m")
-  check_symbol_exists(log "math.h" HAVE_LOG)
-  check_symbol_exists(exp "math.h" HAVE_EXP)
-
-Now let's add these defines to TutorialConfig.h.in so that we can use them
-from mysqrt.cxx:
-
-  // does the platform provide exp and log functions?
-  #cmakedefine HAVE_LOG
-  #cmakedefine HAVE_EXP
-
-Modify mysqrt.cxx to include math.h. Next, in the mysqrt function we can
-provide an alternate implementation based on log and exp if they are available
-on the system using the following code:
-
-  // if we have both log and exp then use them
-  #if defined(HAVE_LOG) && defined (HAVE_EXP)
-    double result = exp(log(x)*0.5);
-    std::cout << "Computing sqrt of " << x << " to be " << result << " using log" << std::endl;
-  #else
-    ...
-
-Run cmake or cmake-gui to configure the project and then build it with your
-chosen build tool.
-
-You will notice that even though HAVE_LOG and HAVE_EXP are both defined mysqrt
-isn't using them. We should realize quickly that we have forgotten to include
-TutorialConfig.h in mysqrt.cxx. We will also need to update
-MathFunctions/CMakeLists.txt with where it is located.
-
-So let's go ahead and update MathFunctions/CMakeLists.txt to look like:
-
-  add_library(MathFunctions mysqrt.cxx)
-
-  target_include_directories(MathFunctions
-            INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
-            PRIVATE ${Tutorial_BINARY_DIR}
-            )
-
-  install(TARGETS MathFunctions DESTINATION lib)
-  install(FILES MathFunctions.h DESTINATION include)
-
-Now all we need to do is include TutorialConfig.h in mysqrt.cxx
-
-At this point you should go ahead and build the project again.
-
-Run the built Tutorial executable. Which function gives better results now,
-Step1’s sqrt or Step5’s mysqrt?
-
-Exercise: Why is it important that we configure TutorialConfig.h.in after the
-checks for HAVE_LOG and HAVE_EXP? What would happen if we inverted the two?
-
-Exercise: Is there a better place for us to save the HAVE_LOG and HAVE_EXP
-values other than in TutorialConfig.h?
diff --git a/Tests/Tutorial/Step5/tutorial.cxx b/Tests/Tutorial/Step5/tutorial.cxx
deleted file mode 100644
index 1d5742d..0000000
--- a/Tests/Tutorial/Step5/tutorial.cxx
+++ /dev/null
@@ -1,32 +0,0 @@
-// A simple program that computes the square root of a number
-#include <cmath>
-#include <iostream>
-#include <string>
-
-#include "TutorialConfig.h"
-
-#ifdef USE_MYMATH
-#  include "MathFunctions.h"
-#endif
-
-int main(int argc, char* argv[])
-{
-  if (argc < 2) {
-    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
-    std::cout << "Usage: " << argv[0] << " number" << std::endl;
-    return 1;
-  }
-
-  double inputValue = std::stod(argv[1]);
-
-#ifdef USE_MYMATH
-  double outputValue = mysqrt(inputValue);
-#else
-  double outputValue = sqrt(inputValue);
-#endif
-
-  std::cout << "The square root of " << inputValue << " is " << outputValue
-            << std::endl;
-  return 0;
-}
diff --git a/Tests/Tutorial/Step6/TutorialConfig.h.in b/Tests/Tutorial/Step6/TutorialConfig.h.in
deleted file mode 100644
index a091265..0000000
--- a/Tests/Tutorial/Step6/TutorialConfig.h.in
+++ /dev/null
@@ -1,9 +0,0 @@
-// the configured options and settings for Tutorial
-#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
-#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
-
-// does the platform provide exp and log functions?
-#cmakedefine HAVE_LOG
-#cmakedefine HAVE_EXP
-
diff --git a/Tests/Tutorial/Step6/directions.txt b/Tests/Tutorial/Step6/directions.txt
deleted file mode 100644
index 42b9f06..0000000
--- a/Tests/Tutorial/Step6/directions.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-# Adding a Custom Command and Generated File #
-
-In this section we will show how you can add a generated source file into the
-build process of an application. For this example, we will create a table of
-precomputed square roots as part of the build process, and then compile that
-table into our application.
-
-To accomplish this, we first need a program that will generate the table. In the
-MathFunctions subdirectory a new source file named MakeTable.cxx will do just that.
-
-  // A simple program that builds a sqrt table
-  #include <iostream>
-  #include <fstream>
-  #include <cmath>
-
-  int main (int argc, char *argv[])
-  {
-    // make sure we have enough arguments
-    if (argc < 2) {
-      return 1;
-    }
-
-    std::ofstream fout(argv[1],std::ios_base::out);
-    const bool fileOpen = fout.is_open();
-    if(fileOpen) {
-      fout << "double sqrtTable[] = {" << std::endl;
-      for (int i = 0; i < 10; ++i) {
-        fout << sqrt(static_cast<double>(i)) << "," << std::endl;
-      }
-      // close the table with a zero
-      fout << "0};" << std::endl;
-      fout.close();
-    }
-    return fileOpen ? 0 : 1; // return 0 if wrote the file
-  }
-
-Note that the table is produced as valid C++ code and that the output filename
-is passed in as an argument.
-
-The next step is to add the appropriate commands to MathFunctions’ CMakeLists
-file to build the MakeTable executable and then run it as part of the build
-process. A few commands are needed to accomplish this, as shown below:
-
-  # first we add the executable that generates the table
-  add_executable(MakeTable MakeTable.cxx)
-
-  # add the command to generate the source code
-  add_custom_command(
-    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-    DEPENDS MakeTable
-    )
-
-  # add the main library
-  add_library(MathFunctions
-              mysqrt.cxx
-              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-              )
-
-  target_include_directories(MathFunctions
-          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
-          PUBLIC ${Tutorial_BINARY_DIR}
-                 # add the binary tree directory to the search path for include files
-                 ${CMAKE_CURRENT_BINARY_DIR}
-          )
-
-  install(TARGETS MathFunctions DESTINATION lib)
-  install(FILES MathFunctions.h DESTINATION include)
-
-First, the executable for MakeTable is added as any other executable would be
-added. Then we add a custom command that specifies how to produce Table.h by
-running MakeTable. Next we have to let CMake know that mysqrt.cxx depends on
-the generated file Table.h. This is done by adding the generated Table.h to the
-list of sources for the library MathFunctions. We also have to add the current
-binary directory to the list of include directories so that Table.h can be
-found and included by mysqrt.cxx.
-
-Now let's use the generated table. First, modify mysqrt.cxx to include Table.h.
-Next, we can rewrite the mysqrt function to use the table:
-
-  if (x <= 0) {
-    return 0;
-  }
-
-  // use the table to help find an initial value
-  double result = x;
-  if (x >= 1 && x < 10) {
-    result = sqrtTable[static_cast<int>(x)];
-  }
-
-  // do ten iterations
-  for (int i = 0; i < 10; ++i) {
-    if (result <= 0) {
-      result = 0.1;
-    }
-    double delta = x - (result*result);
-    result = result + 0.5*delta/result;
-    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
-  }
-
-Run cmake or cmake-gui to configure the project and then build it with your
-chosen build tool. When this project is built it will first build the MakeTable
-executable. It will then run MakeTable to produce Table.h. Finally, it will
-compile mysqrt.cxx which includes Table.h to produce the MathFunctions library.
diff --git a/Tests/Tutorial/Step6/tutorial.cxx b/Tests/Tutorial/Step6/tutorial.cxx
deleted file mode 100644
index 1d5742d..0000000
--- a/Tests/Tutorial/Step6/tutorial.cxx
+++ /dev/null
@@ -1,32 +0,0 @@
-// A simple program that computes the square root of a number
-#include <cmath>
-#include <iostream>
-#include <string>
-
-#include "TutorialConfig.h"
-
-#ifdef USE_MYMATH
-#  include "MathFunctions.h"
-#endif
-
-int main(int argc, char* argv[])
-{
-  if (argc < 2) {
-    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
-    std::cout << "Usage: " << argv[0] << " number" << std::endl;
-    return 1;
-  }
-
-  double inputValue = std::stod(argv[1]);
-
-#ifdef USE_MYMATH
-  double outputValue = mysqrt(inputValue);
-#else
-  double outputValue = sqrt(inputValue);
-#endif
-
-  std::cout << "The square root of " << inputValue << " is " << outputValue
-            << std::endl;
-  return 0;
-}
diff --git a/Tests/Tutorial/Step7/TutorialConfig.h.in b/Tests/Tutorial/Step7/TutorialConfig.h.in
deleted file mode 100644
index a091265..0000000
--- a/Tests/Tutorial/Step7/TutorialConfig.h.in
+++ /dev/null
@@ -1,9 +0,0 @@
-// the configured options and settings for Tutorial
-#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
-#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
-
-// does the platform provide exp and log functions?
-#cmakedefine HAVE_LOG
-#cmakedefine HAVE_EXP
-
diff --git a/Tests/Tutorial/Step7/build1.cmake b/Tests/Tutorial/Step7/build1.cmake
deleted file mode 100644
index baa475f..0000000
--- a/Tests/Tutorial/Step7/build1.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-set(CTEST_SOURCE_DIRECTORY "$ENV{HOME}/Dashboards/My Tests/CMake/Tests/Tutorial/Step7")
-set(CTEST_BINARY_DIRECTORY "${CTEST_SOURCE_DIRECTORY}-build1")
-
-set(CTEST_CMAKE_COMMAND "cmake")
-set(CTEST_COMMAND "ctest -D Experimental")
diff --git a/Tests/Tutorial/Step7/directions.txt b/Tests/Tutorial/Step7/directions.txt
deleted file mode 100644
index 7d7c2ea..0000000
--- a/Tests/Tutorial/Step7/directions.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-# Building an Installer #
-
-Next suppose that we want to distribute our project to other people so that they
-can use it. We want to provide both binary and source distributions on a variety
-of platforms. This is a little different from the install we did previously in
-the Installing and Testing section (Step 4), where we were installing the
-binaries that we had built from the source code. In this example we will be
-building installation packages that support binary installations and package
-management features. To accomplish this we will use CPack to create platform
-specific installers. Specifically we need to add a few lines to the bottom of
-our top-level CMakeLists.txt file.
-
-  include(InstallRequiredSystemLibraries)
-  set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-  set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-  set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-  include(CPack)
-
-That is all there is to it. We start by including InstallRequiredSystemLibraries.
-This module will include any runtime libraries that are needed by the project
-for the current platform. Next we set some CPack variables to where we have
-stored the license and version information for this project. The version
-information makes use of the variables we set earlier in this tutorial. Finally
-we include the CPack module which will use these variables and some other
-properties of the system you are on to setup an installer.
-
-The next step is to build the project in the usual manner and then run CPack
-on it. To build a binary distribution you would run:
-
-  cpack
-
-To create a source distribution you would type:
-
-  cpack -C CPackSourceConfig.cmake
-
-Alternatively, run “make package” or right click the Package target and
-“Build Project” from an IDE.
-
-Run the installer executable found  in the binary directory. Then run the
-installed executable and verify that it works.
diff --git a/Tests/Tutorial/Step7/tutorial.cxx b/Tests/Tutorial/Step7/tutorial.cxx
deleted file mode 100644
index 1d5742d..0000000
--- a/Tests/Tutorial/Step7/tutorial.cxx
+++ /dev/null
@@ -1,32 +0,0 @@
-// A simple program that computes the square root of a number
-#include <cmath>
-#include <iostream>
-#include <string>
-
-#include "TutorialConfig.h"
-
-#ifdef USE_MYMATH
-#  include "MathFunctions.h"
-#endif
-
-int main(int argc, char* argv[])
-{
-  if (argc < 2) {
-    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
-    std::cout << "Usage: " << argv[0] << " number" << std::endl;
-    return 1;
-  }
-
-  double inputValue = std::stod(argv[1]);
-
-#ifdef USE_MYMATH
-  double outputValue = mysqrt(inputValue);
-#else
-  double outputValue = sqrt(inputValue);
-#endif
-
-  std::cout << "The square root of " << inputValue << " is " << outputValue
-            << std::endl;
-  return 0;
-}
diff --git a/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt
deleted file mode 100644
index dc3eb98..0000000
--- a/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-# first we add the executable that generates the table
-add_executable(MakeTable MakeTable.cxx)
-
-# add the command to generate the source code
-add_custom_command(
-  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  DEPENDS MakeTable
-  )
-
-# add the main library
-add_library(MathFunctions
-            mysqrt.cxx
-            ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-            )
-
-# state that anybody linking to us needs to include the current source dir
-# to find MathFunctions.h, while we don't.
-# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
-# TutorialConfig.h include is an implementation detail
-# state that we depend on our binary dir to find Table.h
-target_include_directories(MathFunctions
-          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
-          PRIVATE ${Tutorial_BINARY_DIR}
-                  ${CMAKE_CURRENT_BINARY_DIR}
-          )
-
-install(TARGETS MathFunctions DESTINATION lib)
-install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step8/directions.txt b/Tests/Tutorial/Step8/directions.txt
deleted file mode 100644
index 588d9c6..0000000
--- a/Tests/Tutorial/Step8/directions.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-# Adding Support for a Dashboard #
-
-Adding support for submitting our test results to a dashboard is very easy. We
-already defined a number of tests for our project in the earlier steps of this
-tutorial. We just have to run those tests and submit them to a dashboard. To
-include support for dashboards we include the CTest module in our top-level
-CMakeLists.txt.
-
-Replace:
-  # enable testing
-  enable_testing()
-
-With:
-  # enable dashboard scripting
-  include(CTest)
-
-The CTest module will automatically call enable_testing(), so
-we can remove it from our CMake files.
-
-We will also need to create a CTestConfig.cmake file where we can specify the
-name of the project and where to submit the dashboard.
-
-  set(CTEST_PROJECT_NAME "CMakeTutorial")
-  set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
-
-  set(CTEST_DROP_METHOD "http")
-  set(CTEST_DROP_SITE "my.cdash.org/")
-  set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
-  set(CTEST_DROP_SITE_CDASH TRUE)
-
-CTest will read in this file when it runs. To create a simple dashboard you can
-run cmake or cmake-gui to configure the project, but do not build it yet.
-Instead, change directory to the binary tree, and then run:
- 'ctest [-VV] –D Experimental'. On Windows, build the EXPERIMENTAL target.
-
-Ctest will build and test the project and submit results to the Kitware public
-dashboard. The results of your dashboard will be uploaded to Kitware's public
-dashboard here: https://my.cdash.org/index.php?project=CMakeTutorial.
diff --git a/Tests/Tutorial/Step8/tutorial.cxx b/Tests/Tutorial/Step8/tutorial.cxx
deleted file mode 100644
index 1d5742d..0000000
--- a/Tests/Tutorial/Step8/tutorial.cxx
+++ /dev/null
@@ -1,32 +0,0 @@
-// A simple program that computes the square root of a number
-#include <cmath>
-#include <iostream>
-#include <string>
-
-#include "TutorialConfig.h"
-
-#ifdef USE_MYMATH
-#  include "MathFunctions.h"
-#endif
-
-int main(int argc, char* argv[])
-{
-  if (argc < 2) {
-    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
-    std::cout << "Usage: " << argv[0] << " number" << std::endl;
-    return 1;
-  }
-
-  double inputValue = std::stod(argv[1]);
-
-#ifdef USE_MYMATH
-  double outputValue = mysqrt(inputValue);
-#else
-  double outputValue = sqrt(inputValue);
-#endif
-
-  std::cout << "The square root of " << inputValue << " is " << outputValue
-            << std::endl;
-  return 0;
-}
diff --git a/Tests/Tutorial/Step9/directions.txt b/Tests/Tutorial/Step9/directions.txt
deleted file mode 100644
index 8771637..0000000
--- a/Tests/Tutorial/Step9/directions.txt
+++ /dev/null
@@ -1,166 +0,0 @@
-# Mixing Static and Shared #
-
-In this section we will show how by using the BUILD_SHARED_LIBS variable we can
-control the default behavior of add_library, and allow control over how
-libraries without an explicit type ( STATIC/SHARED/MODULE/OBJECT ) are built.
-
-To accomplish this we need to add BUILD_SHARED_LIBS to the top level
-CMakeLists.txt. We use the option command as it allows users to optionally
-select if the value should be On or Off.
-
-Next we are going to refactor MathFunctions to become a real library that
-encapsulates using mysqrt or sqrt, instead of requiring the calling code
-to do this logic. This will also mean that USE_MYMATH will not control building
-MathFuctions, but instead will control the behavior of this library.
-
-The first step is to update the starting section of the top level CMakeLists.txt
-to look like:
-
-  cmake_minimum_required(VERSION 3.3)
-  project(Tutorial)
-
-  # control where the static and shared libraries are built so that on windows
-  # we don't need to tinker with the path to run the executable
-  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
-
-  set(CMAKE_CXX_STANDARD 11)
-  set(CMAKE_CXX_STANDARD_REQUIRED True)
-
-  option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
-
-  # the version number.
-  set(Tutorial_VERSION_MAJOR 1)
-  set(Tutorial_VERSION_MINOR 0)
-
-  # configure a header file to pass the version number only
-  configure_file(
-    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
-    "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-    )
-
-  # add the MathFunctions library
-  add_subdirectory(MathFunctions)
-
-  # add the executable
-  add_executable(Tutorial tutorial.cxx)
-  target_link_libraries(Tutorial PUBLIC MathFunctions)
-
-Now that we have made MathFunctions always be used, we will need to update
-the logic of that library. So, in MathFunctions/CMakeLists.txt we need to
-create a SqrtLibrary that will conditionally be built when USE_MYMATH is
-enabled. Now, since this is a tutorial, we are going to explicitly require
-that SqrtLibrary is built statically.
-
-The end result is that MathFunctions/CMakeLists.txt should look like:
-
-  # add the library that runs
-  add_library(MathFunctions MathFunctions.cxx)
-
-  # state that anybody linking to us needs to include the current source dir
-  # to find MathFunctions.h, while we don't.
-  target_include_directories(MathFunctions
-                             INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
-                             )
-
-  # should we use our own math functions
-  option(USE_MYMATH "Use tutorial provided math implementation" ON)
-  if(USE_MYMATH)
-
-    # does this system provide the log and exp functions?
-    include(CheckSymbolExists)
-    set(CMAKE_REQUIRED_LIBRARIES "m")
-    check_symbol_exists(log "math.h" HAVE_LOG)
-    check_symbol_exists(exp "math.h" HAVE_EXP)
-
-    # first we add the executable that generates the table
-    add_executable(MakeTable MakeTable.cxx)
-
-    # add the command to generate the source code
-    add_custom_command(
-      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-      COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-      DEPENDS MakeTable
-      )
-
-    # library that just does sqrt
-    add_library(SqrtLibrary STATIC
-                mysqrt.cxx
-                ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-                )
-
-    # state that we depend on our binary dir to find Table.h
-    target_include_directories(SqrtLibrary PRIVATE
-                               ${CMAKE_CURRENT_BINARY_DIR}
-                               )
-
-    target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
-    if(HAVE_LOG AND HAVE_EXP)
-      target_compile_definitions(SqrtLibrary
-                                 PRIVATE "HAVE_LOG" "HAVE_EXP")
-    endif()
-
-    target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
-  endif()
-
-  # define the symbol stating we are using the declspec(dllexport) when
-  # building on windows
-  target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
-
-  install(TARGETS MathFunctions DESTINATION lib)
-  install(FILES MathFunctions.h DESTINATION include)
-
-Next, update MathFunctions/mysqrt.cxx to use the mathfunctions and detail namespaces:
-
-  #include <iostream>
-  #include "MathFunctions.h"
-
-  // include the generated table
-  #include "Table.h"
-
-  #include <cmath>
-
-  namespace mathfunctions {
-  namespace detail {
-  // a hack square root calculation using simple operations
-  double mysqrt(double x)
-  {
-    ...
-
-    return result;
-  }
-  }
-  }
-
-We also need to make some changes in tutorial.cxx, so that it no longer uses USE_MYMATH:
-1. Always include MathFunctions.h
-2. Always use mathfunctions::sqrt
-
-Finally, update MathFunctions/MathFunctions.h to use dll export defines:
-
-  #if defined(_WIN32)
-  #if defined(EXPORTING_MYMATH)
-    #define DECLSPEC  __declspec(dllexport)
-  #else
-    #define DECLSPEC  __declspec(dllimport)
-  #endif
-  #else //non windows
-    #define DECLSPEC
-  #endif
-
-  namespace mathfunctions
-  {
-    double DECLSPEC sqrt(double x);
-  }
-
-At this point, if you build everything, you will notice that linking fails
-as we are combining a static library without position enabled code with a
-library that has position enabled code. This solution to this is to explicitly
-set the POSITION_INDEPENDENT_CODE target property of SqrtLibrary to be True no
-matter the build type.
-
-Exercise: We modified MathFunctions.h to use dll export defines. Using CMake
-documentation can you find a helper module to simplify this?
-
-Exercise: Determine what command is enabling PIC for SqrtLibrary.
-What happens if we remove said command?
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index ce4cfaf..f52caed 100644
--- a/Utilities/Doxygen/CMakeLists.txt
+++ b/Utilities/Doxygen/CMakeLists.txt
@@ -7,7 +7,7 @@
   get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
   get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
   include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
-  include(${CMake_SOURCE_DIR}/Source/CMakeVersionCompute.cmake)
+  include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake)
   include(${CMake_SOURCE_DIR}/Source/CMakeInstallDestinations.cmake)
   unset(CMAKE_DATA_DIR)
   unset(CMAKE_DATA_DIR CACHE)
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index 0393ff1..9fff442 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -42,10 +42,19 @@
   { symbol: [ "std::istringstream", private, "<sstream>", public ] },
   { symbol: [ "std::ostringstream", private, "<sstream>", public ] },
 
-  # HACK: iwyu suggests those two files each time vector[] is used.
+  # HACK: iwyu suggests <ext/alloc_traits.h> and <memory> each time vector[] is used.
   # https://github.com/include-what-you-use/include-what-you-use/issues/166
   { include: [ "<ext/alloc_traits.h>", private, "<vector>", public ] },
-  { include: [ "<memory>", public, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<cmComputeComponentGraph::TarjanEntry> >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<cmFortranFile> >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<cmGraphEdgeList> >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<cmOrderDirectories::ConflictList> >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<cmStateSnapshot> >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<std::basic_string<char> > >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > > >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >::value_type", private, "<vector>", public ] },
+  { symbol: [ "std::allocator_traits<std::allocator<uv_stdio_container_s> >::value_type", private, "<vector>", public ] },
 
   # TODO: enable this block and remove some <utility> includes?
   #{ symbol: [ "std::pair", private, "<utility>", public ] },
diff --git a/Utilities/Release/create-cmake-release.cmake b/Utilities/Release/create-cmake-release.cmake
index b3cc352..0622ad8 100644
--- a/Utilities/Release/create-cmake-release.cmake
+++ b/Utilities/Release/create-cmake-release.cmake
@@ -5,30 +5,10 @@
 
 file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/logs)
 
-set(RELEASE_SCRIPTS_BATCH_1
-  win32_release.cmake         # Windows x86
-  osx_release.cmake           # OS X x86_64
-  linux64_release.cmake       # Linux x86_64
-)
-
-set(RELEASE_SCRIPTS_BATCH_2
-  win64_release.cmake         # Windows x64
-)
-
-function(write_batch_shell_script filename)
-  set(scripts ${ARGN})
-  set(i 0)
-  file(WRITE ${filename} "#!/bin/bash")
-  foreach(f ${scripts})
-    math(EXPR x "420*(${i}/4)")
-    math(EXPR y "160*(${i}%4)")
-    file(APPEND ${filename}
-    "
-\"${CMAKE_COMMAND}\" -DCMAKE_CREATE_VERSION=${CMAKE_CREATE_VERSION} -DCMAKE_DOC_TARBALL=\"${CMAKE_DOC_TARBALL}\" -P \"${CMAKE_ROOT}/Utilities/Release/${f}\" < /dev/null >& \"${CMAKE_CURRENT_SOURCE_DIR}/logs/${f}-${CMAKE_CREATE_VERSION}.log\" &
-xterm -geometry 64x6+${x}+${y} -sb -sl 2000 -T ${f}-${CMAKE_CREATE_VERSION}.log -e tail -f \"${CMAKE_CURRENT_SOURCE_DIR}/logs/${f}-${CMAKE_CREATE_VERSION}.log\" &
+function(write_rel_shell_script filename script)
+  file(WRITE ${filename} "#!/usr/bin/env bash
+\"${CMAKE_COMMAND}\" -DCMAKE_CREATE_VERSION=${CMAKE_CREATE_VERSION} -DCMAKE_DOC_TARBALL=\"${CMAKE_DOC_TARBALL}\" -P \"${CMAKE_CURRENT_LIST_DIR}/${script}.cmake\" < /dev/null 2>&1 | tee \"${CMAKE_CURRENT_SOURCE_DIR}/logs/${script}-${CMAKE_CREATE_VERSION}.log\"
 ")
-    math(EXPR i "${i}+1")
-  endforeach()
   execute_process(COMMAND chmod a+x ${filename})
 endfunction()
 
@@ -65,12 +45,16 @@
 endfunction()
 
 write_docs_shell_script("create-${CMAKE_CREATE_VERSION}-docs.sh")
-write_batch_shell_script("create-${CMAKE_CREATE_VERSION}-batch1.sh" ${RELEASE_SCRIPTS_BATCH_1})
-write_batch_shell_script("create-${CMAKE_CREATE_VERSION}-batch2.sh" ${RELEASE_SCRIPTS_BATCH_2})
+write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-linux64.sh" linux64_release) # Linux x86_64
+write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-macos.sh"   osx_release    ) # macOS x86_64
+write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-win64.sh"   win64_release  ) # Windows x64
+write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-win32.sh"   win32_release  ) # Windows x86
 
-message("Run one at a time:
- ./create-${CMAKE_CREATE_VERSION}-docs.sh   &&
- ./create-${CMAKE_CREATE_VERSION}-batch1.sh &&
- ./create-${CMAKE_CREATE_VERSION}-batch2.sh &&
+message("Build docs first and then build for each platform:
+ ./create-${CMAKE_CREATE_VERSION}-docs.sh    &&
+ ./create-${CMAKE_CREATE_VERSION}-linux64.sh &&
+ ./create-${CMAKE_CREATE_VERSION}-macos.sh   &&
+ ./create-${CMAKE_CREATE_VERSION}-win64.sh   &&
+ ./create-${CMAKE_CREATE_VERSION}-win32.sh   &&
  echo done
 ")
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index c5b2bfe..736a7c0 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -7,7 +7,7 @@
   get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
   get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
   include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
-  include(${CMake_SOURCE_DIR}/Source/CMakeVersionCompute.cmake)
+  include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake)
   include(${CMake_SOURCE_DIR}/Source/CMakeInstallDestinations.cmake)
   unset(CMAKE_DATA_DIR)
   unset(CMAKE_DATA_DIR CACHE)
@@ -105,7 +105,6 @@
     # Workaround sphinx configurability:
     # https://bitbucket.org/birkenfeld/sphinx/issue/1448/make-qthelp-more-configurable
     COMMAND ${CMAKE_COMMAND} "-DQTHELP_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/"
-      "-DCMake_VERSION=${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}${CMake_VERSION_PATCH}"
       -P "${CMAKE_CURRENT_SOURCE_DIR}/fixup_qthelp_names.cmake"
 
     # Create proper identifiers. Workaround for
@@ -216,7 +215,7 @@
 
 if(SPHINX_QTHELP)
   CMake_OPTIONAL_COMPONENT(sphinx-qthelp)
-  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake-${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}${CMake_VERSION_PATCH}.qch
+  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qch
           DESTINATION ${CMAKE_DOC_DIR} ${COMPONENT}
           )
 endif()
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 70ba080..e50c4f9 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -82,4 +82,4 @@
 # Not supported yet by sphinx:
 # https://bitbucket.org/birkenfeld/sphinx/issue/1448/make-qthelp-more-configurable
 # qthelp_namespace = "org.cmake"
-# qthelp_qch_name = "CMake-300.qch"
+# qthelp_qch_name = "CMake.qch"
diff --git a/Utilities/Sphinx/fixup_qthelp_names.cmake b/Utilities/Sphinx/fixup_qthelp_names.cmake
index e35ef25..179e846 100644
--- a/Utilities/Sphinx/fixup_qthelp_names.cmake
+++ b/Utilities/Sphinx/fixup_qthelp_names.cmake
@@ -10,15 +10,6 @@
   QHCP_CONTENT "${QHCP_CONTENT}"
 )
 
-string(REPLACE
-  "<output>CMake.qch" "<output>CMake-${CMake_VERSION}.qch"
-  QHCP_CONTENT "${QHCP_CONTENT}"
-)
-string(REPLACE
-  "<file>CMake.qch" "<file>CMake-${CMake_VERSION}.qch"
-  QHCP_CONTENT "${QHCP_CONTENT}"
-)
-
 file(WRITE "${QTHELP_DIR}/CMake.qhcp" "${QHCP_CONTENT}")
 
 
diff --git a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
index 15ba46e..60ee8e6 100644
--- a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
+++ b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
@@ -53,7 +53,7 @@
     message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
     set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
   endif()
-elseif()
+else()
   set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
 endif()
 
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 37522fc..bc8a7dc 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -449,7 +449,12 @@
 endif()
 
 if(CMAKE_USE_OPENSSL)
-  find_package(OpenSSL REQUIRED)
+  find_package(OpenSSL)
+  if(NOT OpenSSL_FOUND)
+    message(FATAL_ERROR
+      "Could not find OpenSSL. Install an OpenSSL development package or "
+      "configure CMake with -DCMAKE_USE_OPENSSL=OFF to build without OpenSSL.")
+  endif()
   set(SSL_ENABLED ON)
   set(USE_OPENSSL ON)
   set(HAVE_LIBCRYPTO ON)
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index e6dc736..eb80bfb 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -206,6 +206,7 @@
 /* Handle types. */
 typedef struct uv_loop_s uv_loop_t;
 typedef struct uv_handle_s uv_handle_t;
+typedef struct uv_dir_s uv_dir_t;
 typedef struct uv_stream_s uv_stream_t;
 typedef struct uv_tcp_s uv_tcp_t;
 typedef struct uv_udp_s uv_udp_t;
@@ -634,7 +635,11 @@
 UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
                           const struct sockaddr* addr,
                           unsigned int flags);
+UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);
 
+UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
+                                 struct sockaddr* name,
+                                 int* namelen);
 UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
                                  struct sockaddr* name,
                                  int* namelen);
@@ -1112,6 +1117,11 @@
 } uv_timeval_t;
 
 typedef struct {
+  int64_t tv_sec;
+  int32_t tv_usec;
+} uv_timeval64_t;
+
+typedef struct {
    uv_timeval_t ru_utime; /* user CPU time used */
    uv_timeval_t ru_stime; /* system CPU time used */
    uint64_t ru_maxrss;    /* maximum resident set size */
@@ -1162,6 +1172,17 @@
 UV_EXTERN int uv_os_setenv(const char* name, const char* value);
 UV_EXTERN int uv_os_unsetenv(const char* name);
 
+#ifdef MAXHOSTNAMELEN
+# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)
+#else
+  /*
+    Fallback for the maximum hostname size, including the null terminator. The
+    Windows gethostname() documentation states that 256 bytes will always be
+    large enough to hold the null-terminated hostname.
+  */
+# define UV_MAXHOSTNAMESIZE 256
+#endif
+
 UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
 
 UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
@@ -1199,9 +1220,19 @@
   UV_FS_FCHOWN,
   UV_FS_REALPATH,
   UV_FS_COPYFILE,
-  UV_FS_LCHOWN
+  UV_FS_LCHOWN,
+  UV_FS_OPENDIR,
+  UV_FS_READDIR,
+  UV_FS_CLOSEDIR
 } uv_fs_type;
 
+struct uv_dir_s {
+  uv_dirent_t* dirents;
+  size_t nentries;
+  void* reserved[4];
+  UV_DIR_PRIVATE_FIELDS
+};
+
 /* uv_fs_t is a subclass of uv_req_t. */
 struct uv_fs_s {
   UV_REQ_FIELDS
@@ -1294,6 +1325,18 @@
                             uv_fs_cb cb);
 UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
                                  uv_dirent_t* ent);
+UV_EXTERN int uv_fs_opendir(uv_loop_t* loop,
+                            uv_fs_t* req,
+                            const char* path,
+                            uv_fs_cb cb);
+UV_EXTERN int uv_fs_readdir(uv_loop_t* loop,
+                            uv_fs_t* req,
+                            uv_dir_t* dir,
+                            uv_fs_cb cb);
+UV_EXTERN int uv_fs_closedir(uv_loop_t* loop,
+                             uv_fs_t* req,
+                             uv_dir_t* dir,
+                             uv_fs_cb cb);
 UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
@@ -1536,6 +1579,7 @@
 
 UV_EXTERN uint64_t uv_get_free_memory(void);
 UV_EXTERN uint64_t uv_get_total_memory(void);
+UV_EXTERN uint64_t uv_get_constrained_memory(void);
 
 UV_EXTERN uint64_t uv_hrtime(void);
 
@@ -1589,9 +1633,29 @@
 UV_EXTERN void* uv_key_get(uv_key_t* key);
 UV_EXTERN void uv_key_set(uv_key_t* key, void* value);
 
+UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
+
 typedef void (*uv_thread_cb)(void* arg);
 
 UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
+
+typedef enum {
+  UV_THREAD_NO_FLAGS = 0x00,
+  UV_THREAD_HAS_STACK_SIZE = 0x01
+} uv_thread_create_flags;
+
+struct uv_thread_options_s {
+  unsigned int flags;
+  size_t stack_size;
+  /* More fields may be added at any time. */
+};
+
+typedef struct uv_thread_options_s uv_thread_options_t;
+
+UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
+                                  const uv_thread_options_t* params,
+                                  uv_thread_cb entry,
+                                  void* arg);
 UV_EXTERN uv_thread_t uv_thread_self(void);
 UV_EXTERN int uv_thread_join(uv_thread_t *tid);
 UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);
diff --git a/Utilities/cmlibuv/include/uv/unix.h b/Utilities/cmlibuv/include/uv/unix.h
index 3c1b363..011abcf 100644
--- a/Utilities/cmlibuv/include/uv/unix.h
+++ b/Utilities/cmlibuv/include/uv/unix.h
@@ -31,13 +31,14 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
-#include <netdb.h>
+#include <netdb.h>  /* MAXHOSTNAMELEN on Solaris */
 
 #include <termios.h>
 #include <pwd.h>
 
 #if !defined(__MVS__)
 #include <semaphore.h>
+#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
 #endif
 #include <pthread.h>
 #include <signal.h>
@@ -50,8 +51,6 @@
 # include "linux.h"
 #elif defined (__MVS__)
 # include "os390.h"
-#elif defined(__PASE__)
-# include "posix.h"
 #elif defined(_AIX)
 # include "aix.h"
 #elif defined(__sun)
@@ -64,9 +63,12 @@
       defined(__OpenBSD__)         || \
       defined(__NetBSD__)
 # include "bsd.h"
-#elif defined(__CYGWIN__) || defined(__MSYS__)
+#elif defined(__PASE__)   || \
+      defined(__CYGWIN__) || \
+      defined(__MSYS__)   || \
+      defined(__GNU__)
 # include "posix.h"
-#elif defined(__GNU__)
+#elif defined(__HAIKU__)
 # include "posix.h"
 #endif
 
@@ -149,7 +151,9 @@
 typedef pthread_key_t uv_key_t;
 
 /* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */
-#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
+#if defined(_AIX) || \
+    defined(__OpenBSD__) || \
+    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
 /* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */
 struct _uv_barrier {
   uv_mutex_t mutex;
@@ -178,6 +182,9 @@
 
 typedef struct dirent uv__dirent_t;
 
+#define UV_DIR_PRIVATE_FIELDS \
+  DIR* dir;
+
 #if defined(DT_UNKNOWN)
 # define HAVE_DIRENT_TYPES
 # if defined(DT_REG)
diff --git a/Utilities/cmlibuv/include/uv/version.h b/Utilities/cmlibuv/include/uv/version.h
index abc140a..97f0bc2 100644
--- a/Utilities/cmlibuv/include/uv/version.h
+++ b/Utilities/cmlibuv/include/uv/version.h
@@ -31,7 +31,7 @@
  */
 
 #define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 24
+#define UV_VERSION_MINOR 29
 #define UV_VERSION_PATCH 2
 #define UV_VERSION_IS_RELEASE 0
 #define UV_VERSION_SUFFIX "dev"
diff --git a/Utilities/cmlibuv/include/uv/win.h b/Utilities/cmlibuv/include/uv/win.h
index f3d3809..7f77cc2 100644
--- a/Utilities/cmlibuv/include/uv/win.h
+++ b/Utilities/cmlibuv/include/uv/win.h
@@ -312,6 +312,11 @@
   char d_name[1];
 } uv__dirent_t;
 
+#define UV_DIR_PRIVATE_FIELDS \
+  HANDLE dir_handle;          \
+  WIN32_FIND_DATAW find_data; \
+  BOOL need_find_call;
+
 #define HAVE_DIRENT_TYPES
 #define UV__DT_DIR     UV_DIRENT_DIR
 #define UV__DT_FILE    UV_DIRENT_FILE
diff --git a/Utilities/cmlibuv/src/fs-poll.c b/Utilities/cmlibuv/src/fs-poll.c
index 6c82dfc..89864e2 100644
--- a/Utilities/cmlibuv/src/fs-poll.c
+++ b/Utilities/cmlibuv/src/fs-poll.c
@@ -22,12 +22,20 @@
 #include "uv.h"
 #include "uv-common.h"
 
+#ifdef _WIN32
+#include "win/internal.h"
+#include "win/handle-inl.h"
+#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
+#else
+#include "unix/internal.h"
+#endif
+
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 struct poll_ctx {
-  uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */
+  uv_fs_poll_t* parent_handle;
   int busy_polling;
   unsigned int interval;
   uint64_t start_time;
@@ -36,6 +44,7 @@
   uv_timer_t timer_handle;
   uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
   uv_stat_t statbuf;
+  struct poll_ctx* previous; /* context from previous start()..stop() period */
   char path[1]; /* variable length */
 };
 
@@ -49,6 +58,7 @@
 
 int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
   uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
+  handle->poll_ctx = NULL;
   return 0;
 }
 
@@ -62,7 +72,7 @@
   size_t len;
   int err;
 
-  if (uv__is_active(handle))
+  if (uv_is_active((uv_handle_t*)handle))
     return 0;
 
   loop = handle->loop;
@@ -90,6 +100,8 @@
   if (err < 0)
     goto error;
 
+  if (handle->poll_ctx != NULL)
+    ctx->previous = handle->poll_ctx;
   handle->poll_ctx = ctx;
   uv__handle_start(handle);
 
@@ -104,19 +116,17 @@
 int uv_fs_poll_stop(uv_fs_poll_t* handle) {
   struct poll_ctx* ctx;
 
-  if (!uv__is_active(handle))
+  if (!uv_is_active((uv_handle_t*)handle))
     return 0;
 
   ctx = handle->poll_ctx;
   assert(ctx != NULL);
-  assert(ctx->parent_handle != NULL);
-  ctx->parent_handle = NULL;
-  handle->poll_ctx = NULL;
+  assert(ctx->parent_handle == handle);
 
   /* Close the timer if it's active. If it's inactive, there's a stat request
    * in progress and poll_cb will take care of the cleanup.
    */
-  if (uv__is_active(&ctx->timer_handle))
+  if (uv_is_active((uv_handle_t*)&ctx->timer_handle))
     uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
 
   uv__handle_stop(handle);
@@ -129,7 +139,7 @@
   struct poll_ctx* ctx;
   size_t required_len;
 
-  if (!uv__is_active(handle)) {
+  if (!uv_is_active((uv_handle_t*)handle)) {
     *size = 0;
     return UV_EINVAL;
   }
@@ -153,6 +163,9 @@
 
 void uv__fs_poll_close(uv_fs_poll_t* handle) {
   uv_fs_poll_stop(handle);
+
+  if (handle->poll_ctx == NULL)
+    uv__make_close_pending((uv_handle_t*)handle);
 }
 
 
@@ -173,14 +186,13 @@
   uv_stat_t* statbuf;
   struct poll_ctx* ctx;
   uint64_t interval;
+  uv_fs_poll_t* handle;
 
   ctx = container_of(req, struct poll_ctx, fs_req);
+  handle = ctx->parent_handle;
 
-  if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */
-    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
-    uv_fs_req_cleanup(req);
-    return;
-  }
+  if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle))
+    goto out;
 
   if (req->result != 0) {
     if (ctx->busy_polling != req->result) {
@@ -205,7 +217,7 @@
 out:
   uv_fs_req_cleanup(req);
 
-  if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */
+  if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) {
     uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
     return;
   }
@@ -219,8 +231,27 @@
 }
 
 
-static void timer_close_cb(uv_handle_t* handle) {
-  uv__free(container_of(handle, struct poll_ctx, timer_handle));
+static void timer_close_cb(uv_handle_t* timer) {
+  struct poll_ctx* ctx;
+  struct poll_ctx* it;
+  struct poll_ctx* last;
+  uv_fs_poll_t* handle;
+
+  ctx = container_of(timer, struct poll_ctx, timer_handle);
+  handle = ctx->parent_handle;
+  if (ctx == handle->poll_ctx) {
+    handle->poll_ctx = ctx->previous;
+    if (handle->poll_ctx == NULL && uv__is_closing(handle))
+      uv__make_close_pending((uv_handle_t*)handle);
+  } else {
+    for (last = handle->poll_ctx, it = last->previous;
+         it != ctx;
+         last = it, it = it->previous) {
+      assert(last->previous != NULL);
+    }
+    last->previous = ctx->previous;
+  }
+  uv__free(ctx);
 }
 
 
diff --git a/Utilities/cmlibuv/src/threadpool.c b/Utilities/cmlibuv/src/threadpool.c
index 4258933..7aa5755 100644
--- a/Utilities/cmlibuv/src/threadpool.c
+++ b/Utilities/cmlibuv/src/threadpool.c
@@ -27,7 +27,7 @@
 
 #include <stdlib.h>
 
-#define MAX_THREADPOOL_SIZE 128
+#define MAX_THREADPOOL_SIZE 1024
 
 static uv_once_t once = UV_ONCE_INIT;
 static uv_cond_t cond;
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index 337e58e..1f36926 100644
--- a/Utilities/cmlibuv/src/unix/aix.c
+++ b/Utilities/cmlibuv/src/unix/aix.c
@@ -344,6 +344,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   perfstat_cpu_total_t ps_total;
   int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
@@ -1041,6 +1046,7 @@
   struct poll_ctl pc;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct pollfd*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c
index 0b450ae..a5c47bc 100644
--- a/Utilities/cmlibuv/src/unix/async.c
+++ b/Utilities/cmlibuv/src/unix/async.c
@@ -61,14 +61,43 @@
   if (ACCESS_ONCE(int, handle->pending) != 0)
     return 0;
 
-  if (cmpxchgi(&handle->pending, 0, 1) == 0)
-    uv__async_send(handle->loop);
+  /* Tell the other thread we're busy with the handle. */
+  if (cmpxchgi(&handle->pending, 0, 1) != 0)
+    return 0;
+
+  /* Wake up the other thread's event loop. */
+  uv__async_send(handle->loop);
+
+  /* Tell the other thread we're done. */
+  if (cmpxchgi(&handle->pending, 1, 2) != 1)
+    abort();
 
   return 0;
 }
 
 
+/* Only call this from the event loop thread. */
+static int uv__async_spin(uv_async_t* handle) {
+  int rc;
+
+  for (;;) {
+    /* rc=0 -- handle is not pending.
+     * rc=1 -- handle is pending, other thread is still working with it.
+     * rc=2 -- handle is pending, other thread is done.
+     */
+    rc = cmpxchgi(&handle->pending, 2, 0);
+
+    if (rc != 1)
+      return rc;
+
+    /* Other thread is busy with this handle, spin until it's done. */
+    cpu_relax();
+  }
+}
+
+
 void uv__async_close(uv_async_t* handle) {
+  uv__async_spin(handle);
   QUEUE_REMOVE(&handle->queue);
   uv__handle_stop(handle);
 }
@@ -109,8 +138,8 @@
     QUEUE_REMOVE(q);
     QUEUE_INSERT_TAIL(&loop->async_handles, q);
 
-    if (cmpxchgi(&h->pending, 1, 0) == 0)
-      continue;
+    if (0 == uv__async_spin(h))
+      continue;  /* Not pending. */
 
     if (h->async_cb == NULL)
       continue;
diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h
index be741dc..995aca6 100644
--- a/Utilities/cmlibuv/src/unix/atomic-ops.h
+++ b/Utilities/cmlibuv/src/unix/atomic-ops.h
@@ -23,7 +23,6 @@
 #endif
 
 UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
-UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval));
 UV_UNUSED(static void cpu_relax(void));
 
 /* Prefer hand-rolled assembly over the gcc builtins because the latter also
@@ -49,43 +48,7 @@
   else
     return op4;
 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-  return atomic_cas_uint(ptr, oldval, newval);
-#else
-  return __sync_val_compare_and_swap(ptr, oldval, newval);
-#endif
-}
-
-UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
-#if defined(__i386__) || defined(__x86_64__)
-  long out;
-  __asm__ __volatile__ ("lock; cmpxchg %2, %1;"
-                        : "=a" (out), "+m" (*(volatile long*) ptr)
-                        : "r" (newval), "0" (oldval)
-                        : "memory");
-  return out;
-#elif defined(_AIX) && (defined(__xlC__) || defined(__ibmxl__))
-  const long out = (*(volatile int*) ptr);
-# if defined(__64BIT__)
-  __compare_and_swaplp(ptr, &oldval, newval);
-# else
-  __compare_and_swap(ptr, &oldval, newval);
-# endif /* if defined(__64BIT__) */
-  return out;
-#elif defined (__MVS__)
-#ifdef _LP64
-  unsigned long long op4;
-  if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval,
-                  (unsigned long long*) ptr, *ptr, &op4))
-#else
-  unsigned long op4;
-  if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
-                (unsigned int*) ptr, *ptr, &op4))
-#endif
-    return oldval;
-  else
-    return op4;
-#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-  return atomic_cas_ulong(ptr, oldval, newval);
+  return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
 #else
   return __sync_val_compare_and_swap(ptr, oldval, newval);
 #endif
diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
index 3c2253f..0d7bbe6 100644
--- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
@@ -31,6 +31,10 @@
 #include <net/if_dl.h>
 #endif
 
+#if defined(__HAIKU__)
+#define IFF_RUNNING IFF_LINK
+#endif
+
 static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
   if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
     return 1;
@@ -45,7 +49,8 @@
   if (exclude_type == UV__EXCLUDE_IFPHYS)
     return (ent->ifa_addr->sa_family != AF_LINK);
 #endif
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \
+    defined(__HAIKU__)
   /*
    * On BSD getifaddrs returns information related to the raw underlying
    * devices.  We're not interested in this information.
@@ -84,7 +89,8 @@
     return 0;
   }
 
-  *addresses = uv__malloc(*count * sizeof(**addresses));
+  /* Make sure the memory is initiallized to zero using calloc() */
+  *addresses = uv__calloc(*count, sizeof(**addresses));
 
   if (*addresses == NULL) {
     freeifaddrs(addrs);
@@ -116,6 +122,7 @@
     address++;
   }
 
+#if !(defined(__CYGWIN__) || defined(__MSYS__))
   /* Fill in physical addresses for each interface */
   for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
     if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
@@ -124,20 +131,15 @@
     address = *addresses;
 
     for (i = 0; i < *count; i++) {
-#if defined(__CYGWIN__) || defined(__MSYS__)
-      memset(address->phys_addr, 0, sizeof(address->phys_addr));
-#else
       if (strcmp(address->name, ent->ifa_name) == 0) {
         struct sockaddr_dl* sa_addr;
         sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
         memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-      } else {
-        memset(address->phys_addr, 0, sizeof(address->phys_addr));
       }
-#endif
       address++;
     }
   }
+#endif
 
   freeifaddrs(addrs);
 
diff --git a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
index 309ec79..d42ff05 100644
--- a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
+++ b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
@@ -137,4 +137,13 @@
   errno = ENOSYS;
   return -1;
 }
+
+int uv__statx(int dirfd,
+              const char* path,
+              int flags,
+              unsigned int mask,
+              struct uv__statx* statxbuf) {
+  errno = ENOSYS;
+  return -1;
+}
 #endif
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index a8d6adb..93df7af 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -42,9 +42,9 @@
 #include <pwd.h>
 #include <sched.h>
 #include <sys/utsname.h>
+#include <sys/time.h>
 
 #ifdef __sun
-# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
 # include <sys/filio.h>
 # include <sys/types.h>
 # include <sys/wait.h>
@@ -91,13 +91,8 @@
 #include <sys/ioctl.h>
 #endif
 
-#if !defined(__MVS__)
-#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
-#endif
-
-/* Fallback for the maximum hostname length */
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 256
+#if defined(__linux__)
+#include <sys/syscall.h>
 #endif
 
 static int uv__run_pending(uv_loop_t* loop);
@@ -174,7 +169,9 @@
 
   case UV_FS_POLL:
     uv__fs_poll_close((uv_fs_poll_t*)handle);
-    break;
+    /* Poll handles use file system requests, and one of them may still be
+     * running. The poll code will call uv__make_close_pending() for us. */
+    return;
 
   case UV_SIGNAL:
     uv__signal_close((uv_signal_t*) handle);
@@ -520,6 +517,34 @@
 }
 
 
+/* close() on macos has the "interesting" quirk that it fails with EINTR
+ * without closing the file descriptor when a thread is in the cancel state.
+ * That's why libuv calls close$NOCANCEL() instead.
+ *
+ * glibc on linux has a similar issue: close() is a cancellation point and
+ * will unwind the thread when it's in the cancel state. Work around that
+ * by making the system call directly. Musl libc is unaffected.
+ */
+int uv__close_nocancel(int fd) {
+#if defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
+#if defined(__LP64__)
+  extern int close$NOCANCEL(int);
+  return close$NOCANCEL(fd);
+#else
+  extern int close$NOCANCEL$UNIX2003(int);
+  return close$NOCANCEL$UNIX2003(fd);
+#endif
+#pragma GCC diagnostic pop
+#elif defined(__linux__)
+  return syscall(SYS_close, fd);
+#else
+  return close(fd);
+#endif
+}
+
+
 int uv__close_nocheckstdio(int fd) {
   int saved_errno;
   int rc;
@@ -527,7 +552,7 @@
   assert(fd > -1);  /* Catch uninitialized io_watcher.fd bugs. */
 
   saved_errno = errno;
-  rc = close(fd);
+  rc = uv__close_nocancel(fd);
   if (rc == -1) {
     rc = UV__ERR(errno);
     if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
@@ -562,7 +587,7 @@
 }
 
 
-#if !defined(__CYGWIN__) && !defined(__MSYS__)
+#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__)
 int uv__cloexec_ioctl(int fd, int set) {
   int r;
 
@@ -895,7 +920,8 @@
   QUEUE_REMOVE(&w->pending_queue);
 
   /* Remove stale events for this file descriptor */
-  uv__platform_invalidate_fd(loop, w->fd);
+  if (w->fd != -1)
+    uv__platform_invalidate_fd(loop, w->fd);
 }
 
 
@@ -929,7 +955,7 @@
   rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
   rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
 
-#if !defined(__MVS__)
+#if !defined(__MVS__) && !defined(__HAIKU__)
   rusage->ru_maxrss = usage.ru_maxrss;
   rusage->ru_ixrss = usage.ru_ixrss;
   rusage->ru_idrss = usage.ru_idrss;
@@ -1294,7 +1320,7 @@
     instead by creating a large enough buffer and comparing the hostname length
     to the size input.
   */
-  char buf[MAXHOSTNAMELEN + 1];
+  char buf[UV_MAXHOSTNAMESIZE];
   size_t len;
 
   if (buffer == NULL || size == NULL || *size == 0)
@@ -1426,3 +1452,39 @@
   buffer->machine[0] = '\0';
   return r;
 }
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen) {
+  socklen_t socklen;
+  uv_os_fd_t fd;
+  int r;
+
+  r = uv_fileno(handle, &fd);
+  if (r < 0)
+    return r;
+
+  /* sizeof(socklen_t) != sizeof(int) on some systems. */
+  socklen = (socklen_t) *namelen;
+
+  if (func(fd, name, &socklen))
+    return UV__ERR(errno);
+
+  *namelen = (int) socklen;
+  return 0;
+}
+
+int uv_gettimeofday(uv_timeval64_t* tv) {
+  struct timeval time;
+
+  if (tv == NULL)
+    return UV_EINVAL;
+
+  if (gettimeofday(&time, NULL) != 0)
+    return UV__ERR(errno);
+
+  tv->tv_sec = (int64_t) time.tv_sec;
+  tv->tv_usec = (int32_t) time.tv_usec;
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c
index 31ad8a9..e4cd8ff 100644
--- a/Utilities/cmlibuv/src/unix/darwin.c
+++ b/Utilities/cmlibuv/src/unix/darwin.c
@@ -117,6 +117,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   struct loadavg info;
   size_t size = sizeof(info);
diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c
index 0f729cf..7de88d6 100644
--- a/Utilities/cmlibuv/src/unix/freebsd.c
+++ b/Utilities/cmlibuv/src/unix/freebsd.c
@@ -137,6 +137,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   struct loadavg info;
   size_t size = sizeof(info);
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index bffc956..3023b1e 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -47,7 +47,7 @@
 
 #if defined(__DragonFly__)        ||                                      \
     defined(__FreeBSD__)          ||                                      \
-    defined(__FreeBSD_kernel_)    ||                                      \
+    defined(__FreeBSD_kernel__)   ||                                      \
     defined(__OpenBSD__)          ||                                      \
     defined(__NetBSD__)
 # define HAVE_PREADV 1
@@ -60,7 +60,6 @@
 #endif
 
 #if defined(__APPLE__)
-# include <copyfile.h>
 # include <sys/sysctl.h>
 #elif defined(__linux__) && !defined(FICLONE)
 # include <sys/ioctl.h>
@@ -143,19 +142,34 @@
   while (0)
 
 
+static int uv__fs_close(int fd) {
+  int rc;
+
+  rc = uv__close_nocancel(fd);
+  if (rc == -1)
+    if (errno == EINTR || errno == EINPROGRESS)
+      rc = 0;  /* The close is in progress, not an error. */
+
+  return rc;
+}
+
+
 static ssize_t uv__fs_fsync(uv_fs_t* req) {
 #if defined(__APPLE__)
   /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
    * to the drive platters. This is in contrast to Linux's fdatasync and fsync
    * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
    * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
-   * supported by the file system we should fall back to fsync(). This is the
-   * same approach taken by sqlite.
+   * supported by the file system we fall back to F_BARRIERFSYNC or fsync().
+   * This is the same approach taken by sqlite, except sqlite does not issue
+   * an F_BARRIERFSYNC call.
    */
   int r;
 
   r = fcntl(req->file, F_FULLFSYNC);
   if (r != 0)
+    r = fcntl(req->file, 85 /* F_BARRIERFSYNC */);  /* fsync + barrier */
+  if (r != 0)
     r = fsync(req->file);
   return r;
 #else
@@ -178,7 +192,8 @@
 
 static ssize_t uv__fs_futime(uv_fs_t* req) {
 #if defined(__linux__)                                                        \
-    || defined(_AIX71)
+    || defined(_AIX71)                                                        \
+    || defined(__HAIKU__)
   /* utimesat() has nanosecond resolution but we stick to microseconds
    * for the sake of consistency with other platforms.
    */
@@ -327,6 +342,18 @@
   req->bufs = NULL;
   req->nbufs = 0;
 
+#ifdef __PASE__
+  /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
+  if (result == -1 && errno == EOPNOTSUPP) {
+    struct stat buf;
+    ssize_t rc;
+    rc = fstat(req->file, &buf);
+    if (rc == 0 && S_ISDIR(buf.st_mode)) {
+      errno = EISDIR;
+    }
+  }
+#endif
+
   return result;
 }
 
@@ -349,7 +376,7 @@
 
 
 static ssize_t uv__fs_scandir(uv_fs_t* req) {
-  uv__dirent_t **dents;
+  uv__dirent_t** dents;
   int n;
 
   dents = NULL;
@@ -373,6 +400,87 @@
   return n;
 }
 
+static int uv__fs_opendir(uv_fs_t* req) {
+  uv_dir_t* dir;
+
+  dir = uv__malloc(sizeof(*dir));
+  if (dir == NULL)
+    goto error;
+
+  dir->dir = opendir(req->path);
+  if (dir->dir == NULL)
+    goto error;
+
+  req->ptr = dir;
+  return 0;
+
+error:
+  uv__free(dir);
+  req->ptr = NULL;
+  return -1;
+}
+
+static int uv__fs_readdir(uv_fs_t* req) {
+  uv_dir_t* dir;
+  uv_dirent_t* dirent;
+  struct dirent* res;
+  unsigned int dirent_idx;
+  unsigned int i;
+
+  dir = req->ptr;
+  dirent_idx = 0;
+
+  while (dirent_idx < dir->nentries) {
+    /* readdir() returns NULL on end of directory, as well as on error. errno
+       is used to differentiate between the two conditions. */
+    errno = 0;
+    res = readdir(dir->dir);
+
+    if (res == NULL) {
+      if (errno != 0)
+        goto error;
+      break;
+    }
+
+    if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0)
+      continue;
+
+    dirent = &dir->dirents[dirent_idx];
+    dirent->name = uv__strdup(res->d_name);
+
+    if (dirent->name == NULL)
+      goto error;
+
+    dirent->type = uv__fs_get_dirent_type(res);
+    ++dirent_idx;
+  }
+
+  return dirent_idx;
+
+error:
+  for (i = 0; i < dirent_idx; ++i) {
+    uv__free((char*) dir->dirents[i].name);
+    dir->dirents[i].name = NULL;
+  }
+
+  return -1;
+}
+
+static int uv__fs_closedir(uv_fs_t* req) {
+  uv_dir_t* dir;
+
+  dir = req->ptr;
+
+  if (dir->dir != NULL) {
+    closedir(dir->dir);
+    dir->dir = NULL;
+  }
+
+  uv__free(req->ptr);
+  req->ptr = NULL;
+  return 0;
+}
+
 #if defined(_POSIX_PATH_MAX)
 # define UV__FS_PATH_MAX _POSIX_PATH_MAX
 #elif defined(PATH_MAX)
@@ -702,7 +810,8 @@
 static ssize_t uv__fs_utime(uv_fs_t* req) {
 #if defined(__linux__)                                                         \
     || defined(_AIX71)                                                         \
-    || defined(__sun)
+    || defined(__sun)                                                          \
+    || defined(__HAIKU__)
   /* utimesat() has nanosecond resolution but we stick to microseconds
    * for the sake of consistency with other platforms.
    */
@@ -806,45 +915,6 @@
 }
 
 static ssize_t uv__fs_copyfile(uv_fs_t* req) {
-#if defined(__APPLE__) && !TARGET_OS_IPHONE
-  /* On macOS, use the native copyfile(3). */
-  static int can_clone;
-  copyfile_flags_t flags;
-  char buf[64];
-  size_t len;
-  int major;
-
-  flags = COPYFILE_ALL;
-
-  if (req->flags & UV_FS_COPYFILE_EXCL)
-    flags |= COPYFILE_EXCL;
-
-  /* Check OS version. Cloning is only supported on macOS >= 10.12. */
-  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
-    if (can_clone == 0) {
-      len = sizeof(buf);
-      if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0))
-        return UV__ERR(errno);
-
-      if (1 != sscanf(buf, "%d", &major))
-        abort();
-
-      can_clone = -1 + 2 * (major >= 16);  /* macOS >= 10.12 */
-    }
-
-    if (can_clone < 0)
-      return UV_ENOSYS;
-  }
-
-  /* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */
-  if (req->flags & UV_FS_COPYFILE_FICLONE)
-    flags |= 1 << 24;  /* COPYFILE_CLONE */
-
-  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE)
-    flags |= 1 << 25;  /* COPYFILE_CLONE_FORCE */
-
-  return copyfile(req->path, req->new_path, NULL, flags);
-#else
   uv_fs_t fs_req;
   uv_file srcfd;
   uv_file dstfd;
@@ -971,7 +1041,6 @@
 
   errno = UV__ERR(result);
   return -1;
-#endif
 }
 
 static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
@@ -1051,10 +1120,84 @@
 }
 
 
+static int uv__fs_statx(int fd,
+                        const char* path,
+                        int is_fstat,
+                        int is_lstat,
+                        uv_stat_t* buf) {
+  STATIC_ASSERT(UV_ENOSYS != -1);
+#ifdef __linux__
+  static int no_statx;
+  struct uv__statx statxbuf;
+  int dirfd;
+  int flags;
+  int mode;
+  int rc;
+
+  if (no_statx)
+    return UV_ENOSYS;
+
+  dirfd = AT_FDCWD;
+  flags = 0; /* AT_STATX_SYNC_AS_STAT */
+  mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
+
+  if (is_fstat) {
+    dirfd = fd;
+    flags |= 0x1000; /* AT_EMPTY_PATH */
+  }
+
+  if (is_lstat)
+    flags |= AT_SYMLINK_NOFOLLOW;
+
+  rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
+
+  if (rc == -1) {
+    /* EPERM happens when a seccomp filter rejects the system call.
+     * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
+     */
+    if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
+      return -1;
+
+    no_statx = 1;
+    return UV_ENOSYS;
+  }
+
+  buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
+  buf->st_mode = statxbuf.stx_mode;
+  buf->st_nlink = statxbuf.stx_nlink;
+  buf->st_uid = statxbuf.stx_uid;
+  buf->st_gid = statxbuf.stx_gid;
+  buf->st_rdev = statxbuf.stx_rdev_major;
+  buf->st_ino = statxbuf.stx_ino;
+  buf->st_size = statxbuf.stx_size;
+  buf->st_blksize = statxbuf.stx_blksize;
+  buf->st_blocks = statxbuf.stx_blocks;
+  buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
+  buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
+  buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
+  buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
+  buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
+  buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
+  buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
+  buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
+  buf->st_flags = 0;
+  buf->st_gen = 0;
+
+  return 0;
+#else
+  return UV_ENOSYS;
+#endif /* __linux__ */
+}
+
+
 static int uv__fs_stat(const char *path, uv_stat_t *buf) {
   struct stat pbuf;
   int ret;
 
+  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
+  if (ret != UV_ENOSYS)
+    return ret;
+
   ret = stat(path, &pbuf);
   if (ret == 0)
     uv__to_stat(&pbuf, buf);
@@ -1067,6 +1210,10 @@
   struct stat pbuf;
   int ret;
 
+  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
+  if (ret != UV_ENOSYS)
+    return ret;
+
   ret = lstat(path, &pbuf);
   if (ret == 0)
     uv__to_stat(&pbuf, buf);
@@ -1079,6 +1226,10 @@
   struct stat pbuf;
   int ret;
 
+  ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
+  if (ret != UV_ENOSYS)
+    return ret;
+
   ret = fstat(fd, &pbuf);
   if (ret == 0)
     uv__to_stat(&pbuf, buf);
@@ -1167,7 +1318,7 @@
     X(ACCESS, access(req->path, req->flags));
     X(CHMOD, chmod(req->path, req->mode));
     X(CHOWN, chown(req->path, req->uid, req->gid));
-    X(CLOSE, close(req->file));
+    X(CLOSE, uv__fs_close(req->file));
     X(COPYFILE, uv__fs_copyfile(req));
     X(FCHMOD, fchmod(req->file, req->mode));
     X(FCHOWN, fchown(req->file, req->uid, req->gid));
@@ -1184,6 +1335,9 @@
     X(OPEN, uv__fs_open(req));
     X(READ, uv__fs_read(req));
     X(SCANDIR, uv__fs_scandir(req));
+    X(OPENDIR, uv__fs_opendir(req));
+    X(READDIR, uv__fs_readdir(req));
+    X(CLOSEDIR, uv__fs_closedir(req));
     X(READLINK, uv__fs_readlink(req));
     X(REALPATH, uv__fs_realpath(req));
     X(RENAME, rename(req->path, req->new_path));
@@ -1454,6 +1608,40 @@
   POST;
 }
 
+int uv_fs_opendir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  const char* path,
+                  uv_fs_cb cb) {
+  INIT(OPENDIR);
+  PATH;
+  POST;
+}
+
+int uv_fs_readdir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  uv_dir_t* dir,
+                  uv_fs_cb cb) {
+  INIT(READDIR);
+
+  if (dir == NULL || dir->dir == NULL || dir->dirents == NULL)
+    return UV_EINVAL;
+
+  req->ptr = dir;
+  POST;
+}
+
+int uv_fs_closedir(uv_loop_t* loop,
+                   uv_fs_t* req,
+                   uv_dir_t* dir,
+                   uv_fs_cb cb) {
+  INIT(CLOSEDIR);
+
+  if (dir == NULL)
+    return UV_EINVAL;
+
+  req->ptr = dir;
+  POST;
+}
 
 int uv_fs_readlink(uv_loop_t* loop,
                    uv_fs_t* req,
@@ -1594,6 +1782,9 @@
   req->path = NULL;
   req->new_path = NULL;
 
+  if (req->fs_type == UV_FS_READDIR && req->ptr != NULL)
+    uv__fs_readdir_cleanup(req);
+
   if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
     uv__fs_scandir_cleanup(req);
 
@@ -1601,7 +1792,7 @@
     uv__free(req->bufs);
   req->bufs = NULL;
 
-  if (req->ptr != &req->statbuf)
+  if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf)
     uv__free(req->ptr);
   req->ptr = NULL;
 }
diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c
index c430562..ddacda3 100644
--- a/Utilities/cmlibuv/src/unix/fsevents.c
+++ b/Utilities/cmlibuv/src/unix/fsevents.c
@@ -21,9 +21,10 @@
 #include "uv.h"
 #include "internal.h"
 
-#if TARGET_OS_IPHONE
+#if TARGET_OS_IPHONE || MAC_OS_X_VERSION_MAX_ALLOWED < 1070
 
 /* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */
+/* macOS prior to 10.7 doesn't provide the full FSEvents API so use kqueue */
 
 int uv__fsevents_init(uv_fs_event_t* handle) {
   return 0;
diff --git a/Utilities/cmlibuv/src/unix/getaddrinfo.c b/Utilities/cmlibuv/src/unix/getaddrinfo.c
index 6d23fbe..d7ca7d1 100644
--- a/Utilities/cmlibuv/src/unix/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/unix/getaddrinfo.c
@@ -92,7 +92,9 @@
   }
   assert(!"unknown EAI_* error code");
   abort();
+#ifndef __SUNPRO_C
   return 0;  /* Pacify compiler. */
+#endif
 }
 
 
diff --git a/Utilities/cmlibuv/src/unix/haiku.c b/Utilities/cmlibuv/src/unix/haiku.c
new file mode 100644
index 0000000..7708851
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/haiku.c
@@ -0,0 +1,176 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <FindDirectory.h> /* find_path() */
+#include <OS.h>
+
+
+void uv_loadavg(double avg[3]) {
+  avg[0] = 0;
+  avg[1] = 0;
+  avg[2] = 0;
+}
+
+
+int uv_exepath(char* buffer, size_t* size) {
+  char abspath[B_PATH_NAME_LENGTH];
+  status_t status;
+  ssize_t abspath_len;
+
+  if (buffer == NULL || size == NULL || *size == 0)
+    return UV_EINVAL;
+
+  status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, abspath,
+                     sizeof(abspath));
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  abspath_len = uv__strscpy(buffer, abspath, *size);
+  *size -= 1;
+  if (abspath_len >= 0 && *size > (size_t)abspath_len)
+    *size = (size_t)abspath_len;
+
+  return 0;
+}
+
+
+uint64_t uv_get_free_memory(void) {
+  status_t status;
+  system_info sinfo;
+
+  status = get_system_info(&sinfo);
+  if (status != B_OK)
+    return 0;
+
+  return (sinfo.max_pages - sinfo.used_pages) * B_PAGE_SIZE;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+  status_t status;
+  system_info sinfo;
+
+  status = get_system_info(&sinfo);
+  if (status != B_OK)
+    return 0;
+
+  return sinfo.max_pages * B_PAGE_SIZE;
+}
+
+
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
+int uv_resident_set_memory(size_t* rss) {
+  area_info area;
+  ssize_t cookie;
+  status_t status;
+  thread_info thread;
+
+  status = get_thread_info(find_thread(NULL), &thread);
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  cookie = 0;
+  *rss = 0;
+  while (get_next_area_info(thread.team, &cookie, &area) == B_OK)
+    *rss += area.ram_size;
+
+  return 0;
+}
+
+
+int uv_uptime(double* uptime) {
+  /* system_time() returns time since booting in microseconds */
+  *uptime = (double)system_time() / 1000000;
+  return 0;
+}
+
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+  cpu_topology_node_info* topology_infos;
+  int i;
+  status_t status;
+  system_info system;
+  uint32_t topology_count;
+  uint64_t cpuspeed;
+  uv_cpu_info_t* cpu_info;
+
+  if (cpu_infos == NULL || count == NULL)
+    return UV_EINVAL;
+
+  status = get_cpu_topology_info(NULL, &topology_count);
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  topology_infos = uv__malloc(topology_count * sizeof(*topology_infos));
+  if (topology_infos == NULL)
+    return UV_ENOMEM;
+
+  status = get_cpu_topology_info(topology_infos, &topology_count);
+  if (status != B_OK) {
+    uv__free(topology_infos);
+    return UV__ERR(status);
+  }
+
+  cpuspeed = 0;
+  for (i = 0; i < (int)topology_count; i++) {
+    if (topology_infos[i].type == B_TOPOLOGY_CORE) {
+      cpuspeed = topology_infos[i].data.core.default_frequency;
+      break;
+    }
+  }
+
+  uv__free(topology_infos);
+
+  status = get_system_info(&system);
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  *cpu_infos = uv__calloc(system.cpu_count, sizeof(**cpu_infos));
+  if (*cpu_infos == NULL)
+    return UV_ENOMEM;
+
+  /* CPU time and model are not exposed by Haiku. */
+  cpu_info = *cpu_infos;
+  for (i = 0; i < (int)system.cpu_count; i++) {
+    cpu_info->model = uv__strdup("unknown");
+    cpu_info->speed = (int)(cpuspeed / 1000000);
+    cpu_info++;
+  }
+  *count = system.cpu_count;
+
+  return 0;
+}
+
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+  int i;
+
+  for (i = 0; i < count; i++)
+    uv__free(cpu_infos[i].model);
+
+  uv__free(cpu_infos);
+}
diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c
index 13fed6c..c7e1051 100644
--- a/Utilities/cmlibuv/src/unix/ibmi.c
+++ b/Utilities/cmlibuv/src/unix/ibmi.c
@@ -55,19 +55,155 @@
 #include <strings.h>
 #include <sys/vnode.h>
 
+#include <as400_protos.h>
+
+
+typedef struct {
+  int bytes_available;
+  int bytes_returned;
+  char current_date_and_time[8];
+  char system_name[8];
+  char elapsed_time[6];
+  char restricted_state_flag;
+  char reserved;
+  int percent_processing_unit_used;
+  int jobs_in_system;
+  int percent_permanent_addresses;
+  int percent_temporary_addresses;
+  int system_asp;
+  int percent_system_asp_used;
+  int total_auxiliary_storage;
+  int current_unprotected_storage_used;
+  int maximum_unprotected_storage_used;
+  int percent_db_capability;
+  int main_storage_size;
+  int number_of_partitions;
+  int partition_identifier;
+  int reserved1;
+  int current_processing_capacity;
+  char processor_sharing_attribute;
+  char reserved2[3];
+  int number_of_processors;
+  int active_jobs_in_system;
+  int active_threads_in_system;
+  int maximum_jobs_in_system;
+  int percent_temporary_256mb_segments_used;
+  int percent_temporary_4gb_segments_used;
+  int percent_permanent_256mb_segments_used;
+  int percent_permanent_4gb_segments_used;
+  int percent_current_interactive_performance;
+  int percent_uncapped_cpu_capacity_used;
+  int percent_shared_processor_pool_used;
+  long main_storage_size_long;
+} SSTS0200;
+
+
+static int get_ibmi_system_status(SSTS0200* rcvr) {
+  /* rcvrlen is input parameter 2 to QWCRSSTS */
+  unsigned int rcvrlen = sizeof(*rcvr);
+
+  /* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */
+  unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0};
+
+  /* reset_status is input parameter 4 to QWCRSSTS ("*NO       " in EBCDIC) */
+  unsigned char reset_status[] = {
+    0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
+  };
+
+  /* errcode is input parameter 5 to QWCRSSTS */
+  struct _errcode {
+    int bytes_provided;
+    int bytes_available;
+    char msgid[7];
+  } errcode;
+
+  /* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */
+  ILEpointer __attribute__((aligned(16))) qwcrssts_pointer;
+
+  /* qwcrssts_argv is the array of argument pointers to QWCRSSTS */
+  void* qwcrssts_argv[6];
+
+  /* Set the IBM i pointer to the QSYS/QWCRSSTS *PGM object */
+  int rc = _RSLOBJ2(&qwcrssts_pointer, RSLOBJ_TS_PGM, "QWCRSSTS", "QSYS");
+
+  if (rc != 0)
+    return rc;
+
+  /* initialize the QWCRSSTS returned info structure */
+  memset(rcvr, 0, sizeof(*rcvr));
+
+  /* initialize the QWCRSSTS error code structure */
+  memset(&errcode, 0, sizeof(errcode));
+  errcode.bytes_provided = sizeof(errcode);
+
+  /* initialize the array of argument pointers for the QWCRSSTS API */
+  qwcrssts_argv[0] = rcvr;
+  qwcrssts_argv[1] = &rcvrlen;
+  qwcrssts_argv[2] = &format;
+  qwcrssts_argv[3] = &reset_status;
+  qwcrssts_argv[4] = &errcode;
+  qwcrssts_argv[5] = NULL;
+
+  /* Call the IBM i QWCRSSTS API from PASE */
+  rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0);
+
+  return rc;
+}
+
+
 uint64_t uv_get_free_memory(void) {
-  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
+  SSTS0200 rcvr;
+
+  if (get_ibmi_system_status(&rcvr))
+    return 0;
+
+  /* The amount of main storage, in kilobytes, in the system. */
+  uint64_t main_storage_size = rcvr.main_storage_size;
+
+  /* The current amount of storage in use for temporary objects.
+   * in millions (M) of bytes.
+   */
+  uint64_t current_unprotected_storage_used =
+    rcvr.current_unprotected_storage_used * 1024ULL;
+
+  uint64_t free_storage_size =
+    (main_storage_size - current_unprotected_storage_used) * 1024ULL;
+
+  return free_storage_size < 0 ? 0 : free_storage_size;
 }
 
 
 uint64_t uv_get_total_memory(void) {
-  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
+  SSTS0200 rcvr;
+
+  if (get_ibmi_system_status(&rcvr))
+    return 0;
+
+  return (uint64_t)rcvr.main_storage_size * 1024ULL;
+}
+
+
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
 }
 
 
 void uv_loadavg(double avg[3]) {
+  SSTS0200 rcvr;
+
+  if (get_ibmi_system_status(&rcvr)) {
     avg[0] = avg[1] = avg[2] = 0;
     return;
+  }
+
+  /* The average (in tenths) of the elapsed time during which the processing
+   * units were in use. For example, a value of 411 in binary would be 41.1%.
+   * This percentage could be greater than 100% for an uncapped partition.
+   */
+  double processing_unit_used_percent =
+    rcvr.percent_processing_unit_used / 1000.0;
+
+  avg[0] = avg[1] = avg[2] = processing_unit_used_percent;
 }
 
 
@@ -111,3 +247,4 @@
 
   return 0;
 }
+
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index 48fe6e8..b43c0b1 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -105,8 +105,7 @@
  */
 #if defined(__clang__) ||                                                     \
     defined(__GNUC__) ||                                                      \
-    defined(__INTEL_COMPILER) ||                                              \
-    defined(__SUNPRO_C)
+    defined(__INTEL_COMPILER)
 # define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
 # define UV_UNUSED(declaration)     __attribute__((unused)) declaration
 #else
@@ -194,6 +193,7 @@
 int uv__nonblock_fcntl(int fd, int set);
 int uv__close(int fd); /* preserves errno */
 int uv__close_nocheckstdio(int fd);
+int uv__close_nocancel(int fd);
 int uv__socket(int domain, int type, int protocol);
 ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
 void uv__make_close_pending(uv_handle_t* handle);
@@ -316,4 +316,11 @@
 int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
 #endif
 
+typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen);
+
 #endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index c24f96e..c04e7a4 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -59,7 +59,7 @@
 }
 
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
 static int uv__has_forked_with_cfrunloop;
 #endif
 
@@ -70,7 +70,7 @@
   if (err)
     return err;
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
   if (loop->cf_state != NULL) {
     /* We cannot start another CFRunloop and/or thread in the child
        process; CF aborts if you try or if you try to touch the thread
@@ -86,7 +86,7 @@
     uv__free(loop->cf_state);
     loop->cf_state = NULL;
   }
-#endif
+#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
   return err;
 }
 
@@ -387,6 +387,7 @@
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct kevent*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
@@ -457,7 +458,7 @@
   if (uv__is_active(handle))
     return UV_EINVAL;
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
   /* Nullify field to perform checks later */
   handle->cf_cb = NULL;
   handle->realpath = NULL;
@@ -481,7 +482,7 @@
     }
     return r;
   }
-#endif /* defined(__APPLE__) */
+#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
 
   /* TODO open asynchronously - but how do we report back errors? */
   fd = open(path, O_RDONLY);
@@ -489,8 +490,11 @@
     return UV__ERR(errno);
 
   handle->path = uv__strdup(path);
-  if (handle->path == NULL)
+  if (handle->path == NULL) {
+    uv__close_nocheckstdio(fd);
     return UV_ENOMEM;
+  }
+
   handle->cb = cb;
   uv__handle_start(handle);
   uv__io_init(&handle->event_watcher, uv__fs_event, fd);
@@ -509,7 +513,7 @@
 
   uv__handle_stop(handle);
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
   if (!uv__has_forked_with_cfrunloop)
     r = uv__fsevents_close(handle);
 #endif
diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c
index 3341b94..b539beb 100644
--- a/Utilities/cmlibuv/src/unix/linux-core.c
+++ b/Utilities/cmlibuv/src/unix/linux-core.c
@@ -26,6 +26,7 @@
 #include "uv.h"
 #include "internal.h"
 
+#include <inttypes.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -79,16 +80,20 @@
                       unsigned int numcpus,
                       uv_cpu_info_t* ci);
 static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
-static unsigned long read_cpufreq(unsigned int cpunum);
+static uint64_t read_cpufreq(unsigned int cpunum);
 
 
 int uv__platform_loop_init(uv_loop_t* loop) {
   int fd;
 
-  fd = epoll_create1(EPOLL_CLOEXEC);
+  /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21,
+   * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
+   * architectures, we just use that instead.
+   */
+  fd = epoll_create1(O_CLOEXEC);
 
   /* epoll_create1() can fail either because it's not implemented (old kernel)
-   * or because it doesn't understand the EPOLL_CLOEXEC flag.
+   * or because it doesn't understand the O_CLOEXEC flag.
    */
   if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
     fd = epoll_create(256);
@@ -141,6 +146,7 @@
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct epoll_event*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
@@ -714,20 +720,20 @@
 static int read_times(FILE* statfile_fp,
                       unsigned int numcpus,
                       uv_cpu_info_t* ci) {
-  unsigned long clock_ticks;
   struct uv_cpu_times_s ts;
-  unsigned long user;
-  unsigned long nice;
-  unsigned long sys;
-  unsigned long idle;
-  unsigned long dummy;
-  unsigned long irq;
-  unsigned int num;
-  unsigned int len;
+  uint64_t clock_ticks;
+  uint64_t user;
+  uint64_t nice;
+  uint64_t sys;
+  uint64_t idle;
+  uint64_t dummy;
+  uint64_t irq;
+  uint64_t num;
+  uint64_t len;
   char buf[1024];
 
   clock_ticks = sysconf(_SC_CLK_TCK);
-  assert(clock_ticks != (unsigned long) -1);
+  assert(clock_ticks != (uint64_t) -1);
   assert(clock_ticks != 0);
 
   rewind(statfile_fp);
@@ -760,7 +766,8 @@
      * fields, they're not allowed in C89 mode.
      */
     if (6 != sscanf(buf + len,
-                    "%lu %lu %lu %lu %lu %lu",
+                    "%" PRIu64 " %" PRIu64 " %" PRIu64
+                    "%" PRIu64 " %" PRIu64 " %" PRIu64,
                     &user,
                     &nice,
                     &sys,
@@ -782,8 +789,8 @@
 }
 
 
-static unsigned long read_cpufreq(unsigned int cpunum) {
-  unsigned long val;
+static uint64_t read_cpufreq(unsigned int cpunum) {
+  uint64_t val;
   char buf[1024];
   FILE* fp;
 
@@ -796,7 +803,7 @@
   if (fp == NULL)
     return 0;
 
-  if (fscanf(fp, "%lu", &val) != 1)
+  if (fscanf(fp, "%" PRIu64, &val) != 1)
     val = 0;
 
   fclose(fp);
@@ -859,7 +866,8 @@
     return 0;
   }
 
-  *addresses = uv__malloc(*count * sizeof(**addresses));
+  /* Make sure the memory is initiallized to zero using calloc() */
+  *addresses = uv__calloc(*count, sizeof(**addresses));
   if (!(*addresses)) {
     freeifaddrs(addrs);
     return UV_ENOMEM;
@@ -898,11 +906,12 @@
     address = *addresses;
 
     for (i = 0; i < (*count); i++) {
-      if (strcmp(address->name, ent->ifa_name) == 0) {
+      size_t namelen = strlen(ent->ifa_name);
+      /* Alias interface share the same physical address */
+      if (strncmp(address->name, ent->ifa_name, namelen) == 0 &&
+          (address->name[namelen] == 0 || address->name[namelen] == ':')) {
         sll = (struct sockaddr_ll*)ent->ifa_addr;
         memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
-      } else {
-        memset(address->phys_addr, 0, sizeof(address->phys_addr));
       }
       address++;
     }
@@ -932,3 +941,114 @@
   prctl(PR_SET_NAME, title);  /* Only copies first 16 characters. */
 #endif
 }
+
+
+static uint64_t uv__read_proc_meminfo(const char* what) {
+  uint64_t rc;
+  ssize_t n;
+  char* p;
+  int fd;
+  char buf[4096];  /* Large enough to hold all of /proc/meminfo. */
+
+  rc = 0;
+  fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
+
+  if (fd == -1)
+    return 0;
+
+  n = read(fd, buf, sizeof(buf) - 1);
+
+  if (n <= 0)
+    goto out;
+
+  buf[n] = '\0';
+  p = strstr(buf, what);
+
+  if (p == NULL)
+    goto out;
+
+  p += strlen(what);
+
+  if (1 != sscanf(p, "%" PRIu64 " kB", &rc))
+    goto out;
+
+  rc *= 1024;
+
+out:
+
+  if (uv__close_nocheckstdio(fd))
+    abort();
+
+  return rc;
+}
+
+
+uint64_t uv_get_free_memory(void) {
+  struct sysinfo info;
+  uint64_t rc;
+
+  rc = uv__read_proc_meminfo("MemFree:");
+
+  if (rc != 0)
+    return rc;
+
+  if (0 == sysinfo(&info))
+    return (uint64_t) info.freeram * info.mem_unit;
+
+  return 0;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+  struct sysinfo info;
+  uint64_t rc;
+
+  rc = uv__read_proc_meminfo("MemTotal:");
+
+  if (rc != 0)
+    return rc;
+
+  if (0 == sysinfo(&info))
+    return (uint64_t) info.totalram * info.mem_unit;
+
+  return 0;
+}
+
+
+static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) {
+  char filename[256];
+  uint64_t rc;
+  int fd;
+  ssize_t n;
+  char buf[32];  /* Large enough to hold an encoded uint64_t. */
+
+  snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param);
+
+  rc = 0;
+  fd = uv__open_cloexec(filename, O_RDONLY);
+
+  if (fd < 0)
+    return 0;
+
+  n = read(fd, buf, sizeof(buf) - 1);
+
+  if (n > 0) {
+    buf[n] = '\0';
+    sscanf(buf, "%" PRIu64, &rc);
+  }
+
+  if (uv__close_nocheckstdio(fd))
+    abort();
+
+  return rc;
+}
+
+
+uint64_t uv_get_constrained_memory(void) {
+  /*
+   * This might return 0 if there was a problem getting the memory limit from
+   * cgroups. This is OK because a return value of 0 signifies that the memory
+   * limit is unknown.
+   */
+  return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes");
+}
diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.c b/Utilities/cmlibuv/src/unix/linux-syscalls.c
index bfd7544..5637cf9 100644
--- a/Utilities/cmlibuv/src/unix/linux-syscalls.c
+++ b/Utilities/cmlibuv/src/unix/linux-syscalls.c
@@ -187,6 +187,21 @@
 # endif
 #endif /* __NR_pwritev */
 
+#ifndef __NR_statx
+# if defined(__x86_64__)
+#  define __NR_statx 332
+# elif defined(__i386__)
+#  define __NR_statx 383
+# elif defined(__aarch64__)
+#  define __NR_statx 397
+# elif defined(__arm__)
+#  define __NR_statx (UV_SYSCALL_BASE + 397)
+# elif defined(__ppc__)
+#  define __NR_statx 383
+# elif defined(__s390__)
+#  define __NR_statx 379
+# endif
+#endif /* __NR_statx */
 
 int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
 #if defined(__i386__)
@@ -336,3 +351,19 @@
   return errno = ENOSYS, -1;
 #endif
 }
+
+
+int uv__statx(int dirfd,
+              const char* path,
+              int flags,
+              unsigned int mask,
+              struct uv__statx* statxbuf) {
+  /* __NR_statx make Android box killed by SIGSYS.
+   * That looks like a seccomp2 sandbox filter rejecting the system call.
+   */
+#if defined(__NR_statx) && !defined(__ANDROID__)
+  return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
+#else
+  return errno = ENOSYS, -1;
+#endif
+}
diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.h b/Utilities/cmlibuv/src/unix/linux-syscalls.h
index 3dfd329..7e58bfa 100644
--- a/Utilities/cmlibuv/src/unix/linux-syscalls.h
+++ b/Utilities/cmlibuv/src/unix/linux-syscalls.h
@@ -80,6 +80,36 @@
 #define UV__IN_DELETE_SELF    0x400
 #define UV__IN_MOVE_SELF      0x800
 
+struct uv__statx_timestamp {
+  int64_t tv_sec;
+  uint32_t tv_nsec;
+  int32_t unused0;
+};
+
+struct uv__statx {
+  uint32_t stx_mask;
+  uint32_t stx_blksize;
+  uint64_t stx_attributes;
+  uint32_t stx_nlink;
+  uint32_t stx_uid;
+  uint32_t stx_gid;
+  uint16_t stx_mode;
+  uint16_t unused0;
+  uint64_t stx_ino;
+  uint64_t stx_size;
+  uint64_t stx_blocks;
+  uint64_t stx_attributes_mask;
+  struct uv__statx_timestamp stx_atime;
+  struct uv__statx_timestamp stx_btime;
+  struct uv__statx_timestamp stx_ctime;
+  struct uv__statx_timestamp stx_mtime;
+  uint32_t stx_rdev_major;
+  uint32_t stx_rdev_minor;
+  uint32_t stx_dev_major;
+  uint32_t stx_dev_minor;
+  uint64_t unused1[14];
+};
+
 struct uv__inotify_event {
   int32_t wd;
   uint32_t mask;
@@ -113,5 +143,10 @@
 ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
 ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
 int uv__dup3(int oldfd, int newfd, int flags);
+int uv__statx(int dirfd,
+              const char* path,
+              int flags,
+              unsigned int mask,
+              struct uv__statx* statxbuf);
 
 #endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c
index a2a4e52..c649bb3 100644
--- a/Utilities/cmlibuv/src/unix/netbsd.c
+++ b/Utilities/cmlibuv/src/unix/netbsd.c
@@ -126,6 +126,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 int uv_resident_set_memory(size_t* rss) {
   kvm_t *kd = NULL;
   struct kinfo_proc2 *kinfo = NULL;
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index bffb58b..ffae768 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -136,6 +136,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 int uv_resident_set_memory(size_t* rss) {
   struct kinfo_proc kinfo;
   size_t page_size = getpagesize();
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index dc146e3..273ded7 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -356,6 +356,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 int uv_resident_set_memory(size_t* rss) {
   char* ascb;
   char* rax;
@@ -657,6 +662,7 @@
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct epoll_event*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c
index 9657bc9..7d97550 100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@ -213,7 +213,7 @@
   }
 
   if (err == 0)
-    uv__io_start(handle->loop, &handle->io_watcher, POLLIN | POLLOUT);
+    uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
 
 out:
   handle->delayed_error = err;
@@ -231,9 +231,6 @@
 }
 
 
-typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
-
-
 static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
                                     uv__peersockfunc func,
                                     char* buffer,
@@ -244,10 +241,13 @@
 
   addrlen = sizeof(sa);
   memset(&sa, 0, addrlen);
-  err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
+  err = uv__getsockpeername((const uv_handle_t*) handle,
+                            func,
+                            (struct sockaddr*) &sa,
+                            (int*) &addrlen);
   if (err < 0) {
     *size = 0;
-    return UV__ERR(errno);
+    return err;
   }
 
 #if defined(__linux__)
diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c
index f3181f9..a3b9f21 100644
--- a/Utilities/cmlibuv/src/unix/posix-poll.c
+++ b/Utilities/cmlibuv/src/unix/posix-poll.c
@@ -298,6 +298,8 @@
 void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   size_t i;
 
+  assert(fd >= 0);
+
   if (loop->poll_fds_iterating) {
     /* uv__io_poll is currently iterating.  Just invalidate fd.  */
     for (i = 0; i < loop->poll_fds_used; i++)
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index e9579f5..f4826bf 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -426,6 +426,11 @@
     if (n == SIGKILL || n == SIGSTOP)
       continue;  /* Can't be changed. */
 
+#if defined(__HAIKU__)
+    if (n == SIGKILLTHR)
+      continue;  /* Can't be changed. */
+#endif
+
     if (SIG_ERR != signal(n, SIG_DFL))
       continue;
 
@@ -486,6 +491,8 @@
                               UV_PROCESS_SETGID |
                               UV_PROCESS_SETUID |
                               UV_PROCESS_WINDOWS_HIDE |
+                              UV_PROCESS_WINDOWS_HIDE_CONSOLE |
+                              UV_PROCESS_WINDOWS_HIDE_GUI |
                               UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
 
   uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index 4b9123f..8121f64 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -745,13 +745,13 @@
 
   buf = req->bufs + req->write_index;
 
-  while (n > 0) {
+  do {
     len = n < buf->len ? n : buf->len;
     buf->base += len;
     buf->len -= len;
     buf += (buf->len == 0);  /* Advance to next buffer if this one is empty. */
     n -= len;
-  }
+  } while (n > 0);
 
   req->write_index = buf - req->bufs;
 
@@ -897,7 +897,7 @@
     goto error;
   }
 
-  if (n > 0 && uv__write_req_update(stream, req, n)) {
+  if (n >= 0 && uv__write_req_update(stream, req, n)) {
     uv__write_req_finish(req);
     return;  /* TODO(bnoordhuis) Start trying to write the next request. */
   }
@@ -1541,7 +1541,7 @@
   }
 
   if (written == 0 && req_size != 0)
-    return UV_EAGAIN;
+    return req.error < 0 ? req.error : UV_EAGAIN;
   else
     return written;
 }
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index aac6504..0cd25c1 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -121,6 +121,7 @@
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct port_event*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
@@ -138,8 +139,10 @@
   if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
     return UV__ERR(errno);
 
-  if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
+  if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) {
+    perror("(libuv) port_dissociate()");
     abort();
+  }
 
   return 0;
 }
@@ -177,8 +180,14 @@
     w = QUEUE_DATA(q, uv__io_t, watcher_queue);
     assert(w->pevents != 0);
 
-    if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0))
+    if (port_associate(loop->backend_fd,
+                       PORT_SOURCE_FD,
+                       w->fd,
+                       w->pevents,
+                       0)) {
+      perror("(libuv) port_associate()");
       abort();
+    }
 
     w->events = w->pevents;
   }
@@ -222,10 +231,12 @@
       /* Work around another kernel bug: port_getn() may return events even
        * on error.
        */
-      if (errno == EINTR || errno == ETIME)
+      if (errno == EINTR || errno == ETIME) {
         saved_errno = errno;
-      else
+      } else {
+        perror("(libuv) port_getn()");
         abort();
+      }
     }
 
     /* Update loop->time unconditionally. It's tempting to skip the update when
@@ -373,6 +384,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   (void) getloadavg(avg, 3);
 }
diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c
index 2982851..8cedcd6 100644
--- a/Utilities/cmlibuv/src/unix/tcp.c
+++ b/Utilities/cmlibuv/src/unix/tcp.c
@@ -82,7 +82,7 @@
         handle->flags |= flags;
         return 0;
       }
-      
+
       /* Query to see if tcp socket is bound. */
       slen = sizeof(saddr);
       memset(&saddr, 0, sizeof(saddr));
@@ -235,12 +235,16 @@
   if (r == -1 && errno != 0) {
     if (errno == EINPROGRESS)
       ; /* not an error */
-    else if (errno == ECONNREFUSED)
-    /* If we get a ECONNREFUSED wait until the next tick to report the
-     * error. Solaris wants to report immediately--other unixes want to
-     * wait.
+    else if (errno == ECONNREFUSED
+#if defined(__OpenBSD__)
+      || errno == EINVAL
+#endif
+      )
+    /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
+     * next tick to report the error. Solaris and OpenBSD wants to report
+     * immediately -- other unixes want to wait.
      */
-      handle->delayed_error = UV__ERR(errno);
+      handle->delayed_error = UV__ERR(ECONNREFUSED);
     else
       return UV__ERR(errno);
   }
@@ -279,44 +283,28 @@
 int uv_tcp_getsockname(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  socklen_t socklen;
 
   if (handle->delayed_error)
     return handle->delayed_error;
 
-  if (uv__stream_fd(handle) < 0)
-    return UV_EINVAL;  /* FIXME(bnoordhuis) UV_EBADF */
-
-  /* sizeof(socklen_t) != sizeof(int) on some systems. */
-  socklen = (socklen_t) *namelen;
-
-  if (getsockname(uv__stream_fd(handle), name, &socklen))
-    return UV__ERR(errno);
-
-  *namelen = (int) socklen;
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen);
 }
 
 
 int uv_tcp_getpeername(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  socklen_t socklen;
 
   if (handle->delayed_error)
     return handle->delayed_error;
 
-  if (uv__stream_fd(handle) < 0)
-    return UV_EINVAL;  /* FIXME(bnoordhuis) UV_EBADF */
-
-  /* sizeof(socklen_t) != sizeof(int) on some systems. */
-  socklen = (socklen_t) *namelen;
-
-  if (getpeername(uv__stream_fd(handle), name, &socklen))
-    return UV__ERR(errno);
-
-  *namelen = (int) socklen;
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen);
 }
 
 
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index 2900470..cd0b7aa 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -48,8 +48,10 @@
 STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
 #endif
 
-/* Note: guard clauses should match uv_barrier_t's in include/uv/uv-unix.h. */
-#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
+/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
+#if defined(_AIX) || \
+    defined(__OpenBSD__) || \
+    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
 int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
   struct _uv_barrier* b;
   int rc;
@@ -176,8 +178,21 @@
   if (lim.rlim_cur != RLIM_INFINITY) {
     /* pthread_attr_setstacksize() expects page-aligned values. */
     lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
-    if (lim.rlim_cur >= PTHREAD_STACK_MIN)
-      return lim.rlim_cur;
+
+    /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
+     * too small to safely receive signals on.
+     *
+     * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
+     * the largest MINSIGSTKSZ of the architectures that musl supports) so
+     * let's use that as a lower bound.
+     *
+     * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
+     * is between 28 and 133 KB when compiling against glibc, depending
+     * on the architecture.
+     */
+    if (lim.rlim_cur >= 8192)
+      if (lim.rlim_cur >= PTHREAD_STACK_MIN)
+        return lim.rlim_cur;
   }
 #endif
 
@@ -192,13 +207,36 @@
 
 
 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
+  uv_thread_options_t params;
+  params.flags = UV_THREAD_NO_FLAGS;
+  return uv_thread_create_ex(tid, &params, entry, arg);
+}
+
+int uv_thread_create_ex(uv_thread_t* tid,
+                        const uv_thread_options_t* params,
+                        void (*entry)(void *arg),
+                        void *arg) {
   int err;
-  size_t stack_size;
   pthread_attr_t* attr;
   pthread_attr_t attr_storage;
+  size_t pagesize;
+  size_t stack_size;
+
+  stack_size =
+      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
 
   attr = NULL;
-  stack_size = thread_stack_size();
+  if (stack_size == 0) {
+    stack_size = thread_stack_size();
+  } else {
+    pagesize = (size_t)getpagesize();
+    /* Round up to the nearest page boundary. */
+    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
+#ifdef PTHREAD_STACK_MIN
+    if (stack_size < PTHREAD_STACK_MIN)
+      stack_size = PTHREAD_STACK_MIN;
+#endif
+  }
 
   if (stack_size > 0) {
     attr = &attr_storage;
@@ -778,7 +816,9 @@
     return UV_ETIMEDOUT;
 
   abort();
+#ifndef __SUNPRO_C
   return UV_EINVAL;  /* Satisfy the compiler. */
+#endif
 }
 
 
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index ec337ec..b578e7b 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -30,6 +30,7 @@
 #if defined(__MVS__)
 #include <xti.h>
 #endif
+#include <sys/un.h>
 
 #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
 # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@ -227,9 +228,22 @@
     assert(req != NULL);
 
     memset(&h, 0, sizeof h);
-    h.msg_name = &req->addr;
-    h.msg_namelen = (req->addr.ss_family == AF_INET6 ?
-      sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
+    if (req->addr.ss_family == AF_UNSPEC) {
+      h.msg_name = NULL;
+      h.msg_namelen = 0;
+    } else {
+      h.msg_name = &req->addr;
+      if (req->addr.ss_family == AF_INET6)
+        h.msg_namelen = sizeof(struct sockaddr_in6);
+      else if (req->addr.ss_family == AF_INET)
+        h.msg_namelen = sizeof(struct sockaddr_in);
+      else if (req->addr.ss_family == AF_UNIX)
+        h.msg_namelen = sizeof(struct sockaddr_un);
+      else {
+        assert(0 && "unsupported address family");
+        abort();
+      }
+    }
     h.msg_iov = (struct iovec*) req->bufs;
     h.msg_iovlen = req->nbufs;
 
@@ -263,16 +277,30 @@
  * are different from the BSDs: it _shares_ the port rather than steal it
  * from the current listener.  While useful, it's not something we can emulate
  * on other platforms so we don't enable it.
+ *
+ * zOS does not support getsockname with SO_REUSEPORT option when using
+ * AF_UNIX.
  */
 static int uv__set_reuse(int fd) {
   int yes;
-
-#if defined(SO_REUSEPORT) && !defined(__linux__)
   yes = 1;
+
+#if defined(SO_REUSEPORT) && defined(__MVS__)
+  struct sockaddr_in sockfd;
+  unsigned int sockfd_len = sizeof(sockfd);
+  if (getsockname(fd, (struct sockaddr*) &sockfd, &sockfd_len) == -1)
+      return UV__ERR(errno);
+  if (sockfd.sin_family == AF_UNIX) {
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
+      return UV__ERR(errno);
+  } else {
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
+       return UV__ERR(errno);
+  }
+#elif defined(SO_REUSEPORT) && !defined(__linux__)
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
     return UV__ERR(errno);
 #else
-  yes = 1;
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
     return UV__ERR(errno);
 #endif
@@ -383,6 +411,50 @@
 }
 
 
+int uv__udp_connect(uv_udp_t* handle,
+                    const struct sockaddr* addr,
+                    unsigned int addrlen) {
+  int err;
+
+  err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+  if (err)
+    return err;
+
+  do {
+    errno = 0;
+    err = connect(handle->io_watcher.fd, addr, addrlen);
+  } while (err == -1 && errno == EINTR);
+
+  if (err)
+    return UV__ERR(errno);
+
+  handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+  return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+    int r;
+    struct sockaddr addr;
+
+    memset(&addr, 0, sizeof(addr));
+
+    addr.sa_family = AF_UNSPEC;
+
+    do {
+      errno = 0;
+      r = connect(handle->io_watcher.fd, &addr, sizeof(addr));
+    } while (r == -1 && errno == EINTR);
+
+    if (r == -1 && errno != EAFNOSUPPORT)
+      return UV__ERR(errno);
+
+    handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+    return 0;
+}
+
+
 int uv__udp_send(uv_udp_send_t* req,
                  uv_udp_t* handle,
                  const uv_buf_t bufs[],
@@ -395,9 +467,11 @@
 
   assert(nbufs > 0);
 
-  err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
-  if (err)
-    return err;
+  if (addr) {
+    err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+    if (err)
+      return err;
+  }
 
   /* It's legal for send_queue_count > 0 even when the write_queue is empty;
    * it means there are error-state requests in the write_completed_queue that
@@ -407,7 +481,10 @@
 
   uv__req_init(handle->loop, req, UV_UDP_SEND);
   assert(addrlen <= sizeof(req->addr));
-  memcpy(&req->addr, addr, addrlen);
+  if (addr == NULL)
+    req->addr.ss_family = AF_UNSPEC;
+  else
+    memcpy(&req->addr, addr, addrlen);
   req->send_cb = send_cb;
   req->handle = handle;
   req->nbufs = nbufs;
@@ -459,9 +536,13 @@
   if (handle->send_queue_count != 0)
     return UV_EAGAIN;
 
-  err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
-  if (err)
-    return err;
+  if (addr) {
+    err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+    if (err)
+      return err;
+  } else {
+    assert(handle->flags & UV_HANDLE_UDP_CONNECTED);
+  }
 
   memset(&h, 0, sizeof h);
   h.msg_name = (struct sockaddr*) addr;
@@ -608,6 +689,7 @@
   uv__io_init(&handle->io_watcher, uv__udp_io, fd);
   QUEUE_INIT(&handle->write_queue);
   QUEUE_INIT(&handle->write_completed_queue);
+
   return 0;
 }
 
@@ -636,6 +718,9 @@
     return err;
 
   handle->io_watcher.fd = sock;
+  if (uv__udp_is_connected(handle))
+    handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
   return 0;
 }
 
@@ -743,13 +828,17 @@
                         IPV6_UNICAST_HOPS,
                         &ttl,
                         sizeof(ttl));
-#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
-          defined(__MVS__) */
+
+#else /* !(defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
+           defined(__MVS__)) */
 
   return uv__setsockopt_maybe_char(handle,
                                    IP_TTL,
                                    IPV6_UNICAST_HOPS,
                                    ttl);
+
+#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
+          defined(__MVS__) */
 }
 
 
@@ -851,23 +940,24 @@
   return 0;
 }
 
+int uv_udp_getpeername(const uv_udp_t* handle,
+                       struct sockaddr* name,
+                       int* namelen) {
+
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen);
+}
 
 int uv_udp_getsockname(const uv_udp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  socklen_t socklen;
 
-  if (handle->io_watcher.fd == -1)
-    return UV_EINVAL;  /* FIXME(bnoordhuis) UV_EBADF */
-
-  /* sizeof(socklen_t) != sizeof(int) on some systems. */
-  socklen = (socklen_t) *namelen;
-
-  if (getsockname(handle->io_watcher.fd, name, &socklen))
-    return UV__ERR(errno);
-
-  *namelen = (int) socklen;
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen);
 }
 
 
diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c
index 907ebf2..f4853d6 100644
--- a/Utilities/cmlibuv/src/uv-common.c
+++ b/Utilities/cmlibuv/src/uv-common.c
@@ -34,6 +34,7 @@
 # include <malloc.h> /* malloc */
 #else
 # include <net/if.h> /* if_nametoindex */
+# include <sys/un.h> /* AF_UNIX, sockaddr_un */
 #endif
 
 
@@ -223,6 +224,9 @@
   memset(addr, 0, sizeof(*addr));
   addr->sin6_family = AF_INET6;
   addr->sin6_port = htons(port);
+#ifdef SIN6_LEN
+  addr->sin6_len = sizeof(*addr);
+#endif
 
   zone_index = strchr(ip, '%');
   if (zone_index != NULL) {
@@ -315,17 +319,20 @@
 }
 
 
-int uv_udp_send(uv_udp_send_t* req,
-                uv_udp_t* handle,
-                const uv_buf_t bufs[],
-                unsigned int nbufs,
-                const struct sockaddr* addr,
-                uv_udp_send_cb send_cb) {
+int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
   unsigned int addrlen;
 
   if (handle->type != UV_UDP)
     return UV_EINVAL;
 
+  /* Disconnect the handle */
+  if (addr == NULL) {
+    if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
+      return UV_ENOTCONN;
+
+    return uv__udp_disconnect(handle);
+  }
+
   if (addr->sa_family == AF_INET)
     addrlen = sizeof(struct sockaddr_in);
   else if (addr->sa_family == AF_INET6)
@@ -333,6 +340,70 @@
   else
     return UV_EINVAL;
 
+  if (handle->flags & UV_HANDLE_UDP_CONNECTED)
+    return UV_EISCONN;
+
+  return uv__udp_connect(handle, addr, addrlen);
+}
+
+
+int uv__udp_is_connected(uv_udp_t* handle) {
+  struct sockaddr_storage addr;
+  int addrlen;
+  if (handle->type != UV_UDP)
+    return 0;
+
+  addrlen = sizeof(addr);
+  if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+    return 0;
+
+  return addrlen > 0;
+}
+
+
+int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
+  unsigned int addrlen;
+
+  if (handle->type != UV_UDP)
+    return UV_EINVAL;
+
+  if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
+    return UV_EISCONN;
+
+  if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
+    return UV_EDESTADDRREQ;
+
+  if (addr != NULL) {
+    if (addr->sa_family == AF_INET)
+      addrlen = sizeof(struct sockaddr_in);
+    else if (addr->sa_family == AF_INET6)
+      addrlen = sizeof(struct sockaddr_in6);
+#if defined(AF_UNIX) && !defined(_WIN32)
+    else if (addr->sa_family == AF_UNIX)
+      addrlen = sizeof(struct sockaddr_un);
+#endif
+    else
+      return UV_EINVAL;
+  } else {
+    addrlen = 0;
+  }
+
+  return addrlen;
+}
+
+
+int uv_udp_send(uv_udp_send_t* req,
+                uv_udp_t* handle,
+                const uv_buf_t bufs[],
+                unsigned int nbufs,
+                const struct sockaddr* addr,
+                uv_udp_send_cb send_cb) {
+  int addrlen;
+
+  addrlen = uv__udp_check_before_send(handle, addr);
+  if (addrlen < 0)
+    return addrlen;
+
   return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
 }
 
@@ -341,17 +412,11 @@
                     const uv_buf_t bufs[],
                     unsigned int nbufs,
                     const struct sockaddr* addr) {
-  unsigned int addrlen;
+  int addrlen;
 
-  if (handle->type != UV_UDP)
-    return UV_EINVAL;
-
-  if (addr->sa_family == AF_INET)
-    addrlen = sizeof(struct sockaddr_in);
-  else if (addr->sa_family == AF_INET6)
-    addrlen = sizeof(struct sockaddr_in6);
-  else
-    return UV_EINVAL;
+  addrlen = uv__udp_check_before_send(handle, addr);
+  if (addrlen < 0)
+    return addrlen;
 
   return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
 }
@@ -573,37 +638,66 @@
   dent = dents[(*nbufs)++];
 
   ent->name = dent->d_name;
+  ent->type = uv__fs_get_dirent_type(dent);
+
+  return 0;
+}
+
+uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
+  uv_dirent_type_t type;
+
 #ifdef HAVE_DIRENT_TYPES
   switch (dent->d_type) {
     case UV__DT_DIR:
-      ent->type = UV_DIRENT_DIR;
+      type = UV_DIRENT_DIR;
       break;
     case UV__DT_FILE:
-      ent->type = UV_DIRENT_FILE;
+      type = UV_DIRENT_FILE;
       break;
     case UV__DT_LINK:
-      ent->type = UV_DIRENT_LINK;
+      type = UV_DIRENT_LINK;
       break;
     case UV__DT_FIFO:
-      ent->type = UV_DIRENT_FIFO;
+      type = UV_DIRENT_FIFO;
       break;
     case UV__DT_SOCKET:
-      ent->type = UV_DIRENT_SOCKET;
+      type = UV_DIRENT_SOCKET;
       break;
     case UV__DT_CHAR:
-      ent->type = UV_DIRENT_CHAR;
+      type = UV_DIRENT_CHAR;
       break;
     case UV__DT_BLOCK:
-      ent->type = UV_DIRENT_BLOCK;
+      type = UV_DIRENT_BLOCK;
       break;
     default:
-      ent->type = UV_DIRENT_UNKNOWN;
+      type = UV_DIRENT_UNKNOWN;
   }
 #else
-  ent->type = UV_DIRENT_UNKNOWN;
+  type = UV_DIRENT_UNKNOWN;
 #endif
 
-  return 0;
+  return type;
+}
+
+void uv__fs_readdir_cleanup(uv_fs_t* req) {
+  uv_dir_t* dir;
+  uv_dirent_t* dirents;
+  int i;
+
+  if (req->ptr == NULL)
+    return;
+
+  dir = req->ptr;
+  dirents = dir->dirents;
+  req->ptr = NULL;
+
+  if (dirents == NULL)
+    return;
+
+  for (i = 0; i < req->result; ++i) {
+    uv__free((char*) dirents[i].name);
+    dirents[i].name = NULL;
+  }
 }
 
 
diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h
index 15ac4d0..f788161 100644
--- a/Utilities/cmlibuv/src/uv-common.h
+++ b/Utilities/cmlibuv/src/uv-common.h
@@ -103,6 +103,7 @@
 
   /* Only used by uv_udp_t handles. */
   UV_HANDLE_UDP_PROCESSING              = 0x01000000,
+  UV_HANDLE_UDP_CONNECTED               = 0x02000000,
 
   /* Only used by uv_pipe_t handles. */
   UV_HANDLE_NON_OVERLAPPED_PIPE         = 0x01000000,
@@ -142,6 +143,14 @@
                  unsigned int  addrlen,
                  unsigned int flags);
 
+int uv__udp_connect(uv_udp_t* handle,
+                    const struct sockaddr* addr,
+                    unsigned int addrlen);
+
+int uv__udp_disconnect(uv_udp_t* handle);
+
+int uv__udp_is_connected(uv_udp_t* handle);
+
 int uv__udp_send(uv_udp_send_t* req,
                  uv_udp_t* handle,
                  const uv_buf_t bufs[],
@@ -184,6 +193,8 @@
 int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
 
 void uv__fs_scandir_cleanup(uv_fs_t* req);
+void uv__fs_readdir_cleanup(uv_fs_t* req);
+uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent);
 
 int uv__next_timeout(const uv_loop_t* loop);
 void uv__run_timers(uv_loop_t* loop);
diff --git a/Utilities/cmlibuv/src/uv-data-getter-setters.c b/Utilities/cmlibuv/src/uv-data-getter-setters.c
index b7fcd4a..c302566 100644
--- a/Utilities/cmlibuv/src/uv-data-getter-setters.c
+++ b/Utilities/cmlibuv/src/uv-data-getter-setters.c
@@ -36,7 +36,7 @@
   case UV_REQ_TYPE_MAX:
   case UV_UNKNOWN_REQ:
   default: /* UV_REQ_TYPE_PRIVATE */
-     return NULL;
+    break;
   }
   return NULL;
 }
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 58309c6..e9d0a58 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -627,3 +627,26 @@
 int uv_cpumask_size(void) {
   return (int)(sizeof(DWORD_PTR) * 8);
 }
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen,
+                        int delayed_error) {
+
+  int result;
+  uv_os_fd_t fd;
+
+  result = uv_fileno(handle, &fd);
+  if (result != 0)
+    return result;
+
+  if (delayed_error)
+    return uv_translate_sys_error(delayed_error);
+
+  result = func((SOCKET) fd, name, namelen);
+  if (result != 0)
+    return uv_translate_sys_error(WSAGetLastError());
+
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 65d936b..9e2f084 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -1125,6 +1125,137 @@
     uv__free(dirents);
 }
 
+void fs__opendir(uv_fs_t* req) {
+  WCHAR* pathw;
+  size_t len;
+  const WCHAR* fmt;
+  WCHAR* find_path;
+  uv_dir_t* dir;
+
+  pathw = req->file.pathw;
+  dir = NULL;
+  find_path = NULL;
+
+  /* Figure out whether path is a file or a directory. */
+  if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
+    SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
+    goto error;
+  }
+
+  dir = uv__malloc(sizeof(*dir));
+  if (dir == NULL) {
+    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+    goto error;
+  }
+
+  len = wcslen(pathw);
+
+  if (len == 0)
+    fmt = L"./*";
+  else if (IS_SLASH(pathw[len - 1]))
+    fmt = L"%s*";
+  else
+    fmt = L"%s\\*";
+
+  find_path = uv__malloc(sizeof(WCHAR) * (len + 4));
+  if (find_path == NULL) {
+    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+    goto error;
+  }
+
+  _snwprintf(find_path, len + 3, fmt, pathw);
+  dir->dir_handle = FindFirstFileW(find_path, &dir->find_data);
+  uv__free(find_path);
+  find_path = NULL;
+  if (dir->dir_handle == INVALID_HANDLE_VALUE &&
+      GetLastError() != ERROR_FILE_NOT_FOUND) {
+    SET_REQ_WIN32_ERROR(req, GetLastError());
+    goto error;
+  }
+
+  dir->need_find_call = FALSE;
+  req->ptr = dir;
+  SET_REQ_RESULT(req, 0);
+  return;
+
+error:
+  uv__free(dir);
+  uv__free(find_path);
+  req->ptr = NULL;
+}
+
+void fs__readdir(uv_fs_t* req) {
+  uv_dir_t* dir;
+  uv_dirent_t* dirents;
+  uv__dirent_t dent;
+  unsigned int dirent_idx;
+  PWIN32_FIND_DATAW find_data;
+  unsigned int i;
+  int r;
+
+  req->flags |= UV_FS_FREE_PTR;
+  dir = req->ptr;
+  dirents = dir->dirents;
+  memset(dirents, 0, dir->nentries * sizeof(*dir->dirents));
+  find_data = &dir->find_data;
+  dirent_idx = 0;
+
+  while (dirent_idx < dir->nentries) {
+    if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) {
+      if (GetLastError() == ERROR_NO_MORE_FILES)
+        break;
+      goto error;
+    }
+
+    /* Skip "." and ".." entries. */
+    if (find_data->cFileName[0] == L'.' &&
+        (find_data->cFileName[1] == L'\0' ||
+        (find_data->cFileName[1] == L'.' &&
+        find_data->cFileName[2] == L'\0'))) {
+      dir->need_find_call = TRUE;
+      continue;
+    }
+
+    r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName,
+                                  -1,
+                                  (char**) &dirents[dirent_idx].name);
+    if (r != 0)
+      goto error;
+
+    /* Copy file type. */
+    if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+      dent.d_type = UV__DT_DIR;
+    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
+      dent.d_type = UV__DT_LINK;
+    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0)
+      dent.d_type = UV__DT_CHAR;
+    else
+      dent.d_type = UV__DT_FILE;
+
+    dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent);
+    dir->need_find_call = TRUE;
+    ++dirent_idx;
+  }
+
+  SET_REQ_RESULT(req, dirent_idx);
+  return;
+
+error:
+  SET_REQ_WIN32_ERROR(req, GetLastError());
+  for (i = 0; i < dirent_idx; ++i) {
+    uv__free((char*) dirents[i].name);
+    dirents[i].name = NULL;
+  }
+}
+
+void fs__closedir(uv_fs_t* req) {
+  uv_dir_t* dir;
+
+  dir = req->ptr;
+  FindClose(dir->dir_handle);
+  uv__free(req->ptr);
+  SET_REQ_RESULT(req, 0);
+}
 
 INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
     int do_lstat) {
@@ -2039,6 +2170,9 @@
     XX(MKDTEMP, mkdtemp)
     XX(RENAME, rename)
     XX(SCANDIR, scandir)
+    XX(READDIR, readdir)
+    XX(OPENDIR, opendir)
+    XX(CLOSEDIR, closedir)
     XX(LINK, link)
     XX(SYMLINK, symlink)
     XX(READLINK, readlink)
@@ -2080,6 +2214,8 @@
   if (req->flags & UV_FS_FREE_PTR) {
     if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
       uv__fs_scandir_cleanup(req);
+    else if (req->fs_type == UV_FS_READDIR)
+      uv__fs_readdir_cleanup(req);
     else
       uv__free(req->ptr);
   }
@@ -2247,6 +2383,45 @@
   POST;
 }
 
+int uv_fs_opendir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  const char* path,
+                  uv_fs_cb cb) {
+  int err;
+
+  INIT(UV_FS_OPENDIR);
+  err = fs__capture_path(req, path, NULL, cb != NULL);
+  if (err)
+    return uv_translate_sys_error(err);
+  POST;
+}
+
+int uv_fs_readdir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  uv_dir_t* dir,
+                  uv_fs_cb cb) {
+  INIT(UV_FS_READDIR);
+
+  if (dir == NULL ||
+      dir->dirents == NULL ||
+      dir->dir_handle == INVALID_HANDLE_VALUE) {
+    return UV_EINVAL;
+  }
+
+  req->ptr = dir;
+  POST;
+}
+
+int uv_fs_closedir(uv_loop_t* loop,
+                   uv_fs_t* req,
+                   uv_dir_t* dir,
+                   uv_fs_cb cb) {
+  INIT(UV_FS_CLOSEDIR);
+  if (dir == NULL)
+    return UV_EINVAL;
+  req->ptr = dir;
+  POST;
+}
 
 int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
     const char* new_path, uv_fs_cb cb) {
diff --git a/Utilities/cmlibuv/src/win/handle.c b/Utilities/cmlibuv/src/win/handle.c
index 9d76c3f..61e4df6 100644
--- a/Utilities/cmlibuv/src/win/handle.c
+++ b/Utilities/cmlibuv/src/win/handle.c
@@ -139,7 +139,6 @@
     case UV_FS_POLL:
       uv__fs_poll_close((uv_fs_poll_t*) handle);
       uv__handle_closing(handle);
-      uv_want_endgame(loop, handle);
       return;
 
     default:
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 206ab5f..f7d8ccf 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -276,6 +276,14 @@
 int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
 int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
 
+typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen,
+                        int delayed_error);
+
 
 /*
  * Process stdio handles.
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index 3ce5548..f2cb527 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -809,44 +809,24 @@
 int uv_tcp_getsockname(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  int result;
 
-  if (handle->socket == INVALID_SOCKET) {
-    return UV_EINVAL;
-  }
-
-  if (handle->delayed_error) {
-    return uv_translate_sys_error(handle->delayed_error);
-  }
-
-  result = getsockname(handle->socket, name, namelen);
-  if (result != 0) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
-
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen,
+                             handle->delayed_error);
 }
 
 
 int uv_tcp_getpeername(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  int result;
 
-  if (handle->socket == INVALID_SOCKET) {
-    return UV_EINVAL;
-  }
-
-  if (handle->delayed_error) {
-    return uv_translate_sys_error(handle->delayed_error);
-  }
-
-  result = getpeername(handle->socket, name, namelen);
-  if (result != 0) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
-
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen,
+                             handle->delayed_error);
 }
 
 
diff --git a/Utilities/cmlibuv/src/win/thread.c b/Utilities/cmlibuv/src/win/thread.c
index fd4b7c9..89c53ad 100644
--- a/Utilities/cmlibuv/src/win/thread.c
+++ b/Utilities/cmlibuv/src/win/thread.c
@@ -112,9 +112,34 @@
 
 
 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
+  uv_thread_options_t params;
+  params.flags = UV_THREAD_NO_FLAGS;
+  return uv_thread_create_ex(tid, &params, entry, arg);
+}
+
+int uv_thread_create_ex(uv_thread_t* tid,
+                        const uv_thread_options_t* params,
+                        void (*entry)(void *arg),
+                        void *arg) {
   struct thread_ctx* ctx;
   int err;
   HANDLE thread;
+  SYSTEM_INFO sysinfo;
+  size_t stack_size;
+  size_t pagesize;
+
+  stack_size =
+      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
+
+  if (stack_size != 0) {
+    GetNativeSystemInfo(&sysinfo);
+    pagesize = (size_t)sysinfo.dwPageSize;
+    /* Round up to the nearest page boundary. */
+    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
+
+    if ((unsigned)stack_size != stack_size)
+      return UV_EINVAL;
+  }
 
   ctx = uv__malloc(sizeof(*ctx));
   if (ctx == NULL)
@@ -126,7 +151,7 @@
   /* Create the thread in suspended state so we have a chance to pass
    * its own creation handle to it */
   thread = (HANDLE) _beginthreadex(NULL,
-                                   0,
+                                   (unsigned)stack_size,
                                    uv__thread_start,
                                    ctx,
                                    CREATE_SUSPENDED,
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index f38e9a8..a98fe26 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -736,8 +736,8 @@
       /* Ignore keyup events, unless the left alt key was held and a valid
        * unicode character was emitted. */
       if (!KEV.bKeyDown &&
-          KEV.wVirtualKeyCode != VK_MENU &&
-          KEV.uChar.UnicodeChar != 0) {
+          (KEV.wVirtualKeyCode != VK_MENU ||
+           KEV.uChar.UnicodeChar == 0)) {
         continue;
       }
 
diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c
index 37df849..8aeeab3 100644
--- a/Utilities/cmlibuv/src/win/udp.c
+++ b/Utilities/cmlibuv/src/win/udp.c
@@ -36,22 +36,27 @@
 
 /* A zero-size buffer for use by uv_udp_read */
 static char uv_zero_[] = "";
+int uv_udp_getpeername(const uv_udp_t* handle,
+                       struct sockaddr* name,
+                       int* namelen) {
+
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen,
+                             0);
+}
+
 
 int uv_udp_getsockname(const uv_udp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  int result;
 
-  if (handle->socket == INVALID_SOCKET) {
-    return UV_EINVAL;
-  }
-
-  result = getsockname(handle->socket, name, namelen);
-  if (result != 0) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
-
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen,
+                             0);
 }
 
 
@@ -784,6 +789,18 @@
 }
 
 
+int uv__udp_is_bound(uv_udp_t* handle) {
+  struct sockaddr_storage addr;
+  int addrlen;
+
+  addrlen = sizeof(addr);
+  if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+    return 0;
+
+  return addrlen > 0;
+}
+
+
 int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
   WSAPROTOCOL_INFOW protocol_info;
   int opt_len;
@@ -803,7 +820,16 @@
                           handle,
                           sock,
                           protocol_info.iAddressFamily);
-  return uv_translate_sys_error(err);
+  if (err)
+    return uv_translate_sys_error(err);
+
+  if (uv__udp_is_bound(handle))
+    handle->flags |= UV_HANDLE_BOUND;
+
+  if (uv__udp_is_connected(handle))
+    handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+  return 0;
 }
 
 
@@ -880,6 +906,50 @@
 }
 
 
+int uv__udp_connect(uv_udp_t* handle,
+                    const struct sockaddr* addr,
+                    unsigned int addrlen) {
+  const struct sockaddr* bind_addr;
+  int err;
+
+  if (!(handle->flags & UV_HANDLE_BOUND)) {
+    if (addrlen == sizeof(uv_addr_ip4_any_))
+      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
+    else if (addrlen == sizeof(uv_addr_ip6_any_))
+      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
+    else
+      return UV_EINVAL;
+
+    err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+    if (err)
+      return uv_translate_sys_error(err);
+  }
+
+  err = connect(handle->socket, addr, addrlen);
+  if (err)
+    return uv_translate_sys_error(err);
+
+  handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+  return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+    int err;
+    struct sockaddr addr;
+
+    memset(&addr, 0, sizeof(addr));
+
+    err = connect(handle->socket, &addr, sizeof(addr));
+    if (err)
+      return uv_translate_sys_error(err);
+
+    handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+    return 0;
+}
+
+
 /* This function is an egress point, i.e. it returns libuv errors rather than
  * system errors.
  */
@@ -900,6 +970,7 @@
       bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
     else
       return UV_EINVAL;
+
     err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
     if (err)
       return uv_translate_sys_error(err);
@@ -925,9 +996,11 @@
 
   assert(nbufs > 0);
 
-  err = uv__convert_to_localhost_if_unspecified(addr, &converted);
-  if (err)
-    return err;
+  if (addr != NULL) {
+    err = uv__convert_to_localhost_if_unspecified(addr, &converted);
+    if (err)
+      return err;
+  }
 
   /* Already sending a message.*/
   if (handle->send_queue_count != 0)
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index 9237891..7ca8321 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -59,13 +59,6 @@
 # define UNLEN 256
 #endif
 
-/*
-  Max hostname length. The Windows gethostname() documentation states that 256
-  bytes will always be large enough to hold the null-terminated hostname.
-*/
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 256
-#endif
 
 /* Maximum environment variable size, including the terminating null */
 #define MAX_ENV_VAR_LENGTH 32767
@@ -327,6 +320,11 @@
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 uv_pid_t uv_os_getpid(void) {
   return GetCurrentProcessId();
 }
@@ -684,12 +682,9 @@
                            NULL,
                            (BYTE*)&cpu_brand,
                            &cpu_brand_size);
-    if (err != ERROR_SUCCESS) {
-      RegCloseKey(processor_key);
-      goto error;
-    }
-
     RegCloseKey(processor_key);
+    if (err != ERROR_SUCCESS)
+      goto error;
 
     cpu_info = &cpu_infos[i];
     cpu_info->speed = cpu_speed;
@@ -713,9 +708,11 @@
   return 0;
 
  error:
-  /* This is safe because the cpu_infos array is zeroed on allocation. */
-  for (i = 0; i < cpu_count; i++)
-    uv__free(cpu_infos[i].model);
+  if (cpu_infos != NULL) {
+    /* This is safe because the cpu_infos array is zeroed on allocation. */
+    for (i = 0; i < cpu_count; i++)
+      uv__free(cpu_infos[i].model);
+  }
 
   uv__free(cpu_infos);
   uv__free(sppi);
@@ -1510,7 +1507,7 @@
 
 
 int uv_os_gethostname(char* buffer, size_t* size) {
-  char buf[MAXHOSTNAMELEN + 1];
+  char buf[UV_MAXHOSTNAMESIZE];
   size_t len;
 
   if (buffer == NULL || size == NULL || *size == 0)
@@ -1634,6 +1631,10 @@
      https://github.com/gagern/gnulib/blob/master/lib/uname.c */
   OSVERSIONINFOW os_info;
   SYSTEM_INFO system_info;
+  HKEY registry_key;
+  WCHAR product_name_w[256];
+  DWORD product_name_w_size;
+  int version_size;
   int processor_level;
   int r;
 
@@ -1658,16 +1659,56 @@
   }
 
   /* Populate the version field. */
-  if (WideCharToMultiByte(CP_UTF8,
-                          0,
-                          os_info.szCSDVersion,
-                          -1,
-                          buffer->version,
-                          sizeof(buffer->version),
-                          NULL,
-                          NULL) == 0) {
-    r = uv_translate_sys_error(GetLastError());
-    goto error;
+  version_size = 0;
+  r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+                    0,
+                    KEY_QUERY_VALUE,
+                    &registry_key);
+
+  if (r == ERROR_SUCCESS) {
+    product_name_w_size = sizeof(product_name_w);
+    r = RegGetValueW(registry_key,
+                     NULL,
+                     L"ProductName",
+                     RRF_RT_REG_SZ,
+                     NULL,
+                     (PVOID) product_name_w,
+                     &product_name_w_size);
+    RegCloseKey(registry_key);
+
+    if (r == ERROR_SUCCESS) {
+      version_size = WideCharToMultiByte(CP_UTF8,
+                                         0,
+                                         product_name_w,
+                                         -1,
+                                         buffer->version,
+                                         sizeof(buffer->version),
+                                         NULL,
+                                         NULL);
+      if (version_size == 0) {
+        r = uv_translate_sys_error(GetLastError());
+        goto error;
+      }
+    }
+  }
+
+  /* Append service pack information to the version if present. */
+  if (os_info.szCSDVersion[0] != L'\0') {
+    if (version_size > 0)
+      buffer->version[version_size - 1] = ' ';
+
+    if (WideCharToMultiByte(CP_UTF8,
+                            0,
+                            os_info.szCSDVersion,
+                            -1,
+                            buffer->version + version_size,
+                            sizeof(buffer->version) - version_size,
+                            NULL,
+                            NULL) == 0) {
+      r = uv_translate_sys_error(GetLastError());
+      goto error;
+    }
   }
 
   /* Populate the sysname field. */
@@ -1744,3 +1785,20 @@
   buffer->machine[0] = '\0';
   return r;
 }
+
+int uv_gettimeofday(uv_timeval64_t* tv) {
+  /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */
+  const uint64_t epoch = (uint64_t) 116444736000000000ULL;
+  FILETIME file_time;
+  ULARGE_INTEGER ularge;
+
+  if (tv == NULL)
+    return UV_EINVAL;
+
+  GetSystemTimeAsFileTime(&file_time);
+  ularge.LowPart = file_time.dwLowDateTime;
+  ularge.HighPart = file_time.dwHighDateTime;
+  tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L);
+  tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c
index 5e7da2a..5820ba9 100644
--- a/Utilities/cmlibuv/src/win/winsock.c
+++ b/Utilities/cmlibuv/src/win/winsock.c
@@ -87,12 +87,6 @@
   WSAPROTOCOL_INFOW protocol_info;
   int opt_len;
 
-  /* Initialize winsock */
-  errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
-  if (errorno != 0) {
-    uv_fatal_error(errorno, "WSAStartup");
-  }
-
   /* Set implicit binding address used by connectEx */
   if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {
     abort();
@@ -102,6 +96,15 @@
     abort();
   }
 
+  /* Skip initialization in safe mode without network support */
+  if (1 == GetSystemMetrics(SM_CLEANBOOT)) return;
+
+  /* Initialize winsock */
+  errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
+  if (errorno != 0) {
+    uv_fatal_error(errorno, "WSAStartup");
+  }
+
   /* Detect non-IFS LSPs */
   dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 
diff --git a/bootstrap b/bootstrap
index 38fa32b..ac5adc8 100755
--- a/bootstrap
+++ b/bootstrap
@@ -261,6 +261,17 @@
   cmAddSubDirectoryCommand \
   cmAddTestCommand \
   cmArgumentParser \
+  cmBinUtilsLinker \
+  cmBinUtilsLinuxELFGetRuntimeDependenciesTool \
+  cmBinUtilsLinuxELFLinker \
+  cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool \
+  cmBinUtilsMacOSMachOGetRuntimeDependenciesTool \
+  cmBinUtilsMacOSMachOLinker \
+  cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool \
+  cmBinUtilsWindowsPEGetRuntimeDependenciesTool \
+  cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool \
+  cmBinUtilsWindowsPELinker \
+  cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool \
   cmBreakCommand \
   cmBuildCommand \
   cmCMakeMinimumRequired \
@@ -357,6 +368,8 @@
   cmInstallTargetGenerator \
   cmInstallTargetsCommand \
   cmInstalledFile \
+  cmLDConfigLDConfigTool \
+  cmLDConfigTool \
   cmLinkDirectoriesCommand \
   cmLinkItem \
   cmLinkLineComputer \
@@ -388,12 +401,12 @@
   cmPolicies \
   cmProcessOutput \
   cmProjectCommand \
-  cmProperty \
   cmPropertyDefinition \
   cmPropertyDefinitionMap \
   cmPropertyMap \
   cmReturnCommand \
   cmRulePlaceholderExpander \
+  cmRuntimeDependencyArchive \
   cmScriptGenerator \
   cmSearchPath \
   cmSeparateArgumentsCommand \
@@ -409,6 +422,7 @@
   cmState \
   cmStateDirectory \
   cmStateSnapshot \
+  cmStringAlgorithms \
   cmStringReplaceHelper \
   cmStringCommand \
   cmSubdirCommand \
@@ -427,7 +441,6 @@
   cmTimestamp \
   cmTryCompileCommand \
   cmTryRunCommand \
-  cmUnexpectedCommand \
   cmUnsetCommand \
   cmUVHandlePtr \
   cmUVProcessChain \
@@ -443,7 +456,9 @@
 if ${cmake_system_mingw}; then
   CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES}\
     cmGlobalMSYSMakefileGenerator \
-    cmGlobalMinGWMakefileGenerator"
+    cmGlobalMinGWMakefileGenerator \
+    cmVSSetupHelper \
+  "
 fi
 
 LexerParser_CXX_SOURCES="\
@@ -1110,6 +1125,25 @@
 #error "SunPro <= 5.13 mode not supported due to bug in move semantics."
 #endif
 
+#if __cplusplus > 201103L
+#include <iterator>
+int check_cxx14()
+{
+  int a[] = { 0, 1, 2 };
+  auto ai = std::cbegin(a);
+
+  int b[] = { 2, 1, 0 };
+  auto bi = std::cend(b);
+
+  return *ai + *(bi - 1);
+}
+#else
+int check_cxx14()
+{
+  return 0;
+}
+#endif
+
 class Class
 {
 public:
@@ -1120,7 +1154,7 @@
 int main()
 {
   auto const c = std::unique_ptr<Class>(new Class);
-  std::cout << c->Get() << std::endl;
+  std::cout << c->Get() << check_cxx14() << std::endl;
   return 0;
 }
 ' > "${TMPFILE}.cxx"
@@ -1370,7 +1404,7 @@
 uv_c_flags=""
 if ${cmake_system_mingw}; then
   uv_c_flags="${uv_c_flags} -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600"
-  libs="${libs} -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv"
+  libs="${libs} -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -lole32 -loleaut32"
 else
   uv_c_flags="${uv_c_flags} -DCMAKE_BOOTSTRAP"
   case "${cmake_system}" in