Skip to content

ament.bzl: Use marker files instead of subdirectories in packages resource index#623

Open
furushchev wants to merge 2 commits into
mvukov:mainfrom
furushchev:fix-ament-index
Open

ament.bzl: Use marker files instead of subdirectories in packages resource index#623
furushchev wants to merge 2 commits into
mvukov:mainfrom
furushchev:fix-ament-index

Conversation

@furushchev

Copy link
Copy Markdown

Fixes #622

  • Add _write_package_marker: Create marker files at packages/<name> per ament specification
  • Move package.xml to share/<name>/package.xml (correct location)
  • Update get_plugins_xml_path to use share/ directory

Before:

  • share/ament_index/resource_index/packages/foo/package.xml (directory)

After:

  • share/ament_index/resource_index/packages/foo (marker file)
  • share/foo/package.xml (package manifest)

Fixes ament index spec compliance per:
https://github.com/ament/ament_cmake/blob/jazzy/ament_cmake_core/doc/resource_index.md

…source index

- Split _write_package_xml into _write_package_marker and _write_package_xml
- Create marker files at packages/<name> per ament specification
- Move package.xml to share/<name>/package.xml (correct location)
- Update get_plugins_xml_path to use share/ directory
- Fix bug: line 166 was appending base_package twice instead of plugin_package
- Add optional content parameter to _write_package_marker for future flexibility

This change makes rules_ros2's ament index structure compliant with the
official ament specification, which requires marker files (not directories)
in the packages resource type.

Before: share/ament_index/resource_index/packages/foo/package.xml (directory)
After:  share/ament_index/resource_index/packages/foo (marker file)
        share/foo/package.xml (package manifest)

Fixes ament index spec compliance per:
https://github.com/ament/ament_cmake/blob/jazzy/ament_cmake_core/doc/resource_index.md

Verified:
- All marker files are created as files (not directories)
- package.xml files placed in correct share/<package>/ location
- Interface discovery works correctly (bazel run //:interface -- list)
- Structure matches real ROS 2 installations
@mvukov

mvukov commented Apr 27, 2026

Copy link
Copy Markdown
Owner

Interesting :) How did the current implementation work so far without anyone complaining?

@furushchev

furushchev commented Apr 28, 2026

Copy link
Copy Markdown
Author

@mvukov Not sure how exactly, but I had a program that didn't work before, and this fix made it work. (I'll make a PR after this getting merged)

@mvukov

mvukov commented Apr 28, 2026

Copy link
Copy Markdown
Owner

Would be good to add your use case as a unit test.

@furushchev

Copy link
Copy Markdown
Author

Would be good to add your use case as a unit test.

Sorry for the delayed response.
I added one example that fails without this change
#628

@furushchev

Copy link
Copy Markdown
Author

@mvukov Here is the result of the example:

BEFORE

$ bazel run //chatter:interface list
Starting local Bazel server (8.5.1) and connecting to it...
WARNING: For repository 'rules_cc', the root module requires module version rules_cc@0.2.9, but got rules_cc@0.2.16 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
WARNING: For repository 'rules_rust', the root module requires module version rules_rust@0.63.0, but got rules_rust@0.67.0 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
INFO: Analyzed target //chatter:interface (152 packages loaded, 16293 targets configured).
INFO: Found 1 target...
Target //chatter:interface up-to-date:
  bazel-bin/chatter/interface
  bazel-bin/chatter/interface_launch.py
INFO: Elapsed time: 41.328s, Critical Path: 31.60s
INFO: 724 processes: 232 internal, 492 processwrapper-sandbox.
INFO: Build completed successfully, 724 total actions
INFO: Running command line: bazel-bin/chatter/interface <args omitted>
Messages:
Traceback (most recent call last):
  File "/home/furushchev/.cache/bazel/_bazel_furushchev/93dbdedab3419566dfbf2f05e47d5ed2/execroot/_main/bazel-out/k8-fastbuild/bin/chatter/interface.runfiles/com_github_mvukov_rules_ros2+/ros2/ros2_interface.py", line 33, in <module>
    sys.exit(ros2cli.cli.main(argv=sys.argv[1:], extension=extension))
  File "/home/furushchev/.cache/bazel/_bazel_furushchev/93dbdedab3419566dfbf2f05e47d5ed2/execroot/_main/bazel-out/k8-fastbuild/bin/chatter/interface.runfiles/com_github_mvukov_rules_ros2++non_module_deps+ros2cli/ros2cli/ros2cli/cli.py", line 91, in main
    rc = extension.main(parser=parser, args=args)
  File "/home/furushchev/.cache/bazel/_bazel_furushchev/93dbdedab3419566dfbf2f05e47d5ed2/execroot/_main/bazel-out/k8-fastbuild/bin/chatter/interface.runfiles/com_github_mvukov_rules_ros2+/ros2/ros2_cmd.py", line 121, in main
    return extension.main(args=args)
  File "/home/furushchev/.cache/bazel/_bazel_furushchev/93dbdedab3419566dfbf2f05e47d5ed2/execroot/_main/bazel-out/k8-fastbuild/bin/chatter/interface.runfiles/com_github_mvukov_rules_ros2++non_module_deps+ros2cli/ros2interface/ros2interface/verb/list.py",
