本博客转载自:【阿里云开发者社区】ROS 中 CMakeLists.txt 文件使用讲解与总结

一、CMakeLists.txt 作用

ROS 系统的功能包中要包含 CMakeLists.txt 与 package.xml 文件编译功能包的内容。

CMakeLists.txt 原本是 Cmake 编译系统的规则文件,而 Catkin 编译系统基本沿用了 CMake 的编译风格,只是针对 ROS 工程添加了一些宏定义。所以在写法上,catkin 的 CMakeLists.txt 与 CMake 的基本一致。

catkin 的 CMakeLists.txt 文件直接规定了这个 package 要依赖哪些 package,要编译生成哪些目标,如何编译等等流程。

所以 ROS 中 CMakeLists.txt 非常重要,它指定了由源码到目标文件的规则,catkin 编译系统在工作时首先会找到每个 package 下的 CMakeLists.txt ,然后按照规则来编译构建


二、CMakeLists.txt 写法

CMakeLists.txt 的基本语法都还是按照 CMake,而 Catkin 在其中加入了少量的宏。

指令/方法 作用/说明
cmake_minimum_required() CMake 的版本号
project() 项目名称
find_package() 找到编译需要的其他 CMake/Catkin package
catkin_python_setup() catkin 新加宏,打开 catkin 的 Python Module 的支持
add_message_files() catkin 新加宏,添加自定义 Message 文件
generate_message() catkin 新加宏,生成不同语言版本的 msg/srv/action 接口
add_service_files() catkin 新加宏,添加自定义 Service 文件
add_action_files() catkin 新加宏,添加自定义 Action 文件
catkin_package() catkin 新加宏,生成当前 package 的 cmake 配置,供依赖本包的其他软件包调用
catkin_add_gtest() catkin 新加宏,生成测试
add_library() 生成库
add_executable() 生成可执行二进制文件
add_dependencies() 定义目标文件依赖于其他目标文件,确保其他目标已被构建
target_link_libraries() 链接
install() 安装至本机

三、CMakeLists.txt 实例

为了详细的解释 CMakeLists.txt 的写法,以 turtlesim 小海龟这个 pacakge 为例进行讲解。

可 roscd 到 tuetlesim 包下查看,

在 turtlesim/CMakeLists.txt 的写法如下:

cmake_minimum_required(VERSION 2.8.3)  # CMake至少为2.8.3版

project(turtlesim)
# 项目 (package) 名称为 turtlesim,在后续文件中可使用变量 ${PROJECT_NAME} 来引用项目名称 turltesim

# 这两个是 通过ros 指令 创建包  中就自动生成好的


find_package(catkin    REQUIRED    COMPONENTS    
   geometry_msgs    
   message_generation    
   rosconsole    
   roscpp    
   roscpp_serialization    
   roslib    
   rostime    
   std_msgs    
   std_srvs) 
# cmake 宏,指定依赖的其他 pacakge,实际是生成了一些环境变量,如 <NAME>_FOUND,    <NAME>_INCLUDE_DIRS ,    <NAME>_LIBRARYIS 
# 此处catkin是必备依赖    其余的 geometry_msgs... 为组件


include_directories(include    ${catkin_INCLUDE_DIRS}    ${Boost_INCLUDE_DIRS}) 
# 指定C++的头文件路径


link_directories(${catkin_LIBRARY_DIRS}) 
# 指定链接库的路径


add_message_files(DIRECTORY    msg    FILES Color.msg    Pose.msg) #自定义msg文件


add_service_files(DIRECTORY    srv    FILES Kill.srv SetPen.srv Spawn.srv TeleportAbsolute.srv TeleportRelative.srv) #自定义srv文件


generate_messages(DEPENDENCIES    geometry_msgs    std_msgs    std_srvs)
# 在 add_message_files、add_service_files 宏之后必须加上这句话,用于生成 srv msg 头文件,生 成的文件位于 devel/include 中


