rust-lang / rust-lang/rust

-C default-linker-libraries places native libs before user-specified static archives, breaking ld.bfd with --as-needed

Open
#154,975 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-linkage C-discussion needs-triage
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-group for 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.