In which I compile snippets of useful Nix code
Cross-Compiling Arm Assembly in a Nix Flake
We want to compile this trivial assembly targeting ARM assembly on a x86_64
Linux machine (running Debian 12 with Nix in this case):
.global main
.type main, %function
main:
mov w0, #123
ret
The assembly file is in a file called src/main.s
.
The program return 123 as a status code, so we can check whether the program
ran correctly later by checking echo $?
in bash or similar. We can run the
program using qemu-aarch64
(not qemu-system-aarch64
) to emulate an ARM CPU
and corresponding Linux user land, instead of having to spin up a virtual
machine – quite handy when reverse engineering binaries on an x86_64
host.
We want to work with a Nix flake here. That
means better support for different targets, and the ability to have better
reproducibility between builds, as all Nix dependencies are fixed in a
flake.lock
file.
I also want to use flake-utils for an easier time specifying the flake file.
{
description = "Arm64 (aarch64) cross-compile demo";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
crossSystem = {
config = "aarch64-unknown-linux-gnu";
};
};
in
{
packages = rec {
cross-arm-64-asm = pkgs.callPackage
({ stdenv, gcc }:
stdenv.mkDerivation {
name = "cross-arm-64-asm";
nativeBuildInputs = [
gcc
];
phases = [ "buildPhase" "installPhase" ];
buildPhase = ''
$CC -march=armv8-a ${./src/main.s} -o main
'';
installPhase = ''
mkdir -p $out/bin
cp main $out/bin
'';
}
)
{ };
default = cross-arm-64-asm;
};
}
);
}