[PATCH v2 14/18] build-helper: cbindgen, let crates generate a header file
From: Ezekiel Newren via GitGitGadget <hidden>
Date: 2025-09-17 01:16:58
Subsystem:
rust, the rest · Maintainers:
Miguel Ojeda, Linus Torvalds
From: Ezekiel Newren <redacted> Signed-off-by: Ezekiel Newren <redacted> --- rust/build-helper/Cargo.toml | 5 ++++ rust/build-helper/src/lib.rs | 44 +++++++++++++++++++++++++++++++++++- rust/cbindgen-template.toml | 16 +++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 rust/cbindgen-template.toml
diff --git a/rust/build-helper/Cargo.toml b/rust/build-helper/Cargo.toml
index 8939b4b876..2e42bb5405 100644
--- a/rust/build-helper/Cargo.toml
+++ b/rust/build-helper/Cargo.toml@@ -4,3 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] +cbindgen = "0.24.0" +textwrap = "=0.16.1" +once_cell = "=1.20.3" +unicode-width = "=0.1.13" +
diff --git a/rust/build-helper/src/lib.rs b/rust/build-helper/src/lib.rs
index 70e95d16f5..640bc19734 100644
--- a/rust/build-helper/src/lib.rs
+++ b/rust/build-helper/src/lib.rs@@ -1,5 +1,7 @@ use std::collections::HashMap; +use std::io::Write; use std::path::PathBuf; +use cbindgen::Config; fn parse_bool_from_str(value: &str) -> bool {
@@ -23,12 +25,20 @@ fn parse_bool_from_option(value: Option<&String>, default: bool) -> bool { /// To run tests set GIT_BUILD_DIR and run `USE_LINKING=true cargo test` pub struct BuildHelper { crate_env: HashMap<String, String>, + generate_header: bool, + file_out: PathBuf, + config: Config, } impl BuildHelper { pub fn new(crate_env: HashMap<String, String>) -> Self { - let it = Self {crate_env}; + let mut it = Self { + crate_env, + generate_header: false, + file_out: PathBuf::default(), + config: Config::default(), + }; let dir_crate = it.dir_crate(); let dir_workspace = dir_crate.parent().unwrap();
@@ -38,6 +48,12 @@ impl BuildHelper { std::fs::create_dir(dir_interop.clone()).unwrap(); } + let file_cbindgen = dir_workspace.join("cbindgen-template.toml"); + it.file_out = dir_interop.join(format!("{}.h", it.crate_name())); + + it.config = Config::from_file(file_cbindgen.display().to_string().as_str()).unwrap(); + it.config.include_guard = Some(format!("{}_H", it.crate_name().to_uppercase())); + it }
@@ -49,6 +65,16 @@ impl BuildHelper { PathBuf::from(self.crate_env["CARGO_MANIFEST_DIR"].clone()) } + pub fn generate_header<F>(mut self, editor: F) -> Self + where + F: Fn(&mut Config) + { + self.generate_header = true; + editor(&mut self.config); + + self + } + pub fn build(self) { let use_linking = parse_bool_from_option(self.crate_env.get("USE_LINKING"), self.crate_env.get("CARGO_TARGET_DIR").is_none()); let dir_crate = self.dir_crate();
@@ -78,6 +104,22 @@ impl BuildHelper { } else { println!("cargo:warning={} is not linking against C objects, `USE_LINKING=true cargo test`", self.crate_env["CARGO_PKG_NAME"]); } + + if self.generate_header { + let mut buffer = Vec::<u8>::new(); + cbindgen::Builder::new() + .with_crate(dir_crate.clone()) + .with_config(self.config) + .with_std_types(true) + .generate() + .expect("Unable to generate bindings") + .write(&mut buffer); + + let mut fd = std::fs::File::create(self.file_out).unwrap(); + fd.write(buffer.as_slice()).unwrap(); + } else { + let _ = std::fs::remove_file(self.file_out); + } } }
diff --git a/rust/cbindgen-template.toml b/rust/cbindgen-template.toml
new file mode 100644
index 0000000000..cab83218d0
--- /dev/null
+++ b/rust/cbindgen-template.toml@@ -0,0 +1,16 @@ +## compat/posix.h includes stdbool.h where git-compat-util.h does not +## this is mandatory for correct bool C <-> Rust interop. Though the +## 'includes' (and all other variables in this file) can be +## overridden in build.rs. +sys_includes = ["compat/posix.h"] + +autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" + +language = "C" +no_includes = true +usize_is_size_t = true +style = "tag" +tab_width = 4 + +[parse] +parse_deps = false
--
gitgitgadget