ROS:catkin/CMakeLists.txt

1. 简介

文件CMakeLists.txt是CMake build系统用来构建软件包的输入。任意的CMake-compliant包包含一个或多个CMakeLists.txt文件描述代码该如何构建以及在哪里安装。

2. 完整的结构和顺序

CMakeLists.txt文件必须遵循以下格式,不然安装包不会被正确的搭建:

  1. Required CMake Version (cmake_minimum_required)
  2. Package Name (project())
  3. Find other CMake/Catkin packages needed for build (find_package())
  4. Enable Python module support (catkin_python_setup())
  5. Message/Service/Action Generators (add_message_files(), add_service_files(), add_action_files())
  6. Invoke message/service/action generation (generate_messages())
  7. Specify package build info export (catkin_package())
  8. Libraries/Executables to build (add_library()/add_executable()/target_link_libraries())
  9. Tests to build (catkin_add_gtest())
  10. Install rules (install())

2.1 CMake版本

每一个catkin CmakeLists.txt文件必须由所需的Cmake版本开头。Catkin需要2.8.3即以上的版本:

cmake_minimum_required(VERSION 2.8.3)

2.2 功能包名

第二项为功能包的名字,它由CMake的Project函数所指定。当我们制作一个叫做robot_brain的功能包时:

project(robot_brain)

注意在CMake中,通过使用变量${PROJECT_NAME},你可以在后面的CMake脚本中的任何需要的地方使用该项目名。

2.3 寻找依赖CMake功能包

之后,我们需要使用CMake find_package 函数来指定需要找到哪些其他的CMake功能包来构建我们的项目。在catkin中,总是至少有一项依赖项:

find_package(catkin REQUIRED)

如果您的项目依赖于其他的wet packages(基于catkin编写的package叫做wet package,基于rosbuild编写的package叫做dry package),则它们会自动转换为catkin的components(根据CMake)。如果您将它们指定为components,而不是在这些包上使用find_package,这将使工作变得更容易。例如,如果您使用功能包nodelet:

find_package(catkin REQUIRED COMPONENTS nodelet)

还需要包含:

find_package(catkin REQUIRED)
find_package(nodelet REQUIRED)

然而,你会发现这是一种不方便的做事方式。

2.3.1 find_package() 是做什么的

如果CMake通过find_package找到了一个功能包,它将会创建几个CMake环境变量,这些变量提供了关于所找到的功能包的信息。这些环境变量可以在稍后的CMake脚本中使用。环境变量描述了功能包导出的头文件的位置、源文件的位置、包依赖的库以及这些库的路径。名称始终遵循<PACKAGENAME>_<PROPETRY>的惯例:

  • <NAME>_FOUND: 如果找到此库,则设置为真,否则设置为假;
  • <NAME>_INCLUDE_DIRS or <NAME>_INCLUDES: 包含功能包导出的路径;
  • <NAME>_LIBRARIES or <NAME>_LIBS : 由包导出的库;

2.3.2 为什么Catkin功能包被指定为了Components

Catkin功能包并不是真正的catkin的compons。更像是在catkin的设计中利用了CMake的components特性,以节省大量的打字时间。

对于catkin功能包,如果将find_package作为catkin的component,这是有好处的,因为一个单组环境变量会伴随着catkin_prefix创建。比如说,假设在代码中使用了nodelet功能包。推荐的寻找功能包的方法是:

find_package(catkin REQUIRED COMPONENTS nodelet)

这表明nodelet导出的include路径,库之类的也被附加到了catkin变量中。栗如,catkin_INCLUDE_DIRS不仅包含了catkin的路径,也还包含了nodelet的路径。这在之后会派上用场的。

也可以单独使用find_package nodelet:

find_package(nodelet)

这表明nodelet的路径,库之类的将不会被添加进catkin_ variables。

2.3.3 Boost

如果使用C++和Boost,你需要在Boost上调用find_package(),并指定使用Boost的哪些方面作为components。比如说,如果你想要使用Boost threads,你会说:

find_package(Boost REQUIRED COMPONENTS thread)

2.4 catkin_package()

catkin_package()是一个由catkin提供的CMake宏。这是为构建系统指定的catkin-specific信息所必需的,而构建的系统又用于生成pkg-config和CMake文件。

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

  • INCLUDE_DIRS - 导出的包含功能包的路径(也就是cflags)
  • LIBRARIES - 从项目导出的库
  • CATKIN_DEPENDS - 这个项目依赖的其他catkin项目
  • DEPENDS - 这个项目依赖的非catkin CMake项目
  • CFG_EXTRAS - 额外的配置选项

举个栗子:

catkin_package(
   INCLUDE_DIRS include
   LIBRARIES ${PROJECT_NAME}
   CATKIN_DEPENDS roscpp nodelet
   DEPENDS eigen opencv)

这表明文件夹中的“include"文件夹是导出头文件的位置(应该不是src每个项目中创建的include,而是devel里面的)。CMake环境变量${PROJECT_NAME}评估的是之前传递给project()函数的内容。在本例中它是”robot_brain"。“roscpp”+"nodelet"是构建/运行这个包需要出现的包,“eigen”+"opencv"是构建/运行这个包需要出现的系统依赖项。

2.5 指定搭建目标

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

  • Executable Target-我们可以运行的程序
  • Library Target-可被executable targets在构建和/或运行时使用的库

2.5.1 目标命名Target Naming

值得注意的是,无论构建、安装到哪个文件夹,在catkin中构建目标的名称都必须是唯一的。这是CMake的要求。然而,只有在CMake内部才需要目标的唯一名称。可以通过使用set_target_properties()函数将目标重命名为其他的。
栗子:

set_target_properties(rviz_image_view
                      PROPERTIES OUTPUT_NAME image_view
                      PREFIX "")

这会在build和install输出时,将目标的名字rviz_image_view改变为image_view。

2.5.2 自定义输出目录

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

set_target_properties(python_module_library
  PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})

2.5.3 Include路径和Library路径

在指定目标之前,你需要指定在哪里可以找到资源的目标,特别是头文件和库:

  • Include Paths: 可以在其中找到正在构建的代码的头文件(在C/C++中最城建)
  • Library Paths: 可执行目标构建所针对的库的位置
  • include_directories(<dir1>, <dir2>, …, <dirN>)
  • link_directories(<dir1>, <dir2>, …, <dirN>)
2.5.3.1 include_directories()

include_directory的参数应该是find_package调用生成的*_INCLUDE_DIRS变量以及需要包含的任何其他目录。如果正在使用catkin和Boost的话,include_directories()的调用应该是这样的:

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

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

2.5.3.2 link_directories()

2.5.4 可执行目标

2.5.5 库目标

2.5.6 target_link_libraries

2.6 Messages, Services, 和Action Targets

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

有三个宏被提供来分别处理messages, services和actions:

  • add_message_files
  • add_service_files
  • add_action_files
    这些宏之后必须再接上上述宏的调用来调用generation:
 generate_messages()

2.6.1 重要的先决条件/约束

  • 这些宏必须出现在catkin_package()宏之前,以便generation能够正确工作。
 find_package(catkin REQUIRED COMPONENTS ...)
 add_message_files(...)
 add_service_files(...)
 add_action_files(...)
 generate_messages(...)
 catkin_package(...)
 ...
  • catkin_package()宏必须在message_runtime有一个CATKIN_DEPENDS依赖项。
catkin_package(
 ...
 CATKIN_DEPENDS message_runtime ...
 ...)
  • 对于功能包message_generation,必须使用find_package()。可以单独使用,或者作为catkin的一个component:
find_package(catkin REQUIRED COMPONENTS message_generation)
  • 在package.xml文件必须包含对message_generation的构建依赖项和对message_runtime的运行时依赖项。如果依赖项是从其他包中传递过来的,则没有必要。

2.6.2 实栗

如果你的功能包中有两个在目录“msg”的messages,被称作"MyMessage1.msg和"MyMessage2.msg",这些messages依赖std_msgs和sensor_msgs;有一个在目录“srv”的service,被称作"MyService.srv",可执行的does_not_use_local_messages_program使用ROS的某些部分,而不是在这个包中定义的消息/服务,那么您将需要在您的CMakeLists.txt中使用以下内容:

  # Get the information about this package's buildtime dependencies
  find_package(catkin REQUIRED
    COMPONENTS message_generation std_msgs sensor_msgs)

  # Declare the message files to be built
  add_message_files(FILES
    MyMessage1.msg
    MyMessage2.msg
  )

  # Declare the service files to be built
  add_service_files(FILES
    MyService.srv
  )

  # Actually generate the language-specific message and service files
  generate_messages(DEPENDENCIES std_msgs sensor_msgs)

  # Declare that this catkin package's runtime dependencies
  catkin_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 package
  add_executable(does_not_use_local_messages_program src/main.cpp)
  add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})

施工中的第n个坑

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泠山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值