Reputation: 2515
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.
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
.
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
?
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?
Upvotes: 1
Views: 431
Reputation: 2515
Solved it! There's a couple things that were going on here, as I now understand it:
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 thisgnumake42
, because the version of the default make
is incompatible with this projectgnumake42
dependency needed to be in depsBuildBuild
. depsBuildHost
(a.k.a. nativeBuildInputs
) didn't work, not sure whypkgs {crossSystem = ...}
. the "solution" is to use callPackage
, though I'm not exactly sure why this fixes the issue 🤔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
# ...
'';
})
{ }
Upvotes: 1