【问题标题】:CMake: set compile options and compile features per projectCMake:为每个项目设置编译选项和编译功能
【发布时间】:2021-05-04 13:00:29
【问题描述】:

我有一个包含多个软件组件(可执行文件、库)的代码库(例如,存储库)。全部都是使用 CMake 构建的,每个组件都有单独的目标。

现在,我知道设置编译器标志的现代方法是针对特定目标的:

target_compile_options(foo PRIVATE -Werror -Wall -Wextra -pedantic)
target_compile_features(foo PRIVATE cxx_std_17)

但是,我希望整个项目中的所有目标都使用相同的标志。为每个单独的目标编写这些行会导致代码重复并且容易出错(尤其是当标志数量增加时)。有没有办法将编译器标志附加到项目而不是目标?

我知道我可以像这样向顶级目录添加选项:

add_compile_options(-Werror -Wall -Wextra -pedantic)

但我不确定这是否可行,而且我不确定如何为编译功能做同样的事情 (cxx_std_17)。

【问题讨论】:

  • 您不应该在项目本身中设置警告标志。一方面,它们是特定于编译器的。支持多个编译器的警告标志很快就会变成一堆条件,特别是如果您支持同一编译器的多个版本,这些版本具有您需要禁用的不同警告。相反,您可以使用工具链文件或编译器+编译器版本特定的附加 cmake 脚本,这些脚本通过 -DCMAKE_PROJECT_INCLUDE / -DCMAKE_PROJECT_INCLUDE_BEFORE 注入到您的构建中。

标签: cmake


【解决方案1】:

现在,我知道设置编译器标志的现代方法是针对特定目标的:

target_compile_options(foo PRIVATE -Werror -Wall -Wextra -pedantic)
target_compile_features(foo PRIVATE cxx_std_17)

这实际上不是最好/最现代的方式。如果您使用的是 CMake 3.19+,最好的办法是创建一个preset

在您的顶级CMakeLists.txt 旁边创建一个名为CMakePresets.json 的文件,其中包含以下内容:

{
  "version": 1,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 19,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "default",
      "displayName": "Default",
      "description": "Default build using Ninja",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_CXX_FLAGS": "-Werror -Wall -Wextra -pedantic",
        "CMAKE_CXX_STANDARD": "17",
        "CMAKE_CXX_STANDARD_REQUIRED": "YES",
        "CMAKE_CXX_EXTENSIONS": "OFF"
      }
    }
  ]
}

然后配置:

$ cmake --preset=default

以这种方式做事的原因是因为(理想情况下)CMakeLists.txt 中不应包含构建项目所必需的绝对内容。警告标志不在此集中,因此它们属于此处。否则,您会对最终用户施加潜在的无效标志。这在警告标志中非常常见。有一些标志仅是 GCC 或 Clang,其他标志已被删除或重命名,还有其他标志的敏感性在不同版本中发生了变化。如果您的用户通过CMAKE_CXX_FLAGS 手动添加-Werror 而您以其他方式添加标志,则可能会出现问题。

这确实意味着对于,通过target_compile_features 设置cxx_std_NN 通常是合适的,其中NN最低 兼容C++ 版本(不是库的首选版本,尽管它们可能一致)。这是因为可以在INTERFACE(相当于PUBLIC)属性中设置该功能,以确保链接对象为库的标题使用足够新的版本。如果CMAKE_CXX_STANDARD 和编译功能都设置了,将使用最大值。

在旧版本的 CMake 中,toolchain file 可用于相同目的。

【讨论】:

  • 听起来不错!以前从未听说过此功能!在我接受答案之前,请给我一点时间尝试一下。
  • @GeorgP。当然,慢慢来
  • 我遇到了类似的问题,但设置 CMAKE_CXX_FLAGS 将覆盖 CMake 的所有默认值。例如,在 Windows 上,它是“/DWIN32 /D_WINDOWS /W3 /GR /EHsc”。您可以再次指定所有这些选项 - 或者您可以设置环境变量 CXXFLAGS(使用预设)。该值被添加到默认值之前。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-04
  • 2021-06-24
  • 2017-06-14
  • 2015-09-07
  • 1970-01-01
  • 2019-08-26
相关资源
最近更新 更多