CMP0199 — CMake 4.4.0 Documentation

# CMP0199

Added in version 4.2.

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

Historically, when a `$<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 `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 Common Package Specification 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 Common Package Specification packages, only the configuration of the consumed imported target is considered, regardless of the policy setting.

This policy was introduced in CMake version 4.2. It may be set by `cmake_policy()` or `cmake_minimum_required()`. If it is not set, CMake warns, and uses `OLD` behavior.

Note

The `OLD` behavior of a policy is deprecated by definition and may be removed in a future version of CMake.

## Examples

Consider the following imported libraries:

    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.