build: use a toolchain different from prebuilts

This change improves the project build scalability by:
- Providing the clang toolchain path through the PATH environment
variable before invoking make. It means there is no longer a strict
dependency to the toolchain stored in prebuilts. The latter is still
required/used in context of the CI.
- Updating prebuilts tree hash to provide tools required by Arm host
native builds.
- ninja/gn tools path can be provided through NINJA and GN variables on
the make command line (no change). dtc tool is found from PATH.
It can be specified to point to the default prebuilt binary.

Change-Id: Iefb14564554f7d907751ba82db6884fe7fa5c50c
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/Makefile b/Makefile
index ed91a58..c9fb16f 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,12 @@
 
 # Select the project to build.
 PROJECT ?= reference
+
+TOOLCHAIN_LIB := $(shell clang --print-resource-dir)
+
 GN_ARGS := project="$(PROJECT)"
+GN_ARGS += toolchain_lib="$(TOOLCHAIN_LIB)"
+
 # Include assertions in the build
 ifneq (${ENABLE_ASSERTIONS},)
 	GN_ARGS += enable_assertions="$(ENABLE_ASSERTIONS)"
@@ -34,12 +39,16 @@
 else  # HAFNIUM_HERMETIC_BUILD
 
 # Set path to prebuilts used in the build.
-UNNAME_S := $(shell uname -s | tr '[:upper:]' '[:lower:]')
-PREBUILTS := $(CURDIR)/prebuilts/$(UNNAME_S)-x64
+UNAME_S := $(shell uname -s | tr '[:upper:]' '[:lower:]')
+UNAME_M := $(shell uname -m)
+
+ifeq ($(UNAME_M),x86_64)
+UNAME_M := x64
+endif
+
+PREBUILTS := $(CURDIR)/prebuilts/$(UNAME_S)-$(UNAME_M)
 GN ?= $(PREBUILTS)/gn/gn
 NINJA ?= $(PREBUILTS)/ninja/ninja
-export PATH := $(PREBUILTS)/clang/bin:$(PATH)
-
 
 CHECKPATCH := $(CURDIR)/third_party/linux/scripts/checkpatch.pl \
 	--ignore BRACES,SPDX_LICENSE_TAG,VOLATILE,SPLIT_STRING,AVOID_EXTERNS,USE_SPINLOCK_T,NEW_TYPEDEFS,INITIALISED_STATIC,FILE_PATH_CHANGES,EMBEDDED_FUNCTION_NAME,SINGLE_STATEMENT_DO_WHILE_MACRO,MACRO_WITH_FLOW_CONTROL,PREFER_PACKED,PREFER_ALIGNED,INDENTED_LABEL,SPACING --quiet
@@ -95,16 +104,16 @@
 	@echo "Tidying..."
 	# TODO: enable readability-magic-numbers once there are fewer violations.
 	# TODO: enable for c++ tests as it currently gives spurious errors.
-	@find src/ \( -name \*.c \) | xargs prebuilts/linux-x64/clang/bin/clang-tidy -p $(OUT_DIR) -fix
-	@find test/ \( -name \*.c \) | xargs prebuilts/linux-x64/clang/bin/clang-tidy -p $(OUT_DIR) -fix
+	@find src/ \( -name \*.c \) | xargs clang-tidy -p $(OUT_DIR) -fix
+	@find test/ \( -name \*.c \) | xargs clang-tidy -p $(OUT_DIR) -fix
 
 .PHONY: check
 check: $(OUT_DIR)/build.ninja
 	@$(NINJA) -C $(OUT_DIR)
 	@echo "Checking..."
 	# TODO: enable for c++ tests as it currently gives spurious errors.
-	@find src/ \( -name \*.c \) | xargs prebuilts/linux-x64/clang/bin/clang-check -p $(OUT_DIR) -analyze -fix-what-you-can
-	@find test/ \( -name \*.c \) | xargs prebuilts/linux-x64/clang/bin/clang-check -p $(OUT_DIR) -analyze -fix-what-you-can
+	@find src/ \( -name \*.c \) | xargs clang-check -p $(OUT_DIR) -analyze -fix-what-you-can
+	@find test/ \( -name \*.c \) | xargs clang-check -p $(OUT_DIR) -analyze -fix-what-you-can
 
 .PHONY: license
 license:
diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn
index 7e18aeb..055599a 100644
--- a/build/BUILDCONFIG.gn
+++ b/build/BUILDCONFIG.gn
@@ -9,6 +9,11 @@
   # The name of the project being built.
   project = "reference"
 
+  # This default path is overriden from the Makefile based on
+  # the toolchain_lib arg passed through gn.
+  toolchain_lib =
+      rebase_path("//prebuilts/linux-x64/clang/lib64/clang/12.0.5/include")
+
   # Whether to build against the platform for embedded images consisting of
   # include paths and defines. This is also used for host targets that simulate
   # an embedded image.
diff --git a/build/bash/common.inc b/build/bash/common.inc
index f7bfc6c..a047da0 100644
--- a/build/bash/common.inc
+++ b/build/bash/common.inc
@@ -115,6 +115,8 @@
 	##
 	## Paths to tools
 	##
+
+	#TODO: CLANG definition may require update based on build host.
 	CLANG="${ROOT_DIR}/prebuilts/linux-x64/clang/bin/clang"
 	REPO="${ROOT_DIR}/prebuilts/generic/repo/repo"
 
diff --git a/build/image/check_elf.py b/build/image/check_elf.py
index 1c7fb63..6394cb1 100644
--- a/build/image/check_elf.py
+++ b/build/image/check_elf.py
@@ -19,10 +19,8 @@
 import subprocess
 import sys
 
