Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for one set of bindings depending on another (conflicting __BindgenBitfieldUnit) #2835

Open
ian-h-chamberlain opened this issue May 18, 2024 · 3 comments · May be fixed by #2836
Open

Comments

@ian-h-chamberlain
Copy link
Contributor

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!

@ian-h-chamberlain ian-h-chamberlain changed the title Support for one set of bindings depending on another Support for one set of bindings depending on another (conflicting __BindgenBitfieldUnit) May 18, 2024
@emilio
Copy link
Contributor

emilio commented May 18, 2024

I would prefer, I think, making blocklist_type("__BindgenBitfieldUnit") work and documenting it I believe

@emilio
Copy link
Contributor

emilio commented May 18, 2024

(same for the other built-in types of course)

@ian-h-chamberlain
Copy link
Contributor Author

ian-h-chamberlain commented May 18, 2024

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

@ian-h-chamberlain ian-h-chamberlain linked a pull request May 18, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants