CMake、Ament 与 Catkin:ROS 构建系统的前世今生
如果你开发过 ROS(机器人操作系统)程序,一定对CMakeLists.txt、package.xml以及catkin_make或colcon build这些名词不陌生。但你真的清楚CMake、Ament(ROS 2)和Catkin(ROS 1)之间的关系吗?它们有什么区别?为什么 ROS 2 要从 Catkin 迁移到 Ament?
本文将为你彻底讲清这三者的定位、联系与区别,帮助你更好地理解 ROS 的构建体系。
一、CMake:通用的构建引擎
CMake是一个跨平台的开源构建系统生成器。它本身不直接编译代码,而是根据CMakeLists.txt生成原生构建工具(如 Makefile、Ninja、Visual Studio 工程)所需的文件,再由这些工具完成实际的编译链接。
CMake 的核心能力
- 检测编译器和系统环境
- 查找依赖库、头文件(
find_package、find_library) - 定义构建目标(可执行文件、静态/动态库)
- 管理编译选项、链接选项
- 支持测试(CTest)、打包(CPack)
适用范围
任何C/C++ 项目(也支持 Fortran、CUDA 等),以及需要复杂构建配置的 Python 项目(通过pybind11等)。CMake 不包含任何机器人领域的概念。
典型用法
mkdirbuild&&cdbuild cmake..# 生成 Makefilemake# 实际编译二、Catkin:ROS 1 的元构建系统
Catkin是 ROS 1 官方采用的构建系统,它构建在 CMake 之上,为 ROS 1 包提供了额外的抽象和约定。
Catkin 解决了什么问题?
- 需要从
.msg/.srv文件自动生成代码 - 多个 ROS 包之间复杂的依赖关系
- 工作空间(workspace)环境变量自动设置(
setup.bash)
Catkin 的组成
package.xml:包的元信息(名称、版本、依赖)CMakeLists.txt:其中调用find_package(catkin REQUIRED ...)和catkin_package()- 构建工具:
catkin_make(官方简单工具)或catkin build(更强大的catkin_tools)
Catkin 典型用法
mkdir-p~/catkin_ws/srccd~/catkin_ws catkin_make# 一次性构建所有包catkin_make --only-pkg-with-deps my_pkg# 只构建某个包Catkin 的 CMakeLists.txt 片段
cmake_minimum_required(VERSION 2.8.3) project(my_ros1_pkg) find_package(catkin REQUIRED COMPONENTS roscpp std_msgs) catkin_package( INCLUDE_DIRS include LIBRARIES ${PROJECT_NAME} CATKIN_DEPENDS roscpp std_msgs ) add_executable(my_node src/my_node.cpp) target_link_libraries(my_node ${catkin_LIBRARIES})三、Ament:ROS 2 的元构建系统
Ament是 ROS 2 中取代 Catkin 的元构建系统。同样基于 CMake,但设计上更加现代化、模块化。
Ament 相比 Catkin 的改进
- 完全隔离的构建:不再有
devel空间,所有产物直接安装到install空间,避免交叉污染。 - 一等 Python 支持:提供
ament_python构建类型,原生支持纯 Python 包。 - 更清晰的依赖管理:
ament_target_dependencies自动处理 include 路径、库、编译定义。 - 更模块化:
ament_cmake由多个小组件(ament_cmake_core、ament_cmake_export_*等)组成,按需使用。 - 与 colcon 深度集成:
colcon build统一构建 C++ 和 Python 包。
Ament 典型用法
mkdir-p~/ros2_ws/srccd~/ros2_ws colcon build# 构建所有包colcon build --packages-select my_pkg# 只构建指定包Ament 的 CMakeLists.txt 片段
cmake_minimum_required(VERSION 3.8) project(my_ros2_pkg) find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) ament_target_dependencies(my_node rclcpp std_msgs) # 生成消息/服务(ROS 2 使用 rosidl) rosidl_generate_interfaces(${PROJECT_NAME} "msg/MyMsg.msg" "srv/MySrv.srv" ) ament_package()四、三者关系一图以蔽之
┌─────────────────────────────────────────────────────────┐ │ CMake │ │ (通用构建系统生成器) │ │ 提供:target, find_package, add_executable ... │ └─────────────────┬───────────────────┬───────────────────┘ │ │ ▼ ▼ ┌─────────────────────┐ ┌─────────────────────┐ │ Catkin │ │ Ament │ │ (ROS 1 元构建) │ │ (ROS 2 元构建) │ │ 扩展:catkin_package │ │ 扩展:ament_* 宏 │ │ 工具:catkin_make │ │ 工具:colcon │ └─────────────────────┘ └─────────────────────┘- CMake是“引擎”,提供底层能力。
- Catkin和Ament是“专用车身套件”,基于 CMake 封装出 ROS 领域的高级功能。
五、核心功能对比表
| 功能点 | CMake | Catkin (ROS 1) | Ament (ROS 2) |
|---|---|---|---|
| 适用领域 | 任何 C/C++ 项目 | 仅 ROS 1 包 | 仅 ROS 2 包 |
| 包清单文件 | 无(或自定义) | package.xml | package.xml |
| 查找 ROS 依赖 | 不支持 | find_package(catkin ...) | find_package(rclcpp ...) |
| 添加 ROS 依赖 | 手动target_link... | ${catkin_LIBRARIES} | ament_target_dependencies |
| 生成消息/服务代码 | 需要手写生成器 | add_message_files+generate_messages | rosidl_generate_interfaces |
| 环境脚本 | 无 | devel/setup.bash | install/setup.bash |
| 构建命令 | cmake && make | catkin_make或catkin build | colcon build |
| 构建空间隔离 | 手动控制 | devel与build混用 | build+install完全隔离 |
六、为什么 ROS 2 要从 Catkin 迁移到 Ament?
- 现代 CMake 需求:Catkin 要求 CMake 2.8.3(2009 年标准),而 Ament 要求 3.8+,可利用现代 CMake 特性(如
target粒度控制、INTERFACE传播)。 - Python 包支持:Catkin 对 Python 包的处理比较别扭(需要手动编写
setup.py),Ament 则原生支持ament_python构建类型。 - 隔离构建:Catkin 的
devel空间容易导致环境污染和难以复现的问题;Ament 强制安装到install空间,每个包独立。 - 模块化与可维护性:Ament 拆分为多个独立的 CMake 子包(如
ament_cmake_export_dependencies),更易于扩展和维护。 - 与 colcon 统一体验:无论 C++ 还是 Python 包,都用
colcon build构建,开发者体验一致。
七、常见问题速查
Q1:我能在 ROS 2 中直接用 CMake 而不通过 Ament 吗?
技术上可以,但你会失去消息生成、环境脚本自动配置、依赖传播等 ROS 2 生态的关键功能。强烈不建议这么做。
Q2:Catkin 和 Ament 的 CMakeLists.txt 可以互相转换吗?
不能直接转换,但迁移思路是:将catkin_package()改为ament_package(),将find_package(catkin REQUIRED COMPONENTS ...)拆成多个独立的find_package,并替换依赖添加方式为ament_target_dependencies。
Q3:Colcon 只能构建 Ament 包吗?
colcon是构建工具,支持多种构建器(ament_cmake、ament_python、cmake、python等)。你甚至可以用 colcon 构建非 ROS 的纯 CMake 包。
Q4:学习 ROS 构建系统,我应该重点掌握什么?
- 底层理解:CMake 的核心概念(目标、属性、查找包)。
- ROS 层面:熟悉
package.xml的写法,以及对应的构建宏(catkin_*或ament_*)。 - 构建工具:会用
catkin_make/colcon build以及常用选项(--symlink-install、--packages-select)。
八、总结
| 系统 | 本质 | 一句话总结 |
|---|---|---|
| CMake | 通用构建引擎 | 它什么都不懂,但什么都能造。 |
| Catkin | ROS 1 的 CMake 扩展 | 为 ROS 1 定制的“老爷车套件”,功勋卓著但略显陈旧。 |
| Ament | ROS 2 的 CMake 扩展 | 为 ROS 2 全新设计的“现代套件”,更干净、更灵活、更 Python 友好。 |