【问题标题】:Does set_target_properties in CMake override CMAKE_CXX_FLAGS?CMake 中的 set_target_properties 是否覆盖 CMAKE_CXX_FLAGS?
【发布时间】:2011-07-03 02:01:41
【问题描述】:

在我的 CMake 项目开始时,我在变量 CMAKE_CXX_FLAGS 中设置通用编译标志,例如

set(CMAKE_CXX_FLAGS "-W -Wall ${CMAKE_CXX_FLAGS}")

稍后,我需要附加其他特定于配置的编译标志(存储在 BUILD_FLAGS 中)。我可以为此使用以下命令吗:

set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS})

还是我必须手动添加 CMAKE_CXX_FLAGS:

set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BUILD_FLAGS}")

防止 CMAKE_CXX_FLAGS 被 BUILD_FLAGS 覆盖?

【问题讨论】:

  • 我相信它们被附加到 CMAKE_CXX_FLAGS 中,您可以通过调用详细的 make 文件 make target VERBOSE=1 来验证这一点

标签: c++ cmake compiler-flags


【解决方案1】:

已接受的answer 仍在工作,但自 2013 年以来已过时。
此答案基于 CMake v2.8.12、v3.3 和 v3.13 中的新功能。

自 CMake-2.8.12 (2013) 起

设置CMAKE_CXX_FLAGS的两个新命令:

上一版本的文档自cmake-2.8.12以来没有太大变化:

在你的情况下,你可以使用:

target_compile_options(${TARGET} PRIVATE ${BUILD_FLAGS})

或者只是如果你有一个单一的目标:

add_compile_options(${BUILD_FLAGS})

更多示例

target_compile_options(mylib PRIVATE   -O2) # only internal
target_compile_options(mylib INTERFACE -gl) # only external
target_compile_options(mylib PUBLIC    -g)  # same as PRIVATE + INTERFACE

# multiple targets and flags
target_compile_options(mylib1 mylib2 PRIVATE -Wall -Wextra)

target_compile_options(    mylib PUBLIC -DUSEXX)  # Bad
target_compile_definitions(mylib PUBLIC -DUSEXX)  # OK

add_compile_options(-Wall -Wextra) # for all targets in current directory
add_compile_options(-DUSEXX)       # Bad
add_definitions(-DUSEXX)           # OK

已弃用 COMPILE_FLAGS

cmake-3.0 documentationCOMPILE_FLAGS 标记为已弃用:

COMPILE_FLAGS

编译此目标的源代码时要使用的其他标志。

COMPILE_FLAGS 属性设置额外的编译器标志,用于 在目标中构建源。使用COMPILE_DEFINITIONS 传递 额外的预处理器定义。

此属性已弃用。使用 COMPILE_OPTIONS 属性或 改为target_compile_options 命令。

如果您仍想使用set_target_properties(),您可以使用COMPILE_OPTIONS 而不是COMPILE_FLAGS

set_target_properties(${TARGET} PROPERTIES COMPILE_OPTIONS ${BUILD_FLAGS})

自 CMake-3.3 (2015) 起

Anton Petrov 建议使用generator expressions,如answer of ar31 中所示。

CMake 生成器表达式 将您的${BUILD_FLAGS} 应用于:

  • C++ 语言使用$<COMPILE_LANGUAGE:CXX>(也可以是CCUDA...)
  • 使用$<CXX_COMPILER_ID:Clang>的Clang编译器
    (对于gcc,也可以是GNU,对于Visual C++,也可以是MSVC...参见full list
    (如果语言是 C,请改用 $<C_COMPILER_ID:Clang>
  • 以及更多支持的 C++ 功能编译器版本...(请参阅documentation

在你的情况下,你可以使用:

target_compile_options(${TARGET} PRIVATE
          $<$<COMPILE_LANGUAGE:CXX>:${BUILD_FLAGS_FOR_CXX}>
          $<$<COMPILE_LANGUAGE:C>:${BUILD_FLAGS_FOR_C}>)

或关于编译器:

target_compile_options(${TARGET} PRIVATE
          $<$<CXX_COMPILER_ID:Clang>:${BUILD_FLAGS_FOR_CLANG}>
          $<$<CXX_COMPILER_ID:GNU>:${BUILD_FLAGS_FOR_GCC}>
          $<$<CXX_COMPILER_ID:MSVC>:${BUILD_FLAGS_FOR_VISUAL}>)

自 CMake-3.13 (2018) 起

Craig Scott 提到的新函数 target_link_options() 允许将选项传递给链接器。

C 和 C++ 文件的不同选项

最好的方法是使用两个不同的目标来区分 C 文件和 C++ 文件。

【讨论】:

  • 如果你有混合目标怎么办?例如 C 和 C++。如何仅为 C 目标设置选项?
  • 嗨@Martin。我不知道目标混合使用每种源文件的不同选项的 C 和 C++ 文件。我可能会建议将此目标分成两部分:一个用于 C 源代码,另一个用于 C++。 ...好的,我开始在可能的答案中添加一个部分,以提出一种解决这种复杂情况的方法...
  • 为什么我不能以同样的方式使用set_target_properties()LINK_FLAGS?似乎它从不接受多个标志(即使是列表形式)。
  • @olibre 请参阅此答案stackoverflow.com/a/21561742/423959 以了解特定于语言的选项。正确的方法是使用生成器表达式。
  • $&lt;$&lt;COMPILE_LANGUAGE:C&gt;:${BUILD_FLAGS_FOR_CXX}&gt; 可能是个错误,应该是$&lt;$&lt;COMPILE_LANGUAGE:C&gt;:${BUILD_FLAGS_FOR_C}&gt;
【解决方案2】:

使用第一个:

set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS})

编译 TARGET 的源代码时,存储在 BUILD_FLAGS 中的标志会附加在 CMAKE_CXX_FLAGS 之后。文档提示了这一点,但我只是尝试过确认。

COMPILE_FLAGS

   Additional flags to use when compiling this target's sources. 
   
   The COMPILE_FLAGS property sets additional compiler flags used to
   build sources within the target.  Use COMPILE_DEFINITIONS to
   pass additional preprocessor definitions.

完整的命令行相当于:

${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS} -o foo.o -c foo.cc

正如 Ramon 所说,您可以随时与 make VERBOSE=1 联系。

【讨论】:

  • 你是对的,非常感谢你(也感谢 Ramon)。我以前也不知道 VERBOSE 参数,现在我更容易了解 CMake 实际如何处理我的命令。
猜你喜欢
  • 2016-02-02
  • 2021-01-24
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 2022-06-22
  • 2021-04-08
  • 1970-01-01
  • 2022-12-18
相关资源
最近更新 更多