上一篇使用 add_subdirectory() 把项目分割成几个范围有限的 CMakeLists.txt 文件。本文讨论另一种方法:不使用 add_subdirectory(),而是使用模块 include 来组装不同的 CMakeLists.txt 文件。这种方法的灵感来自使用 target_sources() 增强源文件处理方式的实践,它允许我们使用 target_link_libraries() 链接到当前目录之外定义的目标。
注意:本文示例在 CMake 3.5 及以上版本中有效,并已在 GNU/Linux、macOS 和 Windows 上测试过。
本文将使用与上一篇相同的源代码,唯一的更改将出现在 CMakeLists.txt 文件中,我们将在下面的部分中逐个讨论。
用 include() 组织目标
与之前的示例不同,这里我们定义了三个库。
本例中,通过使用 include() 引用 CMakeLists.txt 文件,我们在父作用域中仍然能保持所有目标可用:
include(src/CMakeLists.txt)
include(external/CMakeLists.txt)
我们可以构建一个包含树。要记住,当进入子目录(即 src/CMakeLists.txt)时,需要使用相对于父作用域的路径:
include(${CMAKE_CURRENT_LIST_DIR}/evolution/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/initial/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/io/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/parser/CMakeLists.txt)
这样,我们就可以定义文件树中任何位置的目标,并通过 include() 语句访问并链接它们。不过,我们应该选择在对维护者和代码贡献者容易看到的地方去定义这些目标。
依赖关系图可视化
我们仍然可以配合 Graphviz 图形可视化软件,用 CMake 生成这个项目的依赖关系图:
$ cd build
$ cmake --graphviz=example.dot ..
$ dot -T png example.dot -o example.png
对于当前的设置,我们得到如下依赖关系图:
