-
Notifications
You must be signed in to change notification settings - Fork 182
Re-Export Generated Messages in rclrs #556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…nd on the AMENT_PREFIX_PATH env var. Able to colcon build the entire workspace.
| let dest_path = PathBuf::from(out_dir).join("interfaces.rs"); | ||
|
|
||
| // TODO I would like to run rustfmt on this generated code, similar to how bindgen does it | ||
| fs::write(dest_path, content.clone()).expect("Failed to write interfaces.rs"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interface.rs ends up looking like this
pub mod builtin_interfaces { ... };
pub mod std_msgs {
pub mod msg {
use crate::builtin_interfaces;
// use crate::...; etc
include!("path/to/generated/code");
pub mod rmw {
use crate::builtin_interfaces;
// use crate::...; etc
include!("path/to/generated/rmw/code");
}
}
}Where all generated interface code is placed into a module based on the paths found in the AMENT_PREFIX_PATH share directories.
Interestingly enough, I also learned that the #[path = "..."] attribute for modules works with absolute paths. So that also could work, but I didn't have proper intellisense with that approach so I stuck with include!()
|
|
||
| mod rcl_bindings; | ||
|
|
||
| include!(concat!(env!("OUT_DIR"), "/interfaces.rs")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This generates a lot of warnings right now. Will need to look at how to hygienically do that (or move to another crate and suppress there)
Summary
Working example of re-exporting of the generated interface crates found on the AMENT_PREFIX_PATH env var. With this change generated interface symbols are available directly from
rclrs::, so for example,rclrs::std_msgs::msg::Stringis how you'd access the String type of the generated rust code for the std_msgs package.This depends on ros2-rust/rosidl_rust#12 for fully relocatable symbols.
The way we find the generated code is as follows
AMENT_PREFIX_PATH, look for ashare/directory.share/look for<package>/rust/Cargo.tomlwithin that entry, with the metadata to re-export symbols,include!all source files withinsrc/such that all symbols resolve the same.i.e.
std_msgs::msg::Stringfor a standalone crate build, is effectively the same symbol asrclrs::std_msgs::msg::String.There is still some work needed here, namely I do not have tests fully passing, but I wanted to get this out there early for folks to see it as an option.Tests are now passing. For now, I am simply not installingcolcon-ros-cargoin CI. I believe we will need to remove the patching logic, but need to re-evaluate.I believe this to be a viable alternative to patching, and (could) effectively eliminate the need for vendoring some messages.
Open questions
How does
AMENT_PREFIX_PATHget populated? If its populated as colcon is building packages (which I believe to be the case), then this will also re-export symbols in your own workspace as well as sourced overlays.Should this actually go into
rclrsor a separate crate (i.e. ros_msgs?) By going into rclrs we eliminate the need for vendoring.Its important to know that if we re-build rclrs, and the
AMENT_PREFIX_PATHenv var has changed, then the build.rs will be re-built, which will then re-build all of the generated code.Honestly, I'm not sure if we can really get around this. Rust just really wants you to recompile the code you're using each time you invoke
cargo. We can and should have everything in a colcon workspace share a target directory, but this won't stop all rebuilds. Its possible we expect compiled.rlibs in the share directory and we generate a file which hasextern cratecalls to force rustc to find the dependencies, but this will likely not work with any intellisense, and its overall pretty fragile IMO.