rosidl
rosidl copied to clipboard
Provide documented CMake exported namespace targets for consuming generated packages without ament_target_dependencies
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:
- There are exported namespace targets for individual generated parts, but not a top level
bar::bar
target - 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
- 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
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
)