Add env variable to specify which toolchain to use

The environment variable TOOLCHAIN can specify whether to use
clang (default), or gcc.

Signed-off-by: Fuad Tabba <tabba@google.com>
Change-Id: I8464f453bfdd5eceea61402981242b1574cf1798
diff --git a/Makefile b/Makefile
index eaa09b9..27339e9 100644
--- a/Makefile
+++ b/Makefile
@@ -27,30 +27,70 @@
 endif
 
 LINUX_OUT := $(OUT_DIR)/linux
-CCACHE_DIR := $(OUT_DIR)/.ccache
 SCRIPTS_DIR := $(ROOT_DIR)/build
 
 ##
 ## Common options
 ##
 VERBOSE ?= 0
-CCACHE ?= ""
-
-# Find toolchain for current OS
-UNNAME_S := $(shell uname -s | tr '[:upper:]' '[:lower:]')
-TOOLCHAIN_CLANG := $(ROOT_DIR)/toolchains/$(UNNAME_S)-x86/clang/clang-r383902
-TOOLCHAIN_BINUTILS := $(ROOT_DIR)/toolchains/$(UNNAME_S)-x86/gcc/aarch64-linux-android
-
-CUSTOM_KERNEL_IMAGE=0
+CUSTOM_KERNEL_IMAGE = 0
+ARCH = arm64
 
 # KERNEL_IMAGE can be set to use own custom kernel image.
 ifdef KERNEL_IMAGE
-CUSTOM_KERNEL_IMAGE=1
+CUSTOM_KERNEL_IMAGE = 1
 else
 KERNEL_IMAGE := $(LINUX_OUT)/arch/arm64/boot/Image.gz
 endif
 
 ##
+## Toolchain options and variables
+##
+
+# Specifies which toolchain of the prebuilt toolchains to use.
+# Can be either clang, gcc-4.9, or gcc-9.2.
+TOOLCHAIN ?= clang
+
+# Find the toolchain path for the current OS.
+UNNAME_S := $(shell uname -s | tr '[:upper:]' '[:lower:]')
+TOOLCHAIN_CLANG := $(ROOT_DIR)/toolchains/$(UNNAME_S)-x86/clang/clang-r383902/
+TOOLCHAIN_GCC_49 := $(ROOT_DIR)/toolchains/$(UNNAME_S)-x86/gcc/aarch64-linux-gnu-4.9/
+TOOLCHAIN_GCC_92 := $(ROOT_DIR)/toolchains/$(UNNAME_S)-x86/gcc/aarch64-linux-gnu-9.2/
+
+# Set the toolchain build binary paths and prefixes.
+ifeq ($(TOOLCHAIN), gcc-4.9)
+TOOLCHAIN_BIN := $(TOOLCHAIN_GCC_49)/bin
+TARGET = aarch64-linux-gnu
+else ifeq ($(TOOLCHAIN), gcc-9.2)
+TOOLCHAIN_BIN := $(TOOLCHAIN_GCC_92)/bin
+TARGET = aarch64-none-linux-gnu
+else ifeq ($(TOOLCHAIN), clang)
+TOOLCHAIN_BIN := $(TOOLCHAIN_CLANG)/bin
+CC := $(TOOLCHAIN_BIN)/clang
+LD := $(TOOLCHAIN_BIN)/ld.lld
+OBJCOPY := $(TOOLCHAIN_BIN)/llvm-objcopy
+OBJDUMP := $(TOOLCHAIN_BIN)/llvm-objdump
+TARGET = aarch64-linux-gnu
+# The GCC toolchain is needed when building kvm-unit-tests as well as Linux
+# with Clang, because of lack of support for the LLVM integrated assembler.
+GCC_TOOLCHAIN_DIR = $(TOOLCHAIN_GCC_49)/bin/
+LLVM = "LLVM=1"
+# KVM Unit Tests requires additional flags to build with Clang.
+KUT_COMMON_CFLAGS := -Qunused-arguments --target=$(TARGET) -fno-integrated-as -Wno-asm-operand-widths -fpic --gcc-toolchain=$(GCC_TOOLCHAIN_DIR) --prefix=$(GCC_TOOLCHAIN_DIR)/$(TARGET)-
+else
+$(error Unrecognized toolchain: TOOLCHAIN=$(TOOLCHAIN))
+endif
+
+# common to all GCC versions
+ifneq ($(TOOLCHAIN), clang)
+CC := $(TOOLCHAIN_BIN)/$(TARGET)-gcc
+LD := $(TOOLCHAIN_BIN)/$(TARGET)-ld
+OBJCOPY := $(TOOLCHAIN_BIN)/$(TARGET)-objcopy
+OBJDUMP := $(TOOLCHAIN_BIN)/$(TARGET)-objdump
+GCC_TOOLCHAIN_DIR := $(TOOLCHAIN_BIN)
+endif
+
+##
 ## Common targets
 ##
 
@@ -118,18 +158,9 @@
 ##
 ## kvm-unit-tests
 ##
-KUT_CROSS_PREFIX ?= "aarch64-linux-android-"
-
-KUT_ARCH := "arm64"
 KUT_SRC := $(ROOT_DIR)/kvm-unit-tests
 KUT_OUT := $(OUT_DIR)/kvm-unit-tests
 KUT_STAMP := $(KUT_OUT)/kvm-unit-tests.stamp
-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: kvm-unit-tests
@@ -138,10 +169,10 @@
 	cd $(KUT_OUT) && \
 		$(KUT_SRC)/configure \
 			--erratatxt=$(KUT_SRC)/errata.txt \
-			--prefix=$(KUT_OUT) --arch=$(KUT_ARCH) \
-			--cc=$(KUT_CC) --ld=$(KUT_LD) \
-			--objcopy=$(KUT_OBJCOPY) --objdump=$(KUT_OBJDUMP)
-	PATH=$(KUT_PATH) COMMON_CFLAGS=$(KUT_COMMON_CFLAGS) \
+			--prefix=$(KUT_OUT) --arch=$(ARCH) \
+			--cc=$(CC) --ld=$(LD) \
+			--objcopy=$(OBJCOPY) --objdump=$(OBJDUMP)
+	COMMON_CFLAGS="$(KUT_COMMON_CFLAGS)" \
 		$(MAKE) -C $(KUT_OUT) standalone
 	touch $(KUT_STAMP)
 
@@ -156,18 +187,15 @@
 ##
 LINUX_DEFCONFIG ?= defconfig
 LINUX_VERBOSE ?= $(VERBOSE)
-LINUX_CROSS_COMPILE ?= "aarch64-linux-gnu-"
 LINUX_SRC ?= $(ROOT_DIR)/linux
 
-LINUX_ARCH := arm64
-LINUX_PATH := $(TOOLCHAIN_CLANG)/bin:$(PATH)
 LINUX_MAKE := \
-	PATH=$(LINUX_PATH) \
-	ARCH=$(LINUX_ARCH) \
-	CROSS_COMPILE=$(LINUX_CROSS_COMPILE) \
+	PATH=$(TOOLCHAIN_BIN):$(PATH) \
+	ARCH=$(ARCH) \
+	CROSS_COMPILE="$(TARGET)-" \
 	$(MAKE) \
-	LLVM=1 \
-	GCC_TOOLCHAIN_DIR=$(TOOLCHAIN_BINUTILS)/bin \
+	$(LLVM) \
+	GCC_TOOLCHAIN_DIR="$(GCC_TOOLCHAIN_DIR)" \
 	-C $(LINUX_SRC) \
 	V=$(LINUX_VERBOSE) \
 	O=$(LINUX_OUT)
@@ -200,11 +228,13 @@
 ## Generating/Updating prebuilts
 ##
 
+.PHONY:update-prebuilts
 update-prebuilts: \
 	prebuilts/linux-aarch64/images \
 	prebuilts/linux-x86/qemu
 
 # The rootfs and rom images for qemu
+.PHONY:prebuilts/linux-aarch64/images
 prebuilts/linux-aarch64/images: buildroot
 	- rm -rf $@
 	mkdir -p $@
@@ -212,13 +242,13 @@
 	cp $(BR_OUT)/per-package/host-qemu/host/share/qemu/efi-virtio.rom $@
 
 # The qemu binary
+.PHONY:prebuilts/linux-x86/qemu
 prebuilts/linux-x86/qemu:
 	- rm -rf $@
-	${SCRIPTS_DIR}/aarch64/build_qemu.sh $(OUT_DIR)/qemu ${TOOLCHAIN_CLANG}/bin
+	${SCRIPTS_DIR}/aarch64/build_qemu.sh $(OUT_DIR)/qemu ${TOOLCHAIN_BIN}
 	mkdir -p $@/bin
 	cp $(OUT_DIR)/qemu/qemu-system-aarch64 $@/bin
 
-
 ##
 ## Run tests
 ##