調用ROS中的函數,cmakelists的編寫學習過程。如有錯誤,請留言指教。多謝
A.首先要了解的
B.整體的結構及排序
-
Required CMake Version (cmake_minimum_required)//cmake版本
-
Package Name (project()) //項目名稱
-
Find other CMake/Catkin packages needed for build (find_package()) //需要的庫文件
-
Message/Service/Action Generators (add_message_files(), add_service_files(), add_action_files()) //輸出的信息,服務,及生成的東西
-
Invoke message/service/action generation (generate_messages()) //生成信息~~~
-
Specify package build info export (catkin_package()) //catkin的庫文件
-
Libraries/Executables to build (add_library()/add_executable()/target_link_libraries()) //庫文件,生成文件及路徑
-
Tests to build (catkin_add_gtest())
-
Install rules (install())
每一個Catkin(catkin是ROS的一個官方的編譯構建系統)的cmakelist的編寫都是要從版本開始的。catkin對cmake的要求至少是2.8.3以上的
具體的命令比如:
cmake_minimum_required(VERSION 2.8.3)D。項目名
接下來就要寫有Cmake函數指定的項目的名稱。比如建立一個工程名,叫robot_brain
project(robot_brain)
E尋找Cmake依賴庫
接下來,我們用CMake find_package函數來發現其他的指定的Cmake指令,來建立我們自己的項目。調用ROS,至少需要catkin的依賴庫
find_package(catkin REQUIRED)如果你的工程裏面呢,只用到了一些庫,那麼就會轉變爲catkin的一些函數。不用使用find_package函數來找到所有的庫文件,只需要像函數一樣指定他們就可以了。這樣會更簡單一些。舉個例子,如果你像用nodelet.函數呢
find_package(catkin REQUIRED COMPONENTS nodelet)需要注意的是:如果你只用find_package來找到一些函數來設置一個標誌,那麼就不能用runtime的依賴項了。而是應該像下面一樣:
find_package(catkin REQUIRED) find_package(nodelet REQUIRED)
E.a find_package函數講解
如果通過CMake的find_package函數來找到庫文件的話,就找到一些庫文件的信息並且會創建一些環境變量,這些環境變量可以在稍後的Cmake腳本里面被利用到。這些環境變量描述了頭文件的輸出位置,源文件的位置,庫文件的依賴項以及庫文件的位置。指令大部分是下面這樣<PACKAGE NAME>_<PROPERTY>(文件名+屬性)
E.b 爲什麼Catkin的庫文件要被當做組件?
carkin的庫文件並不是組件,而cmake組件的功能則用來catkin的設計,能夠顯著節省打字時間的。
對於catkin的庫文件呢,如果進行一個簡單的環境變量的設置,用find_package函數作爲catkin部件調用,相比之下利用catkin_ prefix函數來進行調用還是有優勢的。舉個例子,假如在源碼中你要使用nodelet函數的話,找到這個庫文件的方法可以這樣寫
find_package(catkin REQUIRED COMPONENTS nodelet)這意味着nodelet的包含路徑、庫路徑以及一些輸出等等都附加給了catkin的變量了。舉個例子,catkin_INCLUDE_DIRS包含的包含路徑,並不僅僅catkin,也包含了nodelet。這個以後會排上很到用場。
我們也可以用find_package來找到nodelet
find_package(nodelet)
這意味着nodelet的路徑,庫路徑等等不會添加到catkin的變量中。
結果保留在nodelet_INCLUDE_DIRS,nodelet_LIBRARIES等等。其他的變量也可以使用這個函數來創建
find_package(catkin REQUIRED COMPONENTS nodelet)
E.c boost庫
如果使用C++和boost庫的話,需要調用find_package()函數用於boost,並指定boost的什麼方面要用作組件。
find_package(Boost REQUIRED COMPONENTS thread)
F.catkin_package()
catkin_package()是Cmake定義的宏,這就需要指定catkin特殊的信息來建立系統,反過來pkg-config 和CMake files。
這個函數必須在聲明任何目標文件(add_library() o和add_executable())前進行調用,這個函數有5個參數。
1.INCLUDE_DIRS - The exported include paths (i.e. cflags) for the package//包含路徑
2.LIBRARIES - The exported libraries from the project//項目輸出的庫文件
3.CATKIN_DEPENDS - Other catkin projects that this project depends on//這個項目調用的其他的catkin項目
4.DEPENDS - Non-catkin CMake projects that this project depends on//這個項目調用其他的cmake項目
5.CFG_EXTRAS - Additional configuration options//添加配置選項
舉個例子
catkin_package( INCLUDE_DIRS include LIBRARIES ${PROJECT_NAME} CATKIN_DEPENDS roscpp nodelet DEPENDS eigen opencv)這表明,“include”路徑包含頭文件的輸出路徑。Cmake的環境變量${PROJECT_NAME}評價時候能更早的通過project()的編譯。在這個例子中呢,這個變量就是"robot_brain"."roscpp" + "nodelet"是需要立即被編譯/運行的庫文件,"eigen" + "opencv"是系統依賴項,需要立即運行的。
G.指定建立目標
目標的建立有很多種形式,但是通常呢,表現爲以下兩種形式
生成可執行文件-我們自己可以運行
庫文件目標-在編譯或者運行的時候可以被可執行文件調用。
G.a 目標命名格式
需要注意的是:catkin目標文件的名字,必須唯一的,不考慮編譯或安裝的文件夾的名稱。這是cmake的要求。然而唯一的名字僅僅是cmake的內部要求。使用set_target_properties()函數就可以將目標修改爲其他的名字。舉個例子
set_target_properties(rviz_image_view PROPERTIES OUTPUT_NAME image_view PREFIX "")這樣就在編譯和安裝的時候將目標名rviz_image_view改爲image_view
G.b習慣的輸出路徑
通常,執行文件和庫文件默認的輸出路徑爲catkin文件夾下合理的專門的路徑。比如一個包含python的的函數,那麼一定會創建一個不同的文件夾來導入python。
舉個例子:
set_target_properties(python_module_library PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})
G.c包含路徑和庫路徑
首先定義目標,首先需要定義源文件的位置,尤其是頭文件和庫文件的位置
1.Include Paths-Where can header files be found for the code (most common in C/C++) being built//代碼(大部分是c++/c)需要用到的頭文件的位置
2.Library Paths - Where are libraries located that executable target build against?//可執行目標文件編譯時庫文件的位置
3.include_directories(<dir1>, <dir2>, ..., <dirN>)//包含目錄
4.link_directories(<dir1>, <dir2>, ..., <dirN>)//庫目錄
G.c.1包含目錄
include_directories應該是*_INCLUDE_DIRS自己編寫的find_package包含的以及其他添加的目錄所包含的內容產生的。如果在用catkin以及boost,那麼你的include_directories應該是這樣的:
include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})第一個include指出這個庫的include/directorise也是這個路徑的一部分。
G.c.2鏈接目錄
cmake的link_directories()函數也可以用來添加附加庫路徑,但這是不推薦的。所有的catkin以及cmake的庫再用find_packaged調用時,都自帶他們自己的鏈接路徑。target_link_libraries()進行簡單的鏈接。
舉個例子:
link_directories(~/my_libs)
G.d 可執行文件目錄
我們用CMake的add_executable()函數,來對編譯的可執行文件進行指定。
add_executable(myProgram src/main.cpp src/some_file.cpp src/another_file.cpp)這個指令會產生一個可執行文件,叫做myProgram。包含三個cpp原文件,main,some_file,another_file。
G.f庫目錄
Cmake的add_library()函數,用來添加特殊的庫。
add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
G .e 鏈接目錄
使用target_link_libraries() 函數,將庫和可執行文件鏈接起來。一般在調用add_executable()函數之後使用。
target_link_libraries(<executableTargetName>, <lib1>, <lib2>, ... <libN>)舉個例子:
add_executable(foo src/foo.cpp) add_library(moo src/moo.cpp) target_link_libraries(foo moo) -- This links foo against libmoo.so在大多數的情況下呢,不用使用link_directories()函數,因爲這個鏈接會通過函數find_packages自動添加的。
(未完待續)