Skip to content

Cross-compile an RT kernel and deploy it to a headless Pi

Building natively on a Pi 4 takes hours. Cross-compiling on a normal workstation takes about forty minutes. And if you’ve never done it, the scary part isn’t the build — it’s that a bad kernel on a headless box means physically extracting the SD card. This page addresses both.

Terminal window
sudo apt install crossbuild-essential-arm64 bc bison flex libssl-dev make \
libc6-dev libncurses5-dev
Terminal window
git clone --depth=1 --branch rpi-6.12.y \
https://github.com/raspberrypi/linux.git
cd linux

Use Raspberry Pi’s tree, not vanilla. RPi’s PREEMPT_RT is already merged in 6.12 and the board’s DT/overlays live there.

Terminal window
export ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
make bcm2711_defconfig # Pi 4
scripts/config --enable PREEMPT_RT
scripts/config --set-str LOCALVERSION "-rt-cuckoo"
make olddefconfig

Now apply the patch — this is the whole reason you’re building a kernel rather than installing one.

Terminal window
make -j$(nproc) Image modules dtbs
Terminal window
# Note the ABSOLUTE path. `~` does not expand inside a make variable —
# INSTALL_MOD_PATH=~/out silently installs into a literal "~" directory
# and you end up shipping an 80 KB tarball that contains nothing.
make INSTALL_MOD_PATH=/home/you/out modules_install
tar -C /home/you/out -czf rt-modules.tar.gz lib/modules/
gzip -c arch/arm64/boot/Image > kernel-rt.img.gz

The rule: never overwrite the kernel that currently boots.

Terminal window
scp kernel-rt.img.gz rt-modules.tar.gz pi@host:/tmp/
ssh pi@host
sudo tar -C / -xzf /tmp/rt-modules.tar.gz
zcat /tmp/kernel-rt.img.gz | sudo tee /boot/firmware/kernel-rt.img > /dev/null

kernel8.img — the stock kernel — is untouched. Then add one line to /boot/firmware/config.txt:

kernel=kernel-rt.img
Terminal window
sudo reboot
Terminal window
$ uname -a
Linux gps-ntp 6.12.x-rt-cuckoo #1 SMP PREEMPT_RT ... aarch64