Cross-compiling with Rust: which packages to use?

I’ve made a buildEnv using the packages: rustc, cargo, gcc, pkgsCross.aarch64-multiplatform.gcc

I get the following error:

cargo build --target x86_64-unknown-linux-gnu
   Compiling hello-rust v0.1.0 
error[E0463]: can't find crate for `std`
  |
  = note: the `x86_64-unknown-linux-gnu` target may not be installed
  = help: consider downloading the target with `rustup target add x86_64-unknown-linux-gnu`

Do I need to add the target as a package?

Also, “x86_64-unknown-linux-gnu-gcc” is missing from /bin. How can I install it?

I’ve tried to search for it on NixOS Search
and it shows up under “libgcc” package, and supposedly provides it, but it’s still missing.
So I’m confused as to how to install these in a idiomatic nixpkgs way.

I tried using runCommand to copy from “pkgsCross.aarch64-multiplatform.gcc”, which also contains gcc. Should I copy them and add “x86_64-unknown-linux-gnu-” prefixes, or what’s the correct way? It seems quite hacky.

The Nix wiki links to an example, but it uses rustup, and I want to use a nix package.
I’m guessing there is no package currently?

Can you post the whole thing? Typically you want to use a correctly configured cross pkgs + callPackage on your pkg accepting any dependencies you need (i.e. stdenv, rustPlatform, etc).

1 Like

I’m not currently trying to build a nix package, but rather just trying to make the std library available (like nix-shell).

But “rustc” package is not designed for cross-compile maybe?

The code is quite convoluted and I’m struggling to see how I could configure it to build the x86 std lib.

Can I just copy the std lib rmeta files/folder from rustc x86 package?

Can you maybe share your current devshell and the project you try to compile within that shell?

It is 100% workable for cross compile. I’m on a plane and can share working rust code later in around 14 hours, assuming no one else helps you first.

@bme That would be great.

@NobbZ

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
  };
  outputs = { self, nixpkgs }:
  let
    systems = ["x86_64-linux" "aarch64-linux"];
  in
  {
    packages = nixpkgs.lib.genAttrs systems (system:
      let
        pkgs = import nixpkgs { system = system; };
      in
      rec {
        example = pkgs.buildEnv {
            name = "example-fs";
            paths = [ 
              rustc
              cargo
              gcc
             ];
          };
      });
  };
}

I use that filesystem in a container.

I don’t currently use nix for building because the core idea is to use offline containers.

cat > Cargo.toml <<EOF
[package]
name = "hello-rust"
version = "0.1.0"
edition = "2024"

[dependencies]
EOF

mkdir src
cat > src/main.rs <<EOF
fn main() {
    println!(
        "Hello from {} ({})",
        std::env::consts::ARCH,
        std::env::consts::OS
    );
}
EOF

mkdir .cargo
cat > .cargo/config.toml <<EOF
[target.x86_64-unknown-linux-gnu]
linker = "x86_64-unknown-linux-gnu-gcc"

[target.aarch64-unknown-linux-gnu]
linker = "aarch64-unknown-linux-gnu-gcc"
EOF
cargo build --target x86_64-unknown-linux-gnu
cargo build --target aarch64-unknown-linux-gnu

I think the above example should work?

I have never tried to have a cross-ready development-shell, but as a datapoint, crate2nix generates files which are cross-ready. For example, I can get a cross compiled nix-du as follows:

nom-build -E 'let pkgs= import <nixpkgs> {}; in pkgs.pkgsCross.aarch64-multiplatform.callPackage ./nix-du.nix {}'

I think this only helps if you are only interested in a cross compiled finished product, which you develop in a native shell.

I never had any success with shells based on buildEnv.

Please prefer a proper mkShell and remove any container abstraction you have.