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 are
re-evaluated as escape prefixes, and invalid escape sequences (such as
\b in Windows paths) can 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.
The OLD behavior for this policy is to interpret escape sequences in macro
argument references and in arguments passed to variable_watch() callback
commands. The NEW behavior is to 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.
Mixed Policy Chains¶
Whether pre-escaping occurs is determined by the policy setting at each
call site. When a project and its dependencies use different CMP0219
settings, each macro call in the chain follows the policy where that call
appears.
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.
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.
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.