Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Linking

Linking is often the bottleneck in Rust compile times, especially during development. After the compiler has translated each crate into object files, the linker combines them into a single executable. For a large project with hundreds of dependencies, there is a lot of data to process. Debug builds make this worse: Rust emits extensive debug information by default, and a typical backend service can produce debug binaries of 200 MB or more. Most of that volume passes through the linker, which on many systems defaults to GNU ld — a capable but single-threaded linker that was not designed for this scale.

There are three approaches to reducing link times: reducing the amount of data the linker has to process, using a faster linker, and using a parallel linker.

Reducing Debug Information

By default, debug builds include full debug information so that tools like gdb and lldb can provide useful stack traces and variable inspection. This debug information is the largest contributor to binary size in dev builds and adds significant work for the linker.

You can reduce this overhead by splitting debug information into a separate file rather than embedding it in the binary, or by reducing the debug info level:

[profile.dev]
# Split debug info into a separate file (reduces linker work)
split-debuginfo = "packed"
[profile.dev]
# Reduce debug info to line tables only (faster linking, less useful debugger)
debug = "line-tables-only"

For release builds, stripping debug information entirely is covered in Binary Size.

rust-lld

Starting with Rust 1.90, the Rust toolchain ships with and uses rust-lld (a bundled copy of LLVM’s LLD linker) by default on x86_64-unknown-linux-gnu. LLD is significantly faster than GNU ld because it is designed for parallel processing and has a more efficient architecture for handling large inputs.

Benchmarks from the Rust team show that LLD provides roughly 7x faster linking on incremental rebuilds, translating to around a 40% reduction in end-to-end compilation time for projects like ripgrep. For most developers on Linux x86_64, this improvement happens automatically with no configuration needed.

mold

mold is a linker designed from scratch for parallelism. On Linux, it is typically the fastest linker available, outperforming even LLD for large projects. Its macOS counterpart is sold.

The tradeoff is that mold must be installed separately and does not support all platforms. But if you are on Linux and link times are a bottleneck, mold is worth trying.

To use mold, install it through your system package manager (e.g. apt install mold on Debian/Ubuntu) and configure Cargo to use it:

[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

Alternatively, you can use mold’s wrapper mode, which intercepts linker invocations without changing your Cargo configuration:

mold -run cargo build

Reading

Resolving Rust Symbols by Shriram Balaji

Walks through the entire Rust compilation pipeline from lexing through LLVM code generation, then focuses on what the linker actually does: combining object files, resolving symbols, and producing executables. Covers ELF object file structure, symbol tables (strong vs weak symbols), name mangling (how Global becomes __ZN11foo6Global17ha2a12041c4e557c5E), and how to manually compile Rust files into static libraries and link them. Read this if you want to understand what the linker is doing under the hood.

5.1 Faster Linking by Luca Palmieri

Section from Luca’s “Zero to Production” series showing how to configure alternative linkers for Rust on different platforms. Predates the rust-lld default but the configuration approach is still useful for opting into mold or for platforms where LLD is not yet the default. Note: the article mentions zld for macOS, which has since been deprecated in favor of Apple’s improved lld.

Short practical post showing a 70% reduction in link times (from ~10s to ~3s) by switching from GNU ld to lld with a two-line .cargo/config change. Good illustration of the kind of improvement alternative linkers provide.

Announcement from the Rust team about enabling rust-lld (a bundled copy of LLVM’s LLD) by default on nightly for Linux targets. Explains the motivation: LLD is faster than GNU ld, and bundling it means Rust controls the linker version, avoiding compatibility issues with system linkers. This was the precursor to the stable rollout in Rust 1.90.

Announces the stable rollout of rust-lld as the default linker on x86_64-unknown-linux-gnu in Rust 1.90. Reports 7x faster linking on incremental rebuilds and a 40% reduction in end-to-end compilation time for projects like ripgrep. Explains how to opt out if compatibility issues arise and the plan to expand to other Linux targets.

Broad survey of techniques for reducing Rust compile times. The linker section recommends trying mold, lld, or zld (now deprecated) and shows how to configure each. Also covers other approaches that complement faster linking: removing unused dependencies, splitting large crates, and compilation caching.