← Debugging Guides

阅读中文版本

Rust — linking with cc failed

Diagnose Rust linker errors from missing native libraries, wrong target toolchains, feature flags, or duplicate symbols, and fix the build environment.

advanceddebuggingrustbuild-tools

Symptoms

  • error: linking with `cc` failed: exit status: 1
  • undefined reference to `...`
  • The crate builds on one machine but fails in CI or in a container
  • The failure appears after adding a -sys crate or changing the target

Possible causes

  • A native library or its development headers are missing
  • pkg-config cannot find the library or returns the wrong version
  • The build target uses musl while a dependency only supports glibc
  • A feature enables a system library that is not installed
  • Duplicate symbols from two crates or a stale build cache

Diagnosis steps

Read the linker invocation and the first undefined symbol

cargo build -vv 2>&1 | grep -B5 -A10 'undefined reference\|linking with'

Interpretation

The first undefined reference names the missing symbol or library; later errors are usually consequences.

Check native dependencies and pkg-config

pkg-config --modversion LIBRARY || echo missing

Interpretation

A missing .pc file or development package explains a link failure for -sys crates.

Compare the target and toolchain

rustc -vV && cargo build --target x86_64-unknown-linux-musl

Interpretation

A musl target with a glibc-only dependency often fails; reproduce with the exact CI target.

Root cause

The Rust compiler could not link the final binary because a native library, symbol, or target toolchain was missing or incompatible. The error is in the build environment or feature configuration, not in Rust syntax.

Fix

Install the missing development package, fix pkg-config paths, choose a compatible target, enable only the needed features, or clean the target directory after a toolchain change. Pin the CI image to include the native dependencies.

Risk note

Adding a linker flag to ignore undefined symbols can produce a binary that crashes at runtime. Fix the actual dependency.

Verify the fix

Run a clean build in the same container or CI image, then run the binary and its tests. Confirm the dynamic libraries resolve with ldd on Linux, and build the same target locally to reproduce and verify the fix.

The linker is the last step

Rust compiles successfully and then invokes the system linker to produce a binary. A link failure means the compiler could not resolve a symbol or find a library. Read the first undefined reference or the -l flag in the invocation; the later output is usually a cascade.

undefined reference to `SSL_new'
collect2: error: ld returned 1 exit status

Native dependencies and pkg-config

A -sys crate wraps a C library. It needs the library and its headers, and often pkg-config metadata. In a slim container, install the -dev or -devel package and verify pkg-config --modversion. Set PKG_CONFIG_PATH if the library is in a nonstandard prefix. Do not vendor a binary without matching headers.

Target and toolchain

A musl target produces a static binary but some dependencies require glibc or a system library that musl does not provide. Build the same target in CI and locally. After changing the toolchain or features, run cargo clean if stale objects or flags may be cached. Reproduce with cargo build -vv and keep the command in the issue.

Verify the artifact

Run the binary and its tests in the target environment; a successful link does not prove the runtime loader can find shared libraries. Use ldd on Linux or inspect the binary’s dependencies. Build in a clean container to ensure the fix is in the image, not only on a developer machine.