ROS下的CMakeList.txt编写

2024-04-27 01:58
文章标签 编写 txt ros cmakelist

本文主要是介绍ROS下的CMakeList.txt编写,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • 一、 概述
    • 二、 整体结构和命令一览
    • 三、 CMake版本
    • 四、 软件包名称
    • 五、 查找相关的CMake包
      • 5.1 那find_package()作何用?
      • 5.2为啥Catkin包是组件形式?
      • 5.3Boost库
    • 六、catkin_package()
    • 七、指定构建目标
      • 7.1目标命名
      • 7.2自定义输出目录
      • 7.3包含路径和库路径
        • 7.3.1 include_directories()
        • 7.3.2 link_directories()
        • 7.4 可执行目标
        • 7.5 库目标
        • 7.6 target_link_libraries()
    • 八、消息、服务和响应
      • 8.1 使用条件
      • 8.2 例子
    • 九、启用Python模块支持
    • 十、单位测试
    • 十一、可选步骤:指定可安装的目标
      • 11.1 安装Python可执行脚本
      • 11.2 安装头文件
      • 11.3 安装roslaunch文件或其他资源

一、 概述

CMake构建系统通过ROS包中的CMakeList.txt来构建软件包。互相依赖的包都包含一个或者多个CMakeList.txt来描述如何编译代码和如何安装。在catkin 项目中,CMakeList.txt 符合标准的vanilla CMakeList.txt 格式,但稍微有点不同。

二、 整体结构和命令一览

在编写CMakeLists.txt时必须遵循特定的格式,否则软件包将无法正确构建和编译。一个完整的ROS下CMakeList.txt由下面内容组成
1. 所需CMake版本(cmake_minimum_required)
2. 软件包名称(project())
3. 查找构建所需的其他CMake / Catkin软件包(find_package())
4. 启用Python模块支持(catkin_python_setup())
5. 消息/服务/动作生成器(add_message_files(),add_service_files(),add_action_files())
6. 生成消息/服务/动作等自定义消息(generate_messages())
7. 指定包的构建信息输出(catkin_package())
8. 要建立的库/可执行文件(add_library()/ add_executable()/ target_link_libraries())
9. 测试(catkin_add_gtest())
10. 安装规则(install())

三、 CMake版本

CMakeLists.txt文件必须以CMake的版本开头。下面表示的是Catkin需要2.8.3或更高的版本。

cmake_minimum_required(VERSION 2.8.3)

四、 软件包名称

继而需要指定CMake工程名,一般取作包名。例如我们的项目名叫做robot_brain

project(robot_brain)

而在CMake中,可以在CMake文本中使用变量${PROJECT_NAME}来引用项目名称。

五、 查找相关的CMake包

接下来我们要用find_package指令来指定在构建项目过程中依赖了哪些其他的包,在ROS中,catkin必备依赖,所以雷打不打地我们写上catkin REQUIRED

find_package(catkin REQUIRED)

在此基础上,如果我们还需要依赖其他包(或者组件),我们就在 上述的包后面继续添加包(组件)名即可:

find_package(catkin REQUIRED COMPONENTS nodelet)

或者可以写成

find_package(catkin REQUIRED)
find_package(nodelet REQUIRED)

值得注意一点的是:这里添加的包用于构建包使用,而不是添加运行时依赖项。

你也可以做:

find_package(catkin REQUIRED)
find_package(nodelet REQUIRED)

如何写,看个人习惯吧,如果不考虑篇幅,其实我更喜欢把所有包(组件)列成一列,直观。在普通的CMakeLists.txt中是没有find_package()的,那么,catkin中的这个语句有啥作用呢?

5.1 那find_package()作何用?

如果CMake通过find_package找到一个包,则会自动生成有关包所在路径的CMake环境变量,环境变量描述了包中头文件的位置,源文件的位置,包所依赖的库以及这些库的路径。
这些变量名称以< PACKAGE NAME >_< PROPERTY >的形式出现:
- < NAME >_FOUND - 如果找到库,则设置为true,否则为false
- < NAME > _INCLUDE_DIRS或 _INCLUDES - 包导出的包含路径
- < NAME > _LIBRARIES或 _LIBS - 由包导出的库
- < NAME > _DEFINITIONS -
- …

