如何构建具有多个相互依赖的子目录的C++项目?

Dan*_*ham 65 c++ cmake

我有一个C++项目,我将目录用作更多的组织元素 - 可以使用Java中的包或PHP中的目录.目录不是自给自足的元素,而是组织整个项目的一种方式,使我不被源头所淹没.如何构建我的CMakeLists.txt文件来处理这个?使目录库似乎不适合这里,因为它们都是相互依赖的,并不打算以这种方式使用.

作为一个相关的问题,我在CMake中看到的多个子目录的大多数例子(并没有很多这些例子)忽略或掩盖了设置问题include_directories,这是我一直遇到的问题.除了梳理我的源文件以确定哪个文件取决于哪个文件以及在哪个目录中,还是将所有目录设置/src/为潜在的包含目录并让CMake解决哪些实际依赖?

这是一个示例结构:

--src
  --top1
    --mid1
      --bot1
        --src1.cpp
        --hdr1.h
      --bot2
        --src2.cpp
        --hdr2.h
    --mid2
      --bot3
        --src3.cpp
        --src4.cpp
        --hdr3.h
  --top2
    --mid3
      --src5.cpp
      --hdr4.h
Run Code Online (Sandbox Code Playgroud)

等等等等.如何构建我的CMakeLists.txt文件来处理这种结构?

sak*_*kra 59

由于项目中的目录结构只是用于保存文件的组织,因此一种方法是CMakeLists.txt自动查找目录中的所有源文件,src并将所有目录添加为包含头文件的包含目录.以下CMake文件可以作为起点:

cmake_minimum_required(VERSION 3.0)

project (Foo)

file(GLOB_RECURSE Foo_SOURCES "src/*.cpp")
file(GLOB_RECURSE Foo_HEADERS "src/*.h")

set (Foo_INCLUDE_DIRS "")
foreach (_headerFile ${Foo_HEADERS})
    get_filename_component(_dir ${_headerFile} PATH)
    list (APPEND Foo_INCLUDE_DIRS ${_dir})
endforeach()
list(REMOVE_DUPLICATES Foo_INCLUDE_DIRS)

add_executable (FooExe ${Foo_SOURCES})
target_include_directories(FooExe PRIVATE ${Foo_INCLUDE_DIRS})
Run Code Online (Sandbox Code Playgroud)

这两个file(GLOB_RECURSE ...命令确定源文件和头文件的集合.该foreach循环计算一组包含所有头文件的列表目录.

计算源文件集的一个缺点是CMake不会自动检测何时将新文件添加到源树.您手动必须重新创建构建文件.

  • 这次真是万分感谢!我无法理解这是如此难以找到 - 是否有人在子目录中组织他们的源文件? (17认同)
  • 这个答案非常简洁.但是,现在适当的解决方案是使用target_include_directories等. (3认同)
  • @Cygon--显然不是.:-) (2认同)
  • 我认为`target_include_directories`可以在cmake版本2.8.11+上找到. (2认同)

saj*_*our 5

虽然@sakra对这个问题给出了很好的答案,但我认为更深入地探讨它更合适。

出于多种原因,我们希望将代码分成模块和库。比如代码封装、可重用性、更容易调试等。这个想法也会在编译过程中传播。

换句话说,我们希望将编译过程分成小的编译步骤,每个步骤属于一个模块。所以每个模块都必须有自己的编译过程。这就是为什么我们CMakeLists.txt每个目录使用一个文件的原因。CMakeLists.txt因此,每个目录都有自己的编译命令,并且项目的根目录中会有一个主文件。

这是一个例子。考虑一个项目的以下结构:

src/
|
- main.cpp
|
_sum/
    |
    - sum.h
    |
    - sum.cpp
Run Code Online (Sandbox Code Playgroud)

CmakeLists.txt我们每个目录都有一个。第一个目录是项目的根目录,src/其中包含文件夹。这是该文件的内容:

cmake_minimum_required(VERSION 3.4)
project(multi_file)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-Wall")

add_subdirectory(src) 
Run Code Online (Sandbox Code Playgroud)

接下来CMakeLists.txt将位于src/目录中:

add_subdirectory("sum")

add_executable(out main.cpp)
target_link_libraries(out sum)
Run Code Online (Sandbox Code Playgroud)

最后一个将在sum/目录中:

add_library(sum SHARED sum.cpp)
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助。我创建了一个github 存储库,以防您觉得需要查看代码或需要进一步的解释。