Skip to content

$CC incorrectly set to cross-compiler when rustToolchain and cross-compiler coexist in mkShell #257

@PeterWang-dev

Description

@PeterWang-dev

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions