如何构建具有多个相互依赖子目录的c++项目
How can I build a C++ project with multiple interdependent subdirectories?
我有一个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
等等。我如何构建我的CMakeLists.txt
文件来处理这种结构?
由于项目中的目录结构只是为了保持文件的组织,一种方法是让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})
两个file(GLOB_RECURSE ...
命令确定源文件和头文件的集合。foreach
循环从所有头文件列表中计算包含目录的集合。CONFIGURE_DEPENDS
标志告诉CMake在构建时重新运行glob命令。
计算源文件集的一个缺点是CMake不会自动检测新文件何时添加到源树中。你必须手动重新创建你的构建文件。
虽然@sakra对这个问题给出了一个很好的答案,但我认为更应该深入地探讨这个问题。
我们想把代码分成模块和库有很多原因。比如代码封装、可重用性、更容易调试等。这个想法也会在编译过程中传播。
换句话说,我们希望将编译过程划分为小的编译步骤,每个编译步骤属于一个模块。所以每个模块都必须有自己的编译过程。这就是我们为每个目录使用一个CMakeLists.txt
文件的原因。因此,每个目录都会有自己的编译命令,并且在项目的根目录中会有一个主CMakeLists.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)
最后一个将在sum/
目录:
add_library(sum SHARED sum.cpp)
我希望这对你有帮助。我创建了一个github存储库,以便您需要查看代码或需要进一步解释。
我不是CMake专家,但由于没有其他答案,我将看看文档并尝试一下。在不同的目录中组织源文件和包含文件是很正常的。
看起来CMake允许你给出一个包含目录的列表:http://www.cmake.org/cmake/help/cmake-2-8-docs.html命令:include_directories
比如:
include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ... )
这些被传递给编译器,以便它可以找到头文件,并将为每个源文件传递。所以你的任何源文件都应该能够包含任何头文件(我认为这是你所要求的)。
与此类似,您应该能够在add_executable命令中列出所有源文件:add_executable(name "src/top1/mid1/bot1/src1.cpp" "src/top1/id1/bot2/src2.cpp" ...)
所以这将是一个天真的方式来获得所有的构建。每个源文件将被编译,并将在所有这些目录中查找头文件,然后将目标文件链接在一起。考虑是否有任何方法可以简化这一点,这样您就不需要那么多包含文件夹,也许只有几个通用的头文件需要被所有源文件引用。如果事情变得更复杂,你可以在库中建立子层次结构等等。还要考虑分隔源文件和头文件(例如在src和include中)。
- 如何从C++中的依赖类型中获得它所依赖的类型
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 将依赖名称显式标记为类型名和模板的奇怪之处
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- C++GTKMM gui循环依赖关系
- 通过ccmake在cmake中缓存依赖选项
- 当基类是依赖类型时,这是一个缺陷吗
- 我怎样才能将所有子目录与 cmake 自动匹配
- 从不同的附加依赖项中识别等同命名的函数
- 如何在 CMake 中对目标依赖项进行分组?
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 为什么构建目录中新构建的共享库与安装目录中的副本具有不同的依赖项集?
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分专用化
- 为什么内存屏障依赖于变量?
- 处理多个子目录中的 Makefile 依赖项并输出到单独的子目录
- 在cmake中,如何以可伸缩的方式指定子目录的依赖关系
- 如何构建具有多个相互依赖子目录的c++项目