5.2为啥Catkin包是组件形式?

实际上,Catkin的包并不是catkin的真正组成部分。而catkin采用CMake的组件功能,主要是为了节省打字时间。
将Catkin的包作为一种组件看待是很有好处的,当你找到包的时候,各种以catkin为前缀的添加到CMakeLists.txt中了。以前述nodelet包为例:

find_package(catkin REQUIRED COMPONENTS nodelet)

catkin执行到这个语句时,就会导出的nodelet的include路径,库等也添加到catkin前缀的变量中。例如,catkin_INCLUDE_DIRS不仅包含catkin的include路径,还包含了nodelet,这在后面会用到。
当然,我们可以只选择找nodelet的:

find_package(nodelet)

很可惜这样的做法会令nodelet路径,库等不会被添加到catkin变量中,从而生成了例如nodelet_INCLUDE_DIRS,nodelet_LIBRARIES这样的变量等。

5.3Boost库

如果使用C ++和Boost,则需要用find_package()来找Boost库,并指定Boost中的组件。 举个栗子,如果想使用Boost线程,就可以写成:

find_package(Boost REQUIRED COMPONENTS thread)

六、catkin_package()

catkin_package()是一个catkin提供的CMake宏,用于将catkin特定的信息信息输出到构建系统上,用于生成pkg配置文件以及CMake文件。

这个命令必须在add_library()或者add_executable()之前调用,该函数有5个可选参数:

  • INCLUDE_DIRS - 导出包的include路径
  • LIBRARIES - 导出项目中的库
  • CATKIN_DEPENDS - 该项目依赖的其他catkin项目
  • DEPENDS - 该项目所依赖的非catkin CMake项目。
  • CFG_EXTRAS - 其他配置选项

举个栗子:

catkin_package(INCLUDE_DIRS includeLIBRARIES ${PROJECT_NAME}CATKIN_DEPENDS roscpp nodeletDEPENDS eigen opencv)

这表示包文件夹中的文件夹“include”是导出头文件的地方。 ${PROJECT_NAME}根据project中的内容生成,此处是rrobot_brain。“roscpp”+“nodelet”是用来构建/运行此程序包的catkin包,而“eigen”+“opencv”是用于构建/运行此程序包的非catkin包。

七、指定构建目标

构建目标可以有多种形式,但通常主要有以下两种:

  • 执行文件目标 - 可以运行的程序
  • 库目标 - 可在构建和/或运行时给可执行目标使用的库

7.1目标命名

值得重点关注的是,catkin中的构建目标的名称必须是唯一的,但是,但构建目标命名的唯一性只能在CMake内部进行。可以使用set_target_properties()函数将目标重命名为其他目标:
再举个栗子:

set_target_properties(rviz_image_viewPROPERTIES OUTPUT_NAME image_viewPREFIX "")

这时就将rviz_image_view的名称更改为image_view了。

7.2自定义输出目录

一般情况下,令输出目标目录保持默认就可以了,但有时遇到一些特定情况就得因地制宜。再再举个栗子,一个包含了Python bindings的库必须防止在不同的文件夹,才能够被导入Python中,因此可以通过下述方式进行:

set_target_properties(python_module_libraryPROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})

7.3包含路径和库路径

在生成目标之前,请记得先写好包含路径和库路径,不然编译会失败。

  • 包括路径 - 头文件
  • 库路径 - 构建对象需要用到的库
include_directories(<dir1>,<dir2>,...,<dirN>)
link_directories(<dir1>,<dir2>,...,<dirN>)
7.3.1 include_directories()

include_directories()中的参数应该是调用find_package调用时生成的* _INCLUDE_DIRS变量。 如果使用catkin和Boost,那么include_directories()调用应该如下所示:

include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

第一个参数“include”表示包中的include /目录也是路径的一部分。

7.3.2 link_directories()

link_directories()函数可用于添加额外的库路径,但通常不推荐这样做,因为 所有catkin和CMake软件包在find_packaged时都会自动添加链接信息。 只需写target_link_libraries()中就可以了。但真要写,就按照下面那样来写:

link_directories(~/my_libs)
7.4 可执行目标

要指定必须构建的可执行目标,我们必须使用add_executable()CMake函数。

add_executable(myProgram src/main.cpp src/some_file.cpp)

构建myProgram的目标可执行文件,3个源文件构建:src / main.cpp,src / some_file.cpp和src / another_file.cpp。

7.5 库目标

add_library() 用于指定要构建的库。

add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
7.6 target_link_libraries()

target_link_libraries()来指定可执行目标链接的库。 通常在add_executable()调用之后完成。 如果找不到ros,则添加$ {catkin_LIBRARIES}。

target_link_libraries(<executableTargetName>, <lib1>, <lib2>, ... <libN>)
add_executable(foo src/foo.cpp)
add_library(moo src/moo.cpp)
target_link_libraries(foo moo)  -- This links foo against libmoo.so

请注意,在大多数情况中不需要使用link_directories(),因为find_package()自动拉入。

八、消息、服务和响应

  消息(.msg),服务(.srv)和响应(.action)文件在ROS包构建和使用之前需要一个特殊的预处理器构建步骤。 这些宏的要点是生成编程语言特定的文件,以便可以利用其选择的编程语言中的消息,服务和动作。 构建系统将使用生成器(例如gencpp,genpy,genlisp等)生成绑定。

提供了三个宏来分别处理消息,服务和响应:

  • add_message_files
  • add_service_files
  • add_action_files

而在之后必须在下面写下面宏,catkin时候会在devel的include文件夹中生成对应的头文件:

generate_messages()

8.1 使用条件

为了能够正常生成相应的文件,这些宏必须在catkin_package()宏之前,

