Projects¶
Each project lives in its own directory under
experiments/ with a project.json,
a golden reference and its results. This page records what each one is and what it needed from the
toolkit; the numbers are on Results.
| Project | Buildroot | Target | Packages | Status |
|---|---|---|---|---|
| helloworld | 2025.02.18 | aarch64, musl, external toolchain | 29 | full matrix done |
| superduperbird | 2024.05.3 | aarch64, glibc, internal toolchain | 98 | matrix in progress |
| funkey-os | 2021.02 (vendor fork) | 32-bit ARM, musl, external toolchain | 143 | model and sources ready |
| home-assistant-os | 2024.02 (vendor fork) | aarch64, glibc, internal toolchain | 205 | model ready, sources pending |
Candidates for the next ports are summarised in Candidates at the end of this page.
helloworld¶
A minimal image written for developing the toolkit: Bootlin's external musl toolchain, BusyBox
init, and one local package (hello, sources in common/). It has a QEMU boot test
(tests/test-tier0.py) that asserts the guest architecture and the program's output. Its native
list covers the whole dependency closure of hello (12 packages, including the toolchain trio), so it
is the reference for what a native package looks like.
superduperbird¶
nd-0r/superduperbird-buildroot, firmware for the
Spotify Car Thing (Amlogic S905D2), pinned at commit fcc1ef9. An internal glibc toolchain, a 4.9 vendor
kernel, Mesa (mesa3d), SDL2, avahi, OpenSSH and a Rust host toolchain (host-rust-bin), for 98 packages
and 199 Buck2 actions. The rootfs is a tar.
What it needed:
extra_viewfor hidden references:util-linuxincludes the makefile of its child directoryutil-linux-libs(found only by the remote view check: a directory bind exposes the child locally, but the worker has only declared files),gettext-tinyreadsgettext-gnu,avahireadspython3,gcc-initialandgcc-finalread thepackage/gccgroup directory,autoconfreadsautomake,rust-binreadsrustc,util-linuxreadsncurses,linuxreadsuboot-tools,skeleton-init-commonreadsmkpasswd.heavy: both GCC builds, the kernel, Mesa, host CMake and host Python, so two of them never overlap (an out-of-memory kill otherwise).- A kernel-release stub: the rootfs action runs
depmod, whosekernelreleaseprobe needs the kernel's build tree, which is not part of the rootfs action's inputs. manifest_ignorefor/etc/shadow: the root password hash has a random salt on every build.- Vendored sources, because some downloads are git checkouts or have only SHA-512 hashes.
- One oversized source:
googlefontdirectorydownloads the wholegoogle/fontsrepository at one commit (965 MB compressed, 1.9 GB extracted) to install a single family,ufl/ubuntu(2.9 MB in the image). The recipe cannot fetch a subset. It is faithful to Buildroot, costs one large upload per cache and one 1.9 GB extraction, and it sets the minimum block size of the Buildbarn storage (Sizing the storage). - Three deviations from the project's defconfig, in
notes: no post-image script, an older kernel config that builds at the pinned commit, and the device-tree settings the external tree's hook needs.
funkey-os¶
FunKey-OS 2.3.0, firmware for the FunKey S handheld
(Allwinner V3s, Cortex-A7). The external tree is the FunKey/ directory of a monorepo, built on the
FunKey fork of Buildroot (2021.02), pinned by the monorepo's git submodule. A prebuilt musl toolchain is
downloaded as an external toolchain, so nothing compiles a compiler, and the image is small (143
packages, 150 vendored sources).
What it needed from the toolkit, all of it because the Buildroot tree is old:
buildroot.commitandexternal_repo.subdirinproject.json.- A
printvarsfallback whereshow-varsdoes not exist, andbuild_dirwhereshow-infohas nostamp_dir. - A raised stack limit: GNU make 4.3 segfaults in the old
printvars. FORCE_UNSAFE_CONFIGURE=1: the oldhost-tarrefuses to configure as root.
home-assistant-os¶
Home Assistant OS 18.3, generic aarch64 (UEFI)
board. The external tree is buildroot-external/ of the monorepo, on the Home Assistant fork of
Buildroot (2024.02), with an internal glibc toolchain, systemd, Docker and containerd, RAUC, NetworkManager,
and a mainline 6.18 kernel built with LTO: 205 packages, including Go-based ones.
Deviations, in notes: no ccache (its directory is outside the build), no post-image script (it
assembles disk images), and a tar rootfs in place of EROFS so the manifest scanner can read it.
What it needed so far: local package sources that live inside the external tree
(package/hassio), which the extractor now accepts. Downloading Go module sources runs make source, which
builds a Go toolchain, and the log showed parts of the compiler being built too, as a side effect (probably
through host-go's dependencies); that makes br2 fetch expensive on this project.
Candidates¶
Projects not started yet, each chosen because it covers something the four above do not. The four ported projects share a shape: one external tree, one Buildroot pin, and a toolchain that is either a downloaded external musl one or an internal glibc one. The table is ordered by my estimate of value per unit of effort; the sections below it carry the evidence.
| Project | Buildroot | Target | Packages | Value for migration |
|---|---|---|---|---|
| Bottlerocket SDK | 2025.05.1, patched | x86_64, aarch64; glibc, musl | 33, 32 | High. Smallest real project; toolchain-only build; patched tree |
| Nerves (rpi4) | 2026.05.3, patched | aarch64, glibc, no init | not measured | High. Newest Buildroot; Erlang runtime; build driven by a wrapper |
| In-tree QEMU defconfigs | any release | x86_64, riscv64, mips64el, ppc64le | 63 to 69 | High. Four architectures, no external tree, lowest effort |
| Microchip | 2025.02.16 or 2025.02-mchp fork | riscv64, arm; glibc | 192, 320 | Medium-high. Vendor BSP with U-Boot, genimage, systemd; two Buildroot flavours |
| STMicroelectronics | 2025.02.12 | arm, aarch64; glibc | 72, 145 | Medium. TF-A, OP-TEE, U-Boot, Qt5, genimage; four vendor forks |
| Buildroot test suite | any release | many, QEMU | small each | Medium. Many tiny images; needs config extraction from Python |
| In-tree noMMU defconfigs | any release | riscv64, xtensa; uClibc | 64 | Medium, risky. FLAT binaries, initramfs; may break ELF assumptions |
| OpenIPC | 2024.02.10 | mipsel and others; musl | not measured | Medium. MIPS, external musl toolchain, many chip variants |
| Thingino | fork, 2026.08-rc3 | Ingenic MIPS | not measured | Medium. MIPS, submodule pin, 178 camera configs |
| Milk-V Duo SDK | 2021.05 vendored | riscv64, musl | 133 | Medium. RISC-V; Buildroot buried in a large SDK; stale |
| SkiffOS | fork, 2026.11-git | many boards | not measured | Medium. Layered configuration selected at build time |
| thingOS | 2021.11 vendored | arm, glibc | 114 | Low-medium. Small and old; overlaps FunKey-OS |
| motionEyeOS | 2020.05.1 vendored | arm, glibc | 171 | Low-medium. Oldest tree; unmaintained; Python-heavy |
| Batocera | fork, 2026.05-git | x86_64, many ARM SoCs | not measured | Low-medium. Stress test, not a first port |
| Knulli | fork, 2024.11 | ARM handhelds | not measured | Low. Archived, and a Batocera derivative |
Not candidates, because they only look like Buildroot: OpenWrt (forked in 2004, incompatible package format), LibreELEC, Lakka and CoreELEC (their own build system), and Yocto-based projects such as AGL, BalenaOS and OpenSTLinux.
How these numbers were taken¶
- Packages is the number of entries
make show-inforeports for the named defconfig, host packages included. In-tree defconfigs were measured on the 2025.02.18 tree the helloworld experiment uses. External projects were measured on the Buildroot version they pin. The toolkit's own count may differ by a few. - Not measured means the image is assembled by a wrapper (a Makefile, a script, an environment the defconfig depends on) that I did not run.
- Value is a judgement. It weighs what the project adds that the four ported ones do not, against how much toolkit work it probably needs. Statements about what a project "would need" are inferences from the toolkit's project.json keys, not tried ports.
- Activity and stars are from GitHub on 2026-09-21.
Bottlerocket SDK¶
bottlerocket-os/bottlerocket-sdk, the
toolchain and host tools AWS uses to build Bottlerocket. Not a firmware image.
- Buildroot: upstream 2025.05.1 downloaded as a tarball (hash in
hashes/buildroot), with a patch series frompatches/buildroot(sysroot and tools-directory controls for binutils and gcc). - Configs: four defconfigs in
configs/buildroot/:sdk_{x86_64,aarch64}_{gnu,musl}. - Size: 33 packages for
x86_64_gnu, 32 foraarch64_musl, measured on the unpatched tree. - Contents: GCC 13.4.0, binutils 2.44, glibc 2.41 or musl 1.2.5, Linux headers 6.1.147, built in a Fedora 43 builder image.
- Activity: pushed 2026-09-18, Apache-2.0, 58 stars.
- What it adds: a patched Buildroot tree, and a build whose product is a toolchain and sysroot rather than a bootable rootfs. A production user you can name.
- Would need: a way to apply the patch series to
buildroot-src/at setup. I found noproject.jsonkey for that. The Dockerfile's older-distribution compatibility stage may matter for reproducing the exact toolchain.
Nerves¶
nerves-project/nerves_system_br is the
shared Buildroot external tree. Each board is its own repository, for example
nerves_system_rpi4. There are many
systems, from Raspberry Pi to BeagleBone, x86_64, GRiSP2 and QEMU.
- Buildroot: upstream 2026.05.3, set as
NERVES_BR_VERSIONincreate-build.sh, with 17 files underpatches/buildroot. - Tree: 13 package directories in the shared tree;
nerves_defconfigin the board repository. - Target (rpi4): aarch64 Cortex-A72, glibc,
BR2_INIT_NONE(the Erlang runtime is the init), custom skeleton. The toolchain is a prebuilt Nerves GCC 15.3.0, downloaded. The kernel is a Raspberry Pi 6.18 tarball. - Image:
post-createfs.shruns fwup to produce a.fwfirmware file. - Activity: pushed 2026-09-18, release v1.34.5 on 2026-09-15, 414 stars.
- What it adds: the newest Buildroot of any candidate, no init system, an Erlang/OTP runtime,
and a build that is not
make <defconfig>: the defconfig refers toNERVES_DEFCONFIG_DIRand other variables set by the wrapper. - Would need: the wrapper's environment reproduced in the experiment, the patch series applied, and the fwup step skipped or replaced, as for Home Assistant OS's disk images.
- Package count: not measured, because the defconfig does not configure without that environment.
In-tree QEMU defconfigs¶
Buildroot's own qemu_* defconfigs. No external tree, no vendor fork.
| Defconfig | Packages | Rootfs formats |
|---|---|---|
qemu_x86_64_defconfig |
67 | ext2 |
qemu_riscv64_virt_defconfig |
65 | ext2, tar |
qemu_mips64el_malta_defconfig |
63 | ext2 |
qemu_ppc64le_pseries_defconfig |
69 | ext2 |
- Common shape: internal glibc toolchain, BusyBox init, Linux 6.12.27, measured on 2025.02.18. The tree has 283 defconfigs in all.
- What it adds: three architectures (RISC-V, MIPS, PowerPC) plus x86_64 with the cheapest
possible setup:
external: false, no vendored sources beyond what the tree downloads. - Would need: for the three ext2-only defconfigs, a
config_fragmentthat enables a tar rootfs, since the manifest scanner reads tar (the riscv64 one already builds one). Weak as a credibility demonstration, strong as a portability check.
In-tree noMMU defconfigs¶
- Defconfigs present in 2025.02.18:
qemu_riscv64_nommu_virt,qemu_riscv32_nommu_virtandqemu_xtensa_lx60_nommu. There is no ARM noMMU QEMU defconfig; my earlier suggestion ofqemu_arm_versatile_nommu_defconfigwas wrong. The ARM noMMU option is the Cortex-M boards, such asstm32f429_disco_xip_defconfig, which also use XIP. - Measured:
qemu_riscv64_nommu_virthas 64 packages (uClibc,BR2_BINFMT_FLAT, ext2 and tar);qemu_xtensa_lx60_nommuhas 64 (uClibc, FLAT, cpio initramfs). - What it adds: FLAT binaries instead of ELF, no shared libraries, an initramfs image.
- Risk: any step of the rootfs merge that assumes ELF files or
.sofiles will fail here. That is also why it is worth trying once.
Buildroot test suite¶
support/testing/ in the Buildroot tree: 752 test classes, 415 of them under tests/package/.
- Format: each test carries its configuration as a Python string, not as a defconfig file, and boots the image in QEMU to check it.
- Coverage by files whose configuration mentions the package family: Python 110, Lua 34, Perl 13, Go 2, Rust 1, Qt5 1, Meson (through Weston) 1, Erlang 0. It is wide for Python, Lua and Perl and thin elsewhere; my earlier claim that it exercises every infrastructure (waf, qmake, kconfig, rebar) was not verified and should be dropped.
- What it adds: many small, independent images, each with a runtime check.
- Would need: a script that extracts the config strings into defconfigs. Worth doing for a chosen handful (Go, Rust, Lua, Python), not for all 415.
Microchip¶
linux4microchip/buildroot-external-microchip,
an external tree for Microchip's AT91 (SAMA5, SAMA7, SAM9X), PolarFire SoC and PIC64GX boards.
- Buildroot: two flavours in one external tree. PolarFire and PIC64GX use upstream 2025.02.16.
AT91 needs the
buildroot-mchpfork at branch2025.02-mchp. Older branches2022.02-mchpand2023.02-mchpexist. - Configs: 65 defconfigs; 42 package directories in the external tree.
- Measured:
icicle_defconfig(riscv64, internal glibc toolchain, systemd) has 192 packages;sama7d65_curiosity_graphics_defconfig(arm, internal glibc toolchain, systemd) has 320, on the fork. - Also in the defconfig: custom U-Boot,
genimage, a post-image script, kernel fromlinux4microchip-2026.04tarballs. - Activity: pushed 2026-09-08, 31 stars.
- What it adds: RISC-V with a vendor bootloader chain, a second Buildroot flavour selected per board, and image assembly you would have to skip or reproduce.
- Would need:
buildroot.reposet to the fork for the AT91 boards, and the post-image script skipped, as for superduperbird.
STMicroelectronics¶
bootlin/buildroot-external-st, branch
st/2025.02.12. My earlier link to a STMicroelectronics/ repository was wrong; this is the
maintained tree, by Bootlin.
- Buildroot: upstream 2025.02.12.
- Configs: 20 defconfigs for STM32MP135, MP157, MP215, MP235 and MP257 boards, each as
_flash, plain and_demo. Three package directories. - Measured:
st_stm32mp157d_dk1has 72 packages (arm, external glibc toolchain, ext2 and ext4).st_stm32mp257f_dk_demohas 145 (aarch64, external glibc toolchain, squashfs, Qt5). - Also in the defconfig: TF-A, OP-TEE OS and U-Boot from STMicroelectronics forks, kernel
6.6-stm32mp-r3,genimage, a post-image script that builds an SD-card image. - Activity: pushed 2026-07-30, 90 stars.
- What it adds: a full secure-boot firmware chain built by Buildroot, and Qt5.
- Would need: the same image-assembly skip as Microchip. Four vendor forks (kernel, U-Boot, TF-A, OP-TEE) to vendor as custom tarball sources.
OpenIPC¶
OpenIPC/firmware, IP-camera firmware.
- Buildroot: upstream 2024.02.10, downloaded by the top-level Makefile, which also sets compiler flags for older host packages.
- Tree:
BR2_EXTERNAL=generalplus onebr-ext-chip-*directory per vendor. 155 package directories ingeneral/package. - Configs: per chip family, for example HiSilicon 43, SigmaStar 27, Goke 15, Ingenic 12 and Novatek 2. Other families exist and were not counted.
- Example:
t31_lite_defconfigis mipsel XBurst with a downloaded external musl toolchain (mipsel-openipc-linux-musl, headers 3.10). - Activity: pushed 2026-09-20, MIT, 2,206 stars.
- What it adds: MIPS, an external toolchain that is not Bootlin's, and two external-tree layers.
- Package count: not measured; the Makefile picks the chip tree.
Thingino¶
themactep/thingino-firmware, firmware for
Ingenic SoC cameras.
- Buildroot: the
themactep/buildrootfork at commit62b5743, reporting 2026.08-rc3, pinned by a git submodule, the same shape as FunKey-OS. - Tree: 174 package directories; 178 entries under
configs/cameras; configuration fragments for XBurst1 and XBurst2 SoCs and auclibcset. - Activity: pushed 2026-09-20, MIT, 2,160 stars.
- What it adds: MIPS with uClibc fragments, and a very large number of near-identical board configs, which is a good test for caching across variants.
- Not verified: which libc a given camera image uses. My earlier "uClibc or musl" was a guess for both this and OpenIPC; OpenIPC's sample is musl.
- Package count: not measured.
Milk-V Duo SDK¶
milkv-duo/duo-buildroot-sdk (Sophgo CV180x).
- Buildroot: 2021.05, copied into the SDK repository as
buildroot-2021.05/, next to Linux 5.10, U-Boot 2021.10, OpenSBI and other components. A sparse checkout of the Buildroot directory alone was 723 MB. - Configs: 11 defconfigs for Duo and Duo 256M, on SD, SPI NAND and SPI NOR, plus two Cvitek ones.
- Measured:
milkv-duo-sd_musl_riscv64_defconfighas 133 packages (external riscv64 musl toolchain, headers 5.10, an ext2 rootfs of 786 MB). - Activity: last push 2025-05-22, 494 stars.
- What it adds: RISC-V with a vendor toolchain, and a Buildroot that the wrapper script drives together with the rest of the SDK.
- Not checked: how the toolchain is fetched.
SkiffOS¶
skiffos/SkiffOS, a minimal OS for running containers.
- Buildroot: the
skiffos/buildrootfork as a submodule at8256d48, reporting2026.11-git, a development version ahead of the 2026.08 release. - Tree: 29 layer directories under
configs/(Raspberry Pi, Rockchip, Intel, Apple, virtual machines,core, and more). A build combines them, for exampleSKIFF_CONFIG=pi/4,core/debian. - Activity: pushed 2026-09-16, release 2026.08 on 2026-08-03, MIT, 817 stars.
- What it adds: stacked configuration layers instead of one defconfig.
- Package count: not measured; the defconfig is assembled by the Makefile.
thingOS¶
ccrisan/thingos, by the author of motionEyeOS.
- Buildroot: 2021.11, copied into the repository (not a submodule). A
buildroot.repopointing at the project itself should work; not tried. - Configs: Raspberry Pi 2, 3, 4 and 64-bit, NanoPi R1 and Radxa CM3, each with an initramfs variant.
- Measured:
raspberrypi3_defconfighas 114 packages (arm, external glibc toolchain, BusyBox init). - Activity: pushed 2026-08-23, 233 stars.
- What it adds: little that FunKey-OS does not. Useful only as a quick, small extra.
motionEyeOS¶
motioneye-project/motioneyeos, branch dev.
- Buildroot: 2020.05.1, copied into the repository. The oldest tree of the candidates, so the old-Buildroot workarounds listed under FunKey-OS will apply again.
- Configs: 24 board defconfigs.
- Measured:
raspberrypi3_defconfighas 171 packages (arm, external glibc toolchain, tar rootfs, Raspberry Pi kernel from a commit tarball). - Activity: last push 2025-02-14, 8,215 stars. GitHub does not mark it archived, but the README says the maintainer can no longer be involved and is looking for a successor. My earlier "archived" was wrong; "unmaintained" is accurate.
- What it adds: a Python-heavy image on an old Buildroot.
Batocera¶
batocera-linux/batocera.linux.
- Buildroot: the
batocera-linux/buildrootfork as a submodule at4236c4b, reporting2026.05-git. - Tree: 661 package directories in the external tree, against about 2,900 in upstream
Buildroot. 40 board files under
configs/(Raspberry Pi, Rockchip, Allwinner, StarFive, Qualcomm, x86_64 and others). Driven by a top-level Makefile and a Docker builder, with a ccache directory inside the project tree. - Activity: pushed 2026-09-20, 3,221 stars.
- What it adds: the largest package set of any candidate: Qt, SDL, Python and emulator cores. Expect the long tail of hidden references that superduperbird produced, at several times the scale.
- Package count: not measured. Do this after the smaller candidates.
Knulli¶
knulli-cfw/distribution, a Batocera derivative for
handhelds.
- Buildroot: the
knulli-cfw/buildrootfork at37060ae, reporting 2024.11. - Tree: 586 package directories; 12 board files.
- Activity: GitHub marks the repository archived; last push 2026-06-16, 1,026 stars. It may have moved; I did not check.
- What it adds: nothing that Batocera does not. Skip it.