用于 lib 和可执行文件的 c++ CMake 项目结构
c++ CMake project structure for lib and executable
我有一个关于如何构建 C++ 项目并使用 CMake(在 CLion 中)构建该项目的问题。我对 c++(两周前才开始学习这门语言)和 CMake(我从未配置过 CMake 文件)非常陌生。然而,我对其他编程语言及其生态系统(如 Java、JavaScript、Php 和 .NET 有很多经验——也许与这些生态系统的类比会有所帮助?
我们正在为一个学校项目构建我们自己的(小型,2d)游戏和游戏引擎。游戏引擎应该可以自行发布,游戏应该建立在我们自己的引擎上。引擎将有自己的依赖项(使用 SDL2 构建,这是一项要求)。
我想象引擎将成为一个(静态)库,而实际游戏将编译为依赖引擎库的可执行文件。
为了简化项目管理,我们希望将引擎和游戏代码托管在同一个 git 存储库中。
考虑到我们可能想将一个 math
模块放入我们的引擎中(可能不是这种情况,但为了这个问题的目的)我想象一个如下所示的文件夹结构:
our-project/
├── README.md
├── engine
│ ├── src
│ │ ├── math.cpp
│ │ └── math.h
│ └── test
│ └── ...
└── game
├── src
│ └── main.cpp
└── test
└── ...
引擎将包含以下代码:
// in math.h
namespace engine::math {
int add(int a, int b);
}
// in math.cpp
#include "math.h"
namespace engine::math {
int add(int a, int b) {
return a + b;
}
}
假设我们想在我们的游戏中使用这个引擎代码,我想象以下代码:
// in game/main.cpp
#include <iostream>
#include "engine/math.h"
using namespace engine;
int main() {
std::cout << math::add(10, 1) << std::endl;
}
问题
- 如何设置 CMake,以便我既可以单独构建引擎(静态库),又可以构建依赖于同一引擎的游戏(可执行文件)?
- 我应该如何管理引擎头文件?我如何让它们可以访问游戏代码?我应该为头文件使用不同的结构吗?
- 这个文件夹结构是否易于管理?我应该考虑采用不同的方法吗?
您声明了单独的 CMake 目标,即在 engine/src/CMakeLists.txt
:
add_library(engine
math.cpp)
在 game/src/CMakeLists.txt
期间,您有
add_executable(my-game
main.cpp)
target_link_libraries(my-game
PRIVATE
engine)
当使用例如make
,您可以通过
单独构建目标
make engine # build only the engine, not the executable
make my-game # build engine if necessary, then build executable
单独的测试目标也很有意义。
CMake 中的包含标志传播如下。
target_include_directories(engine
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR})
以上设置将一个包含目录传播到 link 针对引擎的所有目标。这很简单,但有一个缺点:您无法区分 public headers 和实现细节。作为替代方案,您可以拥有一个目录 engine/src/public/engine
,其中包含游戏将使用的所有 public headers:
target_include_directories(engine
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/public)
target_include_directories(engine
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/public/engine)
这样,game
中的客户端代码使用 #include "engine/math.h"
,而在 engine
中,您可以直接使用 #include "math.h"
。我喜欢这样的设置,因为它很容易看出什么是库的接口以及它的实现是什么。但这也有点品味问题。
又自以为是了。但我认为这是一个很好的目录结构。坚持下去。
我有一个关于如何构建 C++ 项目并使用 CMake(在 CLion 中)构建该项目的问题。我对 c++(两周前才开始学习这门语言)和 CMake(我从未配置过 CMake 文件)非常陌生。然而,我对其他编程语言及其生态系统(如 Java、JavaScript、Php 和 .NET 有很多经验——也许与这些生态系统的类比会有所帮助?
我们正在为一个学校项目构建我们自己的(小型,2d)游戏和游戏引擎。游戏引擎应该可以自行发布,游戏应该建立在我们自己的引擎上。引擎将有自己的依赖项(使用 SDL2 构建,这是一项要求)。
我想象引擎将成为一个(静态)库,而实际游戏将编译为依赖引擎库的可执行文件。
为了简化项目管理,我们希望将引擎和游戏代码托管在同一个 git 存储库中。
考虑到我们可能想将一个 math
模块放入我们的引擎中(可能不是这种情况,但为了这个问题的目的)我想象一个如下所示的文件夹结构:
our-project/
├── README.md
├── engine
│ ├── src
│ │ ├── math.cpp
│ │ └── math.h
│ └── test
│ └── ...
└── game
├── src
│ └── main.cpp
└── test
└── ...
引擎将包含以下代码:
// in math.h
namespace engine::math {
int add(int a, int b);
}
// in math.cpp
#include "math.h"
namespace engine::math {
int add(int a, int b) {
return a + b;
}
}
假设我们想在我们的游戏中使用这个引擎代码,我想象以下代码:
// in game/main.cpp
#include <iostream>
#include "engine/math.h"
using namespace engine;
int main() {
std::cout << math::add(10, 1) << std::endl;
}
问题
- 如何设置 CMake,以便我既可以单独构建引擎(静态库),又可以构建依赖于同一引擎的游戏(可执行文件)?
- 我应该如何管理引擎头文件?我如何让它们可以访问游戏代码?我应该为头文件使用不同的结构吗?
- 这个文件夹结构是否易于管理?我应该考虑采用不同的方法吗?
您声明了单独的 CMake 目标,即在
engine/src/CMakeLists.txt
:add_library(engine math.cpp)
在
game/src/CMakeLists.txt
期间,您有add_executable(my-game main.cpp) target_link_libraries(my-game PRIVATE engine)
当使用例如
单独构建目标make
,您可以通过make engine # build only the engine, not the executable make my-game # build engine if necessary, then build executable
单独的测试目标也很有意义。
CMake 中的包含标志传播如下。
target_include_directories(engine INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
以上设置将一个包含目录传播到 link 针对引擎的所有目标。这很简单,但有一个缺点:您无法区分 public headers 和实现细节。作为替代方案,您可以拥有一个目录
engine/src/public/engine
,其中包含游戏将使用的所有 public headers:target_include_directories(engine INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/public) target_include_directories(engine PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/public/engine)
这样,
game
中的客户端代码使用#include "engine/math.h"
,而在engine
中,您可以直接使用#include "math.h"
。我喜欢这样的设置,因为它很容易看出什么是库的接口以及它的实现是什么。但这也有点品味问题。又自以为是了。但我认为这是一个很好的目录结构。坚持下去。