---
title: How to Use mold or lld for Faster Linking in Rust
summary: Speed up Rust builds by configuring Cargo to use the faster mold or lld linkers via rustflags in your config file.
lang: en
slug: how-to-use-mold-or-lld-for-faster-linking-in-rust
published: 2026-04-17T14:12:14+00:00
updated: 2026-04-25T22:00:13+00:00
canonical: https://www.rustfaq.org/en/how-to-use-mold-or-lld-for-faster-linking-in-rust/
---

# How to Use mold or lld for Faster Linking in Rust



## 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.

```toml
# .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.

```toml
# .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

- [What is the cost of bounds checking](/en/what-is-the-cost-of-bounds-checking/)
- [How to Use perf and flamegraph with Rust Applications](/en/how-to-use-perf-and-flamegraph-with-rust-applications/)
- [How to Use Shaders with Rust](/en/how-to-use-shaders-with-rust/)