Build
Dependencies, parameters, configuration, and artifacts for x86_64, ARM64, and RISC-V64.
On this page
Dependencies
The apt commands below target Debian/Ubuntu Linux hosts.
Native x86_64 needs GCC and glibc development files; kernel building additionally needs make, flex, bison, bc, OpenSSL/ELF development files, and Perl.
Builders do not install dependencies automatically, and cross builders do not initially check every link input, so finding gcc is not a complete environment check.
sudo apt-get update
sudo apt-get install -y \
bash git build-essential libc6-dev flex bison bc libssl-dev libelf-dev \
cpio gzip rsync python3 kmod binutils file patch perl pkg-config \
coreutils findutils grep sed diffutils qemu-system-x86sudo apt-get install -y \
crossbuild-essential-arm64 libc6-dev-arm64-cross qemu-system-arm \
gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu \
libc6-dev-riscv64-cross qemu-system-misc opensbi| Purpose | Tools or packages |
|---|---|
| ARM64 compilation | aarch64-linux-gnu-gcc/ar/objdump; crossbuild-essential-arm64 and libc6-dev-arm64-cross. |
| RISC-V64 compilation | riscv64-linux-gnu-gcc/ar/objdump; gcc-riscv64-linux-gnu, binutils-riscv64-linux-gnu, and libc6-dev-riscv64-cross. |
| RISC-V64 boot | qemu-system-misc and opensbi; scripts use /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin. |
| Packing and module indexes | GNU cpio with --reproducible, gzip with -n, kmod for depmod, and rsync for DTB copying. |
aarch64-linux-gnu-gcc -print-file-name=libc.a
riscv64-linux-gnu-gcc -print-file-name=libc.a
printf 'int main(void) { return 0; }\n' | aarch64-linux-gnu-gcc -static -x c - -o /dev/null
printf 'int main(void) { return 0; }\n' | riscv64-linux-gnu-gcc -static -x c - -o /dev/null
test -r /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bingcc-riscv64-linux-gnu commonly recommends rather than requires libc6-dev-riscv64-cross.
Environments installing only the compiler or using --no-install-recommends should check libc.a explicitly; if missing, -print-file-name returns libc.a unchanged rather than a full path.
Static BusyBox and guest C tests both need these development files.
Parameters
| Parameter | x86_64 build_system.sh | ARM64 / RISC-V64 |
|---|---|---|
| JOBS | Defaults to 2; passed to parallel kernel and BusyBox make. | Defaults to $(nproc); used for kernel, BusyBox, and SDK builds. |
| BUILD_ROOT | Defaults to <repo>/.build; created and converted to an absolute path. | Defaults to <repo>/.build; use an absolute custom path. |
| CC | Script default gcc, used for BusyBox and the BCI example; the kernel invocation does not explicitly forward it, so it is not a whole-system toolchain selector. | Scripts fix aarch64-linux-gnu-gcc or riscv64-linux-gnu-gcc and the matching AR/CROSS_COMPILE; external CC does not switch the target. |
export BUILD_ROOT="$PWD/.build-work"
JOBS=2 CC=gcc ./scripts/build_system.sh
BUILD_ROOT="$BUILD_ROOT" QEMU_TIMEOUT=180 ./scripts/verify_system.shUser-space Makefiles can inherit CC when it is supplied in the environment; build_system.sh’s default local CC and GNU make’s built-in CC are not the same propagation mechanism.
For a first build, use the scripts’ default GNU toolchains rather than treating CC=clang, ARCH, and CROSS_COMPILE as freely composable parameters across all system builders.
Toolchain replacement requires checking each script and Makefile and revalidating every artifact.
x86_64 stages
JOBS=$(nproc) ./scripts/build_system.sh
QEMU_TIMEOUT=180 ./scripts/verify_system.sh- build_kernel.sh invokes prepare_linux.sh, generates x86 defconfig, merges kernel/xtos_defconfig, checks PREEMPT_RT, XTOS_SCHED, BCI, and serdev after olddefconfig, then builds bzImage and modules.
- BusyBox uses system/busybox_defconfig and requires STATIC, BUSYBOX, ASH, and MODPROBE. The script runs BusyBox and uses readelf to check that no INTERP dynamic interpreter exists.
- Copy sdk, tools, and examples to userspace-source; compile three libraries, the static EEG pipeline/benchmark, rt/spsc/signal C tests, and bci_test. The system installs .a archives and does not depend on loading SDK .so files in the guest.
- Copy the rootfs skeleton, install applets, headers, the fixture, and modules, run depmod, pack with fixed mtimes, sorted entries, stable ownership and gzip headers, then copy the kernel image and final configuration into images.
system_build=pass marks build completion. System verification is the subsequent verify_system.sh, which runs /usr/bin/xtos-selftest and checks XTOS_SYSTEM_TEST=PASS. Build-time deletion and rebuilding affect generated directories such as userspace-source/rootfs, not repository source directories. Do not store data that must survive there.
Cross-architecture stages
JOBS=$(nproc) ./scripts/build_system_arm64.sh
QEMU_TIMEOUT=180 ./scripts/verify_system_arm64.sh
QEMU_TIMEOUT=300 ./scripts/verify_guest_arm64.sh
JOBS=$(nproc) ./scripts/build_system_riscv64.sh
QEMU_TIMEOUT=300 ./scripts/verify_system_riscv64.sh
QEMU_TIMEOUT=360 ./scripts/verify_guest_riscv64.shCross builders fix ARCH=arm64 or ARCH=riscv, use the corresponding GNU prefix, initially generate defconfig, enable RT, merge XTOS configuration, and configure virtual-platform devices.
ARM64 uses PL011 and ttyAMA0; RISC-V uses an 8250 serial console and ttyS0.
Both build Image, dtbs, and modules, copy Image/DTBs, and create static BusyBox and /etc/inittab.
The three SDKs are cleaned in source directories and rebuilt with target CC/AR, then checked with target objdump for .a member architecture. Committed rt and signal C tests are statically linked and installed under /bin.
Some test compilation failure branches warn and continue, so Build Complete does not establish that all tests exist.
verify_guest_* reports missing executables as guest_test_*=missing and fails validation.
Artifact paths
Every path below is relative to BUILD_ROOT, which defaults to .build, not to the kernel source directory. QEMU normally reads the installed/copied image; raw kernel output paths help diagnose builds. Keep the two roles distinct.
| Artifact | x86_64 | ARM64 | RISC-V64 |
|---|---|---|---|
| QEMU kernel image | images/xtos-bzImage | kernel-install-arm64/Image | kernel-install-riscv64/Image |
| Raw kernel image | kernel-build/arch/x86/boot/bzImage | kernel-build-arm64/arch/arm64/boot/Image | kernel-build-riscv64/arch/riscv/boot/Image |
| Normal initramfs | images/xtos-rootfs.cpio.gz | initramfs-arm64.cpio.gz | initramfs-riscv64.cpio.gz |
| Unpacked rootfs | rootfs/ | rootfs-arm64/ | rootfs-riscv64/ |
| Final kernel config | kernel-build/.config; copied to images/kernel.config | kernel-build-arm64/.config | kernel-build-riscv64/.config |
| DTB install directory | This QEMU pc path does not use a DTB directory. | kernel-install-arm64/dtbs/ | kernel-install-riscv64/dtbs/ |
file .build/images/xtos-bzImage .build/kernel-install-arm64/Image .build/kernel-install-riscv64/Image
aarch64-linux-gnu-objdump -f .build/rootfs-arm64/usr/lib/libxtos-rt.a
riscv64-linux-gnu-objdump -f .build/rootfs-riscv64/usr/lib/libxtos-rt.aARM64 archive members should report architecture: aarch64, and RISC-V64 members architecture: riscv:rv64. Cross-architecture executables cannot be run directly on an x86 host; test them in the corresponding QEMU guest. A DTB directory existing does not establish real-hardware validation for all represented boards.
Reproducible builds
Source scripts/reproducible_env.sh into the current shell with the dot command.
It defaults SOURCE_DATE_EPOCH to the HEAD commit timestamp, allowing a prior override, and provides defaults of KBUILD_BUILD_VERSION=1 and KBUILD_BUILD_USER/HOST=xbuild while respecting existing overrides, and sets KBUILD_BUILD_TIMESTAMP, LC_ALL=C, and TZ=UTC.
All three system builders normalize rootfs mtimes to the epoch, sort entries, fix ownership to 0:0, and use cpio --reproducible and gzip -n.
. ./scripts/reproducible_env.sh
printf 'SOURCE_DATE_EPOCH=%s\n' "$SOURCE_DATE_EPOCH"
BUILD_ROOT="$PWD/.build-repro-a" JOBS=2 ./scripts/build_system.sh
BUILD_ROOT="$PWD/.build-repro-b" JOBS=2 ./scripts/build_system.sh
cmp .build-repro-a/images/xtos-bzImage .build-repro-b/images/xtos-bzImage
cmp .build-repro-a/images/xtos-rootfs.cpio.gz .build-repro-b/images/xtos-rootfs.cpio.gz
sha256sum .build-repro-a/images/xtos-bzImage .build-repro-b/images/xtos-bzImage
sha256sum .build-repro-a/images/xtos-rootfs.cpio.gz .build-repro-b/images/xtos-rootfs.cpio.gz
BUILD_ROOT="$PWD/.build-repro-a" QEMU_TIMEOUT=180 ./scripts/verify_system.shReproducibility requires a fixed commit, configuration, toolchain, dependencies, and clean kernel/BusyBox/user-space outputs; sourcing the environment and running an incremental build is insufficient. Old BusyBox configuration and generated headers, kernel counters, and residual rootfs files can change results. Before cleanup, identify regenerable directories and preserve evidence. This page uses fresh build directories to avoid destroying existing files.
Build checks
- Confirm the intended architecture’s image, configuration, and initramfs were produced and that every command uses the same BUILD_ROOT. Check final CONFIG_PREEMPT_RT=y, XTOS_SCHED=y, and BCI=m.
- Run the matching boot and guest checks. ARM/RISC-V verify_system_* tolerates a small number of failures, so inspect logs and execute the stricter verify_guest_*.
- If static linking cannot find -lc, check cross libc development packages. For archive architecture errors, investigate concurrent builds or stale libraries. For test_*=missing, inspect compiler warnings rather than masking the issue with a build-completion marker.
Source references at commit dd313955ad57542bcd2af8827157d1bbd0cf5e83: scripts/build_kernel.sh, scripts/prepare_linux.sh, scripts/build_system.sh, scripts/build_system_arm64.sh, scripts/build_system_riscv64.sh, scripts/reproducible_env.sh, scripts/verify_guest_arm64.sh, scripts/verify_guest_riscv64.sh, kernel/xtos_defconfig, and system/busybox_defconfig. These scripts determine parameters, artifact paths, and cleanup behavior.