对于简单的项目,将所有内容保存在一个目录中是可以的,但是大多数实际项目倾向于将它们的文件分割到多个目录中。通常可以找到不同的文件类型或分组在各自的目录下的独立模块,或者将属于逻辑功能组的文件放在项目目录层次结构的各自部分中。虽然目录结构可能由开发人员对项目的看法驱动,但项目的结构方式也会影响构建系统。

在任何多目录项目中,两个基本的CMake命令是add_subdirectory()和include()。

  1. 一个是目录就可,一个是具体的cmake文件

    • add_subdirectory(Charts)

    • include(Charts/CMakeLists.cmake)

  2. add_subdirectory 用于构建子项目(模块化项目,独立库)

  3. include 的主要目的是 直接引入并执行另一个 CMake 脚本(类似 #include 或 import),例如:

    • 引入自定义函数(include(my_functions.cmake))

    • 加载第三方工具的 CMake 配置(include(FindPackageHandleStandardArgs))、

    • 动态生成 CMake 代码(如 configure_file() + include())

1 add_subdirectory()

add_subdirectory()命令允许项目将另一个目录带入构建。该目录必须有自己的CMakeLists.txt文件,该文件将在add_subdirectory()被调用的地方进行处理,并在项目的构建树中为它创建一个相应的目录。

add_subdirectory(sourceDir [ binaryDir ] [ EXCLUDE_FROM_ALL ])
  • sourceDir: 不一定是源树中的子目录,尽管它通常是。可以添加任何目录,sourceDir 可以指定为绝对路径或相对路径,后者相对于当前源目录。绝对路径通常只在添加主源代码树之外的目录时才需要。

  • binaryDir: 通常,binaryDir不需要指定。省略时,CMake会在构建树中创建一个与sourceDir同名的目录。如果sourceDir包含任何路径组件,它们将被镜像到CMake创建的binaryDir中。或者,binaryDir可以显式地指定为绝对路径或相对路径,后者相对于当前二进制目录(稍后将更详细地讨论)求值。如果sourceDir是源树之外的一个路径,CMake需要指定binaryDir,因为相应的相对路径不能再被自动构造。

  • EXCLUDE_FROM_ALL: 可选的EXCLUDE_FROM_ALL关键字用于控制在添加的子目录中定义的目标在默认情况下是否应该包含在项目的ALL目标中。不幸的是,对于一些CMake版本和项目生成器,它并不总是像预期的那样工作,甚至会导致构建破裂。

2 include()

CMake提供的另一个从其他目录中获取内容的方法是include()命令,它有以下两种形式:

include(fileName [OPTIONAL] [RESULT_VARIABLE myVar] [NO_POLICY_SCOPE])
include(module [OPTIONAL] [RESULT_VARIABLE myVar] [NO_POLICY_SCOPE])

第一种形式有点类似于add_subdirectory(),但有一些重要的区别:

  • include()需要读取文件的名称,而add_subdirectory()需要一个目录,并在该目录中查找CMakeLists.txt文件。传递给include()的文件名通常扩展名为.cmake,但可以是任何名称。

  • include()没有引入新的变量范围,而add_subdirectory()引入了。 默认情况下,这两个命令都引入了一个新的策略范围,但是可以使用NO_POLICY_SCOPE选项告诉include()命令不要这样做(add_subdirectory()没有这样的选项)。

3 add_subdirectory 用途

示例代码结构:

project_root/
├── CMakeLists.txt          # 父目录的CMake文件
├── main.cpp                # 主程序
└── my_lib/                 # 子目录
    ├── CMakeLists.txt      # 子目录的CMake文件
    ├── lib_source.cpp      # 库的源文件
    └── lib_header.h        # 库的头文件

具体实现:

3.1 子目录的CMakeLists.txt (my_lib/CMakeLists.txt)

# 创建库
add_library(my_lib STATIC
    lib_source.cpp
    lib_header.h
)

# 如果需要,可以设置包含目录
target_include_directories(mathlib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

3.2 父目录的CMakeLists.txt (CMakeLists.txt)

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 添加子目录(这将执行子目录中的CMakeLists.txt)
add_subdirectory(my_lib)

# 添加可执行文件
add_executable(my_app main.cpp)

# 链接子目录中创建的库
target_link_libraries(my_app PRIVATE mathlib)

参考

参考1: CMake(六):使用子目录