当前位置: 首页 > news >正文

catkin工程和CMakelist.txt的基本使用

catkin工程和CMakelist.txt的基本使用

  • 1.catkin工程和CMakelist.txt的基本使用
    • 1. 顶部基本信息
    • 2. 编译选项 / C++ 标准
    • 3. 依赖查找(catkin 包)
    • 4. 第三方库查找(非 catkin)
    • 5. 导出包信息(catkin_package)
    • 6. 头文件与依赖头路径
    • 7. 生成可执行文件(节点)
    • 8. 链接依赖库
    • 9. 安装规则(让 `catkin_make install` 生效)
  • 2. 使用方的CMakelist.txt和package.xml
      • 问题1:find_package是在哪个路径找到mavros_controller包的?
      • 问题2:为什么添加库使用include_directories( ${catkin_INCLUDE_DIRS},而不需要再写 ../mavros_controller/include路径?
      • 问题3:target_link_libraries中的mavros_controller 可以省略
      • 问题4:省略target_link_libraries中的mavros_controller,但是编译报错找不到mavros_controller.h
  • 3. ROS(catkin):最小 CMakeLists.txt

参考: cmakeList语法详解

1.catkin工程和CMakelist.txt的基本使用

基本文件结构

mavros_controller
├─ CMakeLists.txt
├─ package.xml
├─ include
│  └─ mavros_controller.h
└─ src└─ mavros_controller.cpp

package.xml

<?xml version="1.0"?>
<package format="2"><name>mavros_controller</name><version>0.1.0</version><description>MAVROS controller node that manages OFFBOARD mode, arming, and position setpoints, decoupled from planning.</description><maintainer email="maintainer@example.com">maintainer</maintainer><license>BSD</license><buildtool_depend>catkin</buildtool_depend><build_depend>roscpp</build_depend><build_depend>mavros_msgs</build_depend><build_depend>geometry_msgs</build_depend><build_depend>tf</build_depend><exec_depend>roscpp</exec_depend><exec_depend>mavros_msgs</exec_depend><exec_depend>geometry_msgs</exec_depend><exec_depend>tf</exec_depend><export/>
</package>

CMakelist.txt

cmake_minimum_required(VERSION 3.0.2)   # CMake 最低版本要求
project(mavros_controller)              # 定义工程名,变量 PROJECT_NAME = mavros_controlleradd_compile_options(-std=c++11)         # 设置编译选项,使用 C++11# 查找依赖的 catkin 包
find_package(catkin REQUIRED COMPONENTSroscppmavros_msgsgeometry_msgstf
)find_package(Eigen3 REQUIRED)           # 查找第三方库 Eigen3# 导出给其他包使用的信息(头文件目录、依赖、库)
catkin_package(CATKIN_DEPENDS roscpp mavros_msgs geometry_msgs tfINCLUDE_DIRS includeLIBRARIES mavros_controller
)# 生成库(libmavros_controller.so),供其他包或本包节点链接
add_library(${PROJECT_NAME}src/mavros_controller.cpp
)# 设置头文件搜索路径
include_directories(include${catkin_INCLUDE_DIRS}${EIGEN3_INCLUDE_DIRS}
)# 生成可执行文件(节点)
add_executable(mavros_controller_nodesrc/mavros_controller.cpp
)# 链接库(目前只链接 ROS 依赖)
target_link_libraries(mavros_controller_node${catkin_LIBRARIES}
)# 安装节点可执行文件到 ROS 的 bin 路径
install(TARGETS mavros_controller_nodeRUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)# 安装头文件目录,供其他包 include
install(DIRECTORY include/DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
)

package.xml每个包的“元数据文件”,它的作用相当于一个“身份证 + 依赖清单”。

文件作用典型内容
CMakeLists.txt定义如何编译(技术层面)add_libraryadd_executabletarget_link_librariesinstall
package.xml描述包信息与依赖(元数据层面)包名、版本、维护者、license、依赖 <depend>

语法说明:

1. 顶部基本信息

cmake_minimum_required(VERSION 3.0.2)
project(mavros_controller)
  • cmake_minimum_required:要求 CMake 的最低版本(这里 3.0.2,和 ROS Kinetic/ Melodic/Noetic 常用版本兼容)。
  • project(<name>):定义工程名,同时创建同名变量 PROJECT_NAME 可在后面复用。

2. 编译选项 / C++ 标准

add_compile_options(-std=c++11)
  • 为所有目标添加编译器选项,这里设为 C++11。

  • 现代写法(等价且更清晰):

    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    

3. 依赖查找(catkin 包)

find_package(catkin REQUIRED COMPONENTSroscppmavros_msgsgeometry_msgstf
)
  • 在 ROS/catkin 环境中查找你依赖的ROS 包(编译/链接时用到的消息、库、头文件等)。
  • REQUIRED 表示缺少就报错终止。
  • 这些组件会提供 catkin_INCLUDE_DIRScatkin_LIBRARIES 等变量。

4. 第三方库查找(非 catkin)

find_package(Eigen3 REQUIRED)
  • 查找系统里的 Eigen3(通常是头文件库),成功后会提供 EIGEN3_INCLUDE_DIRS(或 Eigen3::Eigen 目标)。

5. 导出包信息(catkin_package)

catkin_package(CATKIN_DEPENDS roscpp mavros_msgs geometry_msgs tfINCLUDE_DIRS include
)
  • 告诉 catkin:这个包对外暴露什么即想让其他包用到你的头文件 / 库

  • 如果只写一个节点自己用,不打算给别的包复用, catkin_package 可以删掉,不影响你自己的节点编译运行。因为自己在本包内部用不到。

  • CATKIN_DEPENDS:你的包(编译/运行)依赖了哪些其他 catkin 包(会体现在对方包的编译环境里)。

  • INCLUDE_DIRS include:导出本包的头文件目录(下文 install(DIRECTORY include/ ...) 对应安装),使其他包 #include 你的头文件时能找到。

  • 比如你的包提供了 MavrosController.h,希望别的包能:

    #include <mavros_controller/MavrosController.h>
    

    这时候就必须保留 catkin_package(INCLUDE_DIRS include ...),否则安装后下游包找不到头文件路径。

  • 想让其他包不仅能 include,还能链接到你的库

需要在 catkin_package(...) 里加 LIBRARIES mavros_controller,并且在 CMake 里 add_library(mavros_controller ...)

#include头文件只是告诉编译器“这个类有这些方法”,最后还要把 `.cpp里的实现编译出来,然后 链接进可执行文件


6. 头文件与依赖头路径

include_directories(include${catkin_INCLUDE_DIRS}${EIGEN3_INCLUDE_DIRS}
)
  • 为后续目标添加头文件搜索路径:
    • include:你包里的公共头(例如 include/mavros_controller/MavrosController.h)。
    • ${catkin_INCLUDE_DIRS}:上面 find_package(catkin ...) 得到的依赖头路径。
    • ${EIGEN3_INCLUDE_DIRS}:Eigen3 的头路径。

7. 生成可执行文件(节点)

add_executable(mavros_controller_nodesrc/mavros_controller.cpp
)
  • src/mavros_controller.cpp 源文件编译一个可执行文件 mavros_controller_node
  • 典型 ROS 节点会在此 .cpp 中包含 main()

8. 链接依赖库

target_link_libraries(mavros_controller_node${catkin_LIBRARIES}
)
  • 把 ROS 依赖库(roscpp、tf、mavros_msgs 等)链接到你的可执行文件上(mavros_controller_node)。

  • 当你在代码里 #include <ros/ros.h> 并使用 ros::initros::spin 等函数时,这些函数的实现实际上在 roscpp 库 里。

    也可以单独拆开看里面到底有哪些库,然后按需删减。

    target_link_libraries(mavros_controller_node${roscpp_LIBRARIES}${tf_LIBRARIES}
    )
    

    但这没必要,因为 ${catkin_LIBRARIES} 已经帮你统一管理了。


9. 安装规则(让 catkin_make install 生效)

install(TARGETS mavros_controller_nodeRUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)install(DIRECTORY include/DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
)
  • 安装二进制可执行文件到 ${CATKIN_PACKAGE_BIN_DESTINATION}(通常是 devel/.private/<pkg>/install/ 对应路径)。
  • 安装头文件目录到 ${CATKIN_PACKAGE_INCLUDE_DESTINATION},这与 catkin_package(INCLUDE_DIRS include) 一起,使其它包在安装空间也能通过 find_package 找到你的头文件。
  • 如果不写 install(...),在 devel/ 里开发调试:用 catkin_make / catkin build 编译后,二进制会放在 devel/lib/<package_name>/,头文件还在源码目录 include/不写 install() 不影响本地开发和运行
  • 如果不写 install(...),在 install/ 里开发调试:别人用 find_package(catkin REQUIRED COMPONENTS mavros_controller) 时,找不到你的头文件/二进制,就没法复用。自己 source install/setup.bash 后也没法直接运行节点,因为 install/ 下压根没有导出二进制。

2. 使用方的CMakelist.txt和package.xml

现在有其他包想调用mavros_controller包中的方法,使用方包的CMakelist.txt

cmake_minimum_required(VERSION 3.0.2)
project(consumer_pkg)set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)find_package(catkin REQUIRED COMPONENTSroscppgeometry_msgsmavros_msgstfmavros_controller    # 关键:找到并引入你导出的库与头文件
)catkin_package()include_directories(${catkin_INCLUDE_DIRS}  # 包含到 mavros_controller 的 include/
)add_executable(consumer_node src/consumer_node.cpp)
target_link_libraries(consumer_node${catkin_LIBRARIES}     # roscpp/tf 等mavros_controller       # 关键:链接你的库
)# 可选:保证依赖顺序(通常问题不大,这里给出标准写法)
add_dependencies(consumer_node ${catkin_EXPORTED_TARGETS})

使用方包的 package.xml

<package format="2"><name>consumer_pkg</name><version>0.0.1</version><description>Links to mavros_controller library</description><maintainer email="you@example.com">You</maintainer><license>BSD</license><!-- 如果只使用头文件,那么不需要下面这行 --><depend>mavros_controller</depend><depend>roscpp</depend><depend>geometry_msgs</depend><depend>mavros_msgs</depend><depend>tf</depend>
</package>

问题1:find_package是在哪个路径找到mavros_controller包的?

  1. catkin 是怎么“找到包”的?

当你写:

find_package(catkin REQUIRED COMPONENTS mavros_controller)

CMake 会去找 mavros_controller 这个 ROS 包,方式是:

  • ROS_PACKAGE_PATH 中查找 package.xml / manifest.xml 文件;

2. 常见查找路径

devel space(开发空间)

如果你在同一个工作空间里编译了 mavros_controller
catkin 会在 devel/share/mavros_controller/cmake/ 下生成:

mavros_controllerConfig.cmake
mavros_controllerConfig-version.cmake

这两个文件就是 find_package 用的“入口”。

所以只要你 source devel/setup.bash,CMake 就能通过环境变量找到这些路径。


install space(安装空间)

如果你执行了:

catkin_make install

会在 install/share/mavros_controller/cmake/ 下生成同样的 Config.cmake

发布成 deb 包(比如 sudo apt install ros-noetic-mavros-controller)后,也是这个逻辑。

  • CMake 会查 $CMAKE_PREFIX_PATH(被 setup.bash 设置了),里面包含 devel/install/
  • 然后拼接路径 share/mavros_controller/cmake/mavros_controllerConfig.cmake

问题2:为什么添加库使用include_directories( ${catkin_INCLUDE_DIRS},而不需要再写 …/mavros_controller/include路径?

因为你用了:

find_package(catkin REQUIRED COMPONENTS mavros_controller)
include_directories(${catkin_INCLUDE_DIRS})
  1. 当你 find_package(... mavros_controller) 的时候,CMake 会读取 mavros_controller 包在 devel/share/mavros_controller/cmake/ 下生成的 Config.cmake 文件。

  2. 这个文件里包含了 catkin_package() 导出的信息,比如:

    set(mavros_controller_INCLUDE_DIRS /home/user/ws/devel/include)
    

    或者 install 空间里的 /home/user/ws/install/include

  3. ${catkin_INCLUDE_DIRS} 会自动拼接所有依赖包的 INCLUDE_DIRS,所以你得到的路径已经包含了 mavros_controller/include

这样,你在源代码里只需要:

#include <mavros_controller/MavrosController.h>

编译时就能找到。

总结:catkin 已经通过 catkin_package(INCLUDE_DIRS include) 导出了,${catkin_INCLUDE_DIRS} 自动包含

问题3:target_link_libraries中的mavros_controller 可以省略

3.1 什么时候可以不写 mavros_controller

在使用方包里,若你这样写了:

find_package(catkin REQUIRED COMPONENTSroscpp geometry_msgs mavros_msgs tfmavros_controller        # 引入这个依赖
)add_executable(consumer_node src/consumer_node.cpp)target_link_libraries(consumer_node${catkin_LIBRARIES}      # 只写这一行
)

提供方包已正确导出:

catkin_package(INCLUDE_DIRS includeLIBRARIES mavros_controllerCATKIN_DEPENDS roscpp geometry_msgs mavros_msgs tf
)

那么 ${catkin_LIBRARIES}自动包含 mavros_controller 的库,显式再写一次 mavros_controller 并不必要。

3.2 什么时候必须显式写 mavros_controller

  • 提供方包没有catkin_package(LIBRARIES ...) 里导出库;
  • 没有mavros_controller 放进 find_package(catkin REQUIRED COMPONENTS ...)
  • 不链接 ${catkin_LIBRARIES}(只链接个别库);
  • 你的库名和导出目标名不一致或导出有误(安装/导出没配好);
  • 你不走库,而是想把 .cpp 独立编进可执行(这时根本不需要链接库,但也失去复用意义)。

推荐

最稳妥写法是只链接:

target_link_libraries(consumer_node ${catkin_LIBRARIES})

并确保提供方正确导出库catkin_package(LIBRARIES ...) + add_library(...) + install(TARGETS ...))。
若你不确定导出是否规范,加上显式库名也没坏处:

target_link_libraries(consumer_node ${catkin_LIBRARIES} mavros_controller)

问题4:省略target_link_libraries中的mavros_controller,但是编译报错找不到mavros_controller.h

报错的根因:
在consumer_pkg里已经写了 find_package(... mavros_controller)include_directories(${catkin_INCLUDE_DIRS}),但是包的使用方 consumer_pkg/package.xml 没有声明对 mavros_controller 的 <build_depend>或者mavros_controller 包的声明在search_manager包后面,因此会先编 search_manager,导致当时还拿不到 mavros_controller 的导出头文件路径,从而找不到头文件。
解决方法:
将mavros_controller包的依赖编译提前

  <build_depend>mavros_controller</build_depend><build_export_depend>mavros_controller</build_export_depend><exec_depend>mavros_controller</exec_depend>

3. ROS(catkin):最小 CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)  # 指定所需的最低 CMake 版本(catkin 常见为 3.0.2)
project(my_pkg)                        # 定义工程名(同时影响生成目标的默认前缀等)find_package(catkin REQUIRED COMPONENTS # 查找 catkin 以及需要的 catkin 组件roscpp                                # 这里仅依赖 roscpp;有需要可继续添加如 std_msgs、sensor_msgs 等
)catkin_package()                        # 声明本包为 catkin 包;可在括号内声明导出头文件/库/依赖等,此处最简include_directories(                    # 为后续目标添加头文件搜索路径${catkin_INCLUDE_DIRS}                # 使用 catkin 导出的头文件路径
)add_executable(my_node                  # 定义可执行目标 my_nodesrc/my_node.cpp                       # 源文件列表(可添加多个 .cpp)
)target_link_libraries(my_node           # 为目标 my_node 链接库${catkin_LIBRARIES}                   # 链接 catkin 导出的库(包含 roscpp 等)
)install(TARGETS my_node                 # 安装目标,方便打包/部署与运行环境查找RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}  # 安装到 devel/install 的 bin 目录
)
  • 这是最基本的 catkin 节奏:找到 catkin 和需要的组件、声明包、包含头文件、添加节点、链接 catkin_LIBRARIES、可选安装。

文章转载自:

http://xTc89E08.qbmjf.cn
http://cEdAXdg1.qbmjf.cn
http://cXxFGGlK.qbmjf.cn
http://cMtRCwBT.qbmjf.cn
http://v7E1HzLW.qbmjf.cn
http://7nNJr3Op.qbmjf.cn
http://U3gCpk1n.qbmjf.cn
http://tgmz7c11.qbmjf.cn
http://kTGHrzLX.qbmjf.cn
http://LrvLY2S2.qbmjf.cn
http://sXI3eL14.qbmjf.cn
http://5tc03cCs.qbmjf.cn
http://ewmrWjR9.qbmjf.cn
http://2EVWuObQ.qbmjf.cn
http://7d2g3E1V.qbmjf.cn
http://okKck5yQ.qbmjf.cn
http://cbLWCBlx.qbmjf.cn
http://ivmfo5zC.qbmjf.cn
http://i9jJrfDn.qbmjf.cn
http://r6X6YZWh.qbmjf.cn
http://VesO0ftC.qbmjf.cn
http://kQzuhrCJ.qbmjf.cn
http://P9QfyxFM.qbmjf.cn
http://Gi0jOWsn.qbmjf.cn
http://LkCp8gTw.qbmjf.cn
http://KJbQwNq3.qbmjf.cn
http://IGNSCMaj.qbmjf.cn
http://TBnyu6U8.qbmjf.cn
http://YgDXY8h7.qbmjf.cn
http://eP5KoZQL.qbmjf.cn
http://www.dtcms.com/a/387181.html

相关文章:

  • 使用 MyCat 实现 MySQL 主从读写分离
  • Visual Studio 函数头显示引用个数
  • 【毕业设计选题】大数据技术专业毕业设计选题指南指南:python(2026 届)
  • 组播实验指导
  • Easylogger与RTT结合使用 Easylogger在FreeRTOS下实现异步输出
  • 【openFeign详细介绍】
  • 抖音私信评论互动消息通知监听自动获取,通过qq机器人转发到qq来通知
  • 19.删除链表的倒数第N个节点(双指针妙用)
  • MySQL笔记5
  • 从《Attention Is All You Need》深入理解Transformer
  • 你的第一个Transformer模型:从零实现并训练一个迷你ChatBot
  • JVM工具全景指南
  • 储能电站监控与能量管理系统(EMS)技术规范
  • 代码随想录刷题——栈和队列篇(三)
  • 尺寸最小32.768KHZ有源晶振SIT1572
  • Python文件写入安全指南:处理不存在文件的完整解决方案
  • 网络层认识——IP协议
  • 软考中级习题与解答——第七章_数据库系统(1)
  • 立创·庐山派K230CanMV开发板的进阶学习——特征检测
  • 使用 Nano-banana 的 API 方式
  • 【原理】为什么React框架的传统递归无法被“中断”从而选用链式fiber结构?
  • Redis网络模型分析:从单线程到多线程的网络架构演进
  • 刷题日记0916
  • 5.PFC闭环控制仿真
  • 三层网络结构接入、汇聚、核心交换层,应该怎么划分才对?
  • Std::Future大冒险:穿越C++并发宇宙的时空胶囊
  • 《LINUX系统编程》笔记p13
  • Spring Cloud-面试知识点(组件、注册中心)
  • 2.2 定点数的运算 (答案见原书 P93)
  • 使用数据断点调试唤醒任务时__state的变化