1

motivation

I have a set of steps to build a cross-compiled project (https://github.com/n64decomp/sm64). These steps require e.g. binutils targeting a MIPS platform like e.g. mips-linux-gnu. (Others like mips64-elf or mips64-linux-gnu are allegedly also supported by this project.)

-> I want to make a shell.nix file that, under nix-shell (or nix shell), generates an environment with cross-targeting binutils executables.

One more note: I am compiling on an M1 mac. However the project doesn't support building from aarm64-darwin, so I'm using x86_64-darwin as the build platform under the Rosetta2 compatibility layer.

attempt

I wrote a shell.nix like so:

{ pkgs ? import <nixpkgs> { # https://nixos.org/manual/nixpkgs/stable/#sec-cross-usage localSystem = (import <nixpkgs/lib>).systems.examples.x86_64-darwin; crossSystem = (import <nixpkgs/lib>).systems.examples.mips-linux-gnu; } }: pkgs.mkShell { # stuff I want at build-time # -> package host = project build # -> package target = project host # pulled from https://github.com/n64decomp/sm64#step-1-install-dependencies-1 nativeBuildInputs = [ # doesn't compile code -> no target pkgs.gnumake42 pkgs.coreutils pkgs.pkg-config # compiles -> target = mips-linux-gnu pkgs.binutils ]; shellHook = '' # some other setup commands... ''; } 

Running nix-shell and trying to use any of the dependencies (e.g., make) generates an error like cannot execute binary file: Exec format error. It seems like all the binaries are built to run on mips, not to build for mips.

I also tried to put these dependencies in buildInputs instead. Running the project build then generates the error

ld: archive has no table of contents file 'audiofile/libaudiofile.a' for architecture x86_64 

Imo, this conversely makes it sound like the target for mips-unknown-linux-gnu-ld is x86_64, and NOT mips.

question

How do I rewrite this shell.nix file to specify packages that run on x86_64-darwin, and build for the target mips-linux-gnu?

EDIT: more info

I opened up a nix repl to check what build/host/target my shell would generate:

nix-repl> pkgs = import <nixpkgs> { localSystem = (import <nixpkgs/lib>).systems.examples.x86_64-darwin; crossSystem = (import <nixpkgs/lib>).systems.examples.mips-linux-gnu; } nix-repl> pkgs.stdenv.buildPlatform.config "x86_64-apple-darwin" nix-repl> pkgs.stdenv.hostPlatform.config "mips-unknown-linux-gnu" nix-repl> pkgs.stdenv.targetPlatform.config "mips-unknown-linux-gnu" 

It looks like my build platform is x86_64-darwin, and my host and target platforms are both mips-linux. This sounds right; I am using x86_64-darwin to build this project, and the resulting ROM runs on mips. (It doesn't generate other code, so the target is irrelevant.)

But nix-shell is used for development; when you run nix-shell derivation.nix, it drops you into the build sequence for the derivation. Thus the environment is on the build platform, right? But it seems here like nix-shell shell.nix is generating a host-platform environment. Why is that?

1 Answer 1

1

Solved it! There's a couple things that were going on here, as I now understand it:

  • the audiofile/libaudiofile.a error was an issue with the project's makefile (which doesn't pose issues when building with other package management tools for some reason...?). I modified the project itself to fix this
  • basically all of these dependencies (minus one) are provided by default. the only dependency I really needed was gnumake42, because the version of the default make is incompatible with this project
  • the gnumake42 dependency needed to be in depsBuildBuild. depsBuildHost (a.k.a. nativeBuildInputs) didn't work, not sure why
  • there's allegedly a nix issue when cross-compiling via specifying pkgs {crossSystem = ...}. the "solution" is to use callPackage, though I'm not exactly sure why this fixes the issue 🤔
  • I thought I needed to set the local system to x86_64-darwin for project compatibility, but it turns out removing this to use the default aarm64-darwin platform works fine too (lesson: sometimes the community doesn't know best, and there's no harm in experimenting to validate what they say!)

Here's the resulting shell.nix file, which I can use to correctly build my desired project:

{ pkgs ? import <nixpkgs> { # https://nixos.org/manual/nixpkgs/stable/#sec-cross-usage crossSystem = (import <nixpkgs/lib>).systems.examples.mips-linux-gnu; } }: pkgs.callPackage ({ mkShell , gnumake42 }: mkShell { # pulled from https://github.com/n64decomp/sm64#step-1-install-dependencies-1 depsBuildBuild = [ gnumake42 # v4.4 breaks the build! ]; shellHook = '' # same setup code as before # ... ''; }) { } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.