使用具有 C++ 继承的 CMake 时,我应该如何组织我的目录结构?

How should I organize my directory structure when using CMake with C++ inheritance?

目前我的目录结构如下所示

.
├── CMakeLists.txt
├── Base
│   ├── CMakeLists.txt
│   ├── include
│   │   └── base.h
│   └── src
│       └── base.cpp
├── Derived
│   ├── CMakeLists.txt
│   ├── include
│   │   └── derived.h
│   └── src
│       └── derived.cpp
└── src
    └── main.cpp

CMakeLists.txt 文件看起来像

./CMakeLists.txt

cmake_minimum_required(VERSION 3.1)

set(CMAKE_CXX_STANDARD 11)

project(MyProj)

add_subdirectory(Base)
add_subdirectory(Derived)

add_executable(main src/main.cpp)
target_link_libraries(main Base)
target_link_libraries(main Derived)

./Base/CMakeLists.txt

add_library(Base STATIC src/base.cpp)
target_include_directories(Base PUBLIC include)

./Derived/CMakeLists.txt

add_library(Derived STATIC src/derived.cpp)
target_include_directories(Derived PUBLIC include)
target_link_libraries(Derived Base)

我想知道在 C++ 中使用继承时,这是否是构建 CMake 项目的合适方法。如果有更惯用的方式来构建它,我愿意接受建议。

为每个 class 创建一个库是多余的,并且可能会减慢某些构建系统上的编译速度。

在我的一些项目中,我有超过 300 种类型,这还不算模板和 lambda。我无法想象为每个 classes 创建一个库。

I want to know if this is an appropriate way to structure a CMake project when using inheritance in C++

您正在使用的功能不应改变代码的物理组织方式。相反,将文件布局基于代码的逻辑自包含部分,并在每个部分之间明确依赖关系。

唯一吹毛求疵的地方:用这个表格把link个图书馆放在一起:

target_link_libraries(main PUBLIC Base) # or private

您的 CMake 的其余部分充分利用了基于目标的 API。我唯一要改变的是在构成库的方面不那么细粒度。

如果您打算构建两个库和一个可执行文件,那么这就是您的结构实现的目标。但是,我建议您考虑一下为什么要这样做,并且可能考虑将两个 类 都放在一个库中是否会更简单。

If I keep extending this, say make another class that inherits from Derived, then I have to make a new CMakeLists.txt file then link and include against these files. I don't have a problem doing this, but it does not seem very maintainable for larger projects

不,除非添加新目标,否则您不必创建新的 CMakeLists.txt。一个项目不一定需要多个目标。

一个目标(无论是可执行文件还是库)不限于只有一个翻译单元。

我个人对小项目的偏好是三个(或两个)目标:一个包含所有功能的库,一个带有 int main() 的主要可执行文件,除了调用该库外什么都不做(如果项目是可执行文件而不是只是库),以及来自测试框架的 int main() 的测试可执行文件。如果库中有可在其他项目中重复使用的部分,则可以选择将该库拆分为更小的部分。


set(CMAKE_CXX_STANDARD 11)

改用目标特定属性:

set_target_properties(
    Base PROPERTIES
    CXX_STANDARD 11

    # use unless you also support older standards
    CXX_STANDARD_REQUIRED ON
)

受抚养者将继承 属性,但您可以在每个受抚养者中明确设置它,以防万一您以后决定不使用基础库,则破坏的可能性较小。