mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-05 14:49:39 -06:00
Create a brand new implementation of `cmTarget::GetMappedConfig` which prioritized a target's `IMPORTED_CONFIGURATIONS` as the 'source of truth' for what configurations are available. In particular, this means that configuration selection when `IMPORTED_CONFIGURATIONS` is set does not depend on the library type in any manner. The fallback logic also uses a more consistent 'usability' criteria that should result in more consistent configuration selection, particularly for `INTERFACE` targets. The previous implementation is retained as a separate method for users requesting the OLD behavior. Fixes: #27022
118 lines
5.1 KiB
ReStructuredText
118 lines
5.1 KiB
ReStructuredText
CMP0200
|
|
-------
|
|
|
|
.. versionadded:: 4.2
|
|
|
|
Location and configuration selection for imported targets is more consistent.
|
|
|
|
The way CMake historically selected the configuration to use for imported
|
|
targets prioritized selection based on location properties for a candidate
|
|
configuration and only considered :prop_tgt:`IMPORTED_CONFIGURATIONS` as a
|
|
fallback. This could result in incorrect configuration selection especially
|
|
for ``INTERFACE`` libraries.
|
|
|
|
CMake 4.2 and above consider :prop_tgt:`IMPORTED_CONFIGURATIONS` to be a
|
|
definitive list of available configurations, regardless of whether a
|
|
configuration specific location is provided for the library. Additionally,
|
|
CMake will respect non-configuration-specific locations when a configuration
|
|
specific location is not specified.
|
|
|
|
This policy provides compatibility with projects that rely on the historical
|
|
behavior. The policy setting applies to targets and is recorded at the point
|
|
an imported target is created. Accordingly, imported packages may override the
|
|
policy set by the consumer for targets they create. In particular, targets
|
|
imported from |CPS| packages always use the ``NEW`` behavior.
|
|
|
|
The ``OLD`` behavior for this policy is to retain the historic behavior.
|
|
The ``NEW`` behavior prioritizes selection based on the advertised list of
|
|
available configurations. Both behaviors are described in detail below.
|
|
|
|
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.2
|
|
.. |WARNS_OR_DOES_NOT_WARN| replace:: warns
|
|
.. include:: include/STANDARD_ADVICE.rst
|
|
|
|
.. include:: include/DEPRECATED.rst
|
|
|
|
Mapped configuration selection
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
If :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` (where ``<CONFIG>`` is the
|
|
configuration of the consuming target) is set on an imported target, CMake
|
|
would historically select from that list the first configuration which provides
|
|
a configuration-specific location. If no such configuration exists, CMake
|
|
would selects the consuming target's configuration, if the imported target is
|
|
an ``INTERFACE`` library. Otherwise, CMake considers the target as not having
|
|
a suitable configuration.
|
|
|
|
For ``INTERFACE`` libraries which do not provide a location, this results in
|
|
CMake always selecting the consuming target's configuration and effectively
|
|
ignoring :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>`. This behavior is not
|
|
consistent with configuration selection for imported targets which provide a
|
|
location.
|
|
|
|
Under the ``NEW`` behavior, CMake selects the first configuration from the
|
|
mapping which appears in :prop_tgt:`IMPORTED_CONFIGURATIONS`. If
|
|
:prop_tgt:`IMPORTED_CONFIGURATIONS` is not set, CMake selects the first
|
|
configuration from the mapping which is "usable". For non-``INTERFACE``
|
|
libraries, "usable" means that a location (either configuration-specific or
|
|
configuration-agnostic) is available. ``INTERFACE`` libraries are always
|
|
considered "usable".
|
|
|
|
If no match is found, CMake considers the target as not having a suitable
|
|
configuration.
|
|
|
|
Non-mapped configuration selection
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
If :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is *not* set, CMake would
|
|
historically select the first configuration which provides a location out of
|
|
the following:
|
|
|
|
- The consuming target's configuration, or
|
|
|
|
- The empty configuration, or
|
|
|
|
- The list of configurations in :prop_tgt:`IMPORTED_CONFIGURATIONS`.
|
|
|
|
As an implementation artifact, this results in CMake selecting the *last*
|
|
configuration in :prop_tgt:`IMPORTED_CONFIGURATIONS` for ``INTERFACE``
|
|
libraries which do not provide a location. Again, this behavior is not
|
|
consistent with configuration selection for imported targets which provide a
|
|
location.
|
|
|
|
Under the ``NEW`` behavior, if :prop_tgt:`IMPORTED_CONFIGURATIONS` is set,
|
|
CMake will select the consuming target's configuration if present therein,
|
|
otherwise CMake will select the first imported configuration. If
|
|
:prop_tgt:`IMPORTED_CONFIGURATIONS` is *not* set, CMake will select the
|
|
consuming target's configuration if it is "usable" (as defined in the previous
|
|
section); otherwise, CMake considers the target as not having a suitable
|
|
configuration.
|
|
|
|
Examples
|
|
^^^^^^^^
|
|
|
|
Consider the following imported library:
|
|
|
|
.. code-block:: cmake
|
|
|
|
add_library(test INTERFACE IMPORTED)
|
|
set_target_properties(test PROPERTIES
|
|
IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
|
|
INTERFACE_COMPILE_DEFINITIONS "$<$<CONFIG:debug>:DEBUG>"
|
|
)
|
|
|
|
Under the ``OLD`` policy, CMake will select the ``DEBUG`` configuration of
|
|
``test`` (and thus define the symbol ``DEBUG``) for any target linking to
|
|
``test``, because CMake does not consider any configuration "valid", and, as
|
|
an implementation artifact, the last configuration considered is accepted.
|
|
|
|
Under the ``NEW`` policy, the ``RELEASE`` configuration will be selected
|
|
if the consuming project is built in any configuration other than ``Debug``
|
|
(keeping in mind that configuration matching is case-insensitive). This is
|
|
because ``DEBUG`` will be preferred if the consumer's configuration is also
|
|
``DEBUG``, but ``RELEASE`` will be preferred otherwise because it appears
|
|
first in :prop_tgt:`IMPORTED_CONFIGURATIONS`, and its appearance therein makes
|
|
it a "valid" configuration for an ``INTERFACE`` library.
|
|
|
|
.. |CPS| replace:: Common Package Specification
|