我什么时候应该引用 CMake 变量? [英] When should I quote CMake variables?

查看:28
本文介绍了我什么时候应该引用 CMake 变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是第一次编写 CMake 宏,我很难理解变量是如何工作的.最具体地说,${a} 似乎与 "${a}" 的含义不同.

例如:将列表传递给 CMake 宏

我不明白什么时候应该添加引号,以及更大的基本原则是什么.

解决方案

你必须牢记的 CMake 的两个原则:

  1. CMake 是一种脚本语言,在扩展变量后评估参数
  2. CMake 区分普通字符串和列表变量(带有分号分隔符的字符串)

示例

  • set(_my_text "A B C")message("${_my_text}") 会给出 A B C
  • set(_my_list A B C)message("${_my_list}") 会给出 A;B;C
  • set(_my_list "A" "B" "C")message("${_my_list}") 将给 A;B;C
  • set(_my_list "A" "B" "C") with message(${_my_list}) 会给出 ABC

一些经验法则

您应该考虑一些经验法则:

  1. a) 如果您的变量包含文本——尤其是可能包含分号的文本——您应该添加引号.

    推理:分号是 CMake 中列表元素的分隔符.因此,在应该是一个文本的文本周围加上引号(它无处不在,对我个人而言,使用 CMake 语法突出显示效果更好)

    感谢@schieferstapel 的提示

    b) 更准确地说:带有引号的空格的变量内容确实会保留这些引号(想象一下,它获得了变量内容的一部分).除了 if() 调用的显着例外,这也适用于任何不带引号的(正常或用户定义的函数参数),其中 CMake 在变量扩展后重新解释不带引号的变量的内容(另见经验法则)#3 和策略 CMP0054:仅解释 if() 参数未引用时作为变量或关键字)

    示例:

    • set(_my_text "A B C")message(${_my_text}) 也会给 A B C
    • set(_my_text "A;B;C") with if (${_my_text} STREQUAL "A;B;C") 会给出 if给定参数:A"B"C"STREQUAL"A;B;C"指定未知参数
  2. 如果您的变量包含一个列表,您通常不会添加引号.

    推理:如果您向 CMake 命令提供类似文件列表的内容,它通常需要一个字符串列表,而不是一个包含列表的字符串.您可以看到的差异,例如在 foreach() 命令中接受 ITEMSLISTS.

  3. if() 语句是一种特殊情况,您通常甚至不放置大括号.

    推理:一个字符串可以 - 扩展后 - 再次评估为变量名称.为防止出现这种情况,建议仅命名要比较其内容的变量(例如 if (_my_text STREQUAL "A B C")).

<小时>

COMMAND 示例

  • set(_my_text "A B C") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}"
    • 调用 cmake.exe -E echo "A B C"VS/Windows
    • GCC/Ubuntu上调用cmake -E echo A B C
    • A B C
  • set(_my_text "A B C") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM
    • 调用 cmake.exe -E echo "A B C"VS/Windows
    • GCC/Ubuntu 上调用 cmake -E echo "A B C"
    • A B C
  • set(_my_list A B C) with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}"
    • 调用 cmake.exe -E echo A;B;C
    • A, B: command not found, C: command not found
  • set(_my_list A B C) with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
    • 调用 cmake.exe -E echo "A;B;C"
    • A;B;C
  • set(_my_list "A" "B" "C") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
    • 调用 cmake.exe -E echo "A;B;C"
    • A;B;C
  • set(_my_list "A" "B" "C") with COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list}逐字
    • 调用 cmake.exe -E echo A B C
    • A B C
  • set(_my_list "A + B" "=" "C") with COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
    • call cmake.exe -E echo "A + B" = C
    • A + B = C

add_custom_target()/add_custom_command()/execute_process()

COMMAND 调用中使用变量时,应考虑一些经验法则:

  1. a) 对包含文件路径的参数使用引号(例如包含可执行文件本身的第一个参数).

    推理:它可以包含空格,并且可以重新解释为 COMMAND 调用的单独参数

    b) 如上所示,如果变量 set() 确实包含引号,也可以使用.

  2. 如果您想将某些内容连接到单个参数中以传递给被调用的可执行文件,请使用引号.

    推理:一个变量可能包含一个参数列表——当使用引号时——不会被正确提取(分号而不是空格)

  3. 始终使用 add_custom_target()/add_custom_command()

    添加 VERBATIM 选项

    推理:否则跨平台行为是未定义的,您可能会对引用的字符串感到惊讶.

参考资料

I am writing CMake macros for the first time, and I have a hard time understanding how variables work. Most specifically, ${a} seems to have a different meaning than "${a}".

For example here: Passing a list to a CMake macro

I fail to understand when I am supposed to add quotes, and what are the bigger underlying principles.

解决方案

Two principles of CMake you have to keep in mind:

  1. CMake is a script language and arguments are evaluated after the variables are expanded
  2. CMake differentiates between normal strings and list variables (strings with semicolon delimiters)

Examples

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

Some Rules of Thumb

There are some rules of thumb you should consider:

  1. a) When your variable contains text - especially one that could contain semicolons - you should add quotes.

    Reasoning: A semicolon is a delimiter for list elements in CMake. So put quotes around a text that is supposed to be one (it works everywhere and for me personally looks better with CMake syntax highlighting)

    EDIT: Thanks for the hint from @schieferstapel

    b) To be more precise: A variable content with spaces that already had quotes does keep those quotes (imagine as it getting part of the variable's content). This works everywhere also unquoted (normal or user-defined function parameters) with the prominent exception of if() calls, where CMake re-interprets the content of unquoted variables after variable expansion (see also rule of thumb #3 and policy CMP0054: Only interpret if() arguments as variables or keywords when unquoted)

    Examples:

    • set(_my_text "A B C") with message(${_my_text}) would also give A B C
    • set(_my_text "A;B;C") with if (${_my_text} STREQUAL "A;B;C") would give if given arguments: "A" "B" "C" "STREQUAL" "A;B;C" Unknown arguments specified
  2. If your variable contains a list you normally don't add quotes.

    Reasoning: If you give something like a file list to an CMake command it normally expect a list of strings and not one string containing a list. The difference you can see e.g. in the foreach() command accepting ITEMS or LISTS.

  3. if() statements are a special case where you normally don't even put the braces.

    Reasoning: A string could - after expansion - evaluate again to a variable name. To prevent this it's recommended to just name the variable whose content you want to compare (e.g. if (_my_text STREQUAL "A B C")).


COMMAND Examples

  • set(_my_text "A B C") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" would
    • call cmake.exe -E echo "A B C" on VS/Windows
    • call cmake -E echo A B C on GCC/Ubuntu
    • give A B C
  • set(_my_text "A B C") with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM would
    • call cmake.exe -E echo "A B C" on VS/Windows
    • call cmake -E echo "A B C" on GCC/Ubuntu
    • give A B C
  • set(_my_list A B C) with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" would
    • call cmake.exe -E echo A;B;C
    • give A, B: command not found, C: command not found
  • set(_my_list A B C) with COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM would
    • 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 would
    • 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 would
    • 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 would
    • call cmake.exe -E echo "A + B" = C
    • give A + B = C

Some Rules of Thumb with add_custom_target()/add_custom_command()/execute_process()

There are some rules of thumb you should consider when you use variables in COMMAND calls:

  1. a) Use quotes for the arguments that contain file paths (like the first argument containing the executable itself).

    Reasoning: It could contain spaces and could be reinterpreted as separate arguments to the COMMAND call

    b) See above, works also if the variable set() did include quotes.

  2. Use quotes only if you want to concatenate something into a single parameter to be passed to executable that is called.

    Reasoning: A variable could contain a list of parameters which - when using quotes - won't be correctly extracted (semicolons instead of spaces)

  3. Always add the VERBATIM option with add_custom_target()/add_custom_command()

    Reasoning: Otherwise the cross-platform behavior is undefined and you could get surprises with your quoted strings.

References

这篇关于我什么时候应该引用 CMake 变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