-HF_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-CLANG_ROOT = os.path.join(HF_ROOT, "prebuilts", "linux-x64", "clang")
-OBJDUMP = os.path.join(CLANG_ROOT, "bin", "llvm-objdump")
-NM = os.path.join(CLANG_ROOT, "bin", "llvm-nm")
+OBJDUMP = "llvm-objdump"
+NM = "llvm-nm"
 
 def check_eret_speculation_barrier(args):
 	"""
diff --git a/build/image/convert_to_binary.py b/build/image/convert_to_binary.py
index 1a81e32..af2a450 100644
--- a/build/image/convert_to_binary.py
+++ b/build/image/convert_to_binary.py
@@ -16,9 +16,7 @@
 import subprocess
 import sys
 
-HF_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-CLANG_ROOT = os.path.join(HF_ROOT, "prebuilts", "linux-x64", "clang")
-OBJCOPY = os.path.join(CLANG_ROOT, "bin", "llvm-objcopy")
+OBJCOPY = "llvm-objcopy"
 
 def Main():
     parser = argparse.ArgumentParser()
diff --git a/build/image/dtc.py b/build/image/dtc.py
index d077818..1513120 100755
--- a/build/image/dtc.py
+++ b/build/image/dtc.py
@@ -13,10 +13,8 @@
 import subprocess
 import sys
 
-HF_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-DTC_ROOT = os.path.join(HF_ROOT, "prebuilts", "linux-x64", "dtc")
-DTC = os.path.join(DTC_ROOT, "dtc")
-FDTOVERLAY = os.path.join(DTC_ROOT, "fdtoverlay")
+DTC = "dtc"
+FDTOVERLAY = "fdtoverlay"
 
 def cmd_compile(args):
     exec_args = [
diff --git a/build/toolchain/BUILD.gn b/build/toolchain/BUILD.gn
index beb1f95..e6dad46 100644
--- a/build/toolchain/BUILD.gn
+++ b/build/toolchain/BUILD.gn
@@ -17,17 +17,14 @@
 
   # TODO: Remove //inc/system if we can stop using the version of stdatomic.h
   # from the Android prebuilt Clang.
-  extra_cflags =
-      "-nostdinc -isystem" +
-      rebase_path("//prebuilts/linux-aarch64/musl/include") + " -isystem" +
-      rebase_path("//prebuilts/linux-x64/clang/lib64/clang/12.0.5/include") +
-      " -isystem" + rebase_path("//inc/system")
+  extra_cflags = "-nostdinc -isystem" +
+                 rebase_path("//prebuilts/linux-aarch64/musl/include") +
+                 " -isystem " + rebase_path("//inc/system")
   extra_defines = "-D_LIBCPP_HAS_MUSL_LIBC=1 -D_GNU_SOURCE=1"
   extra_ldflags = "-no-pie -lc --library-path=" +
                   rebase_path("//prebuilts/linux-aarch64/musl/lib/") + " " +
-                  rebase_path("//prebuilts/linux-aarch64/musl/lib/crt1.o") +
-                  " " + rebase_path(
-                      "//prebuilts/linux-x64/clang/lib64/clang/12.0.5/lib/linux/libclang_rt.builtins-aarch64-android.a")
+                  rebase_path("//prebuilts/linux-aarch64/musl/lib/crt1.o")
+
   toolchain_args = {
     use_platform = true
     plat_arch = "fake"
diff --git a/build/toolchain/embedded.gni b/build/toolchain/embedded.gni
index f422efb..2b47c00 100644
--- a/build/toolchain/embedded.gni
+++ b/build/toolchain/embedded.gni
@@ -120,10 +120,9 @@
 
     # TODO: Remove //inc/system if we can stop using the version of stdatomic.h
     # from the Android prebuilt Clang.
-    extra_cflags +=
-        " -target ${invoker.target} -fcolor-diagnostics -nostdinc -isystem" +
-        rebase_path("//prebuilts/linux-x64/clang/lib64/clang/12.0.5/include") +
-        " -isystem" + rebase_path("//inc/system")
+    extra_cflags += " -target ${invoker.target} -fcolor-diagnostics -nostdinc" +
+                    " -isystem ${toolchain_lib}/include" + " -isystem " +
+                    rebase_path("//inc/system")
     extra_ldflags += " -O2 --icf=all --fatal-warnings --color-diagnostics"
 
     toolchain_args = {
diff --git a/build/toolchain/gen_offset_size_header.py b/build/toolchain/gen_offset_size_header.py
index d05bbb4..972ee91 100755
--- a/build/toolchain/gen_offset_size_header.py
+++ b/build/toolchain/gen_offset_size_header.py
@@ -14,9 +14,7 @@
 import subprocess
 import sys
 
-HF_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-BINUTILS_ROOT = os.path.join(HF_ROOT, "prebuilts", "linux-x64", "gcc", "bin")
-STRINGS = os.path.join(BINUTILS_ROOT, "aarch64-linux-android-strings")
+STRINGS = "llvm-strings"
 
 PROLOGUE = """
 /**
diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md
index 8816841..09706b1 100644
--- a/docs/GettingStarted.md
+++ b/docs/GettingStarted.md
@@ -28,6 +28,14 @@
 pip3 install fdt
 ```
 
+Before building, provide the LLVM/clang toolchain and dtc tool in the PATH
+environment variable. To use the default prebuilt toolchain (used by the
+Hafnium CI):
+
+```shell
+PATH=$PWD/prebuilts/linux-x64/clang/bin:$PWD/prebuilts/linux-x64/dtc:$PATH
+```
+
 By default, the hypervisor is built with clang for a few target platforms along
 with tests. Each project in the `project` directory specifies a root
 configurations of the build. Adding a project is the preferred way to extend
diff --git a/kokoro/build.sh b/kokoro/build.sh
index 347f361..8cb658f 100755
--- a/kokoro/build.sh
+++ b/kokoro/build.sh
@@ -11,6 +11,8 @@
 # Initialize global variables, prepare repo for building.
 init_build
 
+export PATH=$(dirname $CLANG):$PWD/prebuilts/linux-x64/dtc:$PATH
+
 # Assign default values to variables.
 if is_kokoro_build
 then
diff --git a/kokoro/test_common.sh b/kokoro/test_common.sh
index e8380a7..2c31159 100644
--- a/kokoro/test_common.sh
+++ b/kokoro/test_common.sh
@@ -20,5 +20,15 @@
 OUT="out/${PROJECT}"
 LOG_DIR_BASE="${OUT}/kokoro_log"
 
-export LD_LIBRARY_PATH="$PWD/prebuilts/linux-x64/clang/lib64"
+# Set path to prebuilts used in the build.
+UNAME_S=$(uname -s | tr '[:upper:]' '[:lower:]')
+UNAME_M=$(uname -m)
+
+if [ $UNAME_M == "x86_64" ]
+then
+        UNAME_M=x64
+fi
+
+export PREBUILTS="$PWD/prebuilts/${UNAME_S}-${UNAME_M}"
+export LD_LIBRARY_PATH="$(clang --print-resource-dir)/../.."
 
diff --git a/prebuilts b/prebuilts
index 4d08763..aeee4ee 160000
--- a/prebuilts
+++ b/prebuilts
@@ -1 +1 @@
-Subproject commit 4d0876375104e71b97da85567509875aba095a6a
+Subproject commit aeee4eed0a5f47856c15c1db56d0ec6452b8f939