How to Use mold or lld for Faster Linking in Rust

Speed up Rust builds by configuring Cargo to use the faster mold or lld linkers via rustflags in your config file.

The final step that steals your time

You type cargo build --release. The compiler churns through crates, your fans spin up, and then everything stops. The terminal hangs on a single line: Linking. Your CPU usage drops to zero. You watch a progress bar that refuses to move. This is the linker bottleneck. It happens to everyone, especially as projects grow past a few hundred dependencies. The fix is not a faster computer. It is a different tool.

What linking actually does

Compiling Rust code happens in two distinct phases. The first phase translates your .rs files into object files. Each object file contains machine code for a single module, plus a list of unresolved symbols. Those symbols are functions, constants, or static variables that live in other modules. The second phase is linking. The linker takes every object file and every dependency, resolves those missing symbols, patches the memory addresses, and stitches everything into one executable.

The default linker on most Linux systems is bfd or gold. Both are legacy tools. They process files sequentially. They load everything into memory one by one, resolve symbols in a single thread, and write the final binary to disk. When your project pulls in fifty crates, the linker becomes a traffic cop at a single-lane bridge.

mold and lld change the geometry of that bridge. They are modern linkers built for parallel execution. They split the work across all your CPU cores. They use memory mapping instead of reading files sequentially. They skip redundant work by caching intermediate results. The result is a linking phase that finishes in seconds instead of minutes.

The minimal configuration

You do not need to change your Cargo.toml. You do not need to install a nightly compiler. You only need a configuration file in your project root.

# .cargo/config.toml
# Target-specific configuration only applies when building for Linux
[target.'cfg(target_os = "linux")']
# Pass compiler flags that rustc forwards directly to the linker
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

This tells the Rust compiler to pass a specific flag to the underlying linker. The -C flag means compiler option. The link-arg part forwards the value directly to the linker binary. The -fuse-ld=mold argument is a GCC and Clang convention that tells the toolchain to invoke mold instead of the system default.

Commit this file to version control. Every developer who clones the repository gets the speedup automatically. The community treats .cargo/config.toml as a project-level contract. If it changes build behavior, it belongs in git.

How the flags travel

When you run cargo build, Cargo reads .cargo/config.toml before invoking rustc. It sees the rustflags array and appends those arguments to every rustc invocation in the workspace. rustc compiles your code and your dependencies into object files. When it reaches the final step, it calls the linker. Because of the -fuse-ld=mold flag, the compiler wrapper detects the request and launches mold instead of ld.

mold reads the object files in parallel. It builds a symbol table across multiple threads. It resolves relocations simultaneously. It writes the output binary using asynchronous I/O. The entire pipeline stays saturated. Your CPU usage stays high until the binary is written. The terminal returns to your prompt.

The same mechanism works for lld. Replace mold with lld in the flag value. The compiler forwards the argument identically. The linker binary handles the rest.

A realistic cross-platform setup

Real projects often span multiple operating systems. You cannot hardcode mold for every platform. mold does not support Windows. macOS uses a different linking architecture entirely. You need a configuration that adapts to the host system.

# .cargo/config.toml
# Route Linux builds to mold for maximum parallel linking speed
[target.'cfg(target_os = "linux")']
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

# Route macOS builds to lld, which handles Mach-O binaries natively
[target.'cfg(target_os = "macos")']
rustflags = ["-C", "link-arg=-fuse-ld=lld"]

# Route Windows builds to lld, which supports COFF and PE formats
[target.'cfg(target_os = "windows")']
rustflags = ["-C", "link-arg=-fuse-ld=lld"]

This setup routes Linux builds to mold and routes macOS and Windows builds to lld. Both linkers accept the same -fuse-ld syntax. Both integrate cleanly with the Rust toolchain. You commit this file to version control. Every developer who clones the repository gets the speedup automatically.

Continuous integration environments often cache the target directory. If you switch linkers mid-project, the cache may contain object files built with different optimization flags or debug settings. Clear the cache or let the first CI run rebuild everything. The second run will benefit from the faster linking.

Where things break

The configuration works until it does not. The most common failure is a missing binary. If your system does not have mold installed, the linker step fails with a "cannot find linker" or "exec format error". The compiler does not warn you ahead of time. It only fails when it tries to execute the missing tool.

Install the linker before you run the build. On Debian or Ubuntu, run sudo apt install mold. On Fedora, run sudo dnf install mold. On macOS, run brew install llvm to get lld. The binary names differ slightly across package managers. Verify the installation by running mold --version or lld --version in your terminal.

Debug builds behave differently. The linker must process debug symbols, which are massive. mold and lld handle them faster than the default linker, but the speedup is less dramatic. Release builds see the biggest gains because the linker spends more time optimizing symbol resolution and stripping unused code.

macOS presents a subtle trap. The system linker is ld64. It does not understand -fuse-ld. If you accidentally apply the Linux configuration to a Mac, the build fails with an unrecognized flag error. The platform-specific target blocks prevent this. Keep them separate.

Choosing the right linker

Use mold when you are on Linux and want the absolute fastest linking speed. It consistently outperforms every other linker in benchmarks. Use lld when you need cross-platform consistency or you are on macOS. It is maintained by the LLVM project and integrates seamlessly with Clang and Rust. Stick with the default system linker when you are building a tiny project with fewer than ten dependencies. The overhead of configuring an alternative linker outweighs the seconds you save. Reach for mold or lld when your release builds take longer than thirty seconds to link. The compiler does the heavy lifting, but the linker finishes the job. Make sure it finishes quickly.

Where to go next