Description
Hi! This is kind of a feature request for a (maybe unusual) use case where bindings are generated in multiple different crates. In our case we have citro3d-sys
which depends on some types in ctru-sys
.
The idea is to reuse existing types from ctru-sys
wherever possible, instead of regenerating a duplicate definition. For the most part, this works great with allowlist_type
/ blocklist_type
, so we can use something like this:
use ctru_sys::*;
use libc::*;
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
There is one exception where this doesn't work — bindgen
-generated types for bitfields. The various _bindgen_ty_*
seem to avoid overlap (whether this is by design due to deterministic naming, or just coincidence?), but both sets generate pub struct __BindgenBitfieldUnit<Storage>
as well, which unfortunately does overlap.
Input C/C++ Header
Minimal reproduction with two crates a
and b
:
a.h
:
typedef struct A {
unsigned char x;
unsigned b1 : 1;
unsigned b2 : 1;
unsigned baz;
} A;
b.h
:
#include "../a/a.h"
typedef struct B {
A a;
} B;
typedef struct C {
unsigned char x;
unsigned b1 : 1;
unsigned b2 : 1;
unsigned baz;
} C;
Bindgen Invocation
a/build.rs
:
bindgen::Builder::default()
.header("a.h")
.generate()
.expect("Unable to generate bindings")
.write_to_file(PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("bindings.rs"))
.expect("Couldn't write bindings!");
b/build.rs
:
bindgen::Builder::default()
.header("b.h")
.blocklist_type("A")
.generate()
.expect("Unable to generate bindings")
.write_to_file(PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("bindings.rs"))
.expect("Couldn't write bindings!");
Actual Results
With b/lib.rs
:
// Makes it clear when there are duplicates:
#![deny(ambiguous_glob_reexports)]
pub use a::*;
mod bindings {
use a::*;
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
pub use bindings::*;
$ cargo check --workspace
Compiling b v0.1.0 (/Users/ianchamberlain/Documents/Development/rs-sandbox/b)
error: ambiguous glob re-exports
--> b/src/lib.rs:3:9
|
3 | pub use a::*;
| ^^^^ the name `__BindgenBitfieldUnit` in the type namespace is first re-exported here
...
11 | pub use bindings::*;
| ----------- but the name `__BindgenBitfieldUnit` in the type namespace is also re-exported here
|
note: the lint level is defined here
--> b/src/lib.rs:1:9
|
1 | #![deny(ambiguous_glob_reexports)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: could not compile `b` (lib) due to 1 previous error
Expected Results
I think the simplest option to address this in our case would be a flag to skip generating the __BindgenBitfieldUnit
type — would a PR be accepted to add such a flag? I have mostly worked out the implementation already, but maybe there's a better/simpler way to support this kind of use case?
If it would be accepted, I can open a PR adding a skip_bindgen_bitfield_unit
flag, which in this case could be used to avoid the generated conflict by reusing a
's version of the struct instead of generating a new one in b
.
Thank you!