ROS CMakeLists.txt的編寫學習

調用ROS中的函數,cmakelists的編寫學習過程。如有錯誤,請留言指教。多謝

A.首先要了解的

 

 

 
        CMakeLists.txt是CMake的構建系統構建軟件包的輸入文件。任何兼容的CMake都包含了描述如何構建代碼,並在根目錄及子目錄進行安裝到一個或多個的CMakeLists.txt文件。用於catkin項目的CMakeLists.txt文件是有一些限制標準格式。

B.整體的結構及排序
 

                    自己編寫的CMakeLists.txt必須遵循一定的格式,否則庫文件無法正確編譯的。cmake的一些命令都是按照一定的順序編寫的。

 

 

  1. Required CMake Version (cmake_minimum_required)//cmake版本

  2. Package Name (project()) //項目名稱

  3. Find other CMake/Catkin packages needed for build (find_package()) //需要的庫文件

  4. Message/Service/Action Generators (add_message_files(), add_service_files(), add_action_files()) //輸出的信息,服務,及生成的東西

  5. Invoke message/service/action generation (generate_messages()) //生成信息~~~

  6. Specify package build info export (catkin_package()) //catkin的庫文件

  7. Libraries/Executables to build (add_library()/add_executable()/target_link_libraries()) //庫文件,生成文件及路徑

  8. Tests to build (catkin_add_gtest())

  9. Install rules (install())

C.cmake版本

 

 

       每一個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自動添加的。

 

       (未完待續)

 

 

 

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