use std::env;
use std::fs::read_dir;
use std::path::{Path, PathBuf};
const AMENT_PREFIX_PATH: &str = "AMENT_PREFIX_PATH";
const ROS_DISTRO: &str = "ROS_DISTRO";
const BINDGEN_WRAPPER: &str = "src/rcl_wrapper.h";
fn get_env_var_or_abort(env_var: &'static str) -> String {
if let Ok(value) = env::var(env_var) {
value
} else {
panic!(
"{} environment variable not set - please source ROS 2 installation first.",
env_var
);
}
}
fn main() {
let ros_distro = get_env_var_or_abort(ROS_DISTRO);
println!("cargo:rustc-cfg=ros_distro=\"{ros_distro}\"");
let mut builder = bindgen::Builder::default()
.header(BINDGEN_WRAPPER)
.derive_copy(false)
.allowlist_type("rcl_.*")
.allowlist_type("rmw_.*")
.allowlist_type("rcutils_.*")
.allowlist_type("rosidl_.*")
.allowlist_function("rcl_.*")
.allowlist_function("rmw_.*")
.allowlist_function("rcutils_.*")
.allowlist_function("rosidl_.*")
.allowlist_var("rcl_.*")
.allowlist_var("rmw_.*")
.allowlist_var("rcutils_.*")
.allowlist_var("rosidl_.*")
.layout_tests(false)
.default_enum_style(bindgen::EnumVariation::Rust {
non_exhaustive: false,
})
.parse_callbacks(Box::new(bindgen::CargoCallbacks));
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed={BINDGEN_WRAPPER}");
let ament_prefix_paths = get_env_var_or_abort(AMENT_PREFIX_PATH);
for ament_prefix_path in ament_prefix_paths.split(':').map(Path::new) {
let ament_index = ament_prefix_path.join("share/ament_index/resource_index/packages");
if !ament_index.is_dir() {
continue;
}
let include_dir = ament_prefix_path.join("include");
builder = builder.clang_arg(format!("-isystem{}", include_dir.display()));
for dir_entry in read_dir(&ament_index).unwrap().filter_map(|p| p.ok()) {
let package = dir_entry.file_name();
let package_include_dir = include_dir.join(&package);
if package_include_dir.is_dir() {
let new_style_include_dir = package_include_dir.join(&package);
if package == "CycloneDDS" || new_style_include_dir.is_dir() {
builder =
builder.clang_arg(format!("-isystem{}", package_include_dir.display()));
}
}
}
let library_path = ament_prefix_path.join("lib");
println!("cargo:rustc-link-search=native={}", library_path.display());
}
println!("cargo:rustc-link-lib=dylib=rcl");
println!("cargo:rustc-link-lib=dylib=rcl_yaml_param_parser");
println!("cargo:rustc-link-lib=dylib=rcutils");
println!("cargo:rustc-link-lib=dylib=rmw");
println!("cargo:rustc-link-lib=dylib=rmw_implementation");
let bindings = builder.generate().expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("rcl_bindings_generated.rs"))
.expect("Couldn't write bindings!");
}