find_package: Implement UNWIND_INCLUDE

This implements a limited exception mechanism for find_package() via
the UNWIND_INCLUDE keyword.

When package discovery via find_package(UNWIND_INCLUDE) fails the
StateSnapshot is updated to an UNWINDING state. In this state further
calls to find_package() and include() are forbidden. While in the
UNWINDING state, the include() command immediately calls
SetReturnInvoked() whenever it is reached.

The UNWINDING state is reset when a parent call to find_package() is
reached.

Fixes: #26897
This commit is contained in:
Vito Gamberini
2025-07-10 12:42:55 -04:00
parent a4d82a5a6d
commit f61768107e
40 changed files with 404 additions and 8 deletions

View File

@@ -141,7 +141,8 @@ Basic Signature
[REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
[GLOBAL]
[NO_POLICY_SCOPE]
[BYPASS_PROVIDER])
[BYPASS_PROVIDER]
[UNWIND_INCLUDE])
The basic signature is supported by both Module and Config modes.
The ``MODULE`` keyword implies that only Module mode can be used to find
@@ -249,6 +250,21 @@ of the ``NO_POLICY_SCOPE`` option.
itself. Future versions of CMake may detect attempts to use this keyword
from places other than a dependency provider and halt with a fatal error.
.. versionadded:: 4.2
The ``UNWIND_INCLUDE`` keyword is only allowed when ``find_package()`` is
being called within a parent call to ``find_package()``. When a call to
``find_package(UNWIND_INCLUDE)`` fails to find the desired package, it begins
an "unwind" state. In this state further calls to ``find_package()`` and
:command:`include()` are forbidden, and all parent :command:`include()`
commands will immediately invoke :command:`return()` when their scope is
reached. This "unwinding" will continue until the parent ``find_package()``
is returned to.
``UNWIND_INCLUDE`` is only intended to be used by calls to ``find_package()``
generated by :command:`install(EXPORT_PACKAGE_DEPENDENCIES)`, but may be
useful to those who wish to manually manage their dependencies in a similar
manner.
.. _`full signature`:
Full Signature