CMake:子目录可以继承编译功能吗?

Wyz*_*a-- 1 c++ cmake c++14

我有一个 C++ 项目,它由一个主程序 ( main.cpp)、一个定义抽象类的头文件 ( algorithm.hpp) 和一个algorithms/充满实现抽象类的类的子目录 ( ) 组成。我已将 CMake 配置为将子目录构建为对象库:

# algorithms/CMakeLists.txt
add_library(algorithms_lib OBJECT
  algo1.cpp
  algo2.cpp
  # etc.
)
Run Code Online (Sandbox Code Playgroud)

在我的项目的根目录中,我使用这个对象库作为应用程序的源之一:

# Top-level CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(MyApp CXX)

add_subdirectory(algorithms)

add_executable(my-app
  main.cpp
  $<TARGET_OBJECTS:algorithms_lib>
)
Run Code Online (Sandbox Code Playgroud)

我的应用程序是用 C++14 编写的,所以我需要告诉 CMake 为此使用正确的编译选项。我不想要求 CMake 3.8 版(因为它没有打包在我想要支持的一些最近的 Linux 发行版中),所以我不能使用cxx_std_14编译功能;相反,我列出了一些我使用的个人语言功能:

# Top-level CMakeLists.txt (cont.)
target_compile_features(my-app PUBLIC
  cxx_auto_type
  cxx_constexpr
  cxx_defaulted_functions
  # ...14 more lines...
)
Run Code Online (Sandbox Code Playgroud)

问题是,这些功能仅适用于顶级my-app目标,而不适用于algorithms_lib目标,因此子目录中的源代码不会被编译为 C++14。

我知道我可以将整个大块复制target_compile_features到 中algorithms/CMakeLists.txt,但我宁愿不这样做——特别是因为这个例子被简化了,而且我实际上有九个这样的子目录,每个子目录都构建了自己的对象库。那将是大量重复的样板代码。

有没有办法为项目中的所有 C++ 目标(包括子目录)全局设置编译功能?或者最好摆脱add_subdirectory对象库,只在顶级add_executable命令中列出所有单独的子目录文件?我是 CMake 的新手,所以我不知道这种事情的“最佳实践”是什么。

Cra*_*ott 7

听起来您想将以下内容放在CMakeLists.txt文件顶部:

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
Run Code Online (Sandbox Code Playgroud)

这些为没有前导的同名目标属性设置默认值CMAKE_。等效的目标属性执行以下操作:

CXX_STANDARD yy 设置您的代码想要使用的所需的最低 C++ 标准。

CXX_STANDARD_REQUIRED bb表示是否CXX_STANDARD是一个要求(bbYES或其他一些布尔等价物)或它是否只是可取的(bbNO或等价物)。

CXX_EXTENSIONS bb启用 ( bb = YES) 或禁用 ( bb = NO) 编译器扩展。

您不需要指定单独的编译器功能来实现您最终想要做的事情(为您的目标启用 C++14)。您可以在此处找到有关整个领域的完整讨论。