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 可以省略
  • 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)

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://www.pswp.cn/bicheng/98156.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/98156.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/98156.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp打包前端项目

打包前的准备工作确保项目开发已完成&#xff0c;并且已安装最新版本的HBuilderX。检查项目中所有依赖是否已正确安装&#xff0c;配置文件如manifest.json已根据H5需求进行适配。在HBuilderX中打包在 HBuilderX 中&#xff0c;点击顶部菜单栏的 “发行” -> “网站-H5手机版…

Dify + Bright Data MCP:从实时影音数据到可落地的智能体生产线

一、引言&#xff1a;AI 应用与实时影音数据的融合价值 内容生态近年的“视频化、实时化、社交化”浪潮&#xff0c;将数据获取链路推到了更靠前的位置。真正驱动业务的&#xff0c;不是某一帧漂亮的模型输出&#xff0c;而是“数据—理解—动作”的持续闭环。无论是品牌内容策…

【Linux】make/Makefile工具篇

目录一、自动化构建二、make/Makefile2.1 见识一个简单的make/Makefile2.2 Makefile的基本语法2.3 Makefile的语法细节个人主页<—请点击 Linux专栏<—请点击 一、自动化构建 自动化构建是指通过构建工具&#xff08;如make&#xff09;解析构建脚本&#xff08;如Make…

如何在企业微信上以 HTTPS 方式访问内网 OA/ERP 等系统?

企业微信可以将 ZeroNews 平台上添加的内网应用集成到企业微信的工作台。这样&#xff0c;用户即使在外部网络环境中&#xff0c;也可以通过企业微信访问内网的 OA、ERP 等应用。以下是企业在 Linux 服务器上部署 OA 系统&#xff0c;并通过 ZeroNews 通过互联网访问 OA 系统的…

Windows 11 安装使用 nvm,Node.js、npm多版本管理、切换

Windows 11 安装使用 nvm&#xff0c;Node.js、npm多版本管理、切换 文章目录Windows 11 安装使用 nvm&#xff0c;Node.js、npm多版本管理、切换1. nvm 简介2. 安装、配置 nvm2.1. 卸载现有 Node.js&#xff08;非常重要&#xff01;&#xff09;2.2. 下载 nvm-windows 安装包…

在LazyVim中配置Rust开发环境

要在LazyVim中配置Rust开发环境&#xff0c;包括代码补全、格式化、调试等功能&#xff0c;可以按照以下步骤进行配置&#xff1a; 1. 确保基础环境 首先确保你已经安装了&#xff1a; Rust工具链 (rustup, rustc, cargo)LazyVim已正确安装 # 安装Rust工具链 curl --proto http…

LeetCode热题100--114. 二叉树展开为链表--中等

1. 题目 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例 …

REST API 设计最佳实践指南 - 如何用 JavaScript、Node.js 和 Express.js 构建 REST API

过去几年里&#xff0c;我创建并使用过很多 API。在此过程中&#xff0c;我遇到过各种好的和坏的实践&#xff0c;也在开发和调用 API 时碰到过不少棘手的问题&#xff0c;但也有很多顺利的时刻。 网上有很多介绍最佳实践的文章&#xff0c;但在我看来&#xff0c;其中不少都缺…

MyCat

文章目录18.1 MySQL 读写分离概述18.1.1 工作原理18.1.2 为什么要读写分离18.1.3 实现方式18.2 什么是 MyCat18.3 MyCat 安装与配置1. 下载与解压2. 创建用户并修改权限3. 目录说明4. Java 环境要求18.4 MyCat 启动与配置1. 配置环境变量2. 配置 hosts&#xff08;多节点集群&a…

使用 Spring Boot 搭建和部署 Kafka 消息队列系统

使用 Spring Boot 搭建和部署 Kafka 消息队列系统 摘要 本文将引导您在 Kafka 上搭建一个消息队列系统&#xff0c;并整合到您的 Spring Boot 项目中。我们将逐步实现这一方案&#xff0c;探讨其中的关键原理&#xff0c;避开可能遇到的坑&#xff0c;并最终将其部署到 Kuberne…

daily notes[45]

文章目录basic knowledgereferencesbasic knowledge the variable in Rust is not changed. let x5; x6;Rust language promotes the concept that immutable variables are safer than variables in other programming language such as python and and are in favour of th…

技术奇点爆发周:2025 年 9 月科技突破全景扫描

技术奇点爆发周&#xff1a;2025 年 9 月科技突破全景扫描当中国 "祖冲之三号" 量子计算机在特定任务上超越经典超级计算机一千万亿倍的算力新闻&#xff0c;与 OpenAI 宣布 100 亿美元定制芯片量产协议的消息在同一周密集爆发时&#xff0c;我们真切感受到了技术革命…

分布式专题——10.3 ShardingSphere实现原理以及内核解析

1 ShardingSphere-JDBC 内核工作原理当往 ShardingSphere 提交一个逻辑SQL后&#xff0c;ShardingSphere 到底做了哪些事情呢&#xff1f;首先要从 ShardingSphere 官方提供的这张整体架构图说起&#xff1a;1.1 配置管控在 SQL 进入 ShardingSphere 内核处理&#xff08;如解析…

移动语义的里里外外:从 std::move 的幻象到性能的现实

我们都已经听过这样的建议&#xff1a;“使用 std::move 来避免昂贵的拷贝&#xff0c;提升性能。” 这没错&#xff0c;但如果你对它的理解仅止于此&#xff0c;那么你可能正在黑暗中挥舞着一把利剑&#xff0c;既可能披荆斩棘&#xff0c;也可能伤及自身。 移动语义是 C11 带…

selenium完整版一览

selenium 库驱动浏览器selenium库是一种用于Web应用程序测试的工具,它可以驱动浏览器执行特定操作,自动按照脚本代码做出单击、输入、打开、验证等操作,支持的浏览器包括IE、Firefox、Safari、Chrome、Opera等。而在办公领域中如果经常需要使用浏览器操作某些内容,就可以使用se…

[Linux]学习笔记系列 -- lib/kfifo.c 内核FIFO实现(Kernel FIFO Implementation) 高效的无锁字节流缓冲区

文章目录lib/kfifo.c 内核FIFO实现(Kernel FIFO Implementation) 高效的无锁字节流缓冲区历史与背景这项技术是为了解决什么特定问题而诞生的&#xff1f;它的发展经历了哪些重要的里程碑或版本迭代&#xff1f;目前该技术的社区活跃度和主流应用情况如何&#xff1f;核心原理与…

MFC_Install_Create

1. 安装MFC 编写MFC窗口应用程序需要用到Visual Studiohttps://visualstudio.microsoft.com/zh-hans/&#xff0c;然后安装&#xff0c;要选择使用C的桌面开发&#xff0c;再点击右边安装详细信息中的使用C的桌面开发&#xff0c;往下滑&#xff0c;有一个适用于最新的v143生成…

Langchain4j开发之AI Service

学习基于Langchain4j的大模型开发需要学习其中Ai Service的开发模式。里面对大模型做了一层封装&#xff0c;提供一些可以方便调用的api。其中有两种使用Ai Service的方式。一.编程式开发1.首先引入Langchain4的依赖。<dependency><groupId>dev.langchain4j</gr…

认识神经网络和深度学习

什么是神经网络&#xff1f;什么又是深度学习&#xff1f;二者有什么关系&#xff1f;……带着这些疑问&#xff0c;进入本文的学习。什么是神经网络神经网络&#xff08;Neural Network&#xff09;是一种模仿生物神经系统&#xff08;如大脑神经元连接方式&#xff09;设计的…

医疗行业安全合规数据管理平台:构建高效协作与集中化知识沉淀的一体化解决方案

在医疗行业中&#xff0c;数据不仅是日常运营的基础&#xff0c;更是患者安全、服务质量和合规管理的核心载体。随着医疗业务的复杂化和服务模式的多元化&#xff0c;各类机构——从大型医院到科研中心——都面临着海量文档、报告、影像资料和政策文件的管理需求。这些资料往往…