使用具有 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
)
受抚养者将继承 属性,但您可以在每个受抚养者中明确设置它,以防万一您以后决定不使用基础库,则破坏的可能性较小。
目前我的目录结构如下所示
.
├── 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
)
受抚养者将继承 属性,但您可以在每个受抚养者中明确设置它,以防万一您以后决定不使用基础库,则破坏的可能性较小。