【ROS】 CMakeLists 文件详解

发布于:2025-04-03 ⋅ 阅读:(16) ⋅ 点赞:(0)

前言

在 ROS 的学习过程中,即使主要使用 Python 进行开发,仍然会频繁涉及 CMakeLists.txt 文件。因此,本文将简要介绍 CMakeLists.txt 的相关知识,并通过示例加以说明。

在深入了解 CMakeLists.txt 之前,我们首先需要理解它与 CMake、Make、GCC、G++、NVCC 之间的关系,以及 .c.cpp.o.so.a 等文件的作用。此外,还需掌握 编译、链接、构建、目标文件和可执行文件 等相关概念,以便更好地理解 CMakeLists.txt 的作用和使用方式。

有关这些概念的详细介绍,可以参考以下文章:

标准的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 COMPONENTS
  roscpp          # 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(
  FILES
  Pcm_Msg.msg    # PCM 音频数据消息
)

# 添加自定义服务文件
# 说明:指定项目中需要编译的自定义服务文件 (.srv)
# 注意:仅需添加在 srv 目录下的自定义服务文件,无需添加 ROS 自带的服务文件
add_service_files(
  FILES
  Get_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(
  DEPENDENCIES
  std_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 COMPONENTS
  roscpp
  rospy
  std_msgs
  message_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(
  FILES
  Pcm_Msg.msg
)

#添加服务文件
add_service_files(
  FILES
  Get_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
  Get_Awake_Angle_srv.srv
)

#生成消息和服务的依赖项
generate_messages(
  DEPENDENCIES
  std_msgs
)

#配置功能包
catkin_package(
  CATKIN_DEPENDS message_runtime
  LIBRARIES 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++
)

网站公告

今日签到

点亮在社区的每一天
去签到