Using execute_process when one of the arguments contains a space

There is already an entry with a similar title to what I’m trying to do, but I’m afraid it doesn’t quite answer my question.

The situation is this: I’m trying to invoke execute_process where one of the arguments contains a space. Specifically, I want to run bison with a set of flags which are specified in a string variable. For example,

execute_process(COMMAND win_flex_bison3-latest/win_bison.exe ${flags} -d  -o ${nativeGenPath} ${nativeBisonFile}
                COMMAND_ECHO STDOUT)

…where ‘flags’ may be an empty string, or it may be a sequence of space-separated flags such as “-y -v”.

The exact content of ‘flags’ is supplied by the user at build time (and the file containing this command is generated at build time using ‘configure_file’ and then ‘add_custom_target’), so I need to be able to handle various different cases.

What I find is that, if ‘flags’ is empty, of if it contains a single flag such as “-y”, then everything works. But if ‘flags’ is “-y -v” then here is the output that I see:

'win_bison.exe' '-y -v' '-d' '-o' 'C:\Users\name\Development\git\build\solutions\product\GENERATED\mathparse\parser\CalcParser.cpp' 'C:\Users\name\Development\git\apps\product\src\mathparse\parser\CalcParser.y'

C:/Users/name/Development/win_flex_bison3-latest/win_bison.exe: invalid option -- ' '

…indicating that it’s the embedded space between ‘-y’ and ‘v’ that’s the problem.

I’ve tried:

  • The above, but putting ‘flags’ in quotes, i.e. “${flags}”

  • putting the whole command line in quotes, i.e.

set(cmdstring "win_flex_bison3-latest/win_bison.exe ${flags} -d  -o ${nativeGenPath} ${nativeBisonFile}")
execute_process(COMMAND ${cmdstring}
                COMMAND_ECHO STDOUT)
  • recasting ‘flags’ as a list, i.e.
set(flags )
list(APPEND flags "-y")
list(APPEND flags "-v")

…but that just changes the error message to “invalid option – ’ ;'”

So I’m afraid I’ve run out of ideas. Is there any way of handling this situation?

I think you’re on the right track with the list(APPEND flags) strategy, but you also tried quoting things. How about:

set(flags -y -v) # or build up using `list(APPEND)`
execute_process(COMMAND win_flex_bison3-latest/win_bison.exe ${flags} -d  -o ${nativeGenPath} ${nativeBisonFile}
                COMMAND_ECHO STDOUT)

Well, blow me down… Yes, that worked. The one permutation I hadn’t tried! I was thrown by the fact that the usual recommendation when passing lists is to enclose them in quotes, but clearly this is an exception to that rule.

Thank you.

My rule is to quote everything except:

  • when quoting would interfere with automatic dereferencing in conditionals
  • when passing a list of built-up arguments to a command

There are exceptions like when one needs to smuggle lists with empty arguments through “higher-order” commands like ExternalProject_add.