(catkin/CMakeLists.txt - ROS Wiki)

前言

首先,对于学习ROS,CMakeLists.txt 的语法非常重要;如果不懂将无法开发!而要想明白 vanilla(香草) CMakeLists.txt 的语法,首先需要掌握常规Cmake语法。

第一章 概述

我们知道,Cmake是关于编译的事情;然而对于不同的Cmake各有其方言,需要独立查阅理解;本篇专门针对ROS版本的Cmake语法进行叙述;在读本文之前,期望读者已经理解如下几个文章:C语言编译:CMakeLists.txt语句  等。

本片针对文件CMakeLists.txt文件,讲述以下四个方面。

  • CMakeList.txt的固定格式,
  • 以及这些固定格式的内涵。
  • 以及如何去修改添加自己的CMakeList.txt文件。
  • 最后通过实例讲解细节。

第二章 CMakeList.txt约定顺序和结构

文件CMakeLists.txt是用于构建软件包的CMake构建系统的输入。任何符合CMake的软件包都包含一个或多个CMakeLists.txt文件,该文件描述如何构建代码以及将代码安装到何处?用于catkin项目的CMakeLists.txt文件是标准的香草CMakeLists.txt文件,带有一些独特的约束。

注意:您的CMakeLists.txt文件必须遵循下面格式,否则您的包将无法正确生成。配置中的顺序如下。

  • Required CMake Version (cmake_minimum_required)

指定编译器版本

  • Package Name (project())

指定项目名称

  • Find other CMake/Catkin packages needed for build (find_package())

查找其他依赖包

  • Enable Python module support (catkin_python_setup())

包含python支持

  • Message/Service/Action Genera2.3tors

加入用户定义的消息格式文件

(add_message_files(), add_service_files(), add_action_files())

  • Invoke message/service/action generation (generate_messages())

唤醒消息等。

  • Specify package build info export (catkin_package())

应用包信息导出。

  • Libraries/Executables to build (add_library()/add_executable()/target_link_libraries())

指定库路径

  • Tests to build (catkin_add_gtest())

指定测试路径

  • Install rules (install())

安装规则

以上就是标准的CMakeList.txt文件格式。

第三章  CMake版本指定

每个catkin CMakeLists.txt文件必须以所需的CMake版本开始。Catkin需要2.8.3或更高版本。

cmake_minimum_required(VERSION 2.8.3)

第四章 指定包名称

下一项是由CMake项目功能指定的包的名称。假设我们正在制作一个名为robot_brain的软件包。

注意:在CMake中,您可以在以后CMake脚本中的任何位置引用项目名称,只要需要,就可以使用变量${project_name}。此语句还有隐含的效果,那就是将生成如下的变量:

robot_brain_BINARY_DIR 和 robot_brain_SOURCE_DIR,同时,cmake 自动定义了两个等价的名称变量 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR。

第五章  查找依赖的CMake包

然后,我们需要指定需要找到哪些其他CMake包来使用CMake find_package函数构建我们的项目。catkin始终至少有一个依赖项:

以上:catkin是被搜索的项,REQUIRED表示前面的catkin的必须项目;

如果您的项目依赖于其他外来包,则它们会自动转换为katkin(柳絮)的组件(就CMake而言)。如果您将这些包指定为组件,而不是在这些包上使用find_包,这将使工作更轻松。例如,如果使用包nodelet。

find_package(catkin REQUIRED COMPONENTS nodelet)

注意:不应添加运行时依赖项在这里,应该是编译时的依赖项。

你也可以这样做:(然而,你会发现这不太方便)

5.1 find_package()的作用是什么?

如果CMake通过find_package找到一个包,它将导致创建几个CMake环境变量,这些变量提供有关找到的包的信息。这些环境变量可以稍后在CMake脚本中使用。环境变量描述导出的头文件所在的包、源文件所在的位置、包所依赖的库以及这些库的路径。名称始终遵循<PACKAGE NAME>的约定。

  • <NAME>_FOUND - Set to true if the library is found, otherwise false

  • <NAME>_INCLUDE_DIRS or <NAME>_INCLUDES - The include paths exported by the package

  • <NAME>_LIBRARIES or <NAME>_LIBS - The libraries exported by the package

  • <NAME>_DEFINITIONS - ?

5.2 为什么将Catkin-parkage指定为组件?

Catkin packages不是Catkin的真正组成部分。更确切地说,CMake的组件特性被用于Catkin的设计中,以节省大量的打字时间。

对于catkin包,如果您发现将它们打包为catkin的组件,这是有利的,因为使用catkin前缀创建了一组环境变量。例如,假设您在代码中使用了包nodelet。查找包的建议方法是:

