ROS知识: vanilla(香草) CMakeLists.txt 的语法
(catkin/CMakeLists.txt - ROS Wiki)
前言
首先,對(duì)于學(xué)習(xí)ROS,CMakeLists.txt 的語(yǔ)法非常重要;如果不懂將無(wú)法開(kāi)發(fā)!而要想明白?vanilla(香草) CMakeLists.txt 的語(yǔ)法,首先需要掌握常規(guī)Cmake語(yǔ)法。
第一章 概述
我們知道,Cmake是關(guān)于編譯的事情;然而對(duì)于不同的Cmake各有其方言,需要獨(dú)立查閱理解;本篇專(zhuān)門(mén)針對(duì)ROS版本的Cmake語(yǔ)法進(jìn)行敘述;在讀本文之前,期望讀者已經(jīng)理解如下幾個(gè)文章:C語(yǔ)言編譯:CMakeLists.txt語(yǔ)句? 等。 ??
本片針對(duì)文件CMakeLists.txt文件,講述以下四個(gè)方面。
- CMakeList.txt的固定格式,
- 以及這些固定格式的內(nèi)涵。
- 以及如何去修改添加自己的CMakeList.txt文件。
- 最后通過(guò)實(shí)例講解細(xì)節(jié)。
第二章 CMakeList.txt約定順序和結(jié)構(gòu)
文件CMakeLists.txt是用于構(gòu)建軟件包的CMake構(gòu)建系統(tǒng)的輸入。任何符合CMake的軟件包都包含一個(gè)或多個(gè)CMakeLists.txt文件,該文件描述如何構(gòu)建代碼以及將代碼安裝到何處?用于catkin項(xiàng)目的CMakeLists.txt文件是標(biāo)準(zhǔn)的香草CMakeLists.txt文件,帶有一些獨(dú)特的約束。
注意:您的CMakeLists.txt文件必須遵循下面格式,否則您的包將無(wú)法正確生成。配置中的順序如下。
-
Required CMake Version (cmake_minimum_required)
????????????????????? 指定編譯器版本
-
Package Name (project())
????????????????????? 指定項(xiàng)目名稱(chēng)
-
Find other CMake/Catkin packages needed for build (find_package())
????????????????????? 查找其他依賴(lài)包
-
Enable Python module support (catkin_python_setup())
????????????????????? 包含python支持
-
Message/Service/Action Genera2.3tors
?????? ? ? ? ? ? ? ? ? 加入用戶定義的消息格式文件
(add_message_files(),?add_service_files(),?add_action_files())
-
Invoke message/service/action generation (generate_messages())
???????????????????? 喚醒消息等。
-
Specify package build info export (catkin_package())
??????????????????? 應(yīng)用包信息導(dǎo)出。
-
Libraries/Executables to build (add_library()/add_executable()/target_link_libraries())
??????????????????? 指定庫(kù)路徑
-
Tests to build (catkin_add_gtest())
????????????????????? 指定測(cè)試路徑
-
Install rules (install())
??????????????????? 安裝規(guī)則
以上就是標(biāo)準(zhǔn)的CMakeList.txt文件格式。
第三章? CMake版本指定
?每個(gè)catkin CMakeLists.txt文件必須以所需的CMake版本開(kāi)始。Catkin需要2.8.3或更高版本。
cmake_minimum_required(VERSION 2.8.3)
第四章 指定包名稱(chēng)
下一項(xiàng)是由CMake項(xiàng)目功能指定的包的名稱(chēng)。假設(shè)我們正在制作一個(gè)名為robot_brain的軟件包。
注意:在CMake中,您可以在以后CMake腳本中的任何位置引用項(xiàng)目名稱(chēng),只要需要,就可以使用變量${project_name}。此語(yǔ)句還有隱含的效果,那就是將生成如下的變量:
robot_brain_BINARY_DIR 和 robot_brain_SOURCE_DIR,同時(shí),cmake 自動(dòng)定義了兩個(gè)等價(jià)的名稱(chēng)變量 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR。
第五章? 查找依賴(lài)的CMake包
然后,我們需要指定需要找到哪些其他CMake包來(lái)使用CMake find_package函數(shù)構(gòu)建我們的項(xiàng)目。catkin始終至少有一個(gè)依賴(lài)項(xiàng):
以上:catkin是被搜索的項(xiàng),REQUIRED表示前面的catkin的必須項(xiàng)目;
如果您的項(xiàng)目依賴(lài)于其他外來(lái)包,則它們會(huì)自動(dòng)轉(zhuǎn)換為katkin(柳絮)的組件(就CMake而言)。如果您將這些包指定為組件,而不是在這些包上使用find_包,這將使工作更輕松。例如,如果使用包nodelet。
find_package(catkin REQUIRED COMPONENTS nodelet)注意:不應(yīng)添加運(yùn)行時(shí)依賴(lài)項(xiàng)在這里,應(yīng)該是編譯時(shí)的依賴(lài)項(xiàng)。
你也可以這樣做:(然而,你會(huì)發(fā)現(xiàn)這不太方便)
5.1 find_package()的作用是什么?
如果CMake通過(guò)find_package找到一個(gè)包,它將導(dǎo)致創(chuàng)建幾個(gè)CMake環(huán)境變量,這些變量提供有關(guān)找到的包的信息。這些環(huán)境變量可以稍后在CMake腳本中使用。環(huán)境變量描述導(dǎo)出的頭文件所在的包、源文件所在的位置、包所依賴(lài)的庫(kù)以及這些庫(kù)的路徑。名稱(chēng)始終遵循<PACKAGE NAME>的約定。
-
<NAME>_FOUND - Set to true if the library is found, otherwise false
-
<NAME>_INCLUDE_DIRS or <NAME>_INCLUDES - The include paths exported by the package
-
<NAME>_LIBRARIES or <NAME>_LIBS - The libraries exported by the package
-
<NAME>_DEFINITIONS - ?
5.2 為什么將Catkin-parkage指定為組件?
Catkin packages不是Catkin的真正組成部分。更確切地說(shuō),CMake的組件特性被用于Catkin的設(shè)計(jì)中,以節(jié)省大量的打字時(shí)間。
對(duì)于catkin包,如果您發(fā)現(xiàn)將它們打包為catkin的組件,這是有利的,因?yàn)槭褂胏atkin前綴創(chuàng)建了一組環(huán)境變量。例如,假設(shè)您在代碼中使用了包nodelet。查找包的建議方法是:
find_package(catkin REQUIRED COMPONENTS nodelet)這意味著nodelet導(dǎo)出的include路徑、庫(kù)等也會(huì)附加到catkin變量。例如,catkin_INCLUDE_DIRS不僅包含catkin的包含路徑,還包含nodelet的包含路徑!這將在以后派上用場(chǎng)。
相反地說(shuō):我們也可以自己找? find_package找到nodelet:
find_package(nodelet)
這意味著節(jié)點(diǎn)路徑、庫(kù)等不會(huì)添加到catkin變量中。這將導(dǎo)致nodelet_INCLUDE_DIRS、nodelet_LIBRARIES。
為了將少管理一些變量,用:
find_package(catkin REQUIRED COMPONENTS nodelet)
將那些變量集中收集到catkin_INCLUDE_DIRS和catkin_LIBRARIES內(nèi)部。
5.3 調(diào)用Boost
如果使用C++和Boost,則需要調(diào)用Booost上的FundPulkAuthor(),并指定您使用的Boost的哪些方面作為組件。例如,如果您想使用Boost線程,您這樣寫(xiě):
find_package(Boost REQUIRED COMPONENTS thread)第六章 catkin_package()
是catkin提供的CMake宏。這是為構(gòu)建系統(tǒng)指定特定于柳絮的信息所必需的,而構(gòu)建系統(tǒng)又用于生成pkg config和CMake文件。
在使用add_library()或add_executable()聲明任何目標(biāo)之前,必須調(diào)用此函數(shù)。該函數(shù)有5個(gè)可選參數(shù):
- INCLUDE_DIRS-導(dǎo)出的包的INCLUDE路徑(即cflags)
- LIBRARIES-從項(xiàng)目中導(dǎo)出的庫(kù)
- CATKIN_DEPENDS-此項(xiàng)目依賴(lài)的其他CATKIN項(xiàng)目
- DEPENDS-此項(xiàng)目所依賴(lài)的非catkin CMake項(xiàng)目。要更好地理解,請(qǐng)參閱此說(shuō)明。
- CFG_EXTRAS-其他配置選項(xiàng)
可以找到完整的宏文檔。
catkin_package(INCLUDE_DIRS includeLIBRARIES ${PROJECT_NAME}CATKIN_DEPENDS roscpp nodeletDEPENDS eigen opencv)這表示包文件夾中的文件夾“include”是導(dǎo)出的標(biāo)題所在的位置。CMake環(huán)境變量${PROJECT_NAME}的計(jì)算結(jié)果與前面?zhèn)鬟f給PROJECT()函數(shù)的值相同,在本例中,它將是“robot_brain”。“roscpp”+“nodelet”是構(gòu)建/運(yùn)行此軟件包所需的軟件包,“eigen”+“opencv”是構(gòu)建/運(yùn)行此軟件包所需的系統(tǒng)依賴(lài)項(xiàng)。
第七章? 指定構(gòu)建目標(biāo)
構(gòu)建目標(biāo)可以有多種形式,但通常它們代表兩種可能性之一:
- 可執(zhí)行目標(biāo)-我們可以運(yùn)行的程序
- 庫(kù)目標(biāo)—可由可執(zhí)行目標(biāo)在生成和/或運(yùn)行時(shí)使用的庫(kù)
7.1 目標(biāo)命名
請(qǐng)務(wù)必注意,catkin中構(gòu)建目標(biāo)的名稱(chēng)必須是唯一的,無(wú)論它們構(gòu)建/安裝到哪個(gè)文件夾。這是CMake的一個(gè)要求。但是,唯一的目標(biāo)名稱(chēng)僅在CMake內(nèi)部需要。可以使用set_target_properties()函數(shù)將目標(biāo)重命名為其他對(duì)象:
set_target_properties(rviz_image_viewPROPERTIES OUTPUT_NAME image_viewPREFIX "")這將在生成和安裝輸出中將目標(biāo)rviz_image_視圖的名稱(chēng)更改為image_視圖。
7.2 自定義輸出目錄
雖然可執(zhí)行文件和庫(kù)的默認(rèn)輸出目錄通常設(shè)置為合理的值,但在某些情況下必須對(duì)其進(jìn)行自定義。即,包含Python綁定的庫(kù)必須放在不同的文件夾中,才能在Python中導(dǎo)入:
例子:
set_target_properties(python_module_libraryPROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})7.3 包括路徑和庫(kù)路徑
在指定目標(biāo)之前,您需要指定在何處可以找到所述目標(biāo)的資源,特別是頭文件和庫(kù):
例子:
- Include Paths - Where can header files be found for the code (most common in C/C++) being built
- Library Paths - Where are libraries located that executable target build against?
-
include_directories(<dir1>,?<dir2>,?...,?<dirN>)
-
link_directories(<dir1>,?<dir2>,?...,?<dirN>)
7.4 包含目錄()
include_目錄的參數(shù)應(yīng)該是find_包調(diào)用生成的*_include_DIRS變量以及需要包含的任何其他目錄。如果您使用的是catkin和Boost,那么include_directories()調(diào)用應(yīng)該如下所示:
例子:
include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})第一個(gè)參數(shù)“include”表示包中的include/目錄也是路徑的一部分。
link_directories(~/my_libs)請(qǐng)參閱此cmake線程以查看在鏈接目錄link_directories().上使用目標(biāo)鏈接庫(kù)target_link_libraries()的詳細(xì)示例。
7.5 可執(zhí)行目標(biāo)
要指定必須構(gòu)建的可執(zhí)行目標(biāo),必須使用add_executable()CMake函數(shù)。
add_executable(myProgram src/main.cpp src/some_file.cpp src/another_file.cpp)這將構(gòu)建一個(gè)名為myProgram的目標(biāo)可執(zhí)行文件,該文件由3個(gè)源文件構(gòu)建:src/main.cpp、src/some_file.cpp和src/other_file.cpp。
7.6 庫(kù)目標(biāo)
add_library()CMake函數(shù)用于指定要生成的庫(kù)。默認(rèn)情況下,catkin構(gòu)建共享庫(kù)。
add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})7.7 目標(biāo)鏈接庫(kù)
使用target_link_libraries()函數(shù)指定可執(zhí)行目標(biāo)鏈接所針對(duì)的庫(kù)。這通常在add_executable()調(diào)用之后完成。如果未找到ros,則添加${catkin_LIBRARIES}。
語(yǔ)法:
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注意,在大多數(shù)用例中不需要使用link_directories(),因?yàn)檫@些信息是通過(guò)find_package()自動(dòng)拉入的。
第八章 消息、服務(wù)和操作目標(biāo)
ROS包生成和使用ROS中的消息(.msg)、服務(wù)(.srv)和操作(.action)文件之前,需要特殊的預(yù)處理器生成步驟。這些宏的要點(diǎn)是生成特定于編程語(yǔ)言的文件,以便可以使用所選編程語(yǔ)言中的消息、服務(wù)和操作。構(gòu)建系統(tǒng)將使用所有可用的生成器(例如gencpp、genpy、genlisp等)生成綁定。
提供了三個(gè)宏分別處理消息、服務(wù)和操作:
-
add_message_files
-
add_service_files
-
add_action_files
然后,必須在這些宏之后調(diào)用調(diào)用生成的宏:
generate_messages()8.1 重要的先決條件/限制
?這些宏必須位于catkin_package()宏之前,才能正確生成。
find_package(catkin REQUIRED COMPONENTS ...)add_message_files(...)add_service_files(...)add_action_files(...)generate_messages(...)catkin_package(...)...您的catkin_package()宏必須具有CATKIN_DEPENDS依賴(lài)于消息_運(yùn)行時(shí)的依賴(lài)項(xiàng)。?
catkin_package( find_package(catkin REQUIRED COMPONENTS message_generation) ...CATKIN_DEPENDS message_runtime ......)?必須單獨(dú)使用find_package()生成包消息,或?qū)⑵渥鳛閏atkin的一個(gè)組件:
find_package(catkin REQUIRED COMPONENTS message_generation)您的package.xml文件必須包含對(duì)消息\u生成的生成依賴(lài)項(xiàng)和對(duì)消息\u運(yùn)行時(shí)的運(yùn)行時(shí)依賴(lài)項(xiàng)。如果依賴(lài)項(xiàng)是通過(guò)傳遞方式從其他包中拉入的,則不需要這樣做。
如果您有一個(gè)目標(biāo)(甚至是可傳遞的)依賴(lài)于需要構(gòu)建消息/服務(wù)/操作的其他目標(biāo),則需要添加對(duì)目標(biāo)catkin\u導(dǎo)出的\u目標(biāo)的顯式依賴(lài),以便它們以正確的順序構(gòu)建。這種情況幾乎總是適用的,除非你的軟件包真的沒(méi)有使用ROS的任何部分。不幸的是,此依賴(lài)項(xiàng)無(wú)法自動(dòng)傳播。(some_target是由add_executable()設(shè)置的目標(biāo)的名稱(chēng)):
add_dependencies(some_target ${catkin_EXPORTED_TARGETS})如果您有一個(gè)構(gòu)建消息和/或服務(wù)的包以及使用這些消息和/或服務(wù)的可執(zhí)行文件,則需要在自動(dòng)生成的消息目標(biāo)上創(chuàng)建一個(gè)顯式依賴(lài)項(xiàng),以便以正確的順序構(gòu)建它們。(some_target是由add_executable()設(shè)置的目標(biāo)的名稱(chēng)):
add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS})如果您的包同時(shí)滿足上述兩個(gè)條件,則需要添加兩個(gè)依賴(lài)項(xiàng),即:
add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})8.2 實(shí)例
如果您的包在名為“MyMessage1.msg”和“MyMessage2.msg”的目錄中有兩條消息,并且這些消息依賴(lài)于std_msgs和sensor_msgs,則名為“MyService.srv”的目錄中名為“srv”的服務(wù)定義了使用這些消息和服務(wù)的可執(zhí)行消息程序,而可執(zhí)行文件不使用本地消息程序,它使用ROS的某些部分,但不使用此包中定義的消息/服務(wù),那么您需要在CMakeLists.txt中提供以下內(nèi)容:
# Get the information about this package's buildtime dependenciesfind_package(catkin REQUIREDCOMPONENTS message_generation std_msgs sensor_msgs)# Declare the message files to be builtadd_message_files(FILESMyMessage1.msgMyMessage2.msg)# Declare the service files to be builtadd_service_files(FILESMyService.srv)# Actually generate the language-specific message and service filesgenerate_messages(DEPENDENCIES std_msgs sensor_msgs)# Declare that this catkin package's runtime dependenciescatkin_package(CATKIN_DEPENDS message_runtime std_msgs sensor_msgs)# define executable using MyMessage1 etc.add_executable(message_program src/main.cpp)add_dependencies(message_program ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})# define executable not using any messages/services provided by this packageadd_executable(does_not_use_local_messages_program src/main.cpp)add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})此外,如果您希望構(gòu)建actionlib操作,并且在“action”目錄中有一個(gè)名為“MyAction.action”的操作規(guī)范文件,則必須將actionlib\u MSG添加到使用catkin打包的組件列表中,并在調(diào)用之前添加以下調(diào)用以生成\u消息(…):
add_action_files(FILESMyAction.action )此外,包必須對(duì)actionlib_msgs具有構(gòu)建依賴(lài)關(guān)系。
第九章 啟用Python模塊支持
如果您的ROS包提供了一些Python模塊,那么應(yīng)該創(chuàng)建setup.py文件并調(diào)用
catkin_python_setup()在調(diào)用generate_messages()和catkin_package()之前。
第十章 單元測(cè)試
有一個(gè)特定于catkin的宏,用于處理基于gtest的單元測(cè)試,稱(chēng)為catkin_add_gtest()。
if(CATKIN_ENABLE_TESTING)catkin_add_gtest(myUnitTest test/utest.cpp) endif()第十一章 可選步驟:指定可安裝目標(biāo)
構(gòu)建后,將目標(biāo)放置到catkin工作區(qū)的開(kāi)發(fā)空間中。但是,我們通常希望將目標(biāo)安裝到系統(tǒng)(有關(guān)安裝路徑的信息可在REP 122中找到),以便其他人或本地文件夾可以使用它們來(lái)測(cè)試系統(tǒng)級(jí)安裝。換句話說(shuō),如果您希望能夠?qū)Υa進(jìn)行“makeinstall”,則需要指定目標(biāo)的最終位置。
這是使用CMake install()函數(shù)完成的,該函數(shù)將以下參數(shù)作為參數(shù):
-
TARGETS - which targets to install
-
ARCHIVE?DESTINATION - Static libraries and DLL (Windows) .lib stubs
-
LIBRARY?DESTINATION - Non-DLL shared libraries and modules
-
RUNTIME?DESTINATION - Executable targets and DLL (Windows) style shared libraries
以共享庫(kù)為例:
install(TARGETS ${PROJECT_NAME}ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} )以下是可執(zhí)行文件的另一個(gè)示例:
install(TARGETS ${PROJECT_NAME}_nodeRUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )除了這些標(biāo)準(zhǔn)目標(biāo)之外,還必須將一些文件安裝到特殊文件夾中。即,包含Python綁定的庫(kù)必須安裝到不同的文件夾中,才能在Python中導(dǎo)入:
install(TARGETS python_module_libraryARCHIVE DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}LIBRARY DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION} )11.1 安裝Python可執(zhí)行腳本
對(duì)于Python代碼,安裝規(guī)則看起來(lái)不同,因?yàn)闆](méi)有使用add_library()和add_executable()函數(shù),以便CMake確定哪些文件是目標(biāo)以及它們是什么類(lèi)型的目標(biāo)。相反,請(qǐng)?jiān)贑MakeLists.txt文件中使用以下命令:
catkin_install_python(PROGRAMS scripts/myscriptDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})有關(guān)安裝python腳本和模塊的詳細(xì)信息,以及文件夾布局的最佳實(shí)踐,可以在catkin手冊(cè)中找到。
如果只安裝Python腳本而不提供任何模塊,則不需要?jiǎng)?chuàng)建上述setup.py文件,也不需要調(diào)用catkin_Python_setup()。
11.2 安裝頭文件
頭文件還必須安裝到“include”文件夾中,這通常是通過(guò)安裝整個(gè)文件夾的文件來(lái)完成的(可以選擇按文件名模式過(guò)濾,不包括SVN子文件夾)。可以使用如下所示的安裝規(guī)則完成此操作:
install(DIRECTORY include/${PROJECT_NAME}/DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}PATTERN ".svn" EXCLUDE ) 或者,如果include下的子文件夾與包名稱(chēng)不匹配:install(DIRECTORY include/DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}PATTERN ".svn" EXCLUDE )11.3 安裝roslaunch文件或其他資源
其他資源(如launchfiles)可以安裝到${CATKIN\u PACKAGE\u SHARE\u DESTINATION}:
install(DIRECTORY launch/DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launchPATTERN ".svn" EXCLUDE)find_package(Boost REQUIRED COMPONENTS system)
?
include_directories(
? include
? ${catkin_INCLUDE_DIRS}
? ${Boost_INCLUDE_DIRS}
)
?
target_link_libraries(demo ${catkin_LIBRARIES} ${Boost_LIBRARIES})
?
關(guān)于CMake文檔:
[CMake] adding a link directory
總結(jié)
以上是生活随笔為你收集整理的ROS知识: vanilla(香草) CMakeLists.txt 的语法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ROS知识:关于如何命名的约定
- 下一篇: ROS知识:安装rosdep中出现tim