Ask Your Question

How to cleanly handle dependencies in ament?

asked 2018-10-17 01:59:12 -0500

Martin-Idel gravatar image

If I build a library to be used by other ROS 2 developers, what is the way to make it easy to use for downstream packages?

In modern CMake one answer should be exporting targets. This would then allow downstream packages to easily use that target via e.g. find_package(some_dependency REQUIRED) and target_link_libraries(new_target [PUBLIC | PRIVATE | INTERFACE] some_dependency::some_dependency) and if the author of some_dependency has done things right, that's all I have to do as the author of my_target.

Ament_cmake provides help for the exporting mechanism using install(TARGETS my_dependency EXPORT some_dependency ...) and ament_export_interface(some_dependency) (which does the heavy lifting if I'm right). Now if some_dependency itself depends on some_other_dependency, it seems that this dependency must have been added to ament_export_dependencies() for the target some_dependency even if it is not used in any header and could be linked privately. Otherwise I would have to find_package(some_other_dependency) in the build of new_target, which is wrong. This might be an artifact of the problem that it seems impossible to use target_link_libraries together with keywords PUBLIC | PRIVATE | INTERFACE as they are not used internally in ament (at least that's what CMake tells me).

However, there is also ament_target_dependencies() and ament_export_dependencies() and they seem to provide another way of handling dependencies: If I have a ROS 2 package where the export target (if it exists) does not have the same name as the target (then, for some reason, it seems I have to use target_link_libraries, see below for an example), I can just use ament_target_dependencies(new_target some_dependency). If the dependency is used in a header and therefore needs to be linked publicly/by interface, I additionally have to add ament_export_dependency(some_dependency) (in contrast to how I have to use it with exported targets, see above).

What's the preferred way of doing things and how to do this way right?

Some real world examples:

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2018-10-17 12:23:32 -0500

Dirk Thomas gravatar image

ament_cmake_* offers two different approaches to export dependencies:

  • The "classic" CMake approach to export CMake variables like <pkgname>_INCLUDE_DIRECTORIES, <pkgname>_LIBRARIES, etc.

    Related functions are ament_cmake_export_definitions, ament_cmake_export_dependencies, ament_cmake_export_include_directories, ament_cmake_export_libraries. Helper functions like ament_target_dependencies make it easier to use the CMake variables and add "all" of them to a given target.

  • The "modern" CMake approach to export targets.

    The function ament_cmake_export_interfaces does the "heavy lifting" as you mentioned.

A package can decide to use either approach (or both) and downstream packages can use available information accordingly.

Atm almost all ROS 2 packages use the classic approach. The desire / goal would be to use the latter approach everywhere since it provides a cleaner and more precise way (hence it is the modern version).

The the latter approach isn't used much (I am only aware of ament_index_cpp) it might be that the API provided isn't sufficient yet. It seems a function like ament_export_dependency but for the exported target case is missing.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools



Asked: 2018-10-17 01:59:12 -0500

Seen: 492 times

Last updated: Oct 17 '18