Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

DEPENDS and CATKIN_DEPENDS are how you can tell catkin which of your package's dependencies should be passed along to packages which find_package(...) your package.

For example, lets say you find_package(Boost REQUIRED) and in one of your installed headers you #include <boost/function.hpp>. In order for a dependent package to build and link your header they need to have Boost's include directory in the their include path and they need to link against Boost's libraries. They should get that dependency from you since you expose it in your header, i.e. they should not have to find_package(Boost REQUIRED) just because they are building against your package, and do not otherwise use Boost.

The fact that your package depends on Boost is an implementation detail. Therefore when some find_package(...)'s your package they should get the dependency on Boost "for free". The way this works is that you put DEPENDS Boost in your catkin_package(...) call. Internally, catkin will find_package(Boost) and add ${Boost_LIBRARIES} to ${your_pkg_LIBRARIES} and add ${Boost_INCLUDE_DIRS} to ${your_pkg_INCLUDE_DIRS}.

I should note that catkin will take the exact thing you give it and try to find_package(...) it and then try to use the _LIBRARIES and _INCLUDE_DIRS variables for that package. This assumption about find_package(...) layout does not always hold, as CMake does not enforce this. For example, when find_package(...)ing Python: find_package(PythonLibs REQUIRED) results in variables like PYTHON_INCLUDE_PATH, and find_package(OpenGL REQUIRED) results in OPENGL_INCLUDE_DIR. Aside from case of the variable prefixes, the actual prefixes differ (PythonLibs -> PYTHON), and the suffixes are non-standard (PYTHON_INCLUDE_PATH and OPENGL_INCLUDE_DIR vs *_INCLUDE_DIRS). In this case you need to pass the include dirs variable to catkin_package(...) explicitly using the INCLUDE_DIRS option and the libraries using the LIBRARIES option.

The CATKIN_DEPENDS option is exactly like that DEPENDS option, but you must put catkin packages only in that list. The benefit for sorting your catkin depends into a separate option is that catkin can do additional checks and warn you of potentially incorrect practices.

Finally, a simple example 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
)

...

In this example you can see that I find_package(Boost...) and pass it along in the DEPENDS section because it generates compliant CMake variables. I find_package(PythonLibs...) and use it internally but do not pass it along as it is not in any of my exposed headers. I find_package(OpenGL...) but since it does not make compliant CMake variables I pass it along explicitly to INCLUDE_DIRS and LIBRARIES. Finally I find_package(catkin...rosconsole roscpp), I use both internally, but maybe I only use rosconsole in my .c* files and therefore I do not need to pass it along, so in the CATKIN_DEPENDS variable I just put roscpp.

One final example, if a package uses a dependency like Boost directly they should make sure that they find_package(...) it explicitly and that they do not just implicitly depend on it being there from another package. An example where this occurs is that if a package foo exports Boost as a dependency and a package bar depends on foo, but also uses Boost internally then bar will compile fine without an explicit dependency on Boost. But later foo might decide to refactor and remove its dependency on Boost. Now bar will fail to compile as it does not have the implicit dependency on Boost via foo anymore.

To answer part A of your question...

DEPENDS and CATKIN_DEPENDS are how you can tell catkin which of your package's dependencies should be passed along to packages which find_package(...) your package.

For example, lets say you find_package(Boost REQUIRED) and in one of your installed headers you #include <boost/function.hpp>. In order for a dependent package to build and link your header they need to have Boost's include directory in the their include path and they need to link against Boost's libraries. They should get that dependency from you since you expose it in your header, i.e. they should not have to find_package(Boost REQUIRED) just because they are building against your package, and do not otherwise use Boost.

The fact that your package depends on Boost is an implementation detail. Therefore when some find_package(...)'s your package they should get the dependency on Boost "for free". The way this works is that you put DEPENDS Boost in your catkin_package(...) call. Internally, catkin will find_package(Boost) and add ${Boost_LIBRARIES} to ${your_pkg_LIBRARIES} and add ${Boost_INCLUDE_DIRS} to ${your_pkg_INCLUDE_DIRS}.

I should note that catkin will take the exact thing you give it and try to find_package(...) it and then try to use the _LIBRARIES and _INCLUDE_DIRS variables for that package. This assumption about find_package(...) layout does not always hold, as CMake does not enforce this. For example, when find_package(...)ing Python: find_package(PythonLibs REQUIRED) results in variables like PYTHON_INCLUDE_PATH, and find_package(OpenGL REQUIRED) results in OPENGL_INCLUDE_DIR. Aside from case of the variable prefixes, the actual prefixes differ (PythonLibs -> PYTHON), and the suffixes are non-standard (PYTHON_INCLUDE_PATH and OPENGL_INCLUDE_DIR vs *_INCLUDE_DIRS). In this case you need to pass the include dirs variable to catkin_package(...) explicitly using the INCLUDE_DIRS option and the libraries using the LIBRARIES option.

The CATKIN_DEPENDS option is exactly like that DEPENDS option, but you must put catkin packages only in that list. The benefit for sorting your catkin depends into a separate option is that catkin can do additional checks and warn you of potentially incorrect practices.

Finally, a simple example 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
)

...

In this example you can see that I find_package(Boost...) and pass it along in the DEPENDS section because it generates compliant CMake variables. I find_package(PythonLibs...) and use it internally but do not pass it along as it is not in any of my exposed headers. I find_package(OpenGL...) but since it does not make compliant CMake variables I pass it along explicitly to INCLUDE_DIRS and LIBRARIES. Finally I find_package(catkin...rosconsole roscpp), I use both internally, but maybe I only use rosconsole in my .c* files and therefore I do not need to pass it along, so in the CATKIN_DEPENDS variable I just put roscpp.

One final example, if a package uses a dependency like Boost directly they should make sure that they find_package(...) it explicitly and that they do not just implicitly depend on it being there from another package. An example where this occurs is that if a package foo exports Boost as a dependency and a package bar depends on foo, but also uses Boost internally then bar will compile fine without an explicit dependency on Boost. But later foo might decide to refactor and remove its dependency on Boost. Now bar will fail to compile as it does not have the implicit dependency on Boost via foo anymore.