Skip to content

Commit 4110a3c

Browse files
committed
Update bindings to include actions -- added script for automating the binding generation
Signed-off-by: Michael X. Grey <[email protected]>
1 parent 3605b7a commit 4110a3c

File tree

9 files changed

+3337
-3551
lines changed

9 files changed

+3337
-3551
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[workspace]
22
members = [
33
"rclrs",
4+
"generate_bindings",
45
]
56
resolver = "2"

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,8 @@ ros2 launch examples_rclrs_minimal_pub_sub minimal_pub_sub.launch.xml
7474
Further documentation articles:
7575
- [Tutorial on writing your first node with `rclrs`](docs/writing-your-first-rclrs-node.md)
7676
- [Contributor's guide](docs/CONTRIBUTING.md)
77+
78+
> [!TIP]
79+
> For maintainers: To (re-)generate bindings for a certain ROS distro, source that distro
80+
> and then run `cargo run --bin rclrs_generate_bindings` from this root directory of the repo.
81+
> Remember to commit the new or changed binding file.

generate_bindings/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "rclrs_generate_bindings"
3+
version = "0.5.1"
4+
# This project is not military-sponsored, Jacob's employment contract just requires him to use this email address
5+
authors = ["Esteve Fernandez <[email protected]>", "Nikolai Morin <[email protected]>", "Jacob Hassold <[email protected]>"]
6+
edition = "2021"
7+
license = "Apache-2.0"
8+
description = "A ROS 2 client library for developing robotics applications in Rust"
9+
rust-version = "1.75"
10+
11+
[[bin]]
12+
name = "rclrs_generate_bindings"
13+
path = "src/main.rs"
14+
15+
[dependencies]
16+
# Needed to generate the bindings
17+
bindgen = "0.70"
18+
19+
# Needed to ensure the generator is being called from the correct workspace directory
20+
cargo-manifest = "0.17"

generate_bindings/src/main.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use cargo_manifest::Manifest;
2+
use std::path::Path;
3+
use std::fs::read_dir;
4+
5+
const AMENT_PREFIX_PATH: &str = "AMENT_PREFIX_PATH";
6+
const ROS_DISTRO: &str = "ROS_DISTRO";
7+
const BINDGEN_WRAPPER: &str = "rclrs/src/rcl_wrapper.h";
8+
9+
fn get_env_var_or_abort(env_var: &'static str) -> String {
10+
if let Ok(value) = std::env::var(env_var) {
11+
value
12+
} else {
13+
panic!(
14+
"{} environment variable not set - please source ROS 2 installation first.",
15+
env_var
16+
);
17+
}
18+
}
19+
20+
fn main() {
21+
let ros_distro = get_env_var_or_abort(ROS_DISTRO);
22+
let ament_prefix_paths = get_env_var_or_abort(AMENT_PREFIX_PATH);
23+
24+
let Ok(workspace) = Manifest::from_path("Cargo.toml")
25+
.map_err(|_| ())
26+
.and_then(|manifest| manifest.workspace.ok_or(())) else
27+
{
28+
panic!(" > ERROR: Run the generate_bindings script from the root Cargo workspace of ros2_rust");
29+
};
30+
31+
let has_rclrs = workspace.members.iter().find(|member | *member == "rclrs").is_some();
32+
if !has_rclrs {
33+
panic!(
34+
" > ERROR: Run the generate_bindings script from the root Cargo workspace of ros2_rust. \
35+
Could not find rclrs in this workspace. Members include {:?}",
36+
workspace.members,
37+
);
38+
}
39+
40+
let mut builder = bindgen::Builder::default()
41+
.header(BINDGEN_WRAPPER)
42+
.derive_copy(false)
43+
.allowlist_type("rcl_.*")
44+
.allowlist_type("rmw_.*")
45+
.allowlist_type("rcutils_.*")
46+
.allowlist_type("rosidl_.*")
47+
.allowlist_function("rcl_.*")
48+
.allowlist_function("rmw_.*")
49+
.allowlist_function("rcutils_.*")
50+
.allowlist_function("rosidl_.*")
51+
.allowlist_var("rcl_.*")
52+
.allowlist_var("rmw_.*")
53+
.allowlist_var("rcutils_.*")
54+
.allowlist_var("rosidl_.*")
55+
.layout_tests(false)
56+
.default_enum_style(bindgen::EnumVariation::Rust {
57+
non_exhaustive: false,
58+
});
59+
60+
for ament_prefix_path in ament_prefix_paths.split(':').map(Path::new) {
61+
// Locate the ament index
62+
let ament_index = ament_prefix_path.join("share/ament_index/resource_index/packages");
63+
if !ament_index.is_dir() {
64+
continue;
65+
}
66+
67+
// Old-style include directory
68+
let include_dir = ament_prefix_path.join("include");
69+
70+
// Including the old-style packages
71+
builder = builder.clang_arg(format!("-isystem{}", include_dir.display()));
72+
73+
// Search for and include new-style-converted package paths
74+
for dir_entry in read_dir(&ament_index).unwrap().filter_map(|p| p.ok()) {
75+
let package = dir_entry.file_name();
76+
let package_include_dir = include_dir.join(&package);
77+
78+
if package_include_dir.is_dir() {
79+
let new_style_include_dir = package_include_dir.join(&package);
80+
81+
// CycloneDDS is a special case - it needs to be included as if it were a new-style path, but
82+
// doesn't actually have a secondary folder within it called "CycloneDDS"
83+
// TODO(jhdcs): if this changes in future, remove this check
84+
if package == "CycloneDDS" || new_style_include_dir.is_dir() {
85+
builder =
86+
builder.clang_arg(format!("-isystem{}", package_include_dir.display()));
87+
}
88+
}
89+
}
90+
}
91+
92+
let bindings = builder.generate().expect("Unable to generate bindings");
93+
let bindings_path = format!("rclrs/src/rcl_bindings_generated_{ros_distro}.rs");
94+
bindings.write_to_file(bindings_path).expect("Failed to generate bindings");
95+
}

rclrs/generate_bindings.py

Lines changed: 0 additions & 61 deletions
This file was deleted.

rclrs/src/action.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ fn empty_goal_status_array() -> DropGuard<rcl_action_goal_status_array_t> {
229229
#[cfg(test)]
230230
mod tests {
231231
use crate::*;
232-
use example_interfaces::action::{Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback};
232+
use crate::vendor::example_interfaces::action::{Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback};
233233
use tokio::sync::mpsc::unbounded_channel;
234234
use futures::StreamExt;
235235
use std::time::Duration;

0 commit comments

Comments
 (0)