Skip to content

Add support for message definitions in omg idl syntax#617

Open
woutervdstoel wants to merge 4 commits into
mvukov:mainfrom
woutervdstoel:direct-idl-support
Open

Add support for message definitions in omg idl syntax#617
woutervdstoel wants to merge 4 commits into
mvukov:mainfrom
woutervdstoel:direct-idl-support

Conversation

@woutervdstoel

@woutervdstoel woutervdstoel commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

This PR adds support for directly including .idl files as message definitions rather than having them be generated by rosidl. It also supports mixing and matching of idl and msg definitions.

In our repo I also verified this works with rosbag recording and replay.

@lalten lalten mentioned this pull request Mar 25, 2026

@mvukov mvukov left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last time I looked at this, there were constraints:

  • 1 msg in .idl file -> ROS msg
  • 2 msg in .idl file -> ROS srv
  • 3 msg in .idl file -> ROS action
    and that logic is/was pretty much hard-coded in the parser (IIRC).

There should be decent disclaimer about this. Instead of silently failing, what can be done to ensure proper error handline? -- not for this PR but I am curious.

Also, what's the motivation to use .idl directly?

Comment thread ros2/ament.bzl Outdated
outputs.append(src_file)
idl_manifest_contents.append(paths.join("msg", src.basename))

elif src.extension == "idl":

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document why is this necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the PR with simplified logic and some explanation about generated_idl_files.

Comment thread ros2/interfaces.bzl Outdated
Comment thread ros2/interfaces.bzl Outdated
Comment thread ros2/plugin_aspects.bzl
return struct(
package_name = target.label.name,
srcs = target[Ros2InterfaceInfo].info.srcs,
generated_idl_files = target[IdlAdapterAspectInfo].generated_idl_files if IdlAdapterAspectInfo in target else None,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are changes needed in this file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I explained in a comment in ament.bzl why we also need the generated_idl_files . I'm open to implementation suggestions that don't involve changing this struct because I agree this is a bit of a detour.

Comment thread ros2/plugin_aspects.bzl Outdated
@woutervdstoel

Copy link
Copy Markdown
Contributor Author

There should be decent disclaimer about this. Instead of silently failing, what can be done to ensure proper error handline? -- not for this PR but I am curious.

I don't think we can handle this at analysis time since it requires looking at the content of the files. We could of course generate tests to assert it. I think that since it's a feature for advanced users anyway, maybe it doesn't need the greatest error handling?

Also, what's the motivation to use .idl directly?

In our setup: we want to annotate certain message fields with some custom annotations that another tool looks as (which reuses the existing rosidl parser). The IDL format is much more flexible in this regard than the msg format.

I also happen to know that Apex.AI recommends their customers directly write IDL because of the extended feature set.

Comment thread ros2/interfaces.bzl Outdated
Comment thread ros2/interfaces.bzl Outdated
Comment thread ros2/interfaces.bzl Outdated
Comment thread ros2/interfaces.bzl
Comment thread ros2/plugin_aspects.bzl Outdated
Comment thread ros2/plugin_aspects.bzl
implementation = _ros2_interface_collector_aspect_impl,
attr_aspects = _ROS2_COLLECTOR_ATTR_ASPECTS,
provides = [Ros2InterfaceCollectorAspectInfo],
required_aspect_providers = [IdlAdapterAspectInfo],

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary for the logic above to correctly be able to access the IdlAdapterAspectInfo

@mvukov

mvukov commented Apr 2, 2026

Copy link
Copy Markdown
Owner

I don't think we can handle this at analysis time since it requires looking at the content of the files. We could of course generate tests to assert it. I think that since it's a feature for advanced users anyway, maybe it doesn't need the greatest error handling?

For starters, I think it would be enough to clearly document this e.g. in ros2_interface_library rule docs. In a follow-up a proper build time testing can be introduced.

@mvukov

mvukov commented May 17, 2026

Copy link
Copy Markdown
Owner

@woutervdstoel Any plans to wrap up this work?

@woutervdstoel

Copy link
Copy Markdown
Contributor Author

@mvukov I just pushed the documentation change you requested - please let me know if there's anything else that still needs improvement

@mvukov mvukov left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few smaller comments. Please address them and then we can merge this PR. I'll proceed with finishing up Jazzy (@lalten FYI) afterward.

Comment thread ros2/interfaces.bzl Outdated
Comment thread ros2/test/interfaces/py_messages_tests.py Outdated
Comment thread ros2/test/interfaces/cpp_messages_tests.cc
Comment thread ros2/test/interfaces/py_messages_tests.py
Comment thread ros2/interfaces.bzl

@mvukov mvukov left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, I have more questions.

Please let me know if you have time to work on this in the coming days -- let's see whether makes sense to iron out this PR or I can proceed with #558 .

BTW, I pushed a small fix to your branch recently today.

Comment thread ros2/interfaces.bzl

new_file = ctx.actions.declare_file("{}/{}/{}.idl".format(package_name, idl_submodule_name, stem))
idl_files.append(new_file)
ctx.actions.run_shell(

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a symlink suffice here?

Comment thread ros2/interfaces.bzl
def _get_stem(path):
return path.basename[:-len(path.extension) - 1]

def _get_idl_submodule_name(path):

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought... submodule is misleading and not readable. I'd rename submodule -> type because this essentially determines a type (action, msg, srv).

Comment thread ros2/interfaces.bzl
For .msg/.srv and other files, return the extension
"""
if path.extension == "idl":
return path.dirname.split("/")[-1]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anything other than action/msg/srv this should error.

Comment thread ros2/interfaces.bzl
return idl_files, idl_tuples
return idl_files, generated_idl_files, idl_tuples

IdlAdapterAspectInfo = provider("TBD", fields = [

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, I don't see a need to touch this. But I'd like to learn more.

Comment thread ros2/interfaces.bzl
output_dir = adapter_map.dirname

idl_files = []
generated_idl_files = []

@mvukov mvukov Jun 8, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought: why don't you dump everything in idl_files?

IIUC, generated_idl_files is needed such that we put idl files to the ament index. We can dump all idl_files to the index IMO.

Comment thread ros2/ament.bzl
# Generated IDL files in the output tree such that the rosbag mcap writer can include them in the metadata.
# mcap supports both IDL and msg definitions, but not combinations. Therefore, if any handwritten IDL files are
# present, the rosbag writer also needs any generated IDL files it depends on.
if idl.generated_idl_files != None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, here you dump generated IDL files but not user-provided IDL files, right? How then e.g. rosbag knows how to handle user-provided IDL files?

@mvukov mvukov left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Until we sort out some details I pointed out earlier, I'll just make this PR as a not yet ready to be merged.

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.

3 participants