catkin_make生成信息的理解 & ROS中的cmakelist.txt

catkin_make生成信息的理解 & ROS中的cmakelist.txt

标签(空格分隔): ROS


src: 代码空间
build: 编译空间,存放编译时生成的中间文件,二进制文件
devel: 开发空间,存放终止编译的可执行文件和环境变量;
install: 安装空间,最终生成的可执行文件,与devel有点类似,但包行了安装指令,ROS编译结果最终安装的地方,类似Windows的Program Files
创建工作空间

ROS使用 python3 https://www.cnblogs.com/h46incon/p/6207145.html?utm_source=itdadao&utm_medium=referral

$ catkin_make
Base path: /home/alex/code_ROS/pkg_template_ws  //基本路径 
Source space: /home/alex/code_ROS/pkg_template_ws/src
Build space: /home/alex/code_ROS/pkg_template_ws/build
Devel space: /home/alex/code_ROS/pkg_template_ws/devel
Install space: /home/alex/code_ROS/pkg_template_ws/install
####
#### Running command: "make cmake_check_build_system" in "/home/alex/code_ROS/pkg_template_ws/build"
####
-- Using CATKIN_DEVEL_PREFIX: /home/alex/code_ROS/pkg_template_ws/devel
-- Using CMAKE_PREFIX_PATH: /opt/ros/melodic //cmake 前缀路径 这个路径就是ros的安装路径
-- This workspace overlays: /opt/ros/melodic //
-- Found PythonInterp: /usr/bin/python2 (found suitable version "2.7.15", minimum required is "2") //ROS支持所支持的python版本
-- Using PYTHON_EXECUTABLE: /usr/bin/python2 //Python2的bin文件 
//python的解释器,回忆python文件的第一行,`#!/usr/bin/python`,即指定该文件用什么语言解释
//这里就解释了为什么ROS默认支持python2

-- Using Debian Python package layout
-- Using empy: /usr/bin/empy
-- Using CATKIN_ENABLE_TESTING: ON
-- Call enable_testing()
-- Using CATKIN_TEST_RESULTS_DIR: /home/alex/code_ROS/pkg_template_ws/build/test_results
-- Found gtest sources under '/usr/src/googletest': gtests will be built
-- Found gmock sources under '/usr/src/googletest': gmock will be built
-- Found PythonInterp: /usr/bin/python2 (found version "2.7.15") 
-- Using Python nosetests: /usr/bin/nosetests-2.7
-- catkin 0.7.19
-- BUILD_SHARED_LIBS is on
-- BUILD_SHARED_LIBS is on
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 1 packages in topological order:
-- ~~  - ros_pkg_template
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'ros_pkg_template'
-- ==> add_subdirectory(ros_package_template)//当前包视作总的catkin package下的一个sub 路径
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/code_ROS/pkg_template_ws/build
####
#### Running command: "make -j8 -l8" in "/home/alex/code_ROS/pkg_template_ws/build"
####
Scanning dependencies of target class_template
[ 50%] Building CXX object ros_package_template/CMakeFiles/class_template.dir/src/class_template.cpp.o
[100%] Linking CXX executable /home/alex/code_ROS/pkg_template_ws/devel/lib/ros_pkg_template/class_template
[100%] Built target class_template

Cmakelist 详解

cmake_minimum_required(VERSION 2.8.3)
project(ros_pkg_template)

## Find catkin macros and libraries
find_package(catkin REQUIRED COMPONENTS
    roscpp
    geometry_msgs
    joy
)

include_directories(${catkin_INCLUDE_DIRS})

catkin_package(INCLUDE_DIRS CATKIN_DEPENDS
    roscpp
    geometry_msgs
    joy
  DEPENDS
)

###########
## Build ##
###########

add_executable(class_template src/class_template.cpp)
target_link_libraries(class_template ${catkin_LIBRARIES})

#############
## Install ##
#############

find_package(…)

参考资料:https://blog.csdn.net/u011092188/article/details/61425924

查找catkin宏和库

find_package(catkin REQUIRED COMPONENTS
    roscpp
    geometry_msgs
    joy
)

为什么要使用find_package?

因为:如果编译软件使用了外部库,事先并不知道它的头文件和链接库的位置(路径)。得在编译命令中加上包含它们的查找路径。CMake使用find_package命令来解决这个问题。如果找到了,就可以在接下来的语句中使用${XXX_INCLUDE_DIRS}${XXX_LIBRARIES}这两个变量,将我们自己写的cpp文件链接这些库。(这种变量名应该是很常见了吧~)

