cmake:何时引用variables?

我第一次写CMakemacros,而且我很难理解variables是如何工作的。 最具体地说,$ {a}似乎与“$ {a}”有不同的含义。

例如这里:

将一个列表传递给一个cmakemacros

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

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

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

例子

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

一些经验法则

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

  1. a)当你的variables包含文本 – 尤其是一个可能包含分号的文本 – 你应该添加引号。

    推理 :分号是CMake中列表元素的分隔符。 所以把引号放在应该是一个文本的地方(它在任何地方都能正常工作,而且对于我个人而言CMake语法突出显得更好)

    编辑:谢谢@schieferstapel暗示

    b)更确切地说:一个已经有引号的空格的variables内容会保留这些引号(想象它变成了variables内容的一部分)。 除了if()调用,其中CMake在variables扩展之后重新解释非引用variables的内容(另请参阅经验法则#3和策略CMP0054:仅限于此 ),此函数在任何地方都可以正常工作(正常或用户定义的函数参数) 解释if()参数作为variables或关键字时,不加引号 )

    例子:

    • message(${_my_text}) set(_my_text "ABC")也会给ABC
    • if given arguments: "A" "B" "C" "STREQUAL" "A;B;C" Unknown arguments specified if (${_my_text} STREQUAL "A;B;C")将给出if (${_my_text} STREQUAL "A;B;C") set(_my_text "A;B;C") if given arguments: "A" "B" "C" "STREQUAL" "A;B;C" Unknown arguments specified
  2. 如果你的variables包含一个列表,你通常不会添加引号。

    推理 :如果你给一个CMake命令一个文件列表,它通常期望一个string列表,而不是一个包含列表的string。 你可以看到,例如在接受ITEMSLISTSforeach()命令中的差异。

  3. if()语句是一个特殊的情况下,你通常甚至不把大括号。

    推理 :一个string可以在扩展之后再次评估为variables名称。 为了防止这种情况,build议您只为要比较其内容的variables命名(例如if (_my_text STREQUAL "ABC") )。


COMMAND例子

  • 使用COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" set(_my_text "ABC")
    • VS / Windows上调用cmake.exe -E echo "ABC"
    • GCC / Ubuntu上调用cmake -E echo A\ B\ C
    • ABC
  • 使用COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM set(_my_text "ABC") COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM
    • VS / Windows上调用cmake.exe -E echo "ABC"
    • GCC / Ubuntu上调用cmake -E echo "ABC"
    • ABC
  • COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" set(_my_list ABC)
    • 调用cmake.exe -E echo A;B;C
    • AB: command not foundC: command not found
  • set(_my_list ABC) COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
    • 调用cmake.exe -E echo "A;B;C"
    • A;B;C
  • 使用COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM set(_my_list "A" "B" "C") COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
    • 调用cmake.exe -E echo "A;B;C"
    • A;B;C
  • 使用COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM set(_my_list "A" "B" "C") COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
    • 调用cmake.exe -E echo ABC
    • ABC
  • COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM 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调用中使用variables时,应该考虑一些经验法则:

  1. a)为包含文件path的参数使用引号(如包含可执行文件本身的第一个参数)。

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

    b)参见上面,如果variablesset()确实包含引号,也可以使用。

  2. 当您想要将某些参数连接成单个parameter passing给所调用的可执行文件时才使用引号。

    推理 :一个variables可以包含一个参数列表 – 当使用引号时 – 不会被正确提取(分号代替空格)

  3. 总是添加VERBATIM选项add_custom_target() / add_custom_command()

    推理 :否则,跨平台的行为是不确定的,你可以得到惊喜引用的string。

参考

  • CMake:$ {}和“$ {}”之间的区别
  • 什么是CMake语法来设置和使用variables?
  • 在一个string列表中循环
  • CMake与STREQUAL的空string比较失败