build: allow multiple toolchain defaults

This change enables a fairly commonly-requested use-case, which is to
fall back to the host system's native toolchain when building on AArch64
if the bare-metal toolchain is not available.

In this situation, if the `aarch64-none-elf` GCC toolchain cannot be
located, the build system will look for `aarch64-linux-gnu` before
giving up.

Change-Id: I39d2a8837b651b28cf0eafa92f6003a7f66767a0
Signed-off-by: Chris Kay <chris.kay@arm.com>
diff --git a/make_helpers/toolchain.mk b/make_helpers/toolchain.mk
index 6a58af1..243e18f 100644
--- a/make_helpers/toolchain.mk
+++ b/make_helpers/toolchain.mk
@@ -68,17 +68,17 @@
         #     The command line or environment variable used to set the tool for
         #     for the given tool class.
         #
-        #   - <toolchain>-<tool-class>-default
-        #
-        #     The default command to use for the given tool class if the user
-        #     does not explicitly provide one, and if the command could not be
-        #     derived from the C compiler.
-        #
-        #   - <toolchain>-<tool-class>-id-default
+        #   - <toolchain>-<tool-class>-default-id
         #
         #     The default tool identifier used if the tool for the given tool
         #     class cannot be identified.
         #
+        #   - <toolchain>-<tool-class>-default
+        #
+        #     The default commands to try, in the order defined, for the given
+        #     tool class if the user does not explicitly provide one, and if the
+        #     command could not be derived from the C compiler.
+        #
 
         toolchains := host # Used for host targets
         toolchains += aarch32 # Used for AArch32 targets
@@ -271,13 +271,16 @@
 
         define toolchain-warn-unrecognized
                 $(warning )
-                $(warning The configured $($(1)-name) $(toolchain-tool-class-name-$(2)) could not be identified and may not be supported:)
+                $(warning The configured $($(1)-name) $(toolchain-tool-class-name-$(2)) could not be identified:)
                 $(warning )
                 $(warning $(space)   $($(1)-$(2))$(if $($(1)-$(2)-parameter), (via `$($(1)-$(2)-parameter)`)))
                 $(warning )
-                $(warning The default $($(1)-name) $(toolchain-tool-class-name-$(2)) is:)
+                $(warning The following tools were tried, but either did not exist or could not be identified:)
                 $(warning )
-                $(warning $(space)   $($(1)-$(2)-default))
+
+                $(foreach default,$($(1)-$(2)-default), \
+                        $(warning $(space) - $(default)))
+
                 $(warning )
                 $(warning The following tools are supported:)
                 $(warning )
@@ -286,7 +289,7 @@
                         $(warning $(space) - $(toolchain-tool-name-$(tool))))
 
                 $(warning )
-                $(warning The build system will treat this $(toolchain-tool-class-name-$(2)) as $(toolchain-tool-name-$($(1)-$(2)-id-default)).)
+                $(warning The build system will treat this $(toolchain-tool-class-name-$(2)) as $(toolchain-tool-name-$($(1)-$(2)-default-id)).)
                 $(warning )
         endef
 
@@ -390,11 +393,17 @@
         #
 
         define toolchain-determine-tool
-                toolchain-$1-$2-guess = $$(if $$(filter-out cc,$2),$\
+                toolchain-$1-$2-guess-from-cc = $$(if $$(filter-out cc,$2),$\
                         $$(call toolchain-guess-$$($1-cc-id)-$2,$$($1-cc)))
 
                 toolchain-$1-$2-shell = $$(or $$($$($1-$2-parameter)),$\
-                        $$(toolchain-$1-$2-guess),$$($1-$2-default))
+                        $$(toolchain-$1-$2-guess-from-cc),$\
+                        $$(toolchain-$1-$2-default))
+
+                toolchain-$1-$2-default = $$(firstword $\
+                        $$(foreach default,$$($1-$2-default),$\
+                                $$(if $$(call which,$$(default)),$$(default))) $\
+                        $$($1-$2-default))
 
                 $1-$2 := $(if $(call which,$$(toolchain-$1-$2-shell)),$\
                         $$(call escape-shell,$$(toolchain-$1-$2-shell)),$\
@@ -402,7 +411,7 @@
 
                 $1-$2-id := $$(or \
                         $$(call toolchain-guess-tool,$$(toolchain-tools-$2),$$($1-$2)),$\
-                        $$(strip $$(call toolchain-warn-unrecognized,$1,$2)$$($1-$2-id-default)))
+                        $$(strip $$(call toolchain-warn-unrecognized,$1,$2)$$($1-$2-default-id)))
         endef
 
         $(foreach toolchain,$(toolchains), \
diff --git a/make_helpers/toolchains/aarch32.mk b/make_helpers/toolchains/aarch32.mk
index 4e25eaa..4063ed9 100644
--- a/make_helpers/toolchains/aarch32.mk
+++ b/make_helpers/toolchains/aarch32.mk
@@ -7,33 +7,33 @@
 aarch32-name := AArch32
 
 aarch32-cc-parameter := CC
+aarch32-cc-default-id := gnu-gcc
 aarch32-cc-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc
-aarch32-cc-id-default := gnu-gcc
 
 aarch32-cpp-parameter := CPP
+aarch32-cpp-default-id := gnu-gcc
 aarch32-cpp-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc
-aarch32-cpp-id-default := gnu-gcc
 
 aarch32-as-parameter := AS
+aarch32-as-default-id := gnu-gcc
 aarch32-as-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc
-aarch32-as-id-default := gnu-gcc
 
 aarch32-ld-parameter := LD
+aarch32-ld-default-id := gnu-gcc
 aarch32-ld-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc
-aarch32-ld-id-default := gnu-gcc
 
 aarch32-oc-parameter := OC
+aarch32-oc-default-id := gnu-objcopy
 aarch32-oc-default := $(or $(CROSS_COMPILE),arm-none-eabi-)objcopy
-aarch32-oc-id-default := gnu-objcopy
 
 aarch32-od-parameter := OD
+aarch32-od-default-id := gnu-objdump
 aarch32-od-default := $(or $(CROSS_COMPILE),arm-none-eabi-)objdump
-aarch32-od-id-default := gnu-objdump
 
 aarch32-ar-parameter := AR
+aarch32-ar-default-id := gnu-ar
 aarch32-ar-default := $(or $(CROSS_COMPILE),arm-none-eabi-)gcc-ar
-aarch32-ar-id-default := gnu-ar
 
 aarch32-dtc-parameter := DTC
+aarch32-dtc-default-id := generic-dtc
 aarch32-dtc-default := dtc
-aarch32-dtc-id-default := generic-dtc
diff --git a/make_helpers/toolchains/aarch64.mk b/make_helpers/toolchains/aarch64.mk
index afefe3e..476fbf3 100644
--- a/make_helpers/toolchains/aarch64.mk
+++ b/make_helpers/toolchains/aarch64.mk
@@ -7,33 +7,40 @@
 aarch64-name := AArch64
 
 aarch64-cc-parameter := CC
+aarch64-cc-default-id := gnu-gcc
 aarch64-cc-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc
-aarch64-cc-id-default := gnu-gcc
+aarch64-cc-default += $(if $(CROSS_COMPILE),,aarch64-linux-gnu-gcc)
 
 aarch64-cpp-parameter := CPP
+aarch64-cpp-default-id := gnu-gcc
 aarch64-cpp-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc
-aarch64-cpp-id-default := gnu-gcc
+aarch64-cpp-default += $(if $(CROSS_COMPILE),,aarch64-linux-gnu-gcc)
 
 aarch64-as-parameter := AS
+aarch64-as-default-id := gnu-gcc
 aarch64-as-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc
-aarch64-as-id-default := gnu-gcc
+aarch64-as-default += $(if $(CROSS_COMPILE),,aarch64-linux-gnu-gcc)
 
 aarch64-ld-parameter := LD
+aarch64-ld-default-id := gnu-gcc
 aarch64-ld-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc
-aarch64-ld-id-default := gnu-gcc
+aarch64-ld-default += $(if $(CROSS_COMPILE),,aarch64-linux-gnu-gcc)
 
 aarch64-oc-parameter := OC
+aarch64-oc-default-id := gnu-objcopy
 aarch64-oc-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)objcopy
-aarch64-oc-id-default := gnu-objcopy
+aarch64-oc-default += $(if $(CROSS_COMPILE),,aarch64-linux-gnu-objcopy)
 
 aarch64-od-parameter := OD
+aarch64-od-default-id := gnu-objdump
 aarch64-od-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)objdump
-aarch64-od-id-default := gnu-objdump
+aarch64-od-default += $(if $(CROSS_COMPILE),,aarch64-linux-gnu-objdump)
 
 aarch64-ar-parameter := AR
+aarch64-ar-default-id := gnu-ar
 aarch64-ar-default := $(or $(CROSS_COMPILE),aarch64-none-elf-)gcc-ar
-aarch64-ar-id-default := gnu-ar
+aarch64-ar-default += $(if $(CROSS_COMPILE),,aarch64-linux-gnu-gcc-ar)
 
 aarch64-dtc-parameter := DTC
+aarch64-dtc-default-id := generic-dtc
 aarch64-dtc-default := dtc
-aarch64-dtc-id-default := generic-dtc
diff --git a/make_helpers/toolchains/host.mk b/make_helpers/toolchains/host.mk
index ddf022f..00a9dd6 100644
--- a/make_helpers/toolchains/host.mk
+++ b/make_helpers/toolchains/host.mk
@@ -7,33 +7,33 @@
 host-name := host
 
 host-cc-parameter := HOSTCC
+host-cc-default-id := gnu-gcc
 host-cc-default := gcc
-host-cc-id-default := gnu-gcc
 
 host-cpp-parameter := HOSTCPP
+host-cpp-default-id := gnu-gcc
 host-cpp-default := gcc
-host-cpp-id-default := gnu-gcc
 
 host-as-parameter := HOSTAS
+host-as-default-id := gnu-gcc
 host-as-default := gcc
-host-as-id-default := gnu-gcc
 
 host-ld-parameter := HOSTLD
+host-ld-default-id := gnu-gcc
 host-ld-default := gcc
-host-ld-id-default := gnu-gcc
 
 host-oc-parameter := HOSTOC
+host-oc-default-id := gnu-objcopy
 host-oc-default := objcopy
-host-oc-id-default := gnu-objcopy
 
 host-od-parameter := HOSTOD
+host-od-default-id := gnu-objdump
 host-od-default := objdump
-host-od-id-default := gnu-objdump
 
 host-ar-parameter := HOSTAR
+host-ar-default-id := gnu-ar
 host-ar-default := gcc-ar
-host-ar-id-default := gnu-ar
 
 host-dtc-parameter := HOSTDTC
+host-dtc-default-id := generic-dtc
 host-dtc-default := dtc
-host-dtc-id-default := generic-dtc
diff --git a/make_helpers/toolchains/rk3399-m0.mk b/make_helpers/toolchains/rk3399-m0.mk
index 92309f1..3a7f173 100644
--- a/make_helpers/toolchains/rk3399-m0.mk
+++ b/make_helpers/toolchains/rk3399-m0.mk
@@ -6,26 +6,26 @@
 
 rk3399-m0-name := RK3399 M0
 
+rk3399-m0-cc-default-id := gnu-gcc
 rk3399-m0-cc-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc
-rk3399-m0-cc-id-default := gnu-gcc
 
+rk3399-m0-cpp-default-id := gnu-gcc
 rk3399-m0-cpp-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc
-rk3399-m0-cpp-id-default := gnu-gcc
 
+rk3399-m0-as-default-id := gnu-gcc
 rk3399-m0-as-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc
-rk3399-m0-as-id-default := gnu-gcc
 
+rk3399-m0-ld-default-id := gnu-gcc
 rk3399-m0-ld-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc
-rk3399-m0-ld-id-default := gnu-gcc
 
+rk3399-m0-oc-default-id := gnu-objcopy
 rk3399-m0-oc-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)objcopy
-rk3399-m0-oc-id-default := gnu-objcopy
 
+rk3399-m0-od-default-id := gnu-objdump
 rk3399-m0-od-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)objdump
-rk3399-m0-od-id-default := gnu-objdump
 
+rk3399-m0-ar-default-id := gnu-ar
 rk3399-m0-ar-default := $(or $(M0_CROSS_COMPILE),arm-none-eabi-)gcc-ar
-rk3399-m0-ar-id-default := gnu-ar
 
+rk3399-m0-dtc-default-id := generic-dtc
 rk3399-m0-dtc-default := dtc
-rk3399-m0-dtc-id-default := generic-dtc