Cmake: when to quote variables?

This is the first time I'm writing CMake macros, and it's hard for me to understand how a variable works. In particular, $ {a} seems to have a different meaning than "$ {a}".

For example:

Passing a List to cmake Macro

I do not understand when I should add quotes, and what is the basic principle.

+18
variables macros cmake
Mar 07 '16 at 15:32
source share
1 answer

Two CMake principles you should keep in mind:

  • CMake is a script language and arguments are evaluated after variable expansion
  • CMake distinguishes between normal strings and list variables (semicolon-delimited strings)

<strong> Examples

  • set(_my_text "ABC") with message("${_my_text}") will give ABC
  • set(_my_list ABC) with message("${_my_list}") will give A;B;C
  • set(_my_list "A" "B" "C") with message("${_my_list}") will give A;B;C
  • set(_my_list "A" "B" "C") with message(${_my_list}) will give ABC

Some rules of the thumb

There are a few rules you should consider:

  • a) When your variable contains text - especially one that may contain semicolons, you must add quotation marks.

    Reason: The semicolon is a separator for list items in CMake. So put quotation marks around the text, which should be one (it works everywhere and for me personally looks better with CMake syntax highlighting)

    EDIT: Thanks for the tip @schieferstapel

    b) More precisely: variable contents with spaces that already have quotation marks retain these quotation marks (imagine that they become part of the contents of the variable). It works everywhere also without quotes (regular or user-defined function parameters) with a noticeable exception to if() calls, where CMake re-interprets the contents of unquoted variables after expanding the variable (see also rule No. 3 and policy CMP0054: interpret if() arguments as variables or keywords when not quoting )

    Examples:

    • set(_my_text "ABC") with message(${_my_text}) will also give ABC
    • set(_my_text "A;B;C") with if (${_my_text} STREQUAL "A;B;C") will give if given arguments: "A" "B" "C" "STREQUAL" "A;B;C" Unknown arguments specified
  • If your variable contains a list, you usually do not add quotation marks.

    Reasoning: if you pass something like a list of files to the CMake command, then you usually expect a list of lines, not a single line containing a list. The difference that you can see, for example, in the foreach() command that accepts ITEMS or LISTS .

    Operators
  • if() is a special case when you usually don't put curly braces.

    Reasoning: a string can - after expansion - evaluate the variable name again. To prevent this, it is recommended that you simply specify the variable whose contents you want to compare (for example, if (_my_text STREQUAL "ABC") ).




COMMAND Examples

  • set(_my_text "ABC") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" will be
    • call cmake.exe -E echo "ABC" on VS / Windows
    • call cmake -E echo A\ B\ C in GCC / Ubuntu
    • give ABC
  • set(_my_text "ABC") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM will be
    • call cmake.exe -E echo "ABC" on VS / Windows
    • call cmake -E echo "ABC" in GCC / Ubuntu
    • give ABC
  • set(_my_list ABC) with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" will be
    • call cmake.exe -E echo A;B;C
    • enter A , B: command not found , C: command not found
  • set(_my_list ABC) with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM will be
    • call cmake.exe -E echo "A;B;C"
    • give A;B;C
  • set(_my_list "A" "B" "C") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM will be
    • call cmake.exe -E echo "A;B;C"
    • give A;B;C
  • set(_my_list "A" "B" "C") with COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM will be
    • call cmake.exe -E echo ABC
    • give ABC
  • set(_my_list "A + B" "=" "C") with COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM will be
    • call cmake.exe -E echo "A + B" = C
    • give A + B = C

Some thumb rules with add_custom_target() / add_custom_command() / execute_process()

There are several important rules to consider when using variables in COMMAND calls:

  • a) Use quotation marks for arguments containing file paths (for example, the first argument containing the executable itself).

    Reasoning: it can contain spaces and can be reinterpreted as separate arguments for calling COMMAND

    b) See above, also works if set() included quotes.

  • Use quotation marks only if you want to combine something into one parameter, which will be passed to the executable, which is called.

    Reasoning: a variable may contain a list of parameters that, when using quotation marks, will not be correctly extracted (semicolons instead of spaces)

  • Always add the VERBATIM parameter with add_custom_target() / add_custom_command()

    Reasoning: Otherwise, the cross-platform behavior is undefined, and you may get surprises with your quotes.

References

  • CMake: difference between $ {} and "$ {}"
  • What is CMake syntax for setting and using variables?
  • Quoting from a string list
  • Comparing CMake with an empty string with a STREQUAL error
+31
Mar 07 '16 at 20:11
source share



All Articles