Racket team lead by Matthew Flatt did an awesome work on Chez Scheme such as aarch64 support, that means you can use Chez on Raspberry Pi 400. Problem is Raspberry Pi 400 is very slow, hence it is better to compile things on another machine.

I used to rely on QEMU, LXC, LXD, then Docker, and podman; this tutorial describe the best workflow I know today to test, and build software across distributions, and across architectures.

I work on a Lenovo laptop with Ubuntu, and Alpine on the RasperryPi 400. While I can not claim to be able to reproduce the same environment across distro… I can haz Chez^W letloop where ever that matters thanks to Matthew Flatt, and the other awesome people, and companies making code available on the Internet.

I want to demonstrate how to use systemd’s Linux container wrapper aka. systemd-nspawn, and QEMU, a full hardware emulator that can run any Operating System to compile anything from where you are. Moreover Linux kernel has the ability to run arbitrary executable file formats, and rely on QEMU to execute binaries from other architectures via binfmt_misc. With that ability, it possible to use a root filesystem for a distribution built for any arch supported by QEMU, and nspawn inside it, and then compile Chez (or whatever) with ease.

Note: I tried chroot, and proot, as of 2023, systemd’s nspawn works better. Docker, and podman should work.

On the shoulder of giants, that suite of tools allow to cross compile anything from your host with a recent Linux kernel, systemd, QEMU, a rootfs, and that is done without the need to change the build scripts of the software you want to compile.1

To get started on Ubuntu Jammy 22.04, you need the help of apt:

#;sh> sudo apt install systemd-container qemu-user-static

Canonical makes available several root filesystem for several architectures, here we will use Alpine arm64 available at:


Pick the latest, you will be good.

Somewhere in your home directory, extract that archive, like:

#;sh> mkdir -p ~/rootfs/alpine/3.17/arm64/
     #;sh> cd ~/rootfs/alpine/3.17/arm64/
     #;sh> wget https://uk.lxd.images.canonical.com/images/alpine/3.17/arm64/default/20230412_13:02/rootfs.tar.xz
     #;sh> tar xf rootfs.tar.xz

Before calling tar, you may verify the file rootfs.tar.gz with the hash found in the file next to it called SHA256SUM.

As of 2023, you still need sudo rights to use systemd-nspawn,2 once you hit enter, you will enter Alpine arm64 from your host:

#;sh> sudo systemd-nspawn --uuid=$(systemd-id128 new) -D $(pwd)
     [sudo] password for amirouche:
     Spawning container blog on /home/amirouche/rootfs/blog.
     Press ^] three times within 1s to kill container.

You can triple check that it is indeed arm64^W aarch64 with the following:

alpine:~# uname -a
     Linux blog 5.19.0-38-generic #39~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar 17 21:16:15 UTC 2 aarch64 Linux

We will proceed with compiling Chez, before, let’s install dependencies, among other things, git:

alpine:~# apk add build-base git lz4-dev libuuid util-linux-dev zlib-dev

Then the usual hip command line dance hop that may take a while:

alpine:~# git clone https://github.com/racket/chezscheme
     alpine:~# cd chezscheme
     alpine:~# ./configure --threads --disable-x11 --disable-curses
     alpine:~# make -j $(nproc)
     alpine:~# make install
     alpine:~# scheme --version

Let there be loops ;-)

  1. Look into “cross compilation late night hell” if you want to know how hard that can be↩︎

  2. Send me an email if that change↩︎