CMP0219
-------

.. versionadded:: 4.4

:command:`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 :command:`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
:command:`cmake_minimum_required(VERSION 4.4) <cmake_minimum_required>`,
so ``CMP0219`` is ``NEW``), which in turn forwards arguments to a macro
from dependency B (not yet upgraded, so ``CMP0219`` is ``OLD``):

.. code-block:: cmake

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

.. code-block:: cmake

  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:

.. code-block:: cmake

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

.. code-block:: cmake

  # 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 :command:`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
:command:`cmake_path(CONVERT ... TO_CMAKE_PATH_LIST)` avoids the issue entirely, because
forward slashes require no escaping regardless of the policy setting.

.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.4
.. |WARNS_OR_DOES_NOT_WARN| replace:: warns when backslashes are present
.. include:: include/STANDARD_ADVICE.rst

.. include:: include/DEPRECATED.rst
