【问题标题】:c++ CMake project structure for lib and executable [closed]lib和可执行文件的c ++ CMake项目结构[关闭]
【发布时间】:2021-01-03 01:49:54
【问题描述】:

我有一个关于如何构建 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;
}

问题

  1. 如何设置 CMake,以便我既可以单独构建引擎(静态库),又可以构建依赖同一引擎的游戏(可执行文件)?
  2. 我应该如何管理引擎头文件?如何使它们可以访问游戏代码?我应该为头文件使用不同的结构吗?
  3. 此文件夹结构是否易于管理?我应该考虑不同的方法吗?

【问题讨论】:

    标签: c++ cmake build clion directory-structure


    【解决方案1】:
    1. 您声明单独的 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
      

      单独的测试目标也很有意义。

    2. CMake 中包含标志的传播方式如下。

      target_include_directories(engine
         INTERFACE
         ${CMAKE_CURRENT_SOURCE_DIR})
      

      上述设置将包含目录传播到链接到引擎的所有目标。这很简单,但有一个缺点:您无法区分公共标头和实现细节。作为替代方案,您可以拥有一个目录 engine/src/public/engine,其中包含游戏应使用的所有 public 标头:

      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"。我喜欢这样的设置,因为它很容易看出什么是库的接口以及它的实现是什么。但这在某种程度上也是一个品味问题。

    3. 再次固执己见。但我认为这是一个很好的目录结构。坚持下去。

    【讨论】:

    • 有什么理由将CMakeList.txt 文件放在src/ 目录中?
    • 应该是负责该目录的CMakeLists.txt。您将在tests 中拥有另一个,在上面的级别中拥有一个,例如engine/CMakeLists.txt。后者除了add_subdirectory 什么都不做。这种层次结构很常见,不会产生任何意外。
    • 嗯,很清楚,谢谢!当我有时间时,我会在一分钟内尝试这个设置。让我们看看我能不能让它工作。
    • engine/ 和 game/ 都应该自己调用project() 吗?在他们各自的 CMakeLists.txt 中?
    • 不,只有一个project()在最顶层的根目录。
    猜你喜欢
    • 2017-07-06
    • 2014-07-09
    • 2023-04-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多