0

I've a company internal tool which takes multiple files per command line using the following pattern

-i file1 -i file2

To add this tool to my CMake build I've been using the add_custom_target command like this

add_custom_target(
  CustomTarget
  COMMAND ${CompanyTool} ${FILES} -o output"
  DEPENDS ActualTarget)

This works fine as long as FILES only expands to a single one but when I pass in multiple files the command starts to produce only garbage output. Upon inspecting the build.ninja files generated by CMake I found that the custom_target command gets translated to a call where the arguments are followed by backslashes like this

\ -i\ file\

I suspect that's the reason that this ain't working.

Now why the F. does CMake do this and how do I get rid of this behavior?

/edit
Printing the FILES string right before passing it to add_custom_target I can't see those backslashes...

Ok, got it. Building a new list and appending -i and file in a foreach looped worked.

Vinci
  • 1,382
  • 10
  • 12

1 Answers1

1

It seems like you didn't create a cmake list variable, but instead created a single valued variable containing a value with multiple spaces. The fact that you don't see the values separated by ;, but by spaces is a clear indication for this. CMake automatically escapes values as necessary to invoke the command with the exact values in the command line:

Wrong:

set(FILES "foo.txt bar.txt baz.txt file with space.txt")

Correct

set(FILES foo.txt bar.txt baz.txt "file with space.txt")

# example command concatenating the file contents
add_custom_target(
  CustomTarget
  COMMAND ${CMAKE_COMMAND} -E cat ${FILES}
  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

The cmake generator for Visual Studio converts this to the following command on my system:

"D:\Program Files\CMake\bin\cmake.exe" -E cat foo.txt bar.txt baz.txt "file with space.txt"

(Plus some extra stuff for error handling ect.) Running the command does print the concatenated file contents to the console as expected.


Btw: the single " in output" should actually result in a cmake error. Unless somewhere else there's a corresponding ". If this is not just a copy&paste error it indicates that cmake is doing something other than you expect it to do there.

fabian
  • 80,457
  • 12
  • 86
  • 114
  • No definitely not. I've initially had a list created by set(var a b c) and prepended -i to each element. As far as I can tell this works, at least printing the result shows what I had expected. However passing this list to the add_custom_target and using ninja as generator does not work and the ninja rule which gets created contained backslashes. – Vinci Jan 07 '22 at 17:37