如何组织你的项目

下面的说法可能存在一些偏见,但我认为这是一种好的组织方式。我将会讲解如何组织项目的目录结构,这是基于以往的惯例来写的,这么做对你有以下好处:

  • 可以很容易阅读以相同模式组织的项目
  • 避免可能造成冲突的组织形式
  • 避免使目录结构变得混乱和复杂

首先,如果你创建一个名为 project 的项目,它有一个名为 lib 的库,有一个名为 app 的可执行文件,那么目录结构应该如下所示:

  1. - project
  2. - .gitignore
  3. - README.md
  4. - LICENCE.md
  5. - CMakeLists.txt
  6. - cmake
  7. - FindSomeLib.cmake
  8. - something_else.cmake
  9. - include
  10. - project
  11. - lib.hpp
  12. - src
  13. - CMakeLists.txt
  14. - lib.cpp
  15. - apps
  16. - CMakeLists.txt
  17. - app.cpp
  18. - tests
  19. - CMakeLists.txt
  20. - testlib.cpp
  21. - docs
  22. - CMakeLists.txt
  23. - extern
  24. - googletest
  25. - scripts
  26. - helper.py

其中,文件的名称不是绝对的,你可能会看到关于文件夹名称为 tests 还是 test 的争论,并且应用程序所在的文件夹可能为其他的名称( 或者一个项目只有库文件 )。你也许也会看到一个名为 python 的文件夹,那里存储关于 python 绑定器的内容,或者是一个 cmake 文件夹用于存储如 Find<library>.cmake 这样的 .cmake 辅助文件。但是一些比较基础的东西都在上面包括了。

可以注意到一些很明显的问题, CMakeLists.txt 文件被分割到除了 include 目录外的所有源代码目录下。这是为了能够将 include 目录下的所有文件拷贝到 /usr/include 目录或其他类似的目录下(除了配置的头文件,这个我将会在另一章讲到),因此为了避免冲突等问题,其中不能有除了头文件外的其他文件。这也是为什么在 include 目录下有一个名为项目名的目录。顶层 CMakeLists.txt 中应使用 add_subdirectory 命令来添加一个包含 CMakeLists.txt 的子目录。

你经常会需要一个 cmake 文件夹,里面包含所有用到的辅助模块。这是你放置所有 Find*.cmake 的文件。你可以在 github.com/CLIUtils/cmake 找到一些常见的辅助模块集合。你可以通过以下语句将此目录添加到你的 CMake Path 中:

  1. set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

你的 extern 应该几乎只包含 git 子模块( submodule )。通过此方式,你可以明确地控制依赖的版本,并且可以非常轻松地升级。关于添加子模块的例子,可以参见 Testing 章节。

你应该在 .gitignore 中添加形如 /build* 的规则,这样用户就可以在源代码目录下创建 build 目录来构建项目,而不用担心将生成的目标文件添加到 .git 中。有一些软件包禁止这么做,不过这还是相比做一个真正的外部构建并且针对不同的包来使用不同的构建要好的多。

如果你想要避免构建目录在有效的( valid )源代码目录中,你可以在顶层 CMakeLists.txt 文件头部添加如下语句:

  1. ### Require out-of-source builds
  2. file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH)
  3. if(EXISTS "${LOC_PATH}")
  4. message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.")
  5. endif()

可以在这里查看 拓展代码样例