rust-lang/cargo · error

several matching instances of `target.'cfg(..)'.linker` in c

Error message

several matching instances of `target.'cfg(..)'.linker` in configurations
first match `{}` located in {}
second match `{}` located in {}

What it means

In target_linker (compilation.rs:581-600), Cargo selects a `target.'cfg(...)'.linker` by filtering all configured cfg-linker entries whose cfg key matches the current target. If more than one matches, the linker choice is ambiguous and Cargo bails, printing the first and second matching keys and the config-file locations (definition) that defined each.

Source

Thrown at src/compiler/compilation.rs:591

    // With `target-applies-to-host = true`,
    // host artifacts must fall through to pick up from [target]
    // since this is the stable behavior
    if kind.is_host() && !bcx.gctx.target_applies_to_host()? {
        return Ok(None);
    }

    // Try target.'cfg(...)'.linker.
    let target_cfg = bcx.target_data.info(kind).cfg();
    let mut cfgs = bcx
        .gctx
        .target_cfgs()?
        .iter()
        .filter_map(|(key, cfg)| cfg.linker.as_ref().map(|linker| (key, linker)))
        .filter(|(key, _linker)| CfgExpr::matches_key(key, target_cfg));
    let matching_linker = cfgs.next();
    if let Some((key, linker)) = cfgs.next() {
        anyhow::bail!(
            "several matching instances of `target.'cfg(..)'.linker` in configurations\n\
             first match `{}` located in {}\n\
             second match `{}` located in {}",
            matching_linker.unwrap().0,
            matching_linker.unwrap().1.definition,
            key,
            linker.definition
        );
    }
    Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.gctx)))
}

fn explicit_host_kind(host: &str) -> CompileKind {
    let target = CompileTarget::new(host, false).expect("must be a host tuple");
    CompileKind::Target(target)
}

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Keep only ONE matching cfg-linker entry; remove or narrow the broader expression.
  2. Prefer an exact-triple key (`[target.<triple>.linker]`) over overlapping cfgs.
  3. Run `cargo config get` / inspect layered config files for duplicate linker definitions.
  4. Make cfg conditions mutually exclusive so they cannot both match the same target.

Example fix

// before (.cargo/config.toml)
[target.'cfg(unix)'.linker]
linker = "clang"
[target.'cfg(linux)'.linker]
linker = "gcc"
// both match linux -> error

// after
[target.'cfg(target_os = "macos")'.linker]
linker = "clang"
[target.'cfg(target_os = "linux")'.linker]
linker = "gcc"
Defensive patterns

Strategy: validation

Validate before calling

let matching: Vec<_> = target_cfgs.iter()
    .filter(|(_, c)| c.linker.is_some())
    .filter(|(k, _)| CfgExpr::matches_key(k, &target_cfg))
    .collect();
if matching.len() > 1 {
    return Err(format!("{} target.'cfg(..)'.linker match; disambiguate", matching.len()));
}

Type guard

fn single_linker_match(entries: &[(&str, &Config)]) -> bool {
    entries.iter().filter(|(_, c)| c.linker.is_some()).count() <= 1
}

Prevention

When it happens

Trigger: Defining multiple `[target.'cfg(...)'.linker]` entries (across `.cargo/config.toml`, `~/.cargo/config.toml`, or `--config`) whose cfg expressions both evaluate true for the build target — e.g. `[target.'cfg(unix)'.linker]` and `[target.'cfg(target_arch = "x86_64")'.linker]` both matching an x86_64 linux build.

Common situations: Overlapping linker config from global + project files; cross-compilation setups that add a broad cfg-linker that collides with an existing one; merging team config; combining an exact-triple linker with a cfg-based one that also matches.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/b0da7054d6d14665.json. Report an issue: GitHub.