CMP0219 — CMake 4.4.20260621-gcc70e9e-dirty Documentation

# 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.