find_package(catkin REQUIRED COMPONENTS nodelet)

这意味着nodelet导出的include路径、库等也会附加到catkin变量。例如,catkin_INCLUDE_DIRS不仅包含catkin的包含路径,还包含nodelet的包含路径!这将在以后派上用场。

相反地说:我们也可以自己找  find_package找到nodelet:

find_package(nodelet)

这意味着节点路径、库等不会添加到catkin变量中。这将导致nodelet_INCLUDE_DIRS、nodelet_LIBRARIES。

为了将少管理一些变量,用:

find_package(catkin REQUIRED COMPONENTS nodelet)

将那些变量集中收集到catkin_INCLUDE_DIRS和catkin_LIBRARIES内部。

5.3 调用Boost

如果使用C++和Boost,则需要调用Booost上的FundPulkAuthor(),并指定您使用的Boost的哪些方面作为组件。例如,如果您想使用Boost线程,您这样写:

find_package(Boost REQUIRED COMPONENTS thread)

第六章 catkin_package()

是catkin提供的CMake宏。这是为构建系统指定特定于柳絮的信息所必需的,而构建系统又用于生成pkg config和CMake文件。

在使用add_library()或add_executable()声明任何目标之前,必须调用此函数。该函数有5个可选参数:

  • INCLUDE_DIRS-导出的包的INCLUDE路径(即cflags)
  • LIBRARIES-从项目中导出的库
  • CATKIN_DEPENDS-此项目依赖的其他CATKIN项目
  • DEPENDS-此项目所依赖的非catkin CMake项目。要更好地理解,请参阅此说明。
  • CFG_EXTRAS-其他配置选项

可以找到完整的宏文档。

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

这表示包文件夹中的文件夹“include”是导出的标题所在的位置。CMake环境变量${PROJECT_NAME}的计算结果与前面传递给PROJECT()函数的值相同,在本例中,它将是“robot_brain”。“roscpp”+“nodelet”是构建/运行此软件包所需的软件包,“eigen”+“opencv”是构建/运行此软件包所需的系统依赖项。

第七章  指定构建目标

构建目标可以有多种形式,但通常它们代表两种可能性之一:

  • 可执行目标-我们可以运行的程序
  • 库目标—可由可执行目标在生成和/或运行时使用的库

7.1 目标命名

请务必注意,catkin中构建目标的名称必须是唯一的,无论它们构建/安装到哪个文件夹。这是CMake的一个要求。但是,唯一的目标名称仅在CMake内部需要。可以使用set_target_properties()函数将目标重命名为其他对象:

set_target_properties(rviz_image_viewPROPERTIES OUTPUT_NAME image_viewPREFIX "")

这将在生成和安装输出中将目标rviz_image_视图的名称更改为image_视图。

7.2 自定义输出目录

虽然可执行文件和库的默认输出目录通常设置为合理的值,但在某些情况下必须对其进行自定义。即,包含Python绑定的库必须放在不同的文件夹中,才能在Python中导入:

例子:

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

7.3 包括路径和库路径

在指定目标之前,您需要指定在何处可以找到所述目标的资源,特别是头文件和库:

例子:

  • Include Paths - Where can header files be found for the code (most common in C/C++) being built
  • Library Paths - Where are libraries located that executable target build against?
  • include_directories(<dir1>, <dir2>, ..., <dirN>)

  • link_directories(<dir1>, <dir2>, ..., <dirN>)

7.4 包含目录()

include_目录的参数应该是find_包调用生成的*_include_DIRS变量以及需要包含的任何其他目录。如果您使用的是catkin和Boost,那么include_directories()调用应该如下所示:

例子:

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

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

link_directories(~/my_libs)

请参阅此cmake线程以查看在链接目录link_directories().上使用目标链接库target_link_libraries()的详细示例。

7.5 可执行目标

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

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

这将构建一个名为myProgram的目标可执行文件,该文件由3个源文件构建:src/main.cpp、src/some_file.cpp和src/other_file.cpp。

7.6 库目标

add_library()CMake函数用于指定要生成的库。默认情况下,catkin构建共享库。

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

7.7 目标链接库

使用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()自动拉入的。

第八章 消息、服务和操作目标

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

提供了三个宏分别处理消息、服务和操作:

  • add_message_files

  • add_service_files

  • add_action_files

然后,必须在这些宏之后调用调用生成的宏:

 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依赖于消息_运行时的依赖项。​

catkin_package(
find_package(catkin REQUIRED COMPONENTS message_generation)
 ...CATKIN_DEPENDS message_runtime ......)

必须单独使用find_package()生成包消息,或将其作为catkin的一个组件:

find_package(catkin REQUIRED COMPONENTS message_generation)

您的package.xml文件必须包含对消息\u生成的生成依赖项和对消息\u运行时的运行时依赖项。如果依赖项是通过传递方式从其他包中拉入的,则不需要这样做。

如果您有一个目标(甚至是可传递的)依赖于需要构建消息/服务/操作的其他目标,则需要添加对目标catkin\u导出的\u目标的显式依赖,以便它们以正确的顺序构建。这种情况几乎总是适用的,除非你的软件包真的没有使用ROS的任何部分。不幸的是,此依赖项无法自动传播。(some_target是由add_executable()设置的目标的名称):

add_dependencies(some_target ${catkin_EXPORTED_TARGETS})

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

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

如果您的包同时满足上述两个条件,则需要添加两个依赖项,即:

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

8.2 实例

如果您的包在名为“MyMessage1.msg”和“MyMessage2.msg”的目录中有两条消息,并且这些消息依赖于std_msgs和sensor_msgs,则名为“MyService.srv”的目录中名为“srv”的服务定义了使用这些消息和服务的可执行消息程序,而可执行文件不使用本地消息程序,它使用ROS的某些部分,但不使用此包中定义的消息/服务,那么您需要在CMakeLists.txt中提供以下内容:

# Get the information about this package's buildtime dependenciesfind_package(catkin REQUIREDCOMPONENTS message_generation std_msgs sensor_msgs)# Declare the message files to be builtadd_message_files(FILESMyMessage1.msgMyMessage2.msg)# Declare the service files to be builtadd_service_files(FILESMyService.srv)# Actually generate the language-specific message and service filesgenerate_messages(DEPENDENCIES std_msgs sensor_msgs)# Declare that this catkin package's runtime dependenciescatkin_package(CATKIN_DEPENDS message_runtime std_msgs sensor_msgs)# define executable using MyMessage1 etc.add_executable(message_program src/main.cpp)add_dependencies(message_program ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})# define executable not using any messages/services provided by this packageadd_executable(does_not_use_local_messages_program src/main.cpp)add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})

此外,如果您希望构建actionlib操作,并且在“action”目录中有一个名为“MyAction.action”的操作规范文件,则必须将actionlib\u MSG添加到使用catkin打包的组件列表中,并在调用之前添加以下调用以生成\u消息(…):

add_action_files(FILESMyAction.action
)

此外,包必须对actionlib_msgs具有构建依赖关系。

第九章 启用Python模块支持

如果您的ROS包提供了一些Python模块,那么应该创建setup.py文件并调用

catkin_python_setup()

在调用generate_messages()和catkin_package()之前。

第十章 单元测试

有一个特定于catkin的宏,用于处理基于gtest的单元测试,称为catkin_add_gtest()。

if(CATKIN_ENABLE_TESTING)catkin_add_gtest(myUnitTest test/utest.cpp)
endif()

第十一章 可选步骤:指定可安装目标

构建后,将目标放置到catkin工作区的开发空间中。但是,我们通常希望将目标安装到系统(有关安装路径的信息可在REP 122中找到),以便其他人或本地文件夹可以使用它们来测试系统级安装。换句话说,如果您希望能够对代码进行“makeinstall”,则需要指定目标的最终位置。

这是使用CMake install()函数完成的,该函数将以下参数作为参数:

  • TARGETS - which targets to install

  • ARCHIVE DESTINATION - Static libraries and DLL (Windows) .lib stubs

  • LIBRARY DESTINATION - Non-DLL shared libraries and modules

  • RUNTIME DESTINATION - Executable targets and DLL (Windows) style shared libraries

以共享库为例:

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

以下是可执行文件的另一个示例:

install(TARGETS ${PROJECT_NAME}_nodeRUNTIME 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/${PROJECT_NAME}/DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}PATTERN ".svn" EXCLUDE
)
或者,如果include下的子文件夹与包名称不匹配:install(DIRECTORY include/DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}PATTERN ".svn" EXCLUDE
)

11.3 安装roslaunch文件或其他资源

其他资源(如launchfiles)可以安装到${CATKIN\u PACKAGE\u SHARE\u DESTINATION}:

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

find_package(Boost REQUIRED COMPONENTS system)
 
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
  ${Boost_INCLUDE_DIRS}
)
 
target_link_libraries(demo ${catkin_LIBRARIES} ${Boost_LIBRARIES})

关于CMake文档:

[CMake] adding a link directory

