-C default-linker-libraries places native libs before user-specified static archives, breaking ld.bfd with --as-needed
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Summary
When -C default-linker-libraries is used (or will be when Meson 1.10.0+ passes it by default), rustc places the default native libraries (-lm, -ldl, -lc, etc.) before user-specified static archives (-Clink-arg=libfoo.a) in the linker command. Combined with --as-needed, this causes link failures with ld.bfd (GNU ld) because it uses strict left-to-right symbol resolution.
lld tolerates this because it handles back-references from later static archives to earlier shared libraries. ld.bfd does not.
Concrete example
This was hit in the Mesa graphics project when building a Rust test under Coverity. The generated link command looks like:
cc ... [Rust rlibs] -Bdynamic -lm -ldl -lc ...
[static archives: libmesa_util.a ...]
libmesa_util.a contains a reference to sqrtf (from libm), but -lm appears earlier. With --as-needed, ld.bfd skips -lm because nothing needs it at that point, and then fails when libmesa_util.a is processed later:
/usr/bin/ld: src/util/libmesa_util.a.p/format_u_format_other.c.o:
undefined reference to symbol 'sqrtf@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6:
error adding symbols: DSO missing from command line
This does not fail with lld (which tolerates back-references), but fails with ld.bfd which is the system linker on most Linux distributions.
Expected behavior
Default native libraries from -C default-linker-libraries should appear after user-specified link arguments (static archives passed via -Clink-arg), so that they can satisfy symbols referenced by those archives under any linker.
Related issues
- #76992 -- proposes
--start-group/--end-groupfor robustness, which would also fix this - #54675 -- PR that added
-C default-linker-libraries; comment from @xclaesse identifies this exact ordering problem: "The problem with rustc injecting default libraries in the linker command is order now matters, and Meson has no way to tell rustc 'put your native libs last'." - mesonbuild/meson#12877, mesonbuild/meson#13542 -- Meson-side reports of this issue, both now closed
Workaround
Pass -lm explicitly via rust_args with --no-as-needed brackets to force the linker to record it regardless of position:
rust_args: [
'-C', 'link-arg=-Wl,--no-as-needed',
'-C', 'link-arg=-lm',
'-C', 'link-arg=-Wl,--as-needed',
]
System information
- rustc 1.84.1
- GNU ld (GNU Binutils for Ubuntu) 2.44
- Ubuntu 25.10 x86_64
Contributor 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.
Research direction
Start by locating rustc's implementation of -C default-linker-libraries and the linker-command construction that orders default native libraries relative to -Clink-arg archives. Reproduce the example with ld.bfd and --as-needed, then verify that default libraries appear after user-specified static archives and that the link succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100