CMP0219 ------- .. versionadded:: 4.4 :command:`macro` invocations preserve backslashes in arguments. In CMake 4.3 and below, macro argument references (``${ARGN}``, ``${ARGV}``, ``${ARGV}``, 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) `, 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