ROS知识: vanilla(香草) CMakeLists.txt 的语法相关推荐

  1. 用于创建此对象的程序是package_【ROS 学习笔记】CMakeLists.txt 与 package.xml

    0. 前言 在 ROS 中,节点的编写语言通常只有 C++ 和 Python,C++ 需要编译后才能运行,Python 则无需编译. 我们知道 Linux 平台编译 C++ 文件,需要编译器和链接器, ...

  2. CMakeLists.txt的语法介绍和几个实例

    参考 https://blog.csdn.net/afei__/article/details/81201039 https://www.bilibili.com/video/BV12f4y1X7Jm ...

  3. ROS项目库依赖库 CMakeLists.txt中添加第三方库路径

    项目需要读取键盘按键码值,需要用到cursese.h库 首先安装: sudo apt-get install libncurses5-dev 源码头文件加入 #include<curses.h& ...

  4. Android-JNI开发系列《八》CMakeLists.txt语法使用

    人间观察 带饭去上班的都是成年人的奢侈品! 技术永远在不断的更新升级,Android也一样. 目前在Android中的JNI开发都是采用的CMake进行编译c,c++代码来构建项目,早期都是Andro ...

  5. 【转载】CMake 语法 - 详解 CMakeLists.txt

    作者:红橙Darren 链接:https://www.jianshu.com/p/528eeb266f83 来源:简书 目录 1. 初试 cmake 的 helloworld 2. 构建生成 .so ...

  6. ROS学习(六):CMakeLists.txt 文件

    CMakeLists.txt 文件 为 CMake build 文件.是 CMake 编译系统中软件包的输入.描述如何编译代码.安装到哪里. http://wiki.ros.org/catkin/CM ...

  7. 【CMAKE系列】cmake中CMakeLists.txt脚本的常用语法

    在不同的平台编译的时候,会用到一些系统内置的变量,比如操作系统名称,版本号之类: CMAKE_SYSTEM:系統全名,如 "Linux-2.4.22″,"FreeBSD-5.4-R ...

  8. cmake 编译文件 CMakeLists.txt 语法介绍与实例演练

    一.Cmake 简介 cmake 是一个跨平台.开源的构建系统.它是一个集软件构建.测试.打包于一身的软件.它使用与平台和编译器独立的配置文件来对软件编译过程进行控制. 二.常用命令 1. 指定 cm ...

  9. Cmake知识----编写CMakeLists.txt文件编译C/C++程序

    1.CMake编译原理 CMake是一种跨平台编译工具,比make更为高级,使用起来要方便得多.CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt ...

最新文章

  1. 十分钟轻松让你认识Entity Framework 7
  2. java jdk安装 以及myeclipse安装
  3. hdu1722 切蛋糕
  4. Java9新功能之HTTP2和REPL
  5. Linux学习笔记02
  6. 服务器虚拟化的毕业设计,基于Vmware的服务器虚拟化管理毕业论文.doc
  7. Android中监听ScrollView滑动停止和滑动到底部
  8. 字节跳动推出企业技术服务平台“火山引擎”
  9. Python:PDF文件转图像
  10. 独家:为了永不停机的计算服务 - 三月月刊
  11. 一个成功企业家立下的22条规矩
  12. NoSQL数据库的介绍、NoSQL的产品、NoSQL数据库的分类等;
  13. java全栈开发主要工作内容,java全栈工程师
  14. 完美解决小爱同学蓝牙音箱(包括触屏版)连接电脑后找不到音频设备问题
  15. [Error] invalid operands to binary ^ (have ‘double‘ and ‘float‘)
  16. 【数据结构初阶】:栈和队列的实现(用C语言实现,附图详解和附源码)
  17. Mac自带FTP工具用法
  18. Google Instant Apps
  19. 手机生产日期查询方法
  20. 政务云存储 备份方案_在线云存储是否比远程备份解决方案更好?

热门文章

  1. 文巾解题 477. 汉明距离总和
  2. 深度学习核心技术精讲100篇(三十九)-医疗健康领域的短文本理解
  3. MATLAB实战系列(十二)-如何用人工鱼群算法解决带时间窗车辆路径(CVRP)问题(附MATLAB代码)
  4. 为什么通常牛顿法比梯度下降法能更快的收敛
  5. win7 安装openssh_Win732位旗舰版老友纯净版安装OpenSSH的方法
  6. tensorflow2中如何设置GPU的使用
  7. 人工智能的发展趋势和行业岗位
  8. 如何高效的Code Review
  9. 支付系统开发中可能遇到的问题
  10. Ten ways to improve the performance of large tables in MySQL--转载