Introduction

Rust relies on an external linker (typically cc, gcc, or clang) to produce final executables. When the linker is not installed or not in the PATH, cargo build fails with a linker error. This commonly occurs on minimal Docker images, fresh development machines, or CI environments where build tools are not pre-installed.

Symptoms

  • linker cc not found or linker gcc not found
  • could not find native static library during build
  • Build succeeds with cargo check but fails with cargo build
  • Error occurs when compiling crates with C dependencies (e.g., openssl-sys, libz-sys)
  • Works on one machine but not another

error: could not compile my-project due to previous error ```

Common Causes

  • Build tools (gcc, make) not installed on fresh system
  • Minimal Docker image (alpine, distroless) without compiler toolchain
  • Cross-compilation target requires a different linker
  • PATH does not include the linker location
  • MSVC build tools not installed on Windows

Step-by-Step Fix

  1. 1.Install build tools on your platform:
  2. 2.```bash
  3. 3.# Ubuntu/Debian
  4. 4.sudo apt update && sudo apt install -y build-essential pkg-config

# Alpine Linux apk add --no-cache build-base pkgconfig

# Fedora/RHEL sudo dnf groupinstall "Development Tools" sudo dnf install pkg-config

# macOS xcode-select --install

# Windows (MSVC) # Install "Build Tools for Visual Studio 2022" with C++ workload # Or use: winget install Microsoft.VisualStudio.2022.BuildTools ```

  1. 1.Install platform-specific library dependencies:
  2. 2.```bash
  3. 3.# For openssl-sys
  4. 4.sudo apt install -y libssl-dev pkg-config # Debian/Ubuntu
  5. 5.sudo dnf install -y openssl-devel pkg-config # Fedora

# For libz-sys sudo apt install -y zlib1g-dev # Debian/Ubuntu

# For libsqlite3-sys sudo apt install -y libsqlite3-dev # Debian/Ubuntu ```

  1. 1.Configure alternative linker in Cargo config:
  2. 2.```toml
  3. 3.# .cargo/config.toml
  4. 4.[target.x86_64-unknown-linux-gnu]
  5. 5.linker = "clang"

[target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc" ```

  1. 1.**Use cargo-zigbuild for cross-compilation**:
  2. 2.```bash
  3. 3.cargo install cargo-zigbuild
  4. 4.cargo zigbuild --target x86_64-unknown-linux-gnu
  5. 5.cargo zigbuild --target aarch64-unknown-linux-gnu
  6. 6.`
  7. 7.For minimal Docker images, use multi-stage builds:
  8. 8.```dockerfile
  9. 9.# Build stage
  10. 10.FROM rust:1.76-slim AS builder
  11. 11.RUN apt-get update && apt-get install -y pkg-config libssl-dev
  12. 12.WORKDIR /app
  13. 13.COPY . .
  14. 14.RUN cargo build --release

# Runtime stage FROM debian:bookworm-slim COPY --from=builder /app/target/release/my-app /usr/local/bin/ CMD ["my-app"] ```

Prevention

  • Document required system dependencies in README
  • Use cargo chef for Docker layer caching with proper dependency installation
  • Add CI checks that verify build tools are present
  • Use pre-built binaries when available (e.g., ring has pre-built artifacts)
  • Pin your base Docker image to include build tools
  • Consider musl targets for fully static binaries: rustup target add x86_64-unknown-linux-musl