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

Cmake的详细历史,原理,以及常见用法,帮我详细讲解-03 - jack

CMake 是 C++ 开发领域事实上的标准构建工具,也是 ROS 开发的核心基石。它的全称是 Cross Platform Make

不同于直接调用编译器(gcc/clang)或编写特定平台的 Makefile,CMake 的核心理念是:“编写一次构建规则,在任何平台上生成原生的构建文件”

以下是关于 CMake 的详细历史、底层原理以及现代用法的深度解析。


一、 CMake 的历史 (History)

1. 起源:为了解决跨平台痛点 (1999-2000)

CMake 诞生于 Kitware 公司。当时,美国国家医学图书馆 (NLM) 资助了一个庞大的开源项目——ITK (Insight Segmentation and Registration Toolkit),用于医学图像处理。

  • 挑战:ITK 的开发者主要使用 C++,但他们的开发环境五花八门:

  • 有人用 Windows (Visual Studio)。

  • 有人用 Unix/Linux (GCC + Make)。

  • 有人用 macOS (Xcode 后来才加入,早期是其他的)。

  • 痛点:在没有 CMake 之前,维护者必须为 Windows 写 .sln 工程文件,为 Linux 写 Makefile。每当添加一个新文件,就要修改所有平台的配置文件,极其痛苦且容易出错。

  • 诞生:Bill Hoffman 受到了 autotools 的启发,但希望能更简单且支持 Windows,于是开发了 CMake。

2. 发展与统治

  • CMake 2.x: 功能逐渐完善,支持了 KDE(Linux 著名桌面环境)项目,这极大地推动了 CMake 的普及。但那时的语法比较混乱,变量作用域全是全局的(类似 C 语言的宏)。
  • CMake 3.x (Modern CMake): 引入了 “Target-based” (基于目标) 的理念。这是 CMake 的分水岭。它让构建配置变得像面向对象编程一样模块化。ROS 2 全面拥抱了 Modern CMake。

二、 CMake 的核心原理 (Principles)

CMake 不是编译器,它也不直接构建软件。它是一个 “构建系统的生成器” (Build System Generator)

1. 工作流程三部曲

  1. 配置阶段 (Configure):
  • 读取 CMakeLists.txt
  • 检查系统环境(编译器在哪里?依赖库在哪里?)。
  • 建立内部的依赖图谱。
  1. 生成阶段 (Generate):
  • 根据用户的选择(Generator),输出特定平台的构建文件。
  • 在 Linux 上生成 Makefile
  • 在 Windows 上生成 Project.sln.vcxproj
  • 在 Mac 上生成 Project.xcodeproj
  • 或者生成 build.ninja (Ninja 是一个超快的构建工具)。
  1. 构建阶段 (Build):
  • 调用原生的构建工具(make, msbuild, ninja)来实际调用编译器生成二进制文件。

2. Out-of-Source Build (外部构建)

这是 CMake 强烈推荐的哲学。

  • In-Source: 编译产生的 .o, .exe 文件和 .cpp 源码混在一起。清理时极难清理干净。
  • Out-of-Source: 创建一个独立的 build 目录。所有的中间产物都在这里。如果想重新编译,只需 rm -rf build,源码目录永远保持干净。

三、 常见用法与语法 (Common Usage)

我们分为 “传统用法”“现代用法 (Modern CMake)”强烈建议学习现代用法。

1. 基础骨架 (CMakeLists.txt)

每个 CMake 项目的根目录必须有一个 CMakeLists.txt

# 1. 指定 CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)# 2. 定义项目名称和语言
project(MyRobotProject LANGUAGES CXX)# 3. 指定 C++ 标准 (例如 C++14)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

2. 生成可执行文件

# 这里的 "my_node" 是一个 Target(目标)
add_executable(my_node src/main.cpp src/helper.cpp)

3. 处理头文件 (Include Directories)

  • 旧方式 (不推荐): include_directories(include)。这是一个全局设置,会污染所有目标。
  • 新方式 (Target-based):
# 只有 my_node 需要在这个目录下找头文件
target_include_directories(my_node PRIVATE include)

假设你要使用 OpenCV 库。

# 1. 查找库 (在系统中搜索)
# 如果找到,CMake 会创建一些变量或目标 (如 OpenCV::OpenCV)
find_package(OpenCV REQUIRED)# 2. 链接库
# 将 OpenCV 链接到 my_node
target_link_libraries(my_nodePRIVATE${OpenCV_LIBS} # 或者写 OpenCV::OpenCV
)

5. 关键字 PRIVATE, PUBLIC, INTERFACE 的区别

target_link_librariestarget_include_directories 中,这三个关键字至关重要(这是 Modern CMake 的精髓):

  • PRIVATE: “我自己用”。

  • 例子:A 链接了 B。如果不希望依赖 A 的人也自动链接 B,就用 PRIVATE。

  • INTERFACE: “我不收,但我给别人用”。

  • 例子:这是一个纯头文件库(Header-only),没有编译产物,但需要传递头文件路径给使用者。

  • PUBLIC: “我自己用,也给别人用”。

  • 例子:A 在其头文件中包含了 B 的头文件。任何用 A 的人必然需要 B


四、 实际操作示例

假设你的目录结构如下:

project/
├── CMakeLists.txt
├── include/
│   └── robot.h
└── src/├── main.cpp└── robot.cpp

CMakeLists.txt 的最佳实践写法:

cmake_minimum_required(VERSION 3.10)
project(RobotApp)# 创建一个库目标 (Library Target)
add_library(robot_lib src/robot.cpp)# 为库指定头文件路径
# PUBLIC 意味着:编译 robot_lib 需要这个目录,链接 robot_lib 的人也需要这个目录
target_include_directories(robot_lib PUBLIC include)# 创建可执行文件目标 (Executable Target)
add_executable(main_app src/main.cpp)# 链接库
# main_app 只需要链接 robot_lib,不需要知道头文件在哪里
# 因为 robot_lib 已经通过 PUBLIC 传递了头文件路径
target_link_libraries(main_app PRIVATE robot_lib)

五、 总结:CMake 在 ROS 中的地位

  • ROS 1 (Catkin):

  • Catkin 本质上是一堆 CMake 宏 (Macros)

  • 它封装了 find_package(catkin ...)

  • ROS 1 时代很多教程还在使用“旧式 CMake”(即大量使用全局变量 ${catkin_LIBRARIES}),这在当时是为了方便,但在大型项目中容易导致依赖混乱。

  • ROS 2 (Ament/Colcon):

  • ROS 2 强制推行 Modern CMake

  • 你需要显式地使用 ament_target_dependencies(它是 target_link_libraries 的封装)。

  • 理解 PRIVATE/PUBLIC 对于 ROS 2 开发至关重要。

下一步建议:
既然你已经了解了 ROS 1 的步骤和 CMake 的原理,是否需要我为你详细对比一下 ROS 1 CMakeLists.txt 和 标准 Modern CMake 的区别,以便你未来平滑迁移到 ROS 2?

http://www.jsqmd.com/news/114149/

相关文章:

  • 【解密Open-AutoGLM隐私引擎】:90%开发者忽略的4个安全盲区及应对策略
  • Open-AutoGLM隐私技术落地难题,如何用1套框架解决合规与效率双重挑战?
  • Linly-Talker在心理健康科普中的温和表达实践
  • 信息安全和网络空间安全专业怎么选?想学黑客技术应该选哪个专业?学长告诉你!
  • Open-AutoGLM落地难题全破解:企业级应用中的9大挑战与应对策略
  • Linly-Talker与Stable Diffusion结合的可能性探索
  • 解决机器人“完美难题”:智能拣选与码放技术
  • 还在为大模型落地难发愁?:Open-AutoGLM在智能客服中的4步实施法
  • 传送带异物检测玻璃碴子检测数据集VOC+YOLO格式156张1类别
  • 信息安全、网络安全、网络空间安全有什么区别?
  • JavaSE——键盘录入
  • 成都恒利泰国产替代LFCN-320+
  • 写给未来的自己:一名测试开发工程师的十年之约
  • (独家披露)Open-AutoGLM与大模型协同创新路径图(仅限内部交流版)
  • 2025年广东半导体产业园选址公司权威推荐榜单:新材料产业园选址/预制菜产业园选址/人工智能产业园选址咨询机构精选 - 品牌推荐官
  • 数字人语义理解边界:Linly-Talker模糊查询处理
  • 2025年抗菌家居膜品牌排名与选择指南,装饰性好的家居膜推荐 - mypinpai
  • 如何在不牺牲性能的前提下实现Open-AutoGLM级数据保护?:一线专家实战经验分享
  • 如何利用Open-AutoGLM最新迭代快速构建企业级AI系统?99%的人都忽略了这2个关键接口
  • 2025年海口知名的消防排烟防火阀公司排行榜,卡式风机盘管/吊顶式空调机组/直膨式空调机组/消防排烟防火阀设计找哪家 - 品牌推荐师
  • 中小企业福音:Linly-Talker降低数字人应用门槛
  • Open-AutoGLM实战进阶:掌握3种高阶集成模式,抢占AI自动化先机
  • (Open-AutoGLM全球部署黄金标准)首次披露跨国AI项目的适配框架
  • 2025年口碑好的拉伸试验机品牌推荐,专业材料测试设备企业全解析 - myqiye
  • Open-AutoGLM到底多强大?:实测数据揭示其对GDP潜在贡献率
  • 【Open-AutoGLM调参实战指南】:掌握模型动态优化的5大核心技巧
  • 2025海外游学机构TOP5权威推荐:达美游学,甄选优质行学伙伴助力青少年国际视野腾飞 - 工业推荐榜
  • Linly-Talker能否实现语音打断与即时响应?
  • 如何利用缓存机制加快Linly-Talker重复内容生成?
  • Linly-Talker镜像发布:一键生成高拟真数字人讲解视频