如何构建一个C++;具有多个相互依赖的子目录的项目? 我有一个C++项目,我使用目录作为组织元素的更多方式——在PHP中使用java或目录中的包的方式。目录并不打算成为自给自足的元素,而是一种组织整个项目并防止我被资源淹没的方式。如何构造CMakeLists.txt文件来处理此问题?制作目录库似乎不适合这里,因为它们都是相互依赖的,不打算这样使用

如何构建一个C++;具有多个相互依赖的子目录的项目? 我有一个C++项目,我使用目录作为组织元素的更多方式——在PHP中使用java或目录中的包的方式。目录并不打算成为自给自足的元素,而是一种组织整个项目并防止我被资源淹没的方式。如何构造CMakeLists.txt文件来处理此问题?制作目录库似乎不适合这里,因为它们都是相互依赖的,不打算这样使用,c++,cmake,C++,Cmake,作为一个相关的问题,我在CMake中看到的关于多个子目录的大多数示例(这些示例并不多)都忽略或掩盖了设置include_目录的问题,这是我一直遇到的问题。除了梳理我的源文件以确定哪个文件依赖于哪个目录以及在哪个目录中之外,是否还可以将/src/下的所有目录设置为潜在的包含目录,并让CMake确定哪些目录实际上是依赖的 下面是一个示例结构: --src --top1 --mid1 --bot1 --src1.cpp --hdr1.h

作为一个相关的问题,我在CMake中看到的关于多个子目录的大多数示例(这些示例并不多)都忽略或掩盖了设置
include_目录的问题,这是我一直遇到的问题。除了梳理我的源文件以确定哪个文件依赖于哪个目录以及在哪个目录中之外,是否还可以将
/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

诸如此类。如何构造我的
CMakeLists.txt
文件来处理这种结构?

我不是CMake方面的专家,但由于没有其他答案,我将查看文档并尝试一下。在不同的目录中组织源文件和包含文件几乎是常规做法

看起来CMake允许您提供包含目录的列表:

比如:

include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ... )
这些文件将传递给编译器,以便它可以找到头文件,并将传递给每个源文件。因此,您的任何源文件都应该能够包含任何头文件(我认为这就是您所要求的)

与此类似,您应该能够在命令中列出所有源文件:


因此,这将是一个天真的方式,让一切建设。每个源文件都将被编译,并在所有这些目录中查找头文件,然后将目标文件链接到一起。考虑一下,如果有任何简化这一点的方法,那么你就不需要这么多的文件夹,也许只有一些普通的头文件需要被所有的源文件引用。如果事情变得更复杂,你可以将子层次结构存入库等。还考虑分离源文件和头文件(例如在SRC和包含中)。

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

cmake_minimum_required(VERSION 3.12)

project (Foo)

file (GLOB_RECURSE Foo_SOURCES CONFIGURE_DEPENDS "src/*.cpp")
file (GLOB_RECURSE Foo_HEADERS CONFIGURE_DEPENDS "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})
两个
文件(GLOB_RECURSE…
命令确定源文件和头文件的集合。
foreach
循环从所有头文件列表中计算包含目录的集合。
CONFIGURE_dependent
标志告诉CMake在构建时重新运行GLOB命令


计算源文件集的一个缺点是,当新文件添加到源代码树中时,CMake不会自动检测。然后,您必须手动重新创建构建文件。

虽然@sakra对这个问题给出了一个很好的答案,但我相信更深入地研究它更合适

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

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

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

src/
|
- main.cpp
|
_sum/
    |
    - sum.h
    |
    - sum.cpp
每个目录将有一个
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) 
下一个
CMakeLists.txt
将位于
src/
目录中:

add_subdirectory("sum")

add_executable(out main.cpp)
target_link_libraries(out sum)
add_library(sum SHARED sum.cpp)
最后一个将在
sum/
目录中:

add_subdirectory("sum")

add_executable(out main.cpp)
target_link_libraries(out sum)
add_library(sum SHARED sum.cpp)

我希望这会有所帮助。我创建了一个示例,以防您需要查看代码或需要进一步解释。

您是否一定要使用CMake?1。)您是否使用首选的生成器?2.)你真的认为CMake应该弄清楚什么依赖于什么吗?我认为应该可以定义相互独立的模块(例如mid1、mid2、top2)。3.)你是否包括#包括“hdr2.h”或类似的内容?@benoit我想没有,但这是我目前正在使用的。我宁愿不使用Automake,当我的构建没有那么复杂时,学习构建系统似乎需要付出很多努力。@Philipp 1)这不是Cmake吗?2) 我可以将目录定义为相互独立的模块。但这将突破使用组织而不是模块化目录结构的关键。在我的项目中,几乎所有的东西都是相互依赖的,模块会比我想要的大得多。3) 我将“hdr2.h”包括在内,如果您的文件夹不构成相对独立的库,那么您的组织方法仅仅是一种幻觉——复杂的依赖关系可能仍然存在。我建议将模板代码和非模板代码分开。如果可能的话,尝试在.cpp上实现模板,并实例化您需要的模板,我已经尝试过类似的方法,但包含不同的include_目录逻辑(失败得很惨)。我会给你的