A Comfortable Workshop: Containers, Caches, and Build Targets
Part 2 of The Thingino Developer’s Journey / <- Part 1
Your first build worked (right?). Now let’s make the second, tenth, and five-hundredth builds pleasant. Firmware development is an edit–build–flash loop, and everything in this article exists to shrink the “build” part.
Two ways to build: host or container
Host builds need build dependencies installed. Thingino checks them for you:
make bootstrap # runs scripts/dep_check.sh, tells you what's missing
Container builds skip all that. If you have Podman or Docker:
./build-container.sh # build (camera selection menu included)
./build-container.sh shell # drop into a shell inside the container
./build-container.sh menuconfig # Buildroot configuration UI
The container image (ghcr.io/themactep/thingino-builder-image) ships every
dependency preinstalled and pulls automatically on first run. It also
auto-seeds a download cache volume with pre-fetched source tarballs, which
means your first container build skips most of the internet. If your distro is
exotic, your GCC is too new, or you just don’t want 40 dev packages on your
laptop — use the container. The firmware tree is bind-mounted, so artifacts
land in the same output/ directory either way.
The build targets you’ll actually use
CAMERA=<camera> make # clean + parallel build + pack image (the safe default)
CAMERA=<camera> make fast # incremental parallel build - your daily driver
CAMERA=<camera> make dev # serial, verbose build - for debugging build failures
CAMERA=<camera> make menuconfig # poke at the Buildroot config
CAMERA=<camera> make saveconfig # write config changes back to the defconfig
The pattern: make when you want certainty, make fast when you’re
iterating, make dev when something broke and you need to see where.
make dev builds single-threaded with full command echo, so the error is at
the bottom of the output instead of buried under 16 parallel jobs’ worth of
noise.
Interrupted a build with Ctrl-C? Just run make fast again — Buildroot
resumes where it stopped.
One habit worth forming early: when a build fails, don’t re-run it and squint
at the terminal. Build logs are saved under
output/<branch>/<camera>-.../logs/ — grep them like a civilized person.
The three caches that give you your time back
- The download cache (
dl/). Every source tarball Buildroot fetches lands here (BR2_DL_DIR, defaults todl/in the tree). Deleteoutput/and rebuild — nothing re-downloads. You can point it somewhere global:export BR2_DL_DIR=$HOME/buildroot-dl. - ccache. Compiler output is cached in
~/.buildroot-ccache, automatically. A “clean” rebuild of something you’ve built before is dramatically faster because most compilations are cache hits. - Prebuilt toolchains.
make updatefetches prebuilt cross-toolchain bundles, so you never build GCC from scratch. This alone saves an hour.
Together these mean the scary “clean build” is mostly a myth after your first week. Clean builds re-link the world; they rarely re-compile it.
Where everything goes
output/<branch>/<camera>-<kernel>-<libc>/
|-- build/ # per-package build directories
|-- host/ # cross-toolchain and host tools
|-- images/ # <- your firmware
|-- logs/ # <- your build logs
`-- target/ # staged root filesystem
Note the <branch> component: builds from different git branches never
collide. Remember that detail — it becomes a superpower in Part 6.
Odds and ends worth knowing now
- Run target binaries without a camera:
make run CMD="bin/ffmpeg --help"executes a built binary under QEMU user-mode emulation. Great for quick sanity checks of MIPS builds. - Set up the git hooks:
make setup-hooks. The project formats shell scripts withshfmtand web UI JavaScript with Prettier at commit time; the hooks keep you stylistically invisible in code review. - Rebuild one package instead of everything:
CAMERA=<camera> make rebuild-<pkg>— much more on this in Part 5.
What you learned
- Container builds trade disk for zero setup; host builds need
make bootstrap. make fastis your daily driver;make devis your debugger.- Three caches (dl, ccache, prebuilt toolchains) make rebuilds cheap.
- Logs live in
output/.../logs/; builds are resumable; QEMU runs your MIPS binaries.
Next up: Part 3 — Make It Yours: the layered user/
configuration tree, or how to customize builds for your cameras without
carrying a single uncommitted diff.