ROS Catkin 教程之 catkin_package(…) 到底在做什么?

  • Post author:
  • Post category:其他


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_PATH



find_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

)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

此例中你可以看到我

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 的隐式依赖。

                                </div>