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