当前位置: 首页 > news >正文

CMake 多目录项目构建

CMake 多目录项目构建

CMake 多目录项目构建完整笔记


一、项目目录结构

cc/
├── CMakeLists.txt        # 顶层构建文件
├── include/              # 公共头文件目录
│   ├── calc.h            # 四则运算头文件
│   └── sort.h            # 排序算法头文件
├── calc/                 # 四则运算静态库目录
│   ├── add.cpp
│   ├── sub.cpp
│   ├── mul.cpp
│   ├── div.cpp
│   └── CMakeLists.txt
├── lib/                  # 静态库输出目录(自动生成)
│   └── libcalc.a
│   └── libsort.a
├── sort/                 # 排序算法静态库目录
│   ├── insert.cpp        # 插入排序
│   ├── select.cpp        # 选择排序
│   └── CMakeLists.txt
├── test1/                # 四则运算测试程序
│   ├── calc.cpp          # 测试主文件
│   └── CMakeLists.txt
├── test2/                # 排序算法测试程序
│   ├── sort.cpp          # 测试主文件
│   └── CMakeLists.txt
├── bin/                  # 可执行文件输出目录(自动生成)
│   ├── app1              # 四则运算测试程序
│   └── app2              # 排序算法测试程序
└── build/                # 外部构建目录(推荐方式)

二、顶层 CMakeLists.txt(项目入口)

cmake_minimum_required(VERSION 3.15)
project(test)# 定义项目根目录路径
set(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR})# 定义静态库生成路径
set(LIBPATH ${PROJECT_ROOT}/lib)# 定义可执行文件的存储目录
set(EXECPATH ${PROJECT_ROOT}/bin)# 定义头文件路径
set(HEADPATH ${PROJECT_ROOT}/include)# 定义库文件的名字
set(CALCLIB calc)
set(SORTLIB sort)# 定义可执行文件的名字
set(APPNAME1 app1)
set(APPNAME2 app2)# 给当前节点添加子目录
add_subdirectory(calc)
add_subdirectory(sort)
add_subdirectory(test1)
add_subdirectory(test2)

三、子目录 CMakeLists.txt 详解

1. calc/CMakeLists.txt(四则运算静态库)

cmake_minimum_required(VERSION 3.15)
project(calc)# 搜索当前目录下所有源文件
aux_source_directory(./ SRC)# 加载公共头文件路径
include_directories(${HEADPATH})# 设置静态库生成路径
set(LIBRARY_OUTPUT_PATH ${LIBPATH})# 生成静态库 calc
add_library(${CALCLIB} STATIC ${SRC})

2. sort/CMakeLists.txt(排序算法静态库)

cmake_minimum_required(VERSION 3.15)
project(sort)# 搜索当前目录下所有源文件
aux_source_directory(./ SRC)# 加载公共头文件路径
include_directories(${HEADPATH})# 设置静态库生成路径
set(LIBRARY_OUTPUT_PATH ${LIBPATH})# 生成静态库 sort
add_library(${SORTLIB} STATIC ${SRC})

3. test1/CMakeLists.txt(四则运算测试程序)

cmake_minimum_required(VERSION 3.15)
project(test1)# 搜索当前目录下所有源文件
aux_source_directory(./ SRC)# 加载公共头文件路径
include_directories(${HEADPATH})# 链接的库路径(告诉编译器去哪找静态库)
link_directories(${LIBPATH})# 设置可执行文件输出到 bin 文件夹
set(EXECUTABLE_OUTPUT_PATH ${EXECPATH})# 生成可执行文件 app1
add_executable(${APPNAME1} ${SRC})# 现代 CMake 链接方式(推荐)
target_link_libraries(${APPNAME1} PRIVATE ${CALCLIB})

4. test2/CMakeLists.txt(排序算法测试程序)

cmake_minimum_required(VERSION 3.15)
project(test2)# 搜索当前目录下所有源文件
aux_source_directory(./ SRC)# 加载公共头文件路径
include_directories(${HEADPATH})# 链接的库路径(告诉编译器去哪找静态库)
link_directories(${LIBPATH})# 设置可执行文件输出到 bin 文件夹
set(EXECUTABLE_OUTPUT_PATH ${EXECPATH})# 生成可执行文件 app2
add_executable(${APPNAME2} ${SRC})# 现代 CMake 链接方式(推荐)
target_link_libraries(${APPNAME2} PRIVATE ${SORTLIB})

四、关键配置解析

1. 变量定义(顶层文件)

变量 作用 示例值
PROJECT_ROOT 项目根目录路径 ${CMAKE_CURRENT_SOURCE_DIR}
LIBPATH 静态库输出路径 ${PROJECT_ROOT}/lib
EXECPATH 可执行文件输出路径 ${PROJECT_ROOT}/bin
HEADPATH 公共头文件路径 ${PROJECT_ROOT}/include
CALCLIB/SORTLIB 静态库目标名 calc / sort
APPNAME1/APPNAME2 可执行文件目标名 app1 / app2

2. add_subdirectory 命令

  • 作用:添加子目录,构建子项目
  • 示例:add_subdirectory(calc) → 进入 calc/ 目录执行其 CMakeLists.txt
  • 执行顺序:按添加顺序构建,先构建库,再构建可执行文件

3. aux_source_directory 命令

  • 作用:自动扫描指定目录下的所有 .cpp 文件,存入变量
  • 示例:aux_source_directory(./ SRC) → 当前目录下所有源文件存入 SRC
  • 注意:仅扫描当前目录,不递归子目录
  • 作用:将可执行文件与静态库链接
  • 语法:target_link_libraries(目标名 PRIVATE 库名)
  • 特点:现代 CMake 推荐方式,自动处理依赖关系

五、编译与运行步骤

1. 清空并进入构建目录

cd build
rm -rf *

2. 生成构建文件

cmake ..

3. 编译项目

make

4. 运行测试程序

# 四则运算测试
./bin/app1# 排序算法测试
./bin/app2

六、常见问题与解决

1. 头文件找不到

  • 原因:未设置 include_directories(${HEADPATH})
  • 解决:确保子目录 CMakeLists.txt 中包含该命令

2. 静态库找不到

  • 原因:未设置 link_directories(${LIBPATH}) 或静态库未生成
  • 解决:
    • 检查 lib/ 目录下是否生成 libcalc.alibsort.a
    • 确保 test1/test2/ 中包含 link_directories(${LIBPATH})

3. 链接错误 undefined reference

  • 原因:未使用 target_link_libraries 链接静态库
  • 解决:确保可执行文件的 CMakeLists.txt 中包含链接命令

七、总结

  1. 项目结构规范:公共头文件统一放在 include/,库文件放在 lib/,可执行文件放在 bin/
  2. 模块化构建:使用 add_subdirectory 管理子项目,实现库与可执行文件分离
  3. 现代 CMake 实践:优先使用 target_link_libraries 链接库,避免旧版 link_libraries
  4. 路径管理:通过顶层变量统一管理路径,避免硬编码
http://www.jsqmd.com/news/878026/

相关文章:

  • 影刀RPA浏览器自动化系统:多账号环境隔离与资源调度实战
  • 如何优化百度网盘在macOS上的数据传输体验
  • DLSS Swapper完全指南:高效管理游戏DLSS版本,轻松提升画质与性能
  • 终极RPA归档提取指南:三步解决Ren‘Py游戏资源解密难题
  • OpenAI 推出的 GPT-5.5 大模型,倒逼接口芯片升级迭代@ACP#IX8024应用迭代
  • 机器学习非确定性对法律决策的挑战:从代码即法律到过程治理
  • 2026 广州二手电柜回收全攻略:最新价格表 + 隐藏价值 + 避坑指南 + Top3 本地服务商推荐 - 品牌优选官
  • 如何用Stretchly打造你的智能休息提醒系统:完整配置指南
  • PVEL-AD:重新定义光伏电池缺陷检测的AI技术范式
  • 猫抓浏览器插件:一键获取网页视频音频的终极解决方案
  • ArcaNN框架:自动化构建机器学习原子间势,高效模拟化学反应
  • 如何用79万中文医疗对话数据集构建专业的医疗AI助手:完整指南
  • 合肥GEO优化公司怎么选?避坑指南+实战榜单,新手也能精准选型! - 行业深度观察C
  • AD8232开源心电监测系统:如何用50美元构建专业级心率监测器?
  • OpenAI 推出的 GPT-5.5 大模型,倒逼接口芯片升级迭代@ACP#IX8012应用迭代
  • 全页面截图技术解析:Chrome扩展如何实现高精度网页内容捕获
  • VPKEdit:游戏开发者的终极资源管理神器,20+格式一键搞定!
  • 英雄联盟终极本地化工具:League Akari 完整使用指南
  • 信息论在机器学习中的应用:从熵、互信息到模型选择与特征工程
  • 终极解决方案:如何彻底告别腾讯游戏ACE-Guard卡顿问题
  • 曾估值2亿美元,拉勾网主动申请破产,昔日“互联网招聘鼻祖”为何黯淡收场?
  • 对比按次与按 Token Plan 消费,哪种方式在 Taotoken 上更划算
  • 如何快速掌握QrazyBox:专业二维码修复工具的完整指南
  • 5分钟终极指南:免费开源神器CompressO如何将视频文件压缩90%
  • 基于Taotoken构建企业内部知识问答系统,平衡效果与API成本
  • 隐私计算落地难?DeepSeek 4层加密链路全曝光,从训练数据到模型推理的7道防护墙
  • 在ubuntu开发机上体验taotoken分钟级接入多种大模型的过程
  • Windows和Office智能激活终极指南:3步完成KMS_VL_ALL_AIO配置
  • BilibiliDown深度评测:5大实用技巧让你轻松收藏B站优质内容
  • 从山西沁源煤矿瓦斯爆炸事故看煤矿井下无感定位技术应用的极端迫切性