文章目录
ros中CmakeLists构建的一些关键
1. find_package的作用
我们知道,大部分二进制安装的头文件都在/opt/ros/版本号/include/ 库文件都在/opt/ros/版本号/lib 里。而catkin_make在编译过程中会自动从这两个目录下寻找头文件和库文件。我们甚至可以在当前包的头文件中#include <nav_msgs/Odometry.h>而不在CmakeLists中 find_package(nav_msgs)。但这样做是有弊端的。
find_package()的主要作用是根据查找的结果创建CMake环境变量。
-
<NAME>_FOUND
:当库被查找到时置为true,否则为false -
<NAME>_INCLUDE_DIRS
或<NAME>_INCLUDES
:软件包导出的头文件路径 -
<NAME>_LIBRARIES
或<NAME>_LIBS
:软件包导出的库的路径 -
<NAME>_DEFINITIONS
:?也就是说,当你使用find_package时,返回的_INCLUDE_DIRS是所查找包cmake文件导出的头文件路径,而不仅仅是查找包的头文件路径。
以cv_bridge 包为例,如果你不在CmakeLists中查找cv_bridge,而是直接在头文件中包含#include <cv_bridge/cv_bridge.h>。编译时就会报无法找到opencv头文件的错误。因为系统只是在/opt/ros/版本号/include/ 目录下找到了相应的cv_bridge头文件,但并没有将opencv的头文件目录纳入寻找范围。而如果使用find_package,这是因为cv_bridge cmake文件输出的头文件目录也包括了opencv的头文件目录。
2. find_package会递归查找包吗
假设path_searching这个包find_package了plan_env这个包。而Bspline这个包又使用了path_searching这个包,那是否能够只find_package(path_searching)这个包呢。 很遗憾,如果没有额外操作的话,这是行不通的。因为find_package会根据查找包的cmake文件来返回相关环境变量信息。而CMakeList是具有独立性的。正常来说,如果path_searchign 这个包的配置如下:
catkin_package( INCLUDE_DIRS include
LIBRARIES path_searching
CATKIN_DEPENDS
DEPENDS )
那使用find_package(path_searching)所返回的头文件及库文件目录仅是path_searching包的头文件及目录,而不会有plan_env的路径信息。这也就意味着,正常情况下,想要在Bspline包中使用plan_env和path_searching, 必须利用find_package查找path_searching 和 plan_env
3. 能不能不要多次包含
那么,有没有例外呢。是有的
首先, 大多数二进制安装的ros包,如果不依赖于其他第三方库(所谓第三方库,指的是既不在ros目录下,也不系统默认目录下的库), 是可以直接在头文件和源文件中调用而不需要在cmakelist中包含依赖的。
其次,如若是第三方库,我们也可以利用catkin_package中的CATKIN_DEPENDS标签,来避免重复嵌套调用。还是以上述Bspline, path_searching, plan_env三个包为例。
如果我们将path_searchign包CmakeLists中的catkin_package部分改为如下:
catkin_package( INCLUDE_DIRS include
LIBRARIES path_searching
CATKIN_DEPENDS plan_env
DEPENDS )
我们在CATKIN_DEPENDS后加上 plan_env软件包, 这意味着,每次编译,运行path_searching,都需要找到plan_env。
在这之后,我们直接在Bsplined的CmakeList中find_pacakge(path_searching) 而不找plan_env. 并且 在Bspline的package.xml中规定好Bspline依赖于path_searching,让path_searching先于Bspline编译,则我们就可以在Bspline中正常使用这两个包。
4. package.xml定义依赖和编译顺序。
package.xml中主要包含 <buildtool_depend> <build_depend> <build_export_depend> <exec_depend> 这几个标签。
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>path_searching</build_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<build_export_depend>path_searching</build_export_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>path_searching</exec_depend>
其中,我们加入一项 <build_depend>path_searching</build_depend>表示先编译path_searching包再编译本包,由于path_searching.xml同样有<build_depend>plan_env</build_depend>,则plan_env, path_searching, bspline三个包将被顺序编译。