Building
Relevant source files
- Cargo.toml
- build.rs
- src/main.rs
- tools/xtask/src/cli.rs
- tools/xtask/src/commands.rs
- scripts/README.md
- scripts/build/rpi5.sh
- kernel/Cargo.toml
- docs/operations/build.md
- docs/reference/generated/artifacts.md
- firmware/shrike/rp2040/build-uf2.sh
- firmware/shrike/rp2040/flash-uf2.sh
The build is driven by Cargo plus a typed command surface, cargo xtask. The root package (axiomos) is both the host-side QEMU runner (src/main.rs) and the image assembler (build.rs), which builds the kernel and every userspace binary for the target architecture as artifact dependencies.
Build flow
cargo xtask
cargo xtask is an alias for run --locked --package xtask --. The grammar below comes from tools/xtask/src/cli.rs and the usage text in commands.rs.
| Command | What it does |
|---|---|
cargo xtask build x86_64 | cargo build --locked -p axiomos |
cargo xtask build rpi5 | Runs scripts/build/rpi5.sh |
cargo xtask build riscv | Runs scripts/build/riscv.sh (standalone RISC-V demo kernel) |
cargo xtask run x86_64 | cargo run --locked -p axiomos -- (runner args after --) |
cargo xtask run virt | Runs scripts/run/virt.sh (AArch64 QEMU virt) |
cargo xtask run riscv | Runs scripts/run/riscv.sh |
cargo xtask deploy rpi5 | Runs scripts/deploy/rpi5.sh |
cargo xtask bench verifier | Runs scripts/benchmark/verifier-cost.py (alias verifier-cost) |
cargo xtask debug qemu | Runs scripts/debug/qemu-triage.sh |
cargo xtask inventory --check | Validates the component inventory |
cargo xtask boundary --check | Validates workspace/artifact boundaries (--check is required) |
cargo xtask docs [--check] | Regenerates or checks docs/reference/generated/ |
cargo xtask check NAME | Focused checks and all; see CI |
cargo xtask ci [--quick or --full or --extended] | Compatibility entry point for the audit gate |
build, run, deploy, bench and debug all take a target, an optional --dry-run, and trailing arguments after -- that are forwarded to the underlying implementation. --dry-run prints the delegated command instead of running it.
cargo xtask build rpi5 --dry-run
cargo xtask run x86_64 -- --headless --smp 2x86_64 via plain Cargo
cargo build # debug
cargo build --release # release
cargo run # build then boot in QEMU
cargo run -- --no-run # build only; prints KERNEL_BINARY, BOOTABLE_ISO, DISK_IMAGEThe default feature set is x86_64_deps, which pulls the x86_64 builds of the kernel (with cloud-profile) and all userspace crates.
AArch64 and Raspberry Pi 5
The AArch64 image uses --no-default-features --features aarch64_deps:
cargo build --release --target aarch64-unknown-none \
--no-default-features --features aarch64_depsscripts/build/rpi5.sh wraps the two-stage process for the Pi; see Raspberry Pi 5.
Cargo features
Root Cargo.toml features:
| Feature | Effect |
|---|---|
x86_64_deps (default) | x86_64 kernel and userspace artifacts |
aarch64_deps | AArch64 kernel and userspace artifacts |
bpf-unsigned-development | Enables the kernel and init development path for unsigned BPF (x86_64) |
bpf-unsigned-development-aarch64 | Same, for AArch64 |
audit-diagnostics / audit-diagnostics-aarch64 | One-shot serial markers consumed by the audit gate |
audit-fault-injection | Fault-injection boot probe (x86_64) |
bringup-diagnostics | Raw AArch64 register/UART probes for bring-up |
managed-runtime | x86_64: enables managed-runtime in the kernel, init and signed_bpf_loader, so the loader becomes the UART installer (see Installer) |
managed-runtime-aarch64 | The same three features for the AArch64 build |
managed-syscall-probe | Implies managed-runtime and builds the installer as an opt-in QEMU userspace ABI probe. The Cargo comment says it does not enable physical managed control |
host-runner-tests | Compile only the host runner and its tests; build.rs rejects it outside the debug profile or with target artifact features |
Kernel features (kernel/Cargo.toml) that you pass for the Pi build via scripts/build/rpi5.sh:
| Feature | Meaning |
|---|---|
cloud-profile | Cloud eBPF profile (used for x86_64 and AArch64 virt) |
embedded-profile | Embedded eBPF profile; implies rpi5 |
embedded-rpi5 | Alias for embedded-profile (default for the Pi script) |
virt | AArch64 QEMU virt platform |
verifier-cost | Emit AXIOM VERIFIER COST markers (instrumentation, not for production) |
bench | On-chip latency instrumentation and diagnostic reflex; plus bench-pwm, bench-estop-rearm, bench-reflex-rearm and others |
trace-control-link | Per-poll control-link trace records |
managed-runtime | Managed-runtime kernel support (the CPU0 executor, installer syscalls, recorder). Opt-in |
managed-runtime-bench-markers | Implies managed-runtime. Unloaded v0.5 qualification only: GPIO12 brackets each timer release and GPIO13 rises immediately before the recorder append; both fall before return (per the kernel/Cargo.toml comment) |
audit-diagnostics, audit-fault-injection, bringup-diagnostics | As above |
cloud-profile and embedded-profile are mutually exclusive in kernel_bpf, and one of them is required. bpf-unsigned-development is an explicit escape hatch for local demo images. The kernel source says production artifacts must never enable it.
Managed-runtime image
managed-runtime is a separate opt-in image configuration, described in Managed runtime. In it, init runs only the installer and no legacy diagnostic workloads, and signed bundles are uploaded after boot with rk runtime instead of being baked in with AXIOM_SIGNED_BPF_STARTUP_PATH. The build still needs AXIOM_BPF_TRUSTED_KEY_PATH.
# x86_64 (QEMU)
cargo build --release --features managed-runtime
# opt-in QEMU userspace ABI probe
cargo run --locked --release --features managed-syscall-probe -- --headless --smp 1 --mem 1GFor the Pi, pass managed-runtime in the kernel feature list; see Raspberry Pi 5. Software and host testing only: physical qualification has not been run and actuation is disabled (Qualification).
Signed versus unsigned BPF
Without bpf-unsigned-development, the kernel includes the production trust key with include_bytes!(env!("AXIOM_BPF_TRUSTED_KEY_PATH")), so AXIOM_BPF_TRUSTED_KEY_PATH must be set at build time. The Pi and virt scripts check that the file exists and is exactly 32 bytes. With the feature, the trust module takes a different path and no key is needed. In that mode init spawns sched_switch_export_demo and sched_switch_bridge_demo instead of signed_bpf_loader.
An optional signed startup program can be baked into the rootfs: set AXIOM_SIGNED_BPF_STARTUP_PATH to a signed container and build.rs copies it to /var/lib/rkbpf/programs/startup.rbpf.
Environment variables
| Variable | Used by | Purpose |
|---|---|---|
AXIOM_BPF_TRUSTED_KEY_PATH | kernel build, rpi5.sh, virt.sh | 32-byte Ed25519 public key |
AXIOM_SIGNED_BPF_STARTUP_PATH | build.rs | Signed program placed in the rootfs |
AXIOM_ARTIFACT_PATHS | build.rs | File to which build.rs writes KERNEL_BINARY, DISK_IMAGE, BOOTABLE_ISO and OVMF paths for that exact invocation |
AXIOM_DISK_IMAGE | rpi5.sh (kernel stage) | Rootfs image embedded in the kernel |
CARGO_TARGET_DIR | rpi5.sh, deploy | Alternate target directory |
AXIOMOS_QEMU_MONITOR_PORT, AXIOMOS_QEMU_DISABLE_MONITOR, AXIOMOS_QEMU_AUDIT_NAME | src/main.rs | Runner QEMU options |
What build.rs produces
Resolve the kernel
The kernel ELF comes from CARGO_BIN_FILE_KERNEL_X86_kernel or CARGO_BIN_FILE_KERNEL_AARCH64_kernel, set by Cargo for the artifact dependency.
Populate the rootfs directory
userspace/core/file_structure declares the tree. Each executable is copied from its artifact dependency into /bin. See Userspace.
Make the ext2 image
mke2fs -d builds a 20M ext2 image. The UUID, hash seed and SOURCE_DATE_EPOCH are pinned so the image is byte-reproducible; the embedded image affects kernel8.img provenance.
x86_64 only: ISO and firmware
Limine is cloned at the pinned revision, an ISO is built with xorriso, and OVMF is fetched (checked against OVMF_SHA256).
Shrike RP2040 firmware
firmware/shrike/rp2040/build-uf2.sh builds the Shrike firmware UF2. With no argument it builds the default image (shrike_rp2040.uf2). With --runtime it enables the fpga-runtime feature, requires the pinned FPGA image firmware/shrike/fpga/forgefpga/axiomos_r04_mcu.bin in the flash-contract check, writes shrike_rp2040_runtime.uf2, and includes the bitstream in the SHA-256 sidecar. flash-uf2.sh UF2 MOUNT [fpga-bitstream] verifies the sidecar and flash contract before copying. The generated artifact table lists the runtime UF2 as experimental, for unloaded qualification.
Artifacts
Per docs/reference/generated/artifacts.md:
| Artifact | Producer | Location |
|---|---|---|
| x86_64 boot ISO, kernel ELF, rootfs | cargo build --locked --release -p axiomos | Paths reported by target/release/axiomos --no-run |
| Pi 5 kernel ELF | cargo xtask build rpi5 -- release embedded-rpi5 | target/aarch64-unknown-none/release/kernel |
| Pi 5 raw kernel | same | target/aarch64-unknown-none/release/kernel8.img |
| Pi 5 hashes | same | target/aarch64-unknown-none/release/rpi5-artifacts.sha256 |
| Pi 5 managed-runtime image | AXIOM_BPF_TRUSTED_KEY_PATH=... bash scripts/build/rpi5.sh release embedded-rpi5,managed-runtime | Same files as above |
| Shrike runtime qualification UF2 | firmware/shrike/rp2040/build-uf2.sh --runtime | firmware/shrike/rp2040/target/thumbv6m-none-eabi/release/shrike_rp2040_runtime.uf2 |
| AArch64 virt rootfs | cargo xtask run virt | Reported by the invocation |
Do not select artifacts by newest timestamp. Use the paths reported through AXIOM_ARTIFACT_PATHS or --no-run.
Scripts layout
scripts/README.md states that scripts are focused process adapters behind cargo xtask.
| Responsibility | Script |
|---|---|
| Build | build/riscv.sh, build/rpi5.sh |
| Run | run/riscv.sh, run/virt.sh |
| Deploy | deploy/rpi5.sh |
| Smoke test | test/smoke-bpf.sh |
| Verify | verify/engineering-audit.sh, verify/*.py, verify/gates/ |
| Benchmark | benchmark/analyze-v03.py, benchmark/verifier-cost.py (plus analyze-v04.py, v04-behavior-runner.py present in the tree), and the v0.5 tools analyze-v05.py, v05-host-runner.py, v05-audit-stitch.py, v05-physical-reducer.py (see Performance) |
| Debug | debug/qemu-triage.sh |
| Hardware-in-the-loop | hil/* (see Hardware-in-the-loop) |