Skip to content

pixi-build-rust: cross-compiling aarch64 → linux-64 fails with cc1: error: unknown value 'nocona' for '-march' (HOST CFLAGS leaking into BUILD-platform compiles) #6942

Description

@toprinse

Checks

  • I have checked that this issue has not already been reported.

  • I have confirmed this bug exists on the latest version of pixi, using pixi --version.

Reproducible example

Reproducer

No ARM hardware needed - runs on GitHub's free ubuntu-24.04-arm runners:
pixi-cc-leak-reproducer

The repro crate mirrors the shape that triggered this for us in practice (git-cliff-core -> include-flate-codegen -> zstd-sys), reduced to the essential mechanism: a proc-macro = true crate depending on a crate whose build.rs calls cc::Build::new().compile(..).

Issue description

Summary

Cross-compiling a Rust package with pixi-build-rust from an aarch64 machine to a linux-64 (x86-64) target fails whenever the crate graph includes something compiled for the BUILD platform (proc-macros, build-dependencies with native code) that goes through the cc crate. The build machine's own compiler ends up receiving a -march=nocona -mtune=haswell flag meant for the HOST (x86-64) target, which its aarch64 gcc rejects:

cc1: error: unknown value 'nocona' for '-march'

Confirmed test matrix

BUILD runner HOST target (--target-platform) Result
x86-64 (local machine) linux-aarch64 ✅ works
CI, amd64 runner linux-aarch64 ✅ works
CI, aarch64 runner linux-aarch64 ✅ works
CI, aarch64 runner linux-64 ❌ fails

Only the "aarch64 building for x86-64" direction fails, and only because x86-64's conda-forge activation sets a microarchitecture baseline (-march=nocona -mtune=haswell) while aarch64's does not - there's nothing to leak in the reverse direction.

Root cause

conda-forge's cross-compilation activation scripts follow a convention: unsuffixed CC/CFLAGS are scoped to HOST (the platform being built for); CC_<triple>/CFLAGS_<triple> are scoped to BUILD (the machine actually running the compiler - used for proc-macros and build scripts, since those always execute natively regardless of the overall cross-compilation target).

cc-rs (the cc crate almost every native-code build script uses) resolves these two kinds of variables differently:

  • CC/AR: first-match-wins across CC_<triple>, then generic CC (getenv_with_target_prefixes).
  • CFLAGS/CXXFLAGS: all matching variables are concatenated (envflags()) - generic CFLAGS first, then the more specific CFLAGS_<triple>. The specific one does not override the generic one, it's appended to it.

So a proc-macro's native build-dependency, correctly compiled for BUILD (aarch64) with a clean CFLAGS_aarch64_unknown_linux_gnu, still receives the HOST-scoped generic CFLAGS (-march=nocona -mtune=haswell, meant for x86-64) on top - and its aarch64 compiler rejects it.

This is visible directly in cc-rs's own debug output from a real failing
CI run:

CC_aarch64_unknown_linux_gnu = Some(aarch64-conda-linux-gnu-cc)
CFLAGS_aarch64_unknown_linux_gnu = Some(-isystem $BUILD_PREFIX/include)      <- clean
CFLAGS = Some(-march=nocona -mtune=haswell ...)                              <- leaks in anyway
aarch64-conda-linux-gnu-cc: error: unknown value 'nocona' for '-march'

Current workaround

Forcing clean flags via a cargo config.toml (stripping -march=nocona -mtune=haswell) works but throws away the intended tuning for the real
HOST target too, not just the BUILD-platform proc-macro compiles.

Possible fix direction

Since cc-rs itself won't let a specific CFLAGS_<triple> override the generic one, the fix likely has to happen in pixi-build-rust's generated build script: when actually cross-compiling (BUILD != HOST), wrap CC_<build-triple>/CXX_<build-triple> so the wrapper strips HOST-only microarchitecture flags (-march=, -mtune=, -mcpu=, -mfpu=, -mfloat-abi=, Apple's -arch <value>) from argv before invoking the real compiler, leaving generic CFLAGS/CXXFLAGS (and HOST-target compiles) untouched. Happy to submit a PR along these lines if that approach sounds right.

Expected behavior

Cross-compiling from aarch64 runner to amd64 package should produce correct x86_64 package

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions