cmake学习--add_subdirectory

张开发
2026/5/17 21:31:01 15 分钟阅读
cmake学习--add_subdirectory
add_subdirectory引入的是构建规则不是目标文件当你执行add_subdirectory时CMake 会读取子目录中的CMakeLists.txt解析其中的构建指令如add_library,add_executable记录这些目标和依赖关系到 CMake 的构建数据库中此时并没有编译任何文件也没有生成目标文件.o/.obj或可执行文件。完整流程示例# 顶层 CMakeLists.txt cmake_minimum_required(VERSION 3.10) project(Demo) add_subdirectory(lib) # ① 只是注册构建规则 add_executable(main main.cpp) target_link_libraries(main mylib) # ② 建立依赖关系下级的lib的cmakelist# lib/CMakeLists.txt add_library(mylib util.cpp) # ③ 注册库的构建规则各阶段发生的事情阶段命令实际行为配置阶段(cmake ..)add_subdirectory(lib)读取lib/CMakeLists.txt记录需要构建mylib这个库配置阶段target_link_libraries(main mylib)记录main需要链接mylib生成阶段(cmake ..)-生成 Makefile/Ninja 文件包含完整构建规则构建阶段(make)make main才真正编译util.cpp生成util.o然后链接成libmylib.a最终由main链接libmylib.a关键理解# 配置阶段只读 CMakeLists.txt不编译 $ cmake .. -- Configuring done # add_subdirectory 在这里生效 -- Generating done # 此时查看 build 目录还没有 .o 或 .a 文件 $ ls lib/ CMakeFiles/ CMakeLists.txt # 只有 CMake 的缓存文件$ make Scanning dependencies of target mylib [ 25%] Building CXX object lib/CMakeFiles/mylib.dir/util.cpp.o [ 50%] Linking CXX static library libmylib.a # ← 中间产物静态库mylib Scanning dependencies of target main [ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.o [100%] Linking CXX executable main引入的具体内容add_subdirectory引入的是CMake 目标Target的定义cmakeadd_subdirectory(lib) # 之后你可以使用子目录中定义的目标名称 target_link_libraries(main mylib) # mylib 是目标名称 target_include_directories(main PRIVATE lib) # 甚至可以使用目录路径这些目标包含源文件列表如util.cpp编译选项target_compile_options链接库依赖包含路径target_include_directories自定义命令等类比理解可以把add_subdirectory理解为不是“把做好的饭菜端过来”而是“把菜谱加入菜单”告诉厨师编译器如何做这道菜实际烹饪编译发生在make或cmake --build时与预编译库的对比# 方式1add_subdirectory有源码 add_subdirectory(lib) # 引入构建规则 # 构建时才会编译 util.cpp - libmylib.a # 方式2使用预编译库已有 libmylib.a add_library(mylib STATIC IMPORTED) # 直接引入已存在的二进制文件 set_target_properties(mylib PROPERTIES IMPORTED_LOCATION /path/to/libmylib.a) # 不需要编译直接使用总结add_subdirectory引入的是构建规则/目标定义逻辑实体目标文件.o,.a,.exe是在后续make/cmake --build构建阶段才生成的好处配置阶段快速可以根据条件决定是否引入子目录依赖关系清晰这就是为什么 CMake 分两个阶段配置生成 vs 构建—— 先用add_subdirectory组织构建逻辑再实际编译产生二进制文件。配置阶段记录需要构建libmylib.a和main构建阶段先编译util.cpp→util.o归档util.o→libmylib.a中间产物编译main.cpp→main.o链接main.o libmylib.a→main最终可执行文件

更多文章