catkin_package(CATKIN_DEPENDS    geometry_msgs    message_runtime    std_msgs    std_srvs) 
#    catkin 宏命令,用于配置 ROS 的 package 配置文件和 CMake 文件 
#    这个命令必须在 add_library() 或者 add_executable() 之前调用,该函数有 5 个可选参数: 
#    (1)    INCLUDE_DIRS          -    导出包的include路径 
#    (2)    LIBRARIES                  -    导出项目中的库 
#    (3)    CATKIN_DEPENDS    -    该项目依赖的其他catkin项目 
#    (4)    DEPENDS                   -    该项目所依赖的非catkin    CMake项目。 
#    (5)    CFG_EXTRAS             -    其他配置选


set(turtlesim_node_SRCS src/turtlesim.cpp src/turtle.cpp src/turtle_frame.cpp) 
set(turtlesim_node_HDRS include/turtlesim/turtle_frame.h ) 
# 指定 turtlesim_node_SRCS、turtlesim_node_HDRS 变量

qt5_wrap_cpp(turtlesim_node_MOCS    ${turtlesim_node_HDRS})


add_executable(turtlesim_node    ${turtlesim_node_SRCS}    ${turtlesim_node_MOCS}) #    指定可执行文件目标turtlesim_node 

target_link_libraries(turtlesim_node    Qt5::Widgets    ${catkin_LIBRARIES}    ${Boost_LIBRARIE S}) #    指定链接可执行文件

add_dependencies(turtlesim_node    turtlesim_gencpp)
add_executable(turtle_teleop_key    tutorials/teleop_turtle_key.cpp) target_link_libraries(turtle_teleop_key    ${catkin_LIBRARIES}) add_dependencies(turtle_teleop_key    turtlesim_gencpp)
add_executable(draw_square    tutorials/draw_square.cpp) target_link_libraries(draw_square    ${catkin_LIBRARIES}    ${Boost_LIBRARIES}) add_dependencies(draw_square    turtlesim_gencpp)
add_executable(mimic    tutorials/mimic.cpp) target_link_libraries(mimic    ${catkin_LIBRARIES}) add_dependencies(mimic    turtlesim_gencpp) 
#  同样指定可执行目标、链接、依赖


install(TARGETS    turtlesim_node    turtle_teleop_key    draw_square    mimic RUNTIME    DESTINATION    ${CATKIN_PACKAGE_BIN_DESTINATION}) #  安装目标文件到本地系统



install(DIRECTORY    images DESTINATION    ${CATKIN_PACKAGE_SHARE_DESTINATION} FILES_MATCHING    PATTERN    "*.png"    PATTERN    "*.svg")


四、工程实践中遇到的问题总结

在一个功能包中,将类的函数定义与声明分开文件写,用 main.cpp 调用

类的声明和定义分开文件下,按之前那么处理、分布查看

只加这个,先生成 library

在这里插入图片描述
编译成功类的声明和函数定义分开写的

在这里插入图片描述

生成了这个文件

继续加 main.cpp 的
只加这个

在这里插入图片描述

报错,很多都没定义

在这里插入图片描述

加上这个

在这里插入图片描述

这一条最后去掉了编译也成功 ,在使用自己的 msg 头文件时,必须添加 add_dependencies,否则找不到自定义的 msg 产生的头文件!

报错一样
再加

在这里插入图片描述

报错变了 没有了 ros::init() 这种未定义了,说明必须要加上面的,是最基本的

在这里插入图片描述

现在的错误就是没有找到类的定义的函数

把这个库加上

在这里插入图片描述

还是没找到,和之前报错一样

给上面那个类的定义,那个库也加上 target_link_libraries

在这里插入图片描述

编译就通过了

target_link_libraries() 这个功能可能是让其它文件可以定用这个库

  • 那么还有个问题 ,要想用其它功能包的类的函数怎么办?

官网有详细的解释
CMakeLists.txt ROS 官网

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