# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # Builds the kernel and rootfs for the guest used in integration testing. # # The main artifacts are: # target/guest_under_test/bzImage # target/guest_under_test/rootfs ARCH ?= $(shell arch) ifeq ($(ARCH), x86_64) KERNEL_ARCH=x86 KERNEL_BINARY=bzImage DOCKER_ARCH=amd64 CROSS_COMPILE= RUSTFLAGS= else ifeq ($(ARCH), aarch64) KERNEL_ARCH=arm64 KERNEL_BINARY=Image DOCKER_ARCH=arm64v8 CROSS_COMPILE=aarch64-linux-gnu- RUSTFLAGS="-Clinker=aarch64-linux-gnu-ld" else $(error Only x86_64 or aarch64 are supported) endif # Build against the musl toolchain, which will produce a statically linked, # portable binary that we can run on the alpine linux guest without needing # libc at runtime RUST_TARGET ?= $(ARCH)-unknown-linux-musl # We are building everything in target/guest_under_test CARGO_TARGET ?= $(shell cargo metadata --no-deps --format-version 1 | \ jq -r ".target_directory") TARGET ?= $(CARGO_TARGET)/guest_under_test/$(ARCH) $(shell mkdir -p $(TARGET)) # Parameteters for building the kernel locally KERNEL_REPO ?= https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git KERNEL_BRANCH ?= v6.1.59 KERNEL_SRC_BASE ?= $(TARGET)/kernel-source-$(KERNEL_BRANCH) KERNEL_SRC_PATCHED ?= $(KERNEL_SRC_BASE)-patched KERNEL_BUILD ?= $(TARGET)/kernel-build KERNEL_PATCHES ?= "`readlink -f ./kernel/patches`" ################################################################################ # Main targets all: $(TARGET)/rootfs $(TARGET)/bzImage # Clean all local build artifacts, but not downloaded sources. clean: rm -rf $(TARGET)/kernel-build $(TARGET)/rootfs-build $(TARGET)/initramfs-build $(TARGET)/rootfs $(TARGET)/bzImage $(TARGET)/initramfs.cpio.gz clean-all: rm -rf $(TARGET) x86_64_initramfs: $(TARGET)/initramfs delegate: $(TARGET)/rootfs-build/delegate readclock: $(TARGET)/rootfs-build/readclock ################################################################################ # Build rootfs rootfs : ${TARGET}/rootfs # Build rootfs from Dockerfile and export into squashfs $(TARGET)/rootfs: $(TARGET)/rootfs-build/delegate $(TARGET)/rootfs-build/readclock rootfs/Dockerfile # Build image from Dockerfile DOCKER_BUILDKIT=1 docker build -t crosvm_e2e_test_guest $(TARGET)/rootfs-build \ -f rootfs/Dockerfile --build-arg ARCH=$(DOCKER_ARCH) # Make sure tar2sqfs is available. If not, print a help message. tar2sqfs --help > /dev/null || \ { \ echo 'tar2sqfs is not found. To install, run: `sudo apt install -y squashfs-tools-ng` or something equivalent.' ; \ exit 1 ; \ } # Create container and export into squashfs, and don't forget to clean up # the container afterwards. set -x && \ CONTAINER=$$(docker create crosvm_e2e_test_guest) && \ docker export $$CONTAINER | tar2sqfs -c gzip -f $@ && \ docker rm $$CONTAINER # Build and copy delegate binary into rootfs build directory $(TARGET)/rootfs-build/delegate: rootfs/delegate/Cargo.toml rootfs/delegate/src/main.rs rootfs/delegate/src/wire_format.rs rustup target add $(RUST_TARGET) CARGO_TARGET_DIR=$(TARGET) RUSTFLAGS=$(RUSTFLAGS) cargo build --target $(RUST_TARGET) --release --manifest-path=rootfs/delegate/Cargo.toml mkdir -p $(TARGET)/rootfs-build cp $(TARGET)/$(RUST_TARGET)/release/delegate $(TARGET)/rootfs-build/delegate # Build and copy readclock binary into rootfs build directory $(TARGET)/rootfs-build/readclock: rootfs/readclock/Cargo.toml rootfs/readclock/src/main.rs rootfs/readclock/src/lib.rs rustup target add $(RUST_TARGET) CARGO_TARGET_DIR=$(TARGET) RUSTFLAGS=$(RUSTFLAGS) cargo build --target $(RUST_TARGET) --release --manifest-path=rootfs/readclock/Cargo.toml mkdir -p $(TARGET)/rootfs-build cp $(TARGET)/$(RUST_TARGET)/release/readclock $(TARGET)/rootfs-build/readclock ################################################################################ # Build initramfs # Build initramfs from Containerfile and package as cpio archive $(TARGET)/initramfs: $(TARGET)/rootfs-build/delegate initramfs/Containerfile initramfs/init.sh -mkdir -p $(TARGET)/initramfs-build cp initramfs/init.sh $(TARGET)/initramfs-build/init.sh cp $(TARGET)/rootfs-build/delegate $(TARGET)/initramfs-build/delegate podman build -t crosvm_e2e_test_guest_initramfs $(TARGET)/initramfs-build -f initramfs/Containerfile -mkdir -p $(TARGET)/initramfs-build/cpio-base # Create container and export into squashfs, and don't forget to clean up # the container afterwards. set -x; \ CONTAINER=$$(podman create crosvm_e2e_test_guest_initramfs); \ podman export $$CONTAINER | tar -xf - -C $(TARGET)/initramfs-build/cpio-base; \ podman rm $$CONTAINER; \ cd $(TARGET)/initramfs-build/cpio-base; \ find . -print0 | cpio --null --create --verbose --format=newc | gzip --best > $(TARGET)/initramfs.cpio.gz ################################################################################ # Build kernel kernel: $(TARGET)/bzImage # Make this target PHONY to make sure everything is up to date with the kernel's make recipe. # You can use custom kernel source by running: # make kernel KERNEL_SRC_PATCHED=${PATH_TO_YOUR_KERNEL} # (Note: you have to manually apply the patches applied in %-patched recipe to pass all the tests.) .PHONY : $(TARGET)/bzImage $(TARGET)/bzImage : $(KERNEL_SRC_PATCHED) mkdir -p $(KERNEL_BUILD) cat kernel/common.config kernel/$(KERNEL_ARCH).config > $(KERNEL_BUILD)/.config make -C $(KERNEL_SRC_PATCHED) O=$(KERNEL_BUILD) \ ARCH=$(KERNEL_ARCH) \ CROSS_COMPILE=$(CROSS_COMPILE) \ -j$(shell nproc)\ olddefconfig \ $(KERNEL_BINARY) cp $(KERNEL_BUILD)/arch/${KERNEL_ARCH}/boot/$(KERNEL_BINARY) $@ $(KERNEL_SRC_PATCHED): $(KERNEL_SRC_BASE) rm -rf $@.tmp ; true # ignore failure cp -r $(KERNEL_SRC_BASE) $@.tmp git -C $@.tmp am $(KERNEL_PATCHES)/virtio_pvclock.patch mv $@.tmp $@ $(KERNEL_SRC_BASE): rm -rf $@ git clone --depth 1 --branch $(KERNEL_BRANCH) $(KERNEL_REPO) $@ .PHONY: clean all update-prebuilts