【ROS】 CMakeLists文件详解
- 前言
- 标准的CMAKELIST.TXT文件的组成部分
- CMake 版本要求和项目名称
- 指定编译器和设置构建规则
- 查找 ROS 依赖
- 消息和服务文件
- catkin_package
- 设置头文件目录路径
- 添加可执行文件的构建规则
- 设置编译依赖关系(构建顺序)
- 设置目标文件的链接库
- 其他规则
- 示例文件
前言
在 ROS 的学习过程中,即使主要使用 Python 进行开发,仍然会频繁涉及 CMakeLists.txt
文件。因此,本文将简要介绍 CMakeLists.txt
的相关知识,并通过示例加以说明。
在深入了解 CMakeLists.txt
之前,我们首先需要理解它与 CMake、Make、GCC、G++、NVCC 之间的关系,以及 .c
、.cpp
、.o
、.so
、.a
等文件的作用。此外,还需掌握 编译、链接、构建、目标文件和可执行文件 等相关概念,以便更好地理解 CMakeLists.txt
的作用和使用方式。
有关这些概念的详细介绍,可以参考以下文章:
- 【编译、链接与构建详解】Makefile 与 CMakeLists 的作用。
标准的CMAKELIST.TXT文件的组成部分
一个标准的 ROS CMakeLists.txt
文件通常包含以下几个部分,每个部分负责不同的配置和设置:
CMake 版本要求和项目名称
- 指定 CMake 的最低版本要求
- 定义项目的名称
# 指定所需的 CMake 最低版本(>=2.8.3)
cmake_minimum_required(VERSION 2.8.3)# 定义项目名称为 'xf_mic_asr_offline'
project(xf_mic_asr_offline)
指定编译器和设置构建规则
- 指定编译器版本
- 设置构建规则
# 启用 C++11 标准支持
# 说明:指定编译器使用 C++11 标准进行代码编译
add_compile_options(-std=c++11)# 配置 C++ 编译器标志
# 说明:在现有的编译标志基础上添加 -g 选项,支持调试信息的生成
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")# 开启详细构建输出
# 说明:设置 CMake 在构建过程中显示完整的编译和链接命令
set(CMAKE_VERBOSE_MAKEFILE ON)
查找 ROS 依赖
- 使用
find_package
查找并加载 ROS 依赖包。如果缺少必要的依赖包,构建过程将报错。
# 查找并加载项目依赖的外部包
# find_package 命令格式:find_package(<包名> [REQUIRED] [[COMPONENTS] [组件1] [组件2] ...])
# 参数说明:
# - REQUIRED:表示该包是必需的,若找不到将导致编译失败
# - COMPONENTS:用于指定需要加载的具体组件find_package(catkin REQUIRED COMPONENTSroscpp # ROS 的 C++ 客户端库rospy # ROS 的 Python 客户端库std_msgs # ROS 标准消息库message_generation # ROS 消息生成工具
)
消息和服务文件
- 定义自定义的消息和服务文件的位置。(官方提供的消息和服务文件无需添加,如
std_msgs
) - 定义自定义消息和服务所依赖的 ROS 官方消息包(例如,自定义的消息文件如果依赖于
std_msgs.msg
,则需要在generate_messages
中添加std_msgs
)。
# 添加自定义消息文件
# 说明:指定项目中需要编译的自定义消息文件 (.msg)
# 注意:仅需添加在 msg 目录下的自定义消息文件,无需添加 ROS 自带的消息文件
add_message_files(FILESPcm_Msg.msg # PCM 音频数据消息
)# 添加自定义服务文件
# 说明:指定项目中需要编译的自定义服务文件 (.srv)
# 注意:仅需添加在 srv 目录下的自定义服务文件,无需添加 ROS 自带的服务文件
add_service_files(FILESGet_Offline_Result_srv.srv # 获取离线识别结果服务Set_Major_Mic_srv.srv # 设置主麦克风服务Get_Major_Mic_srv.srv # 获取主麦克风服务Start_Record_srv.srv # 开始录音服务Set_Awake_Word_srv.srv # 设置唤醒词服务Set_Led_On_srv.srv # 设置 LED 开关服务Get_Awake_Angle_srv.srv # 获取唤醒角度服务
)# 生成消息和服务的接口代码
# 说明:根据上述定义的消息和服务文件生成对应的代码实现
# 参数说明:
# DEPENDENCIES:指定消息生成时依赖的其他消息包
# std_msgs:标准消息包,提供基础数据类型的消息定义
generate_messages(DEPENDENCIESstd_msgs
)
catkin_package
catkin_package
用于配置当前 ROS 功能包的依赖关系及导出项,声明当前包所依赖的其他功能包以及需要导出的文件(如头文件、库文件等),供其他功能包使用。
# catkin_package 函数用于配置当前 ROS 功能包的依赖和导出项
# 函数格式说明:
# catkin_package(CATKIN_DEPENDS [依赖的 ROS 包...] DEPENDS [依赖的系统库...] INCLUDE_DIRS [导出的头文件路径...] LIBRARIES [导出的库文件...])# 参数说明:
# CATKIN_DEPENDS:声明对其他 ROS 包的依赖
# DEPENDS:声明对系统库或非 catkin 包的依赖
# INCLUDE_DIRS:声明本包导出的头文件路径
# LIBRARIES:声明本包导出的库文件路径catkin_package(CATKIN_DEPENDS message_runtime # 依赖 message_runtime 包用于消息运行时支持LIBRARIES libmsc.so # 导出 libmsc.so 库# INCLUDE_DIRS include # 此行被注释,不导出头文件# CATKIN_DEPENDS roscpp rospy sensor_msgs std_msgs # 此行被注释,不使用这些 ROS 包依赖# DEPENDS system_lib # 此行被注释,不使用系统库依赖
)
设置头文件目录路径
- 使用
include_directories
函数来指定编译时的头文件搜索路径。
# include_directories 用于指定编译时的头文件搜索路径
# 函数格式:include_directories([AFTER|BEFORE] [SYSTEM] <目录1> <目录2> ...)
# 参数说明:
# AFTER|BEFORE:可选参数,指定新路径在系统默认搜索路径前还是后添加
# SYSTEM:可选参数,将目录标记为系统目录,编译器会优先搜索
# 目录路径说明:
# include:项目本地头文件目录,通常指向项目的 include 目录
# ${catkin_INCLUDE_DIRS}:ROS 依赖包的头文件目录,包含所有 CATKIN_DEPENDS 声明的包include_directories(include # 本项目的本地头文件目录${catkin_INCLUDE_DIRS} # ROS 依赖包的头文件目录
)
添加可执行文件的构建规则
- 使用
add_executable
函数定义源文件和生成的可执行文件。
# add_executable 用于生成可执行文件
# 函数格式:add_executable(<可执行文件名> [源文件1 源文件2 ...])
# 本例说明:
# 将 src/hid_test_auto.cpp 编译为可执行文件 xf_asr_offline_node
# 该 cpp 文件包含 main 函数入口,是 ROS 节点的主程序文件add_executable(xf_asr_offline_node src/hid_test_auto.cpp)
设置编译依赖关系(构建顺序)
- 设置编译依赖关系有助于确保构建顺序的正确性,自动确定各个目标文件的构建顺序。
# add_dependencies 用于设置目标文件的编译依赖关系
# 函数格式:add_dependencies(<目标文件> <依赖项1> <依赖项2> ...)
# 参数说明:
# 目标文件:可以是可执行文件、动态库、静态库等
# 依赖项:指定目标文件依赖的其他目标,如其他库文件、自动生成的消息代码等add_dependencies(xf_asr_offline_node # 目标文件:语音识别节点的可执行文件${xf_mic_package_EXPORTED_TARGETS} # 依赖项:导出的目标文件xf_mic_asr_offline_gencpp # 依赖项:自动生成的 C++ 消息代码
)
设置目标文件的链接库
- 通过设置目标文件的链接库,可以指定目标文件链接的
.o
目标文件以及静态或动态库,提高代码复用性。
# target_link_libraries 用于设置目标文件的链接库
# 函数格式:target_link_libraries(<目标文件> [库1 库2 ...])
# 链接库分类:
# - ROS 依赖库:${catkin_LIBRARIES} # ROS 相关的库文件
# - 自定义动态库:
# - msc # 语音识别库 libmsc.so
# - offline_record_lib # 离线录音库 liboffline_record_lib.so
# - hid_lib # HID 设备库 libhidapi.so
# - 系统动态库:
# - rt # 实时库
# - dl # 动态链接库
# - pthread # POSIX 线程库
# - stdc++ # C++ 标准库target_link_libraries(xf_asr_offline_node ${catkin_LIBRARIES} # ROS 库msc # 语音识别库offline_record_lib # 离线录音库hid_lib # HID 设备库rt # 实时库dl # 动态链接库pthread # 线程库stdc++ # C++ 标准库
)
其他规则
在 ROS 中,诸如安装规则、版本控制、单元测试配置等其他构建规则使用较少,因此本文将不再详细讨论。
示例文件
#指定CMake最低版本要求
cmake_minimum_required(VERSION 2.8.3)
#定义项目名称
project(xf_mic_asr_offline)#设置编译选项
add_compile_options(-std=c++11) #使用C++11标准
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") #添加调试信息
set(CMAKE_VERBOSE_MAKEFILE ON) #显示详细的构建信息#查找所需的功能包
find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsmessage_generation
)#根据CPU架构选择对应的库文件目录
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64")message("-- 当前cpu架构: ${CMAKE_HOST_SYSTEM_PROCESSOR}")message("-- 使用lib/x64/库")link_directories(lib/x64)
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64")message("-- 当前cpu架构: ${CMAKE_HOST_SYSTEM_PROCESSOR}")message("-- 使用lib/arm64/库")link_directories(lib/arm64)
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch32")message("-- 当前cpu架构: ${CMAKE_HOST_SYSTEM_PROCESSOR}")message("-- 使用lib/arm32/库")link_directories(lib/arm32)
else()message("-- 当前cpu架构: ${CMAKE_HOST_SYSTEM_PROCESSOR}")message("-- 使用默认lib/x64/库,如不正确请修改xf_mic_asr_offline/CMakeLists.txt")link_directories(lib/x64)
endif()#添加消息文件
add_message_files(FILESPcm_Msg.msg
)#添加服务文件
add_service_files(FILESGet_Offline_Result_srv.srvSet_Major_Mic_srv.srvGet_Major_Mic_srv.srvStart_Record_srv.srvSet_Awake_Word_srv.srvSet_Led_On_srv.srvGet_Awake_Angle_srv.srv
)#生成消息和服务的依赖项
generate_messages(DEPENDENCIESstd_msgs
)#配置功能包
catkin_package(CATKIN_DEPENDS message_runtimeLIBRARIES libmsc.so
)#设置头文件目录
include_directories(include${catkin_INCLUDE_DIRS}
)#第一个节点的编译配置
#添加可执行文件
add_executable(xf_asr_offline_node src/hid_test_auto.cpp)
#添加依赖关系
add_dependencies(xf_asr_offline_node${xf_mic_package_EXPORTED_TARGETS}xf_mic_asr_offline_gencpp
)
#添加链接库
target_link_libraries(xf_asr_offline_node ${catkin_LIBRARIES} msc offline_record_lib hid_lib rt dl pthread stdc++
)#第二个节点的编译配置
#添加可执行文件
add_executable(client_node src/client.cpp)
#添加依赖关系
add_dependencies(client_node${xf_mic_package_EXPORTED_TARGETS}xf_mic_asr_offline_gencpp
)
#添加链接库
target_link_libraries(client_node ${catkin_LIBRARIES} offline_record_lib hid_lib rt dl pthread stdc++
)