【发布时间】:2016-06-21 05:37:28
【问题描述】:
我是第一次编写 CMake 宏,我很难理解变量是如何工作的。更具体地说,${a} 似乎与 "${a}" 具有不同的含义。
例如这里:Passing a list to a CMake macro
我不明白什么时候应该添加引号,以及更大的基本原则是什么。
【问题讨论】:
我是第一次编写 CMake 宏,我很难理解变量是如何工作的。更具体地说,${a} 似乎与 "${a}" 具有不同的含义。
例如这里:Passing a list to a CMake macro
我不明白什么时候应该添加引号,以及更大的基本原则是什么。
【问题讨论】:
你必须牢记的两个 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") 和 message(${_my_list}) 将给 ABC
一些经验法则
您应该考虑一些经验法则:
a) 当您的变量包含文本(尤其是可能包含分号的文本)时,您应该添加引号。
推理:分号是 CMake 中列表元素的分隔符。所以在一个应该是一个文本的地方加上引号(它在任何地方都有效,对我个人来说,使用 CMake 语法突出显示效果更好)
编辑:感谢@schieferstapel 的提示
b) 更准确地说:带有空格且已包含引号的变量内容确实保留了这些引号(想象一下,它获取了变量内容的一部分)。这在任何地方也适用于不带引号的(普通或用户定义的函数参数),if() 调用的显着例外,其中 CMake 在变量扩展后重新解释不带引号的变量的内容(另请参见经验法则 #3 和策略 CMP0054: Only interpret if() arguments as variables or keywords when unquoted )
示例:
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
如果您的变量包含一个列表,您通常不会添加引号。
推理:如果你给 CMake 命令提供文件列表之类的东西,它通常需要一个字符串列表,而不是一个包含列表的字符串。您可以看到的差异,例如在foreach() 命令中接受ITEMS 或LISTS。
if() 语句是一种特殊情况,您通常甚至不放置大括号。
推理:一个字符串可以 - 在扩展之后 - 再次评估为一个变量名。为防止这种情况发生,建议只命名要比较其内容的变量(例如if (_my_text STREQUAL "A B C"))。
COMMAND 示例
set(_my_text "A B C") 和 COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" 将
cmake.exe -E echo "A B C"
cmake -E echo A\ B\ C
A B C
set(_my_text "A B C") 和 COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM 将
cmake.exe -E echo "A B C"
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
A,B: command not found,C: 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 调用中使用变量时应考虑一些经验法则:
a) 为包含文件路径的参数使用引号(例如包含可执行文件本身的第一个参数)。
推理:它可以包含空格,并且可以重新解释为 COMMAND 调用的单独参数
b) 见上文,如果变量 set() 确实包含引号,也可以使用。
仅在您想将某些内容连接成单个参数以传递给被调用的可执行文件时使用引号。
推理:一个变量可能包含一个参数列表 - 当使用引号时 - 将无法正确提取(分号而不是空格)
始终将VERBATIM 选项与add_custom_target()/add_custom_command() 一起添加
推理:否则跨平台行为是未定义的,您可能会对引用的字符串感到惊讶。
参考文献
【讨论】:
func(${X}),不带引号)并且X 包含空格,X 仍然只是一个参数,并且不会像您说的那样被扩展/评估。引用每个可能包含带空格的路径的变量太容易出错(就像在例如 POSIX shell 中一样)。
add_custom_command() 部分(以为我当时已经测试过了,但我会仔细检查)。