这让我想起了自己当初的一些骚操作,最开始没搞明白这些关系的时候,自己调用的库编译总通过不了,索性干脆#inclue头文件的时候使用绝对路径,链接.so库的时候直接把绝对路径写进去,也是傻得不行。。。

那么,计算机如何找到这些库和头文件的路径的呢?

首先需要知道的是,${XXX_INCLUDE_DIRS}${XXX_LIBRARIES}这两个变量是需要定义的,那么他们的定义是由谁完成的呢?答案就是.cmake文件,在.cmake文件里。一共有两个.cmake文件对这两个变量进行了定义,分别是FindXXX.cmakeXXXConfig.cmake(为什么是两个,这个下面会讲到),所以只要找到了.cmake文件,就能定义以上两个变量。

那么cmake文件去哪里找?

我们以一个开源库ceres为例,下载下来之后,里面紧接着必然有一个cmake文件夹,与之并列的还有cmakelist.txt。我们往常的正常操作是同目录下新建build文件夹,cd进去然后cmake ..,执行上一级的cmakelist.txt。然后我们发现,在cmake文件夹中,有一堆的FindXXX.cmake,比如FindEigen.cmake,FindGlog.cmake等(这些都是ceres库在运行的时候用到的其他库。)这样编译的时候,自然直接就找到了.cmake文件。

当然你可能会问,这是开源库,人家自己添加了cmake文件夹,里面有FindXXX.cmake之类的文件,我们使用的ROS的package可没有单独的添加cmake文件夹,直接就在cmakelist.txt中find_package(catkin)了。编译的时候直接就catkin_make就完事了,也没主动提供Findcatkin.cmake文件啊!
这就涉及到find_package()的查找*.cmake的顺序问题:

说到查找*.cmake的顺序问题就不得不提到cmake的两种模式:

  • Module模式:搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件,执行该文件从而找到XXX库。其中,具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由FindXXX.cmake模块完成。
  • Config模式:搜索XXX_DIR指定路径下的XXXConfig.cmake文件,执行该文件从而找到XXX库。其中具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成。
  • 不特殊指定的话find_package()执行的是Module模式

1、 find_package()命令首先会在模块路径中寻找FindXXX.cmake,这是查找库的一个典型方式。具体查找路径依次为变量${CMAKE_MODULE_PATH}中的所有目录。如果没有,然后再查看它自己的模块目录 /share/cmake-x.y/Modules/${CMAKE_ROOT}的具体值可以通过CMake中message命令输出)。这里先运行的是模块模式。
2、 如果没找到这样的文件,find_package()会在~/.cmake/packages/或/usr/local/share/中的各个包目录中查找,寻找<库名字的大写>Config.cmake 或者 <库名字的小写>-config.cmake (比如库Opencv,它会查找/usr/local/share/OpenCV中的OpenCVConfig.cmake或opencv-config.cmake)。这里执行配置模式。

总结:所以,定义${XXX_INCLUDE_DIRS}${XXX_LIBRARIES}两个变量的,不止可以是FindXXX.cmake,也可以是XXXConfig.cmake。

也就是说,Findcatkin.cmake这个文件,系统会根据两种模式自动去一些路径里面找它。但是我们搜索发现,电脑里面并没有Findcatkin.cmake这个文件,那么${catkin_LIBRARIES}${catkin_INCLUDE_DIRS}两个变量又是如何定义的呢?

说到这里,就不得不提到我们刚学ROS时候那句经典的命令了$ source /opt/ros/Kinect/setup.bash,这句命令帮我们定义了一些ROS相关的环境变量。包括在我们自己的操作空间下执行source devel/setup.zsh等操作。这些环境变量,就能够帮助cmake找到ROS相关的package路径:

那么环境变量有哪些?我们可以运行$ env env,列出当前系统的所有环境变量,找到和ROS相关的环境变量如下:

ROS_DISTRO=melodic
ROS_ETC_DIR=/opt/ros/melodic/etc/ros
ROS_PACKAGE_PATH=/opt/ros/melodic/share
ROS_PYTHON_VERSION=2
ROS_VERSION=1
ROS_ROOT=/opt/ros/melodic/share/ros
ROS_MASTER_URI=http://localhost:11311

找到我们关心的ROS_PACKAGE_PATH,点进去看一下,我们可以看到ROS自带的各种各样的库的名字(roslaunch,rosbag等等)
随便找一个进去看一下(rosbag):

# alex @ alex in /opt/ros/melodic/share/rosbag [10:13:09] 
$ ls
cmake  package.xml

看,果然有一个cmake文件夹,点进去瞅一眼:

