ROS Catkin 教程之 catkin_package(...) 到底在做什麼?

While looking at a CMakeLists.txt file, I was wondering the exact meaning of the CATKIN_DEPENDS option of the catkin_package(...) macro was.

I would expect to see there the same packages as listed in the find_package(...) macro but this does not seem to be the case.

Answer:

DEPENDS 和 CATKIN_DEPENDS 用來告訴 catkin 需要將你程序包的哪些依賴項傳遞給使用 find_package(...) 查找你的程序包的程序包。

例如,假設你 find_package(Boost REQUIRED),並在你的安裝的頭文件中 #include <boost/function.hpp>。爲使一個依賴於你的程序包的程序包能構建和連接你的頭文件,它們需要在自己的 include 路徑中包含 Boost 的 include 目錄,還需要連接 Boost 的庫。由於你已經在頭文件中導出了該依賴,它們應該能從你那裏獲得依賴。也就是它們不再需要 find_package(Boost REQUIRED) ,因爲它們是使用你的包構建的,而不是直接使用 Boost。

你的程序包依賴於 Boost 這一事實是一個實現細節,因此當一些包通過 find_package(...) 查找你的包時,它們能間接獲得對 Boost 的依賴。讓這種機制起作用方法是在你的 catkin_package(...) 調用中加入 DEPENDS Boost。在內部,catkin 將 find_package(Boost),並向 ${your_pkg_LIBRARIES} 添加 ${Boost_LIBRARIES} ,向 ${your_pkg_INCLUDE_DIRS} 添加 ${Boost_INCLUDE_DIRS}

我們應該注意,catkin 將 find_package() 你告訴它的確切的程序包名, 然後嘗試使用該包的 _LIBRARIES 和 _INCLUDE_DIRS 變量。但是 find_package(...) 得到的結果變量的形式並不總是這樣,因爲 CMake 沒有強制執行此操作。例如當 find_package(...) Python 時,find_package(PythonLibs REQUIRED) 的結果變量的形式爲 PYTHON_INCLUDE_PATHfind_package(OpenGL REQUIRED) 的結果變量爲 OPENGL_INCLUDE_DIR。除了變量前綴變得不一樣(PythonLibs -> PYTHON),後綴也變得不標準(PYTHON_INCLUDE_PATH and OPENGL_INCLUDE_DIR vs *_INCLUDE_DIRS)。在這種情況下你就需要使用 INCLUDE_DIRS 選項和 LIBRARIES 選項了。

CATKIN_DEPENDS 選項和 DEPENDS 選項十分相似,但是你只能在其列表中放置 catkin 程序包。將 catkin 依賴設置爲一個單獨的選項的好處是可以讓 catkin 執行一些額外的檢查,然後警告你有什麼不妥的做法。

最後,給個簡單的示例 CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.3)
project(foo)

find_package(Boost REQUIRED COMPONENTS
  system
  thread
)

find_package(PythonLibs REQUIRED)
find_package(OpenGL REQUIRED)

find_package(catkin REQUIRED COMPONENTS
  rosconsole
  roscpp
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
  ${OPENGL_INCLUDE_DIR}
  ${PYTHON_INCLUDE_PATH}
)

catkin_package(
  INCLUDE_DIRS include ${OPENGL_INCLUDE_DIR}
  LIBRARIES foo ${OPENGL_LIBRARIES}
  CATKIN_DEPENDS roscpp
  DEPENDS Boost
)

...

此例中你可以看到我 find_package(Boost...) 並將它傳遞給 catkin_package() 的 DEPENDS 部分,因爲它生成的是兼容 CMake 的變量。我 find_package(PythonLibs...) 並在內部使用它,但是不用將它傳遞給 catkin_package(),因爲我沒有在我任何導出的頭文件中包含它。我 find_package(OpenGL...) ,由於它不是兼容 CMake 的變量,所以我將其顯示地傳遞給 catkin_package() 的 NCLUDE_DIRS 和 LIBRARIES 部分。最後,我 find_package(catkin ... rosconsole roscpp,並在內部使用,但是我可能只在 .c* 文件中使用了 rosconsole,因此我不用傳遞它,所以 catkin_package() 的 CATKIN_DEPENDS 部分我只需放入 roscpp。

最後要說明但是,如果一個程序包有直接使用像 Boost 這樣的依賴項,那麼它們應該確保用 find_package(...) 顯示地查找它,而不是通過其他包隱式地依賴於它。舉個這樣的例子,如果程序包 foo 將 Boost 作爲依賴項導出,又有程序包 bar 依賴於 foo,但也在內部使用 Boost,那麼 bar 即使在沒有顯示依賴 Boost 的情況下也能編譯正常。 但後來 foo 可能決定重構並刪除了它對 Boost 的依賴,那麼現在 bar 將無法編譯,因爲它不再具有通過 foo 傳遞來的對 Boost 的隱式依賴。

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