CMakeList.txt文件詳解

1 整體結構

    CMakeList.txt文件必須遵循以下的格式:

        所需的CMake版本(cmake_minimum_required)

        軟件包的名稱(project())

        查找構建所需要的其他CMake/Catkin軟件包(find_package())

        消息/服務/運動生成器(add_message_files()    add_service_files()    add_action_files())

        調用消息/服務/動作生成(generate_message())

        制定package build info export(catkin_package())

        需要建立的庫/可執行文件(add_library()    add_executable()    target_link_libraries())

        安裝規則(install())


1.1 CMake版本

    每個catkin CMakeList.txt文件都必須以需要的CMake版本。

        cmake_minimum_required(VERSION 2.8.3)

1.2 軟件包名稱

    由CMake項目功能指定的包的名稱。這裏我們製作一個名爲robot_brain的軟件包。

        project(robot_brain)

1.3 查找相關的CMake包

    我們需要使用find_package函數來制定需要找到哪些其他的CMake包來構建我們的項目

        find_package(catkin REQUIRED)

    對於find_package來說,有兩種不同的表達方式分別爲:

        find_package(catkin REQUIRE COMPONENTS nodelet)

    或者

        find_package(catkin REQUIRE)

        find_package(nodelet REQUIRE)

    對於兩者的區別。如果通過了find_package找到了一個包,會創建幾個提供有關找到的包的消息的Cmake環境變量。

    這些環境變量導出了頭文件的位置,源文件的位置,包所依賴的庫以及這些庫的地址。

    <NAME>_FOUND-如果找到庫,則設置爲true,否則爲false

    <NAME>_INCLUDE_DIR/_INCLUDE-包導出的路徑

    <NAME>_LIBRARIES/_LIBS-包導出的庫

    如果find_package作爲catkin的組件(例如第一種方式),這是有好處的。

        find_package(catkin REQUIRE COMPONENTS nodelet)   

    這意味着由nodelet導出的include路徑,庫等也附加到了catkin_變量,這裏的變量是上面指示的<NAME>_,反之使用方式二,則路徑,庫等不會被添加到catkin_變量中。

1.4 Boost

    如果想使用Boost,並制定用作組件的Boost的哪些方面,如你想要使用Boost線程,則

        find_package(Boost REQUIRE COMPONENTS thread) 

1.5 catkin_package()

   catkin_package()是一個catkin提供的CMake宏。這是爲構建系統指定catkin特定消息所必須的。後者又用於生成pkg_config和CMake文件。

    在使用add_library()或者add_executable()聲明任何目標之前,必須調用此函數

    舉例:

    

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"是需要存在來構建運行此程序包的系統依賴項.

1.6 指定構建目標

    構建目標可以有多種形式,但一般有兩種形式:

        可執行目標-我們可以運行的程序

        庫目標-可以在構建和運行時可執行目標使用的庫

1.6.1 目標命名

    需要注意,catkin中構建目標的名稱必須是唯一的。但是,目標的唯一名稱只能在CMake內部進行。

    可以使用set_target_properties()函數重命名爲其他的目標。

    例如:

    set_target_properties(rviz_image_view

                                        PROPERTIES OOUTPUT_NAME image_view

                                        PREFIX "")

    這表示將目標rviz_image_view名稱更改爲image_view

1.6.2 包括路徑和庫路徑

    在指定目標之前,需要指定可以爲所述目標找到資源的位置,特別是頭文件和庫:

        包括路徑-在哪裏可以找到代碼的頭文件

        庫路徑-哪些庫用於該可執行目標建立對象

    例如:

    包括路徑:include_directories()

    include_derectories()的參數應該是find_package調用和需要包含的任何其他目錄生成的_INCLUDE_DIRS變量。如果你使用catkin和Boost,你的include_directories()調用應該如下所示:

        include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

        第一個參數include表示包中的Include/目錄 也是路徑的一部分。

    庫路徑:link_directories()

        link_directories()函數可以用於添加額外的庫路徑。對於catkin與CMake軟件包在find_package時會自動添加鏈接消息。只需要鏈接到target_link_libraries()中的庫

        如:link_direstories(~/my_libs)

1.6.3 可執行目標

    要指定可執行目標,我們必須使用add_executable()CMake函數

        add_executable(myProgram    src/main.cpp    src/some_file.cpp    src/another_file.cpp)

    這將構建一個名爲myProgram的目標可執行文件,由後面的三個源文件構成

1.6.4 庫目標

    add_library()CMake函數用於指定要構建的庫。默認情況下,catkin構建共享庫。

        add_library(${PROJECT_NAME}    ${${PROJECT_NAME}_SRCS})

1.6.5 target_link_libraries

    使用target_link_libreries()函數用來指定可執行目標鏈接的庫,這通常在add_executable()調用之後完成。

    如果找不到ros,則添加${catkin_LIBRARIES}

    句法:

        target_ink_libraries(<executableTargetName>,    <lib1>,    <lib2>,...)

    對於整體構建目標的實例如下:

        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_package()自動拉入。

1.7 消息,服務和動作

    消息(.msg),服務(.srv),動作(.action)文件在ROS包構建和使用之前需要一個特殊的預處理構建步驟。CMake提供了三個宏來處理消息,服務和動作

        add_message_files

        add_service_files

        add_action_files

    這些宏的要點是生成編程語言特定的文件,以便可以利用其選擇的編程語言中的i消息,服務和動作。構建系統將使用所有可用的生成器(例如gencpp,genpy等)生成綁定。

      這些宏之後必須跟隨調用生成的宏,聲明你所用的消息/服務/動作的依賴項:

        generate_message()

1.7.1 重要先決條件/限制

    這些宏必須在catkin_package()宏之前,以便生成才能正常工作

    如:

        

 find_package(catkin REQUIRED COMPONENTS ...)
 add_message_files(...)
 add_service_files(...)
 add_action_files(...)
 generate_messages(...)
 catkin_package(...)
 ...

    你的catkin_package()宏必須對message_runtime具有CATKIN_DEPENDS依賴關係。

catkin_package(
 ...
 CATKIN_DEPENDS message_runtime ...
 ...)

    你必須對message_generation使用find_package(),單獨或作爲catkin的組件:

        find_package(catkin REQUIRED COMPONENTS messafef_generation)

 同時,你的package.xml文件必須包含對message_generation的構建依賴關係以及message_runtime上的運行時依賴關係。如果依賴關係從其他軟件包中過渡出來則不需要這樣做。

    如果您有一個目標,依賴於需要構建消息/服務/運動的其他一些目標,則需要向目標catkin_EXPORTED_TARGETS添加明確的依賴關係,以便它們以正確的順序構建。(some_target是由add_executable()設置的目標的名稱)

    即不使用自己功能包的消息/服務/動作,而是依賴於外部功能包

        add_dependencies(some_target ${catkin_EXPORTED_TARGETS})

    如果你有一個構建消息或服務的包以及使用這些消息/服務的可執行文件,則需要爲自動生成的消息目標創建明確的依賴關係,以便以正確的順序構建它們

        add_dependencies(some_target ${${PROJECT_NAME}_EXPORTED_TARGETS})

     如果兩者都符合則:

        add_dependencies(some_target ${catkin_EXPORTED_TARGETS} ${${PROJECT_NAME}_EXPORTED_TARGETS})

例如:

你的包有名爲“MyMessage1.msg”和“MyMessage.msg”的名爲“msg”目錄中的兩條消息,這些消息依賴於std_msgssensor_msgs,名爲"src"的名爲"MyService.srv"的目錄中的服務,定義使用這些消息和服務的可執行文件messagge_program,並且使用ROS其他某些部分的可執行的do_not_us_local_message_program,不使用此包中定義的i消息/服務,那麼CMakeList.txt文件需要:

 find_package(catkin REQUIRED
    COMPONENTS message_generation std_msgs sensor_msgs)

  # Declare the message files to be built
  add_message_files(FILES
    MyMessage1.msg
    MyMessage2.msg
  )

  # Declare the service files to be built
  add_service_files(FILES
    MyService.srv
  )

  # Actually generate the language-specific message and service files
  generate_messages(DEPENDENCIES std_msgs sensor_msgs)

  # Declare that this catkin package's runtime dependencies
  catkin_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 package
  add_executable(does_not_use_local_messages_program src/main.cpp)
  add_dependencies(does_not_use_local_messages_program ${catkin_EXPORTED_TARGETS})

    另外,如果要構建actionlib操作,並且在action目錄中有一個名爲"MyAction.action"的操作規範文件,必須將

action_msgs添加到使用catkin進行find_package的組件列表中,然後添加如下對generate_message()的調用

add_action_files(FILES
  MyAction.action
)

    此外,該包必須具有對actionlib_msgs的構建依賴。(在generate_message與catkin_package中)

1.8 安裝選項(install)

    構建目標後,目標被放置在catkin開發空間中。通常我們希望目標安裝到系統中,即希望做一個make install的代碼,你必須制定目標應該在哪裏

    使用install()函數作爲參數完成:

    目標-目標是安裝

    ARCHIVE DESTINATION-靜態庫和DLL.lib(Windows)存根

    LIBRARY DESTINATION-非DLL共享庫和模塊

    RUNTIME DESTINATION-可執行目標和DLL(Windows)樣式共享庫

    如:

        

install(TARGETS ${PROJECT_NAME}
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
    除了這些標準目標,一些文件必須安裝到特殊文件夾。一個包含Python綁定的庫必須安裝到不同的文件夾中才能在Python中導入:

    

install(TARGETS python_module_library
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
)

1.9 安裝python可執行腳本

    對於啓動Python模塊支持,當ROS包提供一些Pyhton模塊時,您應該創建一個setup.py文件並調用.不提供任何模塊則不需要這些操作。

        catkin_python_setup()

    之前調用generate_message()和catkin_package()

    對於Python代碼,安裝規則是不同的,因爲沒有使用add_library()和add_executable()函數。在CMakeList.txt文件中,加入如下的內容

        

catkin_install_python(PROGRAMS scripts/myscript
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

1.10 安裝頭文件

        標題文件必須安裝到"include"文件中,這通常是通過安裝整個文件夾的文件來完成的。可以通過如下所示的安裝規則:

        

install(DIRECTORY include/${PROJECT_NAME}/
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  PATTERN ".svn" EXCLUDE
)    

       或者包含的子文件夾與包名不匹配,則

install(DIRECTORY include/
  DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
  PATTERN ".svn" EXCLUDE
)

1.11 安裝roslaunch文件或者其他資源

    其他資源可以安裝到${CATKIN_PACKAGE_SHARE_DESTINATION}

install(DIRECTORY launch/
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
  PATTERN ".svn" EXCLUDE)

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