CMake 系列(二十):用 target_sources 避免全局变量

上一篇使用 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

对于当前的设置,我们得到如下依赖关系图:

用 Graphviz 生成的项目目标依赖关系图:automata、cpp_test 目标及其链接的各库目标

系列导航


   转载规则


《CMake 系列(二十):用 target_sources 避免全局变量》 由 吴杭沉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
CMake 系列(二十一):链接动态库并指定路径的多种方法 CMake 系列(二十一):链接动态库并指定路径的多种方法
实际开发中,需要链接的动态库往往不在系统默认的搜索路径上,这时就需要在 CMake 中显式指定库的位置。本文整理了链接动态库并指定其路径的几种常用方法,并比较各自的适用场景和优缺点。 方法 1:使用 link_directories 指定全
2022-08-02
下一篇 
CMake 系列(十九):add_subdirectory 的作用域 CMake 系列(十九):add_subdirectory 的作用域
随着项目规模的增长,把所有构建逻辑都集中在一个 CMakeLists.txt 文件里,会让项目越来越难维护。接下来几篇我们讨论构建项目的策略,并限制变量的作用范围和副作用,目的是降低代码的复杂性、简化项目的维护。本文将把一个项目分割成几个范
2022-07-19
  目录