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:
Brad King
2013-03-12 15:40:37 -04:00
parent 51fc4fb3c1
commit 1823ab4d76
10 changed files with 69 additions and 5 deletions

View File

@@ -35,6 +35,7 @@ ExternalData_Add_Test(Data1
-D Paired=DATA{PairedA.dat,PairedB.dat}
-D Meta=DATA{MetaTop.dat,REGEX:Meta[ABC].dat}
-D Directory=DATA{Directory/,A.dat,REGEX:[BC].dat}
-D "Semicolons=DATA{Data.dat}\\;DATA{Data.dat}"
-P ${CMAKE_CURRENT_SOURCE_DIR}/Data1Check.cmake
)
ExternalData_Add_Target(Data1)

View File

@@ -56,3 +56,13 @@ foreach(n A B C)
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()
list(LENGTH Semicolons len)
if("${len}" EQUAL 2)
foreach(file ${Semicolons})
if(NOT EXISTS "${file}")
message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
endif()
endforeach()
else()
message(SEND_ERROR "Semicolons value:\n ${Semicolons}\nis not a list of length 2.")
endif()