【发布时间】:2014-07-22 14:23:25
【问题描述】:
CMake 提供了多种机制来获取编译器的标志:
CMAKE_<LANG>_FLAGS_<CONFIG>variablesadd_compile_optionscommandset_target_propertiescommand
在现代使用中,是否有一种方法优于另一种方法?如果是,为什么?另外,这种方法如何与MSVC等多种配置系统一起使用?
【问题讨论】:
标签: cmake
CMake 提供了多种机制来获取编译器的标志:
CMAKE_<LANG>_FLAGS_<CONFIG> variablesadd_compile_options commandset_target_properties command在现代使用中,是否有一种方法优于另一种方法?如果是,为什么?另外,这种方法如何与MSVC等多种配置系统一起使用?
【问题讨论】:
标签: cmake
对于现代 CMake(2.8.12 及更高版本),您应该使用 target_compile_options,它在内部使用目标属性。
CMAKE_<LANG>_FLAGS 是一个全局变量,使用起来最容易出错。它也不支持generator expressions,它可以派上用场。
add_compile_options 基于目录属性,这在某些情况下很好,但通常不是指定选项的最自然方式。
target_compile_options 在每个目标的基础上工作(通过设置 COMPILE_OPTIONS 和 INTERFACE_COMPILE_OPTIONS 目标属性),这通常会产生最干净的 CMake 代码,因为源文件的编译选项取决于哪个项目文件属于(而不是放在硬盘上的哪个目录)。这还有一个额外的好处,那就是它automatically takes care of passing options on 可以在需要时连接到依赖目标。
尽管它们有点冗长,但 per-target 命令允许对不同的构建选项进行合理的细粒度控制,并且(根据我的个人经验)从长远来看最不可能引起头痛。
理论上,您也可以直接使用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}>")
PUBLIC、PRIVATE 和 INTERFACE 关键字定义了 scope of the options。例如,如果我们将 foo 链接到 bar 和 target_link_libraries(bar foo):
PRIVATE 选项将仅应用于目标本身 (foo),而不应用于链接到它的其他库(消费者)。INTERFACE 选项将仅应用于消费目标 bar
PUBLIC 选项将同时应用于原始目标 foo 和消费目标 bar
【讨论】:
target_compile_options add 选项,所以你可以修改最后一行像this 使其更具可读性)
COMPILE_OPTIONS 目录属性执行此操作。您可以使用add_compile_options 命令进行设置。这是一个好的方法的选项通常很少。
PUBLIC在target_compile_options中有什么用?
PUBLIC 关键字的附加说明。
这三种方式服务于不同的目的,因此一般来说没有一种方式优于其他方式。 CMAKE_<LANG>_FLAGS 是用户可以定义的变量,用于在为项目调用 CMake 时传递标志。另外两个在项目中使用。一个为特定目标设置标志,另一个为整个目录或生成器表达式设置标志。
相关问题:Difference between add_compile_options and SET(CMAKE_CXX_FLAGS...)
【讨论】:
target_compile_options的方式。恕我直言target_compile_options 应该是首选,因为它允许对选项进行细粒度控制,并且允许使用生成器表达式。 add_compile_options 在目录范围内设置标志。你能详细说明你的答案吗?还有一些网站提到应该首选target_compile_options。