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

e7arh2l6  于 2022-11-11  发布在  其他
关注(0)|答案(1)|浏览(111)

CMake提供了多种机制来将标志传递给编译器:

  • CMAKE_<LANG>_FLAGS_<CONFIG>变量
  • add_compile_options命令
  • set_target_properties命令

在现代应用中,是否有一种方法比另一种方法更受青睐?如果是,为什么?还有,这种方法如何与多配置系统(如MSVC)一起使用?

1l5u6lss

1l5u6lss1#

对于现代的CMake(2.8.12及更高版本),您应该使用target_compile_options,它在内部使用目标属性。
CMAKE_<LANG>_FLAGS是一个全局变量,也是最容易出错的变量。它也不支持generator expressions,而generator expressions可以很方便地使用。
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关键字定义了scope of the options。例如,如果我们将foo链接到bar,并使用target_link_libraries(bar foo)

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

相关问题