OsDev?
This post is a little bit in theme with my started and forgotten about OsDev series. However as it doesn’t really fall in line with the project outline set in the abstract, I am not going to categorize it under there as of right now.
Anyway, what am I trying to do? I recently got a Raspberry Pi 5 and of course I wanted to run baremetal Rust on it. As at the time of writing, I wasn’t able to find any libraries to help me in this endeavour and I’ve gotten more interested in lower level languages, I wanted to get assembly working on it first. As my main workstation is on x86_64
architecture and Raspberry Pi is on aarch64
, I needed a cross compiler. And of course, I needed to do it the Nix way.
Nix-y cross compilers
First I tried to go the nix-shell
way as I’ve kind of fallen for them, but it made everything very confusing for me. I couldn’t find the exact packages in the repository. So I knew I needed to use flakes.
There are many thorough explanations on the internet for what flakes are so I’ll save you of the long explanation here. Basically I think of flakes as functions taking package versions (ex. nixpkgs branches) as input and producing specific packages as output.
The flake
WARNING! This code is written with the help of AI.
flake.nix
{
description = "RPI 5 cross-compiler toolchain";
inputs = {
nixpkgs.url = "nixpkgs/nixos-25.05";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
hostSystem: let
pkgs = import nixpkgs {
system = hostSystem;
};
crossToolchain = import nixpkgs {
system = hostSystem;
crossSystem = {
config = "aarch64-unknown-none-elf";
};
};
toolchain = pkgs.symlinkJoin {
name = "aarch64-none-elf-toolchain";
paths = with crossToolchain.buildPackages; [
# cross compiler packages
binutils
#gcc
];
};
devtools = pkgs.mkShell {
packages = with pkgs; [
# Add your own packages for the normal devenv here
#rustup
#bacon
just
rpi-imager
];
};
in {
packages.default = toolchain;
devShells.default = devtools;
}
);
}
- copy the file to your project’s
flake.nix
- run
nix build
to build the cross compiler (creates a symlink./result
to the nix store) - run
nix develop
to enter the development shell
The flake also uses flake-utils
, which should enable the flake to work on every supported architecture.
Problems remain…
Seems okay right? I got a “Hello world” working on qemu so the cross-compilation is working right, but have yet to make sure the program works on the Pi. If I get it working, I am writing a new post with more detail about the specific build process, the boot process and configuration of Raspberry Pi 5 and whatever else I learn. Maybe this project will integrate into the OsDev project someday, who knows…