Robotics StackExchange | Archived questions

ament_target_dependencies doesn't include library during build but target_link_libraries does

I'm not sure if this is an issue that I should raise at the ament_cmake GitHub page or here, so feel free to provide suggestions on that front.

I'm observing a difference in behaviors between ament_target_dependencies and target_link_libraries despite having (almost) identical arguments when running colcon build. My distro is ROS2 Foxy on Ubuntu 20.04.

Ideally I'd like to use the ament_target_dependencies as recommended in the ROS2 tutorials, so I'd like to know if this is an instance mentioned in the Ament CMake Documentation:

Sometimes it will be necessary to call the targetlinklibaries CMake function

Otherwise, I would like to be able to stick with ament_target_dependencies if possible.

An example case would look like the following.

# CMakeLists.txt
...
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(MyLib1 CONFIG REQUIRED)
find_package(MyLib2 CONFIG REQUIRED)

add_executable(example_node example_node.cpp)

### Block 1 ###
ament_target_dependencies(example_node
  rclcpp
  ${MyLib1_LIBRARIES}
  ${MyLib2_LIBRARIES}
)
##############

### Block 2 ###
target_link_libraries(example_node PRIVATE
  ${rclcpp_LIBRARIES}
  ${MyLib1_LIBRARIES}
  ${MyLib2_LIBRARIES}
)
##############
...

In the above CMakeLists.txt, MyLib1 and MyLib2 are non-ROS CMake projects that are installed locally. I am able to verify that ${MyLib1_LIBRARIES} and ${MyLib2_LIBRARIES} exists (and so do the *_INCLUDE_DIRS variables).

Block 1

If I use Block 1 (and comment out Block 2), I get an error about missing header files which are supposed to be provided by MyLib2. If I add an include_directories line that points to the header files at /usr/include/MyLib2/, I was able to progress further in the build but would get linker errors: /usr/bin/ld: /lib/libMyLib2.so: error adding symbols: DSO missing from command line.

I also tried running colcon build verbosely and noticed that the include path for MyLib2 was missing in the make step but not MyLib1.

/usr/bin/c++  -DDEFAULT_RMW_IMPLEMENTATION=rmw_fastrtps_cpp ... -isystem /usr/include/vtk-7.1 -isystem /usr/include/freetype2 -isystem /opt/ros/foxy/include -isystem /usr/include/MyLib1 -isystem /usr/include/eigen3 -isystem /usr/include/pcl-1.10 -isystem /usr/include/ni -isystem /usr/include/openni2  -Wall -Wextra -Wpedantic -std=gnu++14 ...

I was also unable to find libMyLib2.so (but libMyLib1.so can be found) in the build.make file for this package, which seemed all the more mysterious to me.

Block 2

By commenting Block 1 and uncommenting Block 2, there were no issues building and installing with colcon build. The package also worked as expected.

Some final notes

In the example above, I maintain both MyLib1 and MyLib2, so I am able to make changes to those libraries (particularly their *Config.cmake files) at will, as deemed necessary. Thus the point of this entire question is to find out if there seems to be an issue with my configuration and installation of the two libraries, or if such a difference in behaviors when building for ROS2 is expected.

Asked by khaiyichin on 2021-04-30 13:42:36 UTC

Comments

in short, ament_target_dependencies and target_link_libraries really don't do the same thing. The former does more than the latter. In general, you should use ament_target_dependencies unless you know you need to use target_link_libraries. As for your question about block 1, if you follow the ament_cmake documentation you linked to, you should write ament_target_dependencies(example_node rclcpp MyLib1 MyLib2). Does that work?

Asked by christophebedard on 2021-04-30 15:11:55 UTC

@christophebedard I tried what you suggested, but it had the same behavior as Block 1: it complains about missing header files from MyLib2 but is able to detect MyLib1.

Asked by khaiyichin on 2021-04-30 15:48:22 UTC

I see. Maybe ament_target_dependencies expects something from MyLib1/MyLib2 which just isn't there. This would "make sense" if MyLib1/MyLib2 are pure CMake and not ROS/ament packages. Can you just use ament_target_dependencies for rclcpp and target_link_libraries for MyLib1/MyLib2? I think this is usually how it's done, e.g. https://github.com/ros2/rclcpp/blob/d051b8aa20fa263b1480945aebd1a8e5df315b67/rclcpp/CMakeLists.txt#L189-L204

Asked by christophebedard on 2021-05-01 09:04:08 UTC

@christophebedard Yes, you're right that MyLib1 and MyLib2 are pure CMake packages. I looked at the link and that's about the way I'm doing it, so thanks for that!

Asked by khaiyichin on 2021-05-11 09:17:16 UTC

Answers