File: CMP0199.rst

package info (click to toggle)
cmake 4.2.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 152,336 kB
  • sloc: ansic: 403,896; cpp: 303,920; sh: 4,105; python: 3,583; yacc: 3,106; lex: 1,279; f90: 538; asm: 471; lisp: 375; cs: 270; java: 266; fortran: 239; objc: 215; perl: 213; xml: 198; makefile: 111; javascript: 83; pascal: 63; tcl: 55; php: 25; ruby: 22
file content (97 lines) | stat: -rw-r--r-- 3,935 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
CMP0199
-------

.. versionadded:: 4.2

:genex:`$<CONFIG:cfgs>` does not match mapped configurations that are not
selected.

Historically, when a :genex:`$<CONFIG:cfgs>` generator expression appeared in
the properties of an imported target, it would match (that is, evaluate to
``1``) if any of the ``cfgs`` matched *any* of the following:

1. The selected configuration of the imported target being consumed.

2. The configuration of the consuming target.

3. *Any* of the configurations in the :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>`
   of the imported target being consumed
   (where ``<CONFIG>`` is the configuration of the consuming target),
   *whether or not such configurations are valid for the imported target*.

This can result in expressions which are intended to be mutually exclusive
being concurrently evaluated.  This can be especially problematic if the value
of a compile definition is intended to be determined by the configuration, as
this lack of exclusivity could result in redefinition.

CMake 4.2 and above prefer to consider *only* the configuration of the
consuming target and (when applicable) the selected configuration of the
imported target; that is, (2) and (1) in the above list.  Unfortunately,
because users rely on both of these, this policy is not able to fully prevent
multiple unique ``$<CONFIG:cfg>`` expressions from matching concurrently.

This policy provides compatibility with projects that rely on the historical
behavior.  The ``OLD`` behavior for this policy is to retain the historic
behavior as described above.  The ``NEW`` behavior is to consider only the
configurations of the consuming and consumed targets.

.. note::

  This policy only applies to generator expressions being evaluated as part of
  the usage requirements of imported targets which are not imported from |CPS|
  packages.

  For non-imported targets, both the historic and ongoing behavior is to
  consider only the configuration of the consuming target.  (The selected
  configuration of a non-imported target is always the active build
  configuration, which is necessarily the same as the consuming target's
  configuration.)

  For targets imported from |CPS| packages, **only** the configuration of the
  consumed imported target is considered, regardless of the policy setting.

.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.2
.. |WARNS_OR_DOES_NOT_WARN| replace:: warns
.. include:: include/STANDARD_ADVICE.rst

.. include:: include/DEPRECATED.rst

Examples
^^^^^^^^

Consider the following imported libraries:

.. code-block:: cmake

  add_library(test1 INTERFACE IMPORTED)
  set_target_properties(test1 PROPERTIES
    IMPORTED_CONFIGURATIONS "DEBUG"
    INTERFACE_COMPILE_DEFINITIONS
      "$<$<CONFIG:debug>:DEBUG>;$<$<CONFIG:release>:RELEASE>"
  )

  add_library(test2 INTERFACE IMPORTED)
  set_target_properties(test2 PROPERTIES
    IMPORTED_CONFIGURATIONS "TEST"
    INTERFACE_COMPILE_DEFINITIONS
      "$<$<CONFIG:debug>:DEBUG>;$<$<CONFIG:example>:EXAMPLE>;$<$<CONFIG:test>:TEST>"
    MAP_IMPORTED_CONFIG_RELEASE "DEBUG;EXAMPLE;TEST"
  )

Assume that the consuming project is built in the ``Release`` configuration.
A consumer of ``test1`` will see both ``DEBUG`` and ``RELEASE`` defined,
regardless of the policy setting; ``$<CONFIG:debug>`` evaluates to ``1``
because the selected configuration of ``test1`` is ``DEBUG``, and
``$<CONFIG:release>`` evaluates to ``1`` because the consumer's configuration
is ``Release`` (keeping in mind that configuration matching is
case-insensitive).

Under the ``OLD`` policy, a consumer of ``test2`` would see all of ``DEBUG``,
``EXAMPLE`` and ``TEST`` defined; ``$<CONFIG:debug>``, ``$<CONFIG:example>``
and ``$<CONFIG:test>`` all evaluate to ``1`` because all of these
configurations appear in ``MAP_IMPORTED_CONFIG_RELEASE``.

Under the ``NEW`` policy, a consumer of ``test2`` will see only ``TEST``
defined.

.. |CPS| replace:: Common Package Specification