【ROS】CMakeLists.txt文件解析

文章目录


前言

文件CMakeLists.txt是用于构建软件包的 CMake 构建系统的输入。任何兼容 CMake 的包都包含一个或多个 CMakeLists.txt 文件,这些文件描述了如何构建代码以及将其安装到何处。用于 catkin 项目的 CMakeLists.txt 文件是一个标准的 vanilla CMakeLists.txt 文件,带有一些额外的约束。

每个ROS功能包中也都存在一个CMakeLists.txt文件,该文件内容纷繁复杂,本篇文章将对每个功能进行解析。

每个 catkin CMakeLists.txt 文件必须以所需的 CMake 版本开头,Catkin 需要 2.8.3 或更高版本,首先需要在文件开头包含版本声明:

cmake_minimum_required(VERSION 2.8.3)

下一项是 CMake项目函数指定的包的名称,指定了功能包的名称后,可以在文件中使用${PROJECT_NAME } 宏随时使用该变量。

project(robot_brain)

一、依赖的包

1.find_package

然后,我们需要使用 CMake的find_package函数指定需要找到哪些其他 CMake 包来构建我们的项目,如果 CMake 通过 find_package 找到了一个包,它会导致创建几个 CMake 环境变量,这些变量提供有关找到的包的信息。这些环境变量稍后可以在 CMake 脚本中使用。环境变量描述了包导出的头文件在哪里,源文件在哪里,包依赖哪些库,以及这些库的路径,它至少有一个对 catkin 的依赖:

find_package(catkin REQUIRED)

然后我们可以在后面再添加编译和运行过程中使用到的其他功能包,对应于package.xml文件中我们用<depend()>标签指明的功能包:

## Find catkin macros and libraries
find_package(catkin REQUIRED COMPONENTS
  actionlib
  actionlib_msgs
  costmap_2d
  geometry_msgs
  map_msgs
  move_base_msgs
  nav_msgs
  roscpp
  std_msgs
  tf
  visualization_msgs
  exploration_msgs
  dynamic_reconfigure
)

find_package(catkin REQUIRED your_package)函数这样书写好处就是,帮我们省事!在平常我们使用cmake编译文件时,可以使用find_package(your_package)找到需要的功能包,但是这不会包含 catkin 的包含路径,这意味着 your_package的 路径、库等不会添加到 catkin_ 变量中,也就是不会创建your_package_INCLUDE_DIRS、your_package_LIBRARIES 变量。

2.catkin_package

接下来可能会常常看到catkin_package这个函数,它和find_package往往容易搞混,可能会经常有疑问:通过find_package()我们已经完成找头文件和库的目的了,那么catkin_package()要做什么呢?

官方解释是:catkin_package()是catkin提供的CMake宏,用于为catkin提供构建、生成pkg-config和CMake文件所需要的信息。

意思就是find_package负责找依赖路径,catkin_package负责声明编译构建时的依赖信息,如果其他功能包使用本功能包的话,当中会包含我们在本功能包声明的include路径和库,对于DEPENDS依赖项,会将DEPENDS的头文件路径和库添加到本功能包下的include路径和库。

比如:当前我的DEPENS包含了Boost库,当其他功能包调用这个功能包也需要Boost库的时候,就可以不需要再find_package(Boost)

catkin_package(
  CATKIN_DEPENDS
    diagnostic_updater
    dynamic_reconfigure
    geometry_msgs
    nav_msgs
    rosbag
    roscpp
    sensor_msgs
    std_srvs
    tf2
    tf2_msgs
    tf2_ros
  INCLUDE_DIRS include
  LIBRARIES amcl_sensors amcl_map amcl_pf
  DEPENDS Boost
)

它有五个可选参数:

  • INCLUDE_DIRS - 包的导出包含路径

  • LIBRARIES - 从项目中导出的库

  • CATKIN_DEPENDS - 本项目依赖的其他catkin项目

  • DEPENDS - 此项目所依赖的非 catkin CMake 项目。

  • CFG_EXTRAS - 额外的配置选项