line 70, in main
    print_messages()
  File "/home/furushchev/.cache/bazel/_bazel_furushchev/93dbdedab3419566dfbf2f05e47d5ed2/execroot/_main/bazel-out/k8-fastbuild/bin/chatter/interface.runfiles/com_github_mvukov_rules_ros2++non_module_deps+ros2cli/ros2interface/ros2interface/verb/list.py",
line 23, in print_messages
    message_interfaces = get_message_interfaces()
  File "/home/furushchev/.cache/bazel/_bazel_furushchev/93dbdedab3419566dfbf2f05e47d5ed2/execroot/_main/bazel-out/k8-fastbuild/bin/chatter/interface.runfiles/com_github_mvukov_rules_ros2++non_module_deps+ros2_rosidl_runtime_py/rosidl_runtime_py/get_interf
aces.py", line 84, in get_message_interfaces
    interfaces = _get_interfaces(package_names)
  File "/home/furushchev/.cache/bazel/_bazel_furushchev/93dbdedab3419566dfbf2f05e47d5ed2/execroot/_main/bazel-out/k8-fastbuild/bin/chatter/interface.runfiles/com_github_mvukov_rules_ros2++non_module_deps+ros2_rosidl_runtime_py/rosidl_runtime_py/get_interf
aces.py", line 37, in _get_interfaces
    raise LookupError(f"Unknown package '{package_name}'")
LookupError: Unknown package 'action_msgs'

AFTER

$ bazel run //chatter:interface list
WARNING: For repository 'rules_cc', the root module requires module version rules_cc@0.2.9, but got rules_cc@0.2.16 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
WARNING: For repository 'rules_rust', the root module requires module version rules_rust@0.63.0, but got rules_rust@0.67.0 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
INFO: Analyzed target //chatter:interface (91 packages loaded, 7016 targets configured).
INFO: Found 1 target...
Target //chatter:interface up-to-date:
  bazel-bin/chatter/interface
  bazel-bin/chatter/interface_launch.py
INFO: Elapsed time: 0.864s, Critical Path: 0.05s
INFO: 21 processes: 721 action cache hit, 21 internal.
INFO: Build completed successfully, 21 total actions
INFO: Running command line: bazel-bin/chatter/interface <args omitted>
Messages:
    action_msgs/msg/GoalInfo
    action_msgs/msg/GoalStatus
    action_msgs/msg/GoalStatusArray
    builtin_interfaces/msg/Duration
    builtin_interfaces/msg/Time
    lifecycle_msgs/msg/State
    lifecycle_msgs/msg/Transition
    lifecycle_msgs/msg/TransitionDescription
    lifecycle_msgs/msg/TransitionEvent
    rcl_interfaces/msg/FloatingPointRange
    rcl_interfaces/msg/IntegerRange
    rcl_interfaces/msg/ListParametersResult
    rcl_interfaces/msg/Log
    rcl_interfaces/msg/Parameter
    rcl_interfaces/msg/ParameterDescriptor
    rcl_interfaces/msg/ParameterEvent
    rcl_interfaces/msg/ParameterEventDescriptors
    rcl_interfaces/msg/ParameterType
    rcl_interfaces/msg/ParameterValue
    rcl_interfaces/msg/SetParametersResult
    rmw_dds_common/msg/Gid
    rmw_dds_common/msg/NodeEntitiesInfo
    rmw_dds_common/msg/ParticipantEntitiesInfo
    rosgraph_msgs/msg/Clock
    std_msgs/msg/Bool
    std_msgs/msg/Byte
    std_msgs/msg/ByteMultiArray
    std_msgs/msg/Char
    std_msgs/msg/ColorRGBA
    std_msgs/msg/Empty
    std_msgs/msg/Float32
    std_msgs/msg/Float32MultiArray
    std_msgs/msg/Float64
    std_msgs/msg/Float64MultiArray
    std_msgs/msg/Header
    std_msgs/msg/Int16
    std_msgs/msg/Int16MultiArray
    std_msgs/msg/Int32
    std_msgs/msg/Int32MultiArray
    std_msgs/msg/Int64
    std_msgs/msg/Int64MultiArray
    std_msgs/msg/Int8
    std_msgs/msg/Int8MultiArray
    std_msgs/msg/MultiArrayDimension
    std_msgs/msg/MultiArrayLayout
    std_msgs/msg/String
    std_msgs/msg/UInt16
    std_msgs/msg/UInt16MultiArray
    std_msgs/msg/UInt32
    std_msgs/msg/UInt32MultiArray
    std_msgs/msg/UInt64
    std_msgs/msg/UInt64MultiArray
    std_msgs/msg/UInt8
    std_msgs/msg/UInt8MultiArray
    unique_identifier_msgs/msg/UUID
Services:
Actions:

@mvukov

mvukov commented May 17, 2026

Copy link
Copy Markdown
Owner

A unit/integration test should live in this PR.

@mvukov

mvukov commented May 25, 2026

Copy link
Copy Markdown
Owner

Please fix CI complaints.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ament resource type folder is not shallow

2 participants