/ toolchain.mk
toolchain.mk
  1  # SPDX-License-Identifier: GPL-2.0-only
  2  
  3  # ccache integration
  4  ifeq ($(CONFIG_CCACHE),y)
  5  
  6  CCACHE:=$(word 1,$(wildcard $(addsuffix /ccache,$(subst :, ,$(PATH)))))
  7  ifeq ($(CCACHE),)
  8  $(error ccache selected, but not found in PATH)
  9  endif
 10  
 11  export CCACHE_COMPILERCHECK=mtime
 12  export CCACHE_BASEDIR=$(top)
 13  export CCACHE_STATSLOG=$(obj)/ccache.stats
 14  
 15  $(foreach arch,$(ARCH_SUPPORTED), \
 16  	$(eval CC_$(arch):=$(CCACHE) $(CC_$(arch))))
 17  
 18  HOSTCC:=$(CCACHE) $(HOSTCC)
 19  HOSTCXX:=$(CCACHE) $(HOSTCXX)
 20  endif
 21  
 22  # scan-build integration
 23  ifneq ($(CCC_ANALYZER_OUTPUT_FORMAT),)
 24  
 25  ifeq ($(CCC_ANALYZER_ANALYSIS),)
 26  export CCC_ANALYZER_ANALYSIS := -analyzer-opt-analyze-headers
 27  endif
 28  
 29  $(foreach arch,$(ARCH_SUPPORTED), \
 30  	$(eval CC_$(arch):=CCC_CC="$(CC_$(arch))" $(CC) ))
 31  
 32  HOSTCC:=CCC_CC="$(HOSTCC)" $(CC)
 33  HOSTCXX:=CCC_CXX="$(HOSTCXX)" $(CXX)
 34  endif
 35  
 36  # include-what-you-use integration
 37  ifeq ($(CONFIG_IWYU),y)
 38  
 39  IWYU:=$(word 1,$(wildcard $(addsuffix /iwyu,$(subst :, ,$(PATH)))))
 40  ifeq ($(IWYU),)
 41  $(error include-what-you-use selected, but not found in PATH)
 42  endif
 43  
 44  $(foreach arch,$(ARCH_SUPPORTED), \
 45  	$(eval CC_$(arch):=$(IWYU) ))
 46  
 47  CFLAGS_common := -Xiwyu --prefix_header_includes=remove  -Xiwyu --no_comments  -Xiwyu --no_fwd_decls $(CFLAGS_common)
 48  NOCOMPILE := 1
 49  endif
 50  
 51  COREBOOT_STANDARD_STAGES := decompressor bootblock verstage romstage ramstage
 52  MAP-decompressor := bootblock
 53  
 54  ARCHDIR-i386	:= x86
 55  ARCHDIR-x86_32	:= x86
 56  ARCHDIR-x86_64	:= x86
 57  ARCHDIR-arm	:= arm
 58  ARCHDIR-arm64	:= arm64
 59  ARCHDIR-riscv	:= riscv
 60  ARCHDIR-ppc64	:= ppc64
 61  
 62  CFLAGS_arm	+=
 63  CFLAGS_arm64	+=
 64  CFLAGS_riscv	+=
 65  CFLAGS_x86_32	+=
 66  CFLAGS_x86_64	+= -mcmodel=large -mno-red-zone
 67  CFLAGS_ppc64	+=
 68  
 69  GCC_ADAFLAGS_arm	+=
 70  GCC_ADAFLAGS_arm64	+= -mgeneral-regs-only
 71  GCC_ADAFLAGS_riscv	+=
 72  GCC_ADAFLAGS_x86_32	+=
 73  GCC_ADAFLAGS_x86_64	+= -mcmodel=large -mno-red-zone
 74  GCC_ADAFLAGS_ppc64	+=
 75  
 76  # Some boards only provide 2K stacks, so storing lots of data there leads to
 77  # problems. Since C rules don't allow us to statically determine the maximum
 78  # stack use, we use 1.5K as heuristic, assuming that we typically have lots
 79  # of tiny stack frames and the odd large one.
 80  #
 81  # Store larger buffers in BSS, use static to share data in cache-as-ram
 82  # on x86.
 83  # Since GCCs detection of dynamic array bounds unfortunately seems to be
 84  # very basic, you'll sometimes have to use a static upper bound for the
 85  # size and an assert() to make sure it's honored (see gpio_base3_value()
 86  # for an example).
 87  # (If you absolutely need a larger stack frame and are 100% sure it cannot
 88  # cause problems, you can whitelist it with #pragma diagnostic.)
 89  ifeq ($(CONFIG_COMPILER_GCC),y)
 90  CFLAGS_arm	+= -Wstack-usage=1536
 91  CFLAGS_arm64	+= -Wstack-usage=1536
 92  CFLAGS_riscv	+= -Wstack-usage=1536
 93  CFLAGS_ppc64	+= -Wstack-usage=1536
 94  endif
 95  
 96  toolchain_to_dir = \
 97  	$(foreach arch,$(ARCH_SUPPORTED),\
 98  	$(eval CPPFLAGS_$(arch) += \
 99  	-Isrc/arch/$(ARCHDIR-$(arch))/include))
