kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

FreeBSD target support

Status and roadmap for compiling, linking, and running FreeBSD binaries with kit, plus the QEMU VM harness used to execute them. Scope is the release support set: arm64 (aarch64), x64 (amd64), rv64 (riscv64) on FreeBSD.

The execution environment (the VMs) is in good shape; the compile/link path is the gating work — FreeBSD cross-compile was previously untested and turns out to need several fixes, most already landed, with one real linker blocker left.

TL;DR

Execution environment — scripts/freebsd_vm.sh

Orchestrated from a macOS/arm64 host with Homebrew QEMU. One command set provides download, provision, run, and SSH for each arch.

Provisioning model (provision once, cache forever)

A first boot does the expensive one-time setup; the result is saved as a compressed golden disk in the download cache ($DL_ROOT, which survives make clean). Later prepare/run restore it in seconds.

Two provisioning paths:

Per-arch boot quirks (all fixed in the script)

Knobs

KIT_FREEBSD_RELEASE (default 15.0-RELEASE), KIT_FREEBSD_MEM, KIT_FREEBSD_CPUS, KIT_FREEBSD_PROVISION_TIMEOUT, KIT_FREEBSD_ACCEL, KIT_FREEBSD_SSH_USER, KIT_FREEBSD_SSH_KEY. See freebsd_vm.sh doctor.

Sysroot extraction

There is no committed FreeBSD sysroot; extract one per arch from a running VM (it is the matching base system). Minimal static-link set:

bash scripts/freebsd_vm.sh ssh <arch> \
  'tar cf - -C / usr/include usr/lib/crt1.o usr/lib/crti.o usr/lib/crtn.o \
      usr/lib/libc.a usr/lib/libsys.a usr/lib/libssp_nonshared.a' \
  | tar xf - -C build/freebsd-sysroot/<arch>

A proper base.txz extraction harness paralleling test/libc/{glibc,musl} is the intended durable mechanism (pin the dist, record the version).

Compile / link path

kit cc --target=<arch>-freebsdN.N --sysroot=<root> [-static] file.c. Driven through the hosted FreeBSD profile in driver/lib/hosted.c (hosted_resolve_freebsd): crt1/Scrt1 + crti + crtn, libc.a (static) or libc.so.7 (dynamic), interp /libexec/ld-elf.so.1, and __FreeBSD__/__ELF__ defines.

Fixed

Blocker — libc/libsys weak-alias archive cycle

-static links currently fail with undefined reference to 'openat' (and would hit the same class for other syscall wrappers).

Root cause: FreeBSD 15 splits the syscall path across two mutually-recursive archives with weak aliases:

kit's link_ingest_archives (src/link/link_resolve.c) resolves each archive to a fixpoint, but only against the symbols defined before it in link order — it does not re-scan an earlier archive when a later one introduces new undefined references. So a back-reference from libsys.a into libc.a is not satisfied. Re-listing libc.a after libsys.a (the --start-group idiom; currently in the hosted profile) did not resolve it on its own, so weak-definition archive-pull semantics are likely also involved and need confirmation.

Proposed fix (linker work, regression-sensitive — guard with the existing test-link corpus):

Other known gaps

Validation matrix (per arch)

For each of aarch64 / x64 / rv64 on FreeBSD:

How to reproduce today

# 1. Provision the VMs (one-time, cached afterwards). amd64/rv64 are slow (TCG).
bash scripts/freebsd_vm.sh prepare aarch64
bash scripts/freebsd_vm.sh prepare amd64
bash scripts/freebsd_vm.sh prepare riscv64

# 2. Extract a sysroot from one (see "Sysroot extraction" above).

# 3. Cross-compile (currently fails at the libc/libsys link blocker):
build/kit cc --target=x86_64-freebsd15.0 \
  --sysroot=build/freebsd-sysroot/amd64 -static hello.c -o hello

# 4. Once linking works: run it on the VM.
bash scripts/freebsd_vm.sh run amd64 &        # boot
scp -i build/freebsd-vm/ssh/id_ed25519 -P 2222 hello kit@127.0.0.1:
bash scripts/freebsd_vm.sh ssh amd64 ./hello