rosidl icon indicating copy to clipboard operation
rosidl copied to clipboard

Provide documented CMake exported namespace targets for consuming generated packages without ament_target_dependencies

Open Ryanf55 opened this issue 1 year ago • 1 comments

Feature request

Make it easier and more obvious how to consume targets from message packages with target_link_libraries.

Feature description

Using ament_target_dependences, you pass in the CMake project name, and it figures out all the targets for you, performing linking as well as sorting out include directories.

Alternatively, you can use a module-style option with raw CMake like so, where bar_msgs is the message package that calls rosidl_generate_interfaces and foo is the consuming package

find_package(bar_msgs CONFIG REQUIRED)
target_link_libraries(foo PUBLIC ${bar_msgs_TARGETS}

The bar_msgs_TARGETS variable is not a required variable to export according to CMake's find_package docs, however, it is being adopted as an alternative in packages for the time being.

Commonly, in other ROS libraries, in order to use the "modern" CMake targets, exported namespaced targets are provided like so:

find_package(rclcpp CONFIG REQUIRED)
target_link_libraries(foo PUBLIC rclcpp::rclcpp)

Exported namespace targets provide clear advantages in that the target_link_libraries fails if the target is not found. No more include errors or linker errors if you spelled bar_msgs_TARGETS wrong. It is thus desirable for packages generated with rosidl to supply a bar::bar target to consumers. For reference: https://github.com/ros2/rclcpp/pull/2055

Thus, the desired usage to link everything:

find_package(bar_msgs CONFIG REQUIRED)
target_link_libraries(foo PUBLIC bar_msgs::bar_msgs)

OR, for as example, a C++ algorithm package that just needs the message definitions (currently works in humble):

find_package(bar_msgs CONFIG REQUIRED)
target_link_libraries(foo PUBLIC bar_msgs::bar_msgs__rosidl_generator_cpp)

While some of these ALIAS targets are exported, there are a few known issues:

  1. There are exported namespace targets for individual generated parts, but not a top level bar::bar target
  2. It is still desireable to provide the lower level generated targets for packages that just want message definitions, such as an algorithm package that doesn't want additional dependencies
  3. The ROS maintainers have indicated the ROS message generation is tricky, but acknowledge making them easier to consume in modern namespaced CMake target is desired.

Implementation considerations

The exported CMake target names are considered part of a package's public API. CMake lacks basic functionality for easy introspection of these target names. Thus, these targets should be documented as available for use.

For a further discussion, see https://github.com/ament/ament_cmake/issues/292, or my example repo here: https://github.com/Ryanf55/ryan_ros_mvp/tree/bug-cmake-target-link-libraries-msgs

Ryanf55 avatar May 25 '23 13:05 Ryanf55

On occasion, we've "solved" this in our CMake by making an imported interface library which links to the _TARGETS variable

find_package(bar_msgs CONFIG REQUIRED)
add_library(bar_msgs::bar_msgs INTERFACE IMPORTED)
target_link_libraries(bar_msgs::bar_msgs INTERFACE ${bar_msgs_TARGETS})

# ...
target_link_libraries(my_target
  PUBLIC
    bar_msgs::bar_msgs
)

asasine avatar Jun 14 '23 15:06 asasine