Support for one set of bindings depending on another (conflicting `__BindgenBitfieldUnit`)
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!
I would prefer, I think, making blocklist_type("__BindgenBitfieldUnit") work and documenting it I believe
(same for the other built-in types of course)
Ah, that would make sense! I think I can adjust my first attempt to handle that without too much trouble, at least for the bitfield unit type. I'll look at doing the same for other generated types too.
Do you have a suggestion for where exactly to document this (e.g. on blocklist_type itself, or perhaps in the book's "bitfields" page? The latter might make sense for the bitfield unit specifically, but maybe not for anonymous types like _bindgen_ty_1