首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何构建包含多个相互依赖的子目录的C++项目?

如何构建包含多个相互依赖的子目录的C++项目?
EN

Stack Overflow用户
提问于 2011-08-03 12:37:42
回答 3查看 62.6K关注 0票数 65

我有一个C++项目,其中我更多地使用目录作为组织元素--就像使用Java语言中的包或PHP语言中的目录一样。目录并不打算成为自给自足的元素,而只是一种组织整个项目的方式,让我不会被资源淹没。我如何构造我的CMakeLists.txt文件来处理这个问题?制作目录库似乎不适合这里,因为它们都是相互依赖的,并不打算以这种方式使用。

作为一个相关的问题,我在CMake中看到的大多数关于多个子目录的示例(并不是很多)都忽略或掩盖了设置include_directories的问题,这是我一直遇到的问题。没有梳理我的源文件来确定哪个文件依赖于哪个目录,有没有必要将/src/下的所有目录都设置为潜在的包含目录,并让CMake找出哪些目录实际上是依赖的?

下面是一个示例结构:

代码语言:javascript
运行
复制
--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文件来处理这种结构?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-08-03 18:47:00

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

代码语言:javascript
运行
复制
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})

两个file(GLOB_RECURSE ...命令确定源文件和头文件集。foreach循环从所有头文件的列表中计算包含目录的集合。glob标志告诉CMake在构建时重新运行CONFIGURE_DEPENDS命令。

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

票数 65
EN

Stack Overflow用户

发布于 2011-08-03 15:22:53

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

看起来像是CMake允许你给出包含目录的列表:http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories

所以就像这样:

代码语言:javascript
运行
复制
include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ... )

这些文件被传递给编译器,这样它就可以找到头文件,并将为每个源文件传递这些文件。因此,您的任何源文件都应该能够包含任何头文件(我认为这就是您所要求的)。

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

代码语言:javascript
运行
复制
add_executable(name "src/top1/mid1/bot1/src1.cpp" "src/top1/id1/bot2/src2.cpp" ...)

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

票数 3
EN

Stack Overflow用户

发布于 2021-01-01 03:03:53

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

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

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

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

代码语言:javascript
运行
复制
src/
|
- main.cpp
|
_sum/
    |
    - sum.h
    |
    - sum.cpp

我们将为每个目录提供一个CmakeLists.txt。第一个目录是项目的根目录,其中包含src/文件夹。以下是该文件内容:

代码语言:javascript
运行
复制
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/目录:

代码语言:javascript
运行
复制
add_subdirectory("sum")

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

最后一个文件将位于sum/目录中:

代码语言:javascript
运行
复制
add_library(sum SHARED sum.cpp)

我希望这能帮到你。我创建了一个github repository,以防您觉得需要查看代码或需要进一步解释。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6921695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档