blob: 505630ee41392a1d8a12955b70d324584e105739 [file] [log] [blame]
Chris Kayc8a47ba2023-10-20 09:17:33 +00001#
2# Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6
7#
8# TF-A uses three toolchains:
9#
10# - The host toolchain (`host`) for building native tools
11#  - The AArch32 toolchain (`aarch32`) for building Arm AArch32 images
12# - The AArch64 toolchain (`aarch64`) for building Arm AArch64 images
13#
14# In the main Makefile only one of the two Arm toolchains is enabled in any
15# given build, but individual tools and libraries may need access to both.
16#
17
18toolchains ?= host $(ARCH)
19
20ifneq ($(filter host,$(toolchains)),)
21 host-cc := $(HOSTCC)
22 host-cpp := $(HOSTCPP)
23
24 host-as := $(HOSTAS)
25
26 host-ld := $(HOSTLD)
27 host-oc := $(HOSTOC)
28 host-od := $(HOSTOD)
29 host-ar := $(HOSTAR)
30
31 host-dtc := $(HOSTDTC)
32endif
33
34ifneq ($(filter aarch32,$(toolchains)),)
35 aarch32-cc := $(if $(filter-out default,$(origin CC)),$(CC))
36 aarch32-cpp := $(if $(filter-out default,$(origin CPP)),$(CPP))
37
38 aarch32-as := $(if $(filter-out default,$(origin AS)),$(AS))
39
40 aarch32-ld := $(if $(filter-out default,$(origin LD)),$(LD))
41 aarch32-oc := $(if $(filter-out default,$(origin OC)),$(OC))
42 aarch32-od := $(if $(filter-out default,$(origin OD)),$(OD))
43 aarch32-ar := $(if $(filter-out default,$(origin AR)),$(AR))
44
45 aarch32-dtc := $(if $(filter-out default,$(origin DTC)),$(DTC))
46endif
47
48ifneq ($(filter aarch64,$(toolchains)),)
49 aarch64-cc := $(if $(filter-out default,$(origin CC)),$(CC))
50 aarch64-cpp := $(if $(filter-out default,$(origin CPP)),$(CPP))
51
52 aarch64-as := $(if $(filter-out default,$(origin AS)),$(AS))
53
54 aarch64-ld := $(if $(filter-out default,$(origin LD)),$(LD))
55 aarch64-oc := $(if $(filter-out default,$(origin OC)),$(OC))
56 aarch64-od := $(if $(filter-out default,$(origin OD)),$(OD))
57 aarch64-ar := $(if $(filter-out default,$(origin AR)),$(AR))
58
59 aarch64-dtc := $(if $(filter-out default,$(origin DTC)),$(DTC))
60endif
61
62include $(dir $(lastword $(MAKEFILE_LIST)))build_env.mk
63include $(addprefix $(dir $(lastword $(MAKEFILE_LIST)))toolchains/, \
64 $(addsuffix .mk,$(toolchains)))
65
66#
67# Configure tool classes that we recognize.
68#
69# In the context of this build system, a tool class identifies a specific role
70# or type of tool in the toolchain.
71#
72
73# C-related tools
74tool-classes := cc # C compilers
75tool-classes += cpp # C preprocessors
76
77# Assembly-related tools
78tool-classes += as # Assemblers
79
80# Linking and object-handling tools
81tool-classes += ld # Linkers
82tool-classes += oc # Object copiers
83tool-classes += od # Object dumpers
84tool-classes += ar # Archivers
85
86# Other tools
87tool-classes += dtc # Device tree compilers
88
89#
90# Configure tools that we recognize.
91#
92# Here we declare the list of specific toolchain tools that we know how to
93# interact with. We don't organize these into tool classes yet - that happens
94# further down.
95#
96
97# Arm Compiler for Embedded
98tools := arm-clang # armclang
99tools += arm-link # armlink
100tools += arm-ar # armar
101tools += arm-fromelf # fromelf
102
103# LLVM Project
104tools += llvm-clang # clang
105tools += llvm-lld # lld
106tools += llvm-objcopy # llvm-objcopy
107tools += llvm-objdump # llvm-objdump
108tools += llvm-ar # llvm-ar
109
110# GNU Compiler Collection & GNU Binary Utilities
111tools += gnu-gcc # gcc
112tools += gnu-ld # ld
113tools += gnu-objcopy # objcopy
114tools += gnu-objdump # objdump
115tools += gnu-ar # gcc-ar
116
117# Other tools
118tools += dtc # Device Tree Compiler
119
120#
121# Assign tools to tool classes.
122#
123# Multifunctional tools, i.e. tools which can perform multiple roles in a
124# toolchain, may be specified in multiple tool class lists. For example, a C
125# compiler which can also perform the role of a linker may be placed in both
126# `tools-cc` and `tools-ld`.
127#
128
129# C-related tools
130tools-cc := arm-clang llvm-clang gnu-gcc # C compilers
131tools-cpp := arm-clang llvm-clang gnu-gcc # C preprocessors
132
133# Assembly-related tools
134tools-as := arm-clang llvm-clang gnu-gcc # Assemblers
135
136# Linking and object-handling tools
137tools-ld := arm-clang arm-link llvm-clang llvm-lld gnu-gcc gnu-ld # Linkers
138tools-oc := arm-fromelf llvm-objcopy gnu-objcopy # Object copiers
139tools-od := arm-fromelf llvm-objdump gnu-objdump # Object dumpers
140tools-ar := arm-ar llvm-ar gnu-ar # Archivers
141
142# Other tools
143tools-dtc := dtc # Device tree compilers
144
145define check-tool-class-tools
146 $(eval tool-class := $(1))
147
148 ifndef tools-$(tool-class)
149 $$(error no tools registered to handle tool class `$(tool-class)`)
150 endif
151endef
152
153$(foreach tool-class,$(tool-classes), \
154 $(eval $(call check-tool-class-tools,$(tool-class))))
155
156#
157# Default tools for each toolchain.
158#
159# Toolchains can specify a default path to any given tool with a tool class.
160# These values are used in the absence of user-specified values, and are
161# configured by the parent Makefile using variables of the form:
162#
163# - $(toolchain)-$(tool-class)-default
164#
165# For example, the default C compiler for the AArch32 and AArch64 toolchains
166# could be configured with:
167#
168# - aarch32-cc-default
169# - aarch64-cc-default
170#
171
172define check-toolchain-tool-class-default
173 $(eval toolchain := $(1))
174 $(eval tool-class := $(2))
175
176 ifndef $(toolchain)-$(tool-class)-default
177 $$(error no default value specified for tool class `$(tool-class)` of toolchain `$(toolchain)`)
178 endif
179endef
180
181define check-toolchain-tool-class-defaults
182 $(eval toolchain := $(1))
183
184 $(foreach tool-class,$(tool-classes), \
185 $(eval $(call check-toolchain-tool-class-default,$(toolchain),$(tool-class))))
186endef
187
188$(foreach toolchain,$(toolchains), \
189 $(eval $(call check-toolchain-tool-class-defaults,$(toolchain))))
190
191#
192# Helper functions to identify toolchain tools.
193#
194# The functions defined in this section return a tool identifier when given a
195# path to a binary. We generally check a help or version string to more reliably
196# identify tools than by looking at the path alone (e.g. `gcc` on macOS is
197# actually Apple Clang).
198#
199# Each tool-guessing function (`guess-tool-$(tool)`) takes a single argument
200# giving the path to the tool to guess, and returns a non-empty value if the
201# tool corresponds to the tool identifier `$(tool)`:
202#
203# $(call guess-tool-llvm-clang,aarch64-none-elf-gcc) # <empty>
204# $(call guess-tool-gnu-gcc,aarch64-none-elf-gcc) # <non-empty>
205#
206# The `guess-tool` function tries to find the corresponding tool identifier
207# for a tool given its path. It takes two arguments:
208#
209# - $(1): a list of candidate tool identifiers to check
210# - $(2): the path to the tool to identify
211#
212# If any of the guess functions corresponding to candidate tool identifiers
213# return a non-empty value then the tool identifier of the first function to do
214# so is returned:
215#
216# $(call guess-tool,gnu-gcc llvm-clang,armclang) # <empty>
217# $(call guess-tool,gnu-gcc llvm-clang,clang-14) # llvm-clang
218# $(call guess-tool,gnu-gcc llvm-clang,aarch64-none-elf-gcc-12) # gnu-gcc
219#
220# Tools are checked in the order that they appear in `tools-$(tool-class)`, and
221# the first match is returned.
222#
223
224# Arm Compiler for Embedded
225guess-tool-arm-clang = $(shell $(1) --version 2>&1 | grep -o "Tool: armclang")
226guess-tool-arm-link = $(shell $(1) --help 2>&1 | grep -o "Tool: armlink")
227guess-tool-arm-fromelf = $(shell $(1) --help 2>&1 | grep -o "Tool: fromelf")
228guess-tool-arm-ar = $(shell $(1) --version 2>&1 | grep -o "Tool: armar")
229
230# LLVM Project
231guess-tool-llvm-clang = $(shell $(1) -v 2>&1 | grep -o "clang version")
232guess-tool-llvm-lld = $(shell $(1) --help 2>&1 | grep -o "OVERVIEW: lld")
233guess-tool-llvm-objcopy = $(shell $(1) --help 2>&1 | grep -o "llvm-objcopy tool")
234guess-tool-llvm-objdump = $(shell $(1) --help 2>&1 | grep -o "llvm object file dumper")
235guess-tool-llvm-ar = $(shell $(1) --help 2>&1 | grep -o "LLVM Archiver")
236
237# GNU Compiler Collection & GNU Binary Utilities
238guess-tool-gnu-gcc = $(shell $(1) -v 2>&1 | grep -o "gcc version")
239guess-tool-gnu-ld = $(shell $(1) -v 2>&1 | grep -o "GNU ld")
240guess-tool-gnu-objcopy = $(shell $(1) --version 2>&1 | grep -o "GNU objcopy")
241guess-tool-gnu-objdump = $(shell $(1) --version 2>&1 | grep -o "GNU objdump")
242guess-tool-gnu-ar = $(shell $(1) --version 2>&1 | grep -o "GNU ar")
243
244# Other tools
245guess-tool-dtc = $(shell $(1) --version 2>&1 | grep -o "Version: DTC")
246
247guess-tool = $(firstword $(foreach candidate,$(1), \
248 $(if $(call guess-tool-$(candidate),$(2)),$(candidate))))
249
250#
251# Locate and identify tools belonging to each toolchain.
252#
253# Each tool class in each toolchain receives a variable of the form
254# `$(toolchain)-$(tool)` giving the associated path to the program. For example:
255#
256# - `aarch64-ld` gives the linker for the AArch64 toolchain,
257# - `aarch32-oc` gives the object copier for the AArch32 toolchain, and
258# - `host-cc` gives the C compiler for the host toolchain.
259#
260# For each of these variables, if no program path is explicitly provided by the
261# parent Makefile then the C compiler is queried (if supported) for its
262# location. This is done via the `guess-$(tool)-$(tool-class)` set of functions.
263# For example:
264#
265# - `guess-arm-clang-ld` guesses the linker via Arm Clang,
266# - `guess-llvm-clang-as` guesses the assembler via LLVM Clang, and
267# - `guess-gnu-gcc-od` guesses the object dumper via GNU GCC.
268#
269# If the C compiler cannot provide the location (or the tool class is the C
270# compiler), then it is assigned the value of the `$(toolchain)-$(tool)-default`
271# variable.
272#
273
274guess-arm-clang-cpp = $(1) # Use the C compiler
275guess-arm-clang-as = $(1) # Use the C compiler
276guess-arm-clang-ld = # Fall back to `$(toolchain)-ld-default`
277guess-arm-clang-oc = # Fall back to `$(toolchain)-oc-default`
278guess-arm-clang-od = # Fall back to `$(toolchain)-od-default`
279guess-arm-clang-ar = # Fall back to `$(toolchain)-ar-default`
280
281guess-llvm-clang-cpp = $(1) # Use the C compiler
282guess-llvm-clang-as = $(1) # Use the C compiler
283guess-llvm-clang-ld = $(shell $(1) --print-prog-name ld.lld 2>$(nul))
284guess-llvm-clang-oc = $(shell $(1) --print-prog-name llvm-objcopy 2>$(nul))
285guess-llvm-clang-od = $(shell $(1) --print-prog-name llvm-objdump 2>$(nul))
286guess-llvm-clang-ar = $(shell $(1) --print-prog-name llvm-ar 2>$(nul))
287
288guess-gnu-gcc-cpp = $(1) # Use the C compiler
289guess-gnu-gcc-as = $(1) # Use the C compiler
290guess-gnu-gcc-ld = $(if $(filter 1,$(ENABLE_LTO)),$(1),$(shell $(1) --print-prog-name ld.bfd 2>$(nul)))
291guess-gnu-gcc-oc = $(shell $(1) --print-prog-name objcopy 2>$(nul))
292guess-gnu-gcc-od = $(shell $(1) --print-prog-name objdump 2>$(nul))
293guess-gnu-gcc-ar = $(patsubst %$(notdir $(1)),%$(subst gcc,gcc-ar,$(notdir $(1))),$(1))
294
295define locate-toolchain-tool-cc
296 $(eval toolchain := $(1))
297
298 $(toolchain)-cc := $$(strip \
299 $$(or $$($(toolchain)-cc),$$($(toolchain)-cc-default)))
300 $(toolchain)-cc-id := $$(strip \
301 $$(call guess-tool,$$(tools-cc),$$($(toolchain)-cc)))
302endef
303
304define locate-toolchain-tool
305 $(eval toolchain := $(1))
306 $(eval tool-class := $(2))
307
308 ifndef $(toolchain)-$(tool-class)
309 $(toolchain)-$(tool-class) := $$(strip \
310 $$(call guess-$$($(toolchain)-cc-id)-$(tool-class),$$($(toolchain)-cc)))
311
312 ifeq ($$($(toolchain)-$(tool-class)),)
313 $(toolchain)-$(tool-class) := $$(strip \
314 $$($(toolchain)-$(tool-class)-default))
315 endif
316 endif
317
318 $(toolchain)-$(tool-class)-id := $$(strip \
319 $$(call guess-tool,$$(tools-$(tool-class)),$$($$(toolchain)-$(tool-class))))
320endef
321
322define canonicalize-toolchain-tool-path
323 $(eval toolchain := $(1))
324 $(eval tool-class := $(2))
325
326 $(toolchain)-$(tool-class) := $$(strip $$(or \
327 $$(call which,$$($(toolchain)-$(tool-class))), \
328 $$($(toolchain)-$(tool-class))))
329endef
330
331define locate-toolchain
332 $(eval toolchain := $(1))
333
334 $$(eval $$(call locate-toolchain-tool-cc,$(toolchain)))
335 $$(eval $$(call canonicalize-toolchain-tool-path,$(toolchain),cc))
336
337 $$(foreach tool-class,$$(filter-out cc,$$(tool-classes)), \
338 $$(eval $$(call locate-toolchain-tool,$(toolchain),$$(tool-class))) \
339 $$(eval $$(call canonicalize-toolchain-tool-path,$(toolchain),$$(tool-class))))
340endef
341
342$(foreach toolchain,$(toolchains), \
343 $(eval $(call locate-toolchain,$(toolchain))))