find_package(catkin REQUIRED COMPONENTS ...)add_message_files(...)add_service_files(...)add_action_files(...)generate_messages(...)catkin_package(...)`

在catkin_package()宏中写上CATKIN_DEPENDS message_runtime

catkin_package(...CATKIN_DEPENDS message_runtime ......)

并且在find_package()写上message_generation组件:

find_package(catkin REQUIRED COMPONENTS message_generation)

package.xml文件中加上

    <build_depend>message_generation</build_depend><run_depend>message_runtime</run_depend>

  如果构建的对象依赖于其他需要构建消息/服务/响应的构建对象,则需要向目标catkin_EXPORTED_TARGETS添加明确的依赖关系,以便它们以正确的顺序构建。 这种情况比较常用,除非您的包真的不使用ROS的任何部分。 但这种依赖关系不能自动传递。 (some_target是由add_executable()设置的目标的名称):

 add_dependencies(some_target${catkin_EXPORTED_TARGETS})

  如果需要构建消息或服务的包以及使用这些消息和/或服务的可执行文件,则需要为自动生成的消息目标创建明确的依赖关系,以便以正确的顺序构建它们。 (some_target是由add_executable()设置的目标的名称):

add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS})

  如果您的catkin包满足上述两个条件,则需要添加以下两个依赖关系,即:

add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

8.2 例子

  现在有两个依赖于std_msgssensor_msgs的消息MyMessage1.msgMyMessage2.msg,还有一个自定义服务MyService.srvmessage_program是使用这些消息和服务的指令,以及生成不使用自定义消息、服务的程序do_not_use_local_messages_program**catkin包,那么**CMakeLists.txt应该写成:

# 构建时依赖项
find_package(catkin REQUIRED COMPONENTS          message_generation std_msgs # 声明要构建哪些消息
add_message_files(FILESMyMessage1.msgMyMessage2.msg)# 声明构建哪些服务
add_service_files(FILESMyService.srv)# 声明生成上述消息、服务需要依赖的消息以及服务
generate_messages(DEPENDENCIES std_msgs sensor_msgs)# 声明运行时依赖项
catkin_package(CATKIN_DEPENDS message_runtime std_msgs sensor_msgs)# 声明构建生成的可执行文件名称以及依赖项
add_executable(message_program src/main.cpp)
add_dependencies(message_program ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})# 声明构建不需要使用自定义消息、服务的可执行文件
add_executable(does_not_use_local_messages_program src/main.cpp)
add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})

如果要构建响应,则在包中“action”目录中创建有一个名为“MyAction.action”的文件,则必须将actionlib_msgs添加到使用catkin进行find_package的组件列表中,然后在CMakeList.txt中加上下面两行:

add_action_files(FILESMyAction.action)

此外,该包必须具有对actionlib_msgs的构建依赖。

九、启用Python模块支持

  如果catkin包使用一些Python模块,您应该创建一个setup.py文件,并在调用catkin_python_setup()之后调用generate_messages()和catkin_package()。

十、单位测试

  有一个catkin-specific宏用于处理名为catkin_add_gtest()的基于gtest的单元测试。

catkin_add_gtest(myUnitTest test / utest.cpp)

十一、可选步骤:指定可安装的目标

  构建后,构建目标通常被放置在catkin工作区中。但有时候我们希望将目标安装到系统其他地方(有关安装路径的信息可以在REP 122中找到),以便其他人或本地文件夹可以使用它们来测试。换句话说,如果你想要做一个“make install”的代码,你需要指定目标应该生成到哪里。
这是使用CMake install()函数作为参数完成的:

目标 - 目标是安装
ARCHIVE DESTINATION - 静态库和DLL(Windows).lib存根
LIBRARY DESTINATION - 非DLL共享库和模块
RUNTIME DESTINATION - 可执行目标和DLL(Windows)样式共享库

举个栗子:

install(TARGETS ${PROJECT_NAME}ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

  除了这些标准目标,一些文件必须安装到特殊文件夹。即一个包含Python绑定的库必须安装到不同的文件夹中才能在Python中导入:

install(TARGETS python_module_libraryARCHIVE DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}LIBRARY DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
)

11.1 安装Python可执行脚本

  对于Python代码,安装规则看起来是不同的,因为没有使用add_library()和add_executable()函数,以便CMake确定哪些文件是目标以及它们是什么类型的目标。 而是在您的CMakeLists.txt文件中使用以下内容:
  

catkin_install_python(PROGRAMS scripts/myscriptDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

有关安装python脚本和模块的详细信息以及文件夹布局的最佳做法,请参见catkin手册。

  如果您只安装Python脚本并且不提供任何模块,则不需要创建上述setup.py文件,也不需要调用catkin_python_setup()。

11.2 安装头文件

  标题文件也必须安装到“include”文件夹中,这通常是通过安装整个文件夹的文件来完成的(可选地,按文件名模式过滤,不包括SVN子文件夹)。 这可以通过如下所示的安装规则完成:

install(DIRECTORY include/ PROJECTNAME/DESTINATION P R O J E C T N A M E / D E S T I N A T I O N {CATKIN_PACKAGE_INCLUDE_DESTINATION}
PATTERN “.svn” EXCLUDE
)
或者如果包含的子文件夹与包名称不匹配:
install(DIRECTORY include/
DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
PATTERN “.svn” EXCLUDE
)

11.3 安装roslaunch文件或其他资源

其他资源(如启动文件)可以安装到

$ {CATKIN_PACKAGE_SHARE_DESTINATION
install(DIRECTORY launch/DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launchPATTERN ".svn" EXCLUDE)

参考文章:
1.ROS中的CMakeLists.txt
2.catkinCMakeLists.txt

这篇关于ROS下的CMakeList.txt编写的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/939235

相关文章

ROS话题通信流程自定义数据格式

ROS话题通信流程自定义数据格式 需求流程实现步骤定义msg文件编辑配置文件编译 在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如:

BD错误集锦8——在集成Spring MVC + MyBtis编写mapper文件时需要注意格式 You have an error in your SQL syntax

报错的文件 <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.yuan.dao.YuanUserDao"><!

如何利用echarts编写立体的柱状图表

1、引入 import * as echarts from 'echarts' 2、创建图标容器 3、调用渲染 <template><div ref="eachrtsBox" style="width: 200px;height: 200px;"></div></template><script>import * as echarts from 'echarts'export d

CMake笔记之CMAKE_INSTALL_PREFIX详解以及ROS中可执行文件为什么会在devel_lib中

CMake笔记之CMAKE_INSTALL_PREFIX详解以及ROS中可执行文件为什么会在devel_lib中 code review! 文章目录 CMake笔记之CMAKE_INSTALL_PREFIX详解以及ROS中可执行文件为什么会在devel_lib中1.`CMAKE_INSTALL_PREFIX`详解变量作用设置 `CMAKE_INSTALL_PREFIX`示例影响范围常

oracle数据导出txt及导入txt

oracle数据导出txt及导入txt ORACLE数据导出TXT及从TXT导入: 导出到TXT文件: 1、用PL/SQL DEV打开CMD窗口。 2、spool d:/output.txt; 3、set heading off; --去掉表头 4、select * from usergroup; 5、spool off; www.2ct

ssh在本地虚拟机中的应用——解决虚拟机中编写和阅读代码不方便问题的一个小技巧

虚拟机中编程小技巧分享——ssh的使用 事情的起因是这样的:前几天一位工程师过来我这边,他看到我在主机和虚拟机运行了两个vscode环境,不经意间提了句:“这么艰苦的环境写代码啊”。 后来我一想:确实。 我长时间以来都是直接在虚拟机里写的代码,但是毕竟是虚拟机嘛,有时候编辑器没那么流畅,在文件比较多的时候跳转很麻烦,容易卡住。因此,我当晚简单思考了一下,想到了一个可行的解决方法——即用ssh

ROS话题通信机制实操C++

ROS话题通信机制实操C++ 创建ROS工程发布方(二狗子)订阅方(翠花)编辑配置文件编译并执行注意订阅的第一条数据丢失 ROS话题通信的理论查阅ROS话题通信流程理论 在ROS话题通信机制实现中,ROS master 不需要实现,且连接的建立也已经被封装了,需要关注的关键点有三个: 发布方(二狗子)订阅方(翠花)数据(此处为普通文本) 创建ROS工程 创建一个ROS工程

简单 使用 的makefile编写 框架

1、指定编译器,如海思平台:CROSS_COMPILE=arm-hisiv100nptl-linux-; 2、指定编译工具:GCC=$(CROSS_COMPILE)gcc   CC=$(CROSS_COMPILE)g++; 3、使用 export 导出 子makefile 要用的变量; 4、定义变量的形式  指定 工程源文件 需要使用到的 “宏”,在后面的 LDFLAGS 里面使用 -D将其

(转)Sublime Text 2 (Emmet):HTML/CSS代码快速编写神器

Emmet的前身是大名鼎鼎的Zen coding,如果你从事Web前端开发的话,对该插件一定不会陌生。它使用仿CSS选择器的语法来生成代码,大大提高了HTML/CSS代码编写的速度,比如下面的演示:   Zen coding下的编码演示   去年年底,该插件已经改名为Emmet。但Emmet不只改名,还带来了一些新特性。本文就来直观地演示给你。 一、快速编写HTML代码 1.

编程精粹—— Microsoft 编写优质无错 C 程序秘诀 07:编码中的假象

这是一本老书,作者 Steve Maguire 在微软工作期间写了这本书,英文版于 1993 年发布。2013 年推出了 20 周年纪念第二版。我们看到的标题是中译版名字,英文版的名字是《Writing Clean Code ─── Microsoft’s Techniques for Developing》,这本书主要讨论如何编写健壮、高质量的代码。作者在书中分享了许多实际编程的技巧和经验,旨在