Portability in Practice: Build NetBSD for amd64, i386, and evbarm in an Afternoon.

NetBSD’s superpower is portability. The heart of that is the cross-build framework (build.sh): you can build full releases for other architectures without chroots, containers, or VMs. In this guide you’ll go from zero to installable images for amd64, i386, and evbarm (armv7hf) using a single host machine.

TL;DR: clone src, run ./build.sh tools, then ./build.sh -m <arch> release with a separate object directory. Repeat for each architecture.


Host prerequisites

You can build from NetBSD, FreeBSD, or Linux.

  • Multi-core CPU
  • ~32–80 GB free disk (for three arches sharing one objdir)
  • 8–16 GB RAM (more -j jobs helps)

Useful packages by host OS

FreeBSD:

sudo pkg install git gmake bison flex pkgconf xz

NetBSD (via pkgin):

sudo pkgin install git gmake bison flex pkgconf xz

Linux (Debian/Ubuntu-like):

sudo apt update && sudo apt install -y git gcc g++ make bison flex pkg-config xz-utils

Speed tip: use an NVMe SSD and point -O (objdir) to a fast filesystem (ZFS dataset, tmpfs, btrfs) to accelerate repeated builds.


Get the source tree

Git has become the simplest route (CVS remains available). We’ll place src under /usr/src.

sudo mkdir -p /usr/src && sudo chown "$USER" /usr/src
cd /usr/src
# Git example:
git clone https://github.com/NetBSD/src.git .
# (Or use your preferred mirror/branch.)

Unprivileged builds: we’ll use -U so everything happens as your normal user; no touching the live system.


First pass: build the toolchains

build.sh creates a cross toolchain in -T and separates objects in -O.

cd /usr/src
JOBS=$(sysctl -n hw.ncpu 2>/dev/null || nproc)
./build.sh -U -u \
  -O /usr/obj \
  -T /usr/tools \
  -j "$JOBS" tools
  • -U: unprivileged
  • -u: update/incremental
  • -O: object/artifacts directory
  • -T: tools directory
  • -j: parallel jobs = CPU cores

The first run takes longer. After that, new architecture releases reuse the tools.


Build releases per architecture

The magic is switching -m (MACHINE) and, when needed, -a (MACHINE_ARCH).

amd64 (x86_64)

cd /usr/src
./build.sh -U -u -O /usr/obj -T /usr/tools \
  -m amd64 -j "$JOBS" release

Artifacts: .../releasedir/amd64/binary/sets/ and kernels under .../binary/kernel/.

i386 (32-bit x86)

./build.sh -U -u -O /usr/obj -T /usr/tools \
  -m i386 -j "$JOBS" release

Great for older hardware and tiny VMs.

evbarm (ARMv7 hard-float)

./build.sh -U -u -O /usr/obj -T /usr/tools \
  -m evbarm -a earmv7hf -j "$JOBS" release

Look for a ready-to-write image around:

/usr/obj/releasedir/evbarm/binary/gzimg/armv7.img.gz

Note: exact subpaths vary by board; sets are also under .../binary/sets/ if you prefer installing via sysinst.


Installing the images

Write the ARM image to an SD card

Careful: pick the correct device! On NetBSD something like /dev/rsd0d; on Linux usually /dev/sdX.

# NetBSD/FreeBSD (gzcat available):
sudo gzcat /usr/obj/releasedir/evbarm/binary/gzimg/armv7.img.gz \
  | sudo dd of=/dev/rsd0d bs=1m conv=sync

# Linux:
gzip -dc /usr/obj/releasedir/evbarm/binary/gzimg/armv7.img.gz \
  | sudo dd of=/dev/sdX bs=1M conv=fsync
sync

Insert the SD into your ARM board and boot. Initial setup is quick; then adjust rc.conf, networking, sshd, etc.

Install amd64 / i386 using sets

Use sysinst with the sets in .../releasedir/<arch>/binary/sets/. In virtualized environments, mounting the install ISO/USB is often fastest.


Quick post-install (pkgsrc/pkgin)

For prebuilt binaries via pkgin:

# Example: adjust the URL for your exact version/arch
sudo mkdir -p /usr/pkg/etc
echo "https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/<arch>/<version>/All" \
  | sudo tee /usr/pkg/etc/pkgin/repositories.conf

sudo pkg_add pkgin
sudo pkgin -y update
sudo pkgin -y install vim git htop sshrc

Replace <arch> (e.g., amd64, i386, evbarm) and <version> (e.g., 10.0). If you prefer building everything, pkgsrc bootstrap is an option — but pkgin is a great accelerator to start.


Cleanups, rebuilds, and gotchas

  • ./build.sh cleandir if you want a clean slate.
  • Keep -O and -T stable; moving them invalidates caches.
  • Snapshot your -O filesystem (ZFS/Btrfs) before large releases for easy rollbacks.
  • Switching branches? Do cleandir + tools again.

Minimal CI pipeline (cron + Makefile)

Automate nightly releases with a tiny Makefile and cron.

Makefile (save as /usr/src/ci/Makefile):

JOBS?=$(shell sysctl -n hw.ncpu 2>/dev/null || nproc)
OBJ?=/usr/obj
TOOL?=/usr/tools

ARCHS=amd64 i386 evbarmv7

all: $(ARCHS:%=build-%)

build-amd64:
\tcd /usr/src && ./build.sh -U -u -O $(OBJ) -T $(TOOL) -m amd64 -j$(JOBS) release

build-i386:
\tcd /usr/src && ./build.sh -U -u -O $(OBJ) -T $(TOOL) -m i386 -j$(JOBS) release

build-evbarmv7:
\tcd /usr/src && ./build.sh -U -u -O $(OBJ) -T $(TOOL) -m evbarm -a earmv7hf -j$(JOBS) release

Nightly cron (e.g., 02:30):

crontab -e
# add:
30 2 * * * make -C /usr/src/ci all >> /var/log/netbsd-build.log 2>&1

Tip: sync /usr/obj/releasedir/ to an internal web server and publish artifacts automatically.


Pocket checklists

Fast build (after the first time):

  1. cd /usr/src
  2. git pull (or update CVS)
  3. ./build.sh -U -u -O /usr/obj -T /usr/tools -m amd64 -j "$JOBS" release
  4. Repeat for i386 and evbarm -a earmv7hf

ARM SD card:

  1. Locate the image under .../binary/gzimg/
  2. gzcat armv7.img.gz | dd of=<YOUR_DEVICE>
  3. sync and boot

Conclusion

With build.sh, NetBSD portability turns from a slogan into a daily workflow. In a few hours you can prepare toolchains and generate releases for different generations of x86 and also ARM boards — all from one box. From here, it’s easy to expand to evbmips, riscv, and beyond; the process barely changes, and watching three worlds boot from your single build is always satisfying.


Credits & notes

  • Releasedir paths and filenames can vary by version/board; adjust as needed.
  • This guide focuses on unprivileged builds; no host install (destdir=/) required.

Optional cover/thumbnail

  • Title: “NetBSD Cross-Build — amd64 • i386 • evbarm”
  • Subtitle: “Portability in Practice with build.sh”
  • Suggested size: 2048×1152
  • Palette: NetBSD orange (#FF6600), charcoal (#222), white (#FAFAFA)
  • Icon: stylized daemon head + gears

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *