什么时候应该引用变量?

时间:2016-03-07 15:32:58

标签: variables cmake macros

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

例如: Passing a list to a CMake macro

我无法理解何时应该添加引号,以及更重要的基本原则是什么。

1 个答案:

答案 0 :(得分:49)

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

  1. CMake是一种脚本语言,在变量扩展后评估参数
  2. CMake区分正常字符串和列表变量(带分号分隔符的字符串)
  3. <强>实施例

    • 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") message(${_my_list})ABC

    一些经验法则

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

    1. a)当你的变量包含文本时 - 尤其是包含分号的文本 - 你应该添加引号。

      推理:分号是CMake中列表元素的分隔符。所以在一个应该是一个的文本周围加上引号(它可以在任何地方使用,对于我个人看起来更好用CMake语法高亮)

      编辑:感谢@schieferstapel的提示

      b)更确切地说:具有已经有引号的空格的变量内容确实保留了这些引号(想象一下它获得变量内容的一部分)。这种方法在任何地方都可以使用不带引号(正常或用户定义的函数参数)以及if()调用的突出例外,其中CMake在变量扩展后重新解释未引用变量的内容(另请参见经验法则#3和策略{ {3}})

      示例:

      • set(_my_text "A B C") message(${_my_text})也会A B C
      • set(_my_text "A;B;C") if (${_my_text} STREQUAL "A;B;C")if given arguments: "A" "B" "C" "STREQUAL" "A;B;C" Unknown arguments specified
    2. 如果您的变量包含列表,则通常不会添加引号。

      推理:如果你给CMake命令提供类似文件列表的东西,它通常需要一个字符串列表而不是一个包含列表的字符串。您可以看到差异,例如在CMP0054: Only interpret if() arguments as variables or keywords when unquoted命令中接受ITEMSLISTS

    3. if()声明是一种特殊情况,您通常不会戴上牙套。

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

    4. COMMAND示例

      • set(_my_text "A B C")COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}"
        • VS / Windows
        • 上致电cmake.exe -E echo "A B C"
        • GCC / Ubuntu
        • 上致电cmake -E echo A\ B\ C
        • A B C
      • set(_my_text "A B C")COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM
        • VS / Windows
        • 上致电cmake.exe -E echo "A B C"
        • GCC / Ubuntu
        • 上致电cmake -E echo "A B C"
        • A B C
      • set(_my_list A B C)COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}"
        • 致电cmake.exe -E echo A;B;C
        • 提供AB: command not foundC: command not found
      • set(_my_list A B C)COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
        • 致电cmake.exe -E echo "A;B;C"
        • A;B;C
      • set(_my_list "A" "B" "C")COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
        • 致电cmake.exe -E echo "A;B;C"
        • A;B;C
      • set(_my_list "A" "B" "C")COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
        • 致电cmake.exe -E echo A B C
        • A B C
      • set(_my_list "A + B" "=" "C")COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
        • 致电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. 始终使用VERBATIM / add_custom_target()

        添加add_custom_command()选项

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

      4. <强>参考