现代CMake中设置通用编译标志的方法是什么?

113

1个回答

133

对于现代CMake(版本2.8.12及以上),您应该使用内部使用目标属性的target_compile_options

CMAKE_<LANG>_FLAGS是全局变量,最容易出错。它还不支持生成器表达式,而这些表达式非常方便。

add_compile_options基于目录属性,在某些情况下很好,但通常不是指定选项的最自然方式。

target_compile_options基于每个目标(通过设置COMPILE_OPTIONSINTERFACE_COMPILE_OPTIONS目标属性),这通常会产生最清晰的CMake代码,因为源文件的编译选项由其所属的项目(而不是硬盘上所在的目录)确定。这具有额外的优点,即如果需要,它会自动处理传递的使用要求到相关目标。

虽然它们有点冗长,但基于每个目标的命令允许在不同的构建选项上进行合理的精细控制,并且(根据我的个人经验)最不可能在长期运行中引起头痛问题。

理论上,您也可以直接使用set_target_properties设置相应的属性,但target_compile_options通常更易读。

例如,要使用生成器表达式为名为foo的目标设置编译选项,可以编写:

target_compile_options(foo PUBLIC "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>")
target_compile_options(foo PUBLIC "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")

PUBLICPRIVATEINTERFACE 这几个关键字定义了选项的作用域,详见文档。例如,如果我们用 target_link_libraries(bar foo)foo 链接到 bar

  • PRIVATE 选项只应用于目标本身(foo),而不应用于其他链接到它的库(消费者)。
  • INTERFACE 选项只应用于消费目标 bar
  • PUBLIC 选项将应用于原始目标 foo 和消费目标 bar

15
请注意,target_compile_options增加选项,因此您可以修改最后一行的代码(类似于这样)以使其更易读。 - user2288008
2
@ComicSansMS 很棒的回答,也是我在互联网上找到的最好(也是最新)的答案。谢谢! - Ela782
6
PUBLICtarget_compile_options 中的作用是将编译选项传递给当前目标及其依赖项。 - Ramana Reddy
1
@RamanaReddy,我在答案中添加了PUBLIC关键字的额外解释。 - Stefan Profanter
3
请注意,如果您的 MY_DEBUG_OPTIONS 包含空格,则需要使用 SHELL: 前缀,例如:target_compile_options(${NAME} PUBLIC $<$<CONFIG:DEBUG>:SHELL:${MY_DEBUG_OPTIONS}>)。否则,Cmake 将在您的编译器选项周围添加双引号,导致编译错误。 - Nathanael Weiss
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接