二、构建消息、服务、动作

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

如果想编译生成自定义的消息、服务和动作,必须位于catkin_package之前,首先需要在find_package函数中加入message_generation包用于构建消息、服务和动作:

find_package(catkin REQUIRED COMPONENTS message_generation)

然后也需要在catkin_package函数中添加message_runtime 

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

然后使用提供的三个宏来分别处理消息、服务和动作:

  • add_message_files

  • add_service_files

  • add_action_files

add_action_files(
  FILES
  Explore.action
)

add_service_files(
  FILES
  SetPolygon.srv
)

然后使用generation_message函数对它们进行编译,然后如果你的程序中依赖了其他需要构建消息/服务/动作的功能包时,需要在生成可执行文件时添加对目标 catkin_EXPORTED_TARGETS 的显式依赖,以便能够以正确的顺序构建,这种情况一般总是存在的,除非你一点也不用ROS的任何消息/服务/动作,例如你的程序需要依赖move_base包,而move_base包中构建了消息/服务/动作,那么就需要添加这个依赖。

add_dependencies(your_exec ${catkin_EXPORTED_TARGETS})

如果你自己编译的程序使用到了自己构建消息、服务、动作,则需要创建对自动生成的消息目标的显式依赖,以便它们以正确的顺序构建。

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

整体的文件例子如下:

  # 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})

另外,如果想构建动作action时,需要将actionlib_msgs添加到 find_packaged 、generation_message、catking_package的​​组件列表中,在动作机制中有详细说明。

而使用动作的功能包需要将actionlib添加到 find_packaged 、catking_package的​​组件列表中

三、构建目标

构建目标一般有以下两种情况:

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

include_directories()

include_directories 的参数应该是由您的 find_package 调用生成的 *_INCLUDE_DIRS 变量以及需要包含的任何其他目录(一般是我们自己功能包下的include文件夹)

## Specify additional locations of header files
include_directories(
  ${catkin_INCLUDE_DIRS}
  include
)

 add_executable()

要指定必须构建的可执行目标,我们必须使用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/another_file.cpp。

add_executable()

要指定必须构建的可执行目标,我们必须使用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/another_file.cpp。

target_link_libraries()

通常在调用add_executable()之后,使用target_link_libraries()函数指定可执行目标链接到哪些库。

target_link_libraries(<executableTargetName>, <lib1>, <lib2>, ... <libN>)

四、测试和安装

1.测试

测试test设置一般在CMakeLists.txt文件的最后,用于生成测试文件或用于测试链接库是否成功

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_tf_to_tum.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

2.指定可安装目标

在构建时间之后,目标被放置到 catkin 工作区的开发空间中。然而,我们通常希望将目标安装到系统,以便其他人可以使用它们或将它们安装到本地文件夹以测试系统级安装。换句话说,如果你希望能够对你的代码进行“安装”,您需要指定目标应该在哪里安装。

这是使用作为参数的 CMake install()函数完成的:

  • TARGETS - 要安装的目标

  • ARCHIVE DESTINATION- 静态库和 DLL (Windows) .lib 

  • LIBRARY DESTINATION- 非 DLL 共享库和模块

  • RUNTIME DESTINATION - 可执行目标和 DLL (Windows) 样式共享库

3.安装头文件和启动文件

头文件也必须安装到“include”文件夹,这通常是通过安装整个文件夹的文件来完成的(可选择按文件名模式过滤并排除 SVN 子文件夹)。这可以通过如下所示的安装规则来完成:

install(DIRECTORY include/${PROJECT_NAME}/
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  PATTERN ".svn" EXCLUDE
)

 可以将启动文件(launch文件)等其他资源安装到${CATKIN_PACKAGE_SHARE_DESTINATION}:

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


总结

这就是CMakeLists.txt文件的大部分主要功能的解析,其中还有一个generate_dynamic_reconfigure_options()函数没有说到,这个是根动态参数配置相关的,将会在介绍dynamic reconfigure的文章中说到

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值