# alex @ alex in /opt/ros/melodic/share/rosbag/cmake [10:13:57] 
$ ls
rosbagConfig.cmake  rosbagConfig-version.cmake

到此,我们已经能够解释所有的ROS的catkin相关的包在编译的时候如何找到的问题。

回到最开始的一个问题,${catkin_LIBRARIES}${catkin_INCLUDE_DIRS}两个变量的值都是什么?我们可以在cmakelist.txt中使用message(“INFO: catkin_LIBRARIES value is ${catkin_LIBRARIES}”)将两个变量的值都打出来看一下:

${catkin_LIBRARIES}#value is /opt/ros/melodic/lib/libroscpp.so;/usr/lib/x86_64-linux-gnu/libboost_filesystem.so;/usr/lib/x86_64-linux-gnu/libboost_signals.so;/opt/ros/melodic/lib/librosconsole.so;/opt/ros/melodic/lib/librosconsole_log4cxx.so;/opt/ros/melodic/lib/librosconsole_backend_interface.so;/usr/lib/x86_64-linux-gnu/liblog4cxx.so;/usr/lib/x86_64-linux-gnu/libboost_regex.so;/opt/ros/melodic/lib/libxmlrpcpp.so;/opt/ros/melodic/lib/libroscpp_serialization.so;/opt/ros/melodic/lib/librostime.so;/opt/ros/melodic/lib/libcpp_common.so;/usr/lib/x86_64-linux-gnu/libboost_system.so;/usr/lib/x86_64-linux-gnu/libboost_thread.so;/usr/lib/x86_64-linux-gnu/libboost_chrono.so;/usr/lib/x86_64-linux-gnu/libboost_date_time.so;/usr/lib/x86_64-linux-gnu/libboost_atomic.so;/usr/lib/x86_64-linux-gnu/libpthread.so;/usr/lib/x86_64-linux-gnu/libconsole_bridge.so.0.4
${catkin_INCLUDE_DIRS}:#WARNING: catkin_INCLUDE_DIRS /opt/ros/melodic/include;/opt/ros/melodic/share/xmlrpcpp/cmake/…/…/…/include/xmlrpcpp;/usr/include

以rosbag为例,分别是库地址:/opt/ros/melodic/lib/

$ locate librosbag.so
/opt/ros/melodic/lib/librosbag.so

include的头文件地址:/opt/ros/melodic/include/

$ ls rosbag 
bag.h           constants.h   message_instance.h  stream.h
bag_player.h    encryptor.h   player.h            structures.h
buffer.h        exceptions.h  query.h             time_translator.h
chunked_file.h  macros.h      recorder.h          view.h

实际上在使用Clion的时候,就会提示Could not find module Findcatkin.cmake or a configuration file for package catkin。查看我们配置的clion的启动项
Exec="/home/alex/Software/CLion-2019.2.5/clion-2019.2.5/bin/clion.sh" %f
Exec= zsh -i -c “/home/alex/Software/CLion-2019.2.5/clion-2019.2.5/bin/clion.sh” %f
加载环境变量source /opt/ros/melodic/setup.zsh
具体内容如下:

#!/usr/bin/env zsh
# generated from catkin/cmake/templates/setup.zsh.in

CATKIN_SHELL=zsh

# source setup.sh from same directory as this file
_CATKIN_SETUP_DIR=$(builtin cd -q "`dirname "$0"`" > /dev/null && pwd)
emulate -R zsh -c 'source "$_CATKIN_SETUP_DIR/setup.sh"'

参考:https://blog.csdn.net/robinhjwy/article/details/79597095
这里又涉及到了rospack profile

备注:XXX_DIR变量需要在执行Find_package之前定义,比如set(Caffe_DIR /home/xxx/caffe/build),这个路径下包含的就是所需要的.cmake文件
引用自定义的caffe路径:

set(Caffe_DIR /home/caffe/build)   #添加CaffeConfig.cmake的搜索路径

find_package(Caffe REQUIRED)

if (NOT Caffe_FOUND)
    message(FATAL_ERROR "Caffe Not Found!")
endif (NOT Caffe_FOUND)

include_directories(${Caffe_INCLUDE_DIRS})

add_executable(useSSD ssd_detect.cpp)
target_link_libraries(useSSD ${Caffe_LIBRARIES})

其实不管使用哪一种模式,只要找到*.cmake,*.cmake里面都会定义下面这些变量:

<NAME>_FOUND
<NAME>_INCLUDE_DIRS or <NAME>_INCLUDES
<NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS
<NAME>_DEFINITIONS
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章