ament_target_dependencies doesn't include library during build but target_link_libraries does

asked 2021-04-30 13:42:36 -0500

khaiyichin gravatar image

updated 2021-04-30 13:45:54 -0500

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 target_link_libaries 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.

edit retag flag offensive close merge delete

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?

christophebedard gravatar image christophebedard  ( 2021-04-30 15:11:55 -0500 )edit

@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.

khaiyichin gravatar image khaiyichin  ( 2021-04-30 15:48:22 -0500 )edit

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/d...

christophebedard gravatar image christophebedard  ( 2021-05-01 09:04:08 -0500 )edit

@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!

khaiyichin gravatar image khaiyichin  ( 2021-05-11 09:17:16 -0500 )edit