rust-lang/rust · critical
TARGET was not set
Error message
TARGET was not set
What it means
Thrown at build.rs:224 via `env::var("TARGET").expect("TARGET was not set")`. Cargo normally exports TARGET (the triple being built for) to every build script as part of its documented environment; rustc_llvm uses TARGET pervasively (cross-compile detection at build.rs:226, platform-specific linking in build.rs:348-547). Its absence means the build script is not running under a normal Cargo invocation, so the contract is broken.
Source
Thrown at compiler/rustc_llvm/build.rs:224
//
// In that case, there's no guarantee that we can actually run the target,
// so the build system works around this by giving us the LLVM_CONFIG for
// the host platform. This only really works if the host LLVM and target
// LLVM are compiled the same way, but for us that's typically the case.
//
// We *want* detect this cross compiling situation by asking llvm-config
// what its host-target is. If that's not the TARGET, then we're cross
// compiling. Unfortunately `llvm-config` seems either be buggy, or we're
// misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will
// report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This
// tricks us into thinking we're doing a cross build when we aren't, so
// havoc ensues.
//
// In any case, if we're cross compiling, this generally just means that we
// can't trust all the output of llvm-config because it might be targeted
// for the host rather than the target. As a result a bunch of blocks below
// are gated on `if !is_crossed`
let target = env::var("TARGET").expect("TARGET was not set");
let host = env::var("HOST").expect("HOST was not set");
let is_crossed = target != host;
let components = output(Command::new(&llvm_config).arg("--components"));
let mut components = components.split_whitespace().collect::<Vec<_>>();
components.retain(|c| OPTIONAL_COMPONENTS.contains(c) || REQUIRED_COMPONENTS.contains(c));
for component in REQUIRED_COMPONENTS {
if !components.contains(component) {
panic!("require llvm component {component} but wasn't found");
}
}
for component in components.iter() {
println!("cargo:rustc-cfg=llvm_component=\"{component}\"");
}
// Link in our own LLVM shims, compiled with the same flags as LLVMView on GitHub (pinned to 22057b88b0)
Solutions
- Run the build through cargo or bootstrap (`./x.py build`) so Cargo injects TARGET and the other standard build-script variables.
- If invoking the build script manually for debugging, export the variables Cargo would: `TARGET=<triple> HOST=<triple> ... ./build-script-build`.
- Check that no wrapper script or container is sanitizing the environment passed to the build script.
Defensive patterns
Strategy: validation
Validate before calling
# TARGET is set by cargo/x.py; running build.rs standalone leaves it unset
[ -n "${TARGET:-}" ] || { echo "TARGET not set: invoke via './x.py build' or 'cargo build', not rustc directly"; exit 1; } Prevention
- Always build rustc_llvm through ./x.py or cargo, which populate TARGET
- Never execute the build.rs as a standalone binary
- In CI, assert `env | grep -q TARGET` before the build step
When it happens
Trigger: Running the build script through a mechanism that does not set Cargo's standard build-script environment variables — e.g. invoking the compiled build script binary directly, or wrapping cargo in a way that strips env vars. Under normal `cargo build`/`./x.py`, Cargo always sets TARGET.
Common situations: Debugging by executing `./target/debug/build/rustc_llvm-<hash>/build-script-build` by hand; sandboxed/containers that filter the environment; broken custom build orchestration layered on top of cargo.
Related errors
- HOST was not set
- REAL_LIBRARY_PATH_VAR
- command did not execute successfully: {:?} expected success,
- LLVM_CONFIG was not set
- wrong command used for building
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/95b26fe77cafec6f.json.
Report an issue: GitHub.