`__attribute__((weak))` declarations are emitted as ordinary externs, producing strong undefined references on ELF
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 52/100
Research direction
Start with the weak_api.h reproducer and run.sh, then inspect the generated bindings.rs and the ELF symbol results described in the issue. Trace how bindgen handles attribute((weak)) declarations and compare the Rust output with the C caller. Done means weak imports remain optional, or bindgen reports that the selected output mode cannot preserve them.
Written by the indexing model from the issue text.
Description
Input C/C++ Header
int api_version(void);
int optional_api(int value) __attribute__((weak));
The first declaration makes sure the test still depends on the shared library
when optional_api is missing. The weak function is used in the usual way:
return optional_api ? optional_api(value) : value + 100;
Bindgen Invocation
$ bindgen weak_api.h \
--rust-target 1.75 \
--no-layout-tests \
--no-rustfmt-bindings \
--output bindings.rs \
-- -I.
Actual Results
The relevant output, reformatted for readability, is:
extern "C" {
pub fn api_version() -> ::std::os::raw::c_int;
}
extern "C" {
pub fn optional_api(
value: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int;
}
optional_api is represented like an ordinary required function. With bindgen
0.72.1 and rustc 1.75, the C and Rust callers lower to:
; C
declare extern_weak i32 @optional_api(i32 noundef)
; Rust, using bindings.rs unchanged
declare noundef i32 @optional_api(i32 noundef) unnamed_addr
A source build from current main at
9d26c6eddeff9192ddedb563192abe3128fc5aae produced the same ordinary Rust
declaration. In that run, the ELF symbol tables contain:
C caller: WEAK UND optional_api
Rust caller: GLOBAL UND optional_api
The full reproducer is
weak-function-linkage-repro.zip.
It builds an old library that exports only api_version, and a new library
that also exports optional_api:
$ unzip weak-function-linkage-repro.zip
$ cd repro
$ BINDGEN=/path/to/bindgen ./run.sh
Both the 0.72.1 and current-main runs gave these results:
C linked to old: version=1 fallback=105
C linked to new: version=2 optional=205
Rust linked to new: version=2 optional=205
Rust linked directly to old: link error, undefined reference to optional_api
C linked to new, run with old: version=1 fallback=105
Rust linked to new, run with old: exit 127, undefined symbol: optional_api
The C caller can run with the old library and take its fallback path. The Rust
caller using the unchanged generated declaration either fails to link or fails
during loader symbol resolution.
As a header-level example, JACK marks APIs such as
jack_set_latency_callback with JACK_WEAK_EXPORT so a caller can check
whether the function exists when using an older JACK library. Bindgen emits
that declaration as an ordinary extern function too.
--dynamic-loading WeakApi is a separate opt-in libloading workaround.
Without --dynamic-link-require-all, both api_version and optional_api
become fallible lookups. It does not preserve the default linker behavior or
infer optionality from the weak attribute.
$ bindgen --version
bindgen 0.72.1
$ clang --version
Ubuntu clang version 15.0.7
$ rustc --version
rustc 1.75.0
Release target: x86_64-unknown-linux-gnu.
The current-main run used rustc 1.82.0. Its bindgen CLI reported 0.72.0, so the
commit above identifies that build.
Expected Results
A binding that keeps optional_api optional, or an explicit diagnostic if the
selected output mode cannot preserve weak imports.
I am not prescribing a particular Rust representation. Silently emitting an
ordinary extern function changes the weak declaration into a required symbol
on ELF.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 846
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 11
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from rust-lang/rust-bindgen
-
--enable-cxx-namespaces panics on namespace [[deprecated]] { ("[" is not a valid Ident)Possibly taken @lwz23 claimed this 47 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
rust-lang/rust-bindgen#3485 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
rust-lang/rust-bindgen#3483 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
rust-lang/rust-bindgen#3370 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
rust-lang/rust-bindgen#3363 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 25/100
rust-lang/rust-bindgen#3540 ·
Maintainers usually reply within 1 day
All issues in rust-lang/rust-bindgen
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
area:frontend kind:bug priority:p3 ready
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
bug priority: medium ui
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
storytold/vectorcraft#6333 · 1 comment ·
Maintainers usually reply within 1 day
-
bug lexer
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 1 day
-
yara-x fails to build with rsa 0.10.0: unresolved import rsa::Pkcs1v15SignPossibly taken @CfirTsabari claimed this today. Open
Difficulty 1/5 Under an hour Newbie friendliness 87/100
VirusTotal/yara-x#865 ·
Maintainers usually reply within 1 day