# ament_cmake: Confused about ament_export_dependencies and ament_export_interfaces

I'm programming on ROS2 Dashing and trying to port some packages, but the ament_cmake docs haven't answered my questions

What does ament_export_dependencies(my_target ...) actually do? Why is it needed if I already declared my dependencies with ament_target_dependencies(my_target ...) or target_link_libraries(my_target PUBLIC ...)?

Finally, why do I hardly see ament_export_interfaces(${PROJECT_NAME} HAS_LIBRARY_TARGET) in the ROS2 codebase if that's the recommended way to expose library projects for downstream consumption? edit retag close merge delete ## 1 Answer Sort by » oldest newest most voted In your example you have ament_export_dependencies(my_target), but that's incorrect. ament_export_dependencies() takes only package names. In short, ament_target_dependencies() sets up stuff for your package, ament_export_dependencies() and ament_export_interfaces() set up stuff for packages that depend on your package. When a package calls find_package(MyDependency), CMake looks for a file called mydependency-config.cmake or MyDependency-config.cmake. CMake documentation calls this a ProjectConfig.cmake file. The ProjectConfig.cmake sets up everything another project would need to depend on this one. It sets variables like MyDependency_INCLUDE_DIRS, creates imported targets like MyDependency::somelibrary, and finds packages MyDependency depends on. First your package needs to use MyDependency when it's being built. ament_target_dependencies(my_target MyDependency) is a helper function that makes sure your executable or library has everything it needs to use MyDependency. It will call target_link_libraries(my_target${MyDependency_LIBRARIES}), target_include_directories(my_target PUBLIC \${MyDependency_INCLUDE_DIRS}), etc.

Once your package is built/installed, other packages might need MyDependency too. For example, if your package includes <my_depdenency/something.hpp> in a header it installs, then packages that include your header will need to know where MyDependency's headers are too. This is where ament_export_dependencies() comes in . Calling ament_export_dependencies(MyDependency) will make your package's ProjectConfig.cmake contain a find_package(MyDependency) call plus logic to combine CMake variables from MyDependency into your package's CMake variables. For example, it will make YourPackage_INCLUDE_DIRS contain everything in MyDependency_INCLUDE_DIRS. The purpose is so packages don't have to find your dependencies. Use ament_export_dependencies() on all dependencies of yours that downstream packages also need.

ament_export_interfaces() is a little different. This creates imported targets, which is a replacement for CMake standard variables in a ProjectConfig.cmake. It will likely be used more in the future, but for now there is at least one issue with it that needs to be fixed. It won't replace ament_export_dependencies(), but it will change how information like include directories and libraries are communicated between packages.

more

Thank you! So what about the PUBLIC/PRIVATE/INTERFACE specifiers on target_link_libraries and target_include_directories? What effect (if any) do these have on consumers of my package/library?

( 2019-08-21 16:22:39 -0500 )edit
1

My understanding of those is lacking. On consumers of your package? I think the keywords only have an effect on consumers if your package export targets. They do have an effect within targets of your package, but the CMake documentation for target_include_directories() and https://cmake.org/cmake/help/v3.5/command/target_link_libraries.html probably explains better than I can.

( 2019-08-21 16:38:11 -0500 )edit

I submitted an issue, as this seems like a bug that it affects people who link to my library via ament_target_dependencies but not via target_link_libraries. https://github.com/ament/ament_cmake/...

( 2019-08-21 17:30:27 -0500 )edit