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

wrap_static_fns is missing from bindgen::Builder #2959

Open
hoangbv15 opened this issue Oct 19, 2024 · 5 comments
Open

wrap_static_fns is missing from bindgen::Builder #2959

hoangbv15 opened this issue Oct 19, 2024 · 5 comments

Comments

@hoangbv15
Copy link

hoangbv15 commented Oct 19, 2024

Hi, I think I'm going crazy, I have been trying to use an external C library in my Rust program without success.
The C library is uhubctl, source code is here https://github.com/mvp/uhubctl/tree/master

As you can see most of the important functions are declared as static functions, for instance

static int usb_find_hubs(void)

And I need to expose them to my Rust program.

After struggling for a while, I realise that the bindings.rs file generated by Bindgen doesn't contain anything, and I also realised that I need the wrap_static_fns flag. Allegedly it should be a method in bindgen::Builder.

However, my VSCode keeps saying that the method is not found, and cargo build gives the same result.

error[E0599]: no method named `wrap_static_fns` found for struct `bindgen::Builder` in the current scope

If I run the command line version

bindgen libs/uhubctl.h -o src/bindings.rs -- -I//opt/homebrew/Cellar/libusb/1.0.27/include/libusb-1.0 -DPROGRAM_VERSION=\"2.6.0\" --wrap-static-fns

I get

panicked at /Users/hoang.bui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-cli-0.70.1/main.rs:45:36:
Unable to generate bindings: ClangDiagnostic("error: unsupported option '--wrap-static-fns'\n")

I am also a total beginner in Rust so I'm completely lost.

I am on macOS Sonoma 14.6.1,
rustc 1.82.0
bindgen 0.70.1

Here is my build.rs

/* File: build.rs */
extern crate bindgen;
extern crate cc;
use std::path::PathBuf;

fn main() {
    // Tell cargo to invalidate the built crate whenever the wrapper changes
    println!("cargo:rerun-if-changed=libs/uhubctl.c");

    let libusb_header_path_flag = "-I/opt/homebrew/Cellar/libusb/1.0.27/include/libusb-1.0";
    let uhubctl_version_flag = "-DPROGRAM_VERSION=\"2.6.0\"";
    
    let bindings = bindgen::Builder::default()
        // The input header we would like to generate bindings for.
        .header("libs/uhubctl.h")
        .wrap_static_fns(true)
        .clang_arg(libusb_header_path_flag)
        .clang_arg(uhubctl_version_flag)
        // Tell cargo to invalidate the built crate whenever any of the
        // included header files changed.
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        // Finish the builder and generate the bindings.
        .generate()
        .expect("Unable to generate bindings");

    // Write the bindings to the src/bindings.rs file.
    let out_path = PathBuf::from("src");
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

    // Build static library
    cc::Build::new()
        .file("libs/uhubctl.c")
        .flag(libusb_header_path_flag)
        .flag(uhubctl_version_flag)
        .compile("uhubctl.a");
}

Any help would be much appreciated!

@pvdrz
Copy link
Contributor

pvdrz commented Oct 19, 2024

My first bet is that you're not actually using 0.70.1 as the released crate clearly has this method: https://docs.rs/bindgen/0.70.1/bindgen/struct.Builder.html#method.wrap_static_fns

The command line version is also wrong as you're passing --wrap-static-fns after the -- which means it is being passed as a CLI argument to clang:

Usage: bindgen <FLAGS> <OPTIONS> <HEADER> -- <CLANG_ARGS>...

Arguments:
  [HEADER]         C or C++ header file
  [CLANG_ARGS]...  Arguments to be passed straight through to clang

That means that you must pass --wrap-static-fns before the --.

@hoangbv15
Copy link
Author

hoangbv15 commented Oct 19, 2024

@pvdrz you are right about the command line, I changed it to

bindgen libs/uhubctl.h -o src/bindings.rs --experimental --wrap-static-fns -- -I//opt/homebrew/Cellar/libusb/1.0.27/include/libusb-1.0 -DPROGRAM_VERSION=\"2.6.0\"

and it worked.

However I'm not sure about the crate, I believe I am on 0.70.1.
Here's my Cargo.toml

[package]
name = "android-charge-limiter-rust"
version = "0.1.0"
edition = "2021"

[build-dependencies]
bindgen = "0.70.1"
cc = "1.0"

[dependencies]

and my Cargo.lock also says 0.70.1

[[package]]
name = "bindgen"
version = "0.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
dependencies = [
 "bitflags",
 "cexpr",
 "clang-sys",
 "itertools",
 "log",
 "prettyplease",
 "proc-macro2",
 "quote",
 "regex",
 "rustc-hash",
 "shlex",
 "syn",
]

I tried deleting Cargo.lock and target/ folder and rebuild, the same result as before

I shift-click on bindgen::Builder to see the underlying code, it takes me to a path in ~/.cargo/ that looks like the right version 0.70.1, but the wrap_static_fns function is nowhere to be found
Image

Here is the content of the ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-0.70.1 folder if it helps
bindgen-0.70.1.zip

And here is my project's source code, maybe someone can try to reproduce
android-charge-limiter-rust.zip

@pvdrz
Copy link
Contributor

pvdrz commented Oct 20, 2024

I think that's because you're missing the experimental feature on your bindgen dependency.

@hoangbv15
Copy link
Author

hoangbv15 commented Oct 20, 2024

@pvdrz could you point to an example or tutorial? The tutorial at https://rust-lang.github.io/rust-bindgen/introduction.html as well as #2405 does not have anything on this

Edit:
After some Googling, I followed this guide roughly to add a feature, as a shot in the dark
https://doc.rust-lang.org/cargo/reference/features.html
I changed the bindgen line in Cargo.toml to

bindgen = { version = "0.70.1", features = ["experimental"] }

and it worked.

I think these things need to be mentioned in the pages that talk about wrap_static_fns or anything that requires this feature

@pvdrz
Copy link
Contributor

pvdrz commented Nov 11, 2024

yeah this might have been an oversight. But the next version of bindgen won't require the experimental to use the feature.

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

No branches or pull requests

2 participants