Generate/update prebuilts and use for unit tests

Generates the rootfs image for qemu, as well as the host qemu binary,
its required dynamic libraries, and ROM image.

Use the generated prebuilts for unit testing, rather than the ones
created by the local instance of buildroot.

Signed-off-by: Fuad Tabba <tabba@google.com>
diff --git a/Makefile b/Makefile
index 732f0b2..5680316 100644
--- a/Makefile
+++ b/Makefile
@@ -15,8 +15,8 @@
 
 # Find toolchain for current OS
 UNNAME_S := $(shell uname -s | tr '[:upper:]' '[:lower:]')
-TOOLCHAIN := $(ROOT_DIR)/toolchains/clang/$(UNNAME_S)-x86/clang-r383902
-export PATH := $(TOOLCHAIN)/bin:$(PATH)
+TOOLCHAIN_CLANG := $(ROOT_DIR)/toolchains/clang/$(UNNAME_S)-x86/clang-r383902
+TOOLCHAIN_BINUTILS := $(ROOT_DIR)/toolchains/gcc/linux-x86/aarch64/aarch64-linux-androide-4.9/aarch64-linux-android
 
 ##
 ## Common targets
@@ -49,6 +49,7 @@
 	@echo ''
 	@echo 'Misc Targets:'
 	@echo '   unittests            - runs the kvm unit tests in the qemu-aarch64 simulated environment'
+	@echo '   update-prebuilts     - generates/update the prebuilt rootfs image (aarch64) and the qemu host utilities (aarch64)'
 
 
 ##
@@ -80,11 +81,13 @@
 KUT_ARCH := "arm64"
 KUT_SRC := $(ROOT_DIR)/kvm-unit-tests
 KUT_OUT := $(OUT_DIR)/kvm-unit-tests
-KUT_CC := $(TOOLCHAIN)/bin/clang
-KUT_LD := $(TOOLCHAIN)/bin/ld.lld
-KUT_OBJCOPY := $(TOOLCHAIN)/bin/llvm-objcopy
-KUT_OBJDUMP := $(TOOLCHAIN)/bin/llvm-objdump
-KUT_COMMON_CFLAGS := "-Qunused-arguments -target aarch64-linux-gnueabi -fno-integrated-as -Wno-asm-operand-widths -fpic"
+KUT_CC := $(TOOLCHAIN_CLANG)/bin/clang
+KUT_LD := $(TOOLCHAIN_CLANG)/bin/ld.lld
+KUT_OBJCOPY := $(TOOLCHAIN_CLANG)/bin/llvm-objcopy
+KUT_OBJDUMP := $(TOOLCHAIN_CLANG)/bin/llvm-objdump
+KUT_COMMON_CFLAGS := "-Qunused-arguments -target aarch64-linux-gnueabi -fno-integrated-as -Wno-asm-operand-widths -fpic --gcc-toolchain=$(TOOLCHAIN_BINUTILS)"
+KUT_PATH := $(TOOLCHAIN_CLANG)/bin:$(TOOLCHAIN_BINUTILS)/bin:$(PATH)
+
 
 .PHONY: kvmunittests
 kvmunittests:
@@ -92,7 +95,7 @@
 		./configure --prefix=$(KUT_OUT) --arch=$(KUT_ARCH) \
 			--cc=$(KUT_CC) --ld=$(KUT_LD) \
 			--objcopy=$(KUT_OBJCOPY) --objdump=$(KUT_OBJDUMP)
-	+ cd $(KUT_SRC) && COMMON_CFLAGS=$(KUT_COMMON_CFLAGS) $(MAKE) install
+	+ cd $(KUT_SRC) && PATH=$(KUT_PATH) COMMON_CFLAGS=$(KUT_COMMON_CFLAGS) $(MAKE) install
 
 .PHONY: kvmunittests_clean
 kvmunittests_clean:
@@ -109,8 +112,14 @@
 LINUX_ARCH := arm64
 LINUX_SRC := $(ROOT_DIR)/linux
 LINUX_OUT := $(OUT_DIR)/linux
-LINUX_MAKE := $(MAKE) ARCH=$(LINUX_ARCH) CROSS_COMPILE=$(LINUX_CROSS_PREFIX) \
-	LLVM=1 -C $(LINUX_SRC) V=$(LINUX_VERBOSE) O=$(LINUX_OUT)
+LINUX_PATH := $(TOOLCHAIN_CLANG)/bin:$(PATH)
+LINUX_MAKE := PATH=$(LINUX_PATH) $(MAKE) \
+	ARCH=$(LINUX_ARCH) \
+	CROSS_COMPILE=$(LINUX_CROSS_PREFIX) \
+	LLVM=1 \
+	-C $(LINUX_SRC) \
+	V=$(LINUX_VERBOSE) \
+	O=$(LINUX_OUT)
 
 .PHONY: linux
 linux:
@@ -135,9 +144,56 @@
 	JOBS := "1"
 endif
 
+
+##
+## Generating/Updating prebuilts
+##
+
+update-prebuilts: \
+	prebuilts/images/linux-aarch64 \
+	prebuilts/host_utils/linux-x86
+
+# The rootfs and rom images for qemu
+prebuilts/images/linux-aarch64: buildroot
+	- rm -rf $@
+	mkdir -p $@
+	cp $(BR_OUT)/images/rootfs.ext4 $@
+	cp $(BR_OUT)/per-package/host-qemu/host/share/qemu/efi-virtio.rom $@
+
+# The qemu binary and the libraries it requires
+prebuilts/host_utils/linux-x86: buildroot
+	- rm -rf $@
+	mkdir -p $@/bin
+	cp $(BR_OUT)/host/bin/qemu-system-aarch64 $@/bin
+	mkdir -p $@/lib
+	cp $(BR_OUT)/host/lib/lib* $@/lib
+
+
+##
+## Run unit tests
+##
+
+MAKE_PID := $(shell echo $$PPID)
+JOB_FLAG := $(filter -j%, $(subst -j ,-j,$(shell ps T | grep "^\s*$(MAKE_PID).*$(MAKE)")))
+JOBS     := $(subst -j,,$(JOB_FLAG))
+ifeq ($(JOBS),)
+	JOBS := "1"
+endif
+
+KUT_QEMU_BIN := $(ROOT_DIR)/prebuilts/host_utils/linux-x86/bin/qemu-system-aarch64
+KUT_QEMU_LIB := $(ROOT_DIR)/prebuilts/host_utils/linux-x86/lib
+KUT_ROOTFS_IMAGE := $(ROOT_DIR)/prebuilts/images/linux-aarch64/rootfs.ext4
+
 # Exclude tests that require user interaction or are known to fail.
 KUT_EXCLUDE := "(.+migrat.+)|(pmu-event-introspection)"
 
 .PHONY: unittests
-unittests: buildroot kvmunittests linux
-	@ VERBOSE=$(VERBOSE) $(TEST_SCRIPTS_DIR)/run_tests.sh -j $(JOBS) -t $(KUT_OUT)/share/kvm-unit-tests/ -x $(KUT_EXCLUDE) -l $(LINUX_OUT)/arch/arm64/boot/Image -r $(BR_OUT)/images/rootfs.ext4 -e $(BR_OUT)/host/bin/qemu-system-aarch64
+unittests: kvmunittests linux
+	@LD_LIBRARY_PATH=$(KUT_QEMU_LIB):$(LD_LIBRARY_PATH) VERBOSE=$(VERBOSE) \
+		$(TEST_SCRIPTS_DIR)/run_tests.sh \
+			-j $(JOBS) \
+			-t $(KUT_OUT)/share/kvm-unit-tests/ \
+			-x $(KUT_EXCLUDE) \
+			-l $(LINUX_OUT)/arch/arm64/boot/Image \
+			-r $(KUT_ROOTFS_IMAGE) \
+			-e $(KUT_QEMU_BIN)