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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章