Problem
When using mkShell with both a Rust toolchain and a cross-compiler for a different target (e.g. riscv32), $CC is incorrectly set to the cross-compiler instead of the native compiler.
This is a common scenario for embedded/simulator development where you need:
- A Rust toolchain to build the simulator (native, x86_64)
- A cross-compiler to build test programs (target, e.g. riscv32)
Minimal Reproduction
# shell.nix
let
pkgs = import (fetchTarball "https://nixos.org/channels/nixos-25.11/nixexprs.tar.xz") {};
pkgsOverlay = pkgs.appendOverlays [
(import (fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz"))
];
in pkgs.mkShell {
packages = [
pkgsOverlay.rust-bin.stable.latest.default # Rust toolchain for the simulator
pkgs.pkgsCross.riscv32.buildPackages.gcc # Cross-compiler for test programs
];
}
$ nix-shell --pure shell.nix --run 'echo "CC=$CC CC_FOR_BUILD=$CC_FOR_BUILD"'
CC=riscv32-unknown-linux-gnu-gcc CC_FOR_BUILD=gcc
# Expected: CC=gcc, or at least CC_FOR_BUILD should be the cross-compiler
Without rustToolchain in packages:
CC=gcc CC_FOR_BUILD=
# Correct
Without cross-compiler in packages:
CC=gcc CC_FOR_BUILD=
# Correct
Analysis (AIGC, but seems correct)
The root cause is in lib/mk-aggregated.nix:
# Workaround: should be `pkgsHostHost.cc` but `stdenv`'s cc itself have -1 offset.
depsHostHostPropagated = [ stdenv.cc ];
This writes the native gcc into propagated-host-host-deps. During setup.sh's findInputs, when processing the rust toolchain's propagated dependencies, the offset math causes the native gcc to be registered with targetOffset=-1 (BUILD role, setting CC_FOR_BUILD=gcc). Later, defaultNativeBuildInputs tries to register the same native gcc with targetOffset=0 (HOST role, which would set CC=gcc), but findInputs's deduplication skips it because the store path is already registered. The cross-compiler's setup-hook (which sets CC=riscv32-...-gcc) is therefore left unoverridden.
Environment
- nixpkgs: nixos-25.11
- rust-overlay: master (current as of 2026-04-25)
- Host: x86_64-linux
Problem
When using
mkShellwith both a Rust toolchain and a cross-compiler for a different target (e.g. riscv32),$CCis incorrectly set to the cross-compiler instead of the native compiler.This is a common scenario for embedded/simulator development where you need:
Minimal Reproduction
Without
rustToolchainin packages:Without cross-compiler in packages:
Analysis (AIGC, but seems correct)
The root cause is in
lib/mk-aggregated.nix:This writes the native gcc into
propagated-host-host-deps. Duringsetup.sh'sfindInputs, when processing the rust toolchain's propagated dependencies, the offset math causes the native gcc to be registered withtargetOffset=-1(BUILD role, settingCC_FOR_BUILD=gcc). Later,defaultNativeBuildInputstries to register the same native gcc withtargetOffset=0(HOST role, which would setCC=gcc), butfindInputs's deduplication skips it because the store path is already registered. The cross-compiler's setup-hook (which setsCC=riscv32-...-gcc) is therefore left unoverridden.Environment