Cmake: How do I include a literal double quote in a user command?

I am trying to create a custom command that runs with some environment variables, such as LDFLAGS, the value of which must be specified if it contains spaces:

LDFLAGS="-Lmydir -Lmyotherdir" 

I cannot find a way to include this argument in the cmake user command due to cmake escaping rules. Here is what I have tried so far:

 COMMAND LDFLAGS="-Ldir -Ldir2" echo blah VERBATIM) 

gives "LDFLAGS=\"-Ldir -Ldir2\"" echo blah

 COMMAND LDFLAGS=\"-Ldir -Ldir2\" echo blah VERBATIM) 

gives LDFLAGS=\"-Ldir -Ldir2\" echo blah

It seems I either passed the whole line or the escaped quotes were not resolved when used as part of the command.

Would appreciate either a way to include an alphabetic double quote, or an alternative to a better way to set environement variables for a command. Note that I'm still on cmake 2.8, so I don't have a new env command available in 3.2. Thanks in advance!

Note that this is not a duplicate of cmake: when to quote variables? , since none of these citation methods work for this particular case.

+6
source share
2 answers

The obvious choice — often recommended when falling into COMMAND boundaries, especially in older versions of CMake — is to use an external script.

I just wanted to add some simple COMMAND options that really work and don't need a shell, but I have to admit that it still partially depends on the platform.

  • As an example, we can only quote the cited part into a variable:

     set(vars_as_string "-Ldir -Ldir2") add_custom_target( QuotedEnvVar COMMAND env LD_FLAGS=${vars_as_string} | grep LD_FLAGS ) 

    This actually excludes space, not quotation marks.

  • Another example might be adding it with escaped quotes as a “run” rule:

     add_custom_target( LauncherEnvVar COMMAND env | grep LD_FLAGS ) set_target_properties( LauncherEnvVar PROPERTIES RULE_LAUNCH_CUSTOM "env LD_FLAGS=\"-Ldir -Ldir2\"" ) 

Change Added examples for several quoted arguments without the need to speed up quotes

  • Another example would be to "hide part of the complexity" in a function and - if you want to add this to all your user commands - use the global RULE_LAUNCH_CUSTOM property:

     function(set_env) get_property(_env GLOBAL PROPERTY RULE_LAUNCH_CUSTOM) if (NOT _env) set_property(GLOBAL PROPERTY RULE_LAUNCH_CUSTOM "env") endif() foreach(_arg IN LISTS ARGN) set_property(GLOBAL APPEND_STRING PROPERTY RULE_LAUNCH_CUSTOM " ${_arg}") endforeach() endfunction(set_env) set_env(LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb") add_custom_target( MultipleEnvVar COMMAND env | grep -E 'LDFLAGS|CFLAGS' ) 

Alternative (for CMake> = 3.0)

  • I think that what we are really looking for here (except cmake -E env ... ) is called Bracket Argument and allows the character without the need to add backslashes:

     set_property( GLOBAL PROPERTY RULE_LAUNCH_CUSTOM [=[env LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb"]=] ) add_custom_target( MultipleEnvVarNew COMMAND env | grep -E 'LDFLAGS|CFLAGS' ) 

References

+5
source

Ok, I deleted my original answer because it is better than @Florian suggested. Multiple quoted arguments require one additional setup. Consider a list of environment variables as such:

 set(my_env_vars LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb") 

To get the desired extension, convert to a string and then replace ; a space.

 set(my_env_string "${my_env_vars}") #produces LDFLAGS="...";CFLAGS="..." string(REPLACE ";" " " my_env_string "${my_env_string}") 

Then you can continue @Florian's brilliant answer and add a trigger rule. If you need a semicolon in your line, you first need to convert them to something else first.

Please note that in this case I do not need to run using env :

 set_target_properties(mytarget PROPERTIES RULE_LAUNCH_CUSTOM "${my_env_string}") 

This, of course, depends on your shell.

On the other hand, my initial answer is lower, since I also have a case where I do not have access to the target name.

 set(my_env LDFLAGS=\"-Ldir -Ldir2" CFLAGS=\"-Idira -Idirb\") add_custom_command(COMMAND sh -c "${my_env} grep LDFLAGS" VERBATIM) 

This method still requires replacing the semicolons from the list-> string conversion.

+1
source

All Articles