mold Linker em Rust: Compilação Mais Rápida | Rust Brasil

Aprenda a usar o mold em projetos Rust para acelerar o link final no Linux, configurar .cargo/config.toml, comparar com LLD e integrar mold na CI e no Docker.

O mold é um dos jeitos mais baratos de reduzir o tempo de compilação de projetos Rust no Linux: ele troca o linkador lento do GNU (ld) por um linkador moderno e paralelo, sem alterar o código-fonte. Depois de instalar o pacote do sistema, basta apontar o Cargo com rustflags = ["-C", "link-arg=-fuse-ld=mold"] em .cargo/config.toml. Em builds incrementais de APIs Axum, workers Tokio e CLIs grandes, a etapa de link costuma cair de dezenas de segundos para poucos segundos.

Este guia mostra o que é o mold linker, como instalá-lo, como configurá-lo com Cargo, como medir o ganho real, como compará-lo com LLD e como usá-lo em CI, Docker e monorepos. O mold não resolve monomorfização, macros procedurais pesadas nem download de crates — ele ataca o gargalo específico do link final, que aparece depois que o rustc já emitiu os objetos.

Quando alguém reclama que “Rust é lento para compilar”, costuma misturar três custos diferentes:

  1. typecheck e borrow check do rustc;
  2. codegen e monomorfização de genéricos (muito comum com Tokio, Serde e hyper);
  3. link do executável ou da biblioteca final.

Em um cargo build frio de um serviço novo, as dependências dominam. Em um cargo build quente — o ciclo “salvei o arquivo e quero ver o resultado” — o linkador vira o vilão. O ld.bfd do binutils é correto e estável, mas não foi desenhado para o ritmo de iteração de um monorepo Rust de 2026.

O mold foi criado exatamente para esse cenário: link paralelo, agressivo em performance e com compatibilidade suficiente para o fluxo diário de desenvolvimento. Em times que publicam várias vezes por dia, cada 20–40 segundos economizados no link se multiplica por dezenas de builds locais e de CI.

Se o seu problema ainda é “a primeira compilação demora 8 minutos”, comece pelo guia de como reduzir o tempo de compilação do Rust, por cargo-chef em Docker e por builds Docker otimizados. O mold entra como peça de alto retorno quando o relatório de timings mostra a barra de link grande.

O que é o mold

mold (A Modern Linker) é um linkador ELF de alta performance, mantido de forma independente e disponível nas principais distribuições Linux. A ideia central é simples: o link de um binário grande tem muito trabalho paralelizable — leitura de objetos, resolução de símbolos, relocações, layout de seções — e o mold aproveita múltiplos núcleos de forma agressiva.

Para quem programa em Rust, o ponto prático é:

  • o rustc gera objetos e pede ao driver que invoque o linker do sistema;
  • com -C link-arg=-fuse-ld=mold, o GCC/Clang-compatible driver usa o mold em vez do ld padrão;
  • o binário resultante continua sendo um ELF normal; você não muda a ABI da aplicação só por trocar o linker de desenvolvimento.

Em outras palavras: mold é otimização de developer experience e de CI, não uma reescrita da runtime do Rust.

mold vs LLD vs ld: qual usar?

LinkerOnde brilhaLimitações típicasQuando preferir
ld (GNU bfd)Compatibilidade máxima, default do sistemaMais lento em projetos grandesFallback e ambientes legados
LLD (LLVM)Portabilidade, integração com toolchain LLVMEm alguns monorepos ainda perde para mold no LinuxmacOS/Windows/Linux com foco em homogeneidade LLVM
moldLink muito rápido no LinuxFoco principal em ELF/LinuxDev local Linux e CI Linux com builds frequentes
goldHistórico como “ld mais rápido”Projeto menos central hojeLegado; prefira mold ou LLD em código novo

Regra prática para times brasileiros rodando Linux em notebooks e em runners de GitHub Actions/Gitea:

  1. meça com cargo build --timings;
  2. se o link for relevante, ative mold no alvo Linux;
  3. mantenha LLD como plano B em imagens mínimas onde mold não esteja disponível;
  4. não force mold em alvos que ele não cobre bem.

Como instalar o mold

Debian, Ubuntu e derivados

sudo apt update
sudo apt install -y mold
mold --version

Fedora

sudo dnf install -y mold
mold --version

Arch Linux

sudo pacman -S mold
mold --version

Instalação via binário / release

Se a distribuição estiver atrasada, baixe o release oficial do projeto mold e coloque o binário em um diretório do PATH (~/.local/bin ou /usr/local/bin). Em imagens Docker enxutas, instale o pacote da distro da imagem-base ou copie o binário em um stage dedicado.

macOS e Windows

No macOS, o caminho mais comum continua sendo o linker da Apple, com lld ou experimentos de linkers rápidos da plataforma. No Windows, o fluxo MSVC usa link.exe ou lld-link. Por isso, a configuração recomendada neste artigo é escopada ao alvo Linux, para não quebrar builds de colegas em outros sistemas.

Configurar mold no Cargo

A forma mais limpa e versionável é o arquivo .cargo/config.toml do repositório (ou do usuário em ~/.cargo/config.toml).

Configuração por alvo Linux

# .cargo/config.toml
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

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

Essa forma é preferível a exportar RUSTFLAGS globalmente, porque:

  • não afeta cargo test de crates que compilam para outro alvo;
  • viaja com o repositório;
  • deixa explícito para o time que a otimização é do host Linux.

Alternativa com clang como linker driver

Em alguns ambientes, especialmente com toolchains customizadas, usa-se:

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

Só adote isso se o default do cc da máquina não estiver encaminhando -fuse-ld=mold corretamente. Em Ubuntu/Debian recentes com build-essential e mold instalados, a primeira configuração costuma bastar.

Conferir se o mold realmente entrou no build

# Limpe artefatos de link anteriores se quiser um teste limpo do executável
cargo clean -p meu_binario

# Build verboso: procure mold na linha de link
cargo build -vv 2>&1 | rg -i 'mold|fuse-ld'

Se a linha de link mostrar fuse-ld=mold ou invocar mold, a configuração está ativa. Se continuar só com ld/collect2 sem mold, revise o alvo (rustc -vV), o caminho do binário mold e se algum wrapper de CI sobrescreve RUSTFLAGS.

Meça antes e depois

Nunca declare vitória por sensação. Use o relatório nativo do Cargo:

cargo build --timings

Abra target/cargo-timings/cargo-timing.html e observe:

  • tempo total;
  • tempo da unidade final (o binário ou a cdylib);
  • quantos segundos ficam na fase de link em relação ao codegen.

Compare três cenários:

  1. build frio (cargo clean + build) — mold ajuda, mas dependências ainda dominam;
  2. build incremental de código (mude uma linha em src/main.rs) — aqui mold brilha;
  3. build após mudança de Cargo.toml/Cargo.lock — muita recompilação de crates; mold ajuda no final, mas não apaga o custo do rustc.

Para números repetíveis:

hyperfine --warmup 1 \
  'cargo build -q' \
  'cargo build -q --release'

Lembre: release e dev têm perfis diferentes. O mold acelera o link nos dois, mas o codegen de --release continua bem mais caro.

mold em workspaces e monorepos

Em Cargo workspaces, o ganho se multiplica porque cada binário (api, worker, cli, migrate) paga um link próprio. Um monorepo com quatro binaries pode invocar o linker quatro vezes no mesmo cargo build --workspace.

Boas práticas:

  • coloque a config de mold na raiz do workspace, não em cada crate;
  • evite misturar RUSTFLAGS diferentes entre crates do mesmo build;
  • se algum membro precisa de flags especiais (por exemplo, cdylib com version script), isole essas flags no alvo/pacote e não desligue o mold para o resto do monorepo sem medir;
  • combine com cargo-nextest na CI: testes mais rápidos + link mais rápido = feedback bem mais curto.

mold na CI

Em runners Linux efêmeros, o mold reduz o tempo do job depois que as dependências já estão cacheadas. A ordem de alavancas continua sendo:

  1. cache de ~/.cargo/registry e git;
  2. cache de compilação (sccache ou cache de target com chave correta);
  3. mold para o link;
  4. paralelismo de testes com nextest;
  5. cargo-chef quando o build roda dentro de Docker.

Exemplo mínimo em um job Debian/Ubuntu:

- name: Install mold
  run: sudo apt-get update && sudo apt-get install -y mold

- name: Configure Cargo to use mold
  run: |
    mkdir -p .cargo
    cat >> .cargo/config.toml <<'EOF'
    [target.x86_64-unknown-linux-gnu]
    rustflags = ["-C", "link-arg=-fuse-ld=mold"]
    EOF

- name: Build
  run: cargo build --locked --all-targets

Se o repositório já versiona .cargo/config.toml com mold, o step de “Configure Cargo” fica desnecessário — o que é o ideal.

Armadilha de RUSTFLAGS na CI

Pipelines que fazem:

export RUSTFLAGS="-D warnings"

podem sobrescrever silenciosamente as flags do .cargo/config.toml dependendo de como as flags são mescladas no ambiente. Prefira:

export RUSTFLAGS="${RUSTFLAGS:-} -D warnings"

ou configure lints no Cargo.toml/[lints] e deixe o mold no config do alvo. Sempre valide com cargo build -vv no job quando o tempo de link “não mudou”.

mold em Docker

Dentro de uma imagem de build:

FROM rust:1-bookworm AS builder
RUN apt-get update \
    && apt-get install -y --no-install-recommends mold \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=-fuse-ld=mold"

# ... COPY manifests, cargo chef cook, COPY src, cargo build --release

Ou grave o .cargo/config.toml no contexto do build. Em multi-stage, o mold precisa existir apenas no stage de compilação; a imagem final de runtime não carrega o linker.

Combine com:

O mold não substitui essas peças: ele só encurta o RUN cargo build --release quando o linker seria o freio de mão.

O que o mold não resolve

Seja honesto com o time — mold não é milagre:

  • não reduz monomorfização de genéricos;
  • não acelera macros procedurais pesadas (serde, prost, async-trait em excesso);
  • não evita baixar crates do crates.io;
  • não substitui sccache entre máquinas;
  • não corrige features desnecessárias em dependências;
  • não melhora tempo de teste por si só (a não ser pelo relink de binários de integração).

Para o restante do pipeline de performance de build e de runtime, use o mapa:

SintomaFerramenta / guia
Link lento no Linuxmold (este guia)
Rebuild Docker recompila depscargo-chef
Mesmas crates recompilam em CIsccache no guia de tempo de compilação
Suíte de testes lentacargo-nextest
Binário grande / features demaisCargo + corte de features
CPU em produção, não no buildprofiling em produção

Checklist de adoção em um projeto real

  • mold --version funciona no host ou na imagem de build;
  • .cargo/config.toml define mold só nos alvos Linux relevantes;
  • cargo build -vv mostra fuse-ld=mold;
  • cargo build --timings foi comparado antes/depois em build incremental;
  • CI instala mold ou usa imagem que já o contém;
  • RUSTFLAGS da CI não apaga a config do mold;
  • macOS/Windows do time não quebram por config global agressiva;
  • Docker multi-stage instala mold só no builder;
  • documentação interna do time menciona a dependência de sistema;
  • release engineering e assinatura de binários continuam iguais (guia de release).

mold e carreira: por que isso aparece em entrevista

Em processos seletivos de backend, plataforma e DevOps, “como você encurta o ciclo de feedback de um monorepo Rust?” é uma pergunta cada vez mais comum. Saber explicar a diferença entre compilar e linkar, citar cargo build --timings, mold/LLD, sccache e cargo-chef mostra maturidade de engenharia — não só de sintaxe da linguagem.

Se você está montando portfólio para o mercado brasileiro, combine esse tipo de otimização prática com projetos publicáveis e com acompanhamento de vagas Rust e empresas que usam Rust. Builds rápidos não substituem ownership e async, mas são o tipo de detalhe que separa quem só “fez o tutorial” de quem já sofreu com CI de verdade.

Conclusão

O mold linker é uma das otimizações de melhor relação esforço/benefício para quem desenvolve Rust no Linux em 2026. A instalação é trivial, a configuração cabe em poucas linhas de .cargo/config.toml e o impacto aparece exatamente no ciclo que mais dói: o build incremental do dia a dia e os jobs de CI que já têm cache de dependências.

Não use mold como desculpa para ignorar features inchadas, Docker sem multi-stage ou testes seriais. Use-o como peça de um sistema: meça com timings, acelere o link com mold, estabilize deps com cargo-chef, reutilize compilação com sccache e paralelize testes com nextest. Esse combo é o que times sérios de Rust colocam de pé quando o produto cresce e o cargo build deixa de ser detalhe.

Perguntas frequentes

O que é o mold linker?

mold é um linkador moderno focado em velocidade, especialmente eficaz em binários ELF no Linux. Em projetos Rust, ele substitui o ld lento na etapa final do cargo build.

Como usar mold com Cargo?

Instale o mold no sistema e adicione ao .cargo/config.toml:

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

Valide com cargo build -vv e meça com cargo build --timings.

mold funciona no macOS?

O foco do mold é Linux/ELF. No macOS, mantenha o linker da plataforma ou LLD e restrinja a config de mold aos alvos *-unknown-linux-gnu.

mold é melhor que LLD?

Em muitos monorepos Linux, sim para tempo de link. LLD ainda é excelente e mais “universal” no ecossistema LLVM. A decisão correta é medir no seu projeto.

mold substitui sccache e cargo-chef?

Não. mold acelera o link; sccache cacheia compilação; cargo-chef cacheia dependências em layers Docker. Combine as três quando cada uma atacar um gargalo real.

Leia também