cmake到ROS的catkin_make的CMakeLists.txt文件有什么区别和联系
这是一个非常核心且重要的问题,尤其对于从通用 C++ 开发转向 ROS (Robot Operating System) 开发的工程师来说。
简单来说,它们的关系是:继承与扩展。
一个用于 catkin_make
的 CMakeLists.txt
文件 本质上就是一个标准的 CMakeLists.txt 文件,但它额外使用了一套由 Catkin 提供的、为 ROS 定制的宏和变量。Catkin 并没有取代 CMake,而是基于 CMake 构建了一套工作流和规范,专门用于管理 ROS 软件包(Package)之间的复杂依赖关系。
下面我们来详细对比它们的联系和区别。
联系:共同的基础
所有在标准 CMakeLists.txt
中能用的命令,在 Catkin 的 CMakeLists.txt
中也完全适用。这包括:
- 核心逻辑:
if()
,else()
,foreach()
,list()
等控制流命令完全一样。 - 设置变量:
set(VARIABLE "value")
的用法完全一样。 - 添加目标:
add_executable(my_node src/my_node.cpp)
(创建可执行文件)add_library(my_lib src/my_lib.cpp)
(创建库)
- 链接库:
target_link_libraries(my_node my_lib)
(链接目标)
- 包含头文件:
target_include_directories(my_node PUBLIC include)
核心思想:catkin_make
只是一个封装工具,它最终还是会调用 cmake
和 make
。所以,你所知道的 CMake 知识是构建 Catkin 项目的基石。
区别:Catkin 引入的 ROS 特有扩展
Catkin 的主要目的是为了解决 ROS 的核心需求:管理大量独立开发、又相互依赖的软件包。为此,它引入了一系列特殊的命令和变量。
1. 项目声明与包信息 (catkin_package
)
这是最核心、最重要的区别。
-
标准 CMake:
project(my_awesome_project)
project()
声明了项目名称,并设置了一些项目级别的变量。 -
Catkin (ROS):
project(my_ros_package) ... # 这是 Catkin 的核心命令! catkin_package(INCLUDE_DIRS includeLIBRARIES ${PROJECT_NAME}CATKIN_DEPENDS roscpp std_msgsDEPENDS system_lib )
catkin_package()
的作用远超project()
。它向 ROS 构建系统声明:- 这是一个 Catkin 软件包。
- 它向其他软件包“导出”了什么信息。比如:
INCLUDE_DIRS
: 当其他包依赖此包时,需要包含的头文件目录。LIBRARIES
: 当其他包依赖此包时,需要链接的库。CATKIN_DEPENDS
: 依赖的其他 Catkin 软件包(如roscpp
)。DEPENDS
: 依赖的系统库(如Boost
,Eigen
)。
一句话总结:
project()
是对内的声明,而catkin_package()
是对外的接口声明,它定义了这个包如何被其他 ROS 包所使用。
2. 查找依赖 (find_package
)
-
标准 CMake:
find_package(Boost 1.65.1 REQUIRED)
直接查找系统或指定路径下的库。
-
Catkin (ROS):
find_package(catkin REQUIRED COMPONENTSroscppstd_msgssensor_msgstf )
这里
find_package
的用法被 Catkin "重载"了。- 你总是先查找
catkin
这个“元包”(meta-package)。 COMPONENTS
关键字后面列出所有你需要的其他 ROS 软件包。- Catkin 会自动帮你找到这些组件,并创建好相关的变量,如
${catkin_INCLUDE_DIRS}
和${catkin_LIBRARIES}
,供你后续使用。
- 你总是先查找
3. ROS 消息/服务/动作的自动生成
这是 ROS 独有的功能,标准 CMake 完全没有这个概念。
-
标准 CMake: N/A
-
Catkin (ROS):
# 1. 找到生成消息所需要的依赖 find_package(catkin REQUIRED COMPONENTS message_generation std_msgs)# 2. 列出你的 .msg 和 .srv 文件 add_message_files(FILES MyMessage.msg) add_service_files(FILES MyService.srv)# 3. 核心命令:调用它来生成 C++, Python 等语言的头文件和代码 generate_messages(DEPENDENCIES std_msgs)
这套流程会自动处理
.msg
文件,在构建目录中生成对应的MyMessage.h
头文件,并确保依赖它的目标在头文件生成之后才开始编译。
4. 安装 (install
)
-
标准 CMake:
install(TARGETS my_app DESTINATION bin) install(FILES my_header.h DESTINATION include)
路径是用户通过
CMAKE_INSTALL_PREFIX
自定义的。 -
Catkin (ROS):
# 使用 Catkin 提供的变量来确保安装到 ROS 标准目录结构中 install(TARGETS my_nodeRUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) install(DIRECTORY launch/DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch )
Catkin 提供了一系列
CATKIN_PACKAGE_*_DESTINATION
变量,确保你的可执行文件、库、launch 文件、配置文件等能被安装到 ROS 环境下的标准位置(如/opt/ros/noetic/lib/<package_name>
),这样rosrun
和roslaunch
才能找到它们。
示例:并排对比
假设我们要创建一个简单的可执行文件。
标准 CMakeLists.txt | Catkin (ROS) CMakeLists.txt |
---|---|
|
设置 C++ 标准
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
查找系统库 (例如 Boost)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
创建可执行文件
add_executable(my_app src/main.cpp)
链接库
target_link_libraries(my_app
PRIVATE
${Boost_LIBRARIES}
)
安装
install(TARGETS my_app
DESTINATION bin)
cmake_minimum_required(VERSION 3.0.2)
project(my_ros_package)
查找 Catkin 依赖 (roscpp, std_msgs)
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)
Catkin 核心:声明包的导出信息
catkin_package(
INCLUDE_DIRS
LIBRARIES
CATKIN_DEPENDS roscpp std_msgs
DEPENDS
)
包含 Catkin 找到的头文件路径
include_directories(
${catkin_INCLUDE_DIRS}
)
创建 ROS 节点 (可执行文件)
add_executable(my_node src/my_node.cpp)
链接 Catkin 找到的库
target_link_libraries(my_node
${catkin_LIBRARIES}
)
安装规则 (通常在 ROS 中是可选的)
install(…)
总结
特性 | 标准 CMake | Catkin (ROS) CMake |
---|---|---|
基础语法 | 是基础 | 完全继承和使用 |
项目声明 | project(name) | project(name) + catkin_package() (核心) |
查找依赖 | find_package(Lib) | find_package(catkin COMPONENTS ...) |
代码生成 | 不处理特定领域文件 | generate_messages() 等用于 .msg/.srv/.action |
构建工具 | cmake & make | catkin_make (封装了 cmake & make ) |
目标 | 构建通用的软件 | 构建能在 ROS 生态中互相发现和通信的软件包 |
把 Catkin 看作是 CMake 的一个**“行业特定框架”**,就像 Ruby on Rails 是 Ruby 的 Web 开发框架一样。你仍然在写 CMake 代码,但你需要遵循 Catkin 的规则并使用它提供的工具,才能让你的软件包无缝地融入整个 ROS 系统。