rust-lang/rust · error

Failed to spawn `as`.

Error message

Failed to spawn `as`.

What it means

This fires in Cranelift codegen's `compile_global_asm` when the environment variable `CG_CLIF_FORCE_GNU_AS` is set. The code spawns the system assembler (`as`, path from `config.assembler`) via `Command::new(&config.assembler).spawn().expect(...)`. If the assembler binary cannot be found in PATH, lacks execute permission, or the OS refuses to spawn it (resource limits, fork failure), the panic fires.

Source

Thrown at compiler/rustc_codegen_cranelift/src/global_asm.rs:233

) -> Result<(), String> {
    assert!(!global_asm.is_empty());

    // Remove all LLVM style comments
    let mut global_asm = global_asm
        .lines()
        .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
        .collect::<Vec<_>>()
        .join("\n");
    global_asm.push('\n');

    // Assemble `global_asm`
    if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() {
        let mut child = Command::new(&config.assembler)
            .arg("-o")
            .arg(&global_asm_object_file)
            .stdin(Stdio::piped())
            .spawn()
            .expect("Failed to spawn `as`.");
        child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
        let status = child.wait().expect("Failed to wait for `as`.");
        if !status.success() {
            return Err(format!("Failed to assemble `{}`", global_asm));
        }
    } else {
        // Escape { and }
        let global_asm = global_asm.replace('{', "{{").replace('}', "}}");

        let mut child = Command::new(std::env::current_exe().unwrap())
            // Avoid a warning about the jobserver fd not being passed
            .env_remove("CARGO_MAKEFLAGS")
            .arg("--target")
            .arg(&config.target)
            .arg("--crate-type")
            .arg("staticlib")
            .arg("--emit")
            .arg("obj")

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Install binutils: `apt-get install binutils` (Debian/Ubuntu) or `apk add binutils` (Alpine).
  2. Remove the `CG_CLIF_FORCE_GNU_AS` environment variable — without it, cg_clif uses rustc+LLVM to assemble global asm instead of spawning `as` directly.
  3. Verify the assembler is in PATH: `which as`.
  4. If cross-compiling, install the cross-assembler (e.g., `gcc-multilib` or the target's binutils).

Example fix

# before (CG_CLIF_FORCE_GNU_AS set but `as` missing → panic)
CG_CLIF_FORCE_GNU_AS=1 cargo build

# after (install binutils, or remove the env var)
# Option A: install binutils
apt-get install -y binutils
# Option B: unset the flag
unset CG_CLIF_FORCE_GNU_AS
cargo build
Defensive patterns

Strategy: validation

Validate before calling

// Before building with global_asm! + CG_CLIF_FORCE_GNU_AS, verify
// the assembler exists:
// which as || { echo 'as not found; install binutils'; exit 1; }
// Rust-side check in build.rs:
// fn main() {
//     if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() {
//         let out = std::process::Command::new("which").arg("as").output();
//         if !out.map(|o| o.status.success()).unwrap_or(false) {
//             panic!("CG_CLIF_FORCE_GNU_AS set but `as` not found. Install binutils.");
//         }
//     }
// }

Try / catch

// In a build script, handle assembler spawn failure gracefully:
use std::process::Command;
let result = Command::new(&assembler).arg("-o").arg(&outfile).spawn();
match result {
    Ok(mut child) => { child.wait().expect("wait failed"); }
    Err(e) => {
        eprintln!("Failed to spawn assembler: {}. Install binutils or unset CG_CLIF_FORCE_GNU_AS.", e);
        std::process::exit(1);
    }
}

Prevention

When it happens

Trigger: Compiling a crate that uses `global_asm!` with the Cranelift backend while `CG_CLIF_FORCE_GNU_AS` is set, and the system assembler (`as`) is not installed or not in PATH. Common on minimal Docker containers, Alpine Linux (uses `as` from binutils), or cross-compilation setups without the target's assembler.

Common situations: Minimal Docker images (e.g., `debian:slim`, Alpine) without `binutils` installed. Cross-compilation where the target's `as` isn't in PATH. Systems where `as` exists but is not executable or the process table is full. Setting `CG_CLIF_FORCE_GNU_AS` to bypass the default LLVM-via-rustc asm path.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/2a347b8709b912f5. Report an issue: GitHub.