Merge topic 'xcframework-plist-cache'

da330bcf88 macOS: Cache parsed xcframework plist content

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !11076
diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst
index 52ce7f4..5984117 100644
--- a/Help/command/foreach.rst
+++ b/Help/command/foreach.rst
@@ -58,7 +58,8 @@
 The ``<items>`` following the ``ITEMS`` keyword are processed
 as in the first variant of the ``foreach`` command.
 The forms ``LISTS A`` and ``ITEMS ${A}`` are
-equivalent.
+equivalent. If no ``<lists>`` or ``<items>`` are given, the body
+of the loop will never be executed (i.e., it is processed as empty).
 
 The following example shows how the ``LISTS`` option is
 processed:
@@ -97,13 +98,18 @@
 command iterates over each list simultaneously setting the
 iteration variables as follows:
 
-- if the only ``loop_var`` given, then it sets a series of
+- if a single ``loop_var`` is given, then it sets a series of
   ``loop_var_N`` variables to the current item from the
   corresponding list;
-- if multiple variable names passed, their count should match
-  the lists variables count;
-- if any of the lists are shorter, the corresponding iteration
-  variable is not defined for the current iteration.
+- if multiple variable names are passed, it sets each variable to the
+  current item from the corresponding list. The number of iteration
+  variables must match the number of list variables.
+
+If no ``<lists>`` are given, the body of the loop will never be executed
+(i.e., it is processed as empty).
+
+The following example shows how the ``ZIP_LISTS`` option is
+processed:
 
 .. noqa: spellcheck off
 
diff --git a/Help/dev/README.rst b/Help/dev/README.rst
index 2a2d32d..84766a6 100644
--- a/Help/dev/README.rst
+++ b/Help/dev/README.rst
@@ -40,11 +40,13 @@
 * The `CMake Documentation Guide`_.
 * The `CMake Testing Guide`_.
 * The `CMake Experimental Features Guide`_.
+* The `CMake Debugging Guide`_.
 
 .. _`CMake Source Code Guide`: source.rst
 .. _`CMake Documentation Guide`: documentation.rst
 .. _`CMake Testing Guide`: testing.rst
 .. _`CMake Experimental Features Guide`: experimental.rst
+.. _`CMake Debugging Guide`: debug.rst
 
 Maintainer Documentation
 ========================
diff --git a/Help/dev/debug.rst b/Help/dev/debug.rst
new file mode 100644
index 0000000..ded270f
--- /dev/null
+++ b/Help/dev/debug.rst
@@ -0,0 +1,197 @@
+CMake Debugging Guide
+*********************
+
+This guide explains how to attach a debugger to CMake's unit testing framework.
+We'll focus on using **GDB** on Linux for both command-line and IDE debugging.
+See documentation on `CMake Development`_ for more information.
+
+.. _`CMake Development`: README.rst
+
+Linux: Using GDB
+================
+
+On Linux, the GNU Debugger (**GDB**) is the standard tool for debugging the
+CMake test suite. The core process involves launching the ``cmake`` executable
+from within GDB with a specific set of arguments that configure and run the
+desired test.
+
+GDB Configuration
+-----------------
+
+For effective debugging, GDB must be configured to handle child processes
+correctly, which CMake tests often create. A good practice is to use a local
+``.gdbinit`` file in your build directory. This keeps CMake-specific settings
+separate from your global configuration.
+
+**1. Enable Local .gdbinit Files (One-Time Setup)**
+
+To allow GDB to automatically load configuration from your build directory,
+add the following line to your global GDB initialization file at
+``$HOME/.gdbinit``. This is a one-time setup that makes future projects easier
+to manage.
+
+.. code-block:: text
+
+  set auto-load local-gdbinit on
+
+**2. Create a Project-Specific .gdbinit**
+
+Next, create a ``.gdbinit`` file inside your CMake **build directory**.
+This file will contain settings specific to debugging CMake.
+To make this easier, you can symlink the template file provided in the CMake
+source tree:
+
+.. code-block:: bash
+
+  # Navigate to your build directory
+  cd /path/to/your/cmake/build
+
+  # Create a symlink to the template
+  ln -s $cmake_srcdir/Utilities/gdb/gdbinit-template .gdbinit
+
+The template contains the essential settings for debugging CMake tests:
+
+.. code-block:: gdb
+
+  # Allows GDB to follow child processes
+  set follow-fork-mode child
+
+  # Allows the parent process continue in parallel
+  set non-stop on
+
+Debugging from the Command Line
+-------------------------------
+
+To start debugging, first cd to the build directory. Then, launch the
+``cmake`` executable using ``gdb --args``, which passes the necessary test
+configuration arguments directly to CMake.
+
+.. note::
+
+  To get the launch command, run ``ctest -R "RunCMake.$TESTNAME" -VV -N``
+
+
+The following example runs the ``InstallPackageInfo`` test.
+
+.. code-block:: bash
+
+  # Define paths to your CMake source and build directories
+  CMAKE_SOURCE_DIR="$HOME/cmake"
+  CMAKE_BUILD_DIR="$CMAKE_SOURCE_DIR/build"
+
+  # Define the specific test to run
+  TEST_NAME="InstallPackageInfo"
+
+  # Navigate to the build directory
+  cd "$CMAKE_BUILD_DIR"
+
+  # Launch GDB with the appropriate arguments for the test
+  gdb --args ./bin/cmake \
+    "-DCMAKE_MODULE_PATH=$CMAKE_SOURCE_DIR/Tests/RunCMake" \
+    "-DRunCMake_GENERATOR=Ninja" \
+    "-DRunCMake_SOURCE_DIR=$CMAKE_SOURCE_DIR/Tests/RunCMake/$TEST_NAME" \
+    "-DRunCMake_BINARY_DIR=$CMAKE_BUILD_DIR/Tests/RunCMake/$TEST_NAME" \
+    "-P" "$CMAKE_SOURCE_DIR/Tests/RunCMake/RunCMakeTest.cmake"
+
+Once GDB loads, you may set breakpoints (e.g., ``b cmInstallCommand``) and
+then start the test by typing ``run``.
+
+Filtering Tests
+---------------
+
+Some test suites contain multiple sub-tests. To run only a specific one,
+you can use the ``RunCMake_TEST_FILTER`` environment variable.
+
+For example, to run only the "Metadata" test within the ``InstallPackageInfo``
+suite, you can set the variable before launching GDB:
+
+.. code-block:: bash
+
+  RunCMake_TEST_FILTER="Metadata" gdb --args ...
+
+Alternatively, you can set the environment variable from within the
+GDB session before running the test:
+
+.. code-block:: gdb-prompt
+
+  (gdb) set environment RunCMake_TEST_FILTER Metadata
+  (gdb) run
+
+
+IDE Integration
+---------------
+
+You can also debug CMake tests directly from your IDE.
+
+CLion
+=====
+
+If you have configured GDB to auto-load local ``.gdbinit`` files as described
+above, CLion will automatically pick up the necessary settings.
+
+A simple way to debug a test is to modify its ``CTest`` run configuration:
+
+#. **Select the Test**: In the "Run/Debug Configurations" dialog, find the
+   ``CTest`` entry for your test (e.g., ``RunCMake.InstallPackageInfo``).
+#. **Add CTest Arguments**: In the "CTest arguments" field, add
+   ``--extra-verbose``. This is helpful for debugging because it prints the
+   exact command ``CTest`` uses to run the test.
+#. **Set Working Directory**: Ensure the "Working Directory" field is set to
+   ``$CMakeCurrentLocalGenerationDir$``.
+
+You can now set breakpoints in your code and debug this configuration.
+
+Visual Studio Code
+==================
+
+Create a ``launch.json`` file in the ``.vscode`` directory of your
+CMake **source folder** with the following configuration. This configuration
+hardcodes the necessary GDB settings, so it does not depend on an external
+``.gdbinit`` file.
+
+.. code-block:: json
+
+  {
+   "version": "0.2.0",
+   "configurations": [
+     {
+       "name": "Debug CMake Test",
+       "type": "cppdbg",
+       "request": "launch",
+       "program": "${workspaceFolder}/build/bin/cmake",
+       "args": [
+         "-DCMAKE_MODULE_PATH=${workspaceFolder}/Tests/RunCMake",
+         "-DRunCMake_GENERATOR=Ninja",
+         "-DRunCMake_SOURCE_DIR=${workspaceFolder}/Tests/RunCMake/InstallPackageInfo",
+         "-DRunCMake_BINARY_DIR=${workspaceFolder}/build/Tests/RunCMake/InstallPackageInfo",
+         "-P",
+         "${workspaceFolder}/Tests/RunCMake/RunCMakeTest.cmake"
+       ],
+       "stopAtEntry": false,
+       "cwd": "${workspaceFolder}/build",
+       "environment": [],
+       "MIMode": "gdb",
+       "setupCommands": [
+         {
+           "description": "Enable pretty-printing for gdb",
+           "text": "-enable-pretty-printing",
+           "ignoreFailures": true
+         },
+         {
+           "description": "Follow child processes",
+           "text": "set follow-fork-mode child",
+           "ignoreFailures": true
+         },
+         {
+           "description": "Don't stop the parent process",
+           "text": "set non-stop on",
+           "ignoreFailures": true
+         }
+       ]
+     }
+   ]
+  }
+
+.. note::
+
+  Remember to change the test name (``InstallPackageInfo``) in the ``"args"`` section to the specific test you want to debug.
diff --git a/Help/envvar/CTEST_USE_INSTRUMENTATION.rst b/Help/envvar/CTEST_USE_INSTRUMENTATION.rst
index 6e33845..b00c92d 100644
--- a/Help/envvar/CTEST_USE_INSTRUMENTATION.rst
+++ b/Help/envvar/CTEST_USE_INSTRUMENTATION.rst
@@ -10,6 +10,6 @@
    This feature is only available when experimental support for instrumentation
    has been enabled by the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` gate.
 
-Setting this environment variable enables
+Setting this environment variable to ``1``, ``True``, or ``ON`` enables
 :manual:`instrumentation <cmake-instrumentation(7)>` for CTest in
 :ref:`Dashboard Client` mode.
diff --git a/Help/envvar/CTEST_USE_VERBOSE_INSTRUMENTATION.rst b/Help/envvar/CTEST_USE_VERBOSE_INSTRUMENTATION.rst
index 95053e4..4a119aa 100644
--- a/Help/envvar/CTEST_USE_VERBOSE_INSTRUMENTATION.rst
+++ b/Help/envvar/CTEST_USE_VERBOSE_INSTRUMENTATION.rst
@@ -10,8 +10,9 @@
    This feature is only available when experimental support for instrumentation
    has been enabled by the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` gate.
 
-Setting this environment variable causes CTest to report the full
-command line (including arguments) to CDash for each instrumented command.
-By default, CTest truncates the command line at the first space.
+Setting this environment variable to ``1``, ``True``, or ``ON`` causes CTest to
+report the full command line (including arguments) to CDash for each
+instrumented command. By default, CTest truncates the command line at the first
+space.
 
 See also :envvar:`CTEST_USE_INSTRUMENTATION`
diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst
index f7896e5..7e1f61b 100644
--- a/Help/manual/cmake-developer.7.rst
+++ b/Help/manual/cmake-developer.7.rst
@@ -154,7 +154,7 @@
 ``Foo_FIND_COMPONENTS`` if it is set , and only set ``Foo_FOUND`` to
 true if for each searched-for component ``<c>`` that was not found,
 ``Foo_FIND_REQUIRED_<c>`` is not set to true.  The ``HANDLE_COMPONENTS``
-argument of ``find_package_handle_standard_args()`` can be used to
+argument of :command:`find_package_handle_standard_args` can be used to
 implement this.
 
 If ``Foo_FIND_COMPONENTS`` is not set, which modules are searched for
diff --git a/Help/manual/cmake-instrumentation.7.rst b/Help/manual/cmake-instrumentation.7.rst
index d2106aa..06e71ed 100644
--- a/Help/manual/cmake-instrumentation.7.rst
+++ b/Help/manual/cmake-instrumentation.7.rst
@@ -98,8 +98,7 @@
 ----------------------------------------------
 
 You can enable instrumentation when using CTest in :ref:`Dashboard Client`
-mode by setting the :envvar:`CTEST_USE_INSTRUMENTATION` environment variable
-to the current UUID for the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` feature.
+mode by setting the :envvar:`CTEST_USE_INSTRUMENTATION` environment variable.
 Doing so automatically enables the ``dynamicSystemInformation`` option.
 
 The following table shows how each type of instrumented command gets mapped
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 63622a8..58f5e3b 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -282,6 +282,7 @@
    /prop_tgt/IMPORT_SUFFIX
    /prop_tgt/INCLUDE_DIRECTORIES
    /prop_tgt/INSTALL_NAME_DIR
+   /prop_tgt/INSTALL_OBJECT_NAME_STRATEGY
    /prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH
    /prop_tgt/INSTALL_RPATH
    /prop_tgt/INSTALL_RPATH_USE_LINK_PATH
diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst
index f9729b3..fe269c2 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -224,10 +224,10 @@
 ===============================
 
 The ``moc`` and ``uic`` tools are executed as part of a synthesized
-:ref:`<ORIGIN>_autogen` :command:`custom target <add_custom_target>` generated by
-CMake.  By default that :ref:`<ORIGIN>_autogen` target inherits the dependencies
+``<ORIGIN>_autogen`` :command:`custom target <add_custom_target>` generated by
+CMake.  By default, that ``<ORIGIN>_autogen`` target inherits the dependencies
 of the ``<ORIGIN>`` target (see :prop_tgt:`AUTOGEN_ORIGIN_DEPENDS`).
-Target dependencies may be added to the :ref:`<ORIGIN>_autogen` target by adding
+Target dependencies may be added to the ``<ORIGIN>_autogen`` target by adding
 them to the :prop_tgt:`AUTOGEN_TARGET_DEPENDS` target property.
 
 .. note::
@@ -241,9 +241,10 @@
 
 If Qt 5.15 or later is used and the generator is either :generator:`Ninja` or
 :ref:`Makefile Generators`, the ``<ORIGIN>_autogen_timestamp_deps`` target is
-also created in addition to the :ref:`<ORIGIN>_autogen` target.  This target
-does not have any sources or commands to execute, but it has dependencies that
-were previously inherited by the pre-Qt 5.15 :ref:`<ORIGIN>_autogen` target.
+also created in addition to the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
+target.  This target does not have any sources or commands to execute, but it
+has dependencies that were previously inherited by the pre-Qt 5.15
+:ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target.
 These dependencies will serve as a list of order-only dependencies for the
 custom command, without forcing the custom command to re-execute.
 
@@ -252,11 +253,11 @@
 
 When using the :ref:`Visual Studio Generators`, CMake
 generates a ``PRE_BUILD`` :command:`custom command <add_custom_command>`
-instead of the :ref:`<ORIGIN>_autogen`
+instead of the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
 :command:`custom target <add_custom_target>` (for :prop_tgt:`AUTOMOC` and
 :prop_tgt:`AUTOUIC`).  This isn't always possible though and an
-:ref:`<ORIGIN>_autogen` :command:`custom target <add_custom_target>` is used,
-when either
+:ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
+:command:`custom target <add_custom_target>` is used, when either
 
 - the ``<ORIGIN>`` target depends on :prop_sf:`GENERATED` files which aren't
   excluded from :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` by
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index c936f50..28d7b38 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -489,6 +489,7 @@
    /variable/CMAKE_INCLUDE_CURRENT_DIR
    /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE
    /variable/CMAKE_INSTALL_NAME_DIR
+   /variable/CMAKE_INSTALL_OBJECT_NAME_STRATEGY
    /variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH
    /variable/CMAKE_INSTALL_RPATH
    /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH
diff --git a/Help/policy/CMP0183.rst b/Help/policy/CMP0183.rst
index 6804c3b..f2d6601 100644
--- a/Help/policy/CMP0183.rst
+++ b/Help/policy/CMP0183.rst
@@ -5,7 +5,7 @@
 
 :command:`add_feature_info` supports full :ref:`Condition Syntax`.
 
-The ``<enabled>`` parameter accepts a :ref:`semicolon-separated list <CMake
+The ``<condition>`` parameter accepts a :ref:`semicolon-separated list <CMake
 Language Lists>` of conditions.  CMake 3.31 and lower evaluate each
 ``condition`` as ``if(${condition})``, which does not properly handle
 conditions with nested paren groups.  CMake 4.0 and above instead prefer
diff --git a/Help/prop_tgt/AUTOGEN_ORIGIN_DEPENDS.rst b/Help/prop_tgt/AUTOGEN_ORIGIN_DEPENDS.rst
index 33db8a7..4bf83eb 100644
--- a/Help/prop_tgt/AUTOGEN_ORIGIN_DEPENDS.rst
+++ b/Help/prop_tgt/AUTOGEN_ORIGIN_DEPENDS.rst
@@ -4,29 +4,29 @@
 .. versionadded:: 3.14
 
 Switch for forwarding origin target dependencies to the corresponding
-:ref:`<ORIGIN>_autogen` target.
+:ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target.
 
   .. note::
 
     If Qt 5.15 or later is used and the generator is either :generator:`Ninja`
     or :ref:`Makefile Generators`, origin target dependencies are forwarded to
-    the :ref:`<ORIGIN>_autogen_timestamp_deps` target instead of
-    :ref:`<ORIGIN>_autogen`
-
+    the :ref:`<ORIGIN>_autogen_timestamp_deps <<ORIGIN>_autogen_timestamp_deps>`
+    target instead of :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`.
 
 Targets which have their :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` property
-``ON`` have a corresponding :ref:`<ORIGIN>_autogen` target which generates
-``moc`` and ``uic`` files.  As this :ref:`<ORIGIN>_autogen` target is created at
+``ON`` have a corresponding :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target
+which generates ``moc`` and ``uic`` files.
+As this :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target is created at
 generate-time, it is not possible to define dependencies of it using
 e.g.  :command:`add_dependencies`.  Instead the ``AUTOGEN_ORIGIN_DEPENDS``
 target property decides whether the origin target dependencies should be
-forwarded to the :ref:`<ORIGIN>_autogen` target or not.
+forwarded to the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target or not.
 
 By default ``AUTOGEN_ORIGIN_DEPENDS`` is initialized from
 :variable:`CMAKE_AUTOGEN_ORIGIN_DEPENDS` which is ``ON`` by default.
 
-In total the dependencies of the :ref:`<ORIGIN>_autogen` target are composed
-from
+In total the dependencies of the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
+target are composed from
 
 - forwarded origin target dependencies
   (enabled by default via ``AUTOGEN_ORIGIN_DEPENDS``)
@@ -38,11 +38,12 @@
 .. note::
 
     Disabling ``AUTOGEN_ORIGIN_DEPENDS`` is useful to avoid building of
-    origin target dependencies when building the :ref:`<ORIGIN>_autogen` target
-    only. This is especially interesting when a
+    origin target dependencies when building the
+    :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target only.
+    This is especially interesting when a
     :variable:`global autogen target <CMAKE_GLOBAL_AUTOGEN_TARGET>` is enabled.
 
-    When the :ref:`<ORIGIN>_autogen` target doesn't require all the origin target's
-    dependencies, and ``AUTOGEN_ORIGIN_DEPENDS`` is disabled, it might be
-    necessary to extend :prop_tgt:`AUTOGEN_TARGET_DEPENDS` to add missing
-    dependencies.
+    When the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target doesn't require
+    all the origin target's dependencies, and ``AUTOGEN_ORIGIN_DEPENDS`` is
+    disabled, it might be necessary to extend :prop_tgt:`AUTOGEN_TARGET_DEPENDS`
+    to add missing dependencies.
diff --git a/Help/prop_tgt/AUTOGEN_PARALLEL.rst b/Help/prop_tgt/AUTOGEN_PARALLEL.rst
index 9d34355..c1c86e8 100644
--- a/Help/prop_tgt/AUTOGEN_PARALLEL.rst
+++ b/Help/prop_tgt/AUTOGEN_PARALLEL.rst
@@ -6,9 +6,9 @@
 Number of parallel ``moc`` or ``uic`` processes to start when using
 :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`.
 
-The custom :ref:`<ORIGIN>_autogen` target starts a number of threads of which
-each one parses a source file and on demand starts a ``moc`` or ``uic``
-process. ``AUTOGEN_PARALLEL`` controls how many parallel threads
+The custom :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target starts a number
+of threads.  Each thread parses a source file and on demand starts a ``moc``
+or ``uic`` process. ``AUTOGEN_PARALLEL`` controls how many parallel threads
 (and therefore ``moc`` or ``uic`` processes) are started.
 
 - An empty (or unset) value or the string ``AUTO`` sets the number of
diff --git a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst
index 13e2ef7..892dc5e 100644
--- a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst
+++ b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst
@@ -1,28 +1,29 @@
 AUTOGEN_TARGET_DEPENDS
 ----------------------
 
-Additional target dependencies of the corresponding :ref:`<ORIGIN>_autogen`
-target.
+Additional target dependencies of the corresponding
+:ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target.
 
   .. note::
 
     If Qt 5.15 or later is used and the generator is either :generator:`Ninja`
     or :ref:`Makefile Generators`, additional target dependencies are added to
-    the :ref:`<ORIGIN>_autogen_timestamp_deps` target instead of the
-    :ref:`<ORIGIN>_autogen` target.
+    the :ref:`<ORIGIN>_autogen_timestamp_deps <<ORIGIN>_autogen_timestamp_deps>`
+    target instead of the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target.
 
 
 Targets which have their :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` property
-``ON`` have a corresponding :ref:`<ORIGIN>_autogen`  target which generates
-``moc`` and ``uic`` files.  As this :ref:`<ORIGIN>_autogen`  target is created
+``ON`` have a corresponding :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`  target
+which generates ``moc`` and ``uic`` files.
+As this :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target is created
 at generate-time, it is not possible to define dependencies of it using e.g.
 :command:`add_dependencies`.  Instead the ``AUTOGEN_TARGET_DEPENDS`` target
 property can be set to a :ref:`;-list <CMake Language Lists>` of additional
-dependencies for the :ref:`<ORIGIN>_autogen`  target. Dependencies can be target
-names or file names.
+dependencies for the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`  target.
+Dependencies can be target names or file names.
 
-In total the dependencies of the :ref:`<ORIGIN>_autogen`  target are composed
-from
+In total, the dependencies of the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
+target are composed from
 
 - forwarded origin target dependencies
   (enabled by default via :prop_tgt:`AUTOGEN_ORIGIN_DEPENDS`)
diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index 0bd4d13..25c5632 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -251,8 +251,8 @@
 
 :variable:`CMAKE_GLOBAL_AUTOGEN_TARGET`:
 A global ``autogen`` target, that depends on all ``AUTOMOC`` or
-:prop_tgt:`AUTOUIC` generated :ref:`<ORIGIN>_autogen` targets in the project,
-will be generated when this variable is ``ON``.
+:prop_tgt:`AUTOUIC` generated :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
+targets in the project, will be generated when this variable is ``ON``.
 
 :prop_tgt:`AUTOGEN_PARALLEL`:
 This target property controls the number of ``moc`` or ``uic`` processes to
diff --git a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
index fec98f6..50da7c0 100644
--- a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
+++ b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
@@ -22,7 +22,7 @@
 
 If any of the extracted files is :prop_sf:`GENERATED` or if it is not in the
 target's sources, then it might be necessary to add it to the
-:ref:`<ORIGIN>_autogen` target  dependencies.
+:ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target dependencies.
 See :prop_tgt:`AUTOGEN_TARGET_DEPENDS` for reference.
 
 By default ``AUTOMOC_DEPEND_FILTERS`` is initialized from
diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst
index 6f1c85c..8901de3 100644
--- a/Help/prop_tgt/AUTOUIC.rst
+++ b/Help/prop_tgt/AUTOUIC.rst
@@ -76,8 +76,8 @@
 
 :variable:`CMAKE_GLOBAL_AUTOGEN_TARGET`:
 A global ``autogen`` target, that depends on all :prop_tgt:`AUTOMOC` or
-``AUTOUIC`` generated :ref:`<ORIGIN>_autogen` targets in the project,
-will be generated when this variable is ``ON``.
+``AUTOUIC`` generated :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
+targets in the project, will be generated when this variable is ``ON``.
 
 :prop_tgt:`AUTOGEN_PARALLEL`:
 This target property controls the number of ``moc`` or ``uic`` processes to
diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst
index 9b381e4..177f12e 100644
--- a/Help/prop_tgt/CXX_STANDARD.rst
+++ b/Help/prop_tgt/CXX_STANDARD.rst
@@ -40,9 +40,6 @@
 ``26``
   .. versionadded:: 3.25
 
-  C++26. CMake 3.25 and later *recognize* ``26`` as a valid value,
-  no version has support for any compiler.
-
 If the value requested does not result in a compile flag being added for
 the compiler in use, a previous standard flag will be added instead.  This
 means that using:
diff --git a/Help/prop_tgt/EXPORT_FIND_PACKAGE_NAME.rst b/Help/prop_tgt/EXPORT_FIND_PACKAGE_NAME.rst
index b7405d6..f74f6d3 100644
--- a/Help/prop_tgt/EXPORT_FIND_PACKAGE_NAME.rst
+++ b/Help/prop_tgt/EXPORT_FIND_PACKAGE_NAME.rst
@@ -6,9 +6,10 @@
   Experimental. Gated by ``CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_DEPENDENCIES``.
 
 Control the package name associated with a dependency target when exporting a
-:command:`find_dependency` call in :command:`install(EXPORT)` or
+:command:`find_dependency` call in :command:`install(PACKAGE_INFO)`,
+:command:`export(PACKAGE_INFO)`, :command:`install(EXPORT)` or
 :command:`export(EXPORT)`. This can be used to assign a package name to a
-package that is built by CMake and exported, or to override the package in the
-:command:`find_package` call that created the target.
+package that is built by CMake and exported, or a package that was provided by
+:module:`FetchContent`.
 
 This property is initialized by :variable:`CMAKE_EXPORT_FIND_PACKAGE_NAME`.
diff --git a/Help/prop_tgt/INSTALL_OBJECT_NAME_STRATEGY.rst b/Help/prop_tgt/INSTALL_OBJECT_NAME_STRATEGY.rst
new file mode 100644
index 0000000..99f5170
--- /dev/null
+++ b/Help/prop_tgt/INSTALL_OBJECT_NAME_STRATEGY.rst
@@ -0,0 +1,23 @@
+INSTALL_OBJECT_NAME_STRATEGY
+----------------------------
+
+.. versionadded:: 4.2
+
+``INSTALL_OBJECT_NAME_STRATEGY`` is a string target property variable
+specifying the strategy to use when naming installed object files. The
+supported values are:
+
+- ``FULL``: Object files are named after the associated source file.
+- ``SHORT``: Object files are named based on the hash of the source file name
+  to reduce path lengths.
+
+When unset or the named strategy is not supported, the ``FULL`` strategy is
+used.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_INSTALL_OBJECT_NAME_STRATEGY` if it is set when a target is
+created.
+
+.. note::
+  Not all generators support all strategies and paths may differ between
+  generators.
diff --git a/Help/release/3.14.rst b/Help/release/3.14.rst
index 6b3a187..e4a386a 100644
--- a/Help/release/3.14.rst
+++ b/Help/release/3.14.rst
@@ -302,7 +302,7 @@
 * A new :variable:`CMAKE_AUTOGEN_ORIGIN_DEPENDS` variable and
   :prop_tgt:`AUTOGEN_ORIGIN_DEPENDS` target property may be set to enable or
   disable forwarding of the origin target dependencies to the corresponding
-  :ref:`<ORIGIN>_autogen` target.
+  :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target.
 
 CTest
 -----
@@ -346,6 +346,9 @@
   ``xmlrpc``.  CDash is the only maintained testing dashboard for CTest,
   and it only supports submissions over ``http`` and ``https``.
 
+* The :module:`MacroAddFileDependencies` module is deprecated.
+  Port projects to use :command:`set_property` directly.
+
 Other Changes
 =============
 
diff --git a/Help/release/3.16.rst b/Help/release/3.16.rst
index 28273a7..f9f9b33 100644
--- a/Help/release/3.16.rst
+++ b/Help/release/3.16.rst
@@ -165,7 +165,7 @@
   a new ``REASON_FAILURE_MESSAGE`` option to specify a message
   giving the reason for the failure.
 
-* The :module:`FindPkgConfig` module :command:`pkg_search_module` macro
+* The :module:`FindPkgConfig` module :command:`pkg_search_module` command
   now defines a ``<prefix>_MODULE_NAME`` result variable containing the
   first matching module name.
 
diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst
index efc8115..fa57fc4 100644
--- a/Help/release/3.22.rst
+++ b/Help/release/3.22.rst
@@ -75,7 +75,7 @@
 
 * The :module:`FindMatlab` module now provides imported targets.
 
-* The :module:`FindPkgConfig` module gained a :variable:`PKG_CONFIG_ARGN`
+* The :module:`FindPkgConfig` module gained a ``PKG_CONFIG_ARGN``
   variable to specify arguments to ``pkg-config`` calls.
 
 * The :module:`GoogleTest` module :command:`gtest_discover_tests`
diff --git a/Help/release/3.3.rst b/Help/release/3.3.rst
index efb6a7c..3b1da25 100644
--- a/Help/release/3.3.rst
+++ b/Help/release/3.3.rst
@@ -135,7 +135,7 @@
   documentation, and unit tests.
 
 * The :module:`FindPackageHandleStandardArgs` module
-  ``find_package_handle_standard_args`` function now
+  :command:`find_package_handle_standard_args` command now
   always populates both the ``<PackageName>_FOUND``
   and ``<UPPERCASE_NAME>_FOUND`` variables (the latter
   for backwards compatibility).  The ``FOUND_VAR``
diff --git a/Help/release/dev/FindDevIL.rst b/Help/release/dev/FindDevIL.rst
new file mode 100644
index 0000000..b94a933
--- /dev/null
+++ b/Help/release/dev/FindDevIL.rst
@@ -0,0 +1,6 @@
+FindDevIL
+---------
+
+* The :module:`FindDevIL` module now provides a ``DevIL_VERSION`` result
+  variable and version argument and version range can be specified by
+  :command:`find_package`, when finding the DevIL package.
diff --git a/Help/release/dev/find-modules.rst b/Help/release/dev/find-modules.rst
index 80f548a..6b92227 100644
--- a/Help/release/dev/find-modules.rst
+++ b/Help/release/dev/find-modules.rst
@@ -31,6 +31,9 @@
 * The :module:`FindGnuplot` module now provides a ``Gnuplot_VERSION`` result
   variable.  The ``GNUPLOT_VERSION_STRING`` result variable is deprecated.
 
+* The :module:`FindGnuTLS` module now provides a ``GnuTLS_VERSION`` result
+  variable.  The ``GNUTLS_VERSION`` result variable is deprecated.
+
 * The :module:`FindJasper` module now provides a ``Jasper_VERSION`` result
   variable.  The ``JASPER_VERSION_STRING`` result variable is deprecated.
 
@@ -46,6 +49,14 @@
 * The :module:`FindLTTngUST` module now provides a ``LTTngUST_VERSION`` result
   variable.  The ``LTTNGUST_VERSION_STRING`` result variable is deprecated.
 
+* The :module:`FindLua` module now provides ``Lua_VERSION``,
+  ``Lua_VERSION_MAJOR``, ``Lua_VERSION_MINOR``, and ``Lua_VERSION_PATCH``
+  result variables.  The ``LUA_VERSION_STRING``, ``LUA_VERSION_MAJOR``,
+  ``LUA_VERSION_MINOR``, and ``LUA_VERSION_PATCH`` result variables are
+  deprecated.  The :module:`FindLua51` module now similarly provides a
+  ``Lua_VERSION`` instead of the now deprecated ``LUA_VERSION_STRING`` result
+  variable.
+
 * The :module:`FindOpenSceneGraph` module now provides an
   ``OpenSceneGraph_VERSION`` result variable.  The ``OPENSCENEGRAPH_VERSION``
   result variable is deprecated.
@@ -53,6 +64,12 @@
 * The :module:`FindOpenSSL` module now provides an ``OpenSSL_VERSION`` result
   variable.  The ``OPENSSL_VERSION`` result variable is deprecated.
 
+* The :module:`FindPerl` module now provides a ``Perl_VERSION`` result
+  variable.  The ``PERL_VERSION_STRING`` result variable is deprecated.
+
+* The :module:`FindPerlLibs` module now provides a ``PerlLibs_VERSION``
+  result variable.
+
 * The :module:`FindPNG` module now provides a ``PNG_VERSION`` result
   variable.  The ``PNG_VERSION_STRING`` result variable is deprecated.
 
@@ -71,5 +88,9 @@
   ``SQUISH_VERSION_MINOR``, and ``SQUISH_VERSION_PATCH`` result variables
   are deprecated.
 
+* The :module:`FindSubversion` module now provides a ``Subversion_VERSION``
+  result variable.  The ``Subversion_VERSION_SVN`` result variable is
+  deprecated.
+
 * The :module:`FindTIFF` module now provides a ``TIFF_VERSION`` result
   variable.  The ``TIFF_VERSION_STRING`` result variable is deprecated.
diff --git a/Help/release/dev/install-object-name-strategy.rst b/Help/release/dev/install-object-name-strategy.rst
new file mode 100644
index 0000000..bfc189a
--- /dev/null
+++ b/Help/release/dev/install-object-name-strategy.rst
@@ -0,0 +1,5 @@
+install-object-name-strategy
+----------------------------
+
+* The :prop_tgt:`INSTALL_OBJECT_NAME_STRATEGY` target property has been added
+  to control the naming strategy for installed object files.
diff --git a/Help/variable/CMAKE_AUTOGEN_ORIGIN_DEPENDS.rst b/Help/variable/CMAKE_AUTOGEN_ORIGIN_DEPENDS.rst
index 52aa891..139268b 100644
--- a/Help/variable/CMAKE_AUTOGEN_ORIGIN_DEPENDS.rst
+++ b/Help/variable/CMAKE_AUTOGEN_ORIGIN_DEPENDS.rst
@@ -4,14 +4,14 @@
 .. versionadded:: 3.14
 
 Switch for forwarding origin target dependencies to the corresponding
-:ref:`<ORIGIN>_autogen` targets.
+:ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` targets.
 
   .. note::
 
     If Qt 5.15 or later is used and the generator is either :generator:`Ninja`
     or :ref:`Makefile Generators`, additional target dependencies are added to
-    the :ref:`<ORIGIN>_autogen_timestamp_deps` target instead of the
-    :ref:`<ORIGIN>_autogen` target.
+    the :ref:`<ORIGIN>_autogen_timestamp_deps <<ORIGIN>_autogen_timestamp_deps>`
+    target instead of the :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` target.
 
 This variable is used to initialize the :prop_tgt:`AUTOGEN_ORIGIN_DEPENDS`
 property on all the targets.  See that target property for additional
diff --git a/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst b/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst
index 2bf5f05..6e2ecc3 100644
--- a/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst
+++ b/Help/variable/CMAKE_GLOBAL_AUTOGEN_TARGET.rst
@@ -7,9 +7,10 @@
 
 When ``CMAKE_GLOBAL_AUTOGEN_TARGET`` is enabled, a custom target
 ``autogen`` is generated.  This target depends on all :prop_tgt:`AUTOMOC` and
-:prop_tgt:`AUTOUIC` generated :ref:`<ORIGIN>_autogen` targets in the project.
-By building the global ``autogen`` target, all :prop_tgt:`AUTOMOC` and
-:prop_tgt:`AUTOUIC` files in the project will be generated.
+:prop_tgt:`AUTOUIC` generated :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>`
+targets in the project.  By building the global ``autogen`` target, all
+:prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` files in the project will be
+generated.
 
 The name of the global ``autogen`` target can be changed by setting
 :variable:`CMAKE_GLOBAL_AUTOGEN_TARGET_NAME`.
@@ -21,7 +22,8 @@
 
 .. note::
 
-    :ref:`<ORIGIN>_autogen` targets by default inherit their origin target's
-    dependencies. This might result in unintended dependency target builds when
-    only :ref:`<ORIGIN>_autogen` targets are built.  A solution is to disable
-    :prop_tgt:`AUTOGEN_ORIGIN_DEPENDS` on the respective origin targets.
+    :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` targets by default inherit their
+    origin target's dependencies. This might result in unintended dependency
+    target builds when only :ref:`<ORIGIN>_autogen <<ORIGIN>_autogen>` targets
+    are built.  A solution is to disable :prop_tgt:`AUTOGEN_ORIGIN_DEPENDS` on
+    the respective origin targets.
diff --git a/Help/variable/CMAKE_INSTALL_OBJECT_NAME_STRATEGY.rst b/Help/variable/CMAKE_INSTALL_OBJECT_NAME_STRATEGY.rst
new file mode 100644
index 0000000..14cba99
--- /dev/null
+++ b/Help/variable/CMAKE_INSTALL_OBJECT_NAME_STRATEGY.rst
@@ -0,0 +1,8 @@
+CMAKE_INSTALL_OBJECT_NAME_STRATEGY
+----------------------------------
+
+Strategy to use for naming installed object files.
+
+``CMAKE_INSTALL_OBJECT_NAME_STRATEGY`` is used to initialize the
+:prop_tgt:`INSTALL_OBJECT_NAME_STRATEGY` property on all targets.  See that
+target property for more information.
diff --git a/Help/variable/CMAKE_LANG_LINK_MODE.rst b/Help/variable/CMAKE_LANG_LINK_MODE.rst
index 6025671..f8286e4 100644
--- a/Help/variable/CMAKE_LANG_LINK_MODE.rst
+++ b/Help/variable/CMAKE_LANG_LINK_MODE.rst
@@ -12,3 +12,8 @@
   The linker is used directly for the link step.
 
 This variable is read-only. Setting it is undefined behavior.
+
+See Also
+^^^^^^^^
+
+* The :variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` variable.
diff --git a/Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst b/Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst
index 7b252aa..a3d6c97 100644
--- a/Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst
+++ b/Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst
@@ -1,10 +1,17 @@
 CMAKE_<LANG>_USING_LINKER_MODE
 ------------------------------
 
+.. deprecated:: 4.0
+
+  This variable is no longer used.  The type of information stored in the
+  :variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` variable is determined by
+  the :variable:`CMAKE_<LANG>_LINK_MODE` variable.
+
 .. versionadded:: 3.29
 
-This controls how the value of the :variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>`
-variable should be interpreted. The supported linker mode values are:
+This variable controls how the value of the
+:variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` variable should be interpreted.
+The supported linker mode values are:
 
 ``FLAG``
   :variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` holds a
@@ -22,11 +29,5 @@
 
   * value ``TOOL`` is expected and required when the linker is used directly
     for the link step.
-  * value ``FLAGS`` is expected or the variable not set when the compiler is
+  * value ``FLAG`` is expected or the variable not set when the compiler is
     used as driver for the link step.
-
-.. deprecated:: 4.0
-
-This variable is no longer used. The type of information stored in the
-:variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` variable is determined by the
-:variable:`CMAKE_<LANG>_LINK_MODE` variable.
diff --git a/Modules/AddFileDependencies.cmake b/Modules/AddFileDependencies.cmake
index 13828f2..25a78a8 100644
--- a/Modules/AddFileDependencies.cmake
+++ b/Modules/AddFileDependencies.cmake
@@ -6,28 +6,38 @@
 -------------------
 
 .. deprecated:: 3.20
+  Do not use this module in new code.
 
-Add dependencies to a source file.
+  Instead use the :command:`set_property` command to append to the
+  :prop_sf:`OBJECT_DEPENDS` source file property directly:
+
+  .. code-block:: cmake
+
+    set_property(SOURCE <source> APPEND PROPERTY OBJECT_DEPENDS <files>...)
+
+Load this module in a CMake project with:
 
 .. code-block:: cmake
 
-  add_file_dependencies(<source> <files>...)
+  include(AddFileDependencies)
 
-Adds the given ``<files>`` to the dependencies of file ``<source>``.
+Commands
+^^^^^^^^
 
-Do not use this command in new code.  It is just a wrapper around:
+This module provides the following command:
 
-.. code-block:: cmake
+.. command:: add_file_dependencies
 
-  set_property(SOURCE <source> APPEND PROPERTY OBJECT_DEPENDS <files>...)
+  Adds dependencies to a source file:
 
-Instead use the :command:`set_property` command to append to the
-:prop_sf:`OBJECT_DEPENDS` source file property directly.
+  .. code-block:: cmake
 
+    add_file_dependencies(<source> <files>...)
+
+  This command adds the given ``<files>`` to the dependencies of file
+  ``<source>``.
 #]=======================================================================]
 
 function(add_file_dependencies _file)
-
   set_property(SOURCE "${_file}" APPEND PROPERTY OBJECT_DEPENDS "${ARGN}")
-
 endfunction()
diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake
index 4df5bb9..0c7fede 100644
--- a/Modules/BundleUtilities.cmake
+++ b/Modules/BundleUtilities.cmake
@@ -733,7 +733,9 @@
     string(REGEX REPLACE "rpath " "" load_cmds_ov "${load_cmds_ov}")
     if(load_cmds_ov)
       foreach(rpath ${load_cmds_ov})
-        gp_append_unique(${rpaths_var} "${rpath}")
+        if(NOT rpath IN_LIST ${rpaths_var})
+          list(APPEND ${rpaths_var} "${rpath}")
+        endif()
       endforeach()
     endif()
   endif()
@@ -744,7 +746,9 @@
     foreach(rpath ${rpath_var} ${runpath_var})
       # Substitute $ORIGIN with the exepath and add to the found rpaths
       string(REPLACE "$ORIGIN" "${item_dir}" rpath "${rpath}")
-      gp_append_unique(${rpaths_var} "${rpath}")
+      if(NOT rpath IN_LIST ${rpaths_var})
+        list(APPEND ${rpaths_var} "${rpath}")
+      endif()
     endforeach()
   endif()
 
@@ -787,7 +791,9 @@
   get_item_key("${item}" key)
 
   list(LENGTH ${keys_var} length_before)
-  gp_append_unique(${keys_var} "${key}")
+  if(NOT key IN_LIST ${keys_var})
+    list(APPEND ${keys_var} "${key}")
+  endif()
   list(LENGTH ${keys_var} length_after)
 
   if(NOT length_before EQUAL length_after)
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index ca69c38..edb3cc8 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -257,21 +257,27 @@
   # _CUDA_TARGET_DIR always points to the directory containing the include directory.
   # On a scattered installation /usr, on a non-scattered something like /usr/local/cuda or /usr/local/cuda-10.2/targets/aarch64-linux.
   if(EXISTS "${_CUDA_TARGET_DIR}/include/cuda_runtime.h")
-    set(_CUDA_INCLUDE_DIR "${_CUDA_TARGET_DIR}/include")
+    set(_CUDA_INCLUDE_DIRS "${_CUDA_TARGET_DIR}/include")
   else()
-    message(FATAL_ERROR "Unable to find cuda_runtime.h in \"${_CUDA_TARGET_DIR}/include\" for _CUDA_INCLUDE_DIR.")
+    message(FATAL_ERROR "Unable to find cuda_runtime.h in \"${_CUDA_TARGET_DIR}/include\" for _CUDA_INCLUDE_DIRS.")
+  endif()
+
+  # CUDA 13 has multiple includes that are implicitly added by nvcc that we need to replicate for
+  # clang-cuda
+  if(EXISTS "${_CUDA_TARGET_DIR}/include/cccl")
+    list(APPEND _CUDA_INCLUDE_DIRS "${_CUDA_TARGET_DIR}/include/cccl")
   endif()
 
   # Clang does not add any CUDA SDK libraries or directories when invoking the host linker.
   # Add the CUDA toolkit library directory ourselves so that linking works.
   # The CUDA runtime libraries are handled elsewhere by CMAKE_CUDA_RUNTIME_LIBRARY.
-  set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${_CUDA_INCLUDE_DIR}")
+  set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${_CUDA_INCLUDE_DIRS}")
   set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "${_CUDA_LIBRARY_DIR}")
   set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "")
   set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
 
   # Don't leak variables unnecessarily to user code.
-  unset(_CUDA_INCLUDE_DIR)
+  unset(_CUDA_INCLUDE_DIRS)
   unset(_CUDA_LIBRARY_DIR)
   unset(_CUDA_TARGET_DIR)
 elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
diff --git a/Modules/CMakeForceCompiler.cmake b/Modules/CMakeForceCompiler.cmake
index e85c3f9..9b85c68 100644
--- a/Modules/CMakeForceCompiler.cmake
+++ b/Modules/CMakeForceCompiler.cmake
@@ -9,66 +9,98 @@
 
   Do not use.
 
-The macros provided by this module were once intended for use by
-cross-compiling toolchain files when CMake was not able to automatically
-detect the compiler identification.  Since the introduction of this module,
-CMake's compiler identification capabilities have improved and can now be
-taught to recognize any compiler.  Furthermore, the suite of information
-CMake detects from a compiler is now too extensive to be provided by
-toolchain files using these macros.
+  The commands provided by this module were once intended for use by
+  cross-compiling toolchain files when CMake was not able to automatically
+  detect the compiler identification.  Since the introduction of this module,
+  CMake's compiler identification capabilities have improved and can now be
+  taught to recognize any compiler.  Furthermore, the suite of information
+  CMake detects from a compiler is now too extensive to be provided by
+  toolchain files using these macros.
 
-One common use case for this module was to skip CMake's checks for a
-working compiler when using a cross-compiler that cannot link binaries
-without special flags or custom linker scripts.  This case is now supported
-by setting the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable in the
-toolchain file instead.
+  One common use case for this module was to skip CMake's checks for a
+  working compiler when using a cross-compiler that cannot link binaries
+  without special flags or custom linker scripts.  This case is now supported
+  by setting the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable in the
+  toolchain file instead.
 
--------------------------------------------------------------------------
-
-Macro ``CMAKE_FORCE_C_COMPILER`` has the following signature:
+Load this module in a CMake toolchain file:
 
 .. code-block:: cmake
 
-   CMAKE_FORCE_C_COMPILER(<compiler> <compiler-id>)
+  include(CMakeForceCompiler)
 
-It sets :variable:`CMAKE_C_COMPILER <CMAKE_<LANG>_COMPILER>` to
-the given compiler and the cmake internal variable
-:variable:`CMAKE_C_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` to the given
-compiler-id.  It also bypasses the check for working compiler and basic
-compiler information tests.
+Commands
+^^^^^^^^
 
-Macro ``CMAKE_FORCE_CXX_COMPILER`` has the following signature:
+This module provides the following commands:
+
+.. command:: cmake_force_c_compiler
+
+  Sets the :variable:`CMAKE_C_COMPILER <CMAKE_<LANG>_COMPILER>` variable to
+  the given compiler and the :variable:`CMAKE_C_COMPILER_ID
+  <CMAKE_<LANG>_COMPILER_ID>` variable to the given compiler-id:
+
+  .. code-block:: cmake
+
+    cmake_force_c_compiler(<compiler> <compiler-id>)
+
+  This command also bypasses the check for working compiler and basic
+  compiler information tests.
+
+.. command:: cmake_force_cxx_compiler
+
+  Sets the :variable:`CMAKE_CXX_COMPILER <CMAKE_<LANG>_COMPILER>` variable
+  to the given compiler and the :variable:`CMAKE_CXX_COMPILER_ID
+  <CMAKE_<LANG>_COMPILER_ID>` variable to the given compiler-id:
+
+  .. code-block:: cmake
+
+    cmake_force_cxx_compiler(<compiler> <compiler-id>)
+
+  This command also bypasses the check for working compiler and basic
+  compiler information tests.
+
+.. command:: cmake_force_fortran_compiler
+
+  Sets the :variable:`CMAKE_Fortran_COMPILER <CMAKE_<LANG>_COMPILER>`
+  variable to the given compiler and the
+  :variable:`CMAKE_Fortran_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` variable
+  to the given compiler-id:
+
+  .. code-block:: cmake
+
+    cmake_force_fortran_compiler(<compiler> <compiler-id>)
+
+  This command also bypasses the check for working compiler and basic
+  compiler information tests.
+
+Examples
+^^^^^^^^
+
+A simple toolchain file using this module could look like this:
 
 .. code-block:: cmake
+  :caption: ``cmake/toolchains/example-toolchain.cmake``
 
-   CMAKE_FORCE_CXX_COMPILER(<compiler> <compiler-id>)
+  include(CMakeForceCompiler)
+  set(CMAKE_SYSTEM_NAME Generic)
+  cmake_force_c_compiler(chc12 MetrowerksHicross)
+  cmake_force_cxx_compiler(chc12 MetrowerksHicross)
 
-It sets :variable:`CMAKE_CXX_COMPILER <CMAKE_<LANG>_COMPILER>` to
-the given compiler and the cmake internal variable
-:variable:`CMAKE_CXX_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` to the given
-compiler-id.  It also bypasses the check for working compiler and basic
-compiler information tests.
-
-Macro ``CMAKE_FORCE_Fortran_COMPILER`` has the following signature:
+In new CMake code, compiler is detected automatically when setting required
+variables instead:
 
 .. code-block:: cmake
+  :caption: ``cmake/toolchains/example-toolchain.cmake``
 
-   CMAKE_FORCE_Fortran_COMPILER(<compiler> <compiler-id>)
+  set(CMAKE_SYSTEM_NAME Generic)
+  set(CMAKE_C_COMPILER chc12)
+  set(CMAKE_CXX_COMPILER chc12)
 
-It sets :variable:`CMAKE_Fortran_COMPILER <CMAKE_<LANG>_COMPILER>` to
-the given compiler and the cmake internal variable
-:variable:`CMAKE_Fortran_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` to the given
-compiler-id.  It also bypasses the check for working compiler and basic
-compiler information tests.
+See Also
+^^^^^^^^
 
-So a simple toolchain file could look like this:
-
-.. code-block:: cmake
-
-   include (CMakeForceCompiler)
-   set(CMAKE_SYSTEM_NAME Generic)
-   CMAKE_FORCE_C_COMPILER   (chc12 MetrowerksHicross)
-   CMAKE_FORCE_CXX_COMPILER (chc12 MetrowerksHicross)
+* :manual:`cmake-toolchains(7)`
 #]=======================================================================]
 
 macro(CMAKE_FORCE_C_COMPILER compiler id)
diff --git a/Modules/CMakeVerifyManifest.cmake b/Modules/CMakeVerifyManifest.cmake
index d98a49e..5333869 100644
--- a/Modules/CMakeVerifyManifest.cmake
+++ b/Modules/CMakeVerifyManifest.cmake
@@ -5,31 +5,53 @@
 CMakeVerifyManifest
 -------------------
 
-Use this script to verify that embedded manifests and side-by-side
-manifests for a project match.
+This module is intended to be used in command-line mode using the
+:ref:`cmake -P <Script Processing Mode>` to verify that embedded manifests
+and side-by-side manifests for a project match.
 
-This script first recursively globs ``*.manifest`` files from
-the current directory and creates a list of allowed version.
-Additional versions can be passed by setting ``allow_versions``
-from the invocation command.
-Next, the script globs ``*.exe`` and ``*.dll`` files.  Each
+Load this module in a CMake script with:
+
+.. code-block:: cmake
+
+  include(CMakeVerifyManifest)
+
+This module first recursively globs ``*.manifest`` files from
+the current source directory and creates a list of allowed versions.
+
+Next, the script globs all ``*.exe`` and ``*.dll`` files.  Each
 ``.exe`` and ``.dll`` file is scanned for embedded manifests and
 the versions of CRT are checked to be in the list of allowed
-version.
+versions.
 
-Example
-^^^^^^^
+Input Variables
+^^^^^^^^^^^^^^^
 
-To run this script, navigate to a directory and run the script
-with ``cmake -P``.
+This module accepts the following variables:
 
-::
+``allow_versions``
+  Additional versions can be passed by setting the ``allow_versions``
+  variable from the invocation command.  This enables using additional
+  embedded manifest versions in a project, even if that version was not
+  found in a ``.manifest`` file.
 
-  cmake -Dallow_versions=8.0.50608.0 -PCMakeVerifyManifest.cmake
+Examples
+^^^^^^^^
 
-This call allows an embedded manifest of 8.0.50608.0 to be used
-in a project, even if that version was not found in a
-``.manifest`` file.
+To use this module in the project, create a local command-line script (for
+example, in the project's subdirectory ``cmake/scripts``) and include the
+module:
+
+.. code-block:: cmake
+  :caption: ``cmake/scripts/verify-manifest.cmake``
+
+  include(CMakeVerifyManifest)
+
+Then run the local script in command-line and, for example, specify
+additional embedded manifest of ``8.0.50608.0`` to be used in a project:
+
+.. code-block:: shell
+
+  cmake -Dallow_versions=8.0.50608.0 -Pcmake/scripts/verify-manifest.cmake
 #]=======================================================================]
 
 # crt_version:
diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake
index c4b27da..6b83903 100644
--- a/Modules/FeatureSummary.cmake
+++ b/Modules/FeatureSummary.cmake
@@ -7,32 +7,45 @@
 FeatureSummary
 --------------
 
-Functions for generating a summary of enabled/disabled features.
+.. only:: html
 
-These functions can be used to generate a summary of enabled and disabled
-packages and/or features for a build tree such as::
+   .. contents::
 
-    -- The following features have been enabled:
+This module provides commands for generating a summary of enabled/disabled
+features.
 
-     * Example, usage example
+Load this module in CMake with:
 
-    -- The following OPTIONAL packages have been found:
+.. code-block:: cmake
 
-     * LibXml2 (required version >= 2.4), XML library, <http://xmlsoft.org>
-       Enables HTML-import in MyWordProcessor
-       Enables odt-export in MyWordProcessor
-     * PNG, image library, <http://www.libpng.org/pub/png/>
-       Enables saving screenshots
+  include(FeatureSummary)
 
-    -- The following OPTIONAL packages have not been found:
+Commands provided by this module can be used to generate a summary of enabled
+and disabled packages and/or features for a build tree such as::
 
-     * Lua, the Lua scripting language, <https://www.lua.org>
-       Enables macros in MyWordProcessor
-     * OpenGL, Open Graphics Library
+  -- The following features have been enabled:
+
+   * Example, usage example
+
+  -- The following OPTIONAL packages have been found:
+
+   * LibXml2 (required version >= 2.4), XML library, <http://xmlsoft.org>
+     Enables HTML-import in MyWordProcessor
+     Enables odt-export in MyWordProcessor
+   * PNG, image library, <http://www.libpng.org/pub/png/>
+     Enables saving screenshots
+
+  -- The following OPTIONAL packages have not been found:
+
+   * Lua, the Lua scripting language, <https://www.lua.org>
+     Enables macros in MyWordProcessor
+   * OpenGL, Open Graphics Library
 
 Global Properties
 ^^^^^^^^^^^^^^^^^
 
+The following global properties are used by this module:
+
 .. variable:: FeatureSummary_PKG_TYPES
 
   .. versionadded:: 3.8
@@ -69,8 +82,9 @@
 
   This global property defines the default package type.
 
-  When the :command:`feature_summary()` command is called, and the user has not
-  explicitly set a type of some package, its type will be set to this value.
+  When the :command:`feature_summary()` command is called, and the user has
+  not explicitly set a type of some package, its type will be set to the
+  value of this property.
 
   This value must be one of the types defined in the
   :variable:`FeatureSummary_PKG_TYPES` global property.
@@ -88,6 +102,519 @@
       The following <FeatureSummary_<TYPE>_DESCRIPTION> have been found:
 
   If not set, default string ``<TYPE> packages`` is used.
+
+Commands
+^^^^^^^^
+
+This module provides the following commands:
+
+* :command:`feature_summary`
+* :command:`set_package_properties`
+* :command:`add_feature_info`
+
+Printing Feature Summary
+""""""""""""""""""""""""
+
+.. command:: feature_summary
+
+  Prints information about enabled or disabled packages and features of a
+  project:
+
+  .. code-block:: cmake
+
+    feature_summary(
+      WHAT (ALL
+        | PACKAGES_FOUND | PACKAGES_NOT_FOUND
+        | <TYPE>_PACKAGES_FOUND | <TYPE>_PACKAGES_NOT_FOUND
+        | ENABLED_FEATURES | DISABLED_FEATURES)
+      [FILENAME <file>]
+      [APPEND]
+      [VAR <variable-name>]
+      [INCLUDE_QUIET_PACKAGES]
+      [FATAL_ON_MISSING_REQUIRED_PACKAGES]
+      [DESCRIPTION <description> | DEFAULT_DESCRIPTION]
+      [QUIET_ON_EMPTY]
+    )
+
+  This command can be used to print information about enabled or disabled
+  packages and features of a project.  By default, only the names of the
+  features/packages will be printed and their required version when one was
+  specified.  Use :command:`set_package_properties()` to add more useful
+  information, e.g., a homepage URL for the respective package or their
+  purpose in the project.
+
+  .. rubric:: The arguments are:
+
+  ``WHAT``
+    This is the only mandatory option.  It specifies what information will be
+    printed:
+
+    ``ALL``
+      Print everything.
+    ``ENABLED_FEATURES``
+      The list of all features which are enabled.
+    ``DISABLED_FEATURES``
+      The list of all features which are disabled.
+    ``PACKAGES_FOUND``
+      The list of all packages which have been found.
+    ``PACKAGES_NOT_FOUND``
+      The list of all packages which have not been found.
+
+    For each package type ``<TYPE>`` defined by the
+    :variable:`FeatureSummary_PKG_TYPES` global property, the following
+    information can also be used:
+
+    ``<TYPE>_PACKAGES_FOUND``
+      The list of only packages of type ``<TYPE>`` which have been found.
+    ``<TYPE>_PACKAGES_NOT_FOUND``
+      The list of only packages of type ``<TYPE>`` which have not been found.
+
+    .. versionchanged:: 3.1
+      The ``WHAT`` option is now a multi-value keyword, so that these values can
+      be combined, with the exception of the ``ALL`` value, in order to
+      customize the output.  For example:
+
+    .. code-block:: cmake
+
+      feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)
+
+  ``FILENAME <file>``
+    If this option is given, the information is printed into this file instead
+    of the terminal.  Relative ``<file>`` path is interpreted as being relative
+    to the current source directory (i.e. :variable:`CMAKE_CURRENT_SOURCE_DIR`).
+
+  ``APPEND``
+    If this option is given, the output is appended to the ``<file>`` provided
+    by the ``FILENAME`` option, otherwise the file is overwritten if it already
+    exists.
+
+  ``VAR <variable-name>``
+    If this option is given, the information is stored into the specified
+    variable ``<variable-name>`` instead of the terminal.
+
+  ``INCLUDE_QUIET_PACKAGES``
+    If this option is given, packages which have been searched with
+    :command:`find_package(... QUIET)` will also be listed.  By default they are
+    skipped.
+
+  ``FATAL_ON_MISSING_REQUIRED_PACKAGES``
+    If this option is given, CMake will abort with fatal error if a package
+    which is marked as one of the package types listed in the
+    :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global property has not been
+    found.
+
+  ``DESCRIPTION <description>``
+    A description or headline which will be printed above the actual content.
+    Without this option, if only one package type was requested, no title is
+    printed, unless a custom string is explicitly set using this option or
+    ``DEFAULT_DESCRIPTION`` option is used that outputs a default title for the
+    requested type.
+
+  ``DEFAULT_DESCRIPTION``
+    .. versionadded:: 3.9
+
+    The default description or headline to be printed above the content as
+    opposed to the customizable ``DESCRIPTION <description>``.
+
+  ``QUIET_ON_EMPTY``
+    .. versionadded:: 3.8
+
+    If this option is given, when only one package type was requested, and no
+    packages belonging to that category were found, then no output (including
+    the ``DESCRIPTION``) is printed nor added to the ``FILENAME``, or the
+    ``VAR`` variable.
+
+Package Properties
+""""""""""""""""""
+
+.. command:: set_package_properties
+
+  Sets package properties:
+
+  .. code-block:: cmake
+
+    set_package_properties(
+      <PackageName>
+      PROPERTIES
+        [URL <url>]
+        [DESCRIPTION <description>]
+        [TYPE (RUNTIME|OPTIONAL|RECOMMENDED|REQUIRED)]
+        [PURPOSE <purpose>]
+    )
+
+  Use this command to configure and provide information about the package
+  named ``<PackageName>``, which can then be displayed using the
+  :command:`feature_summary()` command.  This command can be called either
+  directly within the corresponding :ref:`Find module <Find Modules>` or in
+  the project that uses the module after invoking the :command:`find_package()`
+  call.  The features for which information can be set are determined
+  automatically after the :command:`find_package()` command.
+
+  .. rubric:: The arguments are:
+
+  ``<PackageName>``
+    The name of the package.  For example, as specified in the
+    :command:`find_package(<PackageName>)` argument.
+
+  ``PROPERTIES``
+    Specifies the properties to set:
+
+    ``URL <url>``
+      This should be the homepage of the package, or something similar.
+      Ideally this is set already directly in the
+      :ref:`Find module <Find Modules>`.
+
+    ``DESCRIPTION <description>``
+      A short description what that package is, at most one sentence.
+      Ideally this is set already directly in the
+      :ref:`Find module <Find Modules>`.
+
+    ``TYPE <type>``
+      What type of dependency has the using project on that package.
+
+      Default ``<type>`` is ``OPTIONAL``.  In this case it is a package
+      which can be used by the project when available at buildtime, but the
+      project also works without it.
+
+      ``RECOMMENDED`` package type is similar to ``OPTIONAL``, i.e.  the
+      project will build if the package is not present, but the
+      functionality of the resulting binaries will be severely limited.  If
+      a ``REQUIRED`` package is not available at buildtime, the project may
+      not even build. This can be combined with the
+      :command:`feature_summary(FATAL_ON_MISSING_REQUIRED_PACKAGES)` command
+      option.
+
+      Last, a ``RUNTIME`` package is a package which is actually not used
+      at all during the build, but which is required for actually running
+      the resulting binaries.  So if such a package is missing, the project
+      can still be built, but it may not work later on.
+
+      If ``set_package_properties()`` is called multiple times for the same
+      package with different TYPEs, the ``TYPE`` is only changed to higher
+      TYPEs (``RUNTIME < OPTIONAL < RECOMMENDED < REQUIRED``), lower TYPEs
+      are ignored.  The ``TYPE`` property is project-specific, so it cannot
+      be set by the :ref:`Find module <Find Modules>`, but must be set in
+      the project.
+
+      The accepted types can be changed by setting the
+      :variable:`FeatureSummary_PKG_TYPES` global property.
+
+    ``PURPOSE <purpose>``
+      This describes which features this package enables in the project,
+      i.e.  it tells the user what functionality they get in the resulting
+      binaries.  If ``set_package_properties()`` is called multiple times
+      for a package, all ``PURPOSE`` properties are appended to a list of
+      purposes of the package in the project.  As the ``TYPE`` property,
+      also the ``PURPOSE`` property is project-specific, so it cannot be
+      set by the :ref:`Find module <Find Modules>`, but must be set in the
+      project.
+
+Adding Feature Info
+"""""""""""""""""""
+
+.. command:: add_feature_info
+
+  Adds feature information:
+
+  .. code-block:: cmake
+
+    add_feature_info(<name> <condition> <description>)
+
+  Use this command to add information about a feature identified with a given
+  ``<name>``.
+
+  .. rubric:: The arguments are:
+
+  ``<name>``
+    Identification name for a feature being added.
+
+  ``<condition>``
+    Specifies the conditions that determine whether this feature is enabled
+    or disabled.
+
+    The ``<condition>`` argument can be:
+
+    * A single condition (such as a variable name).
+
+    * .. versionadded:: 3.8
+        A :ref:`semicolon-separated list <CMake Language Lists>` of multiple
+        conditions.
+
+    * .. versionadded:: 4.0
+        A full :ref:`Condition Syntax` as used in an ``if(<condition>)``
+        clause.  See policy :policy:`CMP0183`.  This enables using entire
+        condition syntax (such as grouping conditions with parens and
+        similar).
+
+  ``<description>``
+    A text describing the feature.  This information can be displayed using
+    :command:`feature_summary()` for ``ENABLED_FEATURES`` and
+    ``DISABLED_FEATURES`` respectively.
+
+Deprecated Commands
+"""""""""""""""""""
+
+The following legacy and deprecated commands are provided for backward
+compatibility with previous CMake versions:
+
+.. command:: set_package_info
+
+  .. deprecated:: 3.8
+    Use the :command:`set_package_properties`, and :command:`add_feature_info`
+    commands instead.
+
+  Sets up information about the specified package, which can then be displayed
+  via :command:`feature_summary()`:
+
+  .. code-block:: cmake
+
+    set_package_info(<PackageName> <description> [<url> [<purpose>]])
+
+  ``<PackageName>``
+    Name of the package.
+
+  ``<description>``
+    A short description of the package.
+
+  ``<url>``
+    Homepage of the package.
+
+  ``<purpose>``
+    The purpose of the package.
+
+  This command can be used either directly in the
+  :ref:`Find module <Find Modules>` or in the project which uses the
+  ``FeatureSummary`` module after the :command:`find_package()` call.  The
+  features for which information can be set are added automatically by the
+  ``find_package()`` command.
+
+.. command:: set_feature_info
+
+  .. deprecated:: 3.8
+
+  Sets feature info for a package:
+
+  .. code-block:: cmake
+
+    set_feature_info(<name> <description> [<url>])
+
+  Does the same as:
+
+  .. code-block:: cmake
+
+    set_package_info(<name> <description> [<url>])
+
+.. command:: print_enabled_features
+
+  .. deprecated:: 3.8
+
+  Prints enabled features:
+
+  .. code-block:: cmake
+
+    print_enabled_features()
+
+  Does the same as:
+
+  .. code-block:: cmake
+
+    feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
+
+.. command:: print_disabled_features
+
+  .. deprecated:: 3.8
+
+  Prints disabled features:
+
+  .. code-block:: cmake
+
+    print_disabled_features()
+
+  Does the same as:
+
+  .. code-block:: cmake
+
+    feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
+
+Examples
+^^^^^^^^
+
+Example: Appending Feature Summary to a File
+""""""""""""""""""""""""""""""""""""""""""""
+
+In the following example, the feature summary output will be appended to
+a specified file instead of printing:
+
+.. code-block:: cmake
+
+  include(FeatureSummary)
+  feature_summary(WHAT ALL FILENAME ${CMAKE_BINARY_DIR}/all.log APPEND)
+
+Example: Storing Feature Summary in a Variable
+""""""""""""""""""""""""""""""""""""""""""""""
+
+In the following example, the feature summary of enabled features is stored
+in a specified variable ``enabledFeaturesText``, including the ``QUIET``
+packages:
+
+.. code-block:: cmake
+
+  include(FeatureSummary)
+
+  feature_summary(
+    WHAT ENABLED_FEATURES
+    INCLUDE_QUIET_PACKAGES
+    DESCRIPTION "Enabled Features:"
+    VAR enabledFeaturesText
+  )
+
+  message(STATUS "${enabledFeaturesText}")
+
+Example: Adding a Custom Package Type
+"""""""""""""""""""""""""""""""""""""
+
+In the following example a custom package type is added and printed only
+the categories that are not empty:
+
+.. code-block:: cmake
+
+  include(FeatureSummary)
+
+  set_property(GLOBAL APPEND PROPERTY FeatureSummary_PKG_TYPES BUILD)
+
+  find_package(FOO)
+  set_package_properties(FOO PROPERTIES TYPE BUILD)
+
+  feature_summary(
+    WHAT BUILD_PACKAGES_FOUND
+    DESCRIPTION "Build tools found:"
+    QUIET_ON_EMPTY
+  )
+
+  feature_summary(
+    WHAT BUILD_PACKAGES_NOT_FOUND
+    DESCRIPTION "Build tools not found:"
+    QUIET_ON_EMPTY
+  )
+
+Example: Setting Package Info
+"""""""""""""""""""""""""""""
+
+Example for setting the info for a package:
+
+.. code-block:: cmake
+
+  include(FeatureSummary)
+
+  find_package(LibXml2)
+  set_package_properties(
+    LibXml2
+    PROPERTIES
+      DESCRIPTION "XML library"
+      URL "http://xmlsoft.org"
+  )
+  # or
+  set_package_properties(
+    LibXml2
+    PROPERTIES
+      TYPE RECOMMENDED
+      PURPOSE "Enables HTML-import in MyWordProcessor"
+  )
+  # or
+  set_package_properties(
+    LibXml2
+    PROPERTIES
+      TYPE OPTIONAL
+      PURPOSE "Enables odt-export in MyWordProcessor"
+  )
+
+  find_package(DBUS)
+  set_package_properties(
+    DBUS
+    PROPERTIES
+      TYPE RUNTIME
+      PURPOSE "Necessary to disable the screensaver during a presentation"
+  )
+
+Example: Printing Feature Summary
+"""""""""""""""""""""""""""""""""
+
+In the following example, this module is used to output feature summary at
+the end of the configuration.  If any required package is not found,
+processing stops with an error message at the end of the configuration
+phase.
+
+.. code-block:: cmake
+
+  cmake_minimum_required(VERSION 3.15)
+  project(Example)
+
+  add_library(example example.c)
+
+  include(FeatureSummary)
+
+  find_package(CURL)
+  set_package_properties(CURL PROPERTIES TYPE REQUIRED)
+  target_link_libraries(example PRIVATE CURL::libcurl)
+
+  find_package(LibXml2 QUIET)
+  set_package_properties(LibXml2 PROPERTIES TYPE RECOMMENDED)
+  if(LibXml2_FOUND)
+    target_link_libraries(example PRIVATE LibXml2::LibXml2)
+  endif()
+
+  feature_summary(
+    WHAT ALL
+    INCLUDE_QUIET_PACKAGES
+    DESCRIPTION "Feature summary:"
+    FATAL_ON_MISSING_REQUIRED_PACKAGES
+  )
+
+Examples: Setting Feature Info
+""""""""""""""""""""""""""""""
+
+Example for setting the info for a feature:
+
+.. code-block:: cmake
+
+  include(FeatureSummary)
+
+  option(WITH_FOO "Help for foo" ON)
+
+  add_feature_info(Foo WITH_FOO "this feature provides very cool stuff")
+
+Example for setting feature info based on a list of conditions:
+
+.. code-block:: cmake
+
+  include(FeatureSummary)
+
+  option(WITH_FOO "Help for foo" ON)
+  option(WITH_BAR "Help for bar" OFF)
+
+  add_feature_info(
+    FooBar
+    "WITH_FOO;NOT WITH_BAR"
+    "this feature is enabled when WITH_FOO is ON and WITH_BAR turned OFF"
+  )
+
+In the next example feature info are set depending on a full condition
+syntax.  Unlike semicolon-separated list of conditions, this enables using
+entire condition syntax as being the ``if`` clause argument:
+
+.. code-block:: cmake
+
+  include(FeatureSummary)
+
+  option(WITH_FOO "Help for foo" ON)
+  option(WITH_BAR "Help for bar" ON)
+  option(WITH_BAZ "Help for baz" OFF)
+
+  add_feature_info(
+    FooBarBaz
+    "WITH_FOO AND (WITH_BAR OR WITH_BAZ)"
+    "this feature is enabled when the entire condition is true"
+  )
 #]=======================================================================]
 
 get_property(_fsPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_PKG_TYPES SET)
@@ -105,15 +632,7 @@
   set_property(GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE OPTIONAL)
 endif()
 
-#[=======================================================================[.rst:
-
-Functions
-^^^^^^^^^
-
-#]=======================================================================]
-
 function(_FS_GET_FEATURE_SUMMARY _property _var _includeQuiet)
-
   get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES)
   get_property(_fsDefaultPkgType GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE)
 
@@ -208,155 +727,6 @@
   set(${_var} "${_currentFeatureText}" PARENT_SCOPE)
 endfunction()
 
-
-#[=======================================================================[.rst:
-.. command:: feature_summary
-
-  .. code-block:: cmake
-
-    feature_summary([FILENAME <file>]
-                    [APPEND]
-                    [VAR <variable_name>]
-                    [INCLUDE_QUIET_PACKAGES]
-                    [FATAL_ON_MISSING_REQUIRED_PACKAGES]
-                    [DESCRIPTION <description> | DEFAULT_DESCRIPTION]
-                    [QUIET_ON_EMPTY]
-                    WHAT (ALL
-                         | PACKAGES_FOUND | PACKAGES_NOT_FOUND
-                         | <TYPE>_PACKAGES_FOUND | <TYPE>_PACKAGES_NOT_FOUND
-                         | ENABLED_FEATURES | DISABLED_FEATURES)
-                   )
-
-  This function can be used to print information about
-  enabled or disabled packages and features of a project.  By default,
-  only the names of the features/packages will be printed and their
-  required version when one was specified.  Use
-  :command:`set_package_properties()` to add more useful information, like e.g.
-  a homepage URL for the respective package or their purpose in the project.
-
-  The options are:
-
-  ``WHAT``
-    This is the only mandatory option.  It specifies what information will be
-    printed:
-
-    ``ALL``
-      Print everything.
-    ``ENABLED_FEATURES``
-      The list of all features which are enabled.
-    ``DISABLED_FEATURES``
-      The list of all features which are disabled.
-    ``PACKAGES_FOUND``
-      The list of all packages which have been found.
-    ``PACKAGES_NOT_FOUND``
-      The list of all packages which have not been found.
-
-    For each package type ``<TYPE>`` defined by the
-    :variable:`FeatureSummary_PKG_TYPES` global property, the following
-    information can also be used:
-
-    ``<TYPE>_PACKAGES_FOUND``
-      The list of only packages of type ``<TYPE>`` which have been found.
-    ``<TYPE>_PACKAGES_NOT_FOUND``
-      The list of only packages of type ``<TYPE>`` which have not been found.
-
-    .. versionchanged:: 3.1
-      The ``WHAT`` option is now a multi-value keyword, so that these values can
-      be combined, with the exception of the ``ALL`` value, in order to
-      customize the output.  For example:
-
-    .. code-block:: cmake
-
-      feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)
-
-  ``FILENAME <file>``
-    If this option is given, the information is printed into this file instead
-    of the terminal.  Relative ``<file>`` path is interpreted as being relative
-    to the current source directory (i.e. :variable:`CMAKE_CURRENT_SOURCE_DIR`).
-
-  ``APPEND``
-    If this option is given, the output is appended to the ``<file>`` provided
-    by the ``FILENAME`` option, otherwise the file is overwritten if it already
-    exists.
-
-  ``VAR <variable_name>``
-    If this option is given, the information is stored into the specified
-    variable ``<variable_name>`` instead of the terminal.
-
-  ``DESCRIPTION <description>``
-    A description or headline which will be printed above the actual content.
-    Without this option, if only one package type was requested, no title is
-    printed, unless a custom string is explicitly set using this option or
-    ``DEFAULT_DESCRIPTION`` option is used that outputs a default title for the
-    requested type.
-
-  ``DEFAULT_DESCRIPTION``
-    .. versionadded:: 3.9
-
-    The default description or headline to be printed above the content as
-    opposed to the customizable ``DESCRIPTION <description>``.
-
-  ``INCLUDE_QUIET_PACKAGES``
-    If this option is given, packages which have been searched with
-    :command:`find_package(... QUIET)` will also be listed.  By default they are
-    skipped.
-
-  ``FATAL_ON_MISSING_REQUIRED_PACKAGES``
-    If this option is given, CMake will abort with fatal error if a package
-    which is marked as one of the package types listed in the
-    :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global property has not been
-    found.
-
-  The :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global property can be
-  modified to change the default package type assigned when not explicitly
-  assigned by the user.
-
-  ``QUIET_ON_EMPTY``
-    .. versionadded:: 3.8
-
-    If this option is given, when only one package type was requested, and no
-    packages belonging to that category were found, then no output (including
-    the ``DESCRIPTION``) is printed nor added to the ``FILENAME``, or the
-    ``VAR`` variable.
-
-  Example 1, append everything to a file:
-
-  .. code-block:: cmake
-
-   include(FeatureSummary)
-   feature_summary(WHAT ALL
-                   FILENAME ${CMAKE_BINARY_DIR}/all.log APPEND)
-
-  Example 2, print the enabled features into the variable
-  ``enabledFeaturesText``, including the ``QUIET`` packages:
-
-  .. code-block:: cmake
-
-    include(FeatureSummary)
-    feature_summary(WHAT ENABLED_FEATURES
-                   INCLUDE_QUIET_PACKAGES
-                   DESCRIPTION "Enabled Features:"
-                   VAR enabledFeaturesText)
-    message(STATUS "${enabledFeaturesText}")
-
-  Example 3, add custom package type and print only the categories that are not
-  empty:
-
-  .. code-block:: cmake
-
-    include(FeatureSummary)
-    set_property(GLOBAL APPEND PROPERTY FeatureSummary_PKG_TYPES BUILD)
-    find_package(FOO)
-    set_package_properties(FOO PROPERTIES TYPE BUILD)
-    feature_summary(WHAT BUILD_PACKAGES_FOUND
-                    DESCRIPTION "Build tools found:"
-                    QUIET_ON_EMPTY)
-    feature_summary(WHAT BUILD_PACKAGES_NOT_FOUND
-                    DESCRIPTION "Build tools not found:"
-                    QUIET_ON_EMPTY)
-
-#]=======================================================================]
-
 function(FEATURE_SUMMARY)
 # cmake_parse_arguments(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)
   set(options APPEND
@@ -498,93 +868,8 @@
   if(requiredPackagesNotFound  AND  _FS_FATAL_ON_MISSING_REQUIRED_PACKAGES)
     message(FATAL_ERROR "feature_summary() Error: REQUIRED package(s) are missing, aborting CMake run.")
   endif()
-
 endfunction()
 
-#[=======================================================================[.rst:
-.. command:: set_package_properties
-
-  .. code-block:: cmake
-
-    set_package_properties(<name> PROPERTIES
-                           [URL <url>]
-                           [DESCRIPTION <description>]
-                           [TYPE (RUNTIME|OPTIONAL|RECOMMENDED|REQUIRED)]
-                           [PURPOSE <purpose>]
-                          )
-
-  Use this function to configure and provide information about the package named
-  ``<name>``, which can then be displayed using the
-  :command:`feature_summary()` command.  This can be performed either directly
-  within the corresponding :ref:`Find module <Find Modules>` or in the project
-  that uses the module after invoking the :command:`find_package()` call.  The
-  features for which information can be set are determined automatically after
-  the :command:`find_package()` command.
-
-  ``URL <url>``
-    This should be the homepage of the package, or something similar.
-    Ideally this is set already directly in the
-    :ref:`Find module <Find Modules>`.
-
-  ``DESCRIPTION <description>``
-    A short description what that package is, at most one sentence.
-    Ideally this is set already directly in the
-    :ref:`Find module <Find Modules>`.
-
-  ``TYPE <type>``
-    What type of dependency has the using project on that package.
-    Default is ``OPTIONAL``.  In this case it is a package which can be used
-    by the project when available at buildtime, but it also work without.
-    ``RECOMMENDED`` is similar to ``OPTIONAL``, i.e.  the project will build if
-    the package is not present, but the functionality of the resulting
-    binaries will be severely limited.  If a ``REQUIRED`` package is not
-    available at buildtime, the project may not even build.  This can be
-    combined with the
-    :command:`feature_summary(FATAL_ON_MISSING_REQUIRED_PACKAGES)` command
-    option.  Last, a ``RUNTIME`` package is a package which is actually not used
-    at all during the build, but which is required for actually running the
-    resulting binaries.  So if such a package is
-    missing, the project can still be built, but it may not work later on.
-    If ``set_package_properties()`` is called multiple times for the same
-    package with different TYPEs, the ``TYPE`` is only changed to higher
-    TYPEs (``RUNTIME < OPTIONAL < RECOMMENDED < REQUIRED``), lower TYPEs are
-    ignored.  The ``TYPE`` property is project-specific, so it cannot be set
-    by the :ref:`Find module <Find Modules>`, but must be set in the project.
-    The accepted types can be changed by setting the
-    :variable:`FeatureSummary_PKG_TYPES` global property.
-
-  ``PURPOSE <purpose>``
-    This describes which features this package enables in the
-    project, i.e.  it tells the user what functionality they get in the
-    resulting binaries.  If ``set_package_properties()`` is called multiple
-    times for a package, all ``PURPOSE`` properties are appended to a list of
-    purposes of the package in the project.  As the ``TYPE`` property, also
-    the ``PURPOSE`` property is project-specific, so it cannot be set by the
-    :ref:`Find module <Find Modules>`, but must be set in the project.
-
-  Example for setting the info for a package:
-
-  .. code-block:: cmake
-
-    include(FeatureSummary)
-    find_package(LibXml2)
-    set_package_properties(LibXml2 PROPERTIES
-                           DESCRIPTION "XML library"
-                           URL "http://xmlsoft.org")
-    # or
-    set_package_properties(LibXml2 PROPERTIES
-                           TYPE RECOMMENDED
-                           PURPOSE "Enables HTML-import in MyWordProcessor")
-    # or
-    set_package_properties(LibXml2 PROPERTIES
-                           TYPE OPTIONAL
-                           PURPOSE "Enables odt-export in MyWordProcessor")
-
-    find_package(DBUS)
-    set_package_properties(DBUS PROPERTIES
-      TYPE RUNTIME
-      PURPOSE "Necessary to disable the screensaver during a presentation")
-#]=======================================================================]
 function(SET_PACKAGE_PROPERTIES _name _props)
   if(NOT "${_props}" STREQUAL "PROPERTIES")
     message(FATAL_ERROR "PROPERTIES keyword is missing in SET_PACKAGE_PROPERTIES() call.")
@@ -609,7 +894,6 @@
     set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_SPP_DESCRIPTION}" )
   endif()
 
-
   if(_SPP_URL)
     get_property(_info  GLOBAL PROPERTY _CMAKE_${_name}_URL)
     if(_info AND NOT "${_info}" STREQUAL "${_SPP_URL}")
@@ -619,7 +903,6 @@
     set_property(GLOBAL PROPERTY _CMAKE_${_name}_URL "${_SPP_URL}" )
   endif()
 
-
   # handle the PURPOSE: use APPEND, since there can be multiple purposes for one package inside a project
   if(_SPP_PURPOSE)
     set_property(GLOBAL APPEND PROPERTY _CMAKE_${_name}_PURPOSE "${_SPP_PURPOSE}" )
@@ -648,68 +931,8 @@
       set_property(GLOBAL PROPERTY _CMAKE_${_name}_TYPE "${_SPP_TYPE}" )
     endif()
   endif()
-
 endfunction()
 
-#[=======================================================================[.rst:
-.. command:: add_feature_info
-
-  .. code-block:: cmake
-
-    add_feature_info(<name> <enabled> <description>)
-
-  Use this function to add information about a feature identified with a given
-  ``<name>``.  The ``<enabled>`` contains whether this feature is enabled or
-  not.  It can be a variable or a list of conditions.
-  ``<description>`` is a text describing the feature.  The information can
-  be displayed using :command:`feature_summary()` for ``ENABLED_FEATURES`` and
-  ``DISABLED_FEATURES`` respectively.
-
-  .. versionchanged:: 3.8
-    ``<enabled>`` can be a list of conditions.
-
-  .. versionchanged:: 4.0
-    Full :ref:`Condition Syntax` is now supported for ``<enabled>``.
-    See policy :policy:`CMP0183`.
-
-  Example for setting the info for a feature:
-
-  .. code-block:: cmake
-
-    include(FeatureSummary)
-
-    option(WITH_FOO "Help for foo" ON)
-    add_feature_info(Foo WITH_FOO "this feature provides very cool stuff")
-
-  Example for setting feature info based on a list of conditions:
-
-  .. code-block:: cmake
-
-    option(WITH_FOO "Help for foo" ON)
-    option(WITH_BAR "Help for bar" OFF)
-    add_feature_info(
-      FooBar
-      "WITH_FOO;NOT WITH_BAR"
-      "this feature is enabled when WITH_FOO is ON and WITH_BAR turned OFF"
-    )
-
-  Example for setting feature info depending on a full condition syntax:
-
-  Unlike semicolon-separated list of conditions, this enables using entire
-  condition syntax as being the ``if`` clause argument, such as grouping
-  conditions with parens and similar.
-
-  .. code-block:: cmake
-
-    option(WITH_FOO "Help for foo" ON)
-    option(WITH_BAR "Help for bar" ON)
-    option(WITH_BAZ "Help for baz" OFF)
-    add_feature_info(
-      FooBarBaz
-      "WITH_FOO AND (WITH_BAR OR WITH_BAZ)"
-      "this feature is enabled when the entire condition is true"
-    )
-#]=======================================================================]
 function(ADD_FEATURE_INFO _name _depends _desc)
   cmake_policy(GET CMP0183 _CDO_CMP0183
     PARENT_SCOPE # undocumented, do not use outside of CMake
@@ -749,34 +972,8 @@
   unset(_CDO_CMP0183)
 endfunction()
 
-
 # The stuff below is only kept for compatibility
 
-#[=======================================================================[.rst:
-Deprecated Functions
-^^^^^^^^^^^^^^^^^^^^
-
-The following legacy and deprecated functions are provided for backward
-compatibility with previous CMake versions:
-
-.. command:: set_package_info
-
-  .. deprecated:: 3.8
-
-  .. code-block:: cmake
-
-    set_package_info(<name> <description> [ <url> [<purpose>] ])
-
-  Set up information about the package ``<name>``, which can then be displayed
-  via :command:`feature_summary()`.  This can be done either directly in the
-  :ref:`Find module <Find Modules>` or in the project which uses the
-  ``FeatureSummary`` module after the :command:`find_package()` call.  The
-  features for which information can be set are added automatically by the
-  ``find_package()`` command.
-
-  This function is deprecated.  Use the :command:`set_package_properties()`, and
-  :command:`add_feature_info()` functions instead.
-#]=======================================================================]
 function(SET_PACKAGE_INFO _name _desc)
   message(DEPRECATION "SET_PACKAGE_INFO is deprecated. Use SET_PACKAGE_PROPERTIES instead.")
   unset(_url)
@@ -796,62 +993,17 @@
   endif()
 endfunction()
 
-#[=======================================================================[.rst:
-.. command:: set_feature_info
-
-  .. deprecated:: 3.8
-
-  .. code-block:: cmake
-
-    set_feature_info(<name> <description> [<url>])
-
-  Does the same as:
-
-  .. code-block:: cmake
-
-    set_package_info(<name> <description> [<url>])
-#]=======================================================================]
 function(SET_FEATURE_INFO)
   message(DEPRECATION "SET_FEATURE_INFO is deprecated. Use ADD_FEATURE_INFO instead.")
   set_package_info(${ARGN})
 endfunction()
 
-#[=======================================================================[.rst:
-.. command:: print_enabled_features
-
-  .. deprecated:: 3.8
-
-  .. code-block:: cmake
-
-    print_enabled_features()
-
-  Does the same as:
-
-  .. code-block:: cmake
-
-    feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
-#]=======================================================================]
 function(PRINT_ENABLED_FEATURES)
   message(DEPRECATION "PRINT_ENABLED_FEATURES is deprecated. Use
     feature_summary(WHAT ENABLED_FEATURES DESCRIPTION \"Enabled features:\")")
   feature_summary(WHAT ENABLED_FEATURES  DESCRIPTION "Enabled features:")
 endfunction()
 
-#[=======================================================================[.rst:
-.. command:: print_disabled_features
-
-  .. deprecated:: 3.8
-
-  .. code-block:: cmake
-
-    print_disabled_features()
-
-  Does the same as:
-
-  .. code-block:: cmake
-
-    feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
-#]=======================================================================]
 function(PRINT_DISABLED_FEATURES)
   message(DEPRECATION "PRINT_DISABLED_FEATURES is deprecated. Use
     feature_summary(WHAT DISABLED_FEATURES DESCRIPTION \"Disabled features:\")")
diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake
index f8e5575..019d45f 100644
--- a/Modules/FindDevIL.cmake
+++ b/Modules/FindDevIL.cmake
@@ -9,7 +9,11 @@
 
 .. code-block:: cmake
 
-  find_package(DevIL [...])
+  find_package(DevIL [<version>] [...])
+
+.. versionadded:: 4.2
+  Support for the ``<version>`` argument in the :command:`find_package`
+  call.  Version can be also specified as a range.
 
 The DevIL package internally consists of the following libraries, all
 distributed as part of the same release:
@@ -62,8 +66,13 @@
 This module defines the following variables:
 
 ``DevIL_FOUND``
-  Boolean indicating whether the DevIL package is found, including the IL and
-  ILU libraries.
+  Boolean indicating whether the (requested version of) DevIL package is
+  found, including the IL and ILU libraries.
+
+``DevIL_VERSION``
+  .. versionadded:: 4.2
+
+  The version of the DevIL found.
 
 ``DevIL_ILUT_FOUND``
   .. versionadded:: 3.21
@@ -113,8 +122,8 @@
   target_link_libraries(app PRIVATE DevIL::ILUT)
 #]=======================================================================]
 
-# TODO: Add version support.
-# Tested under Linux and Windows (MSVC)
+cmake_policy(PUSH)
+cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
 
 include(FindPackageHandleStandardArgs)
 
@@ -123,35 +132,62 @@
   DOC "The path to the directory that contains il.h"
 )
 
-#message("IL_INCLUDE_DIR is ${IL_INCLUDE_DIR}")
-
 find_library(IL_LIBRARIES
   NAMES IL DEVIL
   PATH_SUFFIXES libx32 lib64 lib lib32
   DOC "The file that corresponds to the base il library."
 )
 
-#message("IL_LIBRARIES is ${IL_LIBRARIES}")
-
 find_library(ILUT_LIBRARIES
   NAMES ILUT
   PATH_SUFFIXES libx32 lib64 lib lib32
   DOC "The file that corresponds to the il (system?) utility library."
 )
 
-#message("ILUT_LIBRARIES is ${ILUT_LIBRARIES}")
-
 find_library(ILU_LIBRARIES
   NAMES ILU
   PATH_SUFFIXES libx32 lib64 lib lib32
   DOC "The file that corresponds to the il utility library."
 )
 
-#message("ILU_LIBRARIES is ${ILU_LIBRARIES}")
+# Get version.
+block(PROPAGATE DevIL_VERSION)
+  if(IL_INCLUDE_DIR AND EXISTS "${IL_INCLUDE_DIR}/il.h")
+    set(regex "^[ \t]*#[ \t]*define[ \t]+IL_VERSION[ \t]+([0-9]+)[ \t]*$")
 
-find_package_handle_standard_args(DevIL DEFAULT_MSG
-                                  IL_LIBRARIES ILU_LIBRARIES
-                                  IL_INCLUDE_DIR)
+    file(STRINGS ${IL_INCLUDE_DIR}/il.h result REGEX "${regex}")
+
+    if(result MATCHES "${regex}")
+      set(DevIL_VERSION "${CMAKE_MATCH_1}")
+
+      math(EXPR DevIL_VERSION_MAJOR "${DevIL_VERSION} / 100")
+      math(EXPR DevIL_VERSION_MINOR "${DevIL_VERSION} / 10 % 10")
+      math(EXPR DevIL_VERSION_PATCH "${DevIL_VERSION} % 10")
+
+      set(DevIL_VERSION "")
+      foreach(part MAJOR MINOR PATCH)
+        if(DevIL_VERSION)
+          string(APPEND ".${DevIL_VERSION_${part}}")
+        else()
+          set(DevIL_VERSION "${DevIL_VERSION_${part}}")
+        endif()
+
+        set(
+          DevIL_VERSION
+          "${DevIL_VERSION_MAJOR}.${DevIL_VERSION_MINOR}.${DevIL_VERSION_PATCH}"
+        )
+      endforeach()
+    endif()
+  endif()
+endblock()
+
+find_package_handle_standard_args(
+  DevIL
+  REQUIRED_VARS IL_LIBRARIES ILU_LIBRARIES IL_INCLUDE_DIR
+  VERSION_VAR DevIL_VERSION
+  HANDLE_VERSION_RANGE
+)
+
 # provide legacy variable for compatibility
 set(IL_FOUND ${DevIL_FOUND})
 
@@ -187,3 +223,5 @@
     target_link_libraries(DevIL::ILUT INTERFACE DevIL::ILU)
   endif()
 endif()
+
+cmake_policy(POP)
diff --git a/Modules/FindGnuTLS.cmake b/Modules/FindGnuTLS.cmake
index d9d8260..14c64d7 100644
--- a/Modules/FindGnuTLS.cmake
+++ b/Modules/FindGnuTLS.cmake
@@ -5,12 +5,17 @@
 FindGnuTLS
 ----------
 
-Finds the GNU Transport Layer Security library (GnuTLS).  The GnuTLS
-package includes the main libraries (libgnutls and libdane), as well as the
-optional gnutls-openssl compatibility extra library.  They are all distributed
-as part of the same release.  This module checks for the presence of the main
-libgnutls library and provides usage requirements for integrating GnuTLS into
-CMake projects.
+Finds the GNU Transport Layer Security library (GnuTLS):
+
+.. code-block:: cmake
+
+  find_package(GnuTLS [<version>] [...])
+
+The GnuTLS package includes the main libraries (libgnutls and libdane), as
+well as the optional gnutls-openssl compatibility extra library.  They are
+all distributed as part of the same release.  This module checks for the
+presence of the main libgnutls library and provides usage requirements for
+integrating GnuTLS into CMake projects.
 
 Imported Targets
 ^^^^^^^^^^^^^^^^
@@ -29,12 +34,12 @@
 This module defines the following variables:
 
 ``GnuTLS_FOUND``
-  Boolean indicating whether the (requested version of) GnuTLS is found.  For
+  Boolean indicating whether (the requested version of) GnuTLS is found.  For
   backward compatibility, the ``GNUTLS_FOUND`` variable is also set to the same
   value.
 
-``GNUTLS_VERSION``
-  .. versionadded:: 3.16
+``GnuTLS_VERSION``
+  .. versionadded:: 4.2
 
   The version of GnuTLS found.
 
@@ -61,13 +66,16 @@
 Deprecated Variables
 ^^^^^^^^^^^^^^^^^^^^
 
-These variables are provided for backward compatibility:
+The following variables are provided for backward compatibility:
 
 ``GNUTLS_VERSION_STRING``
   .. deprecated:: 3.16
-    Superseded by ``GNUTLS_VERSION``.
+    Use the ``GnuTLS_VERSION``, which has the same value.
 
-  The version of GnuTLS found.
+``GNUTLS_VERSION``
+  .. versionadded:: 3.16
+  .. deprecated:: 4.2
+    Use the ``GnuTLS_VERSION``, which has the same value.
 
 Examples
 ^^^^^^^^
@@ -80,6 +88,9 @@
   target_link_libraries(project_target PRIVATE GnuTLS::GnuTLS)
 #]=======================================================================]
 
+cmake_policy(PUSH)
+cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
+
 if (GNUTLS_INCLUDE_DIR AND GNUTLS_LIBRARY)
   # in cache already
   set(gnutls_FIND_QUIETLY TRUE)
@@ -94,9 +105,6 @@
     pkg_check_modules(PC_GNUTLS QUIET gnutls)
   endif()
   set(GNUTLS_DEFINITIONS ${PC_GNUTLS_CFLAGS_OTHER})
-  set(GNUTLS_VERSION ${PC_GNUTLS_VERSION})
-  # keep for backward compatibility
-  set(GNUTLS_VERSION_STRING ${PC_GNUTLS_VERSION})
 endif ()
 
 find_path(GNUTLS_INCLUDE_DIR gnutls/gnutls.h
@@ -113,10 +121,43 @@
 
 mark_as_advanced(GNUTLS_INCLUDE_DIR GNUTLS_LIBRARY)
 
+if(GNUTLS_INCLUDE_DIR AND EXISTS "${GNUTLS_INCLUDE_DIR}/gnutls/gnutls.h")
+  file(
+    STRINGS
+    "${GNUTLS_INCLUDE_DIR}/gnutls/gnutls.h"
+    gnutls_version
+    # GnuTLS versions prior to 2.7.2 defined LIBGNUTLS_VERSION instead of the
+    # current GNUTLS_VERSION.
+    REGEX "^#define[\t ]+(LIB)?GNUTLS_VERSION[\t ]+\".*\""
+  )
+
+  string(
+    REGEX REPLACE
+    "^.*GNUTLS_VERSION[\t ]+\"([^\"]*)\".*$"
+    "\\1"
+    GnuTLS_VERSION
+    "${gnutls_version}"
+  )
+  unset(gnutls_version)
+
+  # Fallback to version defined by pkg-config if not successful.
+  if(
+    NOT GnuTLS_VERSION
+    AND PC_GNUTLS_VERSION
+    AND GNUTLS_INCLUDE_DIR IN_LIST PC_GNUTLS_INCLUDE_DIRS
+  )
+    set(GnuTLS_VERSION "${PC_GNUTLS_VERSION}")
+  endif()
+
+  # For backward compatibility.
+  set(GNUTLS_VERSION "${GnuTLS_VERSION}")
+  set(GNUTLS_VERSION_STRING "${GnuTLS_VERSION}")
+endif()
+
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(GnuTLS
                                   REQUIRED_VARS GNUTLS_LIBRARY GNUTLS_INCLUDE_DIR
-                                  VERSION_VAR GNUTLS_VERSION_STRING)
+                                  VERSION_VAR GnuTLS_VERSION)
 
 if(GnuTLS_FOUND)
   set(GNUTLS_LIBRARIES    ${GNUTLS_LIBRARY})
@@ -131,3 +172,5 @@
       IMPORTED_LOCATION "${GNUTLS_LIBRARIES}")
   endif()
 endif()
+
+cmake_policy(POP)
diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index 92e42ca..a203858 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -71,8 +71,9 @@
 ``HDF5::HDF5``
   .. versionadded:: 3.19
 
-  Target encapsulating the usage requirements for all found HDF5 libraries
-  (``HDF5_LIBRARIES``), available if HDF5 and all required components are found.
+  Target encapsulating the usage requirements for all found HDF5 binding
+  libraries (``HDF5_LIBRARIES``), available if HDF5 and all required components
+  are found.
 
 ``hdf5::hdf5``
   .. versionadded:: 3.19
diff --git a/Modules/FindKDE3.cmake b/Modules/FindKDE3.cmake
index f8a8615..438c0b0 100644
--- a/Modules/FindKDE3.cmake
+++ b/Modules/FindKDE3.cmake
@@ -212,7 +212,7 @@
 endif()
 
 # If Qt4 has already been found, fail.
-if(QT4_FOUND)
+if(Qt4_FOUND)
   if(KDE3_FIND_REQUIRED)
     message( FATAL_ERROR "KDE3/Qt3 and Qt4 cannot be used together in one project.")
   else()
diff --git a/Modules/FindKDE4.cmake b/Modules/FindKDE4.cmake
index 220906b..4d289f6 100644
--- a/Modules/FindKDE4.cmake
+++ b/Modules/FindKDE4.cmake
@@ -5,27 +5,214 @@
 FindKDE4
 --------
 
+.. note::
+
+  This module is specifically intended for KDE version 4, which is obsolete
+  and no longer maintained.  For modern application development using KDE
+  technologies with CMake, use a newer version of KDE, and refer to the
+  `KDE documentation
+  <https://develop.kde.org/docs/getting-started/building/cmake-build/>`_.
+
+Finds the KDE 4 installation:
+
+.. code-block:: cmake
+
+  find_package(KDE4 [...])
+
+This module is a wrapper around the following upstream KDE 4 modules:
+
+``FindKDE4Internal.cmake``
+
+  Upstream internal module, which finds the KDE 4 include directories,
+  libraries, and KDE-specific preprocessor tools.  It provides usage
+  requirements for building KDE 4 software and defines several helper
+  commands to simplify working with KDE 4 in CMake.
+
+``KDE4Macros.cmake``
+  Upstream utility module that defines all additional KDE4-specific
+  commands to use KDE 4 in CMake.  For example:
+  ``kde4_automoc()``, ``kde4_add_executable()``, ``kde4_add_library()``,
+  ``kde4_add_ui_files()``, ``kde4_add_ui3_files()``,
+  ``kde4_add_kcfg_files()``, ``kde4_add_kdeinit_executable()``, etc.
+
+Upstream KDE 4 modules are installed by the KDE 4 distribution package in
+``$KDEDIRS/share/apps/cmake/modules/``.  This path is automatically
+appended to the :variable:`CMAKE_MODULE_PATH` variable when calling
+``find_package(KDE4)``, so any additional KDE 4 modules can be included in
+the project with :command:`include`.  For example:
+
+``KDE4Defaults.cmake``
+  Upstream internal module that sets some CMake options which are useful,
+  but not required for building KDE 4 software.  If these settings should
+  be used, include this module after finding KDE 4:
+
+  .. code-block:: cmake
+
+    find_package(KDE4)
+    include(KDE4Defaults)
+
+For usage details, refer to the upstream KDE 4 documentation.  For example,
+at the top of the ``FindKDE4Internal`` module a complete documentation is
+available for all variables and commands these modules provide.
+
+Hints
+^^^^^
+
+This module accepts the following variables before calling the
+``find_package(KDE4)``:
+
+``ENV{KDEDIRS}``
+  Environment variable containing the path to the KDE 4 installation.
+
+KDE 4 is searched in the following directories in the given order:
+
+* :variable:`CMAKE_INSTALL_PREFIX` variable
+* ``KDEDIRS`` environment variable
+* ``/opt/kde4`` path
+
+Examples
+^^^^^^^^
+
+Example: Basic Usage
+""""""""""""""""""""
+
+Finding KDE 4 as required and using it in CMake:
+
+.. code-block:: cmake
+
+  find_package(KDE4 REQUIRED)
+
+  set(sources main.cpp mywidget.cpp mypart.cpp)
+
+  # The kde4_*() commands are provided by the KDE4Macros module, which is
+  # included automatically by FindKDE4, if KDE4 is found:
+  kde4_automoc(${sources})
+  kde4_add_executable(example ${sources})
+
+  target_include_directories(example PRIVATE ${KDE4_INCLUDES})
+  target_link_libraries(example PRIVATE ${KDE4_KDEUI_LIBS} ${KDE4_KPARTS_LIBS})
+
+  install(TARGETS example DESTINATION ${CMAKE_INSTALL_BINDIR})
+  install(FILES kfoo.desktop DESTINATION ${XDG_APPS_DIR})
+
+Example: Full Featured Example
+""""""""""""""""""""""""""""""
+
+In the following example this module is used to find KDE 4 installation.
+
+.. code-block:: cmake
+
+  project(kfoo)
+
+  find_package(KDE4 REQUIRED)
+
+  # Append path from where to include local project modules if any:
+  list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
+  include_directories(${KDE4_INCLUDE_DIRS})
+  add_definitions(${KDE4_DEFINITIONS})
+
+  set(sources main.cpp myappl.cpp view.cpp)
+
+  # If Qt designer UI files version 3 or 4 are available add them to the
+  # sources variable:
+  kde4_add_ui_files(sources maindialog.ui logindialog.ui)
+  kde4_add_ui3_files(sources printerdlg.ui previewdlg.ui)
+
+  # If there are files for the kconfig_compiler add them this way:
+  kde4_add_kcfg_files(sources settings.kcfg)
+
+  # When everything is listed, probably automoc is wanted:
+  kde4_automoc(${sources})
+
+  # Finally, specify what to build:
+  kde4_add_executable(kfoo ${sources})
 
 
-Find KDE4 and provide all necessary variables and macros to compile
-software for it.  It looks for KDE 4 in the following directories in
-the given order:
+The ``kde4_add_executable()`` command is a slightly extended version of the
+CMake command :command:`add_executable`.  Additionally, it does some more
+``RPATH`` handling and supports the ``KDE4_ENABLE_FINAL`` variable.  The
+first argument is the name of the executable followed by a list of source
+files.  If a library needs to be created instead of an executable, the
+``kde4_add_library()`` can be used.  It is an extended version of the
+:command:`add_library` command.  It adds support for the
+``KDE4_ENABLE_FINAL`` variable and under Windows it adds the
+``-DMAKE_KFOO_LIB`` to the compile flags.
 
-::
+.. code-block:: cmake
 
-  CMAKE_INSTALL_PREFIX
-  KDEDIRS
-  /opt/kde4
+  find_package(KDE4 REQUIRED)
 
+  # ...
 
+  kde4_add_library(kfoo ${sources})
 
-Please look in ``FindKDE4Internal.cmake`` and ``KDE4Macros.cmake`` for more
-information.  They are installed with the KDE 4 libraries in
-$KDEDIRS/share/apps/cmake/modules/.
+  # Optionally, set the library version number if needed:
+  set_target_properties(kfoo PROPERTIES VERSION 5.0.0 SOVERSION 5)
 
-Author: Alexander Neundorf <neundorf@kde.org>
+KDE is very modular, so if a KPart, a control center module, or an ioslave
+needs to be created, here's how to do it:
+
+.. code-block:: cmake
+
+  find_package(KDE4 REQUIRED)
+  # ...
+  kde4_add_plugin(kfoo ${sources})
+
+Now, the application/library/plugin probably needs to link to some
+libraries.  For this use the standard :command:`target_link_libraries`
+command.  For every KDE library there are variables available in the form
+of ``KDE4_FOO_LIBS``.  Use them to get also all depending libraries:
+
+.. code-block:: cmake
+
+  target_link_libraries(kfoo ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS})
+
+Example: The kdeinit Executable
+"""""""""""""""""""""""""""""""
+
+In the following example, the so called kdeinit executable is created.
+The ``kde4_add_kdeinit_executable()`` command creates both an executable
+with the given name and a library with the given name prefixed with
+``kdeinit_``.  The :command:`target_link_libraries` command adds all
+required libraries to the ``kdeinit_kbar`` library, and then links the
+``kbar`` against the ``kdeinit_kbar``:
+
+.. code-block:: cmake
+
+  find_package(KDE4 REQUIRED)
+
+  # ...
+
+  kde4_add_kdeinit_executable(kbar ${kbarSources})
+  target_link_libraries(kdeinit_kbar ${KDE4_KIO_LIBS})
+  target_link_libraries(kbar kdeinit_kbar)
+
+  install(TARGETS kbar DESTINATION ${CMAKE_INSTALL_BINDIR})
+  install(TARGETS kdeinit_kbar DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+Example: Removing Compile Definitions
+"""""""""""""""""""""""""""""""""""""
+
+Sometimes, a default compile definition passed to the compiler needs to be
+removed.  The :command:`remove_definitions` command can be used.  For
+example, by default, the KDE4 build system sets the ``-DQT_NO_STL`` flag.
+If the project code uses some of the Qt STL compatibility layer, this flag
+should be removed:
+
+.. code-block:: cmake
+
+  find_package(KDE4 REQUIRED)
+
+  add_definitions(${KDE4_DEFINITIONS})
+
+  # ...
+
+  remove_definitions(-DQT_NO_STL)
 #]=======================================================================]
 
+# Author: Alexander Neundorf <neundorf@kde.org>
+
 # If Qt3 has already been found, fail.
 if(QT_QT_LIBRARY)
   if(KDE4_FIND_REQUIRED)
diff --git a/Modules/FindLua.cmake b/Modules/FindLua.cmake
index 50f37f6..720981d 100644
--- a/Modules/FindLua.cmake
+++ b/Modules/FindLua.cmake
@@ -5,7 +5,13 @@
 FindLua
 -------
 
-Finds the Lua library.  Lua is a embeddable scripting language.
+Finds the Lua library:
+
+.. code-block:: cmake
+
+  find_package(Lua [<version>] [...])
+
+Lua is a embeddable scripting language.
 
 .. versionadded:: 3.18
   Support for Lua 5.4.
@@ -35,14 +41,27 @@
   Boolean indicating whether (the requested version of) Lua is found.  For
   backward compatibility, the ``LUA_FOUND`` variable is also set to the same
   value.
-``LUA_VERSION_STRING``
+
+``Lua_VERSION``
+  .. versionadded:: 4.2
+
   The version of Lua found.
-``LUA_VERSION_MAJOR``
+
+``Lua_VERSION_MAJOR``
+  .. versionadded:: 4.2
+
   The major version of Lua found.
-``LUA_VERSION_MINOR``
+
+``Lua_VERSION_MINOR``
+  .. versionadded:: 4.2
+
   The minor version of Lua found.
-``LUA_VERSION_PATCH``
+
+``Lua_VERSION_PATCH``
+  .. versionadded:: 4.2
+
   The patch version of Lua found.
+
 ``LUA_LIBRARIES``
   Libraries needed to link against to use Lua.  This list includes both ``lua``
   and ``lualib`` libraries.
@@ -56,6 +75,35 @@
   The directory containing the Lua header files, such as ``lua.h``,
   ``lualib.h``, and ``lauxlib.h``, needed to use Lua.
 
+Deprecated Variables
+^^^^^^^^^^^^^^^^^^^^
+
+The following variables are provided for backward compatibility:
+
+``LUA_VERSION_STRING``
+  .. deprecated:: 4.2
+    Superseded by the ``Lua_VERSION``.
+
+  The version of Lua found.
+
+``LUA_VERSION_MAJOR``
+  .. deprecated:: 4.2
+    Superseded by the ``Lua_VERSION_MAJOR``.
+
+  The major version of Lua found.
+
+``LUA_VERSION_MINOR``
+  .. deprecated:: 4.2
+    Superseded by the ``Lua_VERSION_MINOR``.
+
+  The minor version of Lua found.
+
+``LUA_VERSION_PATCH``
+  .. deprecated:: 4.2
+    Superseded by the ``Lua_VERSION_PATCH``.
+
+  The patch version of Lua found.
+
 Examples
 ^^^^^^^^
 
@@ -81,6 +129,7 @@
 #]=======================================================================]
 
 cmake_policy(PUSH)  # Policies apply to functions at definition-time
+cmake_policy(SET CMP0140 NEW)
 cmake_policy(SET CMP0159 NEW)  # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
 
 unset(_lua_include_subdirs)
@@ -146,7 +195,7 @@
 endfunction()
 
 function(_lua_get_header_version)
-  unset(LUA_VERSION_STRING PARENT_SCOPE)
+  unset(Lua_VERSION PARENT_SCOPE)
   set(_hdr_file "${LUA_INCLUDE_DIR}/lua.h")
 
   if (NOT EXISTS "${_hdr_file}")
@@ -159,27 +208,39 @@
   file(STRINGS "${_hdr_file}" lua_version_strings
        REGEX "^#define[ \t]+LUA_(RELEASE[ \t]+\"Lua [0-9]|VERSION([ \t]+\"Lua [0-9]|_[MR])).*")
 
-  string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MAJOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MAJOR ";${lua_version_strings};")
-  if (LUA_VERSION_MAJOR MATCHES "^[0-9]+$")
-    string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MINOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MINOR ";${lua_version_strings};")
-    string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_RELEASE[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_PATCH ";${lua_version_strings};")
-    set(LUA_VERSION_STRING "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}.${LUA_VERSION_PATCH}")
+  string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MAJOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" Lua_VERSION_MAJOR ";${lua_version_strings};")
+
+  if (Lua_VERSION_MAJOR MATCHES "^[0-9]+$")
+    string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MINOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" Lua_VERSION_MINOR ";${lua_version_strings};")
+    string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_RELEASE[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" Lua_VERSION_PATCH ";${lua_version_strings};")
+    set(Lua_VERSION "${Lua_VERSION_MAJOR}.${Lua_VERSION_MINOR}.${Lua_VERSION_PATCH}")
   else ()
-    string(REGEX REPLACE ".*;#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};")
-    if (NOT LUA_VERSION_STRING MATCHES "^[0-9.]+$")
-      string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};")
+    string(REGEX REPLACE ".*;#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" Lua_VERSION ";${lua_version_strings};")
+    if (NOT Lua_VERSION MATCHES "^[0-9.]+$")
+      string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" Lua_VERSION ";${lua_version_strings};")
     endif ()
-    string(REGEX REPLACE "^([0-9]+)\\.[0-9.]*$" "\\1" LUA_VERSION_MAJOR "${LUA_VERSION_STRING}")
-    string(REGEX REPLACE "^[0-9]+\\.([0-9]+)[0-9.]*$" "\\1" LUA_VERSION_MINOR "${LUA_VERSION_STRING}")
-    string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]).*" "\\1" LUA_VERSION_PATCH "${LUA_VERSION_STRING}")
+    string(REGEX REPLACE "^([0-9]+)\\.[0-9.]*$" "\\1" Lua_VERSION_MAJOR "${Lua_VERSION}")
+    string(REGEX REPLACE "^[0-9]+\\.([0-9]+)[0-9.]*$" "\\1" Lua_VERSION_MINOR "${Lua_VERSION}")
+    string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]).*" "\\1" Lua_VERSION_PATCH "${Lua_VERSION}")
   endif ()
   foreach (ver IN LISTS _lua_append_versions)
-    if (ver STREQUAL "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}")
-      set(LUA_VERSION_MAJOR ${LUA_VERSION_MAJOR} PARENT_SCOPE)
-      set(LUA_VERSION_MINOR ${LUA_VERSION_MINOR} PARENT_SCOPE)
-      set(LUA_VERSION_PATCH ${LUA_VERSION_PATCH} PARENT_SCOPE)
-      set(LUA_VERSION_STRING ${LUA_VERSION_STRING} PARENT_SCOPE)
-      return()
+    if (ver STREQUAL "${Lua_VERSION_MAJOR}.${Lua_VERSION_MINOR}")
+      set(LUA_VERSION_STRING "${Lua_VERSION}")
+      set(LUA_VERSION_MAJOR "${Lua_VERSION_MAJOR}")
+      set(LUA_VERSION_MINOR "${Lua_VERSION_MINOR}")
+      set(LUA_VERSION_PATCH "${Lua_VERSION_PATCH}")
+
+      return(
+        PROPAGATE
+          Lua_VERSION
+          Lua_VERSION_MAJOR
+          Lua_VERSION_MINOR
+          Lua_VERSION_PATCH
+          LUA_VERSION_STRING
+          LUA_VERSION_MAJOR
+          LUA_VERSION_MINOR
+          LUA_VERSION_PATCH
+      )
     endif ()
   endforeach ()
 endfunction()
@@ -208,9 +269,9 @@
     endif()
     _lua_get_header_version()
     # Found accepted version -> Ok
-    if (LUA_VERSION_STRING)
+    if (Lua_VERSION)
       if (LUA_Debug)
-        message(STATUS "Found suitable version ${LUA_VERSION_STRING} in ${LUA_INCLUDE_DIR}/lua.h")
+        message(STATUS "Found suitable version ${Lua_VERSION} in ${LUA_INCLUDE_DIR}/lua.h")
       endif()
       return()
     endif()
@@ -230,12 +291,12 @@
 _lua_get_header_version()
 unset(_lua_append_versions)
 
-if (LUA_VERSION_STRING)
+if (Lua_VERSION)
   set(_lua_library_names
-    lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR}
-    lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}
-    lua-${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}
-    lua.${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}
+    lua${Lua_VERSION_MAJOR}${Lua_VERSION_MINOR}
+    lua${Lua_VERSION_MAJOR}.${Lua_VERSION_MINOR}
+    lua-${Lua_VERSION_MAJOR}.${Lua_VERSION_MINOR}
+    lua.${Lua_VERSION_MAJOR}.${Lua_VERSION_MINOR}
     )
 endif ()
 
@@ -270,7 +331,7 @@
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(Lua
                                   REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
-                                  VERSION_VAR LUA_VERSION_STRING)
+                                  VERSION_VAR Lua_VERSION)
 
 mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARY)
 
diff --git a/Modules/FindLua50.cmake b/Modules/FindLua50.cmake
index ac36c86..b512d37 100644
--- a/Modules/FindLua50.cmake
+++ b/Modules/FindLua50.cmake
@@ -11,7 +11,13 @@
   not maintained anymore.  In new code use the latest supported Lua version and
   the version-agnostic module :module:`FindLua` instead.
 
-Finds the Lua library.  Lua is a embeddable scripting language.
+Finds the Lua library:
+
+.. code-block:: cmake
+
+  find_package(Lua50 [...])
+
+Lua is a embeddable scripting language.
 
 When working with Lua, its library headers are intended to be included in
 project source code as:
diff --git a/Modules/FindLua51.cmake b/Modules/FindLua51.cmake
index cba30e4..8f105ed 100644
--- a/Modules/FindLua51.cmake
+++ b/Modules/FindLua51.cmake
@@ -11,7 +11,13 @@
   not maintained anymore.  In new code use the latest supported Lua version and
   the version-agnostic module :module:`FindLua` instead.
 
-Finds the Lua library.  Lua is a embeddable scripting language.
+Finds the Lua library:
+
+.. code-block:: cmake
+
+  find_package(Lua51 [<version>] [...])
+
+Lua is a embeddable scripting language.
 
 When working with Lua, its library headers are intended to be included in
 project source code as:
@@ -35,9 +41,13 @@
 This module defines the following variables:
 
 ``Lua51_FOUND``
-  Boolean indicating whether Lua is found.  For backward compatibility, the
-  ``LUA51_FOUND`` variable is also set to the same value.
-``LUA_VERSION_STRING``
+  Boolean indicating whether (the requested version of) Lua is found.  For
+  backward compatibility, the ``LUA51_FOUND`` variable is also set to the
+  same value.
+
+``Lua_VERSION``
+  .. versionadded:: 4.2
+
   The version of Lua found.
 
 Cache Variables
@@ -48,9 +58,21 @@
 ``LUA_INCLUDE_DIR``
   The directory containing the Lua header files, such as ``lua.h``,
   ``lualib.h``, and ``lauxlib.h``, needed to use Lua.
+
 ``LUA_LIBRARIES``
   Libraries needed to link against to use Lua.
 
+Deprecated Variables
+^^^^^^^^^^^^^^^^^^^^
+
+The following variables are provided for backward compatibility:
+
+``LUA_VERSION_STRING``
+  .. deprecated:: 4.2
+    Superseded by the ``Lua_VERSION``.
+
+  The version of Lua found.
+
 Examples
 ^^^^^^^^
 
@@ -118,14 +140,15 @@
 if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
   file(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"")
 
-  string(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
+  string(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" Lua_VERSION "${lua_version_str}")
+  set(LUA_VERSION_STRING "${Lua_VERSION}")
   unset(lua_version_str)
 endif()
 
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(Lua51
                                   REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
-                                  VERSION_VAR LUA_VERSION_STRING)
+                                  VERSION_VAR Lua_VERSION)
 
 mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY)
 
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index a842756..b32bbcc 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -5,28 +5,56 @@
 FindOpenGL
 ----------
 
-FindModule for OpenGL and OpenGL Utility Library (GLU).
+Finds the OpenGL and OpenGL Utility Library (GLU), for using OpenGL in a
+CMake project:
+
+.. code-block:: cmake
+
+  find_package(OpenGL [COMPONENTS <components>...] [...])
+
+OpenGL (Open Graphics Library) is a cross-platform API for rendering 2D and
+3D graphics.  It is widely used in CAD, games, and visualization software.
+
+* *GL* refers to the core OpenGL library, which provides the fundamental
+  graphics rendering API.
+
+* *GLU* (OpenGL Utility Library) is a companion library that offers utility
+  functions built on top of OpenGL, such as tessellation and more complex
+  shape drawing.
 
 .. versionchanged:: 3.2
   X11 is no longer added as a dependency on Unix/Linux systems.
 
 .. versionadded:: 3.10
-  GLVND support on Linux.  See the :ref:`Linux Specific` section below.
+  GLVND (GL Vendor-Neutral Dispatch library) support on Linux.  See the
+  :ref:`Linux Specific` section below.
 
-Optional COMPONENTS
-^^^^^^^^^^^^^^^^^^^
+Components
+^^^^^^^^^^
 
-.. versionadded:: 3.10
+This module supports optional components which can be specified with the
+:command:`find_package` command:
 
-This module respects several optional COMPONENTS:
+.. code-block:: cmake
+
+  find_package(OpenGL [COMPONENTS <components>...])
+
+Supported components are:
 
 ``EGL``
-  The EGL interface between OpenGL, OpenGL ES and the underlying windowing system.
+  .. versionadded:: 3.10
+
+  The EGL interface between OpenGL, OpenGL ES and the underlying windowing
+  system.
 
 ``GLX``
+  .. versionadded:: 3.10
+
   An extension to X that interfaces OpenGL, OpenGL ES with X window system.
 
 ``OpenGL``
+  .. versionadded:: 3.10
+
   The cross platform API for 3D graphics.
 
 ``GLES2``
@@ -42,103 +70,177 @@
 Imported Targets
 ^^^^^^^^^^^^^^^^
 
-.. versionadded:: 3.8
-
-This module defines the :prop_tgt:`IMPORTED` targets:
+This module provides the following :ref:`Imported Targets`:
 
 ``OpenGL::GL``
-  Defined to the platform-specific OpenGL libraries if the system has OpenGL.
-``OpenGL::GLU``
-  Defined if the system has OpenGL Utility Library (GLU).
+  .. versionadded:: 3.8
 
-.. versionadded:: 3.10
-  Additionally, the following GLVND-specific library targets are defined:
+  Target encapsulating the usage requirements of platform-specific OpenGL
+  libraries, available if OpenGL is found.
+
+``OpenGL::GLU``
+  .. versionadded:: 3.8
+
+  Target encapsulating the OpenGL Utility Library (GLU) usage requirements,
+  available if GLU is found.
+
+Additionally, the following GLVND-specific library imported targets are
+provided:
 
 ``OpenGL::OpenGL``
-  Defined to libOpenGL if the system is GLVND-based.
+  .. versionadded:: 3.10
+
+  Target encapsulating the libOpenGL usage requirements, available if
+  system is GLVND-based and OpenGL is found.
+
 ``OpenGL::GLX``
-  Defined if the system has OpenGL Extension to the X Window System (GLX).
+  .. versionadded:: 3.10
+
+  Target encapsulating the usage requirements of the OpenGL Extension to the
+  the X Window System (GLX), available if OpenGL and GLX are found.
+
 ``OpenGL::EGL``
-  Defined if the system has EGL.
+  .. versionadded:: 3.10
+
+  Target encapsulating the EGL usage requirements, available if OpenGL and EGL
+  are found.
+
 ``OpenGL::GLES2``
   .. versionadded:: 3.27
 
-  Defined if the system has GLES2.
+  Target encapsulating the GLES2 usage requirements, available if OpenGL and
+  GLES2 are found.
+
 ``OpenGL::GLES3``
   .. versionadded:: 3.27
 
-  Defined if the system has GLES3.
+  Target encapsulating the GLES3 usage requirements, available if OpenGL and
+  GLES3 are found.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
 
-This module sets the following variables:
+This module defines the following variables:
 
-``OPENGL_FOUND``
- True, if the system has OpenGL and all components are found.
+``OpenGL_FOUND``
+  .. versionadded:: 3.3
+
+  Boolean indicating whether the OpenGL and all requested components are found.
+
 ``OPENGL_XMESA_FOUND``
- True, if the system has XMESA.
+  Boolean indicating whether OpenGL XMESA is found.
+
 ``OPENGL_GLU_FOUND``
- True, if the system has GLU.
+  Boolean indicating whether GLU is found.
+
 ``OpenGL_OpenGL_FOUND``
- True, if the system has an OpenGL library.
+  .. versionadded:: 3.10
+
+  Boolean indicating whether GLVND OpenGL library is found.
+
 ``OpenGL_GLX_FOUND``
- True, if the system has GLX.
+  .. versionadded:: 3.10
+
+  Boolean indicating whether GLVND GLX is found.
+
 ``OpenGL_EGL_FOUND``
- True, if the system has EGL.
-``OpenGL::GLES2``
- Defined if the system has GLES2.
-``OpenGL::GLES3``
- Defined if the system has GLES3.
-``OPENGL_INCLUDE_DIR``
- Path to the OpenGL include directory.
- The ``OPENGL_INCLUDE_DIRS`` variable is preferred.
-``OPENGL_EGL_INCLUDE_DIRS``
- Path to the EGL include directory.
-``OPENGL_LIBRARIES``
- Paths to the OpenGL library, windowing system libraries, and GLU libraries.
- On Linux, this assumes GLX and is never correct for EGL-based targets.
- Clients are encouraged to use the ``OpenGL::*`` import targets instead.
+  .. versionadded:: 3.10
+
+  Boolean indicating whether GLVND EGL is found.
+
+``OpenGL_GLES2_FOUND``
+  .. versionadded:: 3.27
+
+  Boolean indicating whether GLES2 is found.
+
+``OpenGL_GLES3_FOUND``
+  .. versionadded:: 3.27
+
+  Boolean indicating whether GLES3 is found.
+
 ``OPENGL_INCLUDE_DIRS``
   .. versionadded:: 3.29
 
   Paths to the OpenGL include directories.
 
-.. versionadded:: 3.10
-  Variables for GLVND-specific libraries ``OpenGL``, ``EGL`` and ``GLX``.
+``OPENGL_EGL_INCLUDE_DIRS``
+  .. versionadded:: 3.10
 
-Cache variables
+  Path to the EGL include directory.
+
+``OPENGL_LIBRARIES``
+  Paths to the OpenGL library, windowing system libraries, and GLU libraries.
+  On Linux, this assumes GLX and is never correct for EGL-based targets.
+  Clients are encouraged to use the ``OpenGL::*`` imported targets instead.
+
+Cache Variables
 ^^^^^^^^^^^^^^^
 
 The following cache variables may also be set:
 
-``OPENGL_egl_LIBRARY``
- Path to the EGL library.
-``OPENGL_glu_LIBRARY``
- Path to the GLU library.
-``OPENGL_glx_LIBRARY``
- Path to the GLVND 'GLX' library.
-``OPENGL_opengl_LIBRARY``
- Path to the GLVND 'OpenGL' library
-``OPENGL_gl_LIBRARY``
- Path to the OpenGL library.  New code should prefer the ``OpenGL::*`` import
- targets.
-``OPENGL_gles2_LIBRARY``
-  .. versionadded:: 3.27
-
-  Path to the OpenGL GLES2 library.
-``OPENGL_gles3_LIBRARY``
-  .. versionadded:: 3.27
-
-  Path to the OpenGL GLES3 library.
+``OPENGL_INCLUDE_DIR``
+  The path to the OpenGL include directory.
+  The ``OPENGL_INCLUDE_DIRS`` variable is preferred.
 
 ``OPENGL_GLU_INCLUDE_DIR``
   .. versionadded:: 3.29
 
   Path to the OpenGL GLU include directory.
 
-.. versionadded:: 3.10
-  Variables for GLVND-specific libraries ``OpenGL``, ``EGL`` and ``GLX``.
+``OPENGL_egl_LIBRARY``
+  .. versionadded:: 3.10
+
+  Path to the GLVND EGL library.
+
+``OPENGL_glu_LIBRARY``
+  Path to the GLU library.
+
+``OPENGL_glx_LIBRARY``
+  .. versionadded:: 3.10
+
+  Path to the GLVND GLX library.
+
+``OPENGL_opengl_LIBRARY``
+  .. versionadded:: 3.10
+
+  Path to the GLVND OpenGL library
+
+``OPENGL_gl_LIBRARY``
+  Path to the OpenGL library.
+
+``OPENGL_gles2_LIBRARY``
+  .. versionadded:: 3.27
+
+  Path to the OpenGL GLES2 library.
+
+``OPENGL_gles3_LIBRARY``
+  .. versionadded:: 3.27
+
+  Path to the OpenGL GLES3 library.
+
+Hints
+^^^^^
+
+This module accepts the following variables:
+
+``OpenGL_GL_PREFERENCE``
+  .. versionadded:: 3.10
+
+  This variable is supported on Linux systems to specify the preferred way to
+  provide legacy GL interfaces in case multiple choices are available.  The
+  value may be one of:
+
+  ``GLVND``
+    If the GLVND OpenGL and GLX libraries are available, prefer them.
+    This forces ``OPENGL_gl_LIBRARY`` to be empty.
+
+    .. versionchanged:: 3.11
+      This is the default, unless policy :policy:`CMP0072` is set to ``OLD``
+      and no components are requested (since components
+      correspond to GLVND libraries).
+
+  ``LEGACY``
+    Prefer to use the legacy libGL library, if available.
 
 .. _`Linux Specific`:
 
@@ -160,21 +262,8 @@
 variable will use the corresponding libraries).  Thus, for non-EGL-based
 Linux targets, the ``OpenGL::GL`` target is most portable.
 
-A ``OpenGL_GL_PREFERENCE`` variable may be set to specify the preferred way
+The ``OpenGL_GL_PREFERENCE`` variable may be set to specify the preferred way
 to provide legacy GL interfaces in case multiple choices are available.
-The value may be one of:
-
-``GLVND``
- If the GLVND OpenGL and GLX libraries are available, prefer them.
- This forces ``OPENGL_gl_LIBRARY`` to be empty.
-
- .. versionchanged:: 3.11
-  This is the default, unless policy :policy:`CMP0072` is set to ``OLD``
-  and no components are requested (since components
-  correspond to GLVND libraries).
-
-``LEGACY``
- Prefer to use the legacy libGL library, if available.
 
 For EGL targets the client must rely on GLVND support on the user's system.
 Linking should use the ``OpenGL::OpenGL OpenGL::EGL`` targets.  Using GLES*
@@ -189,7 +278,8 @@
 
 On macOS this module defaults to using the macOS-native framework
 version of OpenGL.  To use the X11 version of OpenGL on macOS, one
-can disable searching of frameworks.  For example:
+can disable searching of frameworks using the :variable:`CMAKE_FIND_FRAMEWORK`
+variable.  For example:
 
 .. code-block:: cmake
 
@@ -205,6 +295,33 @@
 An end user building this project may need to point CMake at their
 X11 installation, e.g., with ``-DOpenGL_ROOT=/opt/X11``.
 
+Deprecated Variables
+^^^^^^^^^^^^^^^^^^^^
+
+The following variables are provided for backward compatibility:
+
+``OPENGL_FOUND``
+  .. deprecated:: 3.3
+    Superseded by the ``OpenGL_FOUND``, which has the same value.
+
+Examples
+^^^^^^^^
+
+Finding the OpenGL library and linking it to a project target:
+
+.. code-block:: cmake
+
+  find_package(OpenGL)
+  target_link_libraries(project_target PRIVATE OpenGL::OpenGL)
+
+See Also
+^^^^^^^^
+
+* The :module:`FindGLEW` module to find OpenGL Extension Wrangler Library
+  (GLEW).
+* The :module:`FindGLUT` module to find OpenGL Utility Toolkit (GLUT)
+  library.
+* The :module:`FindVulkan` module to find Vulkan graphics API.
 #]=======================================================================]
 
 set(_OpenGL_REQUIRED_VARS OPENGL_gl_LIBRARY)
@@ -582,7 +699,7 @@
 unset(_OpenGL_REQUIRED_VARS)
 
 # OpenGL:: targets
-if(OPENGL_FOUND)
+if(OpenGL_FOUND)
   set(OPENGL_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR})
 
   # ::OpenGL is a GLVND library, and thus Linux-only: we don't bother checking
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index 5081936..b4c7291 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -5,28 +5,42 @@
 FindPackageHandleStandardArgs
 -----------------------------
 
-This module provides functions intended to be used in :ref:`Find Modules`
+This module provides commands intended to be used in :ref:`Find Modules`
 implementing :command:`find_package(<PackageName>)` calls.
 
+Load this module in a CMake find module with:
+
+.. code-block:: cmake
+  :caption: ``FindFoo.cmake``
+
+  include(FindPackageHandleStandardArgs)
+
+Commands
+^^^^^^^^
+
+This module provides the following commands:
+
+* :command:`find_package_handle_standard_args`
+* :command:`find_package_check_version`
+
 .. command:: find_package_handle_standard_args
 
-  This command handles the ``REQUIRED``, ``QUIET`` and version-related
-  arguments of :command:`find_package`.  It also sets the
-  ``<PackageName>_FOUND`` variable.  The package is considered found if all
-  variables listed contain valid results, e.g. valid filepaths.
+  Handles the ``REQUIRED``, ``QUIET`` and version-related arguments of
+  :command:`find_package`.
 
   There are two signatures:
 
   .. code-block:: cmake
 
-    find_package_handle_standard_args(<PackageName>
+    find_package_handle_standard_args(
+      <PackageName>
       (DEFAULT_MSG|<custom-failure-message>)
-      <required-var>...
-      )
+      <required-vars>...
+    )
 
-    find_package_handle_standard_args(<PackageName>
-      [FOUND_VAR <result-var>]
-      [REQUIRED_VARS <required-var>...]
+    find_package_handle_standard_args(
+      <PackageName>
+      [REQUIRED_VARS <required-vars>...]
       [VERSION_VAR <version-var>]
       [HANDLE_VERSION_RANGE]
       [HANDLE_COMPONENTS]
@@ -34,37 +48,33 @@
       [NAME_MISMATCHED]
       [REASON_FAILURE_MESSAGE <reason-failure-message>]
       [FAIL_MESSAGE <custom-failure-message>]
-      )
+      [FOUND_VAR <result-var>] # Deprecated
+    )
 
-  The ``<PackageName>_FOUND`` variable will be set to ``TRUE`` if all
-  the variables ``<required-var>...`` are valid and any optional
-  constraints are satisfied, and ``FALSE`` otherwise.  A success or
-  failure message may be displayed based on the results and on
-  whether the ``REQUIRED`` and/or ``QUIET`` option was given to
-  the :command:`find_package` call.
+  This command sets the ``<PackageName>_FOUND`` variable to ``TRUE`` if all
+  the variables listed in ``<required-vars>...`` contain valid results
+  (e.g., valid filepaths) and any optional constraints are satisfied, and
+  ``FALSE`` otherwise.  A success or failure message may be displayed based
+  on the results and on whether the ``REQUIRED`` and/or ``QUIET`` option
+  was given to the :command:`find_package` call.
 
-  The options are:
+  The arguments are:
+
+  ``<PackageName>``
+    The name of the package.  For example, as written in the
+    ``Find<PackageName>.cmake`` find module filename.
 
   ``(DEFAULT_MSG|<custom-failure-message>)``
     In the simple signature this specifies the failure message.
     Use ``DEFAULT_MSG`` to ask for a default message to be computed
     (recommended).  Not valid in the full signature.
 
-  ``FOUND_VAR <result-var>``
-    .. deprecated:: 3.3
-
-    Specifies either ``<PackageName>_FOUND`` or
-    ``<PACKAGENAME>_FOUND`` as the result variable.  This exists only
-    for compatibility with older versions of CMake and is now ignored.
-    Result variables of both names are now always set for compatibility
-    also with or without this option.
-
-  ``REQUIRED_VARS <required-var>...``
+  ``REQUIRED_VARS <required-vars>...``
     Specify the variables which are required for this package.
     These may be named in the generated failure message asking the
     user to set the missing variable values.  Therefore these should
-    typically be cache entries such as ``FOO_LIBRARY`` and not output
-    variables like ``FOO_LIBRARIES``.
+    typically be cache entries such as ``Foo_LIBRARY`` and not output
+    variables like ``Foo_LIBRARIES``.
 
     .. versionchanged:: 3.18
       If ``HANDLE_COMPONENTS`` is specified, this option can be omitted.
@@ -100,6 +110,14 @@
     will automatically check whether the package configuration file
     was found.
 
+  ``NAME_MISMATCHED``
+    .. versionadded:: 3.17
+
+    Indicate that the ``<PackageName>`` does not match the value of
+    :variable:`CMAKE_FIND_PACKAGE_NAME` variable. This is usually a mistake
+    and raises a warning, but it may be intentional for usage of the
+    command for components of a larger package.
+
   ``REASON_FAILURE_MESSAGE <reason-failure-message>``
     .. versionadded:: 3.16
 
@@ -110,48 +128,76 @@
     Specify a custom failure message instead of using the default
     generated message.  Not recommended.
 
-  ``NAME_MISMATCHED``
-    .. versionadded:: 3.17
+  ``FOUND_VAR <result-var>``
+    .. deprecated:: 3.3
+      This option should no longer be used.
 
-    Indicate that the ``<PackageName>`` does not match
-    ``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a
-    warning, but it may be intentional for usage of the command for components
-    of a larger package.
+    Specifies either ``<PackageName>_FOUND`` or ``<PACKAGENAME>_FOUND`` as the
+    result variable.  This exists only for backward compatibility with older
+    versions of CMake and is now ignored.  Result variables of both names are
+    now always set for compatibility also with or without this option.
 
-Example for the simple signature:
+  .. note::
+
+    If ``<PackageName>`` does not match :variable:`CMAKE_FIND_PACKAGE_NAME`
+    for the calling module, a warning that there is a mismatch is given.  The
+    ``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using
+    the old signature and the ``NAME_MISMATCHED`` argument using the new
+    signature.  To avoid forcing the caller to require newer versions of CMake
+    for usage, the variable's value will be used if defined when the
+    ``NAME_MISMATCHED`` argument is not passed for the new signature (but using
+    both is an error).
+
+.. command:: find_package_check_version
+
+  .. versionadded:: 3.19
+
+  Checks if a given version is valid against the version-related arguments
+  of :command:`find_package`:
+
+  .. code-block:: cmake
+
+    find_package_check_version(
+      <version>
+      <result-var>
+      [HANDLE_VERSION_RANGE]
+      [RESULT_MESSAGE_VARIABLE <message-var>]
+    )
+
+  The arguments are:
+
+  ``<version>``
+    The version string to check.
+
+  ``<result-var>``
+    Name of the result variable that will hold a boolean value giving the
+    result of the check.
+
+  ``HANDLE_VERSION_RANGE``
+    Enable handling of a version range, if one is specified.  Without this
+    option, a developer warning will be displayed if a version range is
+    specified.
+
+  ``RESULT_MESSAGE_VARIABLE <message-var>``
+    Specify a variable to get back a message describing the result of the check.
+
+Examples
+^^^^^^^^
+
+Examples: Full Signature
+""""""""""""""""""""""""
+
+Example for using a full signature of ``find_package_handle_standard_args()``:
 
 .. code-block:: cmake
+  :caption: ``FindLibArchive.cmake``
 
-  find_package_handle_standard_args(LibXml2 DEFAULT_MSG
-    LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
-
-The ``LibXml2`` package is considered to be found if both
-``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid.
-Then also ``LibXml2_FOUND`` is set to ``TRUE``.  If it is not found
-and ``REQUIRED`` was used, it fails with a
-:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was
-used or not.  If it is found, success will be reported, including
-the content of the first ``<required-var>``.  On repeated CMake runs,
-the same message will not be printed again.
-
-.. note::
-
-  If ``<PackageName>`` does not match ``CMAKE_FIND_PACKAGE_NAME`` for the
-  calling module, a warning that there is a mismatch is given. The
-  ``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using
-  the old signature and the ``NAME_MISMATCHED`` argument using the new
-  signature. To avoid forcing the caller to require newer versions of CMake for
-  usage, the variable's value will be used if defined when the
-  ``NAME_MISMATCHED`` argument is not passed for the new signature (but using
-  both is an error)..
-
-Example for the full signature:
-
-.. code-block:: cmake
-
-  find_package_handle_standard_args(LibArchive
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(
+    LibArchive
     REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR
-    VERSION_VAR LibArchive_VERSION)
+    VERSION_VAR LibArchive_VERSION
+  )
 
 In this case, the ``LibArchive`` package is considered to be found if
 both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid.
@@ -159,56 +205,73 @@
 contained in ``LibArchive_VERSION``.  Since no ``FAIL_MESSAGE`` is given,
 the default messages will be printed.
 
-Another example for the full signature:
+Another example for the full signature of
+``find_package_handle_standard_args()``:
 
 .. code-block:: cmake
+  :caption: ``FindAutomoc4.cmake``
 
   find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
-  find_package_handle_standard_args(Automoc4  CONFIG_MODE)
 
-In this case, a ``FindAutmoc4.cmake`` module wraps a call to
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(Automoc4 CONFIG_MODE)
+
+In this case, a ``FindAutomoc4.cmake`` module wraps a call to
 ``find_package(Automoc4 NO_MODULE)`` and adds an additional search
 directory for ``automoc4``.  Then the call to
-``find_package_handle_standard_args`` produces a proper success/failure
+``find_package_handle_standard_args()`` produces a proper success/failure
 message.
 
-.. command:: find_package_check_version
+Example: Simple Signature
+"""""""""""""""""""""""""
 
-  .. versionadded:: 3.19
-
-  Helper function which can be used to check if a ``<version>`` is valid
-  against version-related arguments of :command:`find_package`.
-
-  .. code-block:: cmake
-
-    find_package_check_version(<version> <result-var>
-      [HANDLE_VERSION_RANGE]
-      [RESULT_MESSAGE_VARIABLE <message-var>]
-      )
-
-  The ``<result-var>`` will hold a boolean value giving the result of the check.
-
-  The options are:
-
-  ``HANDLE_VERSION_RANGE``
-    Enable handling of a version range, if one is specified. Without this
-    option, a developer warning will be displayed if a version range is
-    specified.
-
-  ``RESULT_MESSAGE_VARIABLE <message-var>``
-    Specify a variable to get back a message describing the result of the check.
-
-Example for the usage:
+Example for using a simple signature of ``find_package_handle_standard_args()``:
 
 .. code-block:: cmake
+  :caption: ``FindLibXml2.cmake``
 
-  find_package_check_version(1.2.3 result HANDLE_VERSION_RANGE
-    RESULT_MESSAGE_VARIABLE reason)
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(
+    LibXml2
+    DEFAULT_MSG
+    LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR
+  )
+
+In this example, the ``LibXml2`` package is considered to be found if both
+``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` variables are valid.  Then
+also ``LibXml2_FOUND`` is set to ``TRUE``.  If it is not found and
+``REQUIRED`` was used, it fails with a :command:`message(FATAL_ERROR)`,
+independent whether ``QUIET`` was used or not.  If it is found, success will
+be reported, including the content of the first required variable specified
+in ``<required-vars>...``.  On repeated CMake runs, the same message will
+not be printed again.
+
+Example: Checking Version
+"""""""""""""""""""""""""
+
+Example for the ``find_package_check_version()`` usage:
+
+.. code-block:: cmake
+  :caption: ``FindFoo.cmake``
+
+  include(FindPackageHandleStandardArgs)
+  find_package_check_version(
+    1.2.3
+    result
+    HANDLE_VERSION_RANGE
+    RESULT_MESSAGE_VARIABLE reason
+  )
   if(result)
     message(STATUS "${reason}")
   else()
-    message(FATAL_ERROR "${reason}")
+    # Logic when version check is not successful.
+    message(WARNING "${reason}")
   endif()
+
+See Also
+^^^^^^^^
+
+* :ref:`Find Modules` for details how to write a find module.
 #]=======================================================================]
 
 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
diff --git a/Modules/FindPerl.cmake b/Modules/FindPerl.cmake
index 06a2e62..b1c4f51 100644
--- a/Modules/FindPerl.cmake
+++ b/Modules/FindPerl.cmake
@@ -5,8 +5,13 @@
 FindPerl
 --------
 
-Finds a Perl interpreter.  Perl is a general-purpose, interpreted, dynamic
-programming language.
+Finds a Perl interpreter:
+
+.. code-block:: cmake
+
+  find_package(Perl [<version>] [...])
+
+Perl is a general-purpose, interpreted, dynamic programming language.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
@@ -14,10 +19,13 @@
 This module defines the following variables:
 
 ``Perl_FOUND``
-  True if the Perl executable was found.  For backward compatibility, the
-  ``PERL_FOUND`` variable is also set to the same value.
+  Boolean indicating whether the (requested version of) Perl executable is
+  found.  For backward compatibility, the ``PERL_FOUND`` variable is also
+  set to the same value.
 
-``PERL_VERSION_STRING``
+``Perl_VERSION``
+  .. versionadded:: 4.2
+
   The version of Perl found.
 
 Cache Variables
@@ -28,14 +36,34 @@
 ``PERL_EXECUTABLE``
   Full path to the ``perl`` executable.
 
+Deprecated Variables
+^^^^^^^^^^^^^^^^^^^^
+
+The following variables are provided for backward compatibility:
+
+``PERL_VERSION_STRING``
+  .. deprecated:: 4.2
+    Superseded by the ``Perl_VERSION``.
+
+  The version of Perl found.
+
 Examples
 ^^^^^^^^
 
-Finding the Perl interpreter:
+Finding the Perl interpreter and executing it in a process:
 
 .. code-block:: cmake
 
   find_package(Perl)
+
+  if(Perl_FOUND)
+    execute_process(COMMAND ${PERL_EXECUTABLE} --help)
+  endif()
+
+See Also
+^^^^^^^^
+
+* The :module:`FindPerlLibs` to find Perl libraries.
 #]=======================================================================]
 
 include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake)
@@ -64,7 +92,6 @@
   )
 
 if(PERL_EXECUTABLE)
-  ### PERL_VERSION
   execute_process(
     COMMAND
       ${PERL_EXECUTABLE} -V:version
@@ -76,7 +103,8 @@
       OUTPUT_STRIP_TRAILING_WHITESPACE
   )
   if(NOT PERL_VERSION_RESULT_VARIABLE AND NOT PERL_VERSION_OUTPUT_VARIABLE MATCHES "^version='UNKNOWN'")
-    string(REGEX REPLACE "version='([^']+)'.*" "\\1" PERL_VERSION_STRING ${PERL_VERSION_OUTPUT_VARIABLE})
+    string(REGEX REPLACE "version='([^']+)'.*" "\\1" Perl_VERSION ${PERL_VERSION_OUTPUT_VARIABLE})
+    set(PERL_VERSION_STRING "${Perl_VERSION}")
   else()
     execute_process(
       COMMAND ${PERL_EXECUTABLE} -v
@@ -86,9 +114,11 @@
       OUTPUT_STRIP_TRAILING_WHITESPACE
     )
     if(NOT PERL_VERSION_RESULT_VARIABLE AND PERL_VERSION_OUTPUT_VARIABLE MATCHES "This is perl.*[ \\(]v([0-9\\._]+)[ \\)]")
-      set(PERL_VERSION_STRING "${CMAKE_MATCH_1}")
+      set(Perl_VERSION "${CMAKE_MATCH_1}")
+      set(PERL_VERSION_STRING "${Perl_VERSION}")
     elseif(NOT PERL_VERSION_RESULT_VARIABLE AND PERL_VERSION_OUTPUT_VARIABLE MATCHES "This is perl, version ([0-9\\._]+) +")
-      set(PERL_VERSION_STRING "${CMAKE_MATCH_1}")
+      set(Perl_VERSION "${CMAKE_MATCH_1}")
+      set(PERL_VERSION_STRING "${Perl_VERSION}")
     endif()
   endif()
 endif()
@@ -105,7 +135,7 @@
 endif ()
 find_package_handle_standard_args(Perl
                                   REQUIRED_VARS PERL_EXECUTABLE
-                                  VERSION_VAR PERL_VERSION_STRING)
+                                  VERSION_VAR Perl_VERSION)
 unset(FPHSA_NAME_MISMATCHED)
 
 mark_as_advanced(PERL_EXECUTABLE)
diff --git a/Modules/FindPerlLibs.cmake b/Modules/FindPerlLibs.cmake
index 330700e..ab6b333 100644
--- a/Modules/FindPerlLibs.cmake
+++ b/Modules/FindPerlLibs.cmake
@@ -5,18 +5,33 @@
 FindPerlLibs
 ------------
 
-Finds Perl libraries.  Perl is a general-purpose, interpreted, dynamic
-programming language.  This module detects whether Perl is installed and
-determines the locations of include paths, libraries, and the library name.
+Finds Perl libraries:
+
+.. code-block:: cmake
+
+  find_package(PerlLibs [<version>] [...])
+
+Perl is a general-purpose, interpreted, dynamic programming language.
+
+This module detects whether Perl interpreter is installed via the
+:module:`FindPerl` module and determines the locations of Perl include paths,
+libraries, and the library name.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
 
-This module sets the following variables:
+This module defines the following variables:
 
 ``PerlLibs_FOUND``
-  True if ``perl.h`` and ``libperl`` were found.  For backward compatibility,
-  the ``PERLLIBS_FOUND`` variable is also set to the same value.
+  Boolean indicating whether the (requested version of) Perl library
+  (``perl.h`` and ``libperl``) is found.  For backward compatibility, the
+  ``PERLLIBS_FOUND`` variable is also set to the same value.
+
+``PerlLibs_VERSION``
+  .. versionadded:: 4.2
+
+  The version of Perl library found.
+
 ``PERL_SITESEARCH``
   Path to the sitesearch install directory (``-V:installsitesearch``).
 ``PERL_SITEARCH``
@@ -58,11 +73,18 @@
 .. code-block:: cmake
 
   find_package(PerlLibs 6.0)
+
+See Also
+^^^^^^^^
+
+* The :module:`FindPerl` module to find the Perl interpreter.
 #]=======================================================================]
 
 # find the perl executable
 include(${CMAKE_CURRENT_LIST_DIR}/FindPerl.cmake)
 
+set(PerlLibs_VERSION "${Perl_VERSION}")
+
 if (PERL_EXECUTABLE)
 
   function (perl_get_info _pgi_info tag)
@@ -122,10 +144,10 @@
   ### PERL_POSSIBLE_LIBRARY_NAMES
   perl_get_info(PERL_POSSIBLE_LIBRARY_NAMES libperl)
   if (NOT PERL_POSSIBLE_LIBRARY_NAMES)
-    set(PERL_POSSIBLE_LIBRARY_NAMES perl${PERL_VERSION_STRING} perl)
+    set(PERL_POSSIBLE_LIBRARY_NAMES perl${PerlLibs_VERSION} perl)
   endif()
   if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN")
-    list (APPEND PERL_POSSIBLE_LIBRARY_NAMES perl${PERL_VERSION_STRING})
+    list (APPEND PERL_POSSIBLE_LIBRARY_NAMES perl${PerlLibs_VERSION})
   endif()
   if (CMAKE_SYSTEM_NAME MATCHES "MSYS|CYGWIN")
     # On MSYS and CYGWIN environments, current perl -V:libperl gives shared
@@ -141,10 +163,10 @@
     PATHS
       "${PERL_UPDATE_ARCHLIB}/CORE"
       "${PERL_ARCHLIB}/CORE"
-      /usr/lib/perl5/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE
-      /usr/lib/perl/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE
-      /usr/lib/perl5/${PERL_VERSION_STRING}/CORE
-      /usr/lib/perl/${PERL_VERSION_STRING}/CORE
+      /usr/lib/perl5/${PerlLibs_VERSION}/${PERL_ARCHNAME}/CORE
+      /usr/lib/perl/${PerlLibs_VERSION}/${PERL_ARCHNAME}/CORE
+      /usr/lib/perl5/${PerlLibs_VERSION}/CORE
+      /usr/lib/perl/${PerlLibs_VERSION}/CORE
   )
 
   ### PERL_LIBRARY
@@ -154,24 +176,24 @@
     PATHS
       "${PERL_UPDATE_ARCHLIB}/CORE"
       "${PERL_ARCHLIB}/CORE"
-      /usr/lib/perl5/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE
-      /usr/lib/perl/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE
-      /usr/lib/perl5/${PERL_VERSION_STRING}/CORE
-      /usr/lib/perl/${PERL_VERSION_STRING}/CORE
+      /usr/lib/perl5/${PerlLibs_VERSION}/${PERL_ARCHNAME}/CORE
+      /usr/lib/perl/${PerlLibs_VERSION}/${PERL_ARCHNAME}/CORE
+      /usr/lib/perl5/${PerlLibs_VERSION}/CORE
+      /usr/lib/perl/${PerlLibs_VERSION}/CORE
   )
 
 endif ()
 
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(PerlLibs REQUIRED_VARS PERL_LIBRARY PERL_INCLUDE_PATH
-                                           VERSION_VAR PERL_VERSION_STRING)
+                                           VERSION_VAR PerlLibs_VERSION)
 
 # Introduced after CMake 2.6.4 to bring module into compliance
 set(PERL_INCLUDE_DIR  ${PERL_INCLUDE_PATH})
 set(PERL_INCLUDE_DIRS ${PERL_INCLUDE_PATH})
 set(PERL_LIBRARIES    ${PERL_LIBRARY})
 # For backward compatibility with CMake before 2.8.8
-set(PERL_VERSION ${PERL_VERSION_STRING})
+set(PERL_VERSION ${PerlLibs_VERSION})
 
 mark_as_advanced(
   PERL_INCLUDE_PATH
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index b230eb5..91c71ae 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -7,28 +7,454 @@
 
 A ``pkg-config`` module for CMake.
 
-Finds the ``pkg-config`` executable and adds the :command:`pkg_get_variable`,
-:command:`pkg_check_modules` and :command:`pkg_search_module` commands. The
-following variables will also be set:
+Finds the ``pkg-config`` executable and provides commands to use it in
+CMake:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig [<version>] [QUIET] [REQUIRED] [...])
+
+``pkg-config`` is a command-line program for configuring build dependency
+information.  Initially developed by FreeDesktop, it is also available in
+several implementations, such as pkgconf, u-config, and similar.  It reads
+package data from the so-called PC metadata files (``<module-name>.pc``)
+that may come installed with packages.  This module is a wrapper around the
+``pkg-config`` command-line executable.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
 
 ``PKG_CONFIG_FOUND``
-  True if a pkg-config executable was found.
+  Boolean indicating whether the (requested version of) ``pkg-config``
+  executable is found.
 
 ``PKG_CONFIG_VERSION_STRING``
-  The version of pkg-config that was found.
+  The version of ``pkg-config`` that was found.
 
 ``PKG_CONFIG_EXECUTABLE``
-  The pathname of the pkg-config program.
+  The pathname of the ``pkg-config`` program.
 
 ``PKG_CONFIG_ARGN``
   .. versionadded:: 3.22
 
-  A list of arguments to pass to pkg-config.
+  A list of arguments to pass to ``pkg-config``.
 
 Both ``PKG_CONFIG_EXECUTABLE`` and ``PKG_CONFIG_ARGN`` are initialized by the
-module, but may be overridden by the user.  See `Variables Affecting Behavior`_
-for how these variables are initialized.
+module, but may be overridden by the user.  See `Hints`_ for how these
+variables are initialized.
 
+Commands
+^^^^^^^^
+
+This module provides the following commands, if ``pkg-config`` is found:
+
+* :command:`pkg_check_modules`
+* :command:`pkg_search_module`
+* :command:`pkg_get_variable`
+
+.. command:: pkg_check_modules
+
+  Checks for all the given modules, setting a variety of result variables
+  in the calling scope:
+
+  .. code-block:: cmake
+
+    pkg_check_modules(
+      <prefix>
+      [QUIET]
+      [REQUIRED]
+      [NO_CMAKE_PATH]
+      [NO_CMAKE_ENVIRONMENT_PATH]
+      [IMPORTED_TARGET [GLOBAL]]
+      <module-spec> [<module-spec>...]
+    )
+
+  .. rubric:: The arguments are:
+
+  ``<prefix>``
+    Prefix string prepended to result variables for the specified modules.
+
+  ``QUIET``
+    When this argument is given, no status messages will be printed.
+
+  ``REQUIRED``
+    When this argument is given, the command will fail with an error if any
+    of the specified module(s) could not be found.
+
+  ``NO_CMAKE_PATH``, ``NO_CMAKE_ENVIRONMENT_PATH``
+    .. versionadded:: 3.3
+
+    The :variable:`CMAKE_PREFIX_PATH`,
+    :variable:`CMAKE_FRAMEWORK_PATH`, and :variable:`CMAKE_APPBUNDLE_PATH` cache
+    and environment variables will be added to the ``pkg-config`` search path.
+    The ``NO_CMAKE_PATH`` and ``NO_CMAKE_ENVIRONMENT_PATH`` arguments
+    disable this behavior for the cache variables and environment variables
+    respectively.
+    The ``PKG_CONFIG_USE_CMAKE_PREFIX_PATH`` variable set to ``FALSE``
+    disables this behavior globally.
+
+    .. This was actually added in 3.1, but didn't work until 3.3.
+
+  ``IMPORTED_TARGET [GLOBAL]``
+    .. versionadded:: 3.7
+
+    This argument will create an :ref:`imported target <Imported Targets>`
+    named ``PkgConfig::<prefix>`` that can be passed directly as an argument
+    to :command:`target_link_libraries`.  It will encapsulate usage
+    requirements for all specified modules ``<module-spec>...`` at once.
+
+    .. This was actually added in 3.6, but didn't work until 3.7.
+
+    ``GLOBAL``
+      .. versionadded:: 3.13
+
+      This argument is used together with ``IMPORTED_TARGET`` and will make
+      the imported target available in global scope.
+
+    .. versionadded:: 3.15
+      Non-library linker options reported by ``pkg-config`` are stored in the
+      :prop_tgt:`INTERFACE_LINK_OPTIONS` target property.
+
+    .. versionchanged:: 3.18
+      Include directories specified with ``-isystem`` are stored in the
+      :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target property.  Previous
+      versions of CMake left them in the :prop_tgt:`INTERFACE_COMPILE_OPTIONS`
+      property.
+
+  ``<module-spec>``
+    Each ``<module-spec>`` can be either a bare module name (as defined in
+    its PC metadata file name ``<module-name>.pc``) or it can be a module
+    name with a version constraint (operators ``=``, ``<``, ``>``, ``<=``
+    and ``>=`` are supported).  The following are examples for a module
+    named ``foo`` with various constraints:
+
+    - ``foo`` matches any version.
+    - ``foo<2`` only matches versions before 2.
+    - ``foo>=3.1`` matches any version from 3.1 or later.
+    - ``foo=1.2.3`` requires that foo must be exactly version 1.2.3.
+
+  .. rubric:: Result Variables
+
+  The following variables may be set upon return.  Two sets of values exist:
+  One for the common case (``<XXX> = <prefix>``) and another for the
+  information ``pkg-config`` provides when called with the ``--static``
+  option (``<XXX> = <prefix>_STATIC``).
+
+  ``<XXX>_FOUND``
+    Boolean variable set to 1 if module(s) exist.
+  ``<XXX>_LIBRARIES``
+    A list of only the libraries (without the ``-l``).
+  ``<XXX>_LINK_LIBRARIES``
+    The libraries and their absolute paths.
+  ``<XXX>_LIBRARY_DIRS``
+    The paths of the libraries (without the ``-L``).
+  ``<XXX>_LDFLAGS``
+    All required linker flags.
+  ``<XXX>_LDFLAGS_OTHER``
+    All other linker flags.
+  ``<XXX>_INCLUDE_DIRS``
+    The ``-I`` preprocessor flags (without the ``-I``).
+  ``<XXX>_CFLAGS``
+    All required cflags.
+  ``<XXX>_CFLAGS_OTHER``
+    The other compiler flags.
+
+  All but ``<XXX>_FOUND`` may be a :ref:`semicolon-separated list
+  <CMake Language Lists>` if the
+  associated variable returned from ``pkg-config`` has multiple values.
+
+  .. versionchanged:: 3.18
+    Include directories specified with ``-isystem`` are stored in the
+    ``<XXX>_INCLUDE_DIRS`` variable.  Previous versions of CMake left them
+    in ``<XXX>_CFLAGS_OTHER``.
+
+  There are some special variables whose prefix depends on the number of
+  ``<module-spec>`` given.  When there is only one ``<module-spec>``,
+  ``<YYY>`` will simply be ``<prefix>``, but if two or more ``<module-spec>``
+  items are given, ``<YYY>`` will be ``<prefix>_<module-name>``.
+
+  ``<YYY>_VERSION``
+    The version of the module.
+  ``<YYY>_PREFIX``
+    The prefix directory of the module.
+  ``<YYY>_INCLUDEDIR``
+    The include directory of the module.
+  ``<YYY>_LIBDIR``
+    The lib directory of the module.
+
+  .. versionchanged:: 3.8
+    For any given ``<prefix>``, ``pkg_check_modules()`` can be called multiple
+    times with different parameters.  Previous versions of CMake cached and
+    returned the first successful result.
+
+  .. versionchanged:: 3.16
+    If a full path to the found library can't be determined, but it's still
+    visible to the linker, pass it through as ``-l<name>``.  Previous versions
+    of CMake failed in this case.
+
+.. command:: pkg_search_module
+
+  Searches for the first successful match from one or more provided module
+  specifications:
+
+  .. code-block:: cmake
+
+    pkg_search_module(
+      <prefix>
+      [QUIET]
+      [REQUIRED]
+      [NO_CMAKE_PATH]
+      [NO_CMAKE_ENVIRONMENT_PATH]
+      [IMPORTED_TARGET [GLOBAL]]
+      <module-spec> [<module-spec>...]
+    )
+
+  The behavior and arguments of this command are the same as
+  :command:`pkg_check_modules`, except that rather than checking for all
+  the specified modules, it searches for just the first successful match.
+
+  This command can be used, for example, when some package is known to have
+  possible multiple ``<module-spec>`` on different platforms or versions for
+  the same package.
+
+  .. rubric:: Result Variables
+
+  This command defines the same variables as described above with addition
+  to:
+
+  ``<prefix>_MODULE_NAME``
+    .. versionadded:: 3.16
+
+    If a module is found, the ``<prefix>_MODULE_NAME`` variable will contain
+    the name of the matching module. This variable can be used if the
+    :command:`pkg_get_variable` command needs to be called with the
+    ``<module-name>`` argument that was found by the
+    :command:`pkg_search_module`.
+
+.. command:: pkg_get_variable
+
+  .. versionadded:: 3.4
+
+  Retrieves the value of a ``pkg-config`` variable and stores it in the
+  result variable in the calling scope:
+
+  .. code-block:: cmake
+
+    pkg_get_variable(
+      <result-var>
+      <module-name>
+      <var-name>
+      [DEFINE_VARIABLES <key>=<value>...]
+    )
+
+  .. rubric:: The arguments are:
+
+  ``<result-var>``
+    Name of the result variable that will contain the value of ``pkg-config``
+    variable.  If ``pkg-config`` returns multiple values for the specified
+    variable ``<var-name>``, ``<result-var>`` will contain a
+    :ref:`semicolon-separated list <CMake Language Lists>`.
+
+  ``<module-name>``
+    Name of the module as defined in its PC metadata file name
+    (``<module-name>.pc``).
+
+  ``<var-name>``
+    The ``pkg-config`` variable name from the PC metadata file
+    ``<module-name>.pc``.
+
+  ``DEFINE_VARIABLES <key>=<value>...``
+    .. versionadded:: 3.28
+
+    Specify key-value pairs to redefine variables affecting the variable
+    retrieved with ``pkg-config``.
+
+Hints
+^^^^^
+
+This module accepts the following variables before calling
+``find_package(PkgConfig)`` to influence this module's behavior:
+
+``ENV{PKG_CONFIG_PATH}``
+  Environment variable that specifies additional paths in which
+  ``pkg-config`` will search for its ``.pc`` files.  The ``pkg-config``
+  tool by default uses this variable, while CMake also provides more common
+  :variable:`CMAKE_PREFIX_PATH` variable to specify additional paths where
+  to look for packages and their ``.pc`` files.
+
+``ENV{PKG_CONFIG}``
+  .. versionadded:: 3.1
+
+  Environment variable that can be set to the path of the ``pkg-config``
+  executable and can be used to initialize the ``PKG_CONFIG_EXECUTABLE``
+  variable, if it has not yet been set.
+
+``PKG_CONFIG_EXECUTABLE``
+
+  This cache variable can be set to the path of the ``pkg-config``
+  executable.  :command:`find_program` is called internally by the module
+  with this variable.
+
+  .. versionchanged:: 3.22
+    If the ``PKG_CONFIG`` environment variable is set, only the first
+    argument is taken from it when using it as a hint.
+
+``PKG_CONFIG_ARGN``
+
+  .. versionadded:: 3.22
+
+  This cache variable can be set to a list of arguments to additionally pass
+  to ``pkg-config`` if needed. If not provided, it will be initialized from
+  the ``PKG_CONFIG`` environment variable, if set. The first argument in that
+  environment variable is assumed to be the ``pkg-config`` program, while all
+  remaining arguments after that are used to initialize ``PKG_CONFIG_ARGN``.
+  If no such environment variable is defined, ``PKG_CONFIG_ARGN`` is
+  initialized to an empty string. The module does not update the variable once
+  it has been set in the cache.
+
+``PKG_CONFIG_USE_CMAKE_PREFIX_PATH``
+
+  .. versionadded:: 3.1
+
+  Specifies whether :command:`pkg_check_modules` and
+  :command:`pkg_search_module` should add the paths in the
+  :variable:`CMAKE_PREFIX_PATH`, :variable:`CMAKE_FRAMEWORK_PATH` and
+  :variable:`CMAKE_APPBUNDLE_PATH` cache and environment variables to the
+  ``pkg-config`` search path.
+
+  If this variable is not set, this behavior is enabled by default if
+  :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` is 3.1 or later, disabled
+  otherwise.
+
+Examples
+^^^^^^^^
+
+Examples: Finding pkg-config
+""""""""""""""""""""""""""""
+
+Finding ``pkg-config``:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig)
+
+Finding ``pkg-config`` and making it required (if not found, processing stops
+with an error message):
+
+.. code-block:: cmake
+
+  find_package(PkgConfig REQUIRED)
+
+Finding ``pkg-config`` quietly without printing status message as commonly
+used in find modules:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET)
+
+Examples: Using ``pkg_check_modules()``
+"""""""""""""""""""""""""""""""""""""""
+
+Checking for any version of glib2.  If found, the output variable
+``GLIB2_VERSION`` will hold the actual version found:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET)
+
+  if(PKG_CONFIG_FOUND)
+    pkg_check_modules(GLIB2 glib-2.0)
+  endif()
+
+The following example looks for at least version 2.10 of glib2.  If found,
+the output variable ``GLIB2_VERSION`` will hold the actual version found:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET)
+
+  if(PKG_CONFIG_FOUND)
+    pkg_check_modules(GLIB2 glib-2.0>=2.10)
+  endif()
+
+The following example looks for both glib2-2.0 (at least version 2.10) and
+any version of gtk2+-2.0.  Only if both are found will ``FOO`` be considered
+found.  The ``FOO_glib-2.0_VERSION`` and ``FOO_gtk+-2.0_VERSION`` variables
+will be set to their respective found module versions.
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET)
+
+  if(PKG_CONFIG_FOUND)
+    pkg_check_modules(FOO glib-2.0>=2.10 gtk+-2.0)
+  endif()
+
+The following example requires any version of ``xrender``:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET REQUIRED)
+  pkg_check_modules(XRENDER REQUIRED xrender)
+
+Example output variables set by a successful call::
+
+  XRENDER_LIBRARIES=Xrender;X11
+  XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp
+
+Example: Using ``pkg_search_module()``
+""""""""""""""""""""""""""""""""""""""
+
+Searching for LibXml2 package, which might be provided with different
+module specifications (``libxml-2.0`` or ``libxml2``):
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET)
+
+  if(PKG_CONFIG_FOUND)
+    pkg_search_module(BAR libxml-2.0 libxml2 libxml>=2)
+  endif()
+
+Example: Creating Imported Target
+"""""""""""""""""""""""""""""""""
+
+In the following example an imported target is created from the module
+specifications to use in the project directly without using a find module.
+These imported targets can be used, for example, in cases, where package is
+known to support ``pkg-config`` on all supported platforms:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET REQUIRED)
+  pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk4>=4.14)
+  target_link_libraries(example PRIVATE PkgConfig::GTK)
+
+Example: Using ``pkg_get_variable()``
+"""""""""""""""""""""""""""""""""""""
+
+Retrieving the value of ``pkg-config`` variable ``girdir`` from the package
+Gobject:
+
+.. code-block:: cmake
+
+  find_package(PkgConfig QUIET)
+
+  if(PKG_CONFIG_FOUND)
+    pkg_get_variable(GI_GIRDIR gobject-introspection-1.0 girdir)
+  endif()
+
+  message(STATUS "${GI_GIRDIR}")
+
+See Also
+^^^^^^^^
+
+* The :command:`cmake_pkg_config` command for a modern and more advanced
+  way to work with ``pkg-config`` in CMake without requiring ``pkg-config``
+  executable to be installed.
+* :ref:`Find Modules` for details how to write a find module.
 #]========================================]
 
 ### Common stuff ####
@@ -703,161 +1129,6 @@
   endif()
 endmacro()
 
-
-#[========================================[.rst:
-.. command:: pkg_check_modules
-
-  Checks for all the given modules, setting a variety of result variables in
-  the calling scope.
-
-  .. code-block:: cmake
-
-    pkg_check_modules(<prefix>
-                      [REQUIRED] [QUIET]
-                      [NO_CMAKE_PATH]
-                      [NO_CMAKE_ENVIRONMENT_PATH]
-                      [IMPORTED_TARGET [GLOBAL]]
-                      <moduleSpec> [<moduleSpec>...])
-
-  When the ``REQUIRED`` argument is given, the command will fail with an error
-  if module(s) could not be found.
-
-  When the ``QUIET`` argument is given, no status messages will be printed.
-
-  .. versionadded:: 3.3
-    The :variable:`CMAKE_PREFIX_PATH`,
-    :variable:`CMAKE_FRAMEWORK_PATH`, and :variable:`CMAKE_APPBUNDLE_PATH` cache
-    and environment variables will be added to the ``pkg-config`` search path.
-    The ``NO_CMAKE_PATH`` and ``NO_CMAKE_ENVIRONMENT_PATH`` arguments
-    disable this behavior for the cache variables and environment variables
-    respectively.
-    The :variable:`PKG_CONFIG_USE_CMAKE_PREFIX_PATH` variable set to ``FALSE``
-    disables this behavior globally.
-
-    .. This was actually added in 3.1, but didn't work until 3.3.
-
-  .. versionadded:: 3.7
-    The ``IMPORTED_TARGET`` argument will create an imported target named
-    ``PkgConfig::<prefix>`` that can be passed directly as an argument to
-    :command:`target_link_libraries`.
-
-    .. This was actually added in 3.6, but didn't work until 3.7.
-
-  .. versionadded:: 3.13
-    The ``GLOBAL`` argument will make the
-    imported target available in global scope.
-
-  .. versionadded:: 3.15
-    Non-library linker options reported by ``pkg-config`` are stored in the
-    :prop_tgt:`INTERFACE_LINK_OPTIONS` target property.
-
-  .. versionchanged:: 3.18
-    Include directories specified with ``-isystem`` are stored in the
-    :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target property.  Previous
-    versions of CMake left them in the :prop_tgt:`INTERFACE_COMPILE_OPTIONS`
-    property.
-
-  Each ``<moduleSpec>`` can be either a bare module name or it can be a
-  module name with a version constraint (operators ``=``, ``<``, ``>``,
-  ``<=`` and ``>=`` are supported).  The following are examples for a module
-  named ``foo`` with various constraints:
-
-  - ``foo`` matches any version.
-  - ``foo<2`` only matches versions before 2.
-  - ``foo>=3.1`` matches any version from 3.1 or later.
-  - ``foo=1.2.3`` requires that foo must be exactly version 1.2.3.
-
-  The following variables may be set upon return.  Two sets of values exist:
-  One for the common case (``<XXX> = <prefix>``) and another for the
-  information ``pkg-config`` provides when called with the ``--static``
-  option (``<XXX> = <prefix>_STATIC``).
-
-  ``<XXX>_FOUND``
-    set to 1 if module(s) exist
-  ``<XXX>_LIBRARIES``
-    only the libraries (without the '-l')
-  ``<XXX>_LINK_LIBRARIES``
-    the libraries and their absolute paths
-  ``<XXX>_LIBRARY_DIRS``
-    the paths of the libraries (without the '-L')
-  ``<XXX>_LDFLAGS``
-    all required linker flags
-  ``<XXX>_LDFLAGS_OTHER``
-    all other linker flags
-  ``<XXX>_INCLUDE_DIRS``
-    the '-I' preprocessor flags (without the '-I')
-  ``<XXX>_CFLAGS``
-    all required cflags
-  ``<XXX>_CFLAGS_OTHER``
-    the other compiler flags
-
-  All but ``<XXX>_FOUND`` may be a :ref:`;-list <CMake Language Lists>` if the
-  associated variable returned from ``pkg-config`` has multiple values.
-
-  .. versionchanged:: 3.18
-    Include directories specified with ``-isystem`` are stored in the
-    ``<XXX>_INCLUDE_DIRS`` variable.  Previous versions of CMake left them
-    in ``<XXX>_CFLAGS_OTHER``.
-
-  There are some special variables whose prefix depends on the number of
-  ``<moduleSpec>`` given.  When there is only one ``<moduleSpec>``,
-  ``<YYY>`` will simply be ``<prefix>``, but if two or more ``<moduleSpec>``
-  items are given, ``<YYY>`` will be ``<prefix>_<moduleName>``.
-
-  ``<YYY>_VERSION``
-    version of the module
-  ``<YYY>_PREFIX``
-    prefix directory of the module
-  ``<YYY>_INCLUDEDIR``
-    include directory of the module
-  ``<YYY>_LIBDIR``
-    lib directory of the module
-
-  .. versionchanged:: 3.8
-    For any given ``<prefix>``, ``pkg_check_modules()`` can be called multiple
-    times with different parameters.  Previous versions of CMake cached and
-    returned the first successful result.
-
-  .. versionchanged:: 3.16
-    If a full path to the found library can't be determined, but it's still
-    visible to the linker, pass it through as ``-l<name>``.  Previous versions
-    of CMake failed in this case.
-
-  Examples:
-
-  .. code-block:: cmake
-
-    pkg_check_modules (GLIB2 glib-2.0)
-
-  Looks for any version of glib2.  If found, the output variable
-  ``GLIB2_VERSION`` will hold the actual version found.
-
-  .. code-block:: cmake
-
-    pkg_check_modules (GLIB2 glib-2.0>=2.10)
-
-  Looks for at least version 2.10 of glib2.  If found, the output variable
-  ``GLIB2_VERSION`` will hold the actual version found.
-
-  .. code-block:: cmake
-
-    pkg_check_modules (FOO glib-2.0>=2.10 gtk+-2.0)
-
-  Looks for both glib2-2.0 (at least version 2.10) and any version of
-  gtk2+-2.0.  Only if both are found will ``FOO`` be considered found.
-  The ``FOO_glib-2.0_VERSION`` and ``FOO_gtk+-2.0_VERSION`` variables will be
-  set to their respective found module versions.
-
-  .. code-block:: cmake
-
-    pkg_check_modules (XRENDER REQUIRED xrender)
-
-  Requires any version of ``xrender``.  Example output variables set by a
-  successful call::
-
-    XRENDER_LIBRARIES=Xrender;X11
-    XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp
-#]========================================]
 macro(pkg_check_modules _prefix _module0)
   _pkgconfig_parse_options(_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN})
   # check cached value
@@ -877,34 +1148,6 @@
   endif()
 endmacro()
 
-
-#[========================================[.rst:
-.. command:: pkg_search_module
-
-  The behavior of this command is the same as :command:`pkg_check_modules`,
-  except that rather than checking for all the specified modules, it searches
-  for just the first successful match.
-
-  .. code-block:: cmake
-
-    pkg_search_module(<prefix>
-                      [REQUIRED] [QUIET]
-                      [NO_CMAKE_PATH]
-                      [NO_CMAKE_ENVIRONMENT_PATH]
-                      [IMPORTED_TARGET [GLOBAL]]
-                      <moduleSpec> [<moduleSpec>...])
-
-  .. versionadded:: 3.16
-    If a module is found, the ``<prefix>_MODULE_NAME`` variable will contain the
-    name of the matching module. This variable can be used if you need to run
-    :command:`pkg_get_variable`.
-
-  Example:
-
-  .. code-block:: cmake
-
-    pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2)
-#]========================================]
 macro(pkg_search_module _prefix _module0)
   _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN})
   # check cached value
@@ -939,36 +1182,6 @@
   endif()
 endmacro()
 
-#[========================================[.rst:
-.. command:: pkg_get_variable
-
-  .. versionadded:: 3.4
-
-  Retrieves the value of a pkg-config variable ``varName`` and stores it in the
-  result variable ``resultVar`` in the calling scope.
-
-  .. code-block:: cmake
-
-    pkg_get_variable(<resultVar> <moduleName> <varName>
-                     [DEFINE_VARIABLES <key>=<value>...])
-
-  If ``pkg-config`` returns multiple values for the specified variable,
-  ``resultVar`` will contain a :ref:`;-list <CMake Language Lists>`.
-
-  Options:
-
-  ``DEFINE_VARIABLES <key>=<value>...``
-    .. versionadded:: 3.28
-
-    Specify key-value pairs to redefine variables affecting the variable
-    retrieved with ``pkg-config``.
-
-  For example:
-
-  .. code-block:: cmake
-
-    pkg_get_variable(GI_GIRDIR gobject-introspection-1.0 girdir)
-#]========================================]
 function (pkg_get_variable result pkg variable)
   set(_multiValueArgs DEFINE_VARIABLES)
 
@@ -989,55 +1202,3 @@
     PARENT_SCOPE)
   _pkg_restore_path_internal()
 endfunction ()
-
-
-#[========================================[.rst:
-Variables Affecting Behavior
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. variable:: PKG_CONFIG_EXECUTABLE
-
-  This cache variable can be set to the path of the pkg-config executable.
-  :command:`find_program` is called internally by the module with this
-  variable.
-
-  .. versionadded:: 3.1
-    The ``PKG_CONFIG`` environment variable can be used as a hint if
-    ``PKG_CONFIG_EXECUTABLE`` has not yet been set.
-
-  .. versionchanged:: 3.22
-    If the ``PKG_CONFIG`` environment variable is set, only the first
-    argument is taken from it when using it as a hint.
-
-.. variable:: PKG_CONFIG_ARGN
-
-  .. versionadded:: 3.22
-
-  This cache variable can be set to a list of arguments to additionally pass
-  to pkg-config if needed. If not provided, it will be initialized from the
-  ``PKG_CONFIG`` environment variable, if set. The first argument in that
-  environment variable is assumed to be the pkg-config program, while all
-  remaining arguments after that are used to initialize ``PKG_CONFIG_ARGN``.
-  If no such environment variable is defined, ``PKG_CONFIG_ARGN`` is
-  initialized to an empty string. The module does not update the variable once
-  it has been set in the cache.
-
-.. variable:: PKG_CONFIG_USE_CMAKE_PREFIX_PATH
-
-  .. versionadded:: 3.1
-
-  Specifies whether :command:`pkg_check_modules` and
-  :command:`pkg_search_module` should add the paths in the
-  :variable:`CMAKE_PREFIX_PATH`, :variable:`CMAKE_FRAMEWORK_PATH` and
-  :variable:`CMAKE_APPBUNDLE_PATH` cache and environment variables to the
-  ``pkg-config`` search path.
-
-  If this variable is not set, this behavior is enabled by default if
-  :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` is 3.1 or later, disabled
-  otherwise.
-#]========================================]
-
-
-### Local Variables:
-### mode: cmake
-### End:
diff --git a/Modules/FindQt3.cmake b/Modules/FindQt3.cmake
index 9ab193a..ae4bb93 100644
--- a/Modules/FindQt3.cmake
+++ b/Modules/FindQt3.cmake
@@ -92,7 +92,7 @@
 #  QT_WRAP_UI set true if QT_UIC_EXECUTABLE is found
 
 # If Qt4 has already been found, fail.
-if(QT4_FOUND)
+if(Qt4_FOUND)
   if(Qt3_FIND_REQUIRED)
     message( FATAL_ERROR "Qt3 and Qt4 cannot be used together in one project.")
   else()
diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake
index 6ba7e1a..c084e81 100644
--- a/Modules/FindQt4.cmake
+++ b/Modules/FindQt4.cmake
@@ -127,17 +127,18 @@
 This module defines the following variables:
 
 ``Qt4_FOUND``
-  Boolean whether Qt4 has been found.  If false, don't try to use Qt4.
+  Boolean indicating whether (the requested version of) Qt4 is found.
+
 ``QT_FOUND``
-  Boolean whether Qt4 has been found.  If false, don't try to use Qt4.  This
-  variable is for compatibility with other Qt find modules.
-``QT4_FOUND``
-  Boolean whether Qt4 has been found.  If false, don't try to use Qt4.  This
-  variable is for backward compatibility only.
+  Boolean indicating whether (the requested version of) Qt4 has been found.
+  This variable is available for compatibility with other Qt find modules.
+
 ``QT_VERSION_MAJOR``
   The major version of Qt found.
+
 ``QT_VERSION_MINOR``
   The minor version of Qt found.
+
 ``QT_VERSION_PATCH``
   The patch version of Qt found.
 
@@ -438,6 +439,15 @@
   the ``QtCore``, ``QtGui`` and ``QtDeclarative`` components on the project
   target ``myexe``.
 
+Deprecated Variables
+^^^^^^^^^^^^^^^^^^^^
+
+The following variables are provided for backward compatibility:
+
+``QT4_FOUND``
+  .. deprecated:: 2.8.11
+    Use ``Qt4_FOUND``, which has the same value.
+
 Examples
 ^^^^^^^^
 
diff --git a/Modules/FindSubversion.cmake b/Modules/FindSubversion.cmake
index ae17656..47e775f 100644
--- a/Modules/FindSubversion.cmake
+++ b/Modules/FindSubversion.cmake
@@ -22,7 +22,9 @@
   client is found.  For backward compatibility, the ``SUBVERSION_FOUND``
   variable is also set to the same value.
 
-``Subversion_VERSION_SVN``
+``Subversion_VERSION``
+  .. versionadded:: 4.2
+
   Version of the ``svn`` command-line client found.
 
 Cache Variables
@@ -93,6 +95,17 @@
     Last log of the base revision of a Subversion working copy located at
     ``<dir>``.
 
+Deprecated Variables
+^^^^^^^^^^^^^^^^^^^^
+
+The following variables are provided for backward compatibility:
+
+``Subversion_VERSION_SVN``
+  .. deprecated:: 4.2
+    Use the ``Subversion_VERSION``.
+
+  Version of the ``svn`` command-line client found.
+
 Examples
 ^^^^^^^^
 
@@ -166,6 +179,12 @@
     endif()
   endif()
 
+  if(DEFINED Subversion_VERSION_SVN)
+    set(Subversion_VERSION "${Subversion_VERSION_SVN}")
+  else()
+    unset(Subversion_VERSION)
+  endif()
+
   macro(Subversion_WC_INFO dir prefix)
 
     cmake_parse_arguments(
@@ -229,7 +248,7 @@
 
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(Subversion REQUIRED_VARS Subversion_SVN_EXECUTABLE
-                                             VERSION_VAR Subversion_VERSION_SVN )
+                                             VERSION_VAR Subversion_VERSION)
 
 # for compatibility
 set(Subversion_SVN_FOUND ${Subversion_FOUND})
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index fa2ad7b..ddcbdf6 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -5,133 +5,251 @@
 FindwxWidgets
 -------------
 
-Find a wxWidgets (a.k.a., wxWindows) installation.
+Finds a wxWidgets installation and provides usage requirements for usage in
+projects:
 
-This module finds if wxWidgets is installed and selects a default
-configuration to use.  wxWidgets is a modular library.  To specify the
-modules that you will use, you need to name them as components to the
-package:
+.. code-block:: cmake
 
-find_package(wxWidgets COMPONENTS core base ... OPTIONAL_COMPONENTS net ...)
+  find_package(wxWidgets [<version>] [COMPONENTS <components>...] [...])
+
+wxWidgets (formerly known as wxWindows) is a widget toolkit and tools
+library for creating graphical user interfaces (GUIs) for cross-platform
+applications.
 
 .. versionadded:: 3.4
-  Support for :command:`find_package` version argument; ``webview`` component.
+  Support for :command:`find_package` version argument.
 
 .. versionadded:: 3.14
   ``OPTIONAL_COMPONENTS`` support.
 
-There are two search branches: a windows style and a unix style.  For
-windows, the following variables are searched for and set to defaults
-in case of multiple choices.  Change them if the defaults are not
-desired (i.e., these are the only variables you should change to
-select a configuration):
+Components
+^^^^^^^^^^
 
-::
-
-  wxWidgets_ROOT_DIR      - Base wxWidgets directory
-                            (e.g., C:/wxWidgets-3.2.0).
-  wxWidgets_LIB_DIR       - Path to wxWidgets libraries
-                            (e.g., C:/wxWidgets-3.2.0/lib/vc_x64_lib).
-  wxWidgets_CONFIGURATION - Configuration to use
-                            (e.g., msw, mswd, mswu, mswunivud, etc.)
-  wxWidgets_EXCLUDE_COMMON_LIBRARIES
-                          - Set to TRUE to exclude linking of
-                            commonly required libs (e.g., png tiff
-                            jpeg zlib regex expat scintilla lexilla).
-
-
-
-For unix style it uses the wx-config utility.  You can select between
-debug/release, unicode/ansi, universal/non-universal, and
-static/shared in the QtDialog or ccmake interfaces by turning ON/OFF
-the following variables:
-
-::
-
-  wxWidgets_USE_DEBUG
-  wxWidgets_USE_UNICODE
-  wxWidgets_USE_UNIVERSAL
-  wxWidgets_USE_STATIC
-
-There is also a wxWidgets_CONFIG_OPTIONS variable for all other
-options that need to be passed to the wx-config utility.  For example,
-to use the base toolkit found in the /usr/local path, set the variable
-(before calling the FIND_PACKAGE command) as such:
+wxWidgets is a modular library.  This module supports components to specify
+the modules to use.  Components can be specified with the
+:command:`find_package` command:
 
 .. code-block:: cmake
 
-  set(wxWidgets_CONFIG_OPTIONS --toolkit=base --prefix=/usr)
+  find_package(
+    wxWidgets
+    [COMPONENTS <components>...]
+    [OPTIONAL_COMPONENTS <components>...]
+  )
 
+Supported components include:
 
+``base``
+  Finds the library that provides mandatory classes that any wxWidgets code
+  depends on.  This component is always required for applications
+  implementing wxWidgets.
 
-The following are set after the configuration is done for both windows
-and unix style:
+``core``
+  Finds the library that provides basic GUI classes such as GDI classes or
+  controls.
 
-::
+``gl``
+  Finds the OpenGL support.
 
-  wxWidgets_FOUND            - Set to TRUE if wxWidgets was found.
-  wxWidgets_INCLUDE_DIRS     - Include directories for WIN32
-                               i.e., where to find "wx/wx.h" and
-                               "wx/setup.h"; possibly empty for unices.
-  wxWidgets_LIBRARIES        - Path to the wxWidgets libraries.
-  wxWidgets_LIBRARY_DIRS     - compile time link dirs, useful for
-                               rpath on UNIX. Typically an empty string
-                               in WIN32 environment.
-  wxWidgets_DEFINITIONS      - Contains defines required to compile/link
-                               against WX, e.g. WXUSINGDLL
-  wxWidgets_DEFINITIONS_DEBUG- Contains defines required to compile/link
-                               against WX debug builds, e.g. __WXDEBUG__
-  wxWidgets_CXX_FLAGS        - Include dirs and compiler flags for
-                               unices, empty on WIN32. Essentially
-                               "`wx-config --cxxflags`".
-  wxWidgets_USE_FILE         - Convenience include file.
+``mono``
+  Finds the wxWidgets monolithic library.
 
-.. versionadded:: 3.11
-  The following environment variables can be used as hints: ``WX_CONFIG``,
-  ``WXRC_CMD``.
+``aui``
+  Finds the Advanced User Interface docking library.
 
+``net``
+  Finds the library that provides network access.
 
-Sample usage:
+``webview``
+  .. versionadded:: 3.4
 
-.. code-block:: cmake
+  Finds the library that provides rendering of web documents
+  (HTML/CSS/JavaScript).
 
-   # Note that for MinGW users the order of libs is important!
-   find_package(wxWidgets COMPONENTS gl core base OPTIONAL_COMPONENTS net)
-   if(wxWidgets_FOUND)
-     include(${wxWidgets_USE_FILE})
-     # and for each of your dependent executable/library targets:
-     target_link_libraries(<YourTarget> ${wxWidgets_LIBRARIES})
-   endif()
+For a full list of supported wxWidgets components, refer to the upstream
+documentation.
 
-
-
-If wxWidgets is required (i.e., not an optional part):
-
-.. code-block:: cmake
-
-   find_package(wxWidgets REQUIRED gl core base OPTIONAL_COMPONENTS net)
-   include(${wxWidgets_USE_FILE})
-   # and for each of your dependent executable/library targets:
-   target_link_libraries(<YourTarget> ${wxWidgets_LIBRARIES})
+If no components are specified, this module by default searches for ``core``
+and ``base`` components.
 
 Imported Targets
 ^^^^^^^^^^^^^^^^
 
-.. versionadded:: 3.27
-
-This module defines the following :prop_tgt:`IMPORTED` targets:
+This module provides the following :ref:`Imported Targets`:
 
 ``wxWidgets::wxWidgets``
-  An interface library providing usage requirements for the found components.
-#]=======================================================================]
+  .. versionadded:: 3.27
 
-#
-# FIXME: check this and provide a correct sample usage...
-#        Remember to connect back to the upper text.
-# Sample usage with monolithic wx build:
-#
-#   find_package(wxWidgets COMPONENTS mono)
-#   ...
+  An interface imported target encapsulating the wxWidgets usage requirements
+  for the found components, available if wxWidgets is found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``wxWidgets_FOUND``
+  Boolean indicating whether (the requested version of) wxWidgets and all
+  its requested components are found.
+
+``wxWidgets_VERSION_STRING``
+  .. versionadded:: 3.4
+
+  The version of the wxWidgets found.
+
+``wxWidgets_INCLUDE_DIRS``
+  Include directories for WIN32, i.e., where to find ``<wx/wx.h>`` and
+  ``<wx/setup.h>``; possibly empty for Unix-like systems.
+
+``wxWidgets_LIBRARIES``
+  Path to the wxWidgets libraries.
+
+``wxWidgets_LIBRARY_DIRS``
+  Compile time link dirs, useful for setting ``rpath`` on Unix-like systems.
+  Typically an empty string in WIN32 environment.
+
+``wxWidgets_DEFINITIONS``
+  Contains compile definitions required to compile/link against WX, e.g.
+  ``WXUSINGDLL``.
+
+``wxWidgets_DEFINITIONS_DEBUG``
+  Contains compile definitions required to compile/link against WX debug builds,
+  e.g. ``__WXDEBUG__``.
+
+``wxWidgets_CXX_FLAGS``
+  Include directories and compiler flags for Unix-like systems, empty on
+  Windows. Essentially the output of ``wx-config --cxxflags``.
+
+``wxWidgets_USE_FILE``
+  Name of the CMake module for using wxWidgets in current directory.  For
+  usage details refer to the :module:`UsewxWidgets` module.
+
+Hints
+^^^^^
+
+This module accepts the following variables before calling
+``find_package(wxWidgets)``:
+
+``WX_CONFIG``
+  .. versionadded:: 3.11
+
+  Environment variable to manually specify the name of the wxWidgets library
+  configuration provider executable that will be searched besides the default
+  name ``wx-config``.
+
+``WXRC_CMD``
+  .. versionadded:: 3.11
+
+  Environment variable to manually specify the name of the wxWidgets resource
+  file compiler executable that will be searched besides the default name
+  ``wxrc``.
+
+There are two search branches: a Windows style and a Unix style.  For
+Windows, the following variables are searched for and set to defaults
+in case of multiple choices.  Change them if the defaults are not
+desired (i.e., these are the only variables that should be changed to
+select a configuration):
+
+``wxWidgets_ROOT_DIR``
+  Base wxWidgets directory (e.g., ``C:/wxWidgets-3.2.0``).
+
+``wxWidgets_LIB_DIR``
+  Path to wxWidgets libraries (e.g., ``C:/wxWidgets-3.2.0/lib/vc_x64_lib``).
+
+``wxWidgets_CONFIGURATION``
+  Configuration to use (e.g., msw, mswd, mswu, mswunivud, etc.)
+
+``wxWidgets_EXCLUDE_COMMON_LIBRARIES``
+  Set to TRUE to exclude linking of commonly required libs (e.g., png, tiff,
+  jpeg, zlib, regex, expat, scintilla, lexilla, etc.).
+
+For Unix style this module uses the ``wx-config`` utility.  Selecting
+between debug/release, unicode/ansi, universal/non-universal, and
+static/shared is possible in the QtDialog or ccmake interfaces by turning
+ON/OFF the following variables:
+
+``wxWidgets_USE_DEBUG``
+  If enabled, the wxWidgets debug build will be searched.
+
+``wxWidgets_USE_UNICODE``
+  If enabled, the wxWidgets unicode build will be searched.
+
+``wxWidgets_USE_UNIVERSAL``
+  If enabled, the wxWidgets universal build will be searched.
+
+``wxWidgets_USE_STATIC``
+  If enabled, static wxWidgets libraries will be linked.
+
+``wxWidgets_CONFIG_OPTIONS``
+  This variable can be used for all other options that need to be passed to
+  the wx-config utility.  For example, to use the base toolkit found on the
+  system at ``/usr`` install prefix, set the variable (before calling the
+  :command:`find_package` command) as such:
+
+  .. code-block:: cmake
+
+    set(wxWidgets_CONFIG_OPTIONS --toolkit=base --prefix=/usr)
+
+Examples
+^^^^^^^^
+
+Example: Finding wxWidgets
+""""""""""""""""""""""""""
+
+Finding wxWidgets and making it required (if wxWidgets is not found,
+processing stops with an error message):
+
+.. code-block:: cmake
+
+   find_package(wxWidgets REQUIRED)
+
+Example: Using Imported Target
+""""""""""""""""""""""""""""""
+
+Finding wxWidgets and using imported target in a project:
+
+.. code-block:: cmake
+
+  find_package(wxWidgets)
+  target_link_libraries(example PRIVATE wxWidgets::wxWidgets)
+
+Example: Using Components
+"""""""""""""""""""""""""
+
+Finding wxWidgets and specifying components:
+
+.. code-block:: cmake
+
+  find_package(wxWidgets COMPONENTS gl core base OPTIONAL_COMPONENTS net)
+  target_link_libraries(example PRIVATE wxWidgets::wxWidgets)
+
+Example: Monolithic wxWidgets Build
+"""""""""""""""""""""""""""""""""""
+
+Sample usage with monolithic wxWidgets build:
+
+.. code-block:: cmake
+
+  find_package(wxWidgets COMPONENTS mono)
+  target_link_libraries(example PRIVATE wxWidgets::wxWidgets)
+
+Example: Using Variables
+""""""""""""""""""""""""
+
+Finding and using wxWidgets in CMake versions prior to 3.27, when the
+imported target wasn't yet available:
+
+.. code-block:: cmake
+
+  # Note that for MinGW users the order of libs is important.
+  find_package(wxWidgets COMPONENTS gl core base OPTIONAL_COMPONENTS net)
+
+  if(wxWidgets_FOUND)
+    include(${wxWidgets_USE_FILE})
+    # and for each of the project dependent executable/library targets:
+    target_link_libraries(example ${wxWidgets_LIBRARIES})
+  endif()
+#]=======================================================================]
 
 # NOTES
 #
diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake
index f1f5db7..952e66c 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -9,12 +9,19 @@
 
   Use :command:`file(GET_RUNTIME_DEPENDENCIES)` instead.
 
-This module provides functions to analyze and list the dependencies
-(prerequisites) of executable or shared library files.  These functions list the
-shared libraries (``.dll``, ``.dylib``, or ``.so`` files) required by an
+This module provides commands to analyze and list the dependencies
+(prerequisites) of executable or shared library files.  These commands list
+the shared libraries (``.dll``, ``.dylib``, or ``.so`` files) required by an
 executable or shared library.
 
-It determines dependencies using the following platform-specific tools:
+Load this module in CMake with:
+
+.. code-block:: cmake
+
+  include(GetPrerequisites)
+
+This module determines dependencies using the following platform-specific
+tools:
 
 * ``dumpbin`` (Windows)
 * ``objdump`` (MinGW on Windows)
@@ -25,7 +32,10 @@
   The tool specified by the :variable:`CMAKE_OBJDUMP` variable will be used, if
   set.
 
-The following functions are provided by this module:
+Commands
+^^^^^^^^
+
+This module provides the following commands:
 
 * :command:`get_prerequisites`
 * :command:`list_prerequisites`
@@ -40,20 +50,18 @@
   (projects can override it with ``gp_resolved_file_type_override()``)
 * :command:`gp_file_type`
 
-Functions
-^^^^^^^^^
-
 .. command:: get_prerequisites
 
+  Gets the list of shared library files required by specified target:
+
   .. code-block:: cmake
 
     get_prerequisites(<target> <prerequisites-var> <exclude-system> <recurse>
                       <exepath> <dirs> [<rpaths>])
 
-  Gets the list of shared library files required by ``<target>``.  The list
-  in the variable named ``<prerequisites-var>`` should be empty on first
-  entry to this function.  On exit, ``<prerequisites-var>`` will contain the
-  list of required shared library files.
+  The list in the variable named ``<prerequisites-var>`` should be empty on
+  first entry to this command.  On exit, ``<prerequisites-var>`` will contain
+  the list of required shared library files.
 
   The arguments are:
 
@@ -80,16 +88,16 @@
 
   .. versionadded:: 3.14
     The variable ``GET_PREREQUISITES_VERBOSE`` can be set to true before calling
-    this function to enable verbose output.
+    this command to enable verbose output.
 
 .. command:: list_prerequisites
 
+  Prints a message listing the prerequisites of the specified target:
+
   .. code-block:: cmake
 
     list_prerequisites(<target> [<recurse> [<exclude-system> [<verbose>]]])
 
-  Prints a message listing the prerequisites of ``<target>``.
-
   The arguments are:
 
   ``<target>``
@@ -107,15 +115,15 @@
 
 .. command:: list_prerequisites_by_glob
 
+  Prints the prerequisites of shared library and executable files matching a
+  globbing pattern:
+
   .. code-block:: cmake
 
     list_prerequisites_by_glob(<GLOB|GLOB_RECURSE>
                                <glob-exp>
                                [<optional-args>...])
 
-  Prints the prerequisites of shared library and executable files matching a
-  globbing pattern.
-
   The arguments are:
 
   ``GLOB`` or ``GLOB_RECURSE``
@@ -131,44 +139,56 @@
 
 .. command:: gp_append_unique
 
+  Appends the value to the list only if it is not already in the list:
+
   .. code-block:: cmake
 
     gp_append_unique(<list-var> <value>)
 
-  Appends ``<value>`` to the list variable ``<list-var>`` only if the value is
-  not already in the list.
+  The arguments are:
+
+  ``<value>``
+    The value to be appended to the list.
+  ``<list-var>``
+    The list variable name that will have the value appended only if it is
+    not already in the list.
 
 .. command:: is_file_executable
 
+  Checks if given file is a binary executable:
+
   .. code-block:: cmake
 
     is_file_executable(<file> <result-var>)
 
-  Sets ``<result-var>`` to 1 if ``<file>`` is a binary executable; otherwise
-  sets it to 0.
+  This command sets the ``<result-var>`` to 1 if ``<file>`` is a binary
+  executable; otherwise it sets it to 0.
 
 .. command:: gp_item_default_embedded_path
 
+  Determines the reference path for the specified item:
+
   .. code-block:: cmake
 
     gp_item_default_embedded_path(<item> <default-embedded-path-var>)
 
-  Determines the reference path for ``<item>`` when it is embedded inside a
-  bundle and stores it to a variable ``<default-embedded-path-var>``.
+  This command determines the reference path for ``<item>`` when it is
+  embedded inside a bundle and stores it to a variable
+  ``<default-embedded-path-var>``.
 
-  Projects can override this function by defining a custom
-  ``gp_item_default_embedded_path_override()`` function.
+  Projects can override this command by defining a custom
+  ``gp_item_default_embedded_path_override()`` command.
 
 .. command:: gp_resolve_item
 
+  Resolves a given item into an existing full path file and stores it to a
+  variable:
+
   .. code-block:: cmake
 
     gp_resolve_item(<context> <item> <exepath> <dirs> <resolved-item-var>
                     [<rpaths>])
 
-  Resolves a given ``<item>`` into an existing full path file and stores it to a
-  ``<resolved-item-var>`` variable.
-
   The arguments are:
 
   ``<context>``
@@ -187,18 +207,21 @@
   ``<rpaths>``
     See the argument description in :command:`get_prerequisites`.
 
-  Projects can override this function by defining a custom
-  ``gp_resolve_item_override()`` function.
+  Projects can override this command by defining a custom
+  ``gp_resolve_item_override()`` command.
 
 .. command:: gp_resolved_file_type
 
+  Determines the type of a given file:
+
   .. code-block:: cmake
 
     gp_resolved_file_type(<original-file> <file> <exepath> <dirs> <type-var>
                           [<rpaths>])
 
-  Determines the type of ``<file>`` with respect to ``<original-file>``. The
-  resulting type of prerequisite is stored in the ``<type-var>`` variable.
+  This command determines the type of ``<file>`` with respect to the
+  ``<original-file>``.  The resulting type of prerequisite is stored in the
+  ``<type-var>`` variable.
 
   Use ``<exepath>`` and ``<dirs>`` if necessary to resolve non-absolute
   ``<file>`` values -- but only for non-embedded items.
@@ -213,17 +236,20 @@
   * ``embedded``
   * ``other``
 
-  Projects can override this function by defining a custom
-  ``gp_resolved_file_type_override()`` function.
+  Projects can override this command by defining a custom
+  ``gp_resolved_file_type_override()`` command.
 
 .. command:: gp_file_type
 
+  Determines the type of a given file:
+
   .. code-block:: cmake
 
     gp_file_type(<original-file> <file> <type-var>)
 
-  Determines the type of ``<file>`` with respect to ``<original-file>``. The
-  resulting type of prerequisite is stored in the ``<type-var>`` variable.
+  This command determines the type of ``<file>`` with respect to the
+  ``<original-file>``.  The resulting type of prerequisite is stored in the
+  ``<type-var>`` variable.
 
   The ``<type-var>`` variable will be set to one of the following values:
 
@@ -235,6 +261,9 @@
 Examples
 ^^^^^^^^
 
+Example: Basic Usage
+""""""""""""""""""""
+
 Printing all dependencies of a shared library, including system libraries, with
 verbose output:
 
@@ -242,6 +271,25 @@
 
   include(GetPrerequisites)
   list_prerequisites("path/to/libfoo.dylib" 1 0 1)
+
+Example: Upgrading Code
+"""""""""""""""""""""""
+
+For example:
+
+.. code-block:: cmake
+
+  include(GetPrerequisites)
+  # ...
+  gp_append_unique(keys "${key}")
+
+the ``gp_append_unique()`` can be in new code replaced with:
+
+.. code-block:: cmake
+
+  if(NOT key IN_LIST keys)
+    list(APPEND keys "${key}")
+  endif()
 #]=======================================================================]
 
 function(gp_append_unique list_var value)
diff --git a/Modules/MacroAddFileDependencies.cmake b/Modules/MacroAddFileDependencies.cmake
index 9dee09d..0c65c46 100644
--- a/Modules/MacroAddFileDependencies.cmake
+++ b/Modules/MacroAddFileDependencies.cmake
@@ -6,24 +6,38 @@
 ------------------------
 
 .. deprecated:: 3.14
+  Do not use this module in new code.
+
+  Instead use the :command:`set_property` command to append to the
+  :prop_sf:`OBJECT_DEPENDS` source file property directly:
+
+  .. code-block:: cmake
+
+    set_property(SOURCE <source> APPEND PROPERTY OBJECT_DEPENDS <files>...)
+
+Load this module in a CMake project with:
 
 .. code-block:: cmake
 
-  macro_add_file_dependencies(<source> <files>...)
+  include(MacroAddFileDependencies)
 
-Do not use this command in new code.  It is just a wrapper around:
+Commands
+^^^^^^^^
 
-.. code-block:: cmake
+This module provides the following command:
 
-  set_property(SOURCE <source> APPEND PROPERTY OBJECT_DEPENDS <files>...)
+.. command:: macro_add_file_dependencies
 
-Instead use the :command:`set_property` command to append to the
-:prop_sf:`OBJECT_DEPENDS` source file property directly.
+  Adds dependencies to a source file:
 
+  .. code-block:: cmake
+
+    macro_add_file_dependencies(<source> <files>...)
+
+  This command adds the given ``<files>`` to the dependencies of file
+  ``<source>``.
 #]=======================================================================]
 
-macro (MACRO_ADD_FILE_DEPENDENCIES _file)
-
+macro(MACRO_ADD_FILE_DEPENDENCIES _file)
   set_property(SOURCE "${_file}" APPEND PROPERTY OBJECT_DEPENDS "${ARGN}")
-
-endmacro ()
+endmacro()
diff --git a/Modules/TestCXXAcceptsFlag.cmake b/Modules/TestCXXAcceptsFlag.cmake
index a39f8b3..69c7bc3 100644
--- a/Modules/TestCXXAcceptsFlag.cmake
+++ b/Modules/TestCXXAcceptsFlag.cmake
@@ -12,11 +12,19 @@
   :module:`CheckCompilerFlag` module is also available for checking flags across
   multiple languages.
 
-This module provides a macro to test whether the C++ (CXX) compiler supports
+This module provides a command to test whether the C++ (CXX) compiler supports
 specific flags.
 
-Macros
-^^^^^^
+Load this module in a CMake project with:
+
+.. code-block:: cmake
+
+  include(TestCXXAcceptsFlag)
+
+Commands
+^^^^^^^^
+
+This module provides the following command:
 
 .. command:: check_cxx_accepts_flag
 
diff --git a/Modules/UsePkgConfig.cmake b/Modules/UsePkgConfig.cmake
index 2c34c26..b047013 100644
--- a/Modules/UsePkgConfig.cmake
+++ b/Modules/UsePkgConfig.cmake
@@ -10,7 +10,7 @@
   This module should no longer be used.  Instead, use the
   :module:`FindPkgConfig` module or the :command:`cmake_pkg_config` command.
 
-  This module provided a macro for finding external packages using
+  This module provided a command for finding external packages using
   ``pkg-config`` command-line utility.  It has been replaced by the more
   convenient ``FindPkgConfig`` module, which is commonly used in
   :ref:`Find Modules`.
@@ -18,10 +18,16 @@
   As of CMake 3.31, the built-in :command:`cmake_pkg_config` command provides
   even more features to extract package information.
 
-Macros
-^^^^^^
+Load this module in a CMake project with:
 
-This module defines the following macro:
+.. code-block:: cmake
+
+  include(UsePkgConfig)
+
+Commands
+^^^^^^^^
+
+This module provides the following command:
 
 .. command:: pkgconfig
 
@@ -31,9 +37,10 @@
 
     pkgconfig(<package> <includedir> <libdir> <linkflags> <cflags>)
 
-  This macro invokes ``pkg-config`` command-line utility to retrieve the package
-  information into specified variables.  If ``pkg-config`` or the specified
-  package ``<package>`` is NOT found, the result variables remain empty.
+  This command invokes ``pkg-config`` command-line utility to retrieve the
+  package information into specified variables.  If ``pkg-config`` or the
+  specified package ``<package>`` is NOT found, the result variables remain
+  empty.
 
   The arguments are:
 
diff --git a/Modules/UsewxWidgets.cmake b/Modules/UsewxWidgets.cmake
index 3751025..4dc34e3 100644
--- a/Modules/UsewxWidgets.cmake
+++ b/Modules/UsewxWidgets.cmake
@@ -5,42 +5,66 @@
 UsewxWidgets
 ------------
 
+This module serves as a convenience wrapper for using the wxWidgets
+library (formerly known as wxWindows) and propagates its usage requirements,
+such as library directories, include directories, and compiler flags, into
+the current directory scope for use by targets.
+
+Load this module in a CMake project with:
+
+.. code-block:: cmake
+
+  include(UsewxWidgets)
+
 This module calls :command:`include_directories` and
-:command:`link_directories`, sets compile definitions for the current directory
-and appends some compile flags to use wxWidgets library after calling the
-:module:`find_package(wxWidgets) <FindwxWidgets>`.
+:command:`link_directories`, sets compile definitions for the current
+directory and appends some compile flags to use wxWidgets library after
+calling the :module:`find_package(wxWidgets) <FindwxWidgets>`.
 
 Examples
 ^^^^^^^^
 
-Include ``UsewxWidgets`` module in project's ``CMakeLists.txt``:
+Include this module in a project after finding wxWidgets to configure its
+usage requirements:
 
 .. code-block:: cmake
+  :caption: ``CMakeLists.txt``
 
   # Note that for MinGW users the order of libraries is important.
   find_package(wxWidgets REQUIRED net gl core base)
 
-  # Above also sets the wxWidgets_USE_FILE variable that points to this module.
-  include(${wxWidgets_USE_FILE})
+  add_library(example example.cxx)
 
-  # Link wxWidgets libraries for each dependent executable/library target.
-  target_link_libraries(<ProjectTarget> ${wxWidgets_LIBRARIES})
+  if(wxWidgets_FOUND)
+    # Above also sets the wxWidgets_USE_FILE variable that points to this module.
+    include(${wxWidgets_USE_FILE})
+
+    # Link wxWidgets libraries for each dependent executable/library target.
+    target_link_libraries(example PRIVATE ${wxWidgets_LIBRARIES})
+  endif()
 
 As of CMake 3.27, a better approach is to link only the
-:module:`wxWidgets::wxWidgets <FindwxWidgets>` ``IMPORTED`` target to specific
-targets that require it, rather than including this module. Imported targets
-provide better control of the package usage properties, such as include
-directories and compile flags, by applying them only to the targets they are
-linked to, avoiding unnecessary propagation to all targets in the current
-directory.
+:module:`wxWidgets::wxWidgets <FindwxWidgets>` imported target to specific
+targets that require it, rather than including this module.  Imported
+targets provide better control of the package usage properties, such as
+include directories and compile flags, by applying them only to the targets
+they are linked to, avoiding unnecessary propagation to all targets in the
+current directory.
 
 .. code-block:: cmake
+  :caption: ``CMakeLists.txt``
 
-  # CMakeLists.txt
   find_package(wxWidgets)
 
+  add_library(example example.cxx)
+
   # Link the imported target for each dependent executable/library target.
-  target_link_libraries(<ProjectTarget> wxWidgets::wxWidgets)
+  target_link_libraries(example PRIVATE wxWidgets::wxWidgets)
+
+See Also
+^^^^^^^^
+
+* The :module:`FindwxWidgets` module to find wxWidgets.
 #]=======================================================================]
 
 # Author: Jan Woetzel <jw -at- mip.informatik.uni-kiel.de>
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a8f5fd1..600c95e 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -401,6 +401,8 @@
   cmMSVC60LinkLineComputer.h
   cmOSXBundleGenerator.cxx
   cmOSXBundleGenerator.h
+  cmObjectLocation.cxx
+  cmObjectLocation.h
   cmOutputConverter.cxx
   cmOutputConverter.h
   cmNewLineStyle.h
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 51dfa3b..1013360 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 4)
 set(CMake_VERSION_MINOR 1)
-set(CMake_VERSION_PATCH 20250813)
+set(CMake_VERSION_PATCH 20250818)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 05489d0..f0c3439 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -76,6 +76,14 @@
   paths.emplace_back("/Applications/Xcode.app/Contents/Developer/Tools");
   paths.emplace_back("/Developer/Tools");
 
+  std::string const sync_path = cmSystemTools::FindProgram("sync");
+  if (sync_path.empty()) {
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+                  "Cannot locate sync command" << std::endl);
+    return 0;
+  }
+  this->SetOptionIfNotSet("CPACK_COMMAND_SYNC", sync_path);
+
   std::string const hdiutil_path = cmSystemTools::FindProgram("hdiutil");
   if (hdiutil_path.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -415,6 +423,16 @@
   std::string temp_image =
     cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp.dmg");
 
+  // Finish filesystem operations before writing disk image.
+  std::string sync_command = this->GetOption("CPACK_COMMAND_SYNC");
+  std::string sync_error;
+  if (!this->RunCommand(sync_command, &sync_error)) {
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+                  "Error running sync command." << std::endl
+                                                << sync_error << std::endl);
+    return 0;
+  }
+
   std::string create_error;
   auto temp_image_command =
     cmStrCat(this->GetOption("CPACK_COMMAND_HDIUTIL"),
diff --git a/Source/cmCMakePkgConfigCommand.cxx b/Source/cmCMakePkgConfigCommand.cxx
index 181c7d8..0d753bb 100644
--- a/Source/cmCMakePkgConfigCommand.cxx
+++ b/Source/cmCMakePkgConfigCommand.cxx
@@ -911,6 +911,9 @@
   auto& pcEnv = maybeEnv->first;
   auto& imEnv = maybeEnv->second;
 
+  pcEnv.AllowSysCflags = true;
+  pcEnv.AllowSysLibs = true;
+
   pkgProviders providers;
   if (args.Providers) {
     for (auto const& provider_str : *args.Providers) {
diff --git a/Source/cmExportPackageInfoGenerator.cxx b/Source/cmExportPackageInfoGenerator.cxx
index d38c640..4b17ac2 100644
--- a/Source/cmExportPackageInfoGenerator.cxx
+++ b/Source/cmExportPackageInfoGenerator.cxx
@@ -5,9 +5,11 @@
 #include <cstddef>
 #include <memory>
 #include <set>
+#include <type_traits>
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
 #include <cm/string_view>
 #include <cmext/algorithm>
 #include <cmext/string_view>
@@ -27,7 +29,6 @@
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
-#include "cmValue.h"
 
 static std::string const kCPS_VERSION_STR = "0.13.0";
 
@@ -146,15 +147,25 @@
       auto data = Json::Value{ Json::objectValue };
 
       // Add required components.
-      if (!requirement.second.empty()) {
+      if (!requirement.second.Components.empty()) {
         auto components = Json::Value{ Json::arrayValue };
-        for (std::string const& component : requirement.second) {
+        for (std::string const& component : requirement.second.Components) {
           components.append(component);
         }
         data["components"] = components;
       }
 
-      // TODO: version, hint
+      // Add additional dependency information.
+      if (requirement.second.Directory) {
+        auto hints = Json::Value{ Json::arrayValue };
+        hints.append(*requirement.second.Directory);
+        data["hints"] = hints;
+      }
+
+      if (requirement.second.Version) {
+        data["version"] = *requirement.second.Version;
+      }
+
       requirements[requirement.first] = data;
     }
   }
@@ -283,16 +294,24 @@
 
   if (linkedTarget->IsImported()) {
     // Target is imported from a found package.
-    auto pkgName = [linkedTarget]() -> std::string {
-      auto const& pkgStack = linkedTarget->Target->GetFindPackageStack();
+    using Package = cm::optional<std::pair<std::string, cmPackageInformation>>;
+    auto pkgInfo = [](cmTarget* t) -> Package {
+      cmFindPackageStack pkgStack = t->GetFindPackageStack();
       if (!pkgStack.Empty()) {
-        return pkgStack.Top().Name;
+        return std::make_pair(pkgStack.Top().Name, pkgStack.Top().PackageInfo);
       }
 
-      return linkedTarget->Target->GetProperty("EXPORT_FIND_PACKAGE_NAME");
-    }();
+      cmPackageInformation package;
+      std::string const pkgName =
+        t->GetSafeProperty("EXPORT_FIND_PACKAGE_NAME");
+      if (pkgName.empty()) {
+        return cm::nullopt;
+      }
 
-    if (pkgName.empty()) {
+      return std::make_pair(pkgName, package);
+    }(linkedTarget->Target);
+
+    if (!pkgInfo) {
       target->Makefile->IssueMessage(
         MessageType::FATAL_ERROR,
         cmStrCat("Target \"", target->GetName(),
@@ -301,6 +320,8 @@
       return false;
     }
 
+    std::string const& pkgName = pkgInfo->first;
+
     auto const& prefix = cmStrCat(pkgName, "::");
     if (!cmHasPrefix(linkedName, prefix)) {
       target->Makefile->IssueMessage(
@@ -314,8 +335,9 @@
 
     std::string component = linkedName.substr(prefix.length());
     this->LinkTargets.emplace(linkedName, cmStrCat(pkgName, ':', component));
-    // TODO: Record package version, hint.
-    this->Requirements[pkgName].emplace(std::move(component));
+    cmPackageInformation& req =
+      this->Requirements.insert(std::move(*pkgInfo)).first->second;
+    req.Components.emplace(std::move(component));
     return true;
   }
 
@@ -339,7 +361,7 @@
       this->LinkTargets.emplace(linkedName, cmStrCat(':', component));
     } else {
       this->LinkTargets.emplace(linkedName, cmStrCat(pkgName, ':', component));
-      this->Requirements[pkgName].emplace(std::move(component));
+      this->Requirements[pkgName].Components.emplace(std::move(component));
     }
     return true;
   }
diff --git a/Source/cmExportPackageInfoGenerator.h b/Source/cmExportPackageInfoGenerator.h
index 83cb6ad..0614e27 100644
--- a/Source/cmExportPackageInfoGenerator.h
+++ b/Source/cmExportPackageInfoGenerator.h
@@ -6,13 +6,13 @@
 
 #include <iosfwd>
 #include <map>
-#include <set>
 #include <string>
 #include <vector>
 
 #include <cm/string_view>
 
 #include "cmExportFileGenerator.h"
+#include "cmFindPackageStack.h"
 #include "cmStateTypes.h"
 
 namespace Json {
@@ -112,9 +112,10 @@
   std::string const PackageWebsite;
   std::string const PackageLicense;
   std::string const DefaultLicense;
+
   std::vector<std::string> DefaultTargets;
   std::vector<std::string> DefaultConfigurations;
 
   std::map<std::string, std::string> LinkTargets;
-  std::map<std::string, std::set<std::string>> Requirements;
+  std::map<std::string, cmPackageInformation> Requirements;
 };
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 243061e..6c43c7a 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -1224,6 +1224,8 @@
   SetRestoreFindDefinitions setRestoreFindDefinitions(*this);
   cmFindPackageStackRAII findPackageStackRAII(this->Makefile, this->Name);
 
+  findPackageStackRAII.BindTop(this->CurrentPackageInfo);
+
   // See if we have been told to delegate to FetchContent or some other
   // redirected config package first. We have to check all names that
   // find_package() may look for, but only need to invoke the override for the
@@ -1270,6 +1272,8 @@
       this->Names.clear();
       this->Names.emplace_back(overrideName); // Force finding this one
       this->Variable = cmStrCat(this->Name, "_DIR");
+      this->CurrentPackageInfo->Directory = redirectsDir;
+      this->CurrentPackageInfo->Version = this->VersionFound;
       this->SetConfigDirCacheVariable(redirectsDir);
       break;
     }
@@ -1342,7 +1346,6 @@
   }
 
   this->AppendSuccessInformation();
-
   return loadedPackage;
 }
 
@@ -1971,6 +1974,8 @@
   std::string init;
   if (found) {
     init = cmSystemTools::GetFilenamePath(this->FileFound);
+    this->CurrentPackageInfo->Directory = init;
+    this->CurrentPackageInfo->Version = this->VersionFound;
   } else {
     init = this->Variable + "-NOTFOUND";
   }
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index d225fb9..ff8ff27 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -37,6 +37,7 @@
 class cmMakefile;
 class cmPackageState;
 class cmSearchPath;
+class cmPackageInformation;
 
 /** \class cmFindPackageCommand
  * \brief Load settings from an external project.
@@ -286,6 +287,8 @@
   std::set<std::string> OptionalComponents;
   std::set<std::string> RequiredTargets;
   std::string DebugBuffer;
+  cmPackageInformation* CurrentPackageInfo;
+
   enum class SearchResult
   {
     InsufficientVersion,
diff --git a/Source/cmFindPackageStack.h b/Source/cmFindPackageStack.h
index f2bb6c6..e7fb9a6 100644
--- a/Source/cmFindPackageStack.h
+++ b/Source/cmFindPackageStack.h
@@ -5,19 +5,41 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <memory>
+#include <set>
 #include <string>
 
+#include <cm/optional>
+
 #include "cmStack.h"
 
 class cmMakefile;
 
 /**
+ * This data represents the actual contents of find_package
+ * <PACKAGE>-Config.cmake or <PACKAGE>.cps file, and not what is passed
+ * to the find_package command. They can be the same, but it is not guaranteed.
+ */
+
+class cmPackageInformation
+{
+public:
+  cm::optional<std::string> Directory;
+  cm::optional<std::string> Version;
+  cm::optional<std::string> Description;
+  cm::optional<std::string> License;
+  cm::optional<std::string> Website;
+  cm::optional<std::string> PackageUrl;
+  std::set<std::string> Components;
+};
+
+/**
  * Represents one call to find_package.
  */
 class cmFindPackageCall
 {
 public:
-  std::string Name;
+  std::string const Name;
+  cmPackageInformation PackageInfo;
   unsigned int Index;
 };
 
@@ -28,7 +50,7 @@
 class cmFindPackageStackRAII
 {
   cmMakefile* Makefile;
-  cmFindPackageCall** Value = nullptr;
+  cmPackageInformation** Value = nullptr;
 
 public:
   cmFindPackageStackRAII(cmMakefile* mf, std::string const& pkg);
@@ -40,7 +62,7 @@
   /** Get a mutable pointer to the top of the stack.
       The pointer is invalidated if BindTop is called again or when the
       cmFindPackageStackRAII goes out of scope.  */
-  void BindTop(cmFindPackageCall*& value);
+  void BindTop(cmPackageInformation*& value);
 };
 
 /**
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 96867e2..8b74118 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -100,6 +100,9 @@
 bool cmForEachFunctionBlocker::Replay(
   std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus)
 {
+  if (this->Args.size() == this->IterationVarsCount) {
+    return true;
+  }
   return this->ZipLists ? this->ReplayZipLists(functions, inStatus)
                         : this->ReplayItems(functions, inStatus);
 }
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 24a66c4..006594a 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -164,33 +164,36 @@
   std::string result;
   std::string::size_type pos = 0;
   std::string::size_type lastPos = pos;
-  // stack of { Generator Expression Name, Start Position of Value }
-  std::stack<std::pair<std::string, std::string::size_type>> genexps;
+  std::stack<char const*> starts; // indices of "$<"
+  std::stack<char const*> colons; // indices of ":"
   while ((pos = input.find("$<", lastPos)) != std::string::npos) {
     result += input.substr(lastPos, pos - lastPos);
+    starts.push(input.c_str() + pos);
     pos += 2;
     char const* c = input.c_str() + pos;
-    char const* cName = c;
     char const* const cStart = c;
     for (; *c; ++c) {
       if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
+        starts.push(c);
         ++c;
-        cName = c + 1;
         continue;
       }
-      if (c[0] == ':' && cName) {
-        genexps.push({ input.substr(pos + (cName - cStart), c - cName),
-                       pos + (c + 1 - cStart) });
-        cName = nullptr;
-      } else if (c[0] == '>') {
-        if (!cName && !genexps.empty()) {
-          if (collected) {
-            (*collected)[genexps.top().first].push_back(input.substr(
-              genexps.top().second, pos + c - cStart - genexps.top().second));
-          }
-          genexps.pop();
+      if (c[0] == ':') {
+        if (colons.size() < starts.size()) {
+          colons.push(c);
         }
-        if (genexps.empty()) {
+      } else if (c[0] == '>') {
+        if (collected && !starts.empty() && !colons.empty()) {
+          (*collected)[std::string(starts.top() + 2, colons.top())].push_back(
+            std::string(colons.top() + 1, c));
+        }
+        if (!starts.empty()) {
+          starts.pop();
+        }
+        if (!colons.empty()) {
+          colons.pop();
+        }
+        if (starts.empty()) {
           break;
         }
       }
@@ -202,7 +205,7 @@
     pos += traversed;
     lastPos = pos;
   }
-  if (genexps.empty()) {
+  if (starts.empty()) {
     result += input.substr(lastPos);
   }
   return cmGeneratorExpression::StripEmptyListElements(result);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index dc29ca0..14cbee8 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -856,7 +856,10 @@
 std::string const& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
 {
   this->ComputeObjectMapping();
-  return this->Objects[file];
+  auto const useShortPaths = this->GetUseShortObjectNames()
+    ? cmObjectLocations::UseShortPath::Yes
+    : cmObjectLocations::UseShortPath::No;
+  return this->Objects[file].GetPath(useShortPaths);
 }
 
 char const* cmGeneratorTarget::GetCustomObjectExtension() const
@@ -3995,9 +3998,21 @@
 void cmGeneratorTarget::GetTargetObjectNames(
   std::string const& config, std::vector<std::string>& objects) const
 {
+  this->GetTargetObjectLocations(
+    config,
+    [&objects](cmObjectLocation const& buildLoc, cmObjectLocation const&) {
+      objects.push_back(buildLoc.GetPath());
+    });
+}
+
+void cmGeneratorTarget::GetTargetObjectLocations(
+  std::string const& config,
+  std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
+  const
+{
   std::vector<cmSourceFile const*> objectSources;
   this->GetObjectSources(objectSources, config);
-  std::map<cmSourceFile const*, std::string> mapping;
+  std::map<cmSourceFile const*, cmObjectLocations> mapping;
 
   for (cmSourceFile const* sf : objectSources) {
     mapping[sf];
@@ -4005,12 +4020,20 @@
 
   this->LocalGenerator->ComputeObjectFilenames(mapping, this);
 
+  auto const buildUseShortPaths = this->GetUseShortObjectNames()
+    ? cmObjectLocations::UseShortPath::Yes
+    : cmObjectLocations::UseShortPath::No;
+  auto const installUseShortPaths = this->GetUseShortObjectNamesForInstall();
+
   for (cmSourceFile const* src : objectSources) {
     // Find the object file name corresponding to this source file.
     auto map_it = mapping.find(src);
+    auto const& buildLoc = map_it->second.GetLocation(buildUseShortPaths);
+    auto const& installLoc = map_it->second.GetLocation(installUseShortPaths);
     // It must exist because we populated the mapping just above.
-    assert(!map_it->second.empty());
-    objects.push_back(map_it->second);
+    assert(!buildLoc.GetPath().empty());
+    assert(!installLoc.GetPath().empty());
+    cb(buildLoc, installLoc);
   }
 
   // We need to compute the relative path from the root of
@@ -4020,7 +4043,9 @@
   auto ispcObjects = this->GetGeneratedISPCObjects(config);
   for (std::string const& output : ispcObjects) {
     auto relativePathFromObjectDir = output.substr(rootObjectDir.size());
-    objects.push_back(relativePathFromObjectDir);
+    cmObjectLocation ispcLoc(relativePathFromObjectDir);
+    // FIXME: apply short path to this object if needed.
+    cb(ispcLoc, ispcLoc);
   }
 }
 
@@ -5370,6 +5395,25 @@
   return this->LocalGenerator->UseShortObjectNames(kind);
 }
 
+cmObjectLocations::UseShortPath
+cmGeneratorTarget::GetUseShortObjectNamesForInstall() const
+{
+  auto prop = this->Target->GetProperty("INSTALL_OBJECT_NAME_STRATEGY");
+  if (prop == "SHORT"_s) {
+    return cmObjectLocations::UseShortPath::Yes;
+  }
+  if (prop == "FULL"_s) {
+    return cmObjectLocations::UseShortPath::No;
+  }
+  if (prop.IsSet()) {
+    this->Makefile->IssueMessage(
+      MessageType::FATAL_ERROR,
+      cmStrCat("Property INSTALL_OBJECT_NAME_STRATEGY of target \"",
+               this->GetName(), "\" set to the unsupported strategy ", prop));
+  }
+  return cmObjectLocations::UseShortPath::No;
+}
+
 std::string cmGeneratorTarget::GetSupportDirectory(
   cmStateEnums::IntermediateDirKind kind) const
 {
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 9f2349e..517bfcc 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -5,6 +5,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <cstddef>
+#include <functional>
 #include <map>
 #include <memory>
 #include <set>
@@ -20,6 +21,7 @@
 #include "cmAlgorithms.h"
 #include "cmLinkItem.h"
 #include "cmListFileCache.h"
+#include "cmObjectLocation.h"
 #include "cmPolicies.h"
 #include "cmStandardLevel.h"
 #include "cmStateTypes.h"
@@ -298,9 +300,14 @@
                                   cmStateEnums::RuntimeBinaryArtifact) const;
 
   /** Get the names of an object library's object files underneath
-      its object file directory.  */
+      its object file directory for the build.  */
   void GetTargetObjectNames(std::string const& config,
                             std::vector<std::string>& objects) const;
+  /** Get the build and install locations of objects for a given context. */
+  void GetTargetObjectLocations(
+    std::string const& config,
+    std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
+    const;
 
   /** What hierarchy level should the reported directory contain */
   enum BundleDirectoryLevel
@@ -940,6 +947,7 @@
   bool GetUseShortObjectNames(
     cmStateEnums::IntermediateDirKind kind =
       cmStateEnums::IntermediateDirKind::ObjectFiles) const;
+  cmObjectLocations::UseShortPath GetUseShortObjectNamesForInstall() const;
 
   /** Get a build-tree directory in which to place target support files.  */
   std::string GetSupportDirectory(
@@ -1142,7 +1150,7 @@
   using SourceEntriesType = std::map<cmSourceFile const*, SourceEntry>;
   SourceEntriesType SourceDepends;
   mutable std::set<std::string> VisitedConfigsForObjects;
-  mutable std::map<cmSourceFile const*, std::string> Objects;
+  mutable std::map<cmSourceFile const*, cmObjectLocations> Objects;
   std::set<cmSourceFile const*> ExplicitObjectName;
 
   using TargetPtrToBoolMap = std::unordered_map<cmTarget*, bool>;
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index c905a4e..4296c22 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -873,7 +873,7 @@
   std::vector<std::string> empty;
   std::vector<cmSourceFile const*> objectSources;
   gt->GetObjectSources(objectSources, configName);
-  std::map<cmSourceFile const*, std::string> mapping;
+  std::map<cmSourceFile const*, cmObjectLocations> mapping;
   for (cmSourceFile const* it : objectSources) {
     mapping[it];
   }
@@ -891,12 +891,17 @@
     return;
   }
 
+  auto const useShortPaths = this->UseShortObjectNames()
+    ? cmObjectLocations::UseShortPath::Yes
+    : cmObjectLocations::UseShortPath::No;
+
   if (mdi->WindowsExportAllSymbols) {
     std::vector<std::string> objs;
     for (cmSourceFile const* it : objectSources) {
       // Find the object file name corresponding to this source file.
       // It must exist because we populated the mapping just above.
-      auto const& v = mapping[it];
+      auto const& locs = mapping[it];
+      std::string const& v = locs.GetPath(useShortPaths);
       assert(!v.empty());
       std::string objFile = cmStrCat(obj_dir, v);
       objs.push_back(objFile);
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index b2a5f51..1bc347e 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -4,6 +4,7 @@
 
 #include <algorithm>
 #include <cassert>
+#include <cstddef>
 #include <functional>
 #include <map>
 #include <set>
@@ -21,6 +22,7 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmObjectLocation.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
 #include "cmScriptGenerator.h"
@@ -174,18 +176,40 @@
 
   // Write code to install the target file.
   char const* no_dir_permissions = nullptr;
-  char const* no_rename = nullptr;
   bool optional = this->Optional || this->ImportLibrary;
   std::string literal_args;
-  if (!files.FromDir.empty()) {
-    literal_args += " FILES_FROM_DIR \"" + files.FromDir + "\"";
-  }
   if (files.UseSourcePermissions) {
     literal_args += " USE_SOURCE_PERMISSIONS";
   }
-  this->AddInstallRule(os, dest, files.Type, files.From, optional,
-                       this->FilePermissions.c_str(), no_dir_permissions,
-                       no_rename, literal_args.c_str(), indent);
+  if (files.Rename) {
+    if (files.From.size() != files.To.size()) {
+      this->Target->GetLocalGenerator()->IssueMessage(
+        MessageType::INTERNAL_ERROR,
+        "cmInstallTargetGenerator generated a rename request with mismatched "
+        "names.");
+      return;
+    }
+    std::vector<std::string> FileNames;
+    FileNames.resize(1);
+    for (size_t i = 0; i < files.From.size(); ++i) {
+      if (files.FromDir.empty()) {
+        FileNames[0] = files.From[i];
+      } else {
+        FileNames[0] = cmStrCat(files.FromDir, '/', files.From[i]);
+      }
+      this->AddInstallRule(os, dest, files.Type, FileNames, optional,
+                           this->FilePermissions.c_str(), no_dir_permissions,
+                           files.To[i].c_str(), literal_args.c_str(), indent);
+    }
+  } else {
+    char const* no_rename = nullptr;
+    if (!files.FromDir.empty()) {
+      literal_args += " FILES_FROM_DIR \"" + files.FromDir + "\"";
+    }
+    this->AddInstallRule(os, dest, files.Type, files.From, optional,
+                         this->FilePermissions.c_str(), no_dir_permissions,
+                         no_rename, literal_args.c_str(), indent);
+  }
 
   // Add post-installation tweaks.
   if (!files.NoTweak) {
@@ -225,16 +249,21 @@
 
     case cmStateEnums::OBJECT_LIBRARY: {
       // Compute all the object files inside this target
-      std::vector<std::string> objects;
-      this->Target->GetTargetObjectNames(config, objects);
+      std::vector<std::pair<cmObjectLocation, cmObjectLocation>> objects;
+      auto storeObjectLocations = [&objects](cmObjectLocation const& build,
+                                             cmObjectLocation const& install) {
+        objects.emplace_back(build, install);
+      };
+      this->Target->GetTargetObjectLocations(config, storeObjectLocations);
 
       files.Type = cmInstallType_FILES;
       files.NoTweak = true;
+      files.Rename = true;
       files.FromDir = this->Target->GetObjectDirectory(config);
       files.ToDir = computeInstallObjectDir(this->Target, config);
-      for (std::string& obj : objects) {
-        files.From.emplace_back(obj);
-        files.To.emplace_back(std::move(obj));
+      for (auto const& obj : objects) {
+        files.From.emplace_back(obj.first.GetPath());
+        files.To.emplace_back(obj.second.GetPath());
       }
       return files;
     }
@@ -423,9 +452,17 @@
 void cmInstallTargetGenerator::GetInstallObjectNames(
   std::string const& config, std::vector<std::string>& objects) const
 {
-  this->Target->GetTargetObjectNames(config, objects);
-  for (std::string& o : objects) {
-    o = cmStrCat(computeInstallObjectDir(this->Target, config), '/', o);
+  std::vector<cmObjectLocation> installedObjects;
+  auto storeObjectLocations =
+    [&installedObjects](cmObjectLocation const&,
+                        cmObjectLocation const& install) {
+      installedObjects.emplace_back(install);
+    };
+  this->Target->GetTargetObjectLocations(config, storeObjectLocations);
+  objects.reserve(installedObjects.size());
+  auto const rootDir = computeInstallObjectDir(this->Target, config);
+  for (cmObjectLocation const& o : installedObjects) {
+    objects.emplace_back(cmStrCat(rootDir, '/', o.GetPath()));
   }
 }
 
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index da51a81..6ddfca6 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -86,6 +86,7 @@
     std::string ToDir;
 
     NamelinkModeType NamelinkMode = NamelinkModeNone;
+    bool Rename = false;
     bool NoTweak = false;
     bool UseSourcePermissions = false;
     cmInstallType Type = cmInstallType();
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 3a8453e..b79b24b 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -6,9 +6,12 @@
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
+
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
+#include "cmObjectLocation.h"
 #include "cmOutputConverter.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
@@ -111,7 +114,7 @@
 }
 
 void cmLocalCommonGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const* gt)
 {
   // Determine if these object files should use a custom extension
@@ -119,7 +122,11 @@
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
     bool keptSourceExtension;
-    si.second = this->GetObjectFileNameWithoutTarget(
-      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext);
+    bool force = true;
+    si.second.ShortLoc.emplace(this->GetObjectFileNameWithoutTarget(
+      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext, &force));
+    force = false;
+    si.second.LongLoc.Update(this->GetObjectFileNameWithoutTarget(
+      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext, &force));
   }
 }
diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h
index 7c63c19..1c104a7 100644
--- a/Source/cmLocalCommonGenerator.h
+++ b/Source/cmLocalCommonGenerator.h
@@ -13,6 +13,7 @@
 class cmGeneratorTarget;
 class cmGlobalGenerator;
 class cmMakefile;
+struct cmObjectLocations;
 class cmSourceFile;
 
 /** \class cmLocalCommonGenerator
@@ -39,7 +40,7 @@
     cmGeneratorTarget const* target) const override;
 
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr) override;
 
 protected:
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index d1c03a2..f2e9412 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2837,18 +2837,7 @@
                     langFlags.find("-Zi") != std::string::npos;
                 }
 
-                // MSVC 2008 is producing both .pdb and .idb files with /Zi.
-                bool msvc2008OrLess =
-                  cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
-                                                compilerVersion, "16.0") &&
-                  compilerId == "MSVC";
-                // but not when used via toolset -Tv90
-                if (this->Makefile->GetSafeDefinition(
-                      "CMAKE_VS_PLATFORM_TOOLSET") == "v90") {
-                  msvc2008OrLess = false;
-                }
-
-                if (editAndContinueDebugInfo || msvc2008OrLess) {
+                if (editAndContinueDebugInfo) {
                   this->CopyPchCompilePdb(config, lang, target, reuseTarget,
                                           { ".pdb", ".idb" });
                 } else if (programDatabaseDebugInfo) {
@@ -2939,10 +2928,9 @@
     std::string const from_file =
       replaceExtension(reuseTarget->GetCompilePDBPath(config), extension);
     std::string const to_dir = target->GetCompilePDBDirectory(config);
-    std::string const to_file = cmStrCat(
-      replaceExtension(reuseTarget->GetCompilePDBName(config), extension),
-      '/');
-    std::string const dest_file = cmStrCat(to_dir, to_file);
+    std::string const to_file =
+      replaceExtension(reuseTarget->GetCompilePDBName(config), extension);
+    std::string const dest_file = cmStrCat(to_dir, '/', to_file);
 
     file << "foreach(retry RANGE 1 30)\n";
     file << "  if (EXISTS \"" << from_file << "\" AND (NOT EXISTS \""
@@ -4143,7 +4131,7 @@
 }
 
 void cmLocalGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& /*unused*/,
+  std::map<cmSourceFile const*, cmObjectLocations>& /*unused*/,
   cmGeneratorTarget const* /*unused*/)
 {
 }
@@ -4227,8 +4215,13 @@
 
 std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
   cmSourceFile const& source, std::string const& dir_max,
-  bool* hasSourceExtension, char const* customOutputExtension)
+  bool* hasSourceExtension, char const* customOutputExtension,
+  bool const* forceShortObjectName)
 {
+  bool useShortObjectNames = this->UseShortObjectNames();
+  if (forceShortObjectName) {
+    useShortObjectNames = *forceShortObjectName;
+  }
 
   // This can return an absolute path in the case where source is
   // not relative to the current source or binary directoreis
@@ -4246,7 +4239,7 @@
   // Short object path policy selected, use as little info as necessary to
   // select an object name
   bool keptSourceExtension = true;
-  if (this->UseShortObjectNames()) {
+  if (useShortObjectNames) {
     objectName = this->GetShortObjectFileName(source);
     keptSourceExtension = false;
   }
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 4fa48fb..81b516b 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -37,6 +37,7 @@
 class cmLinkLineComputer;
 class cmLinkLineDeviceComputer;
 class cmMakefile;
+struct cmObjectLocations;
 class cmRulePlaceholderExpander;
 class cmSourceFile;
 class cmState;
@@ -473,7 +474,8 @@
   std::string GetObjectFileNameWithoutTarget(
     cmSourceFile const& source, std::string const& dir_max,
     bool* hasSourceExtension = nullptr,
-    char const* customOutputExtension = nullptr);
+    char const* customOutputExtension = nullptr,
+    bool const* forceShortObjectName = nullptr);
 
   /** Fill out the static linker flags for the given target.  */
   void GetStaticLibraryFlags(std::string& flags, std::string const& config,
@@ -524,7 +526,7 @@
                                             std::string const& config);
 
   virtual void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr);
 
   bool IsWindowsShell() const;
diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx
index 2e38dc7..812f025 100644
--- a/Source/cmLocalGhsMultiGenerator.cxx
+++ b/Source/cmLocalGhsMultiGenerator.cxx
@@ -5,9 +5,12 @@
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
+
 #include "cmGeneratorTarget.h"
 #include "cmGhsMultiTargetGenerator.h"
 #include "cmGlobalGenerator.h"
+#include "cmObjectLocation.h"
 #include "cmSourceFile.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
@@ -41,7 +44,7 @@
 }
 
 void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const* gt)
 {
   std::string dir_max = cmStrCat(gt->GetSupportDirectory(), '/');
@@ -63,17 +66,21 @@
   // object name computation.
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName = cmStrCat(
+    bool forceShortObjectName = true;
+    std::string shortObjectName = this->GetObjectFileNameWithoutTarget(
+      *sf, dir_max, nullptr, nullptr, &forceShortObjectName);
+    std::string longObjectName = cmStrCat(
       cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()),
       this->GlobalGenerator->GetLanguageOutputExtension(*sf));
 
-    if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
+    if (counts[cmSystemTools::LowerCase(longObjectName)] > 1) {
       const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
-      bool keptSourceExtension;
-      objectName = this->GetObjectFileNameWithoutTarget(*sf, dir_max,
-                                                        &keptSourceExtension);
-      cmsys::SystemTools::ReplaceString(objectName, "/", "_");
+      forceShortObjectName = false;
+      longObjectName = this->GetObjectFileNameWithoutTarget(
+        *sf, dir_max, nullptr, nullptr, &forceShortObjectName);
+      cmsys::SystemTools::ReplaceString(longObjectName, "/", "_");
     }
-    si.second = objectName;
+    si.second.ShortLoc.emplace(shortObjectName);
+    si.second.LongLoc.Update(longObjectName);
   }
 }
diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h
index 698ef39..ae80b2b 100644
--- a/Source/cmLocalGhsMultiGenerator.h
+++ b/Source/cmLocalGhsMultiGenerator.h
@@ -10,6 +10,7 @@
 class cmGeneratorTarget;
 class cmGlobalGenerator;
 class cmMakefile;
+struct cmObjectLocations;
 class cmSourceFile;
 
 /** \class cmLocalGhsMultiGenerator
@@ -34,6 +35,6 @@
     cmGeneratorTarget const* target) const override;
 
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr) override;
 };
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 4ea3f1b..9d7a507 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -39,7 +39,7 @@
 }
 
 void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const* gt)
 {
   char const* custom_ext = gt->GetCustomObjectExtension();
@@ -73,25 +73,25 @@
 
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName;
-    if (gt->GetUseShortObjectNames()) {
-      objectName = this->GetShortObjectFileName(*sf);
-    } else {
-      objectName =
-        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
-    }
+    std::string shortObjectName = this->GetShortObjectFileName(*sf);
+    std::string longObjectName =
+      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
     if (custom_ext) {
-      objectName += custom_ext;
+      shortObjectName += custom_ext;
+      longObjectName += custom_ext;
     } else {
-      objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+      shortObjectName +=
+        this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+      longObjectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
     }
-    if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
+    if (counts[cmSystemTools::LowerCase(longObjectName)] > 1) {
       const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
       bool keptSourceExtension;
-      objectName = this->GetObjectFileNameWithoutTarget(
+      longObjectName = this->GetObjectFileNameWithoutTarget(
         *sf, dir_max, &keptSourceExtension, custom_ext);
     }
-    si.second = objectName;
+    si.second.ShortLoc.emplace(shortObjectName);
+    si.second.LongLoc.Update(longObjectName);
   }
 }
 
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index fdc15be..8c472c5 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -10,6 +10,7 @@
 
 #include "cmGlobalVisualStudioGenerator.h"
 #include "cmLocalGenerator.h"
+#include "cmObjectLocation.h"
 #include "cmStateTypes.h"
 #include "cmVsProjectType.h"
 
@@ -49,7 +50,7 @@
     cmGeneratorTarget const*) const = 0;
 
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* = nullptr) override;
 
   std::string GetObjectOutputRoot(
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 5bf0966..5d6a32f 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -119,7 +119,7 @@
 }
 
 void cmLocalXCodeGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const*)
 {
   // Count the number of object files with each name. Warn about duplicate
@@ -129,15 +129,17 @@
   std::map<std::string, int> counts;
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName = cmStrCat(
+    std::string shortObjectName = this->GetShortObjectFileName(*sf);
+    std::string longObjectName = cmStrCat(
       cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), ".o");
 
-    std::string objectNameLower = cmSystemTools::LowerCase(objectName);
-    counts[objectNameLower] += 1;
-    if (2 == counts[objectNameLower]) {
+    std::string longObjectNameLower = cmSystemTools::LowerCase(longObjectName);
+    counts[longObjectNameLower] += 1;
+    if (2 == counts[longObjectNameLower]) {
       // TODO: emit warning about duplicate name?
     }
-    si.second = objectName;
+    si.second.ShortLoc.emplace(shortObjectName);
+    si.second.LongLoc.Update(longObjectName);
   }
 }
 
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index 49a5e93..7b501fb 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "cmLocalGenerator.h"
+#include "cmObjectLocation.h"
 
 class cmGeneratorTarget;
 class cmGlobalGenerator;
@@ -35,7 +36,7 @@
   void Generate() override;
   void AddGeneratorSpecificInstallSetup(std::ostream& os) override;
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr) override;
 
   void AddXCConfigSources(cmGeneratorTarget* target) override;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 5ceb35e..ec0fdb7 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4238,18 +4238,19 @@
   this->Makefile->FindPackageStack =
     this->Makefile->FindPackageStack.Push(cmFindPackageCall{
       name,
+      cmPackageInformation(),
       this->Makefile->FindPackageStackNextIndex,
     });
   this->Makefile->FindPackageStackNextIndex++;
 }
 
-void cmFindPackageStackRAII::BindTop(cmFindPackageCall*& value)
+void cmFindPackageStackRAII::BindTop(cmPackageInformation*& value)
 {
   if (this->Value) {
     *this->Value = nullptr;
   }
   this->Value = &value;
-  value = &this->Makefile->FindPackageStack.cmStack::Top();
+  value = &this->Makefile->FindPackageStack.cmStack::Top().PackageInfo;
 }
 
 cmFindPackageStackRAII::~cmFindPackageStackRAII()
diff --git a/Source/cmObjectLocation.cxx b/Source/cmObjectLocation.cxx
new file mode 100644
index 0000000..bb0c2ee
--- /dev/null
+++ b/Source/cmObjectLocation.cxx
@@ -0,0 +1,47 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file LICENSE.rst or https://cmake.org/licensing for details.  */
+
+#include "cmObjectLocation.h"
+
+void cmObjectLocation::Update(std::string path)
+{
+  this->Path = std::move(path);
+}
+
+std::string const& cmObjectLocation::GetPath() const
+{
+  return this->Path;
+}
+
+cm::string_view cmObjectLocation::GetDirectory() const
+{
+  auto const pos = this->Path.rfind('/');
+  if (pos == std::string::npos) {
+    return {};
+  }
+  return cm::string_view(this->Path.c_str(), pos);
+}
+
+cm::string_view cmObjectLocation::GetName() const
+{
+  auto const pos = this->Path.rfind('/');
+  if (pos == std::string::npos) {
+    return this->Path;
+  }
+  auto const nameStart = pos + 1;
+  return cm::string_view(this->Path.c_str() + nameStart,
+                         this->Path.size() - nameStart);
+}
+
+cmObjectLocation const& cmObjectLocations::GetLocation(UseShortPath use) const
+{
+  if (use == UseShortPath::Yes && this->ShortLoc) {
+    return *this->ShortLoc;
+  }
+  return this->LongLoc;
+}
+
+std::string const& cmObjectLocations::GetPath(UseShortPath use) const
+{
+  return this->GetLocation(use).GetPath();
+}
diff --git a/Source/cmObjectLocation.h b/Source/cmObjectLocation.h
new file mode 100644
index 0000000..2cf2564
--- /dev/null
+++ b/Source/cmObjectLocation.h
@@ -0,0 +1,50 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file LICENSE.rst or https://cmake.org/licensing for details.  */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <utility>
+
+#include <cm/optional>
+#include <cm/string_view>
+
+struct cmObjectLocation
+{
+public:
+  cmObjectLocation() = default;
+  cmObjectLocation(std::string path)
+    : Path(std::move(path))
+  {
+  }
+
+  void Update(std::string path);
+
+  // Get the path to the object under the common directory for the target's
+  // objects.
+  std::string const& GetPath() const;
+  // Get the directory of the object file under the common directory.
+  cm::string_view GetDirectory() const;
+  // Get the name of the object file.
+  cm::string_view GetName() const;
+
+private:
+  std::string Path;
+};
+
+struct cmObjectLocations
+{
+  cmObjectLocations() = default;
+
+  cm::optional<cmObjectLocation> ShortLoc;
+  cmObjectLocation LongLoc;
+
+  enum class UseShortPath
+  {
+    Yes,
+    No,
+  };
+  cmObjectLocation const& GetLocation(UseShortPath use) const;
+  std::string const& GetPath(UseShortPath use) const;
+};
diff --git a/Source/cmPkgConfigResolver.cxx b/Source/cmPkgConfigResolver.cxx
index bd8b9b7..8be5f34 100644
--- a/Source/cmPkgConfigResolver.cxx
+++ b/Source/cmPkgConfigResolver.cxx
@@ -56,6 +56,15 @@
   return { &*begin, static_cast<std::size_t>(cur - begin) + 1 };
 }
 
+cm::string_view TrimFlag(cm::string_view flag)
+{
+  std::size_t trim_size = 2;
+  for (auto c = flag.rbegin(); c != flag.rend() && std::isspace(*c); ++c) {
+    ++trim_size;
+  }
+  return { flag.data() + 2, flag.size() - trim_size };
+}
+
 } // namespace
 
 std::string cmPkgConfigVersionReq::string() const
@@ -460,12 +469,10 @@
 
   for (auto flag : flags) {
     if (flag.rfind("-I", 0) == 0) {
-      cm::string_view noprefix{ flag.data() + 2, flag.size() - 2 };
-
-      if (std::all_of(syspaths.begin(), syspaths.end(),
-                      [&](std::string const& path) {
-                        return noprefix.rfind(path, 0) == noprefix.npos;
-                      })) {
+      cm::string_view trimmed = TrimFlag(flag);
+      if (std::all_of(
+            syspaths.begin(), syspaths.end(),
+            [&](std::string const& path) { return path != trimmed; })) {
         result.Includes.emplace_back(AppendAndTrim(result.Flagline, flag));
       }
 
@@ -486,12 +493,10 @@
   for (auto flag : flags) {
     if (flag.rfind("-I", 0) == 0) {
       std::string reroot = Reroot(flag, "-I", sysroot);
-      cm::string_view noprefix{ reroot.data() + 2, reroot.size() - 2 };
-
-      if (std::all_of(syspaths.begin(), syspaths.end(),
-                      [&](std::string const& path) {
-                        return noprefix.rfind(path, 0) == noprefix.npos;
-                      })) {
+      cm::string_view trimmed = TrimFlag(reroot);
+      if (std::all_of(
+            syspaths.begin(), syspaths.end(),
+            [&](std::string const& path) { return path != trimmed; })) {
         result.Includes.emplace_back(AppendAndTrim(result.Flagline, reroot));
       }
 
@@ -548,12 +553,10 @@
 
   for (auto flag : flags) {
     if (flag.rfind("-L", 0) == 0) {
-      cm::string_view noprefix{ flag.data() + 2, flag.size() - 2 };
-
-      if (std::all_of(syspaths.begin(), syspaths.end(),
-                      [&](std::string const& path) {
-                        return noprefix.rfind(path, 0) == noprefix.npos;
-                      })) {
+      cm::string_view trimmed = TrimFlag(flag);
+      if (std::all_of(
+            syspaths.begin(), syspaths.end(),
+            [&](std::string const& path) { return path != trimmed; })) {
         result.LibDirs.emplace_back(AppendAndTrim(result.Flagline, flag));
       }
 
@@ -576,12 +579,10 @@
   for (auto flag : flags) {
     if (flag.rfind("-L", 0) == 0) {
       std::string reroot = Reroot(flag, "-L", sysroot);
-      cm::string_view noprefix{ reroot.data() + 2, reroot.size() - 2 };
-
-      if (std::all_of(syspaths.begin(), syspaths.end(),
-                      [&](std::string const& path) {
-                        return noprefix.rfind(path, 0) == noprefix.npos;
-                      })) {
+      cm::string_view trimmed = TrimFlag(reroot);
+      if (std::all_of(
+            syspaths.begin(), syspaths.end(),
+            [&](std::string const& path) { return path != trimmed; })) {
         result.LibDirs.emplace_back(AppendAndTrim(result.Flagline, reroot));
       }
 
diff --git a/Source/cmStdIoTerminal.cxx b/Source/cmStdIoTerminal.cxx
index 5baff5e..428f7c7 100644
--- a/Source/cmStdIoTerminal.cxx
+++ b/Source/cmStdIoTerminal.cxx
@@ -141,9 +141,13 @@
       f(os.IOS());
       break;
     case TermKind::VT100:
-      SetVT100Attrs(os.IOS(), attrs);
-      f(os.IOS());
-      SetVT100Attrs(os.IOS(), TermAttr::Normal);
+      if (!attrs.empty()) {
+        SetVT100Attrs(os.IOS(), attrs);
+        f(os.IOS());
+        SetVT100Attrs(os.IOS(), TermAttr::Normal);
+      } else {
+        f(os.IOS());
+      }
       break;
 #ifdef _WIN32
     case TermKind::Console: {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index cbf8b90..4d35e5f 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -419,6 +419,7 @@
   { "BUILD_WITH_INSTALL_NAME_DIR"_s, IC::CanCompileSources },
   // ---- Install
   { "INSTALL_NAME_DIR"_s, IC::CanCompileSources },
+  { "INSTALL_OBJECT_NAME_STRATEGY"_s, IC::CanCompileSources },
   { "INSTALL_REMOVE_ENVIRONMENT_RPATH"_s, IC::CanCompileSources },
   { "INSTALL_RPATH"_s, ""_s, IC::CanCompileSources },
   { "INSTALL_RPATH_USE_LINK_PATH"_s, "OFF"_s, IC::CanCompileSources },
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 9e38384..805bdab 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1923,7 +1923,7 @@
 
   bool enabled = true;
   static cm::StdIo::TermAttrSet const noAttrs;
-  cm::StdIo::TermAttrSet attrs = cm::StdIo::TermAttr::Normal;
+  cm::StdIo::TermAttrSet attrs;
   bool newline = true;
   std::string progressDir;
   for (auto const& arg : cmMakeRange(args).advance(2)) {
@@ -1959,6 +1959,9 @@
     } else if (arg == "--white") {
       attrs = cm::StdIo::TermAttr::ForegroundWhite;
     } else if (arg == "--bold") {
+      if (attrs.empty()) {
+        attrs = cm::StdIo::TermAttr::Normal;
+      }
       attrs |= cm::StdIo::TermAttr::ForegroundBold;
     } else if (arg == "--no-newline") {
       newline = false;
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 2d40fd0..fed2c80 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -36,6 +36,8 @@
 set(TEST_HOME "${CMake_BINARY_DIR}/Tests/CMakeFiles/TestHome")
 set(TEST_CONFIG_ENV_CODE "# Isolate tests from user-wide configuration.
 set(ENV{CMAKE_CONFIG_DIR} \"${TEST_HOME}/.config/cmake\")\n")
+set(TEST_INSTRUMENTATION_ENV_CODE "# Isolate tests from CTEST_USE_INSTRUMENTATION var
+unset(ENV{CTEST_USE_INSTRUMENTATION})\n")
 file(MAKE_DIRECTORY "${TEST_HOME}/.config/cmake")
 
 # Fake a user home directory to avoid polluting the real one.
@@ -593,11 +595,11 @@
   if(NOT DEFINED CMake_TEST_Qt4)
     set(CMake_TEST_Qt4 1)
   endif()
-  if(CMake_TEST_Qt4 AND NOT QT4_FOUND)
+  if(CMake_TEST_Qt4 AND NOT Qt4_FOUND)
     find_package(Qt4 QUIET)
   endif()
 
-  if(CMake_TEST_Qt4 AND QT4_FOUND)
+  if(CMake_TEST_Qt4 AND Qt4_FOUND)
     # test whether the Qt4 which has been found works, on some machines
     # which run nightly builds there were errors like "wrong file format"
     # for libQtCore.so. So first check it works, and only if it does add
diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
index 566282e..c2b510e 100644
--- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
+++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
@@ -44,7 +44,7 @@
 endforeach()
 
 # Qt4 is not present, so we can check Qt3
-if (NOT QT4_FOUND)
+if (NOT Qt4_FOUND)
     set(DESIRED_QT_VERSION 3)
     foreach(FIND_MODULE ${NO_QT4_MODULES} "Qt")
         do_find(${FIND_MODULE})
@@ -97,7 +97,7 @@
     CUPS CURL
     EXPAT
     FREETYPE
-    GETTEXT GIT
+    GETTEXT GIT GNUTLS
     HG HSPELL
     ICOTOOL
     JASPER
@@ -115,15 +115,15 @@
     ALSA Armadillo
     BISON Boost BZip2 BZIP2
     CUDA Cups
-    Doxygen DOXYGEN
+    DevIL Doxygen DOXYGEN
     EXPAT
     FLEX Freetype
-    Gettext GIF GTK2
+    Gettext GIF GnuTLS GNUTLS GTK2
     HDF5
     Jasper JPEG
     LibArchive LibLZMA LIBLZMA LibXml2 LibXslt LTTngUST
     OpenSceneGraph OPENSCENEGRAPH OpenSSL OPENSSL
-    PNG PostgreSQL Protobuf
+    Perl PerlLibs PNG PostgreSQL Protobuf
     Ruby RUBY
     SDL SWIG
     TIFF
@@ -133,4 +133,5 @@
 endforeach()
 
 check_version_string(PYTHONINTERP PYTHON_VERSION_STRING)
+check_version_string(SUBVERSION Subversion_VERSION)
 check_version_string(SUBVERSION Subversion_VERSION_SVN)
diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in
index 78dea00..6d634d6 100644
--- a/Tests/EnforceConfig.cmake.in
+++ b/Tests/EnforceConfig.cmake.in
@@ -45,3 +45,4 @@
 @TEST_CONFIG_ENV_CODE@
 @TEST_HOME_ENV_CODE@
 @TEST_WARN_VS_CODE@
+@TEST_INSTRUMENTATION_ENV_CODE@
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index 1208152..c6f0fa3 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -17,7 +17,7 @@
 
 if(NOT DEFINED EP_TEST_SVN OR EP_TEST_SVN)
   find_package(Subversion)
-  if(Subversion_FOUND AND Subversion_VERSION_SVN VERSION_LESS 1.2)
+  if(Subversion_FOUND AND Subversion_VERSION VERSION_LESS 1.2)
     message(STATUS "No ExternalProject svn tests with svn client less than version 1.2")
     set(Subversion_FOUND 0)
   endif()
diff --git a/Tests/FindDevIL/Test/CMakeLists.txt b/Tests/FindDevIL/Test/CMakeLists.txt
index 2b72cf8..f82b7fe 100644
--- a/Tests/FindDevIL/Test/CMakeLists.txt
+++ b/Tests/FindDevIL/Test/CMakeLists.txt
@@ -4,19 +4,21 @@
 
 find_package(DevIL)
 
-#FIXME: check version too.
-# add_definitions(
-#  -DCMAKE_EXPECTED_SDL_VERSION_MAJOR=${SDL_VERSION_MAJOR}
-#  -DCMAKE_EXPECTED_SDL_VERSION_MINOR=${SDL_VERSION_MINOR}
-#  -DCMAKE_EXPECTED_SDL_VERSION_PATCH=${SDL_VERSION_PATCH})
-
 add_executable(test_devil_var main.c)
 target_include_directories(test_devil_var PRIVATE ${IL_INCLUDE_DIRS})
 target_link_libraries(test_devil_var PRIVATE ${IL_LIBRARIES})
+target_compile_definitions(
+  test_devil_var
+  PRIVATE CMAKE_EXPECTED_DEVIL_VERSION="${DevIL_VERSION}"
+)
 add_test(NAME test_devil_var COMMAND test_devil_var)
 
 add_executable(test_devil_il_tgt main.c)
 target_link_libraries(test_devil_il_tgt DevIL::IL)
+target_compile_definitions(
+  test_devil_il_tgt
+  PRIVATE CMAKE_EXPECTED_DEVIL_VERSION="${DevIL_VERSION}"
+)
 add_test(NAME test_devil_il_tgt COMMAND test_devil_il_tgt)
 
 add_executable(test_devil_ilu_tgt main_ilu.c)
diff --git a/Tests/FindDevIL/Test/main.c b/Tests/FindDevIL/Test/main.c
index dfb2f63..f7b2c8b 100644
--- a/Tests/FindDevIL/Test/main.c
+++ b/Tests/FindDevIL/Test/main.c
@@ -1,4 +1,6 @@
 #include <IL/il.h>
+#include <stdio.h>
+#include <string.h>
 
 int main(void)
 {
@@ -6,5 +8,16 @@
   ilInit();
 
   ilShutDown();
-  return 0;
+
+  int version = IL_VERSION;
+  int major = version / 100;
+  int minor = version / 10 % 10;
+  int patch = version % 10;
+  char version_string[100];
+  snprintf(version_string, sizeof(version_string), "%d.%d.%d", major, minor,
+           patch);
+
+  printf("Found DevIL version %s, expected version %s\n", version_string,
+         CMAKE_EXPECTED_DEVIL_VERSION);
+  return strcmp(version_string, CMAKE_EXPECTED_DEVIL_VERSION);
 }
diff --git a/Tests/FindGnuTLS/Test/CMakeLists.txt b/Tests/FindGnuTLS/Test/CMakeLists.txt
index 2a01298..b0e19e3 100644
--- a/Tests/FindGnuTLS/Test/CMakeLists.txt
+++ b/Tests/FindGnuTLS/Test/CMakeLists.txt
@@ -4,7 +4,7 @@
 
 find_package(GnuTLS REQUIRED)
 
-add_definitions(-DCMAKE_EXPECTED_GNUTLS_VERSION="${GNUTLS_VERSION}")
+add_definitions(-DCMAKE_EXPECTED_GNUTLS_VERSION="${GnuTLS_VERSION}")
 
 add_executable(test_tgt main.c)
 target_link_libraries(test_tgt GnuTLS::GnuTLS)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 7aeb192..4342434 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -618,7 +618,7 @@
 if(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
   add_RunCMake_test(VisibilityPreset)
 endif()
-if (QT4_FOUND)
+if (Qt4_FOUND)
   set(CompatibleInterface_ARGS -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE})
 endif()
 add_RunCMake_test(CompatibleInterface)
@@ -728,6 +728,7 @@
 if(DEFINED CMake_TEST_NO_WRITE_ONLY_DIR)
   list(APPEND if_ARGS -DCMake_TEST_NO_WRITE_ONLY_DIR=${CMake_TEST_NO_WRITE_ONLY_DIR})
 endif()
+add_RunCMake_test(INSTALL_OBJECT_NAME_STRATEGY)
 add_RunCMake_test(if -DMSYS=${MSYS})
 add_RunCMake_test(include)
 add_RunCMake_test(include_directories)
@@ -871,10 +872,10 @@
 if(CMake_TEST_Qt5)
   find_package(Qt5Core QUIET)
 endif()
-if (CMake_TEST_Qt4 AND CMake_TEST_Qt5 AND QT4_FOUND AND Qt5Core_FOUND AND NOT Qt5Core_VERSION VERSION_LESS 5.1.0)
+if (CMake_TEST_Qt4 AND CMake_TEST_Qt5 AND Qt4_FOUND AND Qt5Core_FOUND AND NOT Qt5Core_VERSION VERSION_LESS 5.1.0)
   add_RunCMake_test(IncompatibleQt)
 endif()
-if (CMake_TEST_Qt4 AND QT4_FOUND)
+if (CMake_TEST_Qt4 AND Qt4_FOUND)
   add_RunCMake_test(ObsoleteQtMacros -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE})
 endif()
 
diff --git a/Tests/RunCMake/ExportPackageInfo/DependencyVersionCMake-check.cmake b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCMake-check.cmake
new file mode 100644
index 0000000..e4822b7
--- /dev/null
+++ b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCMake-check.cmake
@@ -0,0 +1,15 @@
+include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
+
+set(out_dir "${RunCMake_BINARY_DIR}/DependencyVersionCMake-build")
+
+file(READ "${out_dir}/foo.cps" content)
+expect_value("${content}" "foo" "name")
+expect_array("${content}" 1 "requires" "bar" "components")
+expect_value("${content}" "bar" "requires" "bar" "components" 0)
+expect_value("${content}" "1.3.5" "requires" "bar" "version")
+expect_array("${content}" 1 "requires" "bar" "hints")
+expect_value("${content}" "${CMAKE_CURRENT_LIST_DIR}/config" "requires" "bar" "hints" 0)
+
+string(JSON component GET "${content}" "components" "foo")
+expect_array("${component}" 1 "requires")
+expect_value("${component}" "bar:bar" "requires" 0)
diff --git a/Tests/RunCMake/ExportPackageInfo/DependencyVersionCMake.cmake b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCMake.cmake
new file mode 100644
index 0000000..e82a16e
--- /dev/null
+++ b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCMake.cmake
@@ -0,0 +1,11 @@
+find_package(
+    bar 1.3.4 REQUIRED CONFIG
+    NO_DEFAULT_PATH
+    PATHS ${CMAKE_CURRENT_LIST_DIR}/config
+)
+
+add_library(foo INTERFACE)
+target_link_libraries(foo INTERFACE bar::bar)
+
+install(TARGETS foo EXPORT foo DESTINATION .)
+export(EXPORT foo PACKAGE_INFO foo)
diff --git a/Tests/RunCMake/ExportPackageInfo/DependencyVersionCps-check.cmake b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCps-check.cmake
new file mode 100644
index 0000000..0b84ec1
--- /dev/null
+++ b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCps-check.cmake
@@ -0,0 +1,15 @@
+include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
+
+set(out_dir "${RunCMake_BINARY_DIR}/DependencyVersionCps-build/")
+
+file(READ "${out_dir}/foo.cps" content)
+expect_value("${content}" "foo" "name")
+expect_array("${content}" 1 "requires" "baz" "components")
+expect_value("${content}" "baz" "requires" "baz" "components" 0)
+expect_value("${content}" "1.3.5" "requires" "baz" "version")
+expect_array("${content}" 1 "requires" "baz" "hints")
+expect_value("${content}" "${CMAKE_CURRENT_LIST_DIR}/cps" "requires" "baz" "hints" 0)
+
+string(JSON component GET "${content}" "components" "foo")
+expect_array("${component}" 1 "requires")
+expect_value("${component}" "baz:baz" "requires" 0)
diff --git a/Tests/RunCMake/ExportPackageInfo/DependencyVersionCps.cmake b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCps.cmake
new file mode 100644
index 0000000..97cf54f
--- /dev/null
+++ b/Tests/RunCMake/ExportPackageInfo/DependencyVersionCps.cmake
@@ -0,0 +1,11 @@
+find_package(
+    baz 1.3.4 REQUIRED
+    NO_DEFAULT_PATH
+    PATHS ${CMAKE_CURRENT_LIST_DIR}
+)
+
+add_library(foo INTERFACE)
+target_link_libraries(foo INTERFACE baz::baz)
+
+install(TARGETS foo EXPORT foo DESTINATION .)
+export(EXPORT foo PACKAGE_INFO foo)
diff --git a/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake b/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake
index c505f28..45c4397 100644
--- a/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake
@@ -8,6 +8,7 @@
 set(RunCMake_TEST_OPTIONS
   -Wno-dev
   "-DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO:STRING=b80be207-778e-46ba-8080-b23bba22639e"
+  "-DCMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES:STRING=e82e467b-f997-4464-8ace-b00808fff261"
   )
 
 # Test incorrect usage
@@ -43,3 +44,5 @@
 run_cmake(Config)
 run_cmake(EmptyConfig)
 run_cmake(FileSetHeaders)
+run_cmake(DependencyVersionCMake)
+run_cmake(DependencyVersionCps)
diff --git a/Tests/RunCMake/ExportPackageInfo/config/bar-config-version.cmake b/Tests/RunCMake/ExportPackageInfo/config/bar-config-version.cmake
new file mode 100644
index 0000000..ff683d6
--- /dev/null
+++ b/Tests/RunCMake/ExportPackageInfo/config/bar-config-version.cmake
@@ -0,0 +1,29 @@
+set(PACKAGE_VERSION "1.3.5")
+
+if (PACKAGE_FIND_VERSION_RANGE)
+  # Check for a version range
+  if (PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_RANGE_MIN)
+    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+  else ()
+    if (PACKAGE_FIND_VERSION_RANGE_MAX)
+      if (PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_RANGE_MAX)
+        set(PACKAGE_VERSION_COMPATIBLE FALSE)
+      else ()
+        set(PACKAGE_VERSION_COMPATIBLE TRUE)
+      endif ()
+    else ()
+      set(PACKAGE_VERSION_COMPATIBLE TRUE)
+    endif ()
+  endif ()
+
+elseif (PACKAGE_FIND_VERSION)
+  # Check for a specific version or minimum version
+  if (PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
+    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+  else ()
+    set(PACKAGE_VERSION_COMPATIBLE TRUE)
+    if (PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION)
+      set(PACKAGE_VERSION_EXACT TRUE)
+    endif ()
+  endif ()
+endif ()
diff --git a/Tests/RunCMake/ExportPackageInfo/config/bar-config.cmake b/Tests/RunCMake/ExportPackageInfo/config/bar-config.cmake
new file mode 100644
index 0000000..d17ed84
--- /dev/null
+++ b/Tests/RunCMake/ExportPackageInfo/config/bar-config.cmake
@@ -0,0 +1 @@
+add_library(bar::bar INTERFACE IMPORTED)
diff --git a/Tests/RunCMake/ExportPackageInfo/cps/baz.cps b/Tests/RunCMake/ExportPackageInfo/cps/baz.cps
new file mode 100644
index 0000000..6cf1042
--- /dev/null
+++ b/Tests/RunCMake/ExportPackageInfo/cps/baz.cps
@@ -0,0 +1,14 @@
+{
+  "components" :
+  {
+    "baz" :
+    {
+      "type" : "interface"
+    }
+  },
+  "cps_path" : "@prefix@/cps",
+  "cps_version" : "0.13.0",
+  "compat_version": "1.0.0",
+  "name" : "baz",
+  "version": "1.3.5"
+}
diff --git a/Tests/RunCMake/FindLua/FindLuaTest.cmake b/Tests/RunCMake/FindLua/FindLuaTest.cmake
index 610d544..be5e3ab 100644
--- a/Tests/RunCMake/FindLua/FindLuaTest.cmake
+++ b/Tests/RunCMake/FindLua/FindLuaTest.cmake
@@ -21,8 +21,11 @@
     if(NOT "${LUA_INCLUDE_DIR}" STREQUAL "${path}")
         message(FATAL_ERROR "LUA_INCLUDE_PATH != path: '${LUA_INCLUDE_DIR}' != '${path}'")
     endif()
-    if(NOT LUA_VERSION_STRING MATCHES "^${version}\.[0-9]$")
-        message(FATAL_ERROR "Wrong versionfound in '${LUA_INCLUDE_DIR}': ${LUA_VERSION_STRING} != ${version}")
+    if(NOT Lua_VERSION MATCHES "^${version}\.[0-9]$")
+        message(FATAL_ERROR "Wrong version found in '${LUA_INCLUDE_DIR}': ${Lua_VERSION} != ${version}")
+    endif()
+    if(NOT LUA_VERSION_STRING STREQUAL Lua_VERSION)
+        message(FATAL_ERROR "LUA_VERSION_STRING != Lua_VERSION in '${LUA_INCLUDE_DIR}': ${LUA_VERSION_STRING} != ${Lua_VERSION}")
     endif()
 endfunction()
 
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/CMakeLists.txt b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/CMakeLists.txt
new file mode 100644
index 0000000..c89e908
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.16)
+project(${RunCMake_TEST} C)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake
new file mode 100644
index 0000000..0a538ba
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake
@@ -0,0 +1,3 @@
+add_library(objlib OBJECT test.c subdir/inner_test.c)
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/IONS FILE ions-config.cmake NAMESPACE IONS::)
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake
new file mode 100644
index 0000000..57f13bb
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake
new file mode 100644
index 0000000..57f13bb
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake
new file mode 100644
index 0000000..57f13bb
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume.cmake
new file mode 100644
index 0000000..82192e0
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume.cmake
@@ -0,0 +1,7 @@
+find_package(IONS CONFIG REQUIRED)
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE IONS::objlib)
+
+enable_testing()
+add_test(NAME run COMMAND main)
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default-install-check.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default-install-check.cmake
new file mode 100644
index 0000000..418557e
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default-install-check.cmake
@@ -0,0 +1,2 @@
+# The default behavior is `FULL`.
+include("${CMAKE_CURRENT_LIST_DIR}/FULL-install-check.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake
new file mode 100644
index 0000000..f635ae2
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake
new file mode 100644
index 0000000..4fcc007
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake
@@ -0,0 +1,8 @@
+set(ext_suffix ".c")
+set(subdir "subdir/")
+if (RunCMake_GENERATOR MATCHES "(Visual Studio|Xcode)")
+  set(ext_suffix "")
+  set(subdir "")
+endif ()
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/test${ext_suffix}${CMAKE_C_OUTPUT_EXTENSION}")
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/${subdir}inner_test${ext_suffix}${CMAKE_C_OUTPUT_EXTENSION}")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake
new file mode 100644
index 0000000..d074526
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake
@@ -0,0 +1,3 @@
+set(CMAKE_INSTALL_OBJECT_NAME_STRATEGY FULL)
+
+include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt
new file mode 100644
index 0000000..0ad494d
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error in CMakeLists.txt:
+  Property INSTALL_OBJECT_NAME_STRATEGY of target "objlib" set to the
+  unsupported strategy INVALID
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake
new file mode 100644
index 0000000..d7ae724
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake
@@ -0,0 +1,3 @@
+set(CMAKE_INSTALL_OBJECT_NAME_STRATEGY INVALID)
+
+include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Inspect.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Inspect.cmake
new file mode 100644
index 0000000..ec74ed8
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Inspect.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+set(info "")
+
+# Forward information about the C++ compile features.
+string(APPEND info "\
+set(CMAKE_C_OUTPUT_EXTENSION \"${CMAKE_C_OUTPUT_EXTENSION}\")
+")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake
new file mode 100644
index 0000000..67e030b
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake
@@ -0,0 +1,45 @@
+cmake_minimum_required(VERSION 3.16)
+
+include(RunCMake)
+
+# This test does installation of `OBJECT` libraries which does not work with
+# multi-arch compilation under Xcode.
+if (RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
+  return ()
+endif ()
+
+function(run_install_test case)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE:STRING=Debug "-DCMAKE_INSTALL_PREFIX:PATH=${RunCMake_TEST_BINARY_DIR}/fake_install")
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  run_cmake(${case})
+  run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug)
+  set(prefix "${RunCMake_TEST_BINARY_DIR}/real_install")
+  run_cmake_command(${case}-install ${CMAKE_COMMAND} --install . --config Debug --prefix "${prefix}")
+
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Consume-${case}-build)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE:STRING=Debug "-DCMAKE_PREFIX_PATH:PATH=${prefix}")
+  run_cmake(Consume-${case} "-DCMAKE_PREFIX_PATH=${prefix}")
+  run_cmake_command(Consume-${case}-build ${CMAKE_COMMAND} --build . --config Debug)
+  run_cmake_command(Consume-${case}-test ${CMAKE_CTEST_COMMAND} -C Debug)
+endfunction()
+
+function (check_installed_object path)
+  if (NOT EXISTS "${path}")
+    list(APPEND RunCMake_TEST_FAILED
+      "Could not find installed object at '${path}'")
+  endif ()
+  set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction ()
+
+run_cmake(Inspect)
+include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
+
+run_install_test(Default)
+run_install_test(FULL)
+if (RunCMake_GENERATOR MATCHES "(Ninja|Makefiles|Visual Studio)")
+  run_install_test(SHORT)
+endif ()
+run_cmake(INVALID)
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake
new file mode 100644
index 0000000..15b77d2
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake
@@ -0,0 +1,2 @@
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/f3796fea${CMAKE_C_OUTPUT_EXTENSION}")
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/82237782${CMAKE_C_OUTPUT_EXTENSION}")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake
new file mode 100644
index 0000000..b21fb48
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake
@@ -0,0 +1,3 @@
+set(CMAKE_INSTALL_OBJECT_NAME_STRATEGY SHORT)
+
+include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake")
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c
new file mode 100644
index 0000000..7955cce
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c
@@ -0,0 +1,7 @@
+int test(int a);
+int inner(int a);
+
+int main(void)
+{
+  return test(0) + inner(0);
+}
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c
new file mode 100644
index 0000000..32c726d
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c
@@ -0,0 +1,4 @@
+int inner(int a)
+{
+  return a;
+}
diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c
new file mode 100644
index 0000000..6fa39df
--- /dev/null
+++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c
@@ -0,0 +1,4 @@
+int test(int a)
+{
+  return a;
+}
diff --git a/Tests/RunCMake/InstallPackageInfo/DependencyVersionCMake-check.cmake b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCMake-check.cmake
new file mode 100644
index 0000000..3bca2c9
--- /dev/null
+++ b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCMake-check.cmake
@@ -0,0 +1,15 @@
+include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
+
+set(out_dir "${RunCMake_BINARY_DIR}/DependencyVersionCMake-build/CMakeFiles/Export/5058f1af8388633f609cadb75a75dc9d")
+
+file(READ "${out_dir}/foo.cps" content)
+expect_value("${content}" "foo" "name")
+expect_array("${content}" 1 "requires" "bar" "components")
+expect_value("${content}" "bar" "requires" "bar" "components" 0)
+expect_value("${content}" "1.3.5" "requires" "bar" "version")
+expect_array("${content}" 1 "requires" "bar" "hints")
+expect_value("${content}" "${CMAKE_CURRENT_LIST_DIR}/config" "requires" "bar" "hints" 0)
+
+string(JSON component GET "${content}" "components" "foo")
+expect_array("${component}" 1 "requires")
+expect_value("${component}" "bar:bar" "requires" 0)
diff --git a/Tests/RunCMake/InstallPackageInfo/DependencyVersionCMake.cmake b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCMake.cmake
new file mode 100644
index 0000000..28f129f
--- /dev/null
+++ b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCMake.cmake
@@ -0,0 +1,11 @@
+find_package(
+    bar 1.3.4 REQUIRED CONFIG
+    NO_DEFAULT_PATH
+    PATHS ${CMAKE_CURRENT_LIST_DIR}/config
+)
+
+add_library(foo INTERFACE)
+target_link_libraries(foo INTERFACE bar::bar)
+
+install(TARGETS foo EXPORT foo)
+install(PACKAGE_INFO foo EXPORT foo DESTINATION .)
diff --git a/Tests/RunCMake/InstallPackageInfo/DependencyVersionCps-check.cmake b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCps-check.cmake
new file mode 100644
index 0000000..95c01cd
--- /dev/null
+++ b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCps-check.cmake
@@ -0,0 +1,15 @@
+include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
+
+set(out_dir "${RunCMake_BINARY_DIR}/DependencyVersionCps-build/CMakeFiles/Export/5058f1af8388633f609cadb75a75dc9d")
+
+file(READ "${out_dir}/foo.cps" content)
+expect_value("${content}" "foo" "name")
+expect_array("${content}" 1 "requires" "baz" "components")
+expect_value("${content}" "baz" "requires" "baz" "components" 0)
+expect_value("${content}" "1.3.5" "requires" "baz" "version")
+expect_array("${content}" 1 "requires" "baz" "hints")
+expect_value("${content}" "${CMAKE_CURRENT_LIST_DIR}/cps" "requires" "baz" "hints" 0)
+
+string(JSON component GET "${content}" "components" "foo")
+expect_array("${component}" 1 "requires")
+expect_value("${component}" "baz:baz" "requires" 0)
diff --git a/Tests/RunCMake/InstallPackageInfo/DependencyVersionCps.cmake b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCps.cmake
new file mode 100644
index 0000000..1453d52
--- /dev/null
+++ b/Tests/RunCMake/InstallPackageInfo/DependencyVersionCps.cmake
@@ -0,0 +1,11 @@
+find_package(
+    baz 1.3.4 REQUIRED
+    NO_DEFAULT_PATH
+    PATHS ${CMAKE_CURRENT_LIST_DIR}
+)
+
+add_library(foo INTERFACE)
+target_link_libraries(foo INTERFACE baz::baz)
+
+install(TARGETS foo EXPORT foo)
+install(PACKAGE_INFO foo EXPORT foo DESTINATION .)
diff --git a/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake b/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake
index 67e43ec..82c0d90 100644
--- a/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake
+++ b/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake
@@ -8,6 +8,7 @@
 set(RunCMake_TEST_OPTIONS
   -Wno-dev
   "-DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO:STRING=b80be207-778e-46ba-8080-b23bba22639e"
+  "-DCMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES:STRING=e82e467b-f997-4464-8ace-b00808fff261"
   )
 
 function(run_cmake_install test)
@@ -51,4 +52,6 @@
 run_cmake(Config)
 run_cmake(EmptyConfig)
 run_cmake(FileSetHeaders)
+run_cmake(DependencyVersionCMake)
+run_cmake(DependencyVersionCps)
 run_cmake_install(Destination)
diff --git a/Tests/RunCMake/InstallPackageInfo/config/bar-config-version.cmake b/Tests/RunCMake/InstallPackageInfo/config/bar-config-version.cmake
new file mode 100644
index 0000000..ff683d6
--- /dev/null
+++ b/Tests/RunCMake/InstallPackageInfo/config/bar-config-version.cmake
@@ -0,0 +1,29 @@
+set(PACKAGE_VERSION "1.3.5")
+
+if (PACKAGE_FIND_VERSION_RANGE)
+  # Check for a version range
+  if (PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_RANGE_MIN)
+    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+  else ()
+    if (PACKAGE_FIND_VERSION_RANGE_MAX)
+      if (PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_RANGE_MAX)
+        set(PACKAGE_VERSION_COMPATIBLE FALSE)
+      else ()
+        set(PACKAGE_VERSION_COMPATIBLE TRUE)
+      endif ()
+    else ()
+      set(PACKAGE_VERSION_COMPATIBLE TRUE)
+    endif ()
+  endif ()
+
+elseif (PACKAGE_FIND_VERSION)
+  # Check for a specific version or minimum version
+  if (PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
+    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+  else ()
+    set(PACKAGE_VERSION_COMPATIBLE TRUE)
+    if (PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION)
+      set(PACKAGE_VERSION_EXACT TRUE)
+    endif ()
+  endif ()
+endif ()
diff --git a/Tests/RunCMake/InstallPackageInfo/config/bar-config.cmake b/Tests/RunCMake/InstallPackageInfo/config/bar-config.cmake
new file mode 100644
index 0000000..d17ed84
--- /dev/null
+++ b/Tests/RunCMake/InstallPackageInfo/config/bar-config.cmake
@@ -0,0 +1 @@
+add_library(bar::bar INTERFACE IMPORTED)
diff --git a/Tests/RunCMake/InstallPackageInfo/cps/baz.cps b/Tests/RunCMake/InstallPackageInfo/cps/baz.cps
new file mode 100644
index 0000000..6cf1042
--- /dev/null
+++ b/Tests/RunCMake/InstallPackageInfo/cps/baz.cps
@@ -0,0 +1,14 @@
+{
+  "components" :
+  {
+    "baz" :
+    {
+      "type" : "interface"
+    }
+  },
+  "cps_path" : "@prefix@/cps",
+  "cps_version" : "0.13.0",
+  "compat_version": "1.0.0",
+  "name" : "baz",
+  "version": "1.3.5"
+}
diff --git a/Tests/RunCMake/cmake_pkg_config/ExtractEnv-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractEnv-stderr.txt
index 67713c9..e1c98f3 100644
--- a/Tests/RunCMake/cmake_pkg_config/ExtractEnv-stderr.txt
+++ b/Tests/RunCMake/cmake_pkg_config/ExtractEnv-stderr.txt
@@ -1,5 +1,5 @@
-Includes: -I/Alpha;-I/Gamma
-LibDirs: -L/Delta;-L/Zeta
+Includes: -I/Alpha;-I/Alpha/sub;-I/Gamma
+LibDirs: -L/Delta;-L/Delta/sub;-L/Zeta
 Cflags: QuxInstalled
 PC_LIB_DIRS: Alpha;Beta
 PC_PATH: [^
diff --git a/Tests/RunCMake/cmake_pkg_config/ExtractMangle-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractMangle-stderr.txt
index 75557fc..04a1bc0 100644
--- a/Tests/RunCMake/cmake_pkg_config/ExtractMangle-stderr.txt
+++ b/Tests/RunCMake/cmake_pkg_config/ExtractMangle-stderr.txt
@@ -1,8 +1,8 @@
-Cflags: Beta -I/Gamma
-Includes: -I/Gamma
-Libs: Epsilon -L/Zeta
-LibDirs: -L/Zeta
-Cflags: -I/Alpha Beta -I/Gamma
-Includes: -I/Alpha;-I/Gamma
-Libs: -L/Delta Epsilon -L/Zeta
-LibDirs: -L/Delta;-L/Zeta
+Cflags: -I/Alpha/sub Beta -I/Gamma
+Includes: -I/Alpha/sub;-I/Gamma
+Libs: -L/Delta/sub Epsilon -L/Zeta
+LibDirs: -L/Delta/sub;-L/Zeta
+Cflags: -I/Alpha -I/Alpha/sub Beta -I/Gamma
+Includes: -I/Alpha;-I/Alpha/sub;-I/Gamma
+Libs: -L/Delta -L/Delta/sub Epsilon -L/Zeta
+LibDirs: -L/Delta;-L/Delta/sub;-L/Zeta
diff --git a/Tests/RunCMake/cmake_pkg_config/ExtractReroot-stderr.txt b/Tests/RunCMake/cmake_pkg_config/ExtractReroot-stderr.txt
index ab524d4..d4bab07 100644
--- a/Tests/RunCMake/cmake_pkg_config/ExtractReroot-stderr.txt
+++ b/Tests/RunCMake/cmake_pkg_config/ExtractReroot-stderr.txt
@@ -1,4 +1,4 @@
-Cflags: -I/NewRoot/Alpha Beta -I/NewRoot/Gamma
-Includes: -I/NewRoot/Alpha;-I/NewRoot/Gamma
-Libs: -L/NewRoot/Delta Epsilon -L/NewRoot/Zeta
-LibDirs: -L/NewRoot/Delta;-L/NewRoot/Zeta
+Cflags: -I/NewRoot/Alpha -I/NewRoot/Alpha/sub Beta -I/NewRoot/Gamma
+Includes: -I/NewRoot/Alpha;-I/NewRoot/Alpha/sub;-I/NewRoot/Gamma
+Libs: -L/NewRoot/Delta -L/NewRoot/Delta/sub Epsilon -L/NewRoot/Zeta
+LibDirs: -L/NewRoot/Delta;-L/NewRoot/Delta/sub;-L/NewRoot/Zeta
diff --git a/Tests/RunCMake/cmake_pkg_config/ImportSystem-check.cmake b/Tests/RunCMake/cmake_pkg_config/ImportSystem-check.cmake
new file mode 100644
index 0000000..a6f4eb3
--- /dev/null
+++ b/Tests/RunCMake/cmake_pkg_config/ImportSystem-check.cmake
@@ -0,0 +1,11 @@
+set(expected
+"Include Directories: /TestDirectories/Include
+Link Directories: /TestDirectories/Library
+"
+)
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/import-system.txt" actual)
+
+if(NOT(expected STREQUAL actual))
+  set(RunCMake_TEST_FAILED "cmake_pkg_config import-system.txt does not match expected:\n${actual}")
+endif()
diff --git a/Tests/RunCMake/cmake_pkg_config/ImportSystem.cmake b/Tests/RunCMake/cmake_pkg_config/ImportSystem.cmake
new file mode 100644
index 0000000..bf0fb14
--- /dev/null
+++ b/Tests/RunCMake/cmake_pkg_config/ImportSystem.cmake
@@ -0,0 +1,12 @@
+set(CMAKE_PKG_CONFIG_SYS_INCLUDE_DIRS /TestDirectories/Include)
+set(CMAKE_PKG_CONFIG_SYS_LIB_DIRS /TestDirectories/Library)
+
+cmake_pkg_config(IMPORT import-simple REQUIRED)
+
+file(GENERATE
+  OUTPUT import-system.txt
+  CONTENT
+"Include Directories: $<TARGET_PROPERTY:PkgConfig::import-simple,INTERFACE_INCLUDE_DIRECTORIES>
+Link Directories: $<TARGET_PROPERTY:PkgConfig::import-simple,INTERFACE_LINK_DIRECTORIES>
+"
+)
diff --git a/Tests/RunCMake/cmake_pkg_config/PackageRoot/relocate.pc b/Tests/RunCMake/cmake_pkg_config/PackageRoot/relocate.pc
index 5abce76..ac97d46 100644
--- a/Tests/RunCMake/cmake_pkg_config/PackageRoot/relocate.pc
+++ b/Tests/RunCMake/cmake_pkg_config/PackageRoot/relocate.pc
@@ -2,5 +2,5 @@
 Description: For testing relocation and flag mangling
 Version: 1.0.0
 
-Cflags: -I/Alpha Beta -I/Gamma
-Libs: -L/Delta Epsilon -L/Zeta
+Cflags: -I/Alpha -I/Alpha/sub Beta -I/Gamma
+Libs: -L/Delta -L/Delta/sub Epsilon -L/Zeta
diff --git a/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake b/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake
index 422a993..b2e38fc 100644
--- a/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_pkg_config/RunCMakeTest.cmake
@@ -20,6 +20,7 @@
 run_cmake(ImportPrefix)
 run_cmake(ImportRequires)
 run_cmake(ImportSimple)
+run_cmake(ImportSystem)
 run_cmake(ImportTransitiveFail)
 run_cmake(ImportTransitiveVersion)
 run_cmake(ImportTransitiveVersionFail)
diff --git a/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake
index 15ca477..acfc742 100644
--- a/Tests/RunCMake/foreach/RunCMakeTest.cmake
+++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake
@@ -22,3 +22,4 @@
 run_cmake(foreach-RANGE-out-of-range-test)
 run_cmake(foreach-var-scope-CMP0124-OLD)
 run_cmake(foreach-var-scope-CMP0124-NEW)
+run_cmake(TrailingIn)
diff --git a/Tests/RunCMake/foreach/TrailingIn-result.txt b/Tests/RunCMake/foreach/TrailingIn-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/foreach/TrailingIn-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/foreach/TrailingIn.cmake b/Tests/RunCMake/foreach/TrailingIn.cmake
new file mode 100644
index 0000000..e2b5b2f
--- /dev/null
+++ b/Tests/RunCMake/foreach/TrailingIn.cmake
@@ -0,0 +1,5 @@
+foreach(v IN)
+endforeach()
+
+foreach(v1 v2 IN)
+endforeach()
diff --git a/Tests/RunCMake/property_init/CompileSources.cmake b/Tests/RunCMake/property_init/CompileSources.cmake
index 6909e07..d4f8b06 100644
--- a/Tests/RunCMake/property_init/CompileSources.cmake
+++ b/Tests/RunCMake/property_init/CompileSources.cmake
@@ -78,6 +78,7 @@
   "BUILD_WITH_INSTALL_NAME_DIR"             "@rpath/"           "<SAME>"
   ### Install
   "INSTALL_NAME_DIR"                        "@rpath/"           "<SAME>"
+  "INSTALL_OBJECT_NAME_STRATEGY"            "SHORT"             "<SAME>"
   "INSTALL_REMOVE_ENVIRONMENT_RPATH"        "ON"                "<SAME>"
   "INSTALL_RPATH"                           "@rpath/"           "<SAME>"
   "INSTALL_RPATH_USE_LINK_PATH"             "ON"                "<SAME>"
diff --git a/Tests/RunCMake/string/GenexpStrip.cmake b/Tests/RunCMake/string/GenexpStrip.cmake
new file mode 100644
index 0000000..9de498c
--- /dev/null
+++ b/Tests/RunCMake/string/GenexpStrip.cmake
@@ -0,0 +1,37 @@
+function(test_strip input expected)
+  string(GENEX_STRIP "${input}" strip)
+  if (NOT strip STREQUAL expected)
+    message(FATAL_ERROR "message(GENEXP_STRIP \"${input}\")
+evaluated to \"${strip}\"
+expected \"${expected}\"")
+  endif()
+endfunction()
+
+test_strip( # Simple case
+  "$<BOOL:1>"
+  ""
+)
+test_strip( # LHS contains generator expression
+  "$<$<CONFIG:Release>:NDEBUG>;DEBUG"
+  "DEBUG"
+)
+test_strip( # RHS contains generator expression
+  "$<AND:1,$<BOOL:TRUE>>"
+  ""
+)
+test_strip( # Empty and unfinished expressions
+  "$<>$<$<>"
+  "$<$<>"
+)
+test_strip( # Multiple independent expressions
+  "$<IF:TRUE,TRUE,FALSE> / $<IF:TRUE,TRUE,FALSE>"
+  " / "
+)
+test_strip( # Multiple : in one expression
+  "$<1:2:3>"
+  ""
+)
+test_strip( # Multiple case
+  "1$<AND:1,0>2$<IF:$<$<BOOL:1>:$<CONFIG:RELEASE>>,TRUE,FALSE>3"
+  "123"
+)
diff --git a/Tests/RunCMake/string/RunCMakeTest.cmake b/Tests/RunCMake/string/RunCMakeTest.cmake
index a495363..f4a6ff8 100644
--- a/Tests/RunCMake/string/RunCMakeTest.cmake
+++ b/Tests/RunCMake/string/RunCMakeTest.cmake
@@ -57,3 +57,5 @@
 run_cmake(Hex)
 run_cmake(HexTooManyArgs)
 run_cmake(HexNotEnoughArgs)
+
+run_cmake(GenexpStrip)
diff --git a/Utilities/gdb/gdbinit-template b/Utilities/gdb/gdbinit-template
new file mode 100644
index 0000000..0e4a267
--- /dev/null
+++ b/Utilities/gdb/gdbinit-template
@@ -0,0 +1,5 @@
+# Allows GDB to follow child processes
+set follow-fork-mode child
+
+# Allows the parent process continue in parallel
+set non-stop on
diff --git a/bootstrap b/bootstrap
index d88a88d..e354aa9 100755
--- a/bootstrap
+++ b/bootstrap
@@ -454,6 +454,7 @@
   cmOSXBundleGenerator \
   cmOptionCommand \
   cmOrderDirectories \
+  cmObjectLocation \
   cmOutputConverter \
   cmParseArgumentsCommand \
   cmPathLabel \