Skip to content

Latest commit

 

History

History
219 lines (177 loc) · 8.51 KB

build.md

File metadata and controls

219 lines (177 loc) · 8.51 KB

Build

Drive supported workflows directly through scripts/nvx.py; no Make wrapper is required.

The portable workflow downloads the pinned Linux archive, verifies its SHA-256, applies every patch in kernel/patches, and builds Linux plus the selected guest artifacts in Docker. Alpine remains the default. OpenVMM builds on the host:

python3 scripts/nvx.py build-guest
python3 scripts/nvx.py build-openvmm

nvx verify selects native architecture pins from SOURCE-MANIFEST.json. The top-level Linux/Alpine pins remain x86_64; architectures.aarch64 supplies the ARM kernel configuration, patch list and Alpine archive URL/checksum. Common version and source metadata remain pinned for both architectures. ARM validation requires the ARM direct-boot settings and the same sandbox protections; it does not require the x86 xe9 driver.

Build every guest artifact, including the Ubuntu EROFS distro layer, with:

python3 scripts/nvx.py build-guest --guest all

The OpenVMM restore step excludes the compatibility IGVM artifact, which NVX does not build or package, so builds do not depend on unrelated upstream workflow artifacts.

OpenVMM builds do not require access to runtime hypervisor devices. By default, Windows builds the native MSVC executable and Linux builds the native GNU target. Both build-openvmm and build accept --backend: kvm selects GNU, mshv selects the statically linked musl target on Linux, and whp selects MSVC on Windows. For example, this builds musl without requiring /dev/mshv:

python3 scripts/nvx.py build-openvmm --backend mshv

The combined build command rejects unsupported OS/backend combinations before producing guest artifacts. Guest-only and source-only commands do not select an OpenVMM build target.

When invoked through NVX, OpenVMM's custom TTRPC lifecycle, SMP, and snapshot test uses the ACPI-free, MP-enabled build/vmlinux and build/initramfs.cpio.gz artifacts. The phase-1 lifecycle and TTRPC interface tests continue to use OpenVMM's packaged guest artifacts.

On a Linux host, build either initramfs directly:

python3 scripts/nvx.py build-initramfs --guest alpine
python3 scripts/nvx.py build-initramfs --guest ubuntu

The default build produces:

build/vmlinux
build/vmlinux.config
build/vmlinux.provenance.json
build/initramfs.cpio.gz
build/initramfs.cpio.gz.packages.json
build/initramfs.provenance.json
build/openvmm.provenance.json
openvmm/target/release/openvmm[.exe]

Programmatic callers can select the backend and override the output destination through OpenVmmBuildConfig. Native and musl builds normalize the newly built executable to that destination before recording its provenance. Host OS detection and backend validation live in build.py, not in the configuration object.

Fixed build inputs and defaults live in build_constants.py. Its namespace classes group kernel, OpenVMM, Alpine, Ubuntu, initramfs, Docker, cache-tool, and release settings. For example, Python callers use KernelBuildConstants.VERSION and AlpineBuildConstants.MINIROOTFS_SHA256; the previous module-level constants are not re-exported. Shared repository and artifact directories belong to BuildConstants.

Keep per-invocation choices and overrides in the existing build configuration objects. Environment-dependent cache locations and host-dependent executable selection are still resolved by their helpers when a configuration is created, not frozen into the constants module.

The provenance sidecars bind the kernel to its pinned archive, patch set, input configuration, generated configuration, and output hash; bind the initramfs and package manifest to the pinned Alpine inputs and source files; and bind OpenVMM to the exact clean gitlink revision and executable hash. The Alpine source-file inputs include the constants module. Packaging rejects missing, dirty, stale, or mismatched provenance.

Ubuntu adds:

build/initramfs-ubuntu.cpio.gz
build/initramfs-ubuntu.cpio.gz.packages.json
build/ubuntu-distro.erofs
build/ubuntu-distro.erofs.manifest.json

Prepare the Ubuntu sandbox layer separately on Linux without replacing an existing output:

python3 scripts/nvx.py build-distro-layer \
  --guest ubuntu \
  --output build/ubuntu-distro.erofs

Pass --replace only when intentionally rebuilding that path. The native Ubuntu build requires zstd, and EROFS conversion additionally requires mkfs.erofs from erofs-utils. The builder verifies Ubuntu Base and every supplemental .deb before safe extraction and never executes binaries or maintainer scripts from the Ubuntu root. The Docker builder pins its Debian base image by digest and installs an exact erofs-utils version so clean EROFS builds use the same encoder.

Check both Ubuntu outputs for deterministic rebuilds with:

python3 scripts/nvx.py verify-guest-determinism --guest ubuntu

Run the two test layers separately:

python3 scripts/nvx.py test-openvmm --backend kvm
python3 scripts/nvx.py test-microvm --backend kvm
python3 scripts/nvx.py test-microvm --backend kvm --guest ubuntu

Both commands need the standard guest build outputs above. The second writes complete per-scenario logs under build/test-results/microvm by default.

The Alpine initramfs includes the sandbox PID-1 bootstrap, its container namespace helpers, the static nvx-device-io benchmark helper, and the static nvx-port-io restore packet helper under /sbin. The matching kernel enables virtio-blk, compressed EROFS, overlayfs, ext4 scratch, memory cgroups, and cgroup BPF. The build fails if olddefconfig drops any required option. The APK manifest records the blkid and util-linux tools used by the bootstrap plus the device helper's source and binary SHA-256 values.

The platform configuration also enables Unix-domain sockets for local guest IPC and seccomp filters for workload syscall policies. Overlayfs does not unconditionally follow redirect metadata. These are kernel capabilities, not product-agent configuration; the same requirements are checked after olddefconfig and when verifying source and generated configurations.

The Ubuntu initramfs uses Ubuntu userland with the NVX kernel. It is not an Ubuntu-kernel or systemd VM. Its distribution-neutral package manifest records the Ubuntu Base and supplemental binary/source identities, license metadata, rootfs SHA-256, and NVX helper provenance.

The native kernel build caches the verified and patched source under .cache/linux, uses O=build/linux, runs olddefconfig, exports the exact generated config as build/vmlinux.config, and fails if ACPI is enabled, PVH remains enabled, or the MP-table, APIC, IOAPIC, and command-line virtio-mmio requirements are missing. Changing an archive hash or patch invalidates both source and object caches; changing the input configuration invalidates the object cache.

Release packaging stages and verifies a complete output before replacing an existing dist/ version. Its SOURCE-MANIFEST.json records the package version and exact hashes for OpenVMM, Linux, the generated kernel config, and the unchanged Alpine initramfs. The OpenVMM section advertises microVM ABI 2, control-session protocol 1, and contract nvx-microvm-v2-control-v1; product guest-agent metadata is intentionally not part of this platform manifest.

A binary release directory has this layout:

bin/openvmm[.exe]
guest/vmlinux
guest/vmlinux.config
guest/initramfs.cpio.gz
guest/initramfs.cpio.gz.packages.json
provenance/openvmm.provenance.json
provenance/initramfs.provenance.json
provenance/vmlinux.provenance.json
licenses/LICENSE-OPENVMM
licenses/COPYING-LINUX
LICENSE
README.md
SOURCE-MANIFEST.json
THIRD_PARTY_NOTICES.md
SHA256SUMS

Packages built with --include-source additionally contain source/. SHA256SUMS has sorted SHA256 relative/path entries using POSIX separators for every packaged file, including SOURCE-MANIFEST.json, except SHA256SUMS itself.

Building the packaged Linux source

The Linux corresponding-source archive contains the patched linux-6.18.38/ tree and the exact vmlinux.config used for the distributed kernel.

On a Linux host with the kernel build dependencies installed, run from the archive root:

mkdir build
cp vmlinux.config build/.config
make -C linux-6.18.38 O="$PWD/build" olddefconfig
make -C linux-6.18.38 O="$PWD/build" -j"$(nproc)" vmlinux

The normal repository workflow performs the same build through scripts/nvx.py build-kernel or the Docker artifact target.