mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 13:51:33 -06:00
ExternalData: Preserve escaped semicolons during argument expansion
The CMake language implicitly flattens lists so a ";" in a list element
must be escaped with a backslash. List expansion removes backslashes
escaping semicolons to leave raw semicolons in the values. Teach
ExternalData_Add_Test and ExternalData_Expand_Arguments to re-escape
semicolons found in list elements so the resulting argument lists work
as if constructed directly by the set() command.
For example:
ExternalData_Add_Test(Data NAME test1 COMMAND ... "a\\;b")
ExternalData_Expand_Arguments(Data args2 "c\\;d")
add_test(NAME test2 COMMAND ... ${args2})
should be equivalent to
set(args1 "a\\;b")
add_test(NAME test1 COMMAND ... ${args1})
set(args2 "c\\;d")
add_test(NAME test2 COMMAND ... ${args2})
which is equivalent to
add_test(NAME test1 COMMAND ... "a;b")
add_test(NAME test2 COMMAND ... "c;d")
Note that it is not possible to make ExternalData_Add_Test act exactly
like add_test when quoted arguments contain semicolons because the CMake
language flattens lists when constructing function ARGN values. This
re-escape approach at least allows test arguments to have semicolons.
While at it, teach ExternalData APIs to not transform "DATA{...;...}"
arguments because the contained semicolons are non-sensical.
Suggested-by: Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
This commit is contained in:
@@ -156,7 +156,8 @@
|
||||
# License text for the above reference.)
|
||||
|
||||
function(ExternalData_add_test target)
|
||||
ExternalData_expand_arguments("${target}" testArgs ${ARGN})
|
||||
# Expand all arguments as a single string to preserve escaped semicolons.
|
||||
ExternalData_expand_arguments("${target}" testArgs "${ARGN}")
|
||||
add_test(${testArgs})
|
||||
endfunction()
|
||||
|
||||
@@ -234,13 +235,17 @@ endfunction()
|
||||
|
||||
function(ExternalData_expand_arguments target outArgsVar)
|
||||
# Replace DATA{} references with real arguments.
|
||||
set(data_regex "DATA{([^{}\r\n]*)}")
|
||||
set(data_regex "DATA{([^;{}\r\n]*)}")
|
||||
set(other_regex "([^D]|D[^A]|DA[^T]|DAT[^A]|DATA[^{])+|.")
|
||||
set(outArgs "")
|
||||
# This list expansion un-escapes semicolons in list element values so we
|
||||
# must re-escape them below anywhere a new list expansion will occur.
|
||||
foreach(arg IN LISTS ARGN)
|
||||
if("x${arg}" MATCHES "${data_regex}")
|
||||
# Re-escape in-value semicolons before expansion in foreach below.
|
||||
string(REPLACE ";" "\\;" tmp "${arg}")
|
||||
# Split argument into DATA{}-pieces and other pieces.
|
||||
string(REGEX MATCHALL "${data_regex}|${other_regex}" pieces "${arg}")
|
||||
string(REGEX MATCHALL "${data_regex}|${other_regex}" pieces "${tmp}")
|
||||
# Compose output argument with DATA{}-pieces replaced.
|
||||
set(outArg "")
|
||||
foreach(piece IN LISTS pieces)
|
||||
@@ -254,11 +259,13 @@ function(ExternalData_expand_arguments target outArgsVar)
|
||||
set(outArg "${outArg}${piece}")
|
||||
endif()
|
||||
endforeach()
|
||||
list(APPEND outArgs "${outArg}")
|
||||
else()
|
||||
# No replacements needed in this argument.
|
||||
list(APPEND outArgs "${arg}")
|
||||
set(outArg "${arg}")
|
||||
endif()
|
||||
# Re-escape in-value semicolons in resulting list.
|
||||
string(REPLACE ";" "\\;" outArg "${outArg}")
|
||||
list(APPEND outArgs "${outArg}")
|
||||
endforeach()
|
||||
set("${outArgsVar}" "${outArgs}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
Reference in New Issue
Block a user