Building NetBSD from source with build.sh: creating the toolchain, building the kernel and userland/world, running parallel builds, and cross-compiling for other architectures.

In episode 9 we built a custom kernel with build.sh kernel=MYCUSTOM. Now it's time to complete the big picture: in this episode we'll build the entire NetBSD from source — not just the kernel, but also the toolchain and the entire userland (what we call "world"). This is the pinnacle of the source-based NetBSD philosophy we introduced in episode 2.
The base system source lives in /usr/src. Get it from the official CVS or git repository. The modern git way:
git clone -b netbsd-11 \
https://github.com/NetBSD/src.git /usr/srcMake sure the basic tools are available. NetBSD 11 uses the LLVM/clang toolchain by default, but build.sh builds its own toolchain in the first stage — so the minimum requirements are just: a shell, make, and enough disk space (10-15 GB recommended).
Builds happen in a separate object directory so the source isn't polluted. build.sh defaults to ./obj:
cd /usr/src
mkdir -p /usr/obj
./build.sh -O /usr/obj paramsThe build.sh params command displays build parameters — a quick way to verify your setup is correct.
build.sh works in several stages that can be run separately or in sequence:
| Command | Function |
|---|---|
./build.sh tools | Builds the toolchain (compiler, binutils, etc.) |
./build.sh kernel=GENERIC | Builds the kernel |
./build.sh distribution | Builds the entire userland + sets |
./build.sh release | Produces a complete release in RELEASEDIR |
./build.sh build | All of the above (kernel + distribution) |
This is the most time-consuming stage the first time — building the compiler and tools from source:
cd /usr/src
./build.sh tools...
Building tool: nbtoolchain-gcc-10.5 ...
Build started at ... finished at ...Once built, the toolchain is stored in the obj directory and reused for subsequent builds — making later builds much faster.
With the toolchain ready, build the kernel and the entire userland at once:
./build.sh build# build.sh: Building the kernel
...
# build.sh: Building the world
...
# build.sh: Building the releaseThe -u option is important for repeated builds — it tells build.sh to update existing objects instead of building from scratch:
./build.sh -u buildTo produce a complete release — including installation sets and installer images — use:
./build.sh -u release$ ls /usr/obj/releasedir
binary CHANGES ...This release is what you can use to install NetBSD on another machine, or to upgrade this one.
Building the world takes time. build.sh uses the -j flag for parallel builds:
./build.sh -j 8 -u build=> Running bootstrap mk-files
# Build started at ...Pick the job count according to your core count. Check your cores with sysctl hw.ncpu. A general rule: 1-2 jobs per core.
This is build.sh's most impressive power: cross-compilation. You can build NetBSD for another architecture from a different machine — for example, building a Raspberry Pi (aarch64) image from an x86_64 PC, or building for RISC-V without owning RISC-V hardware.
Just give the -m flag with the target architecture:
./build.sh -m aarch64 kernel=GENERIC64...
copying netbsd to .../aarch64/obj/release/kernels/GENERIC64/netbsdThis also works for a full distribution:
./build.sh -m aarch64 -u release./build.sh -m aarch64 ...
./build.sh -m riscv64 ...
./build.sh -m evbarm ...Info
This cross-build power is what makes NetBSD so attractive in the embedded world: manufacturers and communities build images for hundreds of devices from a few central build machines, without needing to own every piece of hardware.
Once the distribution is built, install it onto your system:
cd /usr/src
./build.sh install=/ install...
===> Installing updated files
Installing /bin/ls
...This command copies the entire built userland onto the system — this is how NetBSD "upgrades the world" from source, equivalent to a distribution upgrade on Linux distros.
For those who want it all in one go:
./build.sh -j 8 -u releasetools -> kernel -> distribution -> releaseIn this episode 10, you've built a complete NetBSD from source with build.sh: creating the toolchain, building the kernel and userland/world, running parallel builds with -j, producing a release, cross-compiling for other architectures, and installing the build result onto the system.
Key takeaways:
build.sh works in stages: tools → kernel → distribution → release.-u for repeated builds (update objects only), -j for parallel.-m <arch> — build for aarch64/riscv from an x86 machine.build.sh install=/ install../build.sh -j 8 -u release, builds the entire system.In the next episode, episode 11, we'll protect the most valuable asset: data management and backup — caring for filesystems with fsck, creating snapshots, and building a backup strategy with dump, tar, cpio, and rsync. See you in episode 11!