100  
101  # set_stage_toolchain: Decides the toolchain to be used by every stage
102  # E.g.: If bootblock is x86_32, it sets ARCH-BOOTBLOCK-y = x86_32, whereas
103  # ARCH-BOOTBLOCK-n = armv7. Then, ARCH-BOOTBLOCK-y can be used anywhere to
104  # decide the compiler toolchain for bootblock stage
105  # This step is essential for initializing the toolchain for coreboot standard
106  # stages i.e. bootblock, romstage and ramstage, since it acts as the second
107  # parameter to create_class_compiler below in init_standard_toolchain
108  map_stage = $(strip $(if $(MAP-$(1)),$(MAP-$(1)),$(1)))
109  set_stage_toolchain= \
110  	$(foreach arch,$(ARCH_SUPPORTED), \
111  	$(eval ARCH-$(1)-$($(shell \
112  		echo CONFIG_ARCH_$(call map_stage,$(1))_$(arch) | \
113  		tr '[:lower:]' '[:upper:]')) := $(arch)))
114  
115  # standard-archs: Tell which architectures are used by the standard stages.
116  standard-archs = $(sort $(foreach stagearch, \
117  			  $(patsubst %,ARCH-%-y,$(COREBOOT_STANDARD_STAGES)), \
118  			  $($(stagearch))))
119  
120  # create_class_compiler: Used to create compiler tool set for
121  # special classes
122  # @1: special class
123  # @2: compiler set to be used
124  # e.g.: smm special class uses i386 as compiler set
125  define create_class_compiler
126  $(if $(2),,$(warning *** The toolchain architecture for $(1) is unknown.) \
127  	$(warning CONFIG_ARCH_$(1)_* settings in $(DOTCONFIG):) \
128  	$(error $(shell grep CONFIG_ARCH_$(1)_ $(DOTCONFIG))))
129  CC_$(1) := $(CC_$(2))
130  GCC_$(1) := $(GCC_CC_$(2))
131  LD_$(1) := $(LD_$(2))
132  NM_$(1) := $(NM_$(2))
133  AR_$(1) := $(AR_$(2))
134  GNATBIND_$(1) := $(GNATBIND_$(2))
135  OBJCOPY_$(1) := $(OBJCOPY_$(2))
136  OBJDUMP_$(1) := $(OBJDUMP_$(2))
137  STRIP_$(1) := $(STRIP_$(2))
138  READELF_$(1) := $(READELF_$(2))
139  CFLAGS_$(1) = $$(CFLAGS_common) $$(CFLAGS_$(2))
140  ADAFLAGS_$(1) = --RTS=$$(obj)/libgnat-$(2)/ $$(ADAFLAGS_common) $$(GCC_ADAFLAGS_$(2))
141  CPPFLAGS_$(1) = $$(CPPFLAGS_common) $$(CPPFLAGS_$(2)) -D__ARCH_$(2)__
142  COMPILER_RT_$(1) := $$(COMPILER_RT_$(2))
143  COMPILER_RT_FLAGS_$(1) := $$(COMPILER_RT_FLAGS_$(2))
144  LDFLAGS_$(1) = $$(LDFLAGS_common) $$(LDFLAGS_$(2))
145  endef
146  
147  # define_class: Allows defining any program as dynamic class and compiler tool
148  # set for the same based on the architecture for which the program is to be
149  # compiled
150  # @1: program (class name)
151  # @2: architecture for which the program needs to be compiled
152  # IMP: Ensure that define_class is called before any .c or .S files are added to
153  # the class of the program. Check subdirs-y for order of subdirectory inclusions
154  define define_class
155  classes-y += $(1)
156  $(eval $(call create_class_compiler,$(1),$(2)))
157  endef
158  
159  # initialize standard toolchain (CC,AS and others) for give stage
160  # @1 : stage for which the toolchain is to be initialized
161  init_standard_toolchain = \
162  	$(eval $(call set_stage_toolchain,$(1))) \
163  	$(eval $(call create_class_compiler,$(1),$(ARCH-$(1)-y)))
164  
165  init_stages = \
166  	$(foreach stage,$(COREBOOT_STANDARD_STAGES), \
167  	$(eval $(call init_standard_toolchain,$(stage))))
168  
169  $(eval $(call toolchain_to_dir))
170  
171  $(call init_stages)
172  
173  # Test for coreboot toolchain (except when explicitly not requested)
174  ifneq ($(NOCOMPILE),1)
175  # Only run if we're doing a build (not for tests, kconfig, ...)
176  # rationale: gcc versions by Linux distributions tend to be quite messed up
177  # llvm/clang also needs patches supplied by the coreboot build
178  COMPILERFAIL:=0
179  IASLFAIL:=0
180  
181  ifneq ($(CONFIG_ANY_TOOLCHAIN),y)
182  # Verify that the coreboot toolchain is being used.
183  $(foreach arch,$(sort $(foreach stage,\
184  	$(COREBOOT_STANDARD_STAGES),$(ARCH-$(stage)-y))), \
185  	$(if $(shell if [ -n "$(CC_$(arch))" ]; then \
186  		$(CC_$(arch)) -v 2>&1 | grep -q "coreboot toolchain" || \
187  		echo not-coreboot; else echo not-coreboot; fi), \
188  		$(eval COMPILERFAIL:=1)\
189  		$(warning The coreboot toolchain for '$(arch)'\
190  			architecture was not found.)\
191  		$(if $(CC_$(arch)),\
192  			$(warning $(CC_$(arch)) -v)\
193  			$(warning $(shell $(CC_$(arch)) -v)))))
194  # If iasl doesn't match the current coreboot version, fail the test
195  # TODO: Figure out if iasl is even needed for the build.
196  $(if $(shell if [ -n "$(IASL)" ]; then \
197  	$(IASL) -v 2>&1 | grep -q "coreboot toolchain" || \
198  	echo not-coreboot; else echo not-coreboot; fi), \
199  	$(eval COMPILERFAIL:=1)$(eval IASLFAIL:=1)\
200  	$(warning The coreboot toolchain version of iasl \
201  		'$(shell util/crossgcc/buildgcc -s iasl)' was not found))
202  else #$(CONFIG_ANY_TOOLCHAIN)
203  # If the coreboot toolchain isn't being used, verify that there is A toolchain
204  $(foreach arch,$(sort \
205  	$(foreach stage,$(COREBOOT_STANDARD_STAGES),$(ARCH-$(stage)-y))), \
206  	$(if $(CC_$(arch)),, $(eval COMPILERFAIL:=1) \
207  	$(warning No compiler found for '$(arch)' architecture. \
208  		Install one or use the coreboot toolchain?)) )
209  # If iasl isn't present, fail
210  # TODO: Figure out if iasl is even needed for the build.
211  $(if $(IASL),, $(eval COMPILERFAIL:=1)$(eval IASLFAIL:=1) \
212  	$(warning iasl not found. \
213  		Please install it or use the coreboot toolchain.))
214  endif
215  
216  # If the compiler check failed, print out warnings
217  ifeq ($(COMPILERFAIL),1)
218  ifneq ($(XGCCPATH),)
219  $(warning )
220  $(warning Path to your toolchain is currently set to '$(XGCCPATH)')
221  endif
222  $(warning )
223  $(warning To build the entire coreboot toolchain: run 'make crossgcc')
224  ifeq ($(IASLFAIL),1)
225  $(warning To build just IASL: run 'make iasl')
226  endif #($(IASLFAIL),1)
227  $(warning For more toolchain build targets: run 'make help_toolchain')
228  $(warning )
229  ifneq ($(CONFIG_ANY_TOOLCHAIN),y)
230  $(warning To try to use any toolchain in your path, \
231  	run 'make menuconfig', then select)
232  $(warning the config option: 'General setup', \
233  	and 'Allow building with any toolchain')
234  $(warning Note that this is NOT supported.  \
235  	Using it means you're on your own.)
236  $(warning )
237  endif #($(CONFIG_ANY_TOOLCHAIN),y)
238  $(error Halting the build)
239  endif #($(COMPILERFAIL),1)
240  
241  endif #($(NOCOMPILE),1)
242  
243  # Run the toolchain version checks if the requested target is 'test-toolchain'
244  # Checks the versions of GCC, binutils, clang, and IASL
245  ifneq ($(MAKECMDGOALS),)
246  ifneq ($(filter test-toolchain,$(MAKECMDGOALS)),)
247  $(foreach arch, $(ARCH_SUPPORTED), \
248  	$(if $(shell if [ -n "$(GCC_CC_$(arch))" ]; then \
249  		$(GCC_CC_$(arch)) --version 2>&1 | head -n1 | rev | \
250  		cut -d ' ' -f 1 | rev | \
251  		grep -q "$$(util/crossgcc/buildgcc -s gcc)" || \
252  		echo not-current; fi), \
253  		$(eval COMPILER_OUT_OF_DATE:=1) \
254  		$(warning The coreboot toolchain version of gcc for '$(arch)' \
255  			architecture is not the current version.) \
256  		$(warning $(arch) gcc version from buildgcc: \
257  			$(shell util/crossgcc/buildgcc -s gcc)) \
258  		$(warning $(arch) version of gcc executable: \
259  			$(shell $(GCC_CC_$(arch)) --version | head -n1 | \
260  			rev | cut -d ' ' -f 1 | rev))) \
261  	$(if $(shell if [ -n "$(CLANG_CC_$(arch))" ]; then \
262  		$(CLANG_CC_$(arch)) --version  2>&1 | \
263  			sed 's/.*clang version/clang version/' | \
264  			head -n1 | cut -d ' ' -f 3 | \
265  		grep -q "$(shell util/crossgcc/buildgcc -s clang)" || \
266  		echo not-current; fi), \
267  		$(eval COMPILER_OUT_OF_DATE:=1) \
268  		$(warning The coreboot toolchain version of clang for \
269  			'$(arch)' architecture is not the current version.) \
270  		$(warning $(arch) clang version from buildgcc: \
271  			$(shell util/crossgcc/buildgcc -s clang)) \
272  		$(warning $(arch) version of clang executable: \
273  			$(shell $(CLANG_CC_$(arch)) --version 2>&1 | \
274  			sed 's/.*clang version/clang version/' | \
275  			head -n1 | cut -d ' ' -f 3))) \
276  	$(if $(shell if [ "$(OBJDUMP_$(arch))" != "invalidobjdump" ]; then \
277  		$(OBJDUMP_$(arch)) -v 2>&1 | \
278  		grep -q "$(shell util/crossgcc/buildgcc -s binutils)" || \
279  		echo not-current; fi), \
280  		$(eval COMPILER_OUT_OF_DATE:=1)\
281  		$(warning The coreboot toolchain version of binutils for \
282  			'$(arch)' architecture is not the current version.)) \
283  )
284  $(if $(shell if [ -n "$(IASL)" ]; then $(IASL) -v 2>&1 | \
285  	grep -q "$(shell util/crossgcc/buildgcc -s iasl)" || \
286  	echo not-coreboot; fi), \
287  	$(eval COMPILER_OUT_OF_DATE:=1)\
288  	$(warning The coreboot toolchain version of iasl \
289  		is not the current version) \
290  		$(warning $(arch) iasl version from buildgcc: \
291  			$(shell util/crossgcc/buildgcc -s iasl)) \
292  		$(warning $(arch) version of iasl executable: \
293  			$(shell $(IASL) -v 2>&1 | \
294  			grep ASL+ | rev | cut -f 1 -d ' ' | rev)))
295  $(eval UPDATED_SUBMODULES:=1)
296  endif #($(filter crossgcc_check%,$(MAKECMDGOALS)),)
297  endif #($(MAKECMDGOALS),)