mozilla / cbindgen

A project for generating C bindings from Rust code
Mozilla Public License 2.0
2.29k stars 294 forks source link

Types not exported when using build script but CLI works #931

Open nbigaouette opened 4 months ago

nbigaouette commented 4 months ago

I am using cbindgen in a build script (build.rs) to generate a C header. I am building a static lib (using crate-type = ["staticlib"]) to be linked in a C project.

I had a problem where some types, defined in one of my dependency and which appear as function arguments are not exported in the header. Trying to debug the issue I compared the generated header with what the cbindgen CLI produces.

It seems that depending on how the header is generated (build script vs cli) the required types are exported or not.

I found this issue https://github.com/mozilla/cbindgen/issues/127 where someone suggested to use cbindgen::Builder::with_parse_deps() and cbindgen::Builder::with_parse_include() but it did not solve my issue. It also links to this RFC issue https://github.com/rust-lang/rfcs/issues/2771 saying that the symbols are not properly exported by Rust. But I don't understand how this could affect differently the CLI or the build script.

I made a small example to reproduce this. See https://github.com/nbigaouette/issue_with_cbindgen. In there I have a workspace with two crates, one is a rust dependency of the other. The CLI produces a header that is valid while the build script misses a type used in the API. Both are using the same configuration.

I've enabled logging (RUST_LOG=trace) for both runs. The build script reports the following:

2024-03-07T22:18:44Z INFO  cbindgen::bindgen::parser] Take ffi::free_standing_function.
[2024-03-07T22:18:44Z WARN  cbindgen::bindgen::ir::ty] Can't find TypeA. This usually means that this type was incompatible or not found.

Clearly it couldn't find TypeA...

nbigaouette commented 4 months ago

I was able to debug this further.

The CLI will call Builder::with_cargo(): https://github.com/mozilla/cbindgen/blob/v0.26.0/src/main.rs#L132 while I was using Builder::with_src() (https://github.com/nbigaouette/issue_with_cbindgen/blob/b98849570b82dc2bd10cb55498b5ce22/b/build.rs#L36)

Unfortunately with_cargo() is not public (https://github.com/mozilla/cbindgen/blob/v0.26.0/src/bindgen/builder.rs#L332). The closest method seems to be with_crate().

Even with with_crate(), I still need to use ParseConfig::include with the crate where the struct resides for it to appear in the final header.

emilio commented 3 months ago

This seems like it was removed intentionally from the public API in 0d8c53ecbcef0d415aa5e97fd2f456b31f3eb014. @eqrion maybe you happen to have more context?