CMAKE-POLICIES(7)
🎀 NAME 🎀
ok so this is cmake-policies — the CMake Policies Reference, straight out of the CMake manual (section 7, iykyk). Bestie, buckle up, because this is the ✨lore✨ page. 💖
💅 INTRODUCTION 💅
CMake policies are literally how CMake introduces behavior changes without breaking every existing project on planet earth. They're a deprecation mechanism, not feature toggles — no cap, that distinction matters.
Every single policy documents two things:
- a deprecated OLD behavior 🫠
- a preferred, glowing, main-character NEW behavior 👑
Projects are expected to update over time and start using the NEW behavior, but their existing releases will keep on working with the OLD behavior. Everyone's happy. Everyone's slaying. 💅
🦋 Updating Projects 🦋
When a new version of CMake introduces policies, their OLD behaviors become immediately deprecated — in that version and every version after it. So you should update your project to the NEW behaviors, like, as soon as possible. fr fr.
Use the cmake_minimum_required() command to record the latest version of CMake that your project has actually been updated for. For example:
cmake_minimum_required(VERSION 3.10...4.3)
This uses the <min>...<policy_max> syntax to enable the NEW behaviors of policies introduced in CMake 4.3 and earlier, while only requiring a minimum CMake version of 3.10. So your project is expected to work with both the OLD and NEW behaviors of policies introduced between those two versions. Versatile icon behavior. 🌈
🌸 Transition Schedule 🌸
To help projects port to the NEW behaviors on their own schedule (no pressure bestie, but also… pressure), CMake offers a transition period:
- If a policy is not set by a project, CMake uses its OLD behavior, but may warn that the policy has not been set. 😭
- Users running CMake may silence the warning without modifying the project by setting the
CMAKE_POLICY_DEFAULT_CMP<NNNN>variable as a cache entry on thecmake(1)command line:
- Users running CMake may silence the warning without modifying the project by setting the
cmake -DCMAKE_POLICY_DEFAULT_CMP0990=OLD ...
- Projects may silence the warning by using the
cmake_policy()command to explicitly set the policy to OLD or NEW behavior:
if(POLICY CMP0990)
cmake_policy(SET CMP0990 NEW)
endif()
- 📌 Note: a policy should almost never be set to OLD — only to silence warnings in an otherwise frozen or stable codebase, or temporarily as part of a larger migration path. Like, don't make it a lifestyle. 🙈
- If a policy is set to OLD by a project, CMake versions released at least 2 years after the version that introduced the policy may issue a warning that the policy's OLD behavior will be removed from a future version of CMake. ⏳
- If a policy is not set to NEW by a project, CMake versions released at least 6 years after the version that introduced the policy, and whose major version number is higher, may issue an error that the policy's OLD behavior has been removed. 💀
👑 SUPPORTED POLICIES 👑
The following policies are supported. Bestie, get comfy. 🍓
🔥 Policies Introduced by CMake 4.4 🔥
💜 CMP0219 💜
Added in version 4.4.
macro() invocations preserve backslashes in arguments.
In CMake 4.3 and below, macro argument references (${ARGN}, ${ARGV}, ${ARGV<n>}, and named macro arguments) are substituted textually and then evaluated by the called command. Backslashes in substituted values get re-evaluated as escape prefixes, and invalid escape sequences (such as \b in Windows paths) can straight-up cause errors. 😭 The same re-evaluation can also occur for arguments passed to a variable_watch() callback command.
CMake 4.4 and above prefer to preserve literal backslashes in those macro argument references. Iconic.
- The OLD behavior for this policy: interpret escape sequences in macro argument references and in arguments passed to
variable_watch()callback commands. - The NEW behavior: preserve backslashes in those values before command invocation. ✨
This policy applies to macro argument references and to arguments passed to variable_watch() callback commands. Other variable references keep their existing behavior — no notes, no changes. 💅
🌀 Mixed Policy Chains 🌀
Whether pre-escaping occurs is determined by the policy setting at each call site. So when a project and its dependencies use different CMP0219 settings, each macro call in the chain follows the policy where that call appears. It's giving "everyone's on their own journey." 🦋
Consider a project (CMP0219 is OLD) that calls a macro from dependency A (upgraded to cmake_minimum_required(VERSION 4.4), so CMP0219 is NEW), which in turn forwards arguments to a macro from dependency B (not yet upgraded, so CMP0219 is OLD):
# Dependency B: cmake_minimum_required(VERSION 3.24)
# CMP0219 is OLD inside dependency B.
macro(depB_store var_name)
set(${var_name} "${ARGN}")
endmacro()
# Dependency A: cmake_minimum_required(VERSION 4.4)
# CMP0219 is NEW inside dependency A.
macro(depA_forward var_name)
depB_store(${var_name} ${ARGN}) # call site is NEW -> pre-escapes
endmacro()
# Project: cmake_minimum_required(VERSION 3.24)
# CMP0219 is OLD in the project.
macro(my_wrapper var_name)
depA_forward(${var_name} ${ARGN}) # call site is OLD -> no pre-escaping
endmacro()
In a fully OLD chain, each macro boundary re-evaluates backslash escapes, so callers must add extra escaping layers to compensate. 😵 To pass the Windows path C:\build\new\temp through three OLD boundaries, the caller needs eight backslashes per separator:
my_wrapper(result "C:\\\\\\\\build\\\\\\\\new\\\\\\\\temp")
message("${result}") # -> C:\build\new\temp
When dependency A upgrades and the middle boundary becomes NEW, that boundary preserves backslashes instead of consuming a level. So the same input now retains an extra layer:
# Same 8x-escaped input through OLD -> NEW -> OLD:
my_wrapper(result "C:\\\\\\\\build\\\\\\\\new\\\\\\\\temp")
message("${result}") # -> C:\\build\\new\\temp (one extra layer)
The caller must then use half the escaping to reach the native path:
# Only 4x-escaped input needed for OLD -> NEW -> OLD:
my_wrapper(result "C:\\\\build\\\\new\\\\temp")
message("${result}") # -> C:\build\new\temp
When a dependency updates its cmake_minimum_required() version to 4.4 or above, call sites inside that dependency begin pre-escaping. Callers that previously added extra backslash layers to compensate for multiple levels of OLD re-evaluation may then need fewer escape layers. 🔁
Where possible, converting paths to forward slashes with cmake_path(CONVERT ... TO_CMAKE_PATH_LIST) avoids the issue entirely, because forward slashes require no escaping regardless of the policy setting. Slash girlies stay winning. 💅
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns when backslashes are present, 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. 🫶
🎀 CMP0218 🎀
Added in version 4.4.
The CMAKE_WARN_DEPRECATED and CMAKE_ERROR_DEPRECATED variables are ignored.
In CMake 4.3 and below, these variables controlled whether deprecation messages resulted in warnings, errors, or were suppressed. However, not all deprecation messages considered the non-cache values. 🙈
CMake 4.4 introduced a new, unified system for managing diagnostics that prefers the cmake_diagnostic() command for manipulating diagnostic actions.
This policy provides compatibility with projects that relied on these variables and have not been updated to be aware of the change. (We see you, legacy codebases. We love you. But also. 👀)
- The OLD behavior for this policy: use the variables to control deprecation messages which respected the non-cache values of these variables in CMake 4.3 and earlier.
- The NEW behavior: does not ascribe any special meaning to the non-cache values of these variables, and uses the
CMD_DEPRECATEDdiagnostic state to control all deprecation messages. 👑
📌 Note: theCMAKE_WARN_DEPRECATEDandCMAKE_ERROR_DEPRECATEDcache variables are synchronized with the initial state of theCMD_DEPRECATEDdiagnostic, regardless of this policy's setting. (The synchronization happens at a point prior to when it is possible to manipulate policies.) However, this behavior is deprecated and will be removed in a future version of CMake. 💀
Any deprecation messages introduced in CMake 4.4 or later are controlled by the CMD_DEPRECATED diagnostic regardless of the setting of this policy.
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns when either variable is accessed or modified, 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. 🫶
🦋 CMP0217 🦋
Added in version 4.4.
The MACROS directory property does not exist anymore. Gone. Not invited to the function. 💀
In CMake 4.3 and below, the macros defined in a directory are registered in the MACROS directory property. However, the property does not have the same scope as macros, so it does not represent the actual list of macros. 🫠 In CMake 4.4 and above, this property is no longer filled with the defined macros. One may still use if(COMMAND myMacro) to test whether one exists. easy peasy. ✨
- The OLD behavior for this policy: store macros definition in the
MACROSdirectory property. - The NEW behavior for this policy: no longer manage the
MACROSdirectory property.
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior. (Quiet king behavior. 🤫)
📌 Note: The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 🫶
🧚 CMP0216 🧚
Added in version 4.4.
Swift targets have a default project name. 🕊️
CMake 4.3 and below did not compile Swift targets with -package-name, and ngl that flag is kind of a whole thing 💅 — because Swift's package access control makes types, functions, and properties visible to other libraries within the same package, but absolutely not from sources outside of the package. CMake 4.4 and above prefer to pass -package-name by default, using the PROJECT_NAME variable value. This policy is the compatibility arc for projects that haven't been updated to expect a package name yet.
🎀 Note: Package access control was added in Swift 5.8 and Xcode 15. So this policy has no effect when you're on an earlier version of Swift or Xcode. None. Zero. Nada.
The OLD behavior for this policy is to build Swift source files without passing a package-name. The NEW behavior for this policy is to build Swift source files with a default package name from PROJECT_NAME.
Regardless of whether this policy is set, the Swift_PACKAGE_NAME target property may be set to explicitly specify or suppress a package name. Your call, bestie 🫶
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
CMP0215
Added in version 4.4.
Ninja Generators emit Swift modules separately from compilation. Iconic behavior, honestly ✨
In CMake 4.3 and below, Swift targets built by Ninja Generators emit .swiftmodule from the Swift compile edge together with object files. And because Ninja treats a build edge as atomic (no splitting, no negotiating 😭), downstream Swift targets must wait for compilation outputs to finish before they can use the module interface. Patiently. Vibes: waiting room.
CMake 4.4 and above prefer to emit .swiftmodule from a dedicated -emit-module build edge so that downstream Swift targets can begin compiling as soon as the module interface is available. Main character scheduling energy. This policy provides compatibility with projects that have not been updated.
The OLD behavior for this policy is to not emit modules separately. The NEW behavior for this policy is to emit .swiftmodule from a dedicated build edge for importable Swift targets by default.
The Swift_SEPARATE_MODULE_EMISSION target property and corresponding CMAKE_Swift_SEPARATE_MODULE_EMISSION variable may be set to enable or disable the behavior on a per-target basis.
💀 Heads up: the NEW behavior requires that policiesCMP0157andCMP0195are also set to NEW.CMP0157selects the split Swift build model that provides the dedicated.swiftmoduleedge, and must be set prior to the firstproject()orenable_language()command that enables the Swift language.CMP0195places the module in the Swift module directory structure that the dedicated edge writes. If either policy is not NEW whileCMP0215is NEW, CMake issues a fatal error when the Swift language is enabled. Like, it will stop you. Immediately.
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
CMP0214
Added in version 4.4.
Honor CMAKE_EXE_LINKER_FLAGS for Swift executable targets. Okay so this one's a little drama that unfolded over several releases 🍓
CMake 3.29 introduced CMP0157, which provides an abstraction for selecting the Swift compilation mode. In CMake 3.30, CMAKE_SHARED_LINKER_FLAGS was accidentally honored for Swift shared library targets when CMP0157 is NEW — but the change went unnoticed and was not documented. The corresponding change was not made for Swift executable targets, leaving linker flag handling inconsistent between Swift executables and Swift shared libraries in CMake 3.30 through 4.3. A whole era of inconsistency. Not the slay we wanted 😭
CMake 4.4 and above prefer to honor CMAKE_EXE_LINKER_FLAGS for Swift executable targets when CMP0157 is set to NEW, restoring consistency with Swift shared library targets. This policy provides compatibility for projects that have not been updated to expect CMAKE_EXE_LINKER_FLAGS to be honored for Swift executables.
The OLD behavior for this policy is to not honor CMAKE_EXE_LINKER_FLAGS for Swift executable targets. The NEW behavior for this policy is to honor CMAKE_EXE_LINKER_FLAGS for Swift executable targets when CMP0157 is set to NEW.
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
CMP0213
Added in version 4.4.
file(ARCHIVE_CREATE) and file(ARCHIVE_EXTRACT) encode archive paths as UTF-8 by default. Encoding glow-up 🌈
CMake 4.3 and below always used the OEM (current locale) encoding for archive paths. CMake 4.4 offer the ENCODING option, but prefer to use UTF-8 by default. This policy provides compatibility for projects that have not been updated to specify the encoding or accept the new default.
The OLD behavior for this policy is to use the current locale as the default encoding, which is also known as an OEM encoding. The NEW behavior uses UTF-8 as the default encoding.
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
CMP0212
Added in version 4.4.
add_custom_command() DEPENDS does not strip .exe suffixes. Bestie, the suffix stays 💅
When searching for dependencies specified with the DEPENDS option of add_custom_command(), CMake 4.3 and below applied a heuristic to remove .exe from the end of DEPENDS argument values, which created a target-level dependency on an executable with that stripped name if such a target exists. This allowed using the name of the target output file as an alternative spelling when naming dependencies. However, with the emergence of CMake's target model, specifying the output file in this way is no longer needed, and leads to conflicts in creating target- and file-level dependencies when targets exist with the .exe suffix in the name itself.
The OLD behavior of this policy strips the .exe suffix from arguments to DEPENDS when searching for target-level dependencies. The NEW behavior does not strip the .exe suffix in its search. CMake will otherwise proceed normally with the other dependency search heuristics as specified in add_custom_command() DEPENDS. Users are encouraged to specify the name of the executable target if a target-level dependency is desired, or use the TARGET_FILE generator expression if a file-level dependency is desired, rather than implying the target indirectly via its output file name. Direct is better, fr fr 🫶
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
CMP0211
Added in version 4.4.
A file may belong to at most one non-HEADERS file set in a target. One file, one home. Boundaries! 🦋
In CMake 4.3 and below, it was possible to specify the same file in multiple file sets in a target. In CMake 4.4 and above, a file may belong to at most one file set in a target except for the HEADERS file set type. This policy provides compatibility for projects that have not been updated accordingly.
The OLD behavior for this policy is to accept the same file in multiple file sets in a target. The NEW behavior for this policy is to accept a given file in at most one file set in a target except for the HEADERS file set type.
This policy was introduced in CMake version 4.4. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns when a file is part of multiple file sets in a target, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌸 Policies Introduced by CMake 4.3
CMP0210
Added in version 4.3.
CMAKE_<LANG>_LINK_FLAGS adds link flags to all target types. Glow-up for one variable, consequences for everyone ✨
In CMake 4.2 and below, CMAKE_<LANG>_LINK_FLAGS held flags relevant to target creation and applied when linking executables only. It was undocumented and originally intended for internal use only, but still available for projects and users to set in order to control linking behavior. (iykyk energy — it was lowkey an internal variable the whole time 👀)
CMake 4.3 and above repurpose this variable to add per-language link flags for all target types that link (executables, shared libraries, and module libraries).
This policy provides compatibility with projects that relied on this variable and have not been updated to be aware of the change.
The OLD behavior for this policy is to apply CMAKE_<LANG>_LINK_FLAGS to invocations of the compiler which drive linking for executables only. The NEW behavior is to apply the flags to all target types.
This policy was introduced in CMake version 4.3. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns when CMAKE_<LANG>_LINK_FLAGS is set, 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. 💀 (like, it still works but it's on the way out, jsyk)
🦋 CMP0209
Added in version 4.3. ✨
Verify interface header sets checks executables without exports.
Okay so picture this: when VERIFY_INTERFACE_HEADER_SETS is set to true on an executable target, CMake 4.2 and below would only actually run those checks if the target's ENABLE_EXPORTS property was true. And the reasoning back then was lowkey sound — no other target could consume the headers of an executable target if that executable target didn't export symbols, right? Makes sense.
But then 💅 other use cases emerged for verifying header file sets where exporting symbols is no longer a requirement. So CMake 4.3 and above prefers to verify interface file sets of executable targets regardless of whether they export symbols or not. Growth! Evolution! We love to see it.
- The OLD behavior of this policy only verifies interface file sets of an executable target if its
ENABLE_EXPORTSproperty is set to true. - The NEW behavior always verifies interface file sets of an executable target when
VERIFY_INTERFACE_HEADER_SETSis set to true.
This policy was introduced in CMake version 4.3. 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. 🙈
🌸 CMP0208
Added in version 4.3. ✨
export(EXPORT) does not allow empty arguments.
So in CMake 4.2 and below, the export(EXPORT) command was out here silently accepting NAMESPACE, FILE or CXX_MODULES_DIRECTORY arguments with empty or missing values. Like, no comment, no nothing. Just vibes. 😭
CMake 4.3 and above issues a diagnostic if any of these keywords are present without an associated value, or if the value given to FILE or CXX_MODULES_DIRECTORY is empty. (Tiny exception bestie: NAMESPACE is allowed to have an empty value, but an empty value must be quoted.) A diagnostic is also issued immediately if the value of EXPORT is missing or empty. (Previously, this would result in an error at generate-time because no export set whose name is empty can exist. So like, it was never gonna work anyway.)
This policy provides compatibility with projects which may have relied on the previous lack of enforcement.
- The OLD behavior for this policy permits these keywords to be present without an accompanying value, or to be given an empty value.
- The NEW behavior requires that a value be given, and that the value (except for
NAMESPACE) is non-empty.
This policy was introduced in CMake version 4.3. 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. 🫶
🎀 CMP0207
Added in version 4.3. ✨
file(GET_RUNTIME_DEPENDENCIES) normalizes paths before matching.
The file(GET_RUNTIME_DEPENDENCIES) and install(RUNTIME_DEPENDENCY_SET) commands support filtering resolved dependencies using regular expressions matching their paths. And ngl, in CMake 4.2 and below, callers were responsible for matching both forward and backward slashes as path separators on Windows — e.g., via [\/]. Your problem, not CMake's. 😭
CMake 4.3 and above prefers to normalize paths to use forward slashes before matching. This policy provides compaitiblity (yes that typo is canon, I don't make the rules) for projects that may have been relying on matching backslashes only.
- The OLD behavior for this policy matches filters against paths that may contain any combination of forward and backward slashes on Windows.
- The NEW behavior for this policy to convert all paths to forward slashes before matching filters.
This policy was introduced in CMake version 4.3. 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. 🌈
🧚 CMP0206
Added in version 4.3. ✨
The CPack Archive Generator defaults to UID 0 and GID 0.
In CMake 4.2 and below, the CPack Archive Generator always used the current user's UID/GID in archive entries. Then CMake 4.3 added the CPACK_ARCHIVE_UID and CPACK_ARCHIVE_GID variables to control them. 🎀
Here's the little logic bit that matters: if either is set, the default for the other is 0. If neither is set, CMake 4.3 and above prefers to default both UID and GID to 0 so that unpacking by root produces paths owned by root. This policy provides compatibility with projects that have not been updated to expect the new behavior.
- The OLD behavior for this policy is to produce archive entries with the current user's UID/GID by default.
- The NEW behavior for this policy is to produce archive entries with the UID/GID set to
0/0by default.
This policy was introduced in CMake version 4.3. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior. (Yeah, she's quiet about this one, no cap.)
See documentation of the CMAKE_POLICY_WARNING_CMP0206 variable to control the warning.
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 💅
🍓 CMP0205
Added in version 4.3. ✨
file(CREATE_LINK) with COPY_ON_ERROR copies directory content.
The file(CREATE_LINK) command's COPY_ON_ERROR option copies the source file to the destination as a fallback if linking it fails. Cute, right? But if the source is a directory, CMake 4.2 and below creates the destination directory but does not copy its contents. Which is like… giving someone an empty gift box. 😭
CMake 4.3 and above prefers to copy the directory contents too. This policy provides compatibility with projects that have not been updated to expect the contents to be copied.
- The OLD behavior for this policy is to create the destination directory without copying contents.
- The NEW behavior for this policy to create the destination directory and copy contents from the source directory.
This policy was introduced in CMake version 4.3. 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. 🌸
👑 Policies Introduced by CMake 4.2
🔥 CMP0204
Added in version 4.2. ✨
A character set is always defined when targeting the MSVC ABI.
In CMake 4.1 and below, Visual Studio Generators compile sources with _MBCS, _UNICODE or _SBCS defined due to behavior of Visual Studio itself. And the preprocessor definition is not modeled by CMake, so it's therefore not added by other generators, such as Ninja. Messy, honestly.
CMake 4.2 and above, when targeting the MSVC ABI, prefers to compile sources with _MBCS defined by all generators unless another charset preprocessor definition is found (_UNICODE or _SBCS). This policy provides compatibility with projects that have not been updated to be aware of the definition. Its setting is recorded by each target as it is created, and affects compilation of sources in that target. 📝
- The OLD behavior for this policy does not model the
_MBCSpreprocessor definition in CMake itself. - The NEW behavior for this policy adds the
_MBCSpreprocessor definition to sources as a default encoding when targeting the MSVC ABI.
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 does not warn, 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. 🦋
💜 CMP0203
Added in version 4.2. ✨
_WINDLL is defined for shared libraries targeting the MSVC ABI.
In CMake 4.1 and below, Visual Studio Generators compile sources in shared libraries with _WINDLL defined due to behavior of Visual Studio itself. The preprocessor definition is not modeled by CMake and is therefore not added by other generators, such as Ninja. Same saga as above, different macro. 😭
CMake 4.2 and above, when targeting the MSVC ABI, prefers to compile sources in shared libraries with _WINDLL defined by all generators. This policy provides compatibility with projects that have not been updated to be aware of the definition. Its setting is recorded by each target as it is created, and affects compilation of sources in that target.
- The OLD behavior for this policy does not model the
_WINDLLpreprocessor definition in CMake itself. - The NEW behavior for this policy adds the
_WINDLLpreprocessor definition to sources in shared libraries when targeting the MSVC ABI.
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 does not warn, 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. ⭐
🎀 CMP0202
Added in version 4.2. ✨
PDB file names always include their target's per-config POSTFIX.
Program database files (.pdb) are always named with their target's DEBUG_POSTFIX or <CONFIG>_POSTFIX target property value. Periodt.
So here's the inconsistency bestie: if the PDB_NAME target property is defined, CMake 4.1 and below excludes the target's per-config postfix from the program data base file name. Otherwise, the per-config postfix is included. Two different rules for the same thing?? Pick a lane. 🚩
CMake 4.2 and above prefers to always name the program database file with the per-config postfix regardless how the name is computed, i.e., using OUTPUT_NAME, or PDB_NAME, or neither. This policy provides compatibility with projects that have not been updated to account for the new behavior.
Lowkey the OLD behavior for this policy is: it does not use the per-config postfix in .pdb file names if the PDB_NAME target property is defined. The NEW behavior always uses the per-config postfix in .pdb file names. 💅
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 does not warn, 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. Not me warning you twice, it's literally in the policy.
🐍 CMP0201
Added in version 4.2.
Python::NumPy does not depend on Python::Development.Module. Periodt. ✨
FindPython3, FindPython2, and FindPython provide Python{3,2,}::NumPy and Python{3,2,}::Development.Module targets when the corresponding components are requested.
In CMake 4.1 and below, requesting the NumPy component implies the Development.Module component, and the provided Python{3,2,}::NumPy targets depend on the provided Python{3,2,}::Development.Module targets. This dependency is not necessary. In CMake 4.2 and above, requesting the NumPy component does not imply the Development.Module component, and the provided Python{3,2,}::NumPy targets do not depend on the provided Python{3,2,}::Development.Module targets. This policy provides compatibility with projects that expect the legacy behavior.
So, the vibe check:
- OLD behavior — makes
NumPydepend onDevelopment.Module. - NEW behavior — does not. That's it, that's the whole policy 🫶
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 does not warn, 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.
🌈 CMP0200
Added in version 4.2.
Location and configuration selection for imported targets is more consistent. Like, so much more consistent, bestie. 🔥
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 IMPORTED_CONFIGURATIONS as a fallback. This could result in incorrect configuration selection especially for INTERFACE libraries. 😭
CMake 4.2 and above consider 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 Common Package Specification packages always use the NEW behavior. 👑
- OLD behavior — retain the historic behavior.
- NEW behavior — prioritizes selection based on the advertised list of available configurations.
Both behaviors are described in detail below. Keep scrolling, it's giving documentation ✨
This policy was introduced in CMake version 4.2. It may be set by cmake_policy() or cmake_minimum_required().
Careful bestie: if it is not set, CMake warns, and uses OLD behavior. Yes, this one actually yells at you. 💀
🙈 Note: The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🗺️ Mapped configuration selection
If 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 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 IMPORTED_CONFIGURATIONS. If 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 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
IMPORTED_CONFIGURATIONS.
As an implementation artifact, this results in CMake selecting the last configuration in 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. 😭 (implementation artifact is such a mood)
Under the NEW behavior, if IMPORTED_CONFIGURATIONS is set, CMake will select the consuming target's configuration if present therein, otherwise CMake will select the first imported configuration. If 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:
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 IMPORTED_CONFIGURATIONS, and its appearance therein makes it a "valid" configuration for an INTERFACE library. Slay 🌟
🦋 CMP0199
Added in version 4.2.
$<CONFIG:cfgs> does not match mapped configurations that are not selected. Obsessed with how specific that is. 💅
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:
- The selected configuration of the imported target being consumed.
- The configuration of the consuming target.
- 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. 💀 Not the redefinition jumpscare.
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. 😭 it's trying its best.
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"
)
So let's say the consumer project gets built in the Release configuration, yeah? A consumer of test1 is gonna see both DEBUG and RELEASE defined, and that's regardless of what the policy is set to — $<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 (and don't forget, config matching is case-insensitive, bestie 💅).
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 show up in MAP_IMPORTED_CONFIG_RELEASE.
Under the NEW policy, a consumer of test2 will see only TEST defined. Clean. Minimal. Slay. ✨
CMP0198
Added in version 4.2. 🎀
CMAKE_PARENT_LIST_FILE is not defined in CMakeLists.txt.
Okay so CMake 4.1 and below defined CMAKE_PARENT_LIST_FILE when processing a CMakeLists.txt — even though there's literally no parent file?? Like, bestie, who is your parent, you don't have one 😭. CMake 4.2 and above prefer to just not define CMAKE_PARENT_LIST_FILE. This policy exists for the projects that accidentally relied on the old behavior — no judgment, it happens to the best of us 💀.
The OLD behavior for this policy is to set CMAKE_PARENT_LIST_FILE to CMAKE_CURRENT_LIST_FILE when processing a CMakeLists.txt. The NEW behavior for this policy is to not set CMAKE_PARENT_LIST_FILE.
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 does not warn, 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.
💜 Policies Introduced by CMake 4.1 💜
CMP0197
Added in version 4.1. ✨
MSVC link -machine: flag is not in CMAKE_*_LINKER_FLAGS.
So when you're using MSVC-like compilers in CMake 4.0 and below, the linker's -machine: flag gets added via the language-agnostic linker flag variables:
CMAKE_EXE_LINKER_FLAGSCMAKE_SHARED_LINKER_FLAGSCMAKE_MODULE_LINKER_FLAGSCMAKE_STATIC_LINKER_FLAGS
And this is problematic — like, actually a problem — when multiple languages' toolchains disagree about if/how to pass the flag through a compiler driver to the linker 😬. And on top of that, carrying the flag around in public-facing variables lets projects or users change it, even though it is required. Not it. Not the vibe.
CMake 4.1 and above prefer to leave the -machine: flag out of CMAKE_*_LINKER_FLAGS variables, and instead generate the link flag automatically wherever it's needed. Iconic behavior honestly 👑.
This policy provides compatibility with projects that have not been updated to expect the lack of the -machine: flags. The policy setting takes effect as of the first project() or enable_language() command that initializes the above-listed CMAKE_*_LINKER_FLAGS variables.
Note 🚨: Once the policy has taken effect at the top of a project for a given language, that choice must be used throughout the tree for that language. In projects that have nested projects in subdirectories, be sure to convert everything together. No half-and-half, fr fr.
The OLD behavior for this policy is to place the MSVC -machine: flag in CMAKE_*_LINKER_FLAGS. The NEW behavior for this policy is to not place the MSVC -machine: flag in CMAKE_*_LINKER_FLAGS.
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
CMP0196
Added in version 4.1. 🌸
The CMakeDetermineVSServicePack module is removed.
Okay so listen — the CMakeDetermineVSServicePack module has long been superseded by the CMAKE_<LANG>_COMPILER_VERSION variable, and honestly the module has been documented as deprecated since CMake 3.0. That's ancient, bestie. It's giving fossil 💀. CMake 4.1 and above prefer to not provide the module at all. This policy provides compatibility for projects that have not been ported away from it.
The OLD behavior of this policy is for include(CMakeDetermineVSServicePack) to load the deprecated module. The NEW behavior halts with a fatal error if anything tries to include the module 😭. Yeah. Straight up stops.
This policy was introduced in CMake version 4.1. 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.
CMP0195
Added in version 4.1. 🦋
Swift modules in build trees use the Swift module directory structure.
So the Swift compiler emits a bunch of supplementary files that together make up the interface to a Swift library. It's fine with finding these files separately, or in a single swiftmodule directory. And the single one keeps things better organized and makes it easier to install the resulting products. Organization?! We love her ✨.
CMake versions 4.1 and above prefer to generate the modules in the directory structure when working with a new enough Swift compiler. This policy provides compatibility for projects that have not been updated to expect the new behavior.
The OLD behavior for this policy is to emit the interface files directly into the current binary directory. The NEW behavior for this policy is to gather the binary swiftmodule and other supplemental compiler outputs in a single Swift module directory. Tidy 🎀.
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
CMP0194
Added in version 4.1. 💖
MSVC is not an assembler for language ASM.
When you enable the ASM language, CMake considers C compiler drivers as assembler candidates. And CMake 4.0 and below accidentally selected MSVC's cl compiler as the CMAKE_ASM_COMPILER — which allowed the ASM language to be enabled on Windows even though cl does not support assembler sources 🙈. Oops. A little whoopsie.
CMake 4.1 and above prefer to reject cl as an assembler candidate, but some existing projects unconditionally enable ASM on Windows even though they add no assembler sources. This policy provides compatibility for such projects so they can configure as before, no cap.
The OLD behavior for this policy is to successfully enable ASM even if cl is the only available candidate. The NEW behavior for this policy is to not consider cl as a candidate assembler for the ASM language.
This policy was introduced in CMake version 4.1. 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.
CMP0193
Added in version 4.1. 🌈
GNUInstallDirs caches CMAKE_INSTALL_* with leading usr/ for install prefix /.
Okay so when CMAKE_INSTALL_PREFIX is /, the CMAKE_INSTALL_<dir> variables — where <dir> is one of BINDIR, SBINDIR, LIBEXECDIR, SHAREDSTATEDIR, INCLUDEDIR, OLDINCLUDEDIR, DATAROOTDIR, and LIBDIR — get prepended with a leading usr/ as documented among the special cases. In CMake 4.0 and below, these CMAKE_INSTALL_<dir> variables were cached without their leading usr/, and it was prepended in normal variables that shadow their cache entries. Messy. CMake 4.1 and above prefer to cache CMAKE_INSTALL_<dir> with their leading usr/.
Consequently, the GNUInstallDirs_get_absolute_install_dir() command no longer alters the relative input variable argument <input-var>. This policy provides compatibility for projects that have not been updated to expect the new behavior.
The OLD behavior for this policy is to cache CMAKE_INSTALL_<dir> variables without the leading usr/. The NEW behavior for this policy is to cache CMAKE_INSTALL_<dir> variables with the leading usr/.
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
CMP0192
Added in version 4.1. ⭐
GNUInstallDirs uses absolute SYSCONFDIR, LOCALSTATEDIR, and RUNSTATEDIR in special prefixes.
The GNUInstallDirs module documents special cases for SYSCONFDIR, LOCALSTATEDIR, and RUNSTATEDIR. So when CMAKE_INSTALL_PREFIX is a special prefix — like, say, /usr — the absolute paths for these directories may end up outside the prefix, e.g. /etc, /var, and /var/run. Sneaky little paths, iykyk 👀.
In CMake 4.0 and below, the default values for the CMAKE_INSTALL_<dir> variables — where <dir> equals SYSCONFDIR, LOCALSTATEDIR, and RUNSTATEDIR — always used relative paths (etc, var, var/run), and the special cases were implemented only when computing absolute paths for the CMAKE_INSTALL_FULL_<dir> variables. CMake 4.1 and above prefer to default CMAKE_INSTALL_<dir> variables to absolute paths, for <dir> equal to SYSCONFDIR, LOCALSTATEDIR, and RUNSTATEDIR, when CMAKE_INSTALL_PREFIX is a special prefix. This policy provides compatibility for projects that have not been updated to expect this behavior.
bestie, quick recap of where we are: the OLD behavior for this policy is to default the CMAKE_INSTALL_<dir> variables to relative paths. The NEW behavior is to default CMAKE_INSTALL_<dir> variables to absolute paths — for <dir> equal to SYSCONFDIR, LOCALSTATEDIR, and RUNSTATEDIR, when CMAKE_INSTALL_PREFIX is a special prefix.
Some deets so nothing surprises you:
- This policy takes effect at the first call of
include(GNUInstallDirs). - Subsequent calls of
include(GNUInstallDirs)reuse cachedCMAKE_INSTALL_<dir>values from the first call. So like… first one wins, no re-negotiating 💅
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. Rude but true 😭
CMP0191
added in version 4.1 ✨
The FindCABLE module is removed.
CMake 4.0 and below provide the FindCABLE module, but the CABLE tool is no longer maintained. So CMake 4.1 and above prefer to not provide the FindCABLE module at all. This policy is the little compatibility blanket for projects that have not been ported away from it 🫶
- The OLD behavior of this policy is for
find_package(CABLE)to load the deprecated module. - The NEW behavior is for
find_package(CABLE)to fail as if the module does not exist. 💀
This policy was introduced in CMake version 4.1. 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.
CMP0190
added in version 4.1 ✨
The modules FindPython3, FindPython2 and FindPython enforce consistency of artifacts in cross-compiling mode.
Starting with CMake 4.1, the modules FindPython3, FindPython2 and FindPython apply, in cross-compiling mode (i.e. the CMAKE_CROSSCOMPILING variable is set to true), the following constraints to the requested components:
- Interpreter or Compiler alone: the host artifacts will be searched.
- Interpreter or Compiler with Development or any sub-component: the target artifacts will be searched. In this case, the
CMAKE_CROSSCOMPILING_EMULATORvariable must be defined and will be used to execute the interpreter or the compiler. 👀
This policy provides compatibility with projects that expect the legacy behavior.
The OLD behavior for this policy does not enforce consistency in cross-compiling mode and will, potentially, return a mix of artifacts (i.e. host and target artifacts). A whole chaotic smoothie, no cap 🍓
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
CMP0189
added in version 4.1 ✨
The TARGET_PROPERTY generator expression evaluates LINK_LIBRARIES properties transitively. 🌀
The LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES target properties record link dependencies through which the TARGET_PROPERTY generator expression evaluates transitive properties. But in CMake 4.0 and below, the properties themselves were not evaluated transitively. CMake 4.1 and above prefer to evaluate the LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES target properties transitively because they are among the build specification and usage requirement properties, respectively. It's giving "obviously, they should be transitive" ✨
This policy provides compatibility for projects that have not been updated to expect the new behavior. It takes effect during buildsystem generation. Generator expressions are evaluated in each directory using the policy setting as of the end of its CMakeLists.txt. As an exception, generator expressions evaluated by the file(GENERATE) command use the policy setting as of its call site. iykyk
- The OLD behavior of this policy is for
TARGET_PROPERTYto not evaluateLINK_LIBRARIESandINTERFACE_LINK_LIBRARIEStransitively. - The NEW behavior is for
TARGET_PROPERTYto evaluateLINK_LIBRARIESandINTERFACE_LINK_LIBRARIEStransitively. 🫶
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
CMP0188
added in version 4.1 ✨
The FindGCCXML module is removed.
CMake 4.0 and below provide the FindGCCXML module, but the GCC-XML tool has long been superseded by CastXML. So CMake 4.1 and above prefer to not provide the FindGCCXML module. This policy provides compatibility for projects that have not been ported away from it 🌸
- The OLD behavior of this policy is for
find_package(GCCXML)to load the deprecated module. - The NEW behavior is for
find_package(GCCXML)to fail as if the module does not exist. 💀
This policy was introduced in CMake version 4.1. 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.
CMP0187
added in version 4.1 ✨
Include a source file without an extension after the same name with an extension.
In CMake 4.0 and below, if two source files have the same filename and only one file has a file extension, and the file with the extension is listed first, the file without the extension is omitted from the target. She just gets ghosted 👻
For example, the following library target only includes hello.c in the target, but omits the file hello:
add_library(library hello.c hello)
But if the file without the extension is listed before the file with the extension, both files are included in the target. Order-dependent behavior, so fun 🙃
Starting in CMake 4.1, CMake includes both files in the library target. Periodt.
This policy has no effect if CMP0115 uses the OLD behavior.
- The OLD behavior for this policy is to omit the file without the extension.
- The NEW behavior for this policy is to include it. 💖
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
CMP0186
added in version 4.1 ✨
Regular expressions match ^ at most once in repeated searches.
This policy affects commands that perform multiple regular expression searches:
string(REGEX MATCHALL)string(REGEX REPLACE)list(TRANSFORM REPLACE)
and the generator expression $<LIST:TRANSFORM,list,REPLACE>.
CMake 4.0 and below match the ^ anchor at the start of every successive search, leading to multiple matches:
string(REGEX REPLACE "^a" "b" result "aaaa") # result="bbbb"
string(REGEX MATCHALL "^a" result "aaaa") # result="a;a;a;a"
CMake 4.1 and above prefer to match the ^ anchor at most once, at the start of the input string:
string(REGEX REPLACE "^a" "b" result "aaaa") # result="baaa"
string(REGEX MATCHALL "^a" result "aaaa") # result="a"
This policy provides compatibility for projects that have not been updated.
- The OLD behavior for this policy is to match
^multiple times, at the start of each search. - The NEW behavior for this policy is to match
^at most once, at the start of the input string. ✨
This policy was introduced in CMake version 4.1. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
🎀 Policies Introduced by CMake 4.0 🎀
CMP0185
added in version 4.0 ✨
FindRuby no longer provides upper-case RUBY_* variables.
FindRuby in CMake 3.31 and below provided result variables named with an upper-case RUBY_ prefix. CMake 3.18 renamed them with a Ruby_ prefix to match the name of the package, but continued to provide the upper-case RUBY_ variables for compatibility.
CMake 4.0 and above prefer to provide only Ruby_ variables and no longer provide RUBY_ variables. This policy provides compatibility with projects that have not been updated 🫶
- The OLD behavior for this policy is to provide both
Ruby_andRUBY_variables. - The NEW behavior for this policy is to provide only
Ruby_variables and notRUBY_variables. 💅
This policy was introduced in CMake version 4.0. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
CMP0184
added in version 4.0 ✨
MSVC runtime checks flags are selected by an abstraction.
Compilers targeting the MSVC ABI have flags to select the runtime checks. Runtime checks selection typically varies with build configuration.
okay so in CMake 3.31 and below, runtime checks flags were being added to the default CMAKE_<LANG>_FLAGS_<CONFIG> cache entries by CMake automatically. like, on its own. no ask. and honestly that sounds helpful because it lets users just edit their cache entries to adjust the flags 💅 but the presence of those default flags is a whole problem for projects that want to choose different runtime checks programmatically. like, it forces you to do string editing on the CMAKE_<LANG>_FLAGS_<CONFIG> variables while knowing what CMake's builtin defaults are, just so you can replace them. exhausting. 😭
CMake 4.0 and above prefer to leave the runtime checks flags out of the default CMAKE_<LANG>_FLAGS_<CONFIG> values and instead offer a first-class abstraction. and the abstraction ate, fr fr — you've got the CMAKE_MSVC_RUNTIME_CHECKS variable and the MSVC_RUNTIME_CHECKS target property, and you may set either one to select the MSVC runtime checks. if they are not set, CMake enables runtime checks for the Debug configuration only, using the default value $<$<CONFIG:Debug>:StackFrameErrorCheck;UninitializedVariable>, if supported by the compiler, or an empty value otherwise. 🎀
This policy provides compatibility with projects that have not been updated to be aware of the abstraction. the policy setting takes effect as of the first project() or enable_language() command that enables a language whose compiler targets the MSVC ABI. ⭐
Note: 🫶 Once the policy has taken effect at the top of a project, that choice will be used throughout the tree. So in projects that have nested projects in subdirectories, be sure to confirm if everything is working with the selected policy behavior. like, actually check. please. 🙈
The OLD behavior for this policy is to place MSVC runtimes checks flags in the default CMAKE_<LANG>_FLAGS_<CONFIG> cache entries and ignore the CMAKE_MSVC_RUNTIME_CHECKS abstraction. The NEW behavior for this policy is to not place MSVC runtime checks flags in the default cache entries and use the abstraction instead. no cap.
This policy was introduced in CMake version 4.0. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
💜 CMP0183
Added in version 4.0. ✨
add_feature_info() supports full Condition Syntax. yes bestie, the full thing.
The <condition> parameter accepts a semicolon-separated list 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 to evaluate each condition as if(<condition>), where <condition> is re-parsed as if literally written in a call to if(). 🧚
This allows expressions like:
"A AND (B OR C)"
but requires expressions like:
"FOO MATCHES (UPPER|lower)"
to be re-written as:
"FOO MATCHES \"(UPPER|lower)\""
Policy CMP0183 provides compatibility for projects that have not been updated to expect the new behavior. 😌
This policy was introduced in CMake version 4.0. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns, and uses OLD behavior. (yes, this one actually warns — the others were all chill about it 🔥)
Note: The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🦋 CMP0182
Added in version 4.0.
Create shared library archives by default on AIX. 🫶 AIX girlies rise.
CMake 3.30 and below always represented SHARED library targets as plain shared object .so files. that's consistent with other UNIX platforms, but it's not the preferred convention on AIX. CMake 3.31 added the AIX_SHARED_LIBRARY_ARCHIVE target property to create a shared library archive: the shared object .so file gets placed inside an archive .a file. iconic! but the behavior was disabled by default for compatibility with existing projects that do not set AIX_SHARED_LIBRARY_ARCHIVE. 🙈
CMake 4.0 and above prefer, when AIX_SHARED_LIBRARY_ARCHIVE is not set, to enable creation of shared library archives by default, because it is the preferred convention on AIX. This policy provides compatibility for projects that have not been updated.
The OLD behavior for this policy is to disable shared library archives when AIX_SHARED_LIBRARY_ARCHIVE is not set. The NEW behavior for this policy is to enable shared library archives when AIX_SHARED_LIBRARY_ARCHIVE is not set.
This policy was introduced in CMake version 4.0. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
🌸 CMP0181
Added in version 4.0.
Okay so this one is about a whole squad of linker flag variables — they are parsed and re-quoted and support the LINKER: prefix. the squad:
CMAKE_EXE_LINKER_FLAGSCMAKE_EXE_LINKER_FLAGS_<CONFIG>CMAKE_SHARED_LINKER_FLAGSCMAKE_SHARED_LINKER_FLAGS_<CONFIG>CMAKE_MODULE_LINKER_FLAGSCMAKE_MODULE_LINKER_FLAGS_<CONFIG>
CMake 3.31 and below use the content of these variables as is. like, raw. untouched. 😬
CMake 4.0 and above parse the content of these variables and manage the escaping of special characters. Moreover — and this is the fun part — the LINKER: prefix is now recognized and expanded. ✨
The OLD behavior of this policy is to consume the content of those six variables as is.
The NEW behavior of this policy is to parse and re-quote the content of those six variables as well as to expand the LINKER: prefix.
This policy was introduced in CMake version 4.0. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
👑 Policies Introduced by CMake 3.31 👑
🍓 CMP0180
Added in version 3.31.
project() always sets <PROJECT-NAME>_* as normal variables. always always. periodt.
In CMake 3.29 and below, the project() command set <PROJECT-NAME>_SOURCE_DIR, <PROJECT-NAME>_BINARY_DIR, and <PROJECT-NAME>_IS_TOP_LEVEL as cache entries, but not as normal variables. then CMake 3.30 started setting them as normal variables, but only if they are already set as normal variables. why?? because it was needed to preserve support for some FetchContent use cases under policy CMP0169's NEW behavior, while also preserving behavior of nested directories that call project() with the same project name. the lore is real — see release notes for 3.30.3, 3.30.4, and 3.30.5 for details. 😭
CMake 3.31 and later prefer to always set <PROJECT-NAME>_SOURCE_DIR, <PROJECT-NAME>_BINARY_DIR, and <PROJECT-NAME>_IS_TOP_LEVEL as both cache entries and normal variables, regardless of what cache or normal variables already exist. This policy provides compatibility for projects that have not been updated to expect this behavior.
The OLD behavior for this policy will only set normal variables for <PROJECT-NAME>_SOURCE_DIR, <PROJECT-NAME>_BINARY_DIR, and <PROJECT-NAME>_IS_TOP_LEVEL if there is already a normal variable by that name when project() is called. The NEW behavior for this policy will always set normal variables for <PROJECT-NAME>_SOURCE_DIR, <PROJECT-NAME>_BINARY_DIR, and <PROJECT-NAME>_IS_TOP_LEVEL when project() is called. 🎀
This policy was introduced in CMake version 3.31. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
🌈 CMP0179
Added in version 3.31.
De-duplication of static libraries on link lines keeps first occurrence. okay this one only matters when policy CMP0156 is set to NEW, so like, note that. 💅
Based on the linker capabilities, the static libraries can be de-duplicated. See policy CMP0156 for more information.
CMake 3.30 and below may choose to keep, on some platforms, the last occurrence of the static libraries rather than the first occurrence when they are de-duplicated. chaos honestly.
CMake 3.31 and above prefer to keep, on all platforms, the first occurrence of the static libraries when they are de-duplicated. consistency slay. 🔥
The OLD behavior for this policy is to keep, on some platforms, the last occurrence of the static libraries when they are de-duplicated. The NEW behavior for this policy is to keep the first occurrence of the static libraries when they are de-duplicated, regardless of the platform. no cap. ⭐
This policy was introduced in CMake version 3.31. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
This policy rolled out in CMake 3.31. You can set it with cmake_policy() or cmake_minimum_required(). If you never set it, CMake won't even warn you — it just quietly uses the OLD behavior 🫶
⚠️ Heads up bestie: the OLD behavior of a policy is deprecated by definition, and it might get yeeted in a future version of CMake. Don't build your whole personality on it 💅
🧪 CMP0172... jk, CMP0178
Added in version 3.31.
Test command lines keep their empty arguments now.
Empty values in the TEST_LAUNCHER and CROSSCOMPILING_EMULATOR target properties are preserved for tests added by any of these:
- The
add_test()command. - The
ExternalData_Add_Test()command from theExternalDatamodule. - The
gtest_add_tests()orgtest_discover_tests()commands from theGoogleTestmodule.
And for gtest_add_tests() and gtest_discover_tests(), empty elements in the values you pass after the EXTRA_ARGS keyword are preserved too ✨
So the OLD behavior of this policy? It just silently discards empty list items from TEST_LAUNCHER and CROSSCOMPILING_EMULATOR in all the cases above. And yeah, it also silently discards empty items from the values after EXTRA_ARGS for gtest_add_tests() and gtest_discover_tests(). Gone. Poof 💀
The NEW behavior preserves empty list items in TEST_LAUNCHER and CROSSCOMPILING_EMULATOR, and in the values after EXTRA_ARGS for gtest_add_tests() and gtest_discover_tests(). Iconic, honestly.
This policy rolled out in CMake 3.31. Set it with cmake_policy() or cmake_minimum_required(). If you don't set it, CMake warns, and uses OLD behavior 🙈
⚠️ Reminder: OLD behavior is deprecated by definition and might get removed in a future CMake. Periodt.
📁 CMP0177
Added in version 3.31.
install() DESTINATION paths get normalized.
Okay so install() has a bunch of different forms, and most of them take a DESTINATION keyword — some of them in more than one place 👀 In CMake 3.30 and earlier, whatever you gave after DESTINATION was used exactly as you wrote it, zero transformations, no vibe check.
The install(EXPORT) form assumes the path has no .. or . path components when it computes a path relative to the DESTINATION. And if your project gave it a path that broke that assumption? The computed path came out straight-up incorrect 😭
CMake 3.31 normalizes all DESTINATION values in any form of install() — with one exception: the INCLUDES DESTINATION of the install(TARGETS) form. The normalization is the same one you get from the cmake_path() command (see Normalization 🦋).
OLD behavior: performs no translation on the DESTINATION values of any install() command. They're used exactly as provided. If a destination path has .. or . components, install(EXPORT) will use the same wrong paths as CMake 3.30 and earlier. Yeah. Same mess.
NEW behavior: normalizes all DESTINATION values except INCLUDES DESTINATION. And if a destination path contains a generator expression, it gets wrapped in a $<PATH:CMAKE_PATH,NORMALIZE,...> generator expression 🎀
This policy dropped in CMake 3.31. Set it via cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns you if it detects a path that would be different if normalized, and uses OLD behavior. BUT — if a destination path contains a generator expression, no warning is issued regardless of the value. Noted, bestie ✍️
⚠️ OLD behavior = deprecated by definition, could vanish in a future CMake.
🪟 CMP0176
Added in version 3.31.
execute_process() ENCODING defaults to UTF-8 now.
The ENCODING option only means anything on Windows, just so we're clear 💅 It specifies the character encoding expected in the process's output on stdout and stderr.
In CMake 3.14 and below, the default encoding was NONE, which corresponds to CMake's internal UTF-8 encoding. Then in CMake 3.15 through CMake 3.30, the default encoding was accidentally changed to AUTO — and the change went completely unnoticed and was never documented 😭 not that being undocumented stopped it from happening.
CMake 3.31 and above prefer the ENCODING default to be UTF-8. This policy is the compatibility shim for projects that may have been relying on the default being AUTO.
OLD behavior: execute_process() uses AUTO by default when no ENCODING is specified. NEW behavior: UTF-8 is the default ENCODING. Slay 🌈
This policy arrived in CMake 3.31. Set it with cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn, and uses OLD behavior 🫶
⚠️ OLD behavior is deprecated by definition and may be removed in a future CMake version.
🚫 CMP0175
Added in version 3.31.
add_custom_command() rejects invalid arguments.
CMake 3.30 and earlier would silently ignore unsupported keywords and missing-or-invalid arguments for the different forms of add_custom_command(). Like, sir, this is not the vibe 💀 CMake 3.31 implements way more rigorous argument checking and will flag invalid or missing arguments as errors.
OLD behavior: accepts the same invalid keywords or arguments as CMake 3.30 and earlier. NEW behavior: flags these as errors that previously went totally unreported:
- The
OUTPUTform does not acceptPRE_BUILD,PRE_LINK, orPOST_BUILDkeywords. - When the
APPENDkeyword is given, theOUTPUTform also does not acceptBYPRODUCTS,COMMAND_EXPAND_LISTS,DEPENDS_EXPLICIT_ONLY,DEPFILE,JOB_POOL,JOB_SERVER_AWARE,USES_TERMINAL, orVERBATIMkeywords. - The
TARGETform requires exactly one ofPRE_BUILD,PRE_LINK, orPOST_BUILDto be given. Previously, if none were given,POST_BUILDwas assumed — and if multiple keywords were given, the last one won 🙈 - The
TARGETform does not acceptDEPENDS,DEPENDS_EXPLICIT_ONLY,DEPFILE,IMPLICIT_DEPENDS,MAIN_DEPENDENCY,JOB_POOL, orJOB_SERVER_AWAREkeywords. - The
TARGETform now requires at least oneCOMMANDto be given. - If a keyword expects a value after it but no value is provided, that used to be treated as though the keyword wasn't given at all. Not anymore.
- The
COMMENTkeyword expects exactly one value after it. If multiple values are given, or ifCOMMENTis given more than once, that's an error.
This policy landed in CMake 3.31. Set it with cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior 🎀
⚠️ OLD behavior = deprecated by definition, may be removed in a future CMake version.
🫙 CMP0174
Added in version 3.31.
cmake_parse_arguments(PARSE_ARGV) defines a variable for an empty string after a single-value keyword.
Lowkey one of the main reasons to use the PARSE_ARGV form of cmake_parse_arguments() in the first place is to handle empty-value corner cases more robustly. The non-PARSE_ARGV form doesn't preserve empty arguments — but the PARSE_ARGV form does 💅 So for each single-value keyword given, a variable should be defined if the keyword is present, even if it's followed by an empty string.
Before CMake 3.31, no variable would be defined if the value after a single-value keyword was an empty string. Which meant your code literally couldn't tell the difference between "keyword wasn't given" and "keyword was given with an empty value" — unless you iterated over all the arguments and checked whether the keyword was there. Exhausting 😭
OLD behavior: cmake_parse_arguments(PARSE_ARGV) does not define a variable for a single-value keyword followed by an empty string, or followed by no value at all.
NEW behavior: cmake_parse_arguments(PARSE_ARGV) always defines a variable for each keyword given in the arguments — even a single-value keyword with an empty string as its value, or with no value at all. With the NEW behavior your code can robustly check whether a single-value keyword was given using just if(DEFINED <prefix>_<keyword>) ✨
This policy popped up in CMake 3.31. Set it with cmake_policy() or cmake_minimum_required(). Unset? CMake warns, and uses OLD behavior 🦋
⚠️ OLD behavior is deprecated by definition and may be removed in a future CMake version.
🧚 CMP0173
Added in version 3.31.
The CMakeFindFrameworks module is removed. Gone. Deleted. Not invited to the group chat anymore 💀
CMake's framework handling has evolved way beyond what the CMakeFindFrameworks module supports. The module has zero handling of XCFrameworks, it never even documented the one command it provides, and find_library() gives you superior capabilities in all respects. Like, in every way. It ate and left no crumbs 👑
OLD behavior: CMakeFindFrameworks keeps providing the undocumented cmake_find_frameworks() command. NEW behavior: halts with a fatal error if anything tries to include the module 🔥
This policy showed up in CMake 3.31. Set it with cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior 🍓
⚠️ OLD behavior is deprecated by definition and may be removed in a future CMake version. Fr fr.
🌸 CMP0172
Added in version 3.31.
The CPack module enables per-machine installation by default in the CPack WIX Generator.
The CPack WIX Generator's CPACK_WIX_INSTALL_SCOPE option controls the scope of the generated Windows Installer package. When CPACK_WIX_VERSION is set to 4 or higher, the default scope is perMachine. But — plot twist — when you're using WIX 3, the default scope is NONE, and CPack does not set any InstallScope in the package specification. The resulting installer requires administrative privileges and installs into the system-wide ProgramFiles directory, but the start menu entry and uninstaller registration are created only for the current user. 💅 (yes, that's a whole vibe of a mismatch, iykyk)
The CPack module in CMake 3.30 and older does not specify any CPACK_WIX_INSTALL_SCOPE value by default, so CPack uses no installation scope by default with WIX 3. CMake 3.31 and newer instead prefer to set CPACK_WIX_INSTALL_SCOPE to perMachine by default to make the behavior consistent across all WIX versions. This policy provides compatibility for projects that have not been updated to expect perMachine behavior. 🫶
The OLD behavior for this policy is to not set CPACK_WIX_INSTALL_SCOPE by default. The NEW behavior for this policy is to set CPACK_WIX_INSTALL_SCOPE to perMachine by default.
This policy was introduced in CMake version 3.31. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP<NNNN> variable to control the warning.
⚠️ Note, bestie: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. Like, don't get attached. 😭
CMP0171
Added in version 3.31.
codegen is a reserved target name. 👑
CMake 3.30 and earlier did not reserve codegen as a builtin target name, leaving projects free to create their own target with that name. CMake 3.31 and later prefer to reserve codegen as a builtin target name to drive custom commands created with the CODEGEN option to add_custom_command(). In order to support building the codegen target in scripted environments, e.g., cmake --build . --target codegen, the codegen target needs to be generated even if no custom commands use the CODEGEN option. This policy provides compatibility for projects that have not been updated to avoid creating a target named codegen. ✨
The OLD behavior of this policy allows projects to create a target with the name codegen. The NEW behavior halts with a fatal error if a target with the name codegen is created. 💀
This policy was introduced in CMake version 3.31. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns, and uses OLD behavior. (note the difference from the one above — this one does warn!)
⚠️ Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌈 Policies Introduced by CMake 3.30
CMP0170
Added in version 3.30.
When FETCHCONTENT_FULLY_DISCONNECTED is set to true, FetchContent_MakeAvailable() and FetchContent_Populate() enforce the constraint that their source directory must already be populated. The requirement has always been documented, but it was not checked or enforced with CMake 3.29 or older. This sometimes led to hard-to-trace errors when a project expected a dependency to have been populated, but its population was silently skipped. 🙈 Like, the most annoying kind of bug — the "where did it go" kind.
CMake 3.30 and above prefers to check and enforce the constraint. This policy provides compatibility for situations where the user cannot easily prevent FETCHCONTENT_FULLY_DISCONNECTED from being inappropriately set to true.
The OLD behavior of this policy allows FETCHCONTENT_FULLY_DISCONNECTED to be set to true even if a dependency's source directory has not been populated. The NEW behavior halts with a fatal error if FETCHCONTENT_FULLY_DISCONNECTED is set to true and a dependency population would be skipped, but that dependency's source directory doesn't exist. 🔥
This policy was introduced in CMake version 3.30. 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.
CMP0169
Added in version 3.30.
Calling FetchContent_Populate() with a single argument (the name of a declared dependency) is deprecated. 🫠
Prior to the introduction of FetchContent_MakeAvailable(), projects populated previously declared content (with FetchContent_Declare()) using the following pattern:
FetchContent_GetProperties(depname)
if(NOT depname_POPULATED)
FetchContent_Populate(depname)
add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR})
endif()
The above pattern does not support a number of features that have been added to FetchContent over time. It ignores options like SYSTEM and EXCLUDE_FROM_ALL which may be given to FetchContent_Declare(), but can't be made known to the above project code. It also does not support dependency providers. Projects should call FetchContent_MakeAvailable() instead of using the above pattern. 👑
CMake 3.30 and above prefers to reject calls to FetchContent_Populate() with the name of a declared dependency. This policy provides compatibility for projects that have not been updated to call FetchContent_MakeAvailable() instead.
The OLD behavior of this policy allows FetchContent_Populate() to be called with the name of a declared dependency. The NEW behavior halts with a fatal error in such cases. 💀
📌 Note: callingFetchContent_Populate()with the full population details as command arguments rather than just a dependency name remains fully supported. Only the form callingFetchContent_Populate()with a single argument (the name of a previously declared dependency) is deprecated with this policy. So breathe — the other form is fine.
This policy was introduced in CMake version 3.30. 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.
CMP0168
Added in version 3.30.
The FetchContent module implements steps directly instead of through a sub-build. 🚀
CMake 3.29 and below implement FetchContent as a separate sub-build. This required configuring that separate project and using a build tool. This approach can be very slow with some generators and operating systems. CMake 3.30 and above prefer to implement the download, update, and patch steps directly as part of the main project. slay, honestly
The NEW behavior has the following characteristics:
- No sub-build is used. All operations are implemented directly from the main project's CMake configure step. When running in CMake script mode, no build tool needs to be available.
- Generator expressions and GNU Make variables of the form
$(SOMEVAR)are not supported. They should not be used in any argument toFetchContent_Declare()orFetchContent_Populate(). - All
LOG_...andUSES_TERMINAL_...options, theQUIEToption, and theFETCHCONTENT_QUIETvariable are ignored.FetchContentoutput is always part of the main project's configure output. This also means it now respects the message logging level (seeCMAKE_MESSAGE_LOG_LEVELand--log-level). The default message log level should be comparable to usingQUIETwith theOLDpolicy setting, except that warnings will now be shown. 👀 - The
PREFIX,TMP_DIR,STAMP_DIR,LOG_DIR, andDOWNLOAD_DIRoptions and their associated directory properties are ignored. TheFetchContentmodule controls those locations internally. cmake --freshwill remove the stamp and script files used for tracking and populating the dependency. This will force the dependency's download, update, and patch steps to be re-executed. The directory used for downloads is not affected bycmake --fresh, so any previously downloaded files for theURLdownload method can still be reused. 🎀
The OLD behavior has the following characteristics:
- A sub-build is always used to implement the download, update, and patch steps. A build tool must be available, even when using
FetchContent_Populate()in CMake script mode. - Generator expressions and GNU Make variables of the form
$(SOMEVAR)can be used, although such use is almost always inappropriate. They are evaluated in the sub-build, so they do not see any information from the main build. - All logging, terminal control, and directory options related to the download, update, or patch steps are supported.
- If the
QUIEToption is used, or theFETCHCONTENT_QUIETvariable is set totrue, warnings will not be shown in the output. cmake --freshhas no effect on the dependency's stamp or script files. Previously executed steps will only re-run if details about the dependency have changed. 😬
No cap, there's a pretty good chance your users can just set the CMAKE_POLICY_DEFAULT_CMP0168 variable to NEW and globally flip everything to the NEW behavior while they wait for the project and all its dependencies to catch up and use the NEW policy setting by default. Like, projects don't typically touch the features that NEW behavior no longer supports, and even the ones that do will usually still work fine when those options are ignored. But bestie, before you go setting this globally, check whether any FetchContent_Declare() or FetchContent_Populate() calls use the ignored options in a way that would legit change observable behavior — anything other than putting temporary or internally-generated files in different locations. 👀
This policy was introduced in CMake version 3.30. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. Periodt.
🦋 CMP0167
Added in version 3.30.
The FindBoost module is removed. Yes, gone. 💀
CMake 3.29 and below provide a FindBoost module, but honestly it needs constant updates to keep up with upstream Boost releases. Upstream Boost 1.70 and above provide a BoostConfig.cmake package configuration file, so find_package(Boost CONFIG) finds the upstream package directly, without the find module. Slay.
CMake 3.30 and above prefer to not provide the FindBoost module, so that find_package(Boost) calls — the ones without the CONFIG or NO_MODULE options — find the upstream BoostConfig.cmake directly. This policy provides compatibility for projects that have not been ported to use the upstream Boost package. 🫶
The OLD behavior of this policy is for find_package(Boost) to load CMake's FindBoost module. The NEW behavior is for find_package(Boost) to search for the upstream BoostConfig.cmake.
This policy was introduced in CMake version 3.30. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
💅 CMP0166
Added in version 3.30.
TARGET_PROPERTY evaluates link properties transitively over private dependencies of static libraries. iykyk ✨
In CMake 3.29 and below, the TARGET_PROPERTY generator expression evaluates properties INTERFACE_LINK_OPTIONS, INTERFACE_LINK_DIRECTORIES, and INTERFACE_LINK_DEPENDS as if they were Transitive Compile Properties rather than Transitive Link Properties — even when policy CMP0099 is set to NEW. Private dependencies of static libraries, which appear in their INTERFACE_LINK_LIBRARIES guarded by LINK_ONLY generator expressions, are not followed. Which is, lowkey, inconsistent with evaluation of the same target properties during buildsystem generation. 😭
CMake 3.30 and above prefer that TARGET_PROPERTY evaluates properties INTERFACE_LINK_OPTIONS, INTERFACE_LINK_DIRECTORIES, and INTERFACE_LINK_DEPENDS as Transitive Link Properties, such that private dependencies of static libraries, which appear in their INTERFACE_LINK_LIBRARIES guarded by LINK_ONLY generator expressions, are followed. This policy provides compatibility for projects that have not been updated to expect the new behavior.
The OLD behavior for this policy is for TARGET_PROPERTY to evaluate properties INTERFACE_LINK_OPTIONS, INTERFACE_LINK_DIRECTORIES, and INTERFACE_LINK_DEPENDS as if they were Transitive Compile Properties by not following private dependencies of static libraries. The NEW behavior for this policy is to evaluate them as Transitive Link Properties by following private dependencies of static libraries. 🌈
This policy was introduced in CMake version 3.30. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🧚 CMP0165
Added in version 3.30.
enable_language() must not be called before project(). Read that again. 🫣
In CMake 3.29 and below, if a project called enable_language() before the first call to project(), the language would be enabled but possibly using unset details that were expected to be set. Like, main character energy but the supporting cast never showed up. In CMake 3.30 and above, enable_language() prefers to reject this case and stop with a fatal error instead, if it detects that project() has not yet been called. This policy provides compatibility for projects that happened to work when enable_language() was called before project() and have not been updated to call these commands in the required order.
The OLD behavior for this policy is to allow enable_language() to be called before project(). The NEW behavior for this policy is to fail with a fatal error in such cases. 💀
This policy was introduced in CMake version 3.30. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🍓 CMP0164
Added in version 3.30.
add_library() rejects SHARED libraries when the platform doesn't support them. Yeah, it actually says no now.
In CMake 3.29 and below, on platforms that do not support shared libraries (TARGET_SUPPORTS_SHARED_LIBS is false), the add_library() command automatically converts SHARED libraries to STATIC libraries to help users build projects on such platforms. Cute in theory! But the semantics of shared and static libraries are different enough that such automatic conversion cannot work in general. Projects using shared libraries need to be ported to such platforms on a case-by-case basis. 😮💨
In CMake 3.30 and above, add_library() prefers to reject creation of shared libraries on platforms that do not support them, and fail with a fatal error message. This policy provides compatibility for projects that happened to work with the automatic conversion to static libraries and have not been updated with an explicit port.
The OLD behavior for this policy is to implicitly create a static library with a developer warning. The NEW behavior for this policy is to fail. Periodt. 🔥
This policy was introduced in CMake version 3.30. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn about the behavior change, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌸 CMP0163
Added in version 3.30.
The GENERATED source file property is now visible in all directories. Scope? Never heard of her. 💅
In CMake 3.29 and below, the GENERATED source file property, like other source file properties, was scoped in every directory separately. Although policy CMP0118 allowed sources marked GENERATED in one directory to be used in other directories without manually marking them as GENERATED again, the GENERATED property was still not visible to get_property() and get_source_file_property() calls. Sneaky.
Whether or not a source file is generated is an all-or-nothing global property of the source: a source is either generated or it is not. No in-between, no vibe check needed. CMake 3.30 and above prefer to treat the GENERATED source file property as globally scoped. Once it is set in one directory, it is immediately visible to get_property() and get_source_file_property() calls in other directories. This policy provides compatibility for projects that have not been updated for this behavior. ✨
The OLD behavior of this policy is for the GENERATED source file property to be visible only in the directories in which it is set. The NEW behavior of this policy is to allow the GENERATED source file property to be visible in all directories once set in any directory. Furthermore — and this is the part people miss — the NEW behavior of this policy implies the NEW behavior of policy CMP0118: the GENERATED property may be set only to boolean values, and may not be turned off once turned on. Once it's on, it's on. Iconic.
This policy was introduced in CMake version 3.30. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn, and uses OLD behavior.
⚠️ The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🎀 CMP0162
Added in version 3.30.
Visual Studio Generators add UseDebugLibraries indicators by default.
The "Use Debug Libraries" setting in Visual Studio projects is basically the thing that tells VS which configs count as debug configs. In standalone projects, this can lowkey affect MSBuild's default pick for the MSVC runtime library, optimization flags, runtime checks, and similar settings. CMake usually generates all those settings explicitly based on what the project says it wants, so CMake 3.29 and below do not write any UseDebugLibraries indicators to .vcxproj files.
CMake 3.30 and above prefer to write UseDebugLibraries indicators, because they're genuinely useful for both humans and tools to reference, and they may also affect the behavior of platform-specific SDKs. The indicator for each configuration of a target gets determined like this:
- If the target compiles sources for a known MSVC runtime library (like the one specified by
MSVC_RUNTIME_LIBRARY), thenUseDebugLibrariesis true for configurations that compile for a"Debug"runtime library, and false for the others. - Otherwise — like in targets created by
add_custom_target()—UseDebugLibrariesis true for theDebugconfiguration, and false for the others.
This policy is basically a compatibility blanket for projects that haven't been updated to expect the indicators yet. The policy setting gets recorded by each target as it's created, and it's used to decide the default behavior for that target's .vcxproj file.
The OLD behavior for this policy is to not generate UseDebugLibraries indicators by default. The NEW behavior for this policy is to generate UseDebugLibraries indicators by default.
If the CMAKE_VS_USE_DEBUG_LIBRARIES variable and/or the VS_USE_DEBUG_LIBRARIES target property is set, it explicitly controls UseDebugLibraries generation regardless of this policy. So like, it overrides, no cap.
This policy was introduced in CMake version 3.30. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
🌸 Policies Introduced by CMake 3.29 🌸
🧚 CMP0161
Added in version 3.29.
The CPACK_PRODUCTBUILD_DOMAINS variable defaults to true. Iconic.
Before CMake 3.29, the CPACK_PRODUCTBUILD_DOMAINS variable was unset by default. When you're using the CPack productbuild Generator, that disables the use of the domains attribute in the productbuild Distribution XML, and falls back to the auth attribute instead. These attributes control where a productbuild package is allowed to be installed. But plot twist: the auth attribute has been deprecated by Apple, so projects should migrate to using domains instead.
CMake 3.29 and above prefer to use a default value of true for CPACK_PRODUCTBUILD_DOMAINS, which means domains will be used by default unless the project explicitly sets CPACK_PRODUCTBUILD_DOMAINS to false. This policy provides compatibility with projects that enabled the CPack productbuild Generator, but did not explicitly set CPACK_PRODUCTBUILD_DOMAINS.
The OLD behavior for this policy is to leave CPACK_PRODUCTBUILD_DOMAINS unset if it hasn't been set. The NEW behavior for this policy is to use a default value of true for CPACK_PRODUCTBUILD_DOMAINS.
This policy was introduced in CMake version 3.29. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns, and uses OLD behavior.
Heads up: a warning will only be emitted if the CPACK_BINARY_PRODUCTBUILD variable is set to true and the project is being built for an Apple platform.
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🦋 CMP0160
Added in version 3.29.
More read-only target properties now error out when you try to set them. Like, they said what they said. 🚫
The set_target_properties() and set_property() commands are intended to error out on all read-only properties. However, CMake 3.28 and below only did this for the following properties:
HEADER_SETSINTERFACE_HEADER_SETSIMPORTED_GLOBALMANUALLY_ADDED_DEPENDENCIESNAMETYPE
This policy enforces the read-only nature of the following target properties:
ALIAS_GLOBALBINARY_DIRCXX_MODULE_SETSIMPORTEDINTERFACE_CXX_MODULE_SETSLOCATIONLOCATION_<CONFIG>SOURCE_DIR
The OLD behavior for this policy is to only error out for the properties MANUALLY_ADDED_DEPENDENCIES, NAME, and TYPE. The NEW behavior for this policy is to error out on all target properties that are documented as read-only.
This policy was introduced in CMake version 3.29. 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.
🎀 CMP0159
Added in version 3.29.
file(STRINGS) with REGEX updates CMAKE_MATCH_<n>. Big glow-up energy.
In CMake 3.28 and below, the file(STRINGS) command's REGEX option does not affect CMAKE_MATCH_<n> variables. CMake 3.29 and above prefer to update the CMAKE_MATCH_<n> variables using captures from the last match in the file, similar to the string(REGEX MATCHALL) command. This policy provides compatibility for projects that have not been updated to expect the behavior.
The OLD behavior for this policy is for file(STRINGS) with REGEX to not store capture groups in CMAKE_MATCH_<n> variables. The NEW behavior is to store the capture groups.
This policy was introduced in CMake version 3.29. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
💅 CMP0158
Added in version 3.29.
add_test() honors CMAKE_CROSSCOMPILING_EMULATOR only when cross-compiling. Periodt.
In CMake 3.28 and below, add_test() unconditionally used the CROSSCOMPILING_EMULATOR target property (initialized by the CMAKE_CROSSCOMPILING_EMULATOR variable) to run test commands naming executable targets. CMake 3.29 and above prefer to use the emulator only when the CMAKE_CROSSCOMPILING variable is enabled. The CMAKE_TEST_LAUNCHER variable may be used instead when not cross-compiling. This policy provides compatibility for projects that have not been updated.
The OLD behavior for this policy is for add_test() to use the CROSSCOMPILING_EMULATOR target property unconditionally. The NEW behavior for this policy is for add_test() to use the CROSSCOMPILING_EMULATOR target property only when cross-compiling.
This policy was introduced in CMake version 3.29. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
⭐ CMP0157
Added in version 3.29.
Swift compilation mode is selected by an abstraction. Cute, right? 🍓
The Swift compiler can compile modules in different modes. The desired build mode depends on whether the developer is iterating and wants to incrementally make changes, or if they're building a release for distribution and want more optimizations applied to the resulting binary.
CMake versions 3.26 through 3.28 build Swift binaries with whole-module optimizations enabled when configured in a non-debug build type. For CMake versions earlier than 3.26, the developer needs to specify the necessary flag manually for the Ninja Generators, and cannot not specify whole-module optimizations to the Xcode generator.
CMake versions 3.29 and above prefer to set the compilation mode using the Swift_COMPILATION_MODE target property, which can be initialized by the CMAKE_Swift_COMPILATION_MODE variable.
This policy provides compatibility for projects that have not been updated. The policy setting takes effect as of the first project() or enable_language() command that enables the Swift language.
Note: once the policy has taken effect at the top of a project, that choice must be used throughout the tree. In projects that have nested projects in subdirectories, be sure to convert everything together. Don't leave half your tree in the old vibe, bestie. 😭
The OLD behavior for this policy builds all Swift targets in wholemodule mode for non-debug configurations. Ninja Generators prepend the -wmo flag to the default set of Swift flags. The Xcode generator sets the SWIFT_COMPILATION_MODE attribute to wholemodule in the generated Xcode project file.
…and the NEW behavior for this policy is to apply the compilation mode that's sitting in the Swift_COMPILATION_MODE target property — and that property gets initialized as each target is created, straight from the CMAKE_Swift_COMPILATION_MODE variable. ✨ Clean, right?
This policy was introduced in CMake version 3.29. You can set it with cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn — it just quietly uses OLD behavior. 🙈
Heads up bestie: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. Not a drill. 💀
CMP0156
Added in version 3.29. 🎀
De-duplicate libraries on link lines based on linker capabilities.
Okay so this one is a whole vibe about linkers, and you need the lore. Traditional linkers keep a set of undefined symbols while linking. The linker walks each file in the order it shows up on the command line, and keeps going until that set of undefined symbols goes empty. When it hits an object file, that object gets linked into the output object, and its undefined symbols get tossed into the set. When it hits an archive file, a traditional linker searches the objects inside it and processes the ones that satisfy symbols in the unresolved set. 🧚
Handling mutually dependent archives can be awkward with a traditional linker, ngl — archive files may have to be specified multiple times. 😭
Some linkers (for instance Apple or Windows linkers, as well as LLVM LLD) record all the symbols found in objects and archives as they iterate over the command line arguments. When one of these linkers hits an undefined symbol that can be resolved by an object file inside a previously processed archive file, it immediately extracts and links it into the output object. Iconic behavior, honestly. 👑
CMake 3.28 and below may generate link lines that repeat static libraries the way a traditional linker would need, even when you're using a linker that does not need it. They may also de-duplicate shared libraries by keeping their last occurrence — which on Windows platforms can change DLL load order. 🫠
CMake 3.29 and above prefer to apply different strategies based on linker capabilities. So when you're targeting Apple and Windows platforms, all libraries are de-duplicated. And on Windows platforms, libraries are de-duplicated by keeping their first occurrence, which respects the project-specified order. This policy is literally just here for compatibility with projects that haven't been updated to expect that latter behavior.
Note bestie: when this policy is set to NEW, the policy CMP0179 controls which occurrence of the static libraries is kept. iykyk 🌸
The OLD behavior for this policy is to always repeat static libraries as if using a traditional linker, and to always de-duplicate shared libraries by keeping the last occurrence of each. The NEW behavior for this policy is to apply different strategies based on linker capabilities. 💅
This policy was introduced in CMake version 3.29. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 🚨
🦋 Policies Introduced by CMake 3.28 🦋
CMP0155
Added in version 3.28. ⭐
C++ sources in targets with at least C++20 are scanned for imports when supported.
CMake 3.27 and below just assume that C++ sources do not import modules. CMake 3.28 and above prefer to assume that C++ sources in targets using C++20 or higher might import modules, and must be scanned before compiling — unless you explicitly disable it. This policy is the compatibility blanket for projects using C++20 or higher, without modules, that haven't been updated to turn off scanning, e.g. via the CMAKE_CXX_SCAN_FOR_MODULES variable. Peep the cmake-cxxmodules(7) manual for more deets on C++ module support. 📚
The OLD behavior for this policy is to assume that C++ 20 and newer sources do not import modules. The NEW behavior for this policy is to assume that C++ 20 and newer files may import modules if the compiler understands how to scan for their dependencies, and need to be scanned. 🔥
This policy was introduced in CMake version 3.28. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 💀
CMP0154
Added in version 3.28. 🍓
Generated files are private by default in targets using File Sets.
CMake 3.27 and below assume that any file generated as an output or byproduct of add_custom_command() or add_custom_target() may be a public header file meant for inclusion by dependents' source files. Which means Ninja Generators have to add conservative order-only dependencies that stop a target's source files from compiling before custom commands from the target's dependencies are finished — even if those custom commands only produce sources private to their own target. The audacity of the old assumption, honestly. 😭
File Sets, introduced by CMake 3.23, give you a way to express the visibility of generated header files. CMake 3.28 and above prefer to assume that, in targets using file sets, generated files are private to their own target by default. Generated public headers must be specified as members of a PUBLIC (or INTERFACE) FILE_SET, typically of type HEADERS. With that info, Ninja Generators may omit the conservative dependencies mentioned above and produce more efficient build graphs. Dependents of such targets may also prune dependencies to those targets when using the OPTIMIZE_DEPENDENCIES target property. Efficiency! We love her. 💅
Additionally, if the custom command's output is a member of a file set of type CXX_MODULES, it will additionally not be required to exist before compiling other sources in the same target. Since these files should not be included at compile time directly, they may not be implicitly required to exist for other compilation rules. ✨
This policy provides compatibility for projects using file sets in targets with generated header files that haven't been updated. Those projects should be updated to express generated public headers in a file set. For example:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
...
)
target_sources(foo
PUBLIC FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR}
FILES ${CMAKE_CURRENT_BINARY_DIR}/foo.h
)
The OLD behavior for this policy is to assume generated files are public, even in targets using file sets, and for Ninja Generators to produce conservative build graphs. The NEW behavior for this policy is to assume generated files are private in targets using file sets, and for Ninja Generators to produce more efficient build graphs. 🌈
This policy was introduced in CMake version 3.28. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 🚨
CMP0153
Added in version 3.28. 🎀
The exec_program() command should not be called.
This command has long been superseded by the execute_process() command, and it's been deprecated since CMake 3.0. CMake >= 3.28 prefers that this command never be called, periodt. 🫶
The OLD behavior for this policy is to allow the command to be called. The NEW behavior for this policy is to issue a FATAL_ERROR when the command is called. Oop — it's a hard stop bestie. 💀
This policy was introduced in CMake version 3.28. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns, and uses OLD behavior. (Yep, this one's chatty — it does warn.)
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 🙈
CMP0152
Added in version 3.28. 🌸
file(REAL_PATH) resolves symlinks before collapsing ../ components.
In CMake 3.27 and below, file(REAL_PATH) collapsed any ../ components in a path before resolving symlinks. Which produced incorrect results when that ../ collapsed away a symlink. Not the slay we thought it was. 😭
The OLD behavior for this policy is to collapse ../ components before resolving symlinks. The NEW behavior for this policy is to resolve all symlinks before collapsing ../ components. Order matters, always. ✨
This policy was introduced in CMake version 3.28. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns, and uses OLD behavior.
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 💅
🧚 Policies Introduced by CMake 3.27 🧚
CMP0151
Added in version 3.27. 💜
AUTOMOC include directory is a system include directory by default.
Headers generated for AUTOMOC are placed in target-specific include directories. CMake 3.26 and older added these as normal include directories. CMake 3.27 and newer prefer to add them as system include directories. This policy provides compatibility for projects that haven't been updated to expect that. 👑
If the AUTOGEN_USE_SYSTEM_INCLUDE target property is set — maybe via the CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE variable — then its value is used regardless of the setting of this policy. It gets the final say, fr fr. 🫶
The OLD behavior for this policy is to add autogen include directory to the target's include directories. The NEW behavior for this policy is to add autogen include directory to the target's system include directories. ⭐
This policy was introduced in CMake version 3.27. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 🚨
💖 quick lore drop before we keep going: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. no cap, don't build your whole personality on it. 🙈
🌈 CMP0150
Added in version 3.27.
ExternalProject_Add() and FetchContent_Declare() treat relative GIT_REPOSITORY paths as being relative to the parent project's remote. 💅
Earlier versions of these commands always treated relative paths in GIT_REPOSITORY as local paths, but the base directory it was treated as relative to was both undocumented and unintuitive. 😭 The OLD behavior for this policy is to interpret relative paths used for GIT_REPOSITORY as local paths relative to the following:
- The parent directory of
SOURCE_DIRforExternalProject_Add(). FETCHCONTENT_BASE_DIRforFetchContent_Declare().
The NEW behavior is to determine the remote from the parent project and interpret the path relative to that remote. The value of CMAKE_CURRENT_SOURCE_DIR when ExternalProject_Add() or FetchContent_Declare() is called determines the parent project. The remote is selected according to the following (first match is used, and yes it goes in order):
- If the parent project is checked out on a branch with an upstream remote defined, use that remote.
- If only one remote is defined, use that remote.
- If multiple remotes are defined and one of them is named
origin, useorigin's remote but also issue a warning.
If an appropriate remote cannot be determined from the above, a fatal error will be raised. 💀 not optional, bestie.
This policy was introduced in CMake version 3.27. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns when a relative path is encountered, 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.
🦋 CMP0149
Added in version 3.27.
Visual Studio Generators select the latest Windows SDK by default. 👑
Visual Studio Generators select a Windows SDK version to put in the WindowsTargetPlatformVersion setting in .vcxproj files. CMake sets the CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION variable to the selected SDK version.
Prior to CMake 3.27, the SDK version was always selected by the value of the CMAKE_SYSTEM_VERSION variable. Users or toolchain files could set that variable to one of the exact Windows SDK versions available on the host system. Since CMAKE_SYSTEM_VERSION defaults to CMAKE_HOST_SYSTEM_VERSION, and it is not guaranteed that a matching Windows SDK version is available, CMake had to fall back to using the latest Windows SDK version if no exact match was available. This approach was problematic, and honestly it's giving chaos:
- The latest Windows SDK might or might not be selected based on whether the host version of Windows happens to match an available SDK version. 🎲
- An old Windows SDK version might be selected that has not been updated for newer language standards such as C11. 💀
CMake 3.27 and higher prefer to ignore the exact value of CMAKE_SYSTEM_VERSION and by default select the latest SDK version available. An exact SDK version may be specified explicitly using a version= field in the CMAKE_GENERATOR_PLATFORM variable. See Visual Studio Platform Selection.
This policy provides compatibility for projects, toolchain files, and build scripts that have not been ported away from using CMAKE_SYSTEM_VERSION to specify an exact SDK version.
⚠️ Note: this policy must be set before the firstproject()orenable_language()command invocation at the top of the project. That is when Visual Studio Generators select a Windows SDK. timing is literally everything, bestie. ⏰
The OLD behavior for this policy is to use the exact value of CMAKE_SYSTEM_VERSION if possible. The NEW behavior for this policy is to ignore it.
This policy was introduced in CMake version 3.27. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
🎀 CMP0148
Added in version 3.27.
The FindPythonInterp and FindPythonLibs modules are removed. bye bestie 👋
These modules have been deprecated since CMake 3.12. CMake 3.27 and above prefer to not provide the modules. This policy provides compatibility for projects that have not been ported away from them.
Projects using the FindPythonInterp and/or FindPythonLibs modules should be updated to use one of their replacements:
FindPython3FindPython2FindPython
The OLD behavior of this policy is for find_package(PythonInterp) and find_package(PythonLibs) to load the deprecated modules. The NEW behavior is for uses of the modules to fail as if they do not exist.
This policy was introduced in CMake version 3.27. 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.
🔥 CMP0147
Added in version 3.27.
Visual Studio Generators build custom commands in parallel. ⚡
Visual Studio 15.8 (2017) and newer support building custom commands in parallel. CMake 3.27 and above prefer to enable this behavior by adding a BuildInParallel setting to custom commands in .vcxproj files. This policy provides compatibility for projects that have not been updated to expect this, e.g., because their custom commands were accidentally relying on serial execution by MSBuild. 😭 (it happens to the best of us). To control this behavior in a more precise way, refer to VS_CUSTOM_COMMAND_DISABLE_PARALLEL_BUILD.
The OLD behavior for this policy is to not add BuildInParallel. The NEW behavior for this policy is to add BuildInParallel for VS 15.8 and newer.
This policy was introduced in CMake version 3.27. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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.
💜 CMP0146
Added in version 3.27.
The FindCUDA module is removed. 🫡
The FindCUDA module has been deprecated since CMake 3.10. CMake 3.27 and above prefer to not provide the module. This policy provides compatibility for projects that have not been ported away from it.
Projects using the FindCUDA module should be updated to use CMake's first-class CUDA language support. List CUDA among the languages named in the top-level call to the project() command, or call the enable_language() command with CUDA. Then one can add CUDA (.cu) sources directly to targets, similar to other languages. it's giving main character energy, honestly ✨
The OLD behavior of this policy is for find_package(CUDA) to load the deprecated module. The NEW behavior is for uses of the module to fail as if it does not exist.
This policy was introduced in CMake version 3.27. 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.
🌸 CMP0145
Added in version 3.27.
The Dart and FindDart modules are removed. 🪦
These modules were added very early in CMake's development to support driving tests with a "DART" tool, but DART has not been distributed or maintained for many years. Projects would include(Dart) to use it, and the Dart module would run find_package(Dart) internally. Since ctest(1) was created, the Dart module has just been a compatibility shim that finds Dart to support some legacy functionality and then forwards to the CTest module.
CMake 3.27 and above prefer to not provide the Dart or FindDart modules. This policy provides compatibility for projects that have not been ported away from them. Projects using the Dart module should be updated to use the CTest module directly.
The OLD behavior of this policy is for include(Dart) and find_package(Dart) to load the deprecated modules. The NEW behavior is for uses of the modules to fail as if they do not exist.
This policy was introduced in CMake version 3.27. 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.
🧚 CMP0144
Added in version 3.27.
find_package() uses upper-case <PACKAGENAME>_ROOT variables.
In CMake 3.27 and above, the find_package(<PackageName>) command now searches prefixes that are specified by the upper-case <PACKAGENAME>_ROOT CMake variable and the <PACKAGENAME>_ROOT environment variable — on top of the case-preserved <PackageName>_ROOT and <PackageName>_ROOT variables that have been used ever since policy CMP0074. This policy exists to keep compatibility with projects that haven't been updated and were maybe using <PACKAGENAME>_ROOT variables for something else entirely 💀.
The OLD behavior for this policy is to ignore <PACKAGENAME>_ROOT variables when the original <PackageName> has lower-case characters. The NEW behavior for this policy is to use <PACKAGENAME>_ROOT variables. Slay 💅.
This policy was introduced in CMake version 3.27. 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. No cap, it's on the way out 🫶.
✨ Policies Introduced by CMake 3.26 ✨
🦋 CMP0143
Added in version 3.26.
The USE_FOLDERS global property is treated as ON by default 👑.
When you're on CMake 3.25 or earlier, USE_FOLDERS is treated as OFF by default unless projects enable the feature themselves. Like, for example:
cmake_minimum_required(VERSION 3.25)
project(foobar LANGUAGES CXX)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
CMake 3.26 and later prefer to enable the feature by default. It's giving "we upgraded so you don't have to" ✨.
Note that it's the policy setting at the end of the top level CMakeLists.txt file that matters. The policy setting applies globally to the whole project. Like, the whole entire project, bestie 🌍.
This policy provides compatibility with projects that have not been updated to expect enabling of folders. Enabling folders causes projects to appear differently in IDEs. Yeah, your IDE is gonna look different, that's the whole point 💅.
This policy was introduced in CMake version 3.26. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 💀.
🌸 Policies Introduced by CMake 3.25 🌸
🎀 CMP0142
Added in version 3.25.
The Xcode generator does not append per-config suffixes to library search paths.
In CMake 3.24 and below, the Xcode generator preceded each entry of a library search path with a copy of itself appended with $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME). That was left over from very early versions of CMake where per-config directories weren't modeled well. Lowkey ancient lore 📜. Such paths often don't even exist, which results in warnings from the toolchain — annoying 😭. CMake 3.25 and above prefer to not add such library search paths. This policy provides compatibility for projects that may have been accidentally relying on the old behavior (oops 🙈).
The OLD behavior for this policy is to append $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to all library search paths. The NEW behavior is to not modify library search paths. Periodt.
This policy was introduced in CMake version 3.25. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 💜.
🧚 CMP0141
Added in version 3.25.
MSVC debug information format flags are selected by an abstraction. Fancy ✨.
Compilers targeting the MSVC ABI have flags to select the debug information format. Debug information format selection typically varies with build configuration.
In CMake 3.24 and below, debug information format flags are added to the default CMAKE_<LANG>_FLAGS_<CONFIG> cache entries by CMake automatically. This allows users to edit their cache entries to adjust the flags. However, the presence of such default flags is problematic for projects that want to choose a different debug information format programmatically. In particular, it requires string editing of the CMAKE_<LANG>_FLAGS_<CONFIG> variables with knowledge of the CMake builtin defaults so they can be replaced. It's giving "manual string surgery" 🔪.
CMake 3.25 and above prefer to leave the debug information format flags out of the default CMAKE_<LANG>_FLAGS_<CONFIG> values and instead offer a first-class abstraction 👑. The CMAKE_MSVC_DEBUG_INFORMATION_FORMAT variable and MSVC_DEBUG_INFORMATION_FORMAT target property may be set to select the MSVC debug information format. If they are not set, CMake enables debug information in debug configurations using the default value $<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>, if supported by the compiler, and otherwise $<$<CONFIG:Debug,RelWithDebInfo>:Embedded>.
This policy provides compatibility with projects that have not been updated to be aware of the abstraction. The policy setting takes effect as of the first project() or enable_language() command that enables a language whose compiler targets the MSVC ABI.
Note: Once the policy has taken effect at the top of a project, that choice will be used throughout the tree. In projects that have nested projects in subdirectories, be sure to confirm if everything is working with the selected policy behavior. Like, seriously, double-check that nested situation bestie 🫶.
The OLD behavior for this policy is to place MSVC debug information format flags in the default CMAKE_<LANG>_FLAGS_<CONFIG> cache entries and ignore the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT abstraction. The NEW behavior for this policy is to not place MSVC debug information format flags in the default cache entries and use the abstraction instead 💅.
This policy was introduced in CMake version 3.25. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 🌈.
⭐ CMP0140
Added in version 3.25.
The return() command checks its parameters. Yes, it's finally doing a vibe check on its own arguments ✨.
The OLD behavior for this policy is to ignore any parameters given to the command. The NEW behavior is to check the validity of the parameters.
This policy was introduced in CMake version 3.25. 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 💀.
🦋 Policies Introduced by CMake 3.24 🦋
💖 CMP0139
Added in version 3.24.
The if() command supports path comparisons using the PATH_EQUAL operator.
The OLD behavior for this policy is to ignore the PATH_EQUAL operator. The NEW behavior is to interpret the PATH_EQUAL operator. It literally just... works now 💅.
This policy was introduced in CMake version 3.24. 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 🌸.
🍓 CMP0138
Added in version 3.24.
CheckIPOSupported uses flags from the calling project.
The CheckIPOSupported module's check_ipo_supported() command compiles a test project to determine whether the toolchain supports INTERPROCEDURAL_OPTIMIZATION. CMake 3.23 and below run the check with the default values of the CMAKE_<LANG>_FLAGS and CMAKE_<LANG>_FLAGS_<CONFIG> variables for the current environment and toolchain settings. However, some projects may modify these flag variables to add flags that affect availability of the toolchain's IPO features. CMake 3.24 and above prefer to honor the calling project's values for these variables 💜. This policy provides compatibility for projects that have not been updated to expect this behavior.
The OLD behavior for this policy is to ignore the calling project's values of CMAKE_<LANG>_FLAGS and CMAKE_<LANG>_FLAGS_<CONFIG>. The NEW behavior for this policy is to use the values of those variables as compiler flags in the test project 👑.
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 💀.
🎀 CMP0137
Added in version 3.24.
try_compile() passes platform variables in project mode.
The try_compile() command source file signature propagates CMake variables containing platform settings, and those specified by the CMAKE_TRY_COMPILE_PLATFORM_VARIABLES variable, into the generated test project. This helps the test project drive the toolchain the same way the calling project will. In CMake 3.23 and below, the whole-project signature does not propagate platform variables automatically. CMake 3.24 and above prefer to propagate platform variables in the whole-project signature ✨. This policy provides compatibility with projects that have not been updated to expect the behavior.
The OLD behavior for this policy is to not pass any additional variables to the whole-project <#try-compiling-whole-projects> signature. The NEW behavior for this policy is to pass the same variables that the source file <#try-compiling-source-files> signature does.
Regardless of the policy setting, the CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES <#variable:CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES> variable may be set to suppress passing the platform variables through either signature. So like, you can always just shut the whole thing off if you want, no policy drama needed 💅
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake. Like, it's on the way out bestie, don't get attached 😭
CMP0136 🫶
Added in version 3.24.
Watcom runtime library flags are selected by an abstraction.
So compilers that target the Watcom ABI have these flags that pick the Watcom runtime library, right? Okay so here's the tea:
In CMake 3.23 and below, Watcom runtime library selection flags get added into the default CMAKE_<LANG>_FLAGS_<CONFIG> <#variable:CMAKE_<LANG>_FLAGS_<CONFIG>> cache entries by CMake, automatically, on its own. Which sounds chill — it lets users edit their cache entries to tweak the flags. But. The presence of those default flags is genuinely problematic for projects that want to choose a different runtime library programmatically. Specifically, it requires string editing of the CMAKE_<LANG>_FLAGS_<CONFIG> <#variable:CMAKE_<LANG>_FLAGS_<CONFIG>> variables with knowledge of the CMake builtin defaults so they can be replaced. Yeah. Gross. 🙈
CMake 3.24 and above would much rather leave the Watcom runtime library selection flags out of the default CMAKE_<LANG>_FLAGS_<CONFIG> <#variable:CMAKE_<LANG>_FLAGS_<CONFIG>> values and instead offer a first-class abstraction. The CMAKE_WATCOM_RUNTIME_LIBRARY <#variable:CMAKE_WATCOM_RUNTIME_LIBRARY> variable and the WATCOM_RUNTIME_LIBRARY <#prop_tgt:WATCOM_RUNTIME_LIBRARY> target property may be set to select the Watcom runtime library. If they're not set then CMake uses the default value MultiThreadedDLL on Windows and SingleThreaded on other platforms — which is equivalent to the original flags, so no cap, nothing changes if you don't touch it ✨
This policy provides compatibility with projects that haven't been updated to be aware of the abstraction. The policy setting takes effect as of the first project() <#command:project> or enable_language() <#command:enable_language> command that enables a language whose compiler targets the Watcom ABI.
Note: once the policy has taken effect at the top of a project, that choice must be used throughout the tree. In projects that have nested projects in subdirectories, be sure to convert everything together. No mixing, bestie — that's the whole vibe check 🚨
The OLD behavior for this policy is to place Watcom runtime library flags in the default CMAKE_<LANG>_FLAGS_<CONFIG> <#variable:CMAKE_<LANG>_FLAGS_<CONFIG>> cache entries and ignore the CMAKE_WATCOM_RUNTIME_LIBRARY <#variable:CMAKE_WATCOM_RUNTIME_LIBRARY> abstraction. The NEW behavior for this policy is to not place Watcom runtime library flags in the default cache entries and use the abstraction instead.
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0135 🦋
Added in version 3.24.
Okay so picture this: you're using the URL download method with the ExternalProject_Add() <#command:externalproject_add> or FetchContent_Declare() <#command:fetchcontent_declare> commands. CMake 3.23 and below sets the timestamps of the extracted contents to the same as the timestamps in the archive. Which means — when the URL changes, the new archive gets downloaded and extracted, but the timestamps of the extracted contents might not be newer than the previous contents 😭 So anything that depends on the extracted contents might not get rebuilt, even though the contents may have literally changed. That's giving "silent stale build" and it's not the vibe.
CMake 3.24 and above prefers to set the timestamps of all extracted contents to the time of the extraction. This ensures that anything depending on the extracted contents will be rebuilt whenever the URL changes. Slay, honestly 👑
The DOWNLOAD_EXTRACT_TIMESTAMP option to the ExternalProject_Add() <#command:externalproject_add> and FetchContent_Declare() <#command:fetchcontent_declare> commands can be used to explicitly specify how timestamps should be handled. When DOWNLOAD_EXTRACT_TIMESTAMP is not given, this policy controls the default behavior. The OLD behavior for this policy is to restore the timestamps from the archive. The NEW behavior sets the timestamps of extracted contents to the time of extraction.
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake warns, and uses OLD behavior. (Yep, this one actually warns at you — it's not a quiet one 🗣️)
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0134 🌸
Added in version 3.24.
The default registry view is TARGET for the find_file() <#command:find_file>, find_path() <#command:find_path>, find_library() <#command:find_library>, and find_package() <#command:find_package> commands and BOTH for the find_program() <#command:find_program> command.
The default registry views in CMake 3.23 and below are selected using the following rules:
- if
CMAKE_SIZEOF_VOID_P<#variable:CMAKE_SIZEOF_VOID_P> has value8:- Use view
64for allfind_*commands except thefind_program()<#command:find_program> command. - Use view
64_32for thefind_program()<#command:find_program> command.
- Use view
- if
CMAKE_SIZEOF_VOID_P<#variable:CMAKE_SIZEOF_VOID_P> has value4or is undefined:- Use view
32for allfind_*commands except thefind_program()<#command:find_program> command. - Use view
32_64for thefind_program()<#command:find_program> command.
- Use view
The OLD behavior for this policy is to use registry views 64 and 64_32 or 32_64 and 32 as default, depending on the CMAKE_SIZEOF_VOID_P <#variable:CMAKE_SIZEOF_VOID_P> variable value. The NEW behavior for this policy is to use registry views TARGET and BOTH as default. Way cleaner, no cap 💅
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0133 🎀
Added in version 3.24.
The CPack <#module:CPack> module disables SLA by default in the CPack DragNDrop Generator <#cpack_gen:CPack DragNDrop Generator>.
Okay so history lesson: the CPack DragNDrop Generator <#cpack_gen:CPack DragNDrop Generator> in CMake 3.22 and below attaches a Software License Agreement (SLA) to .dmg files using the file specified by CPACK_RESOURCE_FILE_LICENSE <#variable:CPACK_RESOURCE_FILE_LICENSE>, if set to a non-default value. But then macOS 12.0 deprecated the tools used to do this 😭 so CMake 3.23 added the CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE <#variable:CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE> option to control the behavior. And CMake 3.23 enables that option by default, for compatibility with older versions.
CMake 3.24 and above prefer to not enable the CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE <#variable:CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE> option by default. This policy provides compatibility with projects that haven't been updated to account for the lack of an SLA in their .dmg packages. Like, heads up, your installer might look different now bestie 🫶
The OLD behavior for this policy is to enable CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE <#variable:CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE> by default. The NEW behavior for this policy is to not enable it by default.
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0133 <#variable:CMAKE_POLICY_WARNING_CMP<NNNN>> variable to control the warning. (Yes, that's CMAKE_POLICY_WARNING_CMP<NNNN> — the generic pattern, with the actual number subbed in. Iconic naming, honestly.)
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0132 🧚
Added in version 3.24.
Do not set compiler environment variables on first run.
Apart from when you're using the Xcode <#generator:Xcode> generator and some Visual Studio Generators <#visual-studio-generators>, CMake 3.23 and below will set environment variables like CC <#envvar:CC>, CXX <#envvar:CXX>, etc. when the corresponding language is enabled. Which sounds fine until you read the fine print: this only occurs on the very first time CMake is run in a build directory, and the environment variables are only defined at configure time, not build time. On subsequent CMake runs, these environment variables are not set — opening up the opportunity for different behavior between the first and subsequent CMake runs. Bestie that is a cursed heisenbug generator and I'm obsessed with how bad it is 💀
CMake 3.24 and above prefer to not set these environment variables when a language is enabled, even on the first run in a build directory. Consistency, we love her ✨
The OLD behavior for this policy sets the relevant environment variable on the first run when a language is enabled. The NEW behavior for this policy does not set any such environment variables.
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0131 💜
Added in version 3.24.
LINK_LIBRARIES <#prop_tgt:LINK_LIBRARIES> supports the $<LINK_ONLY:...> <#genex:LINK_ONLY> generator expression.
CMake 3.23 and below documented the $<LINK_ONLY:...> <#genex:LINK_ONLY> generator expression only for use in INTERFACE_LINK_LIBRARIES <#prop_tgt:INTERFACE_LINK_LIBRARIES>. When used in LINK_LIBRARIES <#prop_tgt:LINK_LIBRARIES>, the content guarded inside $<LINK_ONLY:...> <#genex:LINK_ONLY> was always used, even when collecting non-linking usage requirements such as INTERFACE_COMPILE_DEFINITIONS <#prop_tgt:INTERFACE_COMPILE_DEFINITIONS>. Which, yeah, means the "link only" part of "link only" kinda wasn't doing its job 🙈
okay so CMake 3.24 and above prefers to support $<LINK_ONLY:...> when it's used inside LINK_LIBRARIES, by taking the guarded content and using it only for link dependencies — not for the other usage requirements. This policy is the lil compatibility blanket for projects that haven't been updated to account for that glow-up yet. 💅
So: the OLD behavior for this policy is to use LINK_LIBRARIES content guarded by $<LINK_ONLY:...> even for non-linking usage requirements (yes, even the stuff that has nothing to do with linking, bestie 😭). The NEW behavior is to use the guarded content only for link dependencies. Periodt.
This policy was introduced in CMake version 3.24. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
🫶 Heads up: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. So like... don't get comfy.
✨ CMP0130 ✨
Added in version 3.24.
while() diagnoses condition evaluation errors. 🔥
CMake 3.23 and below accidentally tolerated errors encountered while evaluating the condition passed to the while() command (but not the if() command — if() was always the responsible one, iykyk). For example, the code
set(paren "(")
while(${paren})
endwhile()
creates an unbalanced parenthesis during condition evaluation. Not me making a syntax crime in front of everyone 💀
CMake 3.24 and above prefer to diagnose such errors. This policy provides compatibility for projects that have not been updated to fix their condition errors.
The OLD behavior for this policy is to ignore errors in while() conditions. The NEW behavior for this policy is to diagnose errors in while() conditions.
This policy was introduced in CMake version 3.24. 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.
🌈 Policies Introduced by CMake 3.23 🌈
🦋 CMP0129 🦋
Added in version 3.23.
Compiler id for MCST LCC compilers is now LCC, not GNU. the rebrand era ✨
CMake 3.23 and above recognize MCST LCC compiler as a different one from GNU, with its own command line and set of capabilities. CMake now prefers to present this to projects by setting the CMAKE_<LANG>_COMPILER_ID variable to LCC instead of GNU. However, existing projects may assume the compiler id for LCC is GNU as it was in CMake versions prior to 3.23. Therefore this policy determines for MCST LCC compiler which compiler id to report in the CMAKE_<LANG>_COMPILER_ID variable after language <LANG> is enabled by the project() or enable_language() command. 👑
🚨 The policy must be set prior to the invocation of either command. Like, before. Not after. Before. 🙈
The OLD behavior for this policy is to use compiler id GNU (and set CMAKE_<LANG>_COMPILER_VERSION to the supported GNU compiler version). NEW behavior for this policy is to use compiler id LCC, and set CMAKE_<LANG>_SIMULATE_ID to GNU, and CMAKE_<LANG>_SIMULATE_VERSION to the supported GNU compiler version. 💅
This policy was introduced in CMake version 3.23. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0129 variable to control the warning.
🫶 Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌸 Policies Introduced by CMake 3.22 🌸
💜 CMP0128 💜
Added in version 3.22.
When this policy is set to NEW:
<LANG>_EXTENSIONSis initialized toCMAKE_<LANG>_EXTENSIONSif set, otherwise falling back toCMAKE_<LANG>_EXTENSIONS_DEFAULT. 🎀- Extensions are correctly enabled/disabled if
<LANG>_STANDARDis unset or satisfied by the default. ✨ - Standard mode-affecting flags aren't added unless necessary to achieve the specified mode. no wasted flags, we love efficiency 💅
The OLD behavior:
- Initializes
<LANG>_EXTENSIONStoCMAKE_<LANG>_EXTENSIONSif set, otherwise falling back toON. - Always adds a flag if
<LANG>_STANDARDis set and<LANG>_STANDARD_REQUIREDisOFF. - If
<LANG>_STANDARDis unset:- Doesn't disable extensions even if
<LANG>_EXTENSIONSisOFF. 😭 - Fails to enable extensions if
<LANG>_EXTENSIONSisONexcept for the IAR compiler. (IAR stays winning, I guess 🏆)
- Doesn't disable extensions even if
Code may need to be updated for the NEW behavior in the following cases:
- If a standard mode flag previously overridden by CMake's and not used during compiler detection now takes effect due to CMake no longer adding one as the default detected is appropriate.
Such code should be converted to either:
- Use
<LANG>_STANDARDand<LANG>_EXTENSIONSinstead of manually adding flags. 🫶 - Or ensure the manually-specified flags are used during compiler detection.
- If extensions were disabled without
<LANG>_STANDARDbeing set CMake previously wouldn't actually disable extensions.
Such code should be updated to not disable extensions if they are required.
- If extensions were enabled/disabled when
<LANG>_STANDARDwas satisfied by the compiler's default CMake previously wouldn't actually enable/disable extensions.
Such code should be updated to set the correct extensions mode. fr fr, set it properly
If compiler flags affecting the standard mode are used during compiler detection (for example in a toolchain file using CMAKE_<LANG>_FLAGS_INIT) then they will affect the detected default standard CMAKE_<LANG>_STANDARD_DEFAULT and extensions CMAKE_<LANG>_EXTENSIONS_DEFAULT. 🧚
This policy was introduced in CMake version 3.22. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0128 variable to control the warning.
🫶 Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌟 CMP0127 🌟
Added in version 3.22.
cmake_dependent_option() supports full Condition Syntax. 😭 the glow-up is real
The <condition> parameter accepts a semicolon-separated list of conditions. CMake 3.21 and lower evaluates each condition as if(${condition}), which does not properly handle conditions with nested paren groups (rude). CMake 3.22 and above instead prefer to evaluate each condition as if(<condition>), where <condition> is re-parsed as if literally written in a call to if(). This allows expressions like:
"A AND (B OR C)"
but requires expressions like:
"FOO MATCHES (UPPER|lower)"
to be re-written as:
"FOO MATCHES \"(UPPER|lower)\""
Policy CMP0127 provides compatibility for projects that have not been updated to expect the new behavior. 💅
This policy was introduced in CMake version 3.22. 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.
⭐ Policies Introduced by CMake 3.21 ⭐
🍓 CMP0126 🍓
Added in version 3.21.
When this policy is set to NEW, the set(CACHE) command does not remove any normal variable of the same name from the current scope. 🫶 (bestie stays in the group chat)
The OLD behavior removes any normal variable of the same name from the current scope in the following situations:
- No cache variable of that name existed previously.
- A cache variable of that name existed previously, but it had no type. This can occur when the variable was set on the command line using a form like
cmake -DMYVAR=blahinstead ofcmake -DMYVAR:STRING=blah. 💀 classic - The
FORCEorINTERNALkeywords were used when setting the cache variable.
Note that the NEW behavior has an important difference to the similar NEW behavior of policy CMP0077. The set(CACHE) command always sets the cache variable if it did not exist previously, regardless of the CMP0126 policy setting. The option() command will not set the cache variable if a non-cache variable of the same name already exists and CMP0077 is set to NEW. 👑
This policy was introduced in CMake version 3.21. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0126 variable to control the warning.
The CMAKE_POLICY_DEFAULT_CMP0126 variable may be used to set the policy for a third-party project in a subdirectory without modifying it. 🎀
🫶 Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌈 CMP0125 🌈
Added in version 3.21.
...The find_file(), find_path(), find_library() and find_program() commands cache their result in the variable you name as their first argument 💖. Okay so before CMake 3.21, if a cache variable with that name already existed before the call but the cache variable had no type, any non-cache variable of the same name would get absolutely discarded and the cache variable was always the one used (peep CMP0126 for a different but similar behavior, iykyk 💅). That straight-up contradicts the convention that a non-cache variable should take precedence over a cache variable of the same name 😭. And this situation can totally arise if a user sets a cache variable on the command line without specifying a type, like cmake -DMYVAR=blah ... instead of cmake -DMYVAR:FILEPATH=blah.
Related to the above 🫶: if a cache variable of the specified name already exists and it does have a type, the various find_...() commands would return that value unchanged. In particular, if it contained a relative path, it would not be converted to an absolute path in this situation. Not me, not the relative path, nobody getting converted ✨.
When policy CMP0125 is set to OLD or is unset, the behavior is exactly as described above 🌸. When it is set to NEW, here's the tea:
- If a non-cache variable of the specified name exists when the
find_...()command is called, its value will be used regardless of whether a cache variable of the same name already exists or not. A cache variable will not be created in this case if no such cache variable existed before. If a cache variable of the specified name did already exist, the cache will be updated to match the non-cache variable 👑. - The various
find...()commands will always provide an absolute path in the result variable, except where a relative path provided by a cache or non-cache variable cannot be resolved to an existing path 🦋.
This policy was introduced in CMake version 3.21. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. Bestie, don't build your whole house on it 💀.
CMP0124 🌈
Added in version 3.21.
foreach() loop variables are only available in the loop scope. That's it, that's the vibe check 🧚.
CMake 3.20 and below always leave the loop variable set at the end of the loop, either to the value it had before the loop, if any, or to the empty string. CMake 3.21 and above prefer to leave the loop variable in the state it had before the loop started, either set or unset 🌸. This policy provides compatibility for projects that expect the loop variable to always be left set.
The OLD behavior for this policy is to set the loop variable at the end of the loop, either to its original value, or to an empty value. The NEW behavior for this policy is to restore the loop variable to the state it had before the loop started, either set or unset 💖.
For example:
set(items a b c)
set(var1 "value")
unset(var2)
foreach(var1 IN LISTS items)
endforeach()
foreach(var2 IN LISTS items)
endforeach()
if(DEFINED var1)
message("var1: ${var1}")
endif()
if(DEFINED var2)
message("var2: ${var2}")
endif()
Under the OLD behavior, this code prints var1: value and var2:. Under the NEW behavior, this code prints only var1: value ✨. Post-loop var2 said "I'm out," and honestly? Respect 🫶.
This policy was introduced in CMake version 3.21. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 💀.
CMP0123 🔥
Added in version 3.21.
ARMClang cpu/arch compile and link flags must be set explicitly. No more sneaky auto-magic, bestie 😭.
CMake 3.20 and lower automatically maps the CMAKE_SYSTEM_PROCESSOR variable and an undocumented CMAKE_SYSTEM_ARCH to compile and link options for ARMClang. For example, the -mcpu=cortex-m33 flag is added when CMAKE_SYSTEM_PROCESSOR equals cortex-m33 🎀. CMake requires projects to set either variable or it raises a fatal error. However, the project may need to additionally specify CPU features using e.g. -mcpu=cortex-m33+nodsp, conflicting with the -mcpu=cortex-m33 added by CMake. This results in either link errors or unusable binaries 💀. Iconic disaster, honestly.
CMake 3.21 and above prefer instead to not add any cpu/arch compile and link flags automatically. Instead, projects must specify them explicitly 👑. This policy provides compatibility for projects that have not been updated.
The OLD behavior of this policy requires projects that use ARMClang to set either CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH and it automatically adds a compile option -mcpu= or -march= and a link option --cpu= based on those variables. The NEW behavior does not add compile or link options, and projects are responsible for setting correct options 🦋.
This policy was introduced in CMake version 3.21. 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 💀.
CMP0122 💜
Added in version 3.21.
UseSWIG use library name conventions for CSharp language. Slay, but specifically for C# 💅.
Starting with CMake 3.21, UseSWIG generates now a library using default naming conventions. This policy provides compatibility with projects that expect the legacy behavior 🌸.
This policy was introduced in CMake version 3.21. 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 💀.
CMP0121 🍓
Added in version 3.21.
The list() command now detects invalid indices. Finally, some accountability ✨.
Prior to CMake version 3.21, the list() command's GET, INSERT, SUBLIST, and REMOVE_AT subcommands did not detect invalid index arguments. They just vibed. They did not pass the vibe check 😭.
The OLD behavior of this policy is for invalid indices to be treated as their integer value (if any) at the start of the string. For example, 2good4you is a 2 and not_an_integer is a 0 💀. The NEW behavior is for invalid indices to trigger an error 🫶.
This policy was introduced in CMake version 3.21. 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 💀.
🌈 Policies Introduced by CMake 3.20 🌈
CMP0120 👑
Added in version 3.20.
The WriteCompilerDetectionHeader module is removed. Gone, deceased, no thoughts head empty 🦋.
CMake versions 3.1 through 3.19 provide this module to generate a C++ compatibility layer by reusing information from CMake's table of preprocessor checks for cmake-compile-features(7). However:
- Those granular features have been superseded by meta-features for Requiring Language Standards such as
cxx_std_11. Therefore no new granular feature checks will be added and projects will need to use other means to conditionally use new C++ features 🌸. - The module exposes some of CMake's implementation details directly to C++ translation units 🙈.
- The module's approach effectively provides a header file with CMake, thus tying the version of the header to the version of CMake. Many projects found that the
WriteCompilerDetectionHeaderwas best used by manually generating its header locally with a recent version of CMake and then bundling it with the project source so that it could be used with older CMake versions 💅.
For reasons including the above, CMake 3.20 and above prefer to not provide the WriteCompilerDetectionHeader module. This policy provides compatibility for projects that have not been ported away from it 🫶. Projects using the module should be updated to stop using it. Alternatives include:
- Bundle a copy of the generated header in the project's source 🎀.
- Use a third-party alternative, such as the CC0-licensed Hedley (
https://nemequ.github.io/hedley/) ✨. - Drop support for compilers too old to provide the features natively 👑.
The OLD behavior of this policy is for inclusion of the deprecated WriteCompilerDetectionHeader module to work. The NEW behavior is for inclusion of the module to fail as if it does not exist 💀.
This policy was introduced in CMake version 3.20. 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 💀.
CMP0119 🦋
Added in version 3.20.
LANGUAGE source file property explicitly compiles as specified language. Say what you mean, and mean what you say 💅.
The LANGUAGE source file property is documented to mean that the source file is written in the specified language. In CMake 3.19 and below, setting this property causes CMake to compile the source file using the compiler for the specified language. However, it only passes an explicit flag to tell the compiler to treat the source as the specified language for MSVC-like, XL, and Embarcadero compilers for the CXX language 😭. CMake 3.20 and above prefer to also explicitly tell the compiler to use the specified language using a flag such as -x c on all compilers for which such flags are known ✨.
Okay so this policy is literally a compatibility blanket for projects that have not been updated to expect this behavior. Example: some projects were setting the LANGUAGE property to C on assembly-language .S source files so they could compile them using the C compiler. Bestie, those projects should be updated to use enable_language(ASM), for which CMake will often choose the C compiler as the assembler on relevant platforms anyway. ✨
OLD behavior: interpret the LANGUAGE <LANG> property using its undocumented meaning to "use the <LANG> compiler". NEW behavior: interpret the LANGUAGE <LANG> property using its documented meaning to "compile as a <LANG> source".
This policy was introduced in CMake version 3.20. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
CMP0118 ✨
Added in version 3.20.
GENERATED sources may be used across directories without manual marking. No cap.
In CMake 3.19 and below, the GENERATED source file property, like other source file properties, was scoped in every directory separately. If a source file was generated in one directory, projects had to manually set the GENERATED property in another directory in order to use the file.
Whether or not a source file is generated is an all-or-nothing global property of the source: a source is either generated or it is not. CMake 3.20 and above prefer to allow source files generated in one directory to be used in other directories without manually marking them as GENERATED. Additionally, the GENERATED property may now be set only to boolean values, and may not be turned off once turned on. This policy provides compatibility for projects that have not been updated for this behavior.
OLD behavior: allow generated files to be used only in directories in which their GENERATED property has been turned on. NEW behavior: allow generated files to be used in other directories without explicitly turning on the GENERATED property for those directories.
Added in version 3.30: Policy CMP0163 additionally makes the GENERATED source file property visible to get_property() and get_source_file_property() calls in other directories.
This policy was introduced in CMake version 3.20. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns about setting the GENERATED property to a non-boolean value, 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. 🫶
CMP0117 🎀
Added in version 3.20.
MSVC RTTI flag /GR is not added to CMAKE_CXX_FLAGS by default. (Yes, that’s the CXX member of the CMAKE_<LANG>_FLAGS crew.)
When using MSVC-like compilers in CMake 3.19 and below, the RTTI flag /GR is added to CMAKE_CXX_FLAGS by default. This behavior is left from support for MSVC versions from Visual Studio 2003 and below that did not enable RTTI by default. It is no longer necessary. Furthermore, it is problematic for projects that want to change to /GR- programmatically. In particular, it requires string editing of the CMAKE_CXX_FLAGS variable with knowledge of the CMake builtin default so it can be replaced.
CMake 3.20 and above prefer to leave out /GR from the value of CMAKE_CXX_FLAGS by default.
This policy provides compatibility with projects that have not been updated to expect the lack of the /GR flag. The policy setting takes effect as of the first project() or enable_language() command that initializes CMAKE_CXX_FLAGS.
Note: Once the policy has taken effect at the top of a project for a given language, that choice must be used throughout the tree for that language. In projects that have nested projects in subdirectories, be sure to convert everything together. 💅
OLD behavior: place the MSVC /GR flag in the default CMAKE_CXX_FLAGS cache entry. NEW behavior: do not place the MSVC /GR flag in the default cache entry.
This policy was introduced in CMake version 3.20. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 😭
CMP0116 🌸
Added in version 3.20.
Ninja generators transform DEPFILEs from add_custom_command().
In CMake 3.19 and below, files given to the DEPFILE argument of add_custom_command() were passed directly to Ninja's depfile variable without any path resolution. This meant that if add_custom_command() was called from a subdirectory (created by add_subdirectory()), the DEPFILE argument would have to be either an absolute path or a path relative to CMAKE_BINARY_DIR, rather than CMAKE_CURRENT_BINARY_DIR. In addition, no transformation was done on the file listed in DEPFILE, which meant that the paths within the DEPFILE had the same restrictions.
Starting with CMake 3.20, the DEPFILE argument is relative to CMAKE_CURRENT_BINARY_DIR (unless it is absolute), and the paths in the DEPFILE are also relative to CMAKE_CURRENT_BINARY_DIR. CMake automatically transforms the paths in the DEPFILE (unless they are absolute) after the custom command is run. The file listed in DEPFILE is not modified in any way. Instead, CMake writes the transformation to its own internal file, and passes this internal file to Ninja's depfile variable. This transformation happens regardless of whether or not DEPFILE is relative, and regardless of whether or not add_custom_command() is called from a subdirectory.
OLD behavior: pass the DEPFILE to Ninja unaltered. NEW behavior: transform the DEPFILE after running the custom command. The status of CMP0116 is recorded at the time of the custom command's creation, and you can have custom commands in the same directory with different values for CMP0116 by setting the policy before each custom command.
This policy was introduced in CMake version 3.20. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn by default (unless DEPFILE is used in a subdirectory), and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0116 variable (the CMAKE_POLICY_WARNING_CMP<NNNN> family) to control the warning.
Note: The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 🦋
CMP0115 💖
Added in version 3.20.
Source file extensions must be explicit.
In CMake 3.19 and below, if a source file could not be found by the name specified, it would append a list of known extensions to the name to see if the file with the extension could be found. For example, this would allow the user to run:
add_executable(exe main)
and put main.c in the executable without specifying the extension.
Starting in CMake 3.20, CMake prefers all source files to have their extensions explicitly listed:
add_executable(exe main.c)
OLD behavior: implicitly append known extensions to source files if they can't be found. NEW behavior: do not append known extensions and require them to be explicit.
This policy was introduced in CMake version 3.20. 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. 🍓
🌈 Policies Introduced by CMake 3.19 🌈
CMP0114 👑
Added in version 3.19.
ExternalProject step targets fully adopt their steps.
The ExternalProject_Add() STEP_TARGETS option, and the ExternalProject_Add_StepTargets() function, can be used to create build targets for individual steps of an external project.
In CMake 3.18 and below, step targets have some limitations:
- Step targets always depend on targets named by the
ExternalProject_Add()DEPENDSoption even though not all steps need them. In order to allow step targets to be created without those dependencies, theExternalProject_Add()INDEPENDENT_STEP_TARGETSoption or theExternalProject_Add_StepTargets()NO_DEPENDSoption may be used. However, adding such "independent" step targets makes sense only for specific steps such as download, update, and patch because they do not need any of the external project's build dependencies. Furthermore, it does not make sense to create independent step targets for steps that depend on non-independent steps. Such rules are not enforced, and projects that do not follow them can generate build systems with confusing and generator-specific behavior. - Step targets hold copies of the custom commands implementing their steps that are separate from the copies in the primary target created by
ExternalProject_Add(), and the primary target does not depend on the step targets. In parallel builds that drive the primary target and step targets concurrently, multiple copies of the steps' commands may run concurrently and race each other.
Also, before CMP0113 existed, the step targets that Makefile Generators make would also carry every custom command their step depends on — which is literally how you end up running the same step over and over even in a serial build. 💀 Not the vibe.
So in CMake 3.19 and up, the ExternalProject module ships a glow-up design that fixes all of this:
- Every step gets classified as "independent" if it doesn't depend on other targets named by
ExternalProject_Add()'sDEPENDS. The predefined steps come pre-classified, bestie:download,update, andpatchare independent ✨configure,build,test, andinstallare not
For custom steps, ExternalProject_Add_Step() gives you an INDEPENDENT option to mark them independent yourself. And heads up: it's an error to mark a step independent if it depends on other steps that aren't. 🚩 Also, just so we're clear, this whole "independent" thing only means independent from external targets — it's completely orthogonal to a step's dependencies on other steps. Two different axes, iykyk.
- Step targets made via
ExternalProject_Add()'sSTEP_TARGETSoption or theExternalProject_Add_Step()function are now independent if and only if their steps are marked independent. And theExternalProject_Add()INDEPENDENT_STEP_TARGETSoption plus theExternalProject_Add_StepTargets()NO_DEPENDSoption? No longer allowed. Gone. 🫶 - Step targets, once created, are fully responsible for holding the custom commands that implement their steps. The primary target from
ExternalProject_Add()depends on the step targets, and the step targets depend on each other — and those target-level dependencies match the file-level dependencies the custom commands use for each step. Everything lines up, it's giving choreography. 💅
And when you use ExternalProject_Add()'s UPDATE_DISCONNECTED or TEST_EXCLUDE_FROM_MAIN option, or ExternalProject_Add_Step()'s EXCLUDE_FROM_MAIN option on a custom step, some step targets may get created automatically — those are needed to hold the steps that the primary target and the disconnected step targets commonly depend on.
Policy CMP0114 is the compatibility blanket for projects that haven't been updated to expect the new behavior. OLD behavior = the 3.18-and-below stuff documented above. NEW behavior = the 3.19-and-above stuff documented above. Simple as that.
This policy dropped in CMake version 3.19. You can set it with cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns you and rolls with OLD behavior.
Note: The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. Like, it's on borrowed time, bestie. ⏳
🎀 CMP0113
Added in version 3.19.
Makefile Generators do not repeat custom commands from target dependencies. Periodt.
Picture a chain of custom commands split across two targets that depend on each other:
add_custom_command(OUTPUT output-not-created
COMMAND ... DEPENDS ...)
set_property(SOURCE output-not-created PROPERTY SYMBOLIC 1)
add_custom_command(OUTPUT output-created
COMMAND ... DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/output-not-created)
add_custom_target(first DEPENDS output-not-created)
add_custom_target(second DEPENDS output-created)
add_dependencies(second first)
In CMake 3.18 and lower, the Makefile generators straight up put a copy of both custom commands in the Makefile for target second — even though its dependency on target first already guarantees the first custom command runs before the second. So running make second made that first custom command run once in the first target and then again in the second target. Not me crying over duplicated work 😭
CMake 3.19 and above prefer to not duplicate custom commands in a target when they're already generated in other targets it depends on (directly or indirectly). This policy keeps things compatible for projects that haven't been updated to the new behavior. Specifically, projects that relied on that duplicate execution, or that didn't properly set the SYMBOLIC source file property, might get caught out. 🙈
OLD behavior = duplicate custom commands in dependent targets. NEW behavior = don't duplicate them.
This policy was introduced in CMake version 3.19. Set it with cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn, 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.
🦋 CMP0112
Added in version 3.19.
Target file component generator expressions do not add target dependencies anymore.
These target-based generator expressions — the ones that query for directory or file name components — no longer add a dependency on the target being evaluated:
TARGET_FILE_NAMETARGET_FILE_DIRTARGET_LINKER_FILE_BASE_NAMETARGET_LINKER_FILE_NAMETARGET_LINKER_FILE_DIRTARGET_SONAME_FILE_NAMETARGET_SONAME_FILE_DIRTARGET_PDB_FILE_NAMETARGET_PDB_FILE_DIRTARGET_BUNDLE_DIRTARGET_BUNDLE_DIR_NAMETARGET_BUNDLE_CONTENT_DIR
In CMake 3.18 and lower, a dependency on the evaluated target of any of those expressions was always added. CMake 3.19 and above prefer not to. This policy exists so projects that haven't been updated still work. And the detail that matters: the policy setting gets recorded on each target when it's created, and that's what decides whether generator expressions referencing that target imply a dependency on it. So it's baked in at creation time, bestie. 🧚
OLD behavior = add a dependency on the evaluated target for those generator expressions. NEW behavior = don't add one.
This policy was introduced in CMake version 3.19. Set it with cmake_policy() or cmake_minimum_required(). If it's not set, CMake does not warn by default, and uses OLD behavior.
See the docs for the CMAKE_POLICY_WARNING_CMP0112 variable — that's part of the CMAKE_POLICY_WARNING_CMP<NNNN> family, fyi — if you want to control the warning yourself. 🔔
Note: The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌸 CMP0111
Added in version 3.19.
An imported target that's missing its location property now fails during generation. It's giving accountability. 👑
Imported Targets for library files and executables require that their on-disk location be specified in a target property like IMPORTED_LOCATION, IMPORTED_IMPLIB, or a per-configuration equivalent. If a needed location property isn't set, CMake 3.18 and below would generate the string <TARGET_NAME>-NOTFOUND in its place — which then blows up the corresponding rules at build time. CMake 3.19 and above prefer to raise an error during generation instead. This policy keeps compatibility for projects that haven't been updated to expect the new behavior.
OLD behavior = generate the location of an imported unknown, static, or shared library target as <TARGET_NAME>-NOTFOUND if it's not set. NEW behavior = raise an error. 🔥
This policy was introduced in CMake version 3.19. Set it with cmake_policy() or cmake_minimum_required(). If it's 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.
💜 CMP0110
Added in version 3.19.
add_test() supports arbitrary characters in test names, and honestly? Iconic.
add_test() can now (officially) create tests whose names contain whitespace and other special characters. Before CMake version 3.19 that wasn't allowed — though there was a workaround: explicitly wrapping the test's name in escaped quotes inside the add_test command. Sneaky but it worked. 🙈
And even though it was never officially supported, several projects out in the wild found and implemented that workaround anyway. The problem? The new change that officially lets add_test support whitespace and special characters in test names breaks that workaround. So for those projects to keep working smoothly with newer CMake versions, this policy was introduced. Considerate, honestly.
OLD behavior = still prevent add_test from handling whitespace and special characters properly (unless you use the workaround mentioned above). NEW behavior = allow names with whitespace and special characters for tests created by add_test. ✨
This policy was introduced in CMake version 3.19. Set it with cmake_policy() or cmake_minimum_required(). If it's 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.
🌈 CMP0109
Added in version 3.19.
find_program() requires permission to execute but not to read. Read that again — execute, not read. Weird but true. 💅
In CMake 3.18 and below, on UNIX, find_program() would find files that were readable without needing execute permission — and would not find files that were executable without read permission. In CMake 3.19 and above, find_program prefers to require execute permission but not read permission. This policy keeps compatibility with projects that haven't been updated to expect the new behavior.
OLD behavior = find_program requires read permission but not execute permission. NEW behavior = find_program requires execute permission but not read permission. 🎯
Okay so this one dropped with CMake version 3.19 ✨ you can set it with cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>, and if you just... don't? CMake hits you with a warning and rolls with the OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may genuinely get yeeted in a future version of CMake. So like, don't get comfy 💀
🌸 Policies Introduced by CMake 3.18 🌸
CMP0108
Added in version 3.18.
A target is not allowed to link to itself — not even sneakily through an ALIAS target 🙈
Back in CMake 3.17 and below? A target could totally link to a target aliased to itself. Chaos.
- The OLD behavior for this policy is to allow a target to link to a target aliased to itself.
- The NEW behavior of this policy is to prevent a target from linking to itself through an ALIAS target.
This policy was introduced in CMake version 3.17. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0107
Added in version 3.18.
You are NOT allowed to create an ALIAS target with the same name as another target. Name collisions are giving main character energy and we're not here for it 👑
In CMake 3.17 and below, an ALIAS target could silently overwrite an existing target with the same name. Just... poof, gone, no warning 😭
- The OLD behavior for this policy is to allow target overwrite.
- The NEW behavior of this policy is to prevent target overwriting.
This policy was introduced in CMake version 3.17. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0106
Added in version 3.18.
The Documentation <#module:Documentation> module is removed. RIP bestie 🪦
Documentation <#module:Documentation> was added as a support mechanism for the VTK project and was tuned for that project specifically. Instead of CMake providing this module with (now old) VTK patterns for cache variables and required packages, the module is now deprecated by CMake itself.
- The OLD behavior of this policy is for
Documentation<#module:Documentation> to add cache variables and find VTK documentation dependent packages. - The NEW behavior is to act as an empty module. Literally nothing. An icon of minimalism ✨
This policy was introduced in CMake version 3.18. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command: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 <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0105
Added in version 3.18.
The LINK_OPTIONS <#prop_tgt:LINK_OPTIONS> and INTERFACE_LINK_OPTIONS <#prop_tgt:INTERFACE_LINK_OPTIONS> target properties are now used for the device link step 🔗
In CMake 3.17 and below, link options are simply not used by the device link step.
- The OLD behavior for this policy is to ignore the link options during the device link step.
- The NEW behavior of this policy is to use the link options during the device link step.
This policy was introduced in CMake version 3.18. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0104
Added in version 3.18.
Initialize CMAKE_CUDA_ARCHITECTURES <#variable:CMAKE_CUDA_ARCHITECTURES> when CMAKE_CUDA_COMPILER_ID <#variable:CMAKE_<LANG>_COMPILER_ID> is NVIDIA. And raise an error if CUDA_ARCHITECTURES <#prop_tgt:CUDA_ARCHITECTURES> is empty 🔥
So CMAKE_CUDA_ARCHITECTURES <#variable:CMAKE_CUDA_ARCHITECTURES>, which was introduced in CMake 3.18, is used to initialize CUDA_ARCHITECTURES <#prop_tgt:CUDA_ARCHITECTURES>, which passes correct code generation flags to the CUDA compiler. iykyk 💅
Previous to this, users had to manually specify the code generation flags. This policy is for backwards compatibility with manually specifying code generation flags.
- The OLD behavior for this policy is to not initialize
CMAKE_CUDA_ARCHITECTURES<#variable:CMAKE_CUDA_ARCHITECTURES> whenCMAKE_CUDA_COMPILER_ID<#variable:CMAKE_<LANG>_COMPILER_ID> is NVIDIA. An emptyCUDA_ARCHITECTURES<#prop_tgt:CUDA_ARCHITECTURES> is allowed. - The NEW behavior of this policy is to initialize
CMAKE_CUDA_ARCHITECTURES<#variable:CMAKE_CUDA_ARCHITECTURES> whenCMAKE_CUDA_COMPILER_ID<#variable:CMAKE_<LANG>_COMPILER_ID> is NVIDIA and raise an error ifCUDA_ARCHITECTURES<#prop_tgt:CUDA_ARCHITECTURES> is empty during generation.
If CUDA_ARCHITECTURES <#prop_tgt:CUDA_ARCHITECTURES> is set to a false value, no architectures flags are passed to the compiler. This is intended to support packagers and the rare cases where full control over the passed flags is required 🫶
This policy was introduced in CMake version 3.18. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command: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 <#cmake-policies-intro> and may be removed in a future version of CMake.
✨ Examples ✨
set_target_properties(tgt PROPERTIES CUDA_ARCHITECTURES "35;50;72")
Generates code for real and virtual architectures 30, 50 and 72. (That's what the page says, we don't make the rules 🎀)
set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 70-real 72-virtual)
Generates code for real architecture 70 and virtual architecture 72.
set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES OFF)
CMake will not pass any architecture flags to the compiler. Full silence. Iconic.
CMP0103
Added in version 3.18.
Multiple calls to the export() <#command:export> command with the same FILE without APPEND is no longer allowed. One and done, bestie 🚫
In CMake 3.17 and below, multiple calls to the export() <#command:export> command with the same FILE without APPEND are accepted silently — but only the last occurrence is actually taken into account during the generation. Rude.
- The OLD behavior for this policy is to ignore the multiple occurrences of the
export()<#command:export> command except the last one. - The NEW behavior of this policy is to raise an error on the second call to the
export()<#command:export> command with the sameFILEwithoutAPPEND.
This policy was introduced in CMake version 3.18. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command: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 <#cmake-policies-intro> and may be removed in a future version of CMake.
🌈 Policies Introduced by CMake 3.17 🌈
CMP0102
Added in version 3.17.
The mark_as_advanced() <#command:mark_as_advanced> command no longer creates a cache entry if one does not already exist 🦋
In CMake 3.16 and below, if a variable was not defined at all or just defined locally, the mark_as_advanced() <#command:mark_as_advanced> command would create a new cache entry with an UNINITIALIZED type and no value. Then when a find_path() <#command:find_path> (or other similar find_ command) would next run, it would find this undefined cache entry and set it up with an empty string value. And this whole process would end up deleting the local variable in the process (due to the way the cache works) — effectively clearing any stored find_ results that were only available in the local scope. Not me crying over lost variables 😭
- The OLD behavior for this policy is to create the empty cache definition.
- The NEW behavior of this policy is to ignore variables which do not already exist in the cache.
This policy was introduced in CMake version 3.17. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0102 <#variable:CMAKE_POLICY_WARNING_CMP<NNNN>> variable to control the warning 👀
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0101
Added in version 3.17.
target_compile_options() <#command:target_compile_options> now always honors the BEFORE keyword. Always always. No exceptions 💅
In CMake 3.16 and below, the target_compile_options() <#command:target_compile_options> command ignores the BEFORE keyword when inserting items into the COMPILE_OPTIONS <#prop_tgt:COMPILE_OPTIONS> target property (PRIVATE and PUBLIC items). CMake 3.17 and later honors the BEFORE keyword in all cases. This policy provides compatibility for projects that have not been updated to expect the new behavior.
The behavior of inserting items into the INTERFACE_COMPILE_OPTIONS <#prop_tgt:INTERFACE_COMPILE_OPTIONS> target property (PUBLIC and INTERFACE items) is not affected by this policy. The BEFORE keyword has always been honored when adding items to INTERFACE_COMPILE_OPTIONS <#prop_tgt:INTERFACE_COMPILE_OPTIONS> ⭐
- The OLD behavior for this policy is to not honor the
BEFOREkeyword when inserting into theCOMPILE_OPTIONS<#prop_tgt:COMPILE_OPTIONS> property. - The NEW behavior for this policy is to honor the
BEFOREkeyword in all cases.
This policy was introduced in CMake version 3.17. It may be set by cmake_policy() <#command:cmake_policy> or cmake_minimum_required() <#command:cmake_minimum_required>. If it is not set, CMake does not warn, and uses OLD behavior.
Note: the OLD behavior of a policy is deprecated by definition <#cmake-policies-intro> and may be removed in a future version of CMake.
CMP0100
Added in version 3.17.
Let AUTOMOC <#prop_tgt:AUTOMOC> and AUTOUIC <#prop_tgt:AUTOUIC> process header files that end with a .hh extension 🎀
Since version 3.17, CMake processes header files that end with a .hh extension in AUTOMOC <#prop_tgt:AUTOMOC> and AUTOUIC <#prop_tgt:AUTOUIC>. In earlier CMake versions, these header files were ignored by AUTOMOC <#prop_tgt:AUTOMOC> and AUTOUIC <#prop_tgt:AUTOUIC>. Ghosted, fr fr.
This policy affects how header files that end with a .hh extension get treated in AUTOMOC <#prop_tgt:AUTOMOC> and AUTOUIC <#prop_tgt:AUTOUIC>.
The OLD behavior for this policy is to ignore .hh header files in AUTOMOC <#prop_tgt:AUTOMOC> and AUTOUIC <#prop_tgt:AUTOUIC>.
So like, the NEW behavior here is that .hh header files get processed in AUTOMOC and AUTOUIC exactly like any other header file 💅 periodt, no special-casing bestie.
⚠️ Note: if you wanna silence that CMP0100 warning, you can just yeet source files out ofAUTOMOCandAUTOUICprocessing by setting the source file propertiesSKIP_AUTOMOC,SKIP_AUTOUICorSKIP_AUTOGENon them. Obsessed with a clean build log tbh ✨
# Source skip example:
set_property(SOURCE /path/to/file1.hh PROPERTY SKIP_AUTOMOC ON)
set_property(SOURCE /path/to/file2.hh PROPERTY SKIP_AUTOUIC ON)
set_property(SOURCE /path/to/file3.hh PROPERTY SKIP_AUTOGEN ON)
This policy dropped in CMake version 3.17.0. You can set it with cmake_policy() or cmake_minimum_required(). And if you don't set it? CMake literally warns you and then goes with OLD behavior anyway 😭
Note: the OLD behavior of a policy is deprecated by definition, babes, and it might get removed in a future version of CMake. Don't get attached 💀
CMP0099
Added in version 3.17.
Link properties are transitive over private dependencies of static libraries 🎀
In CMake 3.16 and below, when the buildsystem is being generated, the evaluation of target properties INTERFACE_LINK_OPTIONS, INTERFACE_LINK_DIRECTORIES, and INTERFACE_LINK_DEPENDS does not follow private dependencies of static libraries — and those private deps show up in their INTERFACE_LINK_LIBRARIES guarded by LINK_ONLY generator expressions. So literally only the libraries themselves get propagated to link the dependent binary. That's it. Nothing else. 🙈
CMake 3.17 and later is like "no, we're propagating all the interface link properties actually 💅". This policy exists so projects that haven't been updated to expect the new behavior don't just break.
- The OLD behavior for this policy is to not propagate interface link properties.
- The NEW behavior of this policy is to propagate interface link properties.
Added in version 3.30: Policy CMP0166 makes TARGET_PROPERTY evaluation of these three transitive link properties follow private dependencies of static libraries too 👑
This policy was introduced in CMake version 3.17. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior. (She's quiet about it, okay, respect her choices 🫶)
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake 🌸
CMP0098
Added in version 3.17.
FindFLEX runs flex in the directory CMAKE_CURRENT_BINARY_DIR when executing ✨
So the module provides a flex_target() command that generates FLEX output, right? In CMake 3.16 and below, that command generated a custom build rule that ran flex in the current source directory. CMake 3.17 and later prefers to run it in the build directory and uses CMAKE_CURRENT_BINARY_DIR as the WORKING_DIRECTORY of its add_custom_command() invocation. The whole point: any implicitly generated file gets written relative to the build tree instead of the source tree — unless the generated file is given as an absolute path, obviously 💅
This policy provides compatibility for projects that have not been updated to expect the new behavior.
- The OLD behavior for this policy is for
flex_target()to use the current source directory for theWORKING_DIRECTORYand where to generate implicit files. - The NEW behavior of this policy is to use the current binary directory for the
WORKING_DIRECTORYrelative to which implicit files are generated — unless provided as an absolute path.
This policy was introduced in CMake version 3.17. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 🎀
🌈 Policies Introduced by CMake 3.16 🌈
CMP0097
Added in version 3.16.
ExternalProject_Add() with GIT_SUBMODULES set to "" initializes no submodules 💀
These commands provide a GIT_SUBMODULES option which controls what submodules get initialized and updated. Starting with CMake 3.16, explicitly setting GIT_SUBMODULES to an empty string means no submodules will be initialized or updated. Empty means empty, bestie, it's giving boundaries ✋
This policy provides compatibility for projects that have not been updated to expect the new behavior.
- The OLD behavior for this policy is for
GIT_SUBMODULESwhen set to an empty string to initialize and update all git submodules. - The NEW behavior for this policy is for
GIT_SUBMODULESwhen set to an empty string to initialize and update no git submodules.
This policy was introduced in CMake version 3.16. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
Note: this policy also applies toFetchContent_Declare(), which uses the same download and update features asExternalProject_Add(). However — and this is the messy part — due to an implementation deficiency present since the policy was first introduced, CMake 3.16 and later always uses the NEW behavior forFetchContent_Declare(), regardless of the policy setting 😭 Formally, this forcing of NEW behavior forFetchContent_Declare()will continue to apply in future CMake releases. So like, that's just how it is forever now 🫠
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake 🌸
CMP0096
Added in version 3.16.
The project() command preserves leading zeros in version components 🎀
When a VERSION <major>[.<minor>[.<patch>[.<tweak>]]]] argument is given to the project() command, it stores the version string in the PROJECT_VERSION variable and stores individual integer version components in the PROJECT_VERSION_{MAJOR,MINOR,PATCH,TWEAK} variables (see policy CMP0048). CMake 3.15 and below dropped leading zeros from each component. CMake 3.16 and higher prefers to preserve leading zeros. This policy provides compatibility for projects that have not been updated to expect the new behavior.
- The OLD behavior of this policy drops leading zeros in all components, e.g. such that version
1.07.06becomes1.7.6. - The NEW behavior of this policy preserves the leading zeros in all components, such that version
1.07.06remains unchanged. Iconic, she stays exactly as she is 💅
This policy was introduced in CMake version 3.16. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 ✨
CMP0095
Added in version 3.16.
RPATH entries are properly escaped in the intermediary CMake install script 🔥
Okay so in CMake 3.15 and earlier, RPATH entries set via CMAKE_INSTALL_RPATH or via INSTALL_RPATH had not been escaped before being inserted into the cmake_install.cmake script. Dynamic linkers on ELF-based systems (e.g. Linux and FreeBSD) allow certain keywords in RPATH entries, such as ${ORIGIN} — more details are available in the ld.so man pages on those systems, go read 'em. The syntax of these keywords can match CMake's variable syntax 😭 So in order to not be substituted (usually to an empty string) already by the intermediary cmake_install.cmake script, the user had to double-escape such RPATH keywords, e.g. set(CMAKE_INSTALL_RPATH "\\\${ORIGIN}/../lib"). Not cute. Since the intermediary cmake_install.cmake script is an implementation detail of CMake, CMake 3.16 and later makes sure RPATH entries are inserted literally by escaping any coincidental CMake syntax 👑
- The OLD behavior of this policy is to not escape RPATH entries in the intermediary
cmake_install.cmakescript. - The NEW behavior is to properly escape coincidental CMake syntax in RPATH entries when generating the intermediary
cmake_install.cmakescript.
This policy was introduced in CMake version 3.16. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns when it detects use of CMake-like syntax, 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 🎀
🌈 Policies Introduced by CMake 3.15 🌈
CMP0094
Added in version 3.15.
Modules FindPython3, FindPython2 and FindPython use LOCATION for lookup strategy 💖
Starting with CMake 3.15, Modules FindPython3, FindPython2 and FindPython set value LOCATION for, respectively, variables Python3_FIND_STRATEGY, Python2_FIND_STRATEGY and Python_FIND_STRATEGY. This policy provides compatibility with projects that expect the legacy behavior.
The OLD behavior for this policy set value VERSION for variables Python3_FIND_STRATEGY, Python2_FIND_STRATEGY and Python_FIND_STRATEGY.
This policy was introduced in CMake version 3.15. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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 🌸
CMP0093
Added in version 3.15.
FindBoost reports Boost_VERSION in x.y.z format ✨
In CMake 3.14 and below the module would report the Boost version number as specified in the preprocessor definition BOOST_VERSION in the boost/version.hpp file. In CMake 3.15 and later it is preferred that the reported version number matches the x.y.z format reported by the CMake package shipped with Boost 1.70.0 and later. The macro value is still reported in the Boost_VERSION_MACRO variable — she didn't go anywhere, she just moved 💅
...so like, the OLD behavior here is that FindBoost reports Boost_VERSION exactly as it's specified in the preprocessor definition BOOST_VERSION inside boost/version.hpp. The NEW behavior is that FindBoost reports Boost_VERSION in x.y.z format. ✨
This policy was introduced in CMake version 3.15. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
CMP0092
Added in version 3.15.
MSVC warning flags are not in CMAKE_<LANG>_FLAGS by default.
When using MSVC-like compilers in CMake 3.14 and below, warning flags like /W3 are added to CMAKE_<LANG>_FLAGS by default. This is problematic for projects that want to choose a different warning level programmatically. In particular, it requires string editing of the CMAKE_<LANG>_FLAGS variables with knowledge of the CMake builtin defaults so they can be replaced. 😭
CMake 3.15 and above prefer to leave out warning flags from the value of CMAKE_<LANG>_FLAGS by default.
This policy provides compatibility with projects that have not been updated to expect the lack of warning flags. The policy setting takes effect as of the first project() or enable_language() command that initializes CMAKE_<LANG>_FLAGS for a given language <LANG>.
Note: once the policy has taken effect at the top of a project for a given language, that choice must be used throughout the tree for that language. In projects that have nested projects in subdirectories, be sure to convert everything together. 🫶
The OLD behavior for this policy is to place MSVC warning flags in the default CMAKE_<LANG>_FLAGS cache entries. The NEW behavior for this policy is to not place MSVC warning flags in the default cache entries.
This policy was introduced in CMake version 3.15. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
CMP0091
Added in version 3.15.
MSVC runtime library flags are selected by an abstraction. 👑
Compilers targeting the MSVC ABI have flags to select the MSVC runtime library. Runtime library selection typically varies with build configuration because there is a separate runtime library for Debug builds.
In CMake 3.14 and below, MSVC runtime library selection flags are added to the default CMAKE_<LANG>_FLAGS_<CONFIG> cache entries by CMake automatically. This allows users to edit their cache entries to adjust the flags. However, the presence of such default flags is problematic for projects that want to choose a different runtime library programmatically. In particular, it requires string editing of the CMAKE_<LANG>_FLAGS_<CONFIG> variables with knowledge of the CMake builtin defaults so they can be replaced.
CMake 3.15 and above prefer to leave the MSVC runtime library selection flags out of the default CMAKE_<LANG>_FLAGS_<CONFIG> values and instead offer a first-class abstraction. The CMAKE_MSVC_RUNTIME_LIBRARY variable and MSVC_RUNTIME_LIBRARY target property may be set to select the MSVC runtime library. If they are not set then CMake uses the default value MultiThreaded$<$<CONFIG:Debug>:Debug>DLL which is equivalent to the original flags. ✨
This policy provides compatibility with projects that have not been updated to be aware of the abstraction. The policy setting takes effect as of the first project() or enable_language() command that enables a language whose compiler targets the MSVC ABI.
Note: once the policy has taken effect at the top of a project, that choice must be used throughout the tree. In projects that have nested projects in subdirectories, be sure to convert everything together. 🫶
The OLD behavior for this policy is to place MSVC runtime library flags in the default CMAKE_<LANG>_FLAGS_<CONFIG> cache entries and ignore the CMAKE_MSVC_RUNTIME_LIBRARY abstraction. The NEW behavior for this policy is to not place MSVC runtime library flags in the default cache entries and use the abstraction instead.
This policy was introduced in CMake version 3.15. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
CMP0090
Added in version 3.15.
export(PACKAGE) does not populate package registry by default. 🙈
In CMake 3.14 and below the export(PACKAGE) command populated the user package registry by default and users needed to set the CMAKE_EXPORT_NO_PACKAGE_REGISTRY to disable it, e.g. in automated build and packaging environments. Since the user package registry is stored outside the build tree, this side effect should not be enabled by default. Therefore CMake 3.15 and above prefer that export(PACKAGE) does nothing unless an explicit CMAKE_EXPORT_PACKAGE_REGISTRY variable is set to enable it. This policy provides compatibility with projects that have not been updated.
The OLD behavior for this policy is for export(PACKAGE) command to populate the user package registry unless CMAKE_EXPORT_NO_PACKAGE_REGISTRY is enabled. The NEW behavior is for export(PACKAGE) command to do nothing unless the CMAKE_EXPORT_PACKAGE_REGISTRY is enabled.
This policy was introduced in CMake version 3.15. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
CMP0089
Added in version 3.15.
Compiler id for IBM Clang-based XL compilers is now XLClang. 🦋
CMake 3.15 and above recognize that IBM's Clang-based XL compilers that define __ibmxl__ are a new front-end distinct from xlc with a different command line and set of capabilities. CMake now prefers to present this to projects by setting the CMAKE_<LANG>_COMPILER_ID variable to XLClang instead of XL. However, existing projects may assume the compiler id for Clang-based XL is just XL as it was in CMake versions prior to 3.15. Therefore this policy determines for Clang-based XL compilers which compiler id to report in the CMAKE_<LANG>_COMPILER_ID variable after language <LANG> is enabled by the project() or enable_language() command. The policy must be set prior to the invocation of either command. ⚠️
The OLD behavior for this policy is to use compiler id XL. The NEW behavior for this policy is to use compiler id XLClang.
This policy was introduced in CMake version 3.15. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0089 variable to control the warning.
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 💀
🌈 Policies Introduced by CMake 3.14
CMP0088
Added in version 3.14.
FindBISON runs bison in CMAKE_CURRENT_BINARY_DIR when executing.
The module provides a bison_target() command which generates BISON output. In CMake 3.13 and below the command would generate a custom build rule that runs bison in the source directory. CMake 3.14 and later prefer to run it in the build directory and use CMAKE_CURRENT_BINARY_DIR as the WORKING_DIRECTORY of its add_custom_command() invocation. This ensures that any implicitly generated file is written to the build tree rather than the source. 🎀
This policy provides compatibility for projects that have not been updated to expect the new behavior.
The OLD behavior for this policy is for bison_target() to use the current source directory for the WORKING_DIRECTORY and where to generate implicit files. The NEW behavior of this policy is to use the current binary directory for the WORKING_DIRECTORY and where to generate implicit files.
This policy was introduced in CMake version 3.14. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, 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. 💀
CMP0087
Added in version 3.14.
install(CODE) and install(SCRIPT) support generator expressions. 🌟
In CMake 3.13 and earlier, install(CODE) and install(SCRIPT) did not evaluate generator expressions. CMake 3.14 and later will evaluate generator expressions for install(CODE) and install(SCRIPT).
The OLD behavior of this policy is for install(CODE) and install(SCRIPT) to not evaluate generator expressions. The NEW behavior is to evaluate generator expressions for install(CODE) and install(SCRIPT).
That bit right there is lowkey the whole plot twist, bestie: what actually matters is the value of this policy setting at the end of the directory scope — not whatever it was chillin' at when install(CODE) or install(SCRIPT) got called. And yes, that has real implications for calling these commands from places that have their own policy scope but not their own directory scope (looking at you, files brought in via include() instead of add_subdirectory()). Sneaky. 🫣
This policy showed up in CMake version 3.14. You can set it with cmake_policy() or cmake_minimum_required(). If you don't set it, CMake warns you 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. Not a vibe you want to build on, fr fr. 💀
CMP0086
Added in version 3.14. ✨
UseSWIG honors SWIG_MODULE_NAME via -module flag.
Starting with CMake 3.14, UseSWIG passes the option -module <module_name> to the SWIG compiler if the file property SWIG_MODULE_NAME is specified. This policy exists to keep compatibility with projects that expect the legacy behavior.
- The OLD behavior for this policy is to never pass the
-moduleoption. - The NEW behavior is to pass the
-moduleoption to the SWIG compiler ifSWIG_MODULE_NAMEis specified.
This policy was introduced in CMake version 3.14. 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.
CMP0085
Added in version 3.14. 🦋
$<IN_LIST:...> handles empty list items.
In CMake 3.13 and lower, the $<IN_LIST:...> generator expression always returned 0 if the first argument was empty — even if the list contained an empty item. That's inconsistent with the IN_LIST behavior of if(), which this generator expression is literally meant to emulate. CMake 3.14 and later handles this case correctly.
- The OLD behavior of this policy is for
$<IN_LIST:...>to always return0if the first argument is empty. - The NEW behavior is to return
1if the first argument is empty and the list contains an empty item.
This policy was introduced in CMake version 3.14. 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.
CMP0084
Added in version 3.14. 💅
The FindQt module does not exist for find_package().
Here's the tea: the existence of FindQt means that for Qt upstream to provide package config files that can be found by find_package(Qt), the consuming project has to explicitly specify find_package(Qt CONFIG). Removing this module gives Qt a path forward for exporting its own config files, which can easily be found by consuming projects.
This policy pretends that CMake's internal FindQt module does not exist for find_package(). If a project really wants to use Qt 3 or 4, it can call find_package(Qt[34]), include(FindQt), or add FindQt to their CMAKE_MODULE_PATH.
- The OLD behavior of this policy is for
FindQtto exist forfind_package(). - The NEW behavior is to pretend that it doesn't exist for
find_package().
This policy was introduced in CMake version 3.14. 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.
CMP0083
Added in version 3.14. 🔥
To control generation of Position Independent Executable (PIE) or not, some flags are required at link time.
CMake 3.13 and lower did not add these link flags when POSITION_INDEPENDENT_CODE is set. Rude, honestly.
- The OLD behavior for this policy is to not manage PIE link flags.
- The NEW behavior is to add link flags if
POSITION_INDEPENDENT_CODEis set:- Set to
TRUE: flags to produce a position independent executable are passed to the linker step. For example-piefor GCC. - Set to
FALSE: flags not to produce a position independent executable are passed to the linker step. For example-no-piefor GCC. - Not set: no flags are passed to the linker step.
- Set to
Since a given linker may not support PIE flags in all environments in which it is used, it is the project's responsibility to use the CheckPIESupported module to check for support — that way you can ensure the POSITION_INDEPENDENT_CODE target property for executables will actually be honored at link time. Don't just assume, bestie. Check. 🫶
This policy was introduced in CMake version 3.14. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn, and uses OLD behavior.
Note: the Android platform has a special handling of PIE, so it is not required to use the CheckPIESupported module to ensure flags are passed to the linker.
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
Examples
Behave like CMake 3.13 and do not apply any PIE flags at link stage:
cmake_minimum_required(VERSION 3.13)
project(foo)
# ...
add_executable(foo ...)
set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE)
Use the CheckPIESupported module to detect whether PIE is supported by the current linker and environment. Apply PIE flags only if the linker supports them:
cmake_minimum_required(VERSION 3.14) # CMP0083 NEW
project(foo)
include(CheckPIESupported)
check_pie_supported()
# ...
add_executable(foo ...)
set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE)
CMP0082
Added in version 3.14. 🎀
Install rules from add_subdirectory() calls are interleaved with those in the caller.
CMake 3.13 and lower ran the install rules from add_subdirectory() after all other install rules — even if add_subdirectory() was called before those other install rules. Which is giving chaotic energy, ngl. CMake 3.14 and above prefer to interleave these add_subdirectory() install rules with the others so that they are run in the order they are declared. This policy provides compatibility for projects that have not been updated to expect the new behavior.
- The OLD behavior for this policy is to run the install rules from
add_subdirectory()after the other install rules. - The NEW behavior for this policy is to run all install rules in the order they are declared.
This policy was introduced in CMake version 3.14. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake does not warn by default, and uses OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0082 variable to control the warning. 👀
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌈 Policies Introduced by CMake 3.13 🌈
CMP0081
Added in version 3.13. ⭐
Relative paths not allowed in LINK_DIRECTORIES target property.
CMake 3.12 and lower allowed the LINK_DIRECTORIES directory property to contain relative paths. But like… the base path for such relative entries is not well defined? So CMake 3.13 and later will issue a FATAL_ERROR if the LINK_DIRECTORIES target property (which is initialized by the LINK_DIRECTORIES directory property) contains a relative path.
- The OLD behavior for this policy is not to warn about relative paths in the
LINK_DIRECTORIEStarget property. - The NEW behavior for this policy is to issue a
FATAL_ERRORifLINK_DIRECTORIEScontains a relative path.
This policy was introduced in CMake version 3.13. 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.
CMP0080
Added in version 3.13. 🦋
BundleUtilities cannot be included at configure time.
The macros provided by BundleUtilities are intended to be invoked at install time rather than at configure time, because they depend on the listed targets already existing at the time they are invoked. If they are invoked at configure time, the targets haven't been built yet, and the commands will fail. Like, of course they will. 😭
This policy restricts the inclusion of BundleUtilities to cmake -P style scripts and install rules. Specifically, it looks for the presence of CMAKE_GENERATOR and throws a fatal error if it exists.
- The OLD behavior of this policy is to allow
BundleUtilitiesto be included at configure time. - The NEW behavior of this policy is to disallow such inclusion.
This policy was introduced in CMake version 3.13. 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.
CMP0079
Added in version 3.13. 👑
target_link_libraries() allows use with targets in other directories.
Like, before CMake 3.13, target_link_libraries() was kind of a gatekeeper 💅 — it would straight-up refuse targets that weren't created in the calling directory as its first argument, at least for calls that update the LINK_LIBRARIES property of the target itself. Rude.
But it did accidentally accept targets from other directories on calls that only update INTERFACE_LINK_LIBRARIES — except it would just add entries to the property as if the call were made in the original directory. So those link interface libraries specified this way were always looked up by generators in the scope of the original target, not in the scope that actually called target_link_libraries(). Oops? 🙈
CMake 3.13 said "aht aht, we're fixing this" ✨ — now the target_link_libraries() command can be called from any directory to add link dependencies and link interface libraries to targets created in other directories. The entries get added to LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES using a special (internal) suffix, which tells the generators to look up the names in the calling scope instead of the scope that created the target. Iconic. 🎀
This policy is basically the compatibility blanket for projects that already use target_link_libraries() with the INTERFACE keyword on a target in another directory to add INTERFACE_LINK_LIBRARIES entries that get looked up in the target's directory. Those projects should be updated to be aware of the new scoping rules in that case. No cap.
The OLD behavior of this policy is to disallow target_link_libraries() calls naming targets from another directory — except in the previously accidentally allowed case of using the INTERFACE keyword only. The NEW behavior is to allow all such calls but use the new scoping rules. 🌈
This policy was introduced in CMake version 3.13. 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. 💀
🦋 CMP0078
Added in version 3.13.
UseSWIG generates standard target names.
Starting with CMake 3.13, UseSWIG generates now standard target names. This policy provides compatibility with projects that expect the legacy behavior. Yes bestie, it's a whole vibe shift. ✨
The OLD behavior for this policy relies on the UseSWIG_TARGET_NAME_PREFERENCE variable, which can be used to specify an explicit preference. The value may be one of:
LEGACY— legacy strategy is applied. VariableSWIG_MODULE_<name>_REAL_NAMEmust be used to get the real target name. This is the default if not specified.STANDARD— target name matches the specified name.
This policy was introduced in CMake version 3.13. 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. 💀
🍓 CMP0077
Added in version 3.13.
option() honors normal variables.
Okay so the option() command is typically used to create a cache entry so users can set the option. Makes sense, love that for us. But 😭 there are cases where a normal (non-cached) variable with the same name as the option might be defined by the project before it calls the option() command. Like, a project that embeds another project as a subdirectory might wanna hard-code the subproject's options to build the way it needs. Fair!
For historical reasons in CMake 3.12 and below, the option() command removes a normal (non-cached) variable of the same name when:
- a cache entry of the specified name does not exist at all, or
- a cache entry of the specified name exists but has not been given a type (e.g. via
-D<name>=ONon the command line).
In both of these cases (typically on the first run in a new build tree), the option() command gives the cache entry type BOOL and removes any normal (non-cached) variable of the same name. In the remaining case — where the cache entry of the specified name already exists and has a type (typically on later runs in a build tree) — the option() command changes nothing and any normal variable of the same name remains set.
In CMake 3.13 and above, the option() command prefers to do nothing when a normal variable of the given name already exists. It does not create or update a cache entry, and it does not remove the normal variable. The new behavior is consistent between the first and later runs in a build tree — consistency slay 💅. This policy provides compatibility with projects that haven't been updated to expect the new behavior.
When the option() command sees a normal variable of the given name:
- The OLD behavior for this policy is to proceed even when a normal variable of the same name exists. If the cache entry does not already exist and have a type, then it is created and/or given a type, and the normal variable is removed.
- The NEW behavior for this policy is to do nothing when a normal variable of the same name exists. The normal variable is not removed. The cache entry is not created or updated, and is ignored if it exists.
See CMP0126 for a similar policy for the set(CACHE) command, but note that there are some differences in NEW behavior between the two policies. 👀
This policy was introduced in CMake version 3.13. It may be set by cmake_policy() or cmake_minimum_required(). If it is not set, CMake warns, and uses OLD behavior.
Use the CMAKE_POLICY_DEFAULT_CMP0077 variable to set the policy for a third-party project in a subdirectory without modifying it. So polite of you. 🫶
Note: The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. 💀
🌸 CMP0076
Added in version 3.13.
The target_sources() command converts relative paths to absolute.
In CMake 3.13 and above, the target_sources() command now converts relative source file paths to absolute paths in the following cases:
- Source files are added to the target's
INTERFACE_SOURCESproperty. - The target's
SOURCE_DIRproperty differs fromCMAKE_CURRENT_SOURCE_DIR.
A path that begins with a generator expression is always left unmodified. No touchy. 🙅♀️
This policy provides compatibility with projects that haven't been updated to expect this behavior. The OLD behavior for this policy is to leave all relative source file paths unmodified. The NEW behavior is to convert relative paths to absolute according to the above rules.
This policy was introduced in CMake version 3.13. 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. 💀
🧚 Policies Introduced by CMake 3.12
⭐ CMP0075
Added in version 3.12.
Include file check macros honor CMAKE_REQUIRED_LIBRARIES.
In CMake 3.12 and above:
- the
check_include_file()command in theCheckIncludeFilemodule, - the
check_include_file_cxx()command in theCheckIncludeFileCXXmodule, and - the
check_include_files()command in theCheckIncludeFilesmodule
now prefer to link the check executable to the libraries listed in the CMAKE_REQUIRED_LIBRARIES variable. This policy provides compatibility with projects that have not been updated to expect this behavior. 💖
The OLD behavior for this policy is to ignore CMAKE_REQUIRED_LIBRARIES in the include file check commands. The NEW behavior of this policy is to honor CMAKE_REQUIRED_LIBRARIES in the include file check commands.
This policy was introduced in CMake version 3.12. 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. 💀
🔥 CMP0074
Added in version 3.12.
find_package() uses <PackageName>_ROOT variables.
In CMake 3.12 and above, the find_package(<PackageName>) command now searches prefixes specified by the <PackageName>_ROOT CMake variable and the <PackageName>_ROOT environment variable. Package roots are maintained as a stack, so nested calls to all find_* commands inside find modules and config packages also search the roots as prefixes. Nested, stacked, organized — we love a data structure moment. 📚 This policy provides compatibility with projects that have not been updated to avoid using <PackageName>_ROOT variables for other purposes.
The OLD behavior for this policy is to ignore <PackageName>_ROOT variables. The NEW behavior for this policy is to use <PackageName>_ROOT variables.
This policy was introduced in CMake version 3.12. 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. 💀
🎀 CMP0073
Added in version 3.12.
Do not produce legacy _LIB_DEPENDS cache entries.
Ancient CMake versions once used <tgt>_LIB_DEPENDS cache entries to propagate library link dependencies. Like, ancient ancient — history channel vibes 🏺. This has long been done by other means, leaving the export_library_dependencies() command as the only user of these values. That command has long been disallowed by policy CMP0033, but the <tgt>_LIB_DEPENDS cache entries were left for compatibility with possible non-standard uses by projects.
CMake 3.12 and up would lowkey just rather not create those cache entries at all, periodt. So this policy exists purely for compat with projects that never got around to not using them. 🫶
- OLD behavior — go ahead and set the
<tgt>_LIB_DEPENDScache entries. - NEW behavior — don't set them. Ever. Nope.
This policy landed in CMake version 3.12. You can set it with cmake_policy() or cmake_minimum_required(). And here's the spicy bit: if you don't set it, CMake doesn't warn you — it just quietly uses OLD behavior. 💀
Heads up bestie: the OLD behavior of a policy is deprecated by definition and may be straight-up removed in a future version of CMake. So don't get comfy.
🌈 Policies Introduced by CMake 3.11
✨ CMP0072 ✨
Added in version 3.11.
FindOpenGL now prefers GLVND by default when it's available. Iconic behavior honestly.
So here's the situation: the FindOpenGL module hands you an OpenGL::GL target and an OPENGL_LIBRARIES variable to use for legacy GL interfaces. When both a legacy GL library (like libGL.so) and the GLVND libraries for OpenGL and GLX (like libOpenGL.so and libGLX.so) are available, the module has to pick one. It documents an OpenGL_GL_PREFERENCE variable you can use to state your explicit preference. But when no preference is set at all, the module still has to choose a default. 😭
CMake 3.11 and above prefer to choose GLVND libraries. This policy keeps compatibility with projects that expect the legacy GL library to get used.
- OLD behavior — set
OpenGL_GL_PREFERENCEtoLEGACY. - NEW behavior — set
OpenGL_GL_PREFERENCEtoGLVND.
This policy was introduced in CMake version 3.11. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior. 📢
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🎀 Policies Introduced by CMake 3.10
🌸 CMP0071 🌸
Added in version 3.10.
This one's about letting AUTOMOC and AUTOUIC process GENERATED files. The glow-up we deserved.
Since version 3.10, CMake processes regular and GENERATED source files in AUTOMOC and AUTOUIC. In earlier CMake versions, only regular source files got processed — GENERATED source files were just silently ignored. Rude, honestly. 🙈
So this policy decides how source files that are GENERATED get treated in AUTOMOC and AUTOUIC.
- OLD behavior — ignore
GENERATEDsource files inAUTOMOCandAUTOUIC. - NEW behavior — process
GENERATEDsource files inAUTOMOCandAUTOUICjust like regular source files. Slay.
Note: to silence the CMP0071 warning, you can exclude source files fromAUTOMOCandAUTOUICprocessing by setting the source file propertiesSKIP_AUTOMOC,SKIP_AUTOUICorSKIP_AUTOGEN.
Source skip example:
# ...
set_property(SOURCE /path/to/file1.h PROPERTY SKIP_AUTOMOC ON)
set_property(SOURCE /path/to/file2.h PROPERTY SKIP_AUTOUIC ON)
set_property(SOURCE /path/to/file3.h PROPERTY SKIP_AUTOGEN ON)
# ...
This policy was introduced in CMake version 3.10. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior. 📢
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🦋 CMP0070 🦋
Added in version 3.10.
This one defines file(GENERATE) behavior for relative paths. Vibe check on your paths, basically.
CMake 3.10 and newer define that relative paths given to INPUT and OUTPUT arguments of file(GENERATE) are interpreted relative to the current source and binary directories, respectively. CMake 3.9 and lower didn't define any behavior for relative paths — but also didn't diagnose them either 😭 — and accidentally treated them relative to the process working directory. Policy CMP0070 keeps compatibility with projects that leaned on that old undefined behavior. (Not me judging. Okay, a little.)
This policy affects behavior of relative paths given to file(GENERATE).
- OLD behavior — treat the paths relative to the working directory of CMake.
- NEW behavior — interpret relative paths with respect to the current source or binary directory of the caller.
This policy was introduced in CMake version 3.10. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior. 📢
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
💜 Policies Introduced by CMake 3.9
🔥 CMP0069 🔥
Added in version 3.9.
INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. No cap, it's serious now.
CMake 3.9 and newer prefer to add IPO flags whenever the INTERPROCEDURAL_OPTIMIZATION target property is enabled — and will straight up produce an error if the flags aren't known to CMake for the current compiler. And because a given compiler may not support IPO flags in all the environments it's used in, it's now the project's responsibility to use the CheckIPOSupported module to check for support before enabling the INTERPROCEDURAL_OPTIMIZATION target property. That approach lets a project conditionally turn IPO on when it's supported. It also lets an end user set the CMAKE_INTERPROCEDURAL_OPTIMIZATION variable in an environment known to support IPO — even if the project itself doesn't enable the property. Bestie collaboration. 💅
Since CMake 3.8 and lower only honored INTERPROCEDURAL_OPTIMIZATION for the Intel compiler on Linux, some projects may be out here unconditionally enabling the target property. Policy CMP0069 keeps compatibility with such projects. 🫶
This policy takes effect whenever the IPO property is enabled.
- OLD behavior — add IPO flags only for Intel compiler on Linux.
- NEW behavior — add IPO flags for the current compiler, or produce an error if CMake doesn't know the flags.
This policy was introduced in CMake version 3.9. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior. 📢
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🌟 Examples 🌟
Behave like CMake 3.8 and do not apply any IPO flags except for Intel compiler on Linux:
cmake_minimum_required(VERSION 3.8)
project(foo)
# ...
set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
Use the CheckIPOSupported module to detect whether IPO is supported by the current compiler, environment, and CMake version. Produce a fatal error if support is not available:
cmake_minimum_required(VERSION 3.9) # CMP0069 NEW
project(foo)
include(CheckIPOSupported)
check_ipo_supported()
# ...
set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
Apply IPO flags only if compiler supports it:
cmake_minimum_required(VERSION 3.9) # CMP0069 NEW
project(foo)
include(CheckIPOSupported)
# ...
check_ipo_supported(RESULT result)
if(result)
set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
Apply IPO flags without any checks. This may lead to build errors if IPO is not supported by the compiler in the current environment. Produce an error if CMake does not know IPO flags for the current compiler:
cmake_minimum_required(VERSION 3.9) # CMP0069 NEW
project(foo)
# ...
set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
🍓 CMP0068 🍓
Added in version 3.9.
RPATH settings on macOS do not affect install_name. Let that sink in — the settings are finally minding their own business.
CMake 3.9 and newer remove any effect the following settings may have on the install_name of a target on macOS:
BUILD_WITH_INSTALL_RPATHtarget propertySKIP_BUILD_RPATHtarget propertyCMAKE_SKIP_RPATHvariableCMAKE_SKIP_INSTALL_RPATHvariable
Previously, setting BUILD_WITH_INSTALL_RPATH had the effect of setting both the install_name of a target to INSTALL_NAME_DIR and the RPATH to INSTALL_RPATH. In CMake 3.9, it only affects setting of RPATH. However, if you want INSTALL_NAME_DIR to apply to the target in the build tree, you may set BUILD_WITH_INSTALL_NAME_DIR. 🎀
And if SKIP_BUILD_RPATH, CMAKE_SKIP_RPATH or CMAKE_SKIP_INSTALL_RPATH were used to strip the directory portion of the install_name of a target, you may set INSTALL_NAME_DIR="" instead.
- OLD behavior — use the RPATH settings for
install_nameon macOS. - NEW behavior — ignore the RPATH settings for
install_nameon macOS.
This policy was introduced in CMake version 3.9. It may be set by cmake_policy() or cmake_minimum_required(). If it's not set, CMake warns, and uses OLD behavior. 📢
The OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake.
🧚 Policies Introduced by CMake 3.8
👑 CMP0067 👑
Added in version 3.8.
Honor language standard in try_compile() source-file signature. That's it, that's the whole vibe. 💅
okay so the source-file signature of try_compile() is literally built so callers can vibe-check whether they'll actually be able to compile a given source file with whatever toolchain they're rolling with ✨ and like — to match real compiler behavior, any language standard mode should match too. but plot twist: CMake 3.7 and below did NOT do this 😭. CMake 3.8 and above prefer to honor the language standard settings for C, CXX (C++), and CUDA using the values of these variables:
CMAKE_C_STANDARDCMAKE_C_STANDARD_REQUIREDCMAKE_C_EXTENSIONSCMAKE_CXX_STANDARDCMAKE_CXX_STANDARD_REQUIREDCMAKE_CXX_EXTENSIONSCMAKE_CUDA_STANDARDCMAKE_CUDA_STANDARD_REQUIREDCMAKE_CUDA_EXTENSIONS
this policy is basically the compatibility era for projects that do NOT expect the language standard settings to get used automatically 🙈
the OLD behavior of this policy is to ignore those language standard setting variables when generating the try_compile test project. the NEW behavior is to honor them. periodt 💅
this policy was introduced in CMake version 3.8. it may be set by cmake_policy() or cmake_minimum_required(). if it is not set, CMake does not warn by default, and uses OLD behavior.
see the docs for the CMAKE_POLICY_WARNING_CMP0067 variable (the general pattern is CMAKE_POLICY_WARNING_CMP<NNNN>) to control the warning 🎀
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. like, it's giving "on borrowed time" fr fr 💀
🌈 Policies Introduced by CMake 3.7 🌈
CMP0066 ✨
added in version 3.7.
honor per-config flags in the try_compile() source-file signature 🫶
so the source file signature of the try_compile() command uses the value of the CMAKE_<LANG>_FLAGS variable in the test project so that the test compilation works exactly like it would in the main project. but — and this is the messy part 😭 — CMake 3.6 and below do NOT also honor config-specific compiler flags like the ones in CMAKE_<LANG>_FLAGS_DEBUG. CMake 3.7 and above prefer to honor config-specific compiler flags too. this policy provides compatibility for projects that don't expect config-specific compiler flags to be used.
the OLD behavior of this policy is to ignore config-specific flag variables like CMAKE_<LANG>_FLAGS_DEBUG and only use CMake's built-in defaults for the current compiler and platform.
the NEW behavior of this policy is to honor config-specific flag variables like CMAKE_<LANG>_FLAGS_DEBUG 💖
this policy was introduced in CMake version 3.7. it may be set by cmake_policy() or cmake_minimum_required(). if it is not set, CMake does not warn by default, and uses OLD behavior.
see the docs for the CMAKE_POLICY_WARNING_CMP0066 variable (pattern: CMAKE_POLICY_WARNING_CMP<NNNN>) to control the warning 👑
Note: the OLD behavior of a policy is deprecated by definition and may be removed in a future version of CMake. yes bestie we're saying it again, it's important 💀
💀 UNSUPPORTED POLICIES 💀
the following policies are no longer supported. like, at all. projects' calls to cmake_minimum_required(VERSION) or cmake_policy(VERSION) must set them to NEW. their OLD behaviors have been removed from CMake 🫠
🌸 Policies Introduced by CMake 3.4, Removed by CMake 4.0 🌸
CMP0065
Warning: the OLD behavior of this policy was removed in CMake version 4.0. this policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy()😤
added in version 3.4.
do not add flags to export symbols from executables without the ENABLE_EXPORTS target property.
okay so CMake 3.3 and below, for historical reasons, always linked executables on some platforms with flags like -rdynamic to export symbols from the executables for use by any plugins they may load via dlopen. CMake 3.4 and above prefer to do this only for executables that are explicitly marked with the ENABLE_EXPORTS target property 🎀
the OLD behavior of this policy is to always use the additional link flags when linking executables regardless of the value of the ENABLE_EXPORTS target property.
the NEW behavior of this policy is to only use the additional link flags when linking executables if the ENABLE_EXPORTS target property is set to True.
this policy was introduced in CMake version 3.4. prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). if it was not set, CMake did not warn by default, and used OLD behavior.
see the docs for the CMAKE_POLICY_WARNING_CMP0065 variable (pattern: CMAKE_POLICY_WARNING_CMP<NNNN>) to control the warning in CMake versions before 4.0 ⭐
CMP0064
Warning: the OLD behavior of this policy was removed in CMake version 4.0. this policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy()😤
added in version 3.4.
recognize TEST as an operator for the if() command.
the TEST operator was added to the if() command to determine if a given test name was created by the add_test() command 👀
the OLD behavior for this policy is to ignore the TEST operator. the NEW behavior is to interpret the TEST operator. slay.
this policy was introduced in CMake version 3.4. prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). if it was not set, CMake warned, and used OLD behavior.
🦋 Policies Introduced by CMake 3.3, Removed by CMake 4.0 🦋
CMP0063
Warning: the OLD behavior of this policy was removed in CMake version 4.0. this policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy()😤
added in version 3.3.
honor visibility properties for all target types 💅
the <LANG>_VISIBILITY_PRESET and VISIBILITY_INLINES_HIDDEN target properties affect visibility of symbols during dynamic linking. when first introduced, these properties affected compilation of sources only in shared libraries, module libraries, and executables with the ENABLE_EXPORTS property set. this was sufficient for the basic use cases of shared libraries and executables with plugins. however — some sources may be compiled as part of static libraries or object libraries and then linked into a shared library later 😭 so CMake 3.3 and above prefer to honor these properties for sources compiled in all target types. this policy preserves compatibility for projects expecting the properties to work only for some target types.
the OLD behavior for this policy is to ignore the visibility properties for static libraries, object libraries, and executables without exports. the NEW behavior for this policy is to honor the visibility properties for all target types. iconic.
this policy was introduced in CMake version 3.3. prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). if it was not set, CMake warned, and used OLD behavior.
CMP0062
Warning: the OLD behavior of this policy was removed in CMake version 4.0. this policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy()😤
added in version 3.3.
disallow install() of an export() result 🙅♀️
the export() command generates a file containing Imported Targets, which is suitable for use from the build directory. it is NOT suitable for installation because it contains absolute paths to buildsystem locations, and is particular to a single build configuration. like, it does not travel well, bestie ✈️😭
the install(EXPORT) generates and installs files which contain Imported Targets. these files are generated with relative paths (unless the user specifies absolute paths), and are designed for multi-configuration use. see Creating Packages for more 🎁
CMake 3.3 no longer allows the use of the install(FILES) command with the result of the export() command.
the OLD behavior for this policy is to allow installing the result of an export() command. the NEW behavior for this policy is not to allow installing the result of an export() command.
this policy was introduced in CMake version 3.3. prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). if it was not set, CMake warned, and used OLD behavior.
CMP0061
Warning: the OLD behavior of this policy was removed in CMake version 4.0. this policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy()😤
added in version 3.3.
CTest does not by default tell make to ignore errors (-i) 🚫
the ctest_build() and build_command() commands no longer generate build commands for Makefile Generators with the -i option. previously this was done to help build as much of tested projects as possible. however, this behavior is not consistent with other generators and also causes the return code of the make tool to be meaningless 💀 like, what's the point of a return code that means nothing??
of course users may still add this option manually by setting CTEST_BUILD_COMMAND or the MAKECOMMAND cache entry. see the CTest Build Step MakeCommand setting documentation for their effects 👑
The OLD behavior for this policy was to add -i to the make calls inside CTest. The NEW behavior is to not add -i. That's it, that's the whole vibe. 😌
This policy showed up in CMake version 3.3. Before it got removed in CMake version 4.0, you could set it with cmake_policy() or cmake_minimum_required(). If it was never set, CMake didn't warn about it at all — it just silently used the OLD behavior. 🫶
🔥 CMP0060
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy(). No negotiating, bestie. 💀
Added in version 3.3.
Link libraries by full path even in implicit directories. ✨
So here's the lore. Policy CMP0003 was introduced with the intention of always linking library files by full path whenever a full path is handed to the target_link_libraries() command. Slay. But — and there's always a but — on some platforms (e.g. HP-UX) the compiler front-end adds alternative library search paths for the current architecture. Like, /usr/lib/<arch> has alternatives to libraries in /usr/lib for the current architecture. On platforms like that, find_library() may find a library such as /usr/lib/libfoo.so that does not belong to the current architecture. Awkward. 🙈
Back before policy CMP0003, projects would still build in cases like this, because the incorrect library path would get converted to -lfoo on the link line, and then the linker would find the proper library in the arch-specific search path that the compiler front-end provides implicitly. Iconic workaround behaviour. At the time, we chose to stay compatible with those projects by always converting library files found in implicit link directories into -lfoo flags, which asks the linker to go search for them. That approach let existing projects keep building while still linking to libraries outside implicit link directories by full path (like the ones in the build tree). 🧚
CMake does let projects override this behavior by using an IMPORTED library target with its IMPORTED_LOCATION property set to the desired full path to a library file. In fact, many Find Modules are learning to provide Imported Targets instead of just the traditional Foo_LIBRARIES variable listing library files. Literally so much better. But it makes the link line generated for a library found by a Find Module depend on whether it's linked through an imported target or not — which is, highkey, inconsistent. 😭
And it gets messier: this behavior has been a source of confusion, because the generated link line for a library file depends on its location. It's also a problem for projects trying to link statically, because flags like -Wl,-Bstatic -lfoo -Wl,-Bdynamic may be used to help the linker select libfoo.a instead of libfoo.so — but then they leak dynamic linking into the libraries that follow. (Check the LINK_SEARCH_END_STATIC target property for the solution typically used for that exact problem. 🩹)
When that special case for libraries in implicit link directories first dropped, the list of implicit link directories was just hard-coded (e.g. /lib, /usr/lib, and a few others). Since then, CMake leveled up and learned to detect the implicit link directories used by the compiler front-end. If necessary, the find_library() command could be taught to use this information to help find libraries of the proper architecture. Noted for the future. 💅
For all these reasons, CMake 3.3 and above prefer to drop the special case entirely and link libraries by full path even when they live in implicit link directories. Policy CMP0060 is the compatibility blanket for existing projects. 🫶
- The OLD behavior for this policy is to ask the linker to search for libraries whose full paths are known to be in implicit link directories.
- The NEW behavior for this policy is to link libraries by full path even if they are in implicit link directories.
This policy was introduced in CMake version 3.3. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake did not warn by default, and used OLD behavior. 🙃
Peep the documentation of the CMAKE_POLICY_WARNING_CMP0060 variable (that's the CMAKE_POLICY_WARNING_CMP<NNNN> pattern, iykyk) to control the warning in CMake versions before 4.0. 🔔
🦋 CMP0059
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.3.
Do not treat DEFINITIONS as a built-in directory property. 🎀
CMake 3.3 and above no longer hand you a list of definitions through the DEFINITIONS directory property. The COMPILE_DEFINITIONS directory property is right there and you can use that instead. Upgrade your life. ✨
- The OLD behavior for this policy is to provide the list of flags given so far to the
add_definitions()command. - The NEW behavior is to behave as a normal user-defined directory property.
This policy was introduced in CMake version 3.3. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior. Yes, this one actually told you. 💀
🌸 CMP0058
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.3.
Ninja requires custom command byproducts to be explicit. 👑
Okay so picture this: an intermediate file gets generated during the build, and it's consumed by an expensive operation or by a huge tree of dependents. You can cut down the work needed for an incremental rebuild by updating the file's timestamp only when its content actually changes. With that approach, the generation rule has to have a separate output file that's always updated with a new timestamp newer than any of the rule's dependencies — so the build tool only re-runs the rule when the input changes. We call that separate output file a rule's witness, and the generated file a rule's byproduct. 📝
Byproducts may not be listed as outputs, because their timestamps are allowed to be older than the inputs. And no build tools (like make) that existed back when CMake was designed have any way to express byproducts. So CMake versions before 3.2 had no way to specify them at all. Projects typically just left byproducts undeclared in the rules that generate them. Like this:
add_custom_command(
OUTPUT witness.txt
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/input.txt
byproduct.txt # timestamp may not change
COMMAND ${CMAKE_COMMAND} -E touch witness.txt
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
)
add_custom_target(Provider DEPENDS witness.txt)
add_custom_command(
OUTPUT generated.c
COMMAND expensive-task -i byproduct.txt -o generated.c
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/byproduct.txt
)
add_library(Consumer generated.c)
add_dependencies(Consumer Provider)
This works great for every generator except Ninja. 😭 The Ninja build tool sees a rule listing byproduct.txt as a dependency and no rule listing it as an output. Ninja then complains that there's no way to satisfy the dependency and stops building — even though there are order-only dependencies that make sure byproduct.txt will exist before its consumers need it. For further details on why Ninja works this way, see the discussion of this problem in Ninja Issue 760 (https://github.com/ninja-build/ninja/issues/760). 🔍
Instead of leaving byproducts undeclared in the rules that generate them, Ninja expects byproducts to be listed along with the other outputs. Rules like that may be marked with a restat option that tells Ninja to check the timestamps of outputs after the rules run. That way, byproducts whose timestamps don't change don't make their dependents rebuild for no reason. Chef's kiss. 🤌
But since the approach above never tells CMake which custom command generates byproduct.txt, the Ninja generator doesn't have enough info to add the byproduct as an output of any rule. CMake 2.8.12 and above work around this and let projects using the above approach build, by generating phony build rules that tell Ninja to tolerate such missing files. 💫
However — that workaround prevents Ninja from diagnosing a dependency that's really missing. And it also works poorly in in-source builds, where every custom command dependency, even on source files, needs to be treated this way, because CMake doesn't have enough information to know which files are generated as byproducts of custom commands. Messy. 🙈
🎀 Introducing Byproducts
CMake 3.2 introduced the BYPRODUCTS option to the add_custom_command() and add_custom_target() commands. This option lets byproducts be specified explicitly:
add_custom_command(
OUTPUT witness.txt
BYPRODUCTS byproduct.txt # explicit byproduct specification
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/input.txt
byproduct.txt # timestamp may not change
...
The BYPRODUCTS option is used by the Ninja generator to list byproducts among the outputs of the custom commands that generate them, and it's ignored by other generators. 🧚
CMake 3.3 and above prefer to require projects to specify custom command byproducts explicitly, so it can dodge the phony-rule workaround entirely. Policy CMP0058 was introduced to provide compatibility with existing projects that still need that workaround. 🫶
This policy has no effect on generators other than Ninja.
- The OLD behavior for this policy is to generate Ninja phony rules for unknown dependencies in the build tree.
- The NEW behavior for this policy is to not generate these, and instead require projects to specify custom command
BYPRODUCTSexplicitly.
Heads up bestie: the policy setting must be in scope at the end of the top-level CMakeLists.txt file of the project, and it has global effect. 🌍
This policy was introduced in CMake version 3.3. Before it got yeeted in CMake version 4.0, you could set it with cmake_policy() or cmake_minimum_required(). And if you didn't set it? CMake would straight up warn at you whenever it spotted unknown dependencies in out-of-source build trees, and then just vibe with OLD behavior. 🫠
🦋 CMP0057 🦋
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. Like, gone gone. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.3. ✨
It's giving: support the new IN_LIST operator in if().
CMake 3.3 adds support for the shiny new IN_LIST operator. That's the whole tea. 🍵
- The OLD behavior for this policy is to ignore the
IN_LISToperator (rude, honestly). - The NEW behavior is to actually interpret the
IN_LISToperator. Slay. 💅
This policy was introduced in CMake version 3.3. Before removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🎀 Policies Introduced by CMake 3.2, Removed by CMake 4.0 🎀
🌸 CMP0056 🌸
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.2. ✨
Honor link flags in the try_compile() source-file signature. Bestie, the link flags deserve respect too. 🔗
Okay so here's the lore: the try_compile() command's source-file signature generates a CMakeLists.txt file that builds the source file into an executable. And so that the source gets compiled the same way the calling project might compile it, the generated project sets the value of the CMAKE_<LANG>_FLAGS variable to whatever it is in the calling project. Makes sense, right? But the value of the CMAKE_EXE_LINKER_FLAGS variable may be needed in some cases too — and CMake 3.1 and lower just... didn't set it in the generated project. 🙈 CMake 3.2 and above prefer to set it so that linker flags are honored as well as compiler flags. This policy is the compatibility blanket for that pre-3.2 behavior.
- OLD behavior: don't set the value of the
CMAKE_EXE_LINKER_FLAGSvariable in the generated test project. - NEW behavior: set the value of the
CMAKE_EXE_LINKER_FLAGSvariable in the test project to the same as it is in the calling project. 💖
If the project code doesn't set the policy explicitly, users may set it on the command line by defining the CMAKE_POLICY_DEFAULT_CMP0056 variable in the cache. iykyk. 🧠
This policy was introduced in CMake version 3.2. Before removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake did not warn by default, and used OLD behavior.
See the documentation of the CMAKE_POLICY_WARNING_CMP0056 variable to control the warning in CMake versions before 4.0. 👀
💀 CMP0055 💀
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.2. ✨
Strict checking for the break() command. Time to hold break() accountable, fr fr. 🚨
CMake 3.1 and lower allowed calls to the break() command outside of a loop context, and also just ignored any arguments you gave it. Which was, and I cannot stress this enough, undefined behavior. 😭
- OLD behavior: let
break()be placed outside of loop contexts and ignore any arguments. - NEW behavior: issue an error if a misplaced
breakor any arguments are found. No more chaos gremlin energy. 🛑
This policy was introduced in CMake version 3.2. Before removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🌈 Policies Introduced by CMake 3.1, Removed by CMake 4.0 🌈
🦋 CMP0054 🦋
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.1. ✨
Only interpret if() arguments as variables or keywords when they're unquoted. Quoted means hands off, bestie. 🙅♀️
CMake 3.1 and above no longer implicitly dereference variables or interpret keywords in an if() command argument when it's a Quoted Argument or a Bracket Argument.
- OLD behavior: dereference variables and interpret keywords even if they're quoted or bracketed.
- NEW behavior: don't dereference variables or interpret keywords that have been quoted or bracketed.
Given the following partial example:
set(A E)
set(E "")
if("${A}" STREQUAL "")
message("Result is TRUE before CMake 3.1 or when CMP0054 is OLD")
else()
message("Result is FALSE in CMake 3.1 and above if CMP0054 is NEW")
endif()
After explicit expansion of variables this gives:
if("E" STREQUAL "")
With the policy set to OLD, implicit expansion reduces this semantically to:
if("" STREQUAL "")
With the policy set to NEW, the quoted arguments will not be further dereferenced:
if("E" STREQUAL "")
This policy was introduced in CMake version 3.1. Before removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
💜 CMP0053 💜
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.1. ✨
Simplify variable reference and escape sequence evaluation. Glow-up for the parser, honestly. 🧖♀️
CMake 3.1 introduced a much faster implementation of evaluation of the Variable References and Escape Sequences documented in the cmake-language(7) manual. While the behavior is identical to the legacy implementation in most cases, some corner cases were cleaned up to simplify the behavior. Specifically:
- Expansion of
@VAR@reference syntax defined by theconfigure_file()andstring(CONFIGURE)commands is no longer performed in other contexts. Stay in your lane,@VAR@. - Literal
${VAR}reference syntax may contain only alphanumeric characters (A-Z,a-z,0-9) and the characters_,.,/,-, and+. Note that$is technically allowed in the NEW behavior, but is invalid for OLD behavior — that's due to an oversight during the implementation of CMP0053, and its use as a literal variable reference is discouraged for this reason. 🙈 Variables with other characters in their name may still be referenced indirectly, e.g.
set(varname "otherwise & disallowed $ characters")
message("${${varname}}")
- The setting of policy
CMP0010is not considered, so improper variable reference syntax is always an error. No loopholes, no cap. 🚫 - More characters are allowed to be escaped in variable names. Previously, only
()#" \@^were valid characters to escape. Now any non-alphanumeric, non-semicolon, non-NUL character may be escaped following theescape_identityproduction in the Escape Sequences section of thecmake-language(7)manual. Glow-up indeed. ✨ - OLD behavior: honor the legacy behavior for variable references and escape sequences.
- NEW behavior: use the simpler variable expansion and escape sequence evaluation rules. 💖
This policy was introduced in CMake version 3.1. Before removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🎀 CMP0052 🎀
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.1. ✨
Reject source and build dirs in installed INTERFACE_INCLUDE_DIRECTORIES. Like, actually reject them. 🛑
CMake 3.0 and lower allowed subdirectories of the source directory or build directory to be in the INTERFACE_INCLUDE_DIRECTORIES of installed and exported targets — but only if the directory was also a subdirectory of the installation prefix. Which makes the installation depend on the existence of the source dir or binary dir, and the installation will be broken if either are removed after installation. 😬 Yeah. Not it.
See Include Directories and Usage Requirements for more on specifying include directories for targets.
- OLD behavior: export the content of the
INTERFACE_INCLUDE_DIRECTORIESwith the source or binary directory. - NEW behavior: issue an error if such a directory is used. Protective queen behavior. 👑
This policy was introduced in CMake version 3.1. Before removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
⭐ CMP0051 ⭐
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Added in version 3.1. ✨
List TARGET_OBJECTS in the SOURCES target property. Put some respect on the generator expression's name. 🫶
CMake 3.0 and lower did not include the TARGET_OBJECTS generator expression when returning the SOURCES target property.
Okay so real talk: configure-time CMake code is not built to handle generator expressions 💀. So if you're poking at the SOURCES target property at configure time, you might have to strip the genexes out first with the string(GENEX_STRIP) command. But generate-time code like file(GENERATE)? That one eats the content no problem, no stripping needed 🫶.
The OLD behavior for this policy is to omit TARGET_OBJECTS expressions from the SOURCES target property. The NEW behavior is to include TARGET_OBJECTS expressions in the output. ✨
This policy was introduced in CMake version 3.1. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🧚 Policies Introduced by CMake 3.0, Removed by CMake 4.0 🧚
CMP0050
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Disallow add_custom_command SOURCE signatures. No cap, this one's a glow-up 💅.
CMake 2.8.12 and lower allowed a signature for add_custom_command() that specified an input to a command. Bestie, that was undocumented behavior 😭. Modern CMake associates custom commands with their output, not their input — that's just the vibe now.
The OLD behavior for this policy is to allow the use of add_custom_command() SOURCE signatures. The NEW behavior for this policy is to issue an error if such a signature is used. Periodt. 🔥
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0049
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Do not expand variables in target source entries.
CMake 2.8.12 and lower did a whole extra layer of variable expansion when it was evaluating source file names, like:
set(a_source foo.c)
add_executable(foo ${a_source})
...and that was undocumented behavior 🙈. Like, sneaky little extra expansion nobody asked for.
The OLD behavior for this policy is to expand such variables when processing the target sources. The NEW behavior for this policy is to issue an error if such variables need to be expanded.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0048
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
The project() command manages VERSION variables.
CMake version 3.0 introduced the VERSION option of the project() command so you can specify a project version alongside the name — iconic behavior, honestly 👑. But to keep PROJECT_VERSION and its related variables consistent with the PROJECT_NAME variable, it's necessary to set the VERSION variables to the empty string when no VERSION is given to project(). The catch 🎀: that can change behavior for existing projects that set VERSION variables themselves, because project() may now clear them 😭. This policy controls the behavior for compatibility with such projects.
The OLD behavior for this policy is to leave VERSION variables untouched. The NEW behavior for this policy is to set VERSION as documented by the project() command.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0047
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Use the QCC compiler id for the qcc drivers on QNX. 🦋
CMake 3.0 and above recognize that the QNX qcc compiler driver is different from the GNU compiler. CMake now prefers to present this to projects by setting the CMAKE_<LANG>_COMPILER_ID variable to QCC instead of GNU. But — and you knew there was a but 💀 — existing projects may assume the compiler id for QNX qcc is just GNU, the way it was in CMake versions prior to 3.0. So this policy decides, for QNX qcc, which compiler id gets reported in the CMAKE_<LANG>_COMPILER_ID variable after language <LANG> is enabled by the project() or enable_language() command. Heads up: the policy must be set prior to the invocation of either command. Timing matters, bestie ⏰.
The OLD behavior for this policy is to use the GNU compiler id for the qcc and QCC compiler drivers. The NEW behavior for this policy is to use the QCC compiler id for those drivers.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake did not warn by default, and used OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP<NNNN> variable (that's CMAKE_POLICY_WARNING_CMP0047 for this one) to control the warning in CMake versions before 4.0.
CMP0046
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Error on non-existent dependency in add_dependencies.
CMake 2.8.12 and lower just silently ignored non-existent dependencies listed in the add_dependencies() command 😭 like, girl, where did your dependency go? Nobody said anything.
The OLD behavior for this policy is to silently ignore non-existent dependencies. The NEW behavior for this policy is to report an error if non-existent dependencies are listed in the add_dependencies() command. Much better vibe check fr fr 🔥.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0045
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Error on non-existent target in get_target_property.
In CMake 2.8.12 and lower, the get_target_property() command accepted a non-existent target argument without issuing any error or warning 🙈. The result variable just gets set to a -NOTFOUND value. Iconic level of chill, honestly.
The OLD behavior for this policy is to issue no warning and set the result variable to a -NOTFOUND value. The NEW behavior for this policy is to issue a FATAL_ERROR if the command is called with a non-existent target. 💀
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0044
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Case sensitive <LANG>_COMPILER_ID generator expressions.
CMake 2.8.12 introduced the <LANG>_COMPILER_ID generator expressions (iykyk, cmake-generator-expressions(7)) to let you compare the CMAKE_<LANG>_COMPILER_ID against a test value. The possible valid values are lowercase, but the comparison with the test value was performed case-insensitively 😭 which is giving chaos.
The OLD behavior for this policy is to perform a case-insensitive comparison with the value in the <LANG>_COMPILER_ID expression. The NEW behavior for this policy is to perform a case-sensitive comparison with the value in the <LANG>_COMPILER_ID expression. Slay, consistency 💅.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0043
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Ignore COMPILE_DEFINITIONS_<Config> properties.
CMake 2.8.12 and lower allowed setting the COMPILE_DEFINITIONS_<CONFIG> target property and the COMPILE_DEFINITIONS_<CONFIG> directory property to apply config-specific compile definitions.
But since CMake 2.8.10, the COMPILE_DEFINITIONS property has supported generator expressions (see cmake-generator-expressions(7)) for setting configuration-dependent content ✨. So the continued existence of the suffixed variables is redundant and just causes a maintenance burden, ngl 🫠. Populating the COMPILE_DEFINITIONS_DEBUG property may be replaced with populating COMPILE_DEFINITIONS directly, or via target_compile_definitions():
# Old Interfaces:
set_property(TARGET tgt APPEND PROPERTY
COMPILE_DEFINITIONS_DEBUG DEBUG_MODE
)
set_property(DIRECTORY APPEND PROPERTY
COMPILE_DEFINITIONS_DEBUG DIR_DEBUG_MODE
)
# New Interfaces:
set_property(TARGET tgt APPEND PROPERTY
COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUG_MODE>
)
target_compile_definitions(tgt PRIVATE $<$<CONFIG:Debug>:DEBUG_MODE>)
set_property(DIRECTORY APPEND PROPERTY
COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DIR_DEBUG_MODE>
)
So basically these are the new, correct, slay ways to express config-specific defines — see how the generator expression does the config-matching for you instead of you hand-writing a whole suffixed property? That's the whole vibe. 🦋
The OLD behavior for this policy is to consume the content of the suffixed COMPILE_DEFINITIONS_<CONFIG> target property when generating the compilation command. The NEW behavior for this policy is to ignore the content of the COMPILE_DEFINITIONS_<CONFIG> target property.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior. 💀
CMP0042
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
MACOSX_RPATH is enabled by default. 🍎✨
CMake 2.8.12 and newer has support for using @rpath in a target's install name. This was enabled by setting the target property MACOSX_RPATH. And can we talk about how the @rpath in an install name is a more flexible and powerful mechanism than @executable_path or @loader_path for locating shared libraries? It just is. It's giving main character energy for real. 👑
CMake 3.0 and later prefer this property to be ON by default. Projects wanting @rpath in a target's install name may remove any setting of the INSTALL_NAME_DIR and CMAKE_INSTALL_NAME_DIR variables. 🫶
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0041
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Error on relative include with generator expression. 👀
Okay so back in the day, diagnostics in CMake 2.8.12 and lower would silently ignore an entry in the INTERFACE_INCLUDE_DIRECTORIES of a target if it contained a generator expression at any position. Like, just… not tell you. 🙈 Not the vibe.
The path entries in that target property should not be relative. High-level API should ensure that by adding either a source directory or a install directory prefix, as appropriate.
As an additional diagnostic, the INTERFACE_INCLUDE_DIRECTORIES generated on an IMPORTED target for the install location should not contain paths in the source directory or the build directory. 🚫
The OLD behavior for this policy is to ignore relative path entries if they contain a generator expression. The NEW behavior for this policy is to report an error if a generator expression appears in another location and the path is relative.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0040
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
The target in the TARGET signature of add_custom_command() must exist and must be defined in the current directory. Periodt. 💅
CMake 2.8.12 and lower silently ignored a custom command created with the TARGET signature of add_custom_command() if the target is unknown or was defined outside the current directory. Just quietly ghosted it. 😭
The OLD behavior for this policy is to ignore custom commands for unknown targets. The NEW behavior for this policy is to report an error if the target referenced in add_custom_command() is unknown or was defined outside the current directory.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0039
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Utility targets may not have link dependencies. Simple as that bestie. 🔗🚫
CMake 2.8.12 and lower allowed using utility targets in the left hand side position of the target_link_libraries() command. This is an indicator of a bug in user code. Ngl, it always was.
The OLD behavior for this policy is to ignore attempts to set the link libraries of utility targets. The NEW behavior for this policy is to report an error if an attempt is made to set the link libraries of a utility target.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0038
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Targets may not link directly to themselves. No self-linking. That's not self-care, that's a bug. 🪞💀
CMake 2.8.12 and lower allowed a build target to link to itself directly with a target_link_libraries() call. This is an indicator of a bug in user code. Yeah. Fr fr.
The OLD behavior for this policy is to ignore targets which list themselves in their own link implementation. The NEW behavior for this policy is to report an error if a target attempts to link to itself.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0037
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Target names should not be reserved and should match a validity pattern. ✨ Name your targets responsibly, bestie.
CMake 2.8.12 and lower allowed creating targets using add_library(), add_executable() and add_custom_target() with unrestricted choice for the target name. Newer cmake features such as cmake-generator-expressions(7) and some diagnostics expect target names to match a restricted pattern. 🎀
Target names may contain upper and lower case letters, numbers, the underscore character _, dot ., plus + and minus -. As a special case, ALIAS and IMPORTED targets may contain two consecutive colons. (iykyk 👀)
Target names reserved by one or more CMake generators are not allowed. Among others these include all, clean, help, and install. 🚫
Target names associated with optional features, such as test and package, may also be reserved. CMake 3.10 and below always reserve them. CMake 3.11 and above reserve them only when the corresponding feature is enabled (e.g. by including the CTest or CPack modules).
The OLD behavior for this policy is to allow creating targets with reserved names or which do not match the validity pattern. The NEW behavior for this policy is to report an error if an add_* command is used with an invalid target name.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0036
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
The build_name() command should not be called. Like, ever. It's giving deprecated. 🕰️
This command was added in May 2001 to compute a name for the current operating system and compiler combination. The command has long been documented as discouraged and replaced by the CMAKE_SYSTEM and CMAKE_<LANG>_COMPILER variables. (Use those, they ate. 💅)
CMake >= 3.0 prefer that this command never be called. The OLD behavior for this policy is to allow the command to be called. The NEW behavior for this policy is to issue a FATAL_ERROR when the command is called. 😤
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0035
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
The variable_requires() command should not be called. 🫶
This command was introduced in November 2001 to perform some conditional logic. It has long been replaced by the if() command. Go use if(), she's the icon, she's the moment. 👑
CMake >= 3.0 prefer that this command never be called. The OLD behavior for this policy is to allow the command to be called. The NEW behavior for this policy is to issue a FATAL_ERROR when the command is called. 💀
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
😭 CMP0034
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
Bestie, the utility_source() command? Do not call it. Like, ever. It's giving "2011 called and wants its build system back" 💀
It dropped in March 2001 to help build executables that generate other files, which was cute at the time, but that whole approach has long been replaced by add_executable() combined with add_custom_command(). Glow-up achieved ✨
CMake >= 3.0 would honestly prefer this command never gets called at all:
- OLD behavior — lets you call the command (🙈 no).
- NEW behavior — throws a
FATAL_ERRORthe second you call it (slay 💅).
This policy was introduced in CMake version 3.0. Before it was removed in CMake version 4.0, you could set it with cmake_policy() or cmake_minimum_required(). If you didn't set it, CMake would warn you and then use OLD behavior anyway. Iconic but problematic 🎀
🌸 CMP0033
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
So, export_library_dependencies() — do not call it. Not even ironically 🫶
It was added way back in January 2003 to export <tgt>_LIB_DEPENDS internal CMake cache entries to a file so you could install it with a project. Back in the day, that's how transitive link dependencies worked for applications outside the original build tree of a project. Lowkey historic. But the functionality has been fully superseded by the export() and install(EXPORT) commands 👑
CMake >= 3.0 prefers this command never be called:
- OLD behavior — allows the command to be called.
- NEW behavior — issues a
FATAL_ERRORwhen the command is called.
Introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior. Periodt 💖
🦋 CMP0032
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
output_required_files()? Yeah bestie, don't call it 💀
Added June 2001 to expose the then-current CMake implicit dependency scanner. Key word: then-current. CMake's real implicit dependency scanner has evolved since then, but it is not exposed through this command. The scanning capabilities here are very limited, and honestly this functionality is better achieved through dedicated outside tools.
CMake >= 3.0 prefer that this command never be called:
- OLD behavior — allows the command to be called.
- NEW behavior — issues a
FATAL_ERRORwhen the command is called.
Introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior 🌈
🔥 CMP0031
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
load_command() — nope, do not call it 🙈
Added August 2002 so projects could add arbitrary commands implemented in C or C++. The vibes were immaculate, the reality was not: it does not work when the toolchain in use does not match the ABI of the CMake process. It's been mostly superseded by the macro() and function() commands, which ate and left no crumbs 💅
CMake >= 3.0 prefer that this command never be called:
- OLD behavior — allows the command to be called.
- NEW behavior — issues a
FATAL_ERRORwhen the command is called.
Introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior 🎀
🍓 CMP0030
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
use_mangled_mesa() — bestie, please don't call it 😭
Created September 2001 to support VTK before the modern CMake language and custom command capabilities even existed. And VTK has not used it in years. Literally years. It's giving ancient relic 🏺
CMake >= 3.0 prefer that this command never be called:
- OLD behavior — allows the command to be called.
- NEW behavior — issues a
FATAL_ERRORwhen the command is called.
Introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior 💜
🧚 CMP0029
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
subdir_depends() should not be called. Full stop 🫶
The implementation of this command has been empty since December 2001, but it was kept in CMake for compatibility for a long time. The way it's been doing absolutely nothing for two decades and still showed up to work 😭💀
CMake >= 3.0 prefer that this command never be called:
- OLD behavior — allows the command to be called.
- NEW behavior — issues a
FATAL_ERRORwhen the command is called.
Introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior ⭐
💅 CMP0028
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
Okay so: double colon in a target name means ALIAS or IMPORTED target. That's the whole vibe check ✨
CMake 2.8.12 and lower allowed the use of targets and files with double colons in target_link_libraries(), with some buildsystem generators. Yikes.
The use of double-colons is a common pattern used to namespace IMPORTED targets and ALIAS targets — so it's very much a real convention, not a random flex. Here's the problem: when computing the link dependencies of a target, the name of each dependency could either be a target, or a file on disk. Previously, if a target was not found with a matching name, the name was considered to refer to a file on disk. Which leads to extremely confusing error messages if there's a typo in what should be a target name 😭
See also the LINK_LIBRARIES_ONLY_TARGETS target property 👀
So the behaviors:
- OLD — search for targets, then files on disk, even if the search term contains double-colons.
- NEW — issue a
FATAL_ERRORif a link dependency contains double-colons but is not an IMPORTED target or an ALIAS target.
Introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior 👑
🌟 CMP0027
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
Conditionally linked imported targets with missing include directories. Say that five times fast, I dare you 🫠
CMake 2.8.11 introduced (yes, the original says "introduced introduced", we love a stutter queen 💀) the concept of INTERFACE_INCLUDE_DIRECTORIES, and a check at cmake time that the entries in the INTERFACE_INCLUDE_DIRECTORIES of an IMPORTED target actually exist. CMake 2.8.11 also introduced generator expression support in the target_link_libraries() command. Slay. But — and this is the plot twist — if an imported target is linked as a result of a generator expression evaluation, the entries in the INTERFACE_INCLUDE_DIRECTORIES of that target were not checked for existence as they should be. The audacity 🙈
So:
- OLD behavior — report a warning if an entry in the
INTERFACE_INCLUDE_DIRECTORIESof a generator-expression conditionally linked IMPORTED target does not exist. - NEW behavior — report an error if an entry in the
INTERFACE_INCLUDE_DIRECTORIESof a generator-expression conditionally linked IMPORTED target does not exist.
Introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior 🦋
👑 CMP0026
⚠️ Warning: the OLD behavior of this policy got yeeted in CMake version 4.0. You must set this to NEW by callingcmake_minimum_required()orcmake_policy().
Disallow use of the LOCATION property for build targets. Bye bestie 👋
CMake 2.8.12 and lower allowed reading the LOCATION target property (and configuration-specific variants) to determine the eventual location of build targets. Sounds convenient, right? It relies on the assumption that all necessary information is available at configure-time to determine the final location and filename of the target. But this property is not fully determined until later, at generate-time 😬
At generate time, the $<TARGET_FILE> generator expression can be used to determine the eventual LOCATION of a target output. That's the move. That's the main character energy we're looking for ⭐
Code that reads the LOCATION target property can be ported over to use the $<TARGET_FILE> generator expression together with the file(GENERATE) subcommand, so you generate a file that contains the target location. Cute, clean, forward-compatible. 💅
The OLD behavior for this policy is to allow reading the LOCATION properties from build-targets. The NEW behavior for this policy is to not allow reading the LOCATION properties from build-targets.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0025
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Compiler id for Apple Clang is now AppleClang. Okay so this is kind of a big deal 🍓
CMake 3.0 and above recognize that Apple Clang is a different compiler than upstream Clang and that they have different version numbers. CMake now prefers to present this to projects by setting the CMAKE_<LANG>_COMPILER_ID variable to AppleClang instead of Clang. But — and this is the plot twist — existing projects may assume the compiler id for Apple Clang is just Clang, the way it was in CMake versions prior to 3.0. So this policy determines, for Apple Clang, which compiler id gets reported in the CMAKE_<LANG>_COMPILER_ID variable after language <LANG> is enabled by the project() or enable_language() command. And bestie, listen: the policy must be set prior to the invocation of either command. No take-backs. 💀
The OLD behavior for this policy is to use compiler id Clang. The NEW behavior for this policy is to use compiler id AppleClang.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake did not warn by default, and used OLD behavior.
See documentation of the CMAKE_POLICY_WARNING_CMP0025 variable (that's the CMAKE_POLICY_WARNING_CMP<NNNN> variable, iykyk) to control the warning in CMake versions before 4.0.
CMP0024
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Disallow include export result. 🚫
CMake 2.8.12 and lower allowed use of the include() command with the result of the export() command. This relies on the assumption that the export() command has an immediate effect at configure-time during a cmake run. But certain properties of targets are not fully determined until later, at generate-time — think the link language and the complete list of link libraries. Future refactoring will change the effect of the export() command to be executed at generate-time. Use ALIAS targets instead in cases where the goal is to refer to targets by another name. 🦋
The OLD behavior for this policy is to allow including the result of an export() command. The NEW behavior for this policy is not to allow including the result of an export() command.
This policy was introduced in CMake version 3.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🎀 Policies Introduced by CMake 2.8, Removed by CMake 4.0 🎀
CMP0023
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Plain and keyword target_link_libraries() signatures cannot be mixed. Periodt. 💅
CMake 2.8.12 introduced the target_link_libraries() signature using the PUBLIC, PRIVATE, and INTERFACE keywords to generalize the LINK_PUBLIC and LINK_PRIVATE keywords introduced in CMake 2.8.7. Use of signatures with any of these keywords sets the link interface of a target explicitly — even if it's empty. And that produces confusing behavior when you combine it with the historical behavior of the plain target_link_libraries() signature. For example, consider the code:
target_link_libraries(mylib A)
target_link_libraries(mylib PRIVATE B)
After the first line the link interface has not been set explicitly, so CMake would use the link implementation, A, as the link interface. But then the second line sets the link interface to empty. 😭 In order to avoid this subtle behavior CMake now prefers to disallow mixing the plain and keyword signatures of target_link_libraries() for a single target.
The OLD behavior for this policy is to allow keyword and plain target_link_libraries() signatures to be mixed. The NEW behavior for this policy is to not allow mixing of the keyword and plain signatures.
This policy was introduced in CMake version 2.8.12. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0022
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
INTERFACE_LINK_LIBRARIES defines the link interface. 👑
CMake 2.8.11 constructed the 'link interface' of a target from properties matching (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?. The modern way to specify config-sensitive content is to use generator expressions, and the IMPORTED_ prefix makes uniform processing of the link interface with generator expressions impossible. So the INTERFACE_LINK_LIBRARIES target property was introduced as a replacement in CMake 2.8.12. This new property is named consistently with the INTERFACE_COMPILE_DEFINITIONS, INTERFACE_INCLUDE_DIRECTORIES and INTERFACE_COMPILE_OPTIONS properties. So aesthetic ✨
For in-build targets, CMake will use the INTERFACE_LINK_LIBRARIES property as the source of the link interface only if policy CMP0022 is NEW. When exporting a target which has this policy set to NEW, only the INTERFACE_LINK_LIBRARIES property will be processed and generated for the IMPORTED target by default. A new option to the install(EXPORT) and export commands allows export of the old-style properties for compatibility with downstream users of CMake versions older than 2.8.12. The target_link_libraries() command will no longer populate the properties matching LINK_INTERFACE_LIBRARIES(_<CONFIG>)? if this policy is NEW.
Warning-free future-compatible code which works with CMake 2.8.7 onwards can be written by using the LINK_PRIVATE and LINK_PUBLIC keywords of target_link_libraries(). Bestie, that's the move. 🫶
The OLD behavior for this policy is to ignore the INTERFACE_LINK_LIBRARIES property for in-build targets. The NEW behavior for this policy is to use the INTERFACE_LINK_LIBRARIES property for in-build targets, and ignore the old properties matching (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.
This policy was introduced in CMake version 2.8.12. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0021
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Fatal error on relative paths in the INCLUDE_DIRECTORIES target property. 💀
CMake 2.8.10.2 and lower allowed the INCLUDE_DIRECTORIES target property to contain relative paths. The thing is, the base path for such relative entries is not well defined. So CMake 2.8.12 issues a FATAL_ERROR if the INCLUDE_DIRECTORIES property contains a relative path. Not me being dramatic, that's just what it does.
The OLD behavior for this policy is not to warn about relative paths in the INCLUDE_DIRECTORIES target property. The NEW behavior for this policy is to issue a FATAL_ERROR if INCLUDE_DIRECTORIES contains a relative path.
This policy was introduced in CMake version 2.8.12. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0020
⚠️ Warning: The OLD behavior of this policy was removed in CMake version4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Automatically link Qt executables to the qtmain target on Windows. 🪟
CMake 2.8.10 and lower required users of Qt to always specify a link dependency to the qtmain.lib static library manually on Windows. Then CMake 2.8.11 gained the ability to evaluate generator expressions while determining the link dependencies from IMPORTED targets. That's the glow-up 🌈 — it allows CMake itself to automatically link executables which link to Qt to the qtmain.lib library when using IMPORTED Qt targets.
For applications already linking to qtmain.lib, this should have little impact. For applications which supply their own alternative WinMain implementation, and for applications which use the QAxServer library, this automatic linking will need to be disabled as per the documentation. Heads up on that one 🙈
The OLD behavior for this policy is not to link executables to qtmain.lib automatically when they link to the QtCore IMPORTED target. The NEW behavior for this policy is to link executables to qtmain.lib automatically when they link to QtCore IMPORTED target.
So, like, this one landed in CMake version 2.8.11. Before it got removed in CMake version 4.0, you could set it with cmake_policy() or cmake_minimum_required(). If you didn't set it, CMake gave you a warning and used OLD behavior. 💅
CMP0019
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Do not re-expand variables in include and link information. That's the whole vibe. ✨
CMake 2.8.10 and lower re-evaluated values given to the include_directories, link_directories, and link_libraries commands to expand any leftover variable references at the end of the configuration step. This was for strict compatibility with VERY early CMake versions, because all variable references are now normally evaluated during CMake language processing. CMake 2.8.11 and higher prefer to skip the extra evaluation.
The OLD behavior for this policy is to re-evaluate the values for strict compatibility. The NEW behavior for this policy is to leave the values untouched. No cap. 🎀
This policy was introduced in CMake version 2.8.11. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0018
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Ignore the CMAKE_SHARED_LIBRARY_<Lang>_FLAGS variable. 💅
CMake 2.8.8 and lower compiled sources in SHARED and MODULE libraries using the value of the undocumented CMAKE_SHARED_LIBRARY_<Lang>_FLAGS platform variable. That variable contained platform-specific flags needed to compile objects for shared libraries. Typically it included a flag such as -fPIC for position independent code, but it also included other flags needed on certain platforms. CMake 2.8.9 and higher prefer instead to use the POSITION_INDEPENDENT_CODE target property to determine what targets should be position independent, and new undocumented platform variables to select flags while ignoring CMAKE_SHARED_LIBRARY_<Lang>_FLAGS completely.
The default for either approach produces identical compilation flags, but if a project modifies CMAKE_SHARED_LIBRARY_<Lang>_FLAGS from its original value, this policy determines which approach to use. 👑
The OLD behavior for this policy is to ignore the POSITION_INDEPENDENT_CODE property for all targets and use the modified value of CMAKE_SHARED_LIBRARY_<Lang>_FLAGS for SHARED and MODULE libraries.
The NEW behavior for this policy is to ignore CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not, and honor the POSITION_INDEPENDENT_CODE target property.
This policy was introduced in CMake version 2.8.9. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0017
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Prefer files from the CMake module directory when including from there. 🦋
Starting with CMake 2.8.4, if a cmake-module shipped with CMake (i.e. located in the CMake module directory) calls include() or find_package(), the files located in the CMake module directory are preferred over the files in CMAKE_MODULE_PATH. This makes sure that the modules belonging to CMake always get those files included which they expect, and against which they were developed and tested. In all other cases, the files found in CMAKE_MODULE_PATH still take precedence over the ones in the CMake module directory. The OLD behavior is to always prefer files from CMAKE_MODULE_PATH over files from the CMake modules directory.
This policy was introduced in CMake version 2.8.4. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0016
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
target_link_libraries() reports an error if its only argument is not a target. 😭
In CMake 2.8.2 and lower, the target_link_libraries() command silently ignored if it was called with only one argument, and this argument wasn't a valid target. In CMake 2.8.3 and above, it reports an error in this case. Periodt.
This policy was introduced in CMake version 2.8.3. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0015
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
link_directories() treats paths relative to the source dir. 🌸
In CMake 2.8.0 and lower, the link_directories() command passed relative paths unchanged to the linker. In CMake 2.8.1 and above, the link_directories() command prefers to interpret relative paths with respect to CMAKE_CURRENT_SOURCE_DIR, which is consistent with include_directories() and other commands. The OLD behavior for this policy is to use relative paths verbatim in the linker command. The NEW behavior for this policy is to convert relative paths to absolute paths by appending the relative path to CMAKE_CURRENT_SOURCE_DIR.
This policy was introduced in CMake version 2.8.1. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0014
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Input directories must have CMakeLists.txt. 🎀
CMake versions before 2.8 silently ignored missing CMakeLists.txt files in directories referenced by add_subdirectory() or subdirs(), treating them as if present but empty. In CMake 2.8.0 and above, this cmake_policy() determines whether or not the case is an error. The OLD behavior for this policy is to silently ignore the problem. The NEW behavior for this policy is to report an error. No more ghost directories, bestie. 💀
This policy was introduced in CMake version 2.8.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0013
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Duplicate binary directories are not allowed. 🚫
CMake 2.6.3 and below silently permitted add_subdirectory() calls to create the same binary directory multiple times. During build system generation, files would be written and then overwritten in the build tree and could lead to strange behavior. CMake 2.6.4 and above explicitly detect duplicate binary directories. CMake 2.6.4 always considers this case an error. In CMake 2.8.0 and above, this policy determines whether or not the case is an error. The OLD behavior for this policy is to allow duplicate binary directories. The NEW behavior for this policy is to disallow duplicate binary directories with an error.
This policy was introduced in CMake version 2.8.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0012
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
if() recognizes numbers and boolean constants. 🔥
In CMake versions 2.6.4 and lower, the if() command implicitly dereferenced arguments corresponding to variables, even those named like numbers or boolean constants, except for 0 and 1. Numbers and boolean constants such as true, false, yes, no, on, off, y, n, notfound, ignore (all case insensitive) were recognized in some cases but not all. For example, the code if(TRUE) might have evaluated as false. Numbers such as 2 were recognized only in boolean expressions like if(NOT 2) (leading to false) but not as a single-argument like if(2) (also leading to false). Later versions of CMake prefer to treat numbers and boolean constants literally, so they should not be used as variable names.
The OLD behavior for this policy is to implicitly dereference variables named like numbers and boolean constants. The NEW behavior for this policy is to recognize numbers and boolean constants without dereferencing variables with such names. It's giving "finally, common sense." 💖
This policy was introduced in CMake version 2.8.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0011 🎀
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Okay so this one is about included scripts doing their own automatic cmake_policy() PUSH and POP. 🫶
Back in CMake 2.6.2 and below, CMake Policy settings inside scripts loaded by include() and find_package() would affect the includer. Like, the vibes leaked everywhere 💀. You literally had to make explicit calls to cmake_policy(PUSH) and cmake_policy(POP) to isolate policy changes and protect the includer.
And sure, some scripts intend to affect the policies of their includer — iconic of them — but most do not, bestie, not even a little. So in CMake 2.6.3 and above, include() and find_package() by default PUSH and POP an entry on the policy stack around an included script, but they provide a NO_POLICY_SCOPE option to disable it. This policy determines whether or not to imply NO_POLICY_SCOPE for compatibility.
- The OLD behavior for this policy is to imply
NO_POLICY_SCOPEforinclude()andfind_package()commands. - The NEW behavior for this policy is to allow the commands to do their default
cmake_policyPUSH and POP. ✨
This policy was introduced in CMake version 2.6.3. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0010 💅
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Bad variable reference syntax is an error. Periodt. 💀
In CMake 2.6.2 and below, incorrect variable reference syntax — like a missing close-brace, ${FOO — was reported but did not stop processing of CMake code. The audacity honestly 😭. This policy determines whether a bad variable reference is an error.
- The OLD behavior for this policy is to warn about the error, leave the string untouched, and continue.
- The NEW behavior for this policy is to report an error. 🔥
If CMP0053 is set to NEW, this policy has no effect and is treated as always being NEW.
This policy was introduced in CMake version 2.6.3. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0009 🦋
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
FILE GLOB_RECURSE calls should not follow symlinks by default. No cap. 🌸
In CMake 2.6.1 and below, file(GLOB_RECURSE) calls would follow through symlinks, sometimes coming up with unexpectedly large result sets because of symlinks to top level directories that contain hundreds of thousands of files. Like, hundreds of thousands?? bestie the recursion ate 😭😭
This policy determines whether or not to follow symlinks encountered during a file(GLOB_RECURSE) call.
- The OLD behavior for this policy is to follow the symlinks.
- The NEW behavior for this policy is not to follow the symlinks by default, but only if
FOLLOW_SYMLINKSis given as an additional argument to theFILEcommand. ✨
This policy was introduced in CMake version 2.6.2. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0008 👑
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Libraries linked by full path must have a valid library file name. 💅
In CMake 2.4 and below it is possible to write code like
target_link_libraries(myexe /full/path/to/somelib)
where somelib is supposed to be a valid library file name such as libsomelib.a or somelib.lib. For Makefile generators this produces an error at build time because the dependency on the full path cannot be found. For Visual Studio Generators IDE and Xcode generators this used to work by accident because CMake would always split off the library directory and ask the linker to search for the library by name (-lsomelib or somelib.lib). Accidentally working is so not the flex people thought it was 🙈.
Despite the failure with Makefiles, some projects have code like this and build only with Visual Studio and/or Xcode. This version of CMake prefers to pass the full path directly to the native build tool, which will fail in this case because it does not name a valid library file.
This policy determines what to do with full paths that do not appear to name a valid library file.
- The OLD behavior for this policy is to split the library name from the path and ask the linker to search for it.
- The NEW behavior for this policy is to trust the given path and pass it directly to the native build tool unchanged. ✨
This policy was introduced in CMake version 2.6.1. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0007 🍓
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
The list command no longer ignores empty elements. The empty elements are, in fact, elements, and they deserve to be counted 💖.
This policy determines whether the list command will ignore empty elements in the list. CMake 2.4 and below list commands ignored all empty elements in the list — for example, a;b;;c would have length 3 and not 4. Which is lowkey a lie, bestie, there are clearly four things there 😭.
- The OLD behavior for this policy is to ignore empty list elements.
- The NEW behavior for this policy is to correctly count empty elements in a list. 🌈
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0006 🧚
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION. Like, the bundle needs an address, girly 🎀.
This policy determines whether the install(TARGETS) command must be given a BUNDLE DESTINATION when asked to install a target with the MACOSX_BUNDLE property set. CMake 2.4 and below did not distinguish application bundles from normal executables when installing targets. CMake 2.6 provides a BUNDLE option to the install(TARGETS) command that specifies rules specific to application bundles on the Mac. Projects should use this option when installing a target with the MACOSX_BUNDLE property set.
- The OLD behavior for this policy is to fall back to the
RUNTIME DESTINATIONif aBUNDLE DESTINATIONis not given. - The NEW behavior for this policy is to produce an error if a bundle target is installed without a
BUNDLE DESTINATION. 💀
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0005 ⭐
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Preprocessor definition values are now escaped automatically. She learned to escape, we love growth ✨.
This policy determines whether or not CMake should generate escaped preprocessor definition values added via add_definitions. CMake versions 2.4 and below assumed that only trivial values would be given for macros in add_definitions calls. It did not attempt to escape non-trivial values such as string literals in generated build rules. CMake versions 2.6 and above support escaping of most values, but cannot assume the user has not added escapes already in an attempt to work around limitations in earlier versions. (The workaround escapes are still out there living rent free 🙈.)
- The OLD behavior for this policy is to place definition values given to
add_definitionsdirectly in the generated build rules without attempting to escape anything. - The NEW behavior for this policy is to generate correct escapes for all native build tools automatically. See documentation of the
COMPILE_DEFINITIONStarget property for limitations of the escaping implementation. 👑
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
CMP0004 💜
Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Libraries linked may not have leading or trailing whitespace. Trim the vibes, bestie, not the library names 😭.
CMake versions 2.4 and below silently removed leading and trailing whitespace from libraries linked with code like
target_link_libraries(myexe " A ")
This could lead to subtle errors in user projects. Subtle errors are the worst kind, genuinely the final boss of debugging 💀.
- The OLD behavior for this policy is to silently remove leading and trailing whitespace.
- The NEW behavior for this policy is to diagnose the existence of such whitespace as an error.
The setting for this policy used when checking the library names is that in effect when the target is created by an add_executable() or add_library() command. 🫶
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
💅 CMP0003
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Libraries linked via full path no longer produce linker search paths. Okay so, plot twist: this policy is technically about how libraries whose full paths are NOT known get found at link time, but it exists purely because of a glow-up in how CMake handles the ones whose full paths are known. Consider this code:
target_link_libraries(myexe /path/to/libA.so)
CMake 2.4 and below linked to libraries with known full paths by splitting them on the link line into separate pieces — the linker search path and the library name. So that example might have produced something like
... -L/path/to -lA ...
to link library A. Someone actually did an analysis to order multiple link directories so the linker would find library A where you wanted it, but ngl there are cases where that just doesn't work. CMake versions 2.6 and above use the way more reliable approach of passing the full path straight to the linker in most cases. So the example now produces something like
... /path/to/libA.so ....
😭 Unfortunately this change can break code like
target_link_libraries(myexe /path/to/libA.so B)
where B is meant to find /path/to/libB.so. That code is wrong, bestie — the user is asking the linker to find library B but never gave it a linker search path (which could be added with the link_directories command). But with the old linking implementation it worked accidentally, because the search path added for library A happened to let library B be found too. Very "it works and nobody knows why" energy.
So, to support projects that depend on linker search paths added by linking to libraries with known full paths, the OLD behavior for this policy adds the linker search paths even though they're not needed for their own libraries. When this policy is set to OLD, CMake produces a link line like
... -L/path/to /path/to/libA.so -lB ...
which lets library B be found exactly like before. When this policy is set to NEW, CMake produces
... /path/to/libA.so -lB ...
which more accurately matches what the project actually specified. ✨
The setting used when generating the link line is the one in effect when the target is created by an add_executable or add_library command. For the example above, this code
cmake_policy(SET CMP0003 OLD) # or cmake_policy(VERSION 2.4)
add_executable(myexe myexe.c)
target_link_libraries(myexe /path/to/libA.so B)
will work and suppress the warning for this policy. It may also be updated to work with the corrected linking approach:
cmake_policy(SET CMP0003 NEW) # or cmake_policy(VERSION 2.6)
link_directories(/path/to) # needed to find library B
add_executable(myexe myexe.c)
target_link_libraries(myexe /path/to/libA.so B)
Even better, library B may be specified with a full path:
add_executable(myexe myexe.c)
target_link_libraries(myexe /path/to/libA.so /path/to/libB.so)
When all items on the link line have known paths, CMake doesn't even check this policy, so it has no effect. 🫶
Also important: the warning for this policy is issued for at most one target. That's deliberate — it avoids flooding you with messages for every single target when setting the policy once will probably fix all of them. Iconic restraint, honestly.
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🎀 CMP0002
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
Logical target names must be globally unique. Periodt.
Target names created with add_executable(), add_library(), or add_custom_target() are logical build target names. They have to be globally unique because:
- Unique names may be referenced unambiguously both in CMake code and on make tool command lines.
- Logical names are used by
Xcodeand Visual Studio IDE generators to produce meaningful project names for the targets.
The logical name of executable and library targets doesn't have to match the physical file names that get built, bestie. Consider using the OUTPUT_NAME target property to create two targets with the same physical name while keeping logical names distinct. Custom targets just straight up need globally unique names — unless you use the global property ALLOW_DUPLICATE_CUSTOM_TARGETS with a Makefiles generator. 🙈
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🦋 CMP0001
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
CMAKE_BACKWARDS_COMPATIBILITY should no longer be used. It's giving deprecated. 🫠
The OLD behavior is to check CMAKE_BACKWARDS_COMPATIBILITY and present it to the user. The NEW behavior is to ignore CMAKE_BACKWARDS_COMPATIBILITY completely.
Back in CMake 2.4 and below, the variable CMAKE_BACKWARDS_COMPATIBILITY was used to request compatibility with earlier versions of CMake. In CMake 2.6 and above, all compatibility issues are handled by policies and the cmake_policy() command. However, CMake still has to check CMAKE_BACKWARDS_COMPATIBILITY for projects written for CMake 2.4 and below. Legacy obligations, you know how it is. 💀
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
👑 CMP0000
⚠️ Warning: the OLD behavior of this policy was removed in CMake version 4.0. This policy must be set to NEW by a call tocmake_minimum_required()orcmake_policy().
A minimum required CMake version must be specified. This is the "did you even read the assignment" policy. 😌
CMake requires that projects specify the version of CMake they were written for. This policy exists so that users trying to build the project can be told when they need to update their CMake. Specifying a version also helps the project build with CMake versions newer than the one specified. Use the cmake_minimum_required() command at the top of your main CMakeLists.txt file:
cmake_minimum_required(VERSION <major>.<minor>)
where <major>.<minor> is the version of CMake you want to support (such as 3.14). The command ensures at least that version of CMake is running and helps newer versions stay compatible with the project. See the documentation of cmake_minimum_required() for the deets.
Heads up though: the command invocation must appear in the CMakeLists.txt file itself — a call in an included file is not sufficient. Not me finding out the hard way. 😭 The OLD behavior was to silently ignore the missing invocation. The NEW behavior is to issue an error instead of a warning. No more quiet enabling, bestie.
This policy was introduced in CMake version 2.6.0. Prior to removal in CMake version 4.0, it could be set by cmake_policy() or cmake_minimum_required(). If it was not set, CMake warned, and used OLD behavior.
🌸 Copyright
2000-2026 Kitware, Inc. and Contributors
And that's the whole page, bestie — you made it to the end 🎉 tysm for reading, fr fr. This little masterpiece is from version 4.4.5, dated Oct 28, 2026, filed under CMAKE-POLICIES(7). Go forth and set your policies to NEW 💖
📦 where this page comes from
- arch rolling: cmake 4.4.5-1 · BSD-3-Clause
- 💖 girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms