【问题标题】:cmake list append for compiler flags yields bogus results?cmake list append for compiler flags 产生虚假结果?
【发布时间】:2013-05-08 05:37:21
【问题描述】:

我需要在我的 CMake 文件 (CMake 2.8.10.2) 中的 C 和 C++ 编译行中添加各种标志。我看到有些人使用add_definitions,但据我所知,这是用于预处理器标志的(-D)。我有一些不想传递给预处理器的标志。

所以我一直在尝试修改CMAKE_C_FLAGSCMAKE_CXX_FLAGS。我看到有些人正在使用类似的东西:

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -new -flags -here")

但后来我在 cmake 文档中读到这效率较低,正确的做法是使用 list(APPEND ...),如下所示:

list(APPEND CMAKE_C_FLAGS -new -flags -here)

但是,当我这样做时,我的编译行包含用分号分隔的标志并且是语法错误。我读到这是现在列表存储在内部,但我认为当我使用变量时这将由 cmake 处理。这似乎很基本;难道我做错了什么?我的意思是,除非您碰巧想要一个以分号分隔的值列表(除了我猜是 Windows %PATH% 设置或其他东西),否则如果无法使用这些列表,那么这些列表到底有什么用?即使文档表明它的效率/适当性较低,我是否应该使用引用的版本?

【问题讨论】:

  • 我在 set() 方法中使用了宏,因为在复制内容等时很容易导致 var 名称不匹配:macro(append name item) set(${name} "${ ${name}} ${item}") endmacro()

标签: cmake


【解决方案1】:

在 CMake 中,“列表”是由 分号 分隔的项目字符串。例如:

set(FOO "a")
list(APPEND FOO "b") # now FOO="a;b"
list(APPEND FOO "c") # now FOO="a;b;c"

在 CMake 中,由 空格 分隔的项目字符串只是一个字符串,而不是一个列表。使用string(APPEND) 命令附加到它。例如:

set(FOO "a")
string(APPEND FOO " b") # now FOO="a b"
string(APPEND FOO " c") # now FOO="a b c"

在缺少 string(APPEND) 命令的旧版本 CMake 上,您应该回退到 set 命令。例如:

set(FOO "a")
set(FOO "${FOO} b")
set(FOO "${FOO} c")

【讨论】:

  • 按照您刚才解释的逻辑,set(FOO "${FOO} b") 会将" b" 添加到现有的最后一项(即"x;y;z" 将变为"x;y;z b")。您需要单独引用参数:set(FOO "${FOO}" "b")。对于编译器标志,这没什么大不了的,因为这些单独的参数在传递给编译器之前将与空格连接,但最好还是避免。当然,您可以通过使用list(APPEND ...) 来避免这个问题,但即便如此,您也需要小心单独引用参数。
【解决方案2】:

在这种情况下,您确实通常会使用set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -new -flags -here") 技术。

你说得对,在大多数其他情况下,CMake 可以将分号分隔的列表“翻译”成对编译器有意义的内容(例如,可执行文件中的源文件列表),但在这种情况下,CMake 采用标志作为一个完整的字符串传递给编译器/链接器。

如果您真的想将标志列表保留为 CMake 列表,则可以,但在退出 CMakeLists.txt 之前,您可以自己将列表“翻译”为单个字符串值 CMAKE_C_FLAGS,但不常见看看这个。

【讨论】:

  • 一个更简洁的成语是`string(APPEND CMAKE_C_FLAGS " -new-flags")。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多