1# SPDX-License-Identifier: GPL-2.0-only 2 3# ccache integration 4ifeq ($(CONFIG_CCACHE),y) 5 6CCACHE:=$(word 1,$(wildcard $(addsuffix /ccache,$(subst :, ,$(PATH))))) 7ifeq ($(CCACHE),) 8$(error ccache selected, but not found in PATH) 9endif 10 11export CCACHE_COMPILERCHECK=mtime 12export CCACHE_BASEDIR=$(top) 13export CCACHE_STATSLOG=$(obj)/ccache.stats 14 15$(foreach arch,$(ARCH_SUPPORTED), \ 16 $(eval CC_$(arch):=$(CCACHE) $(CC_$(arch)))) 17 18HOSTCC:=$(CCACHE) $(HOSTCC) 19HOSTCXX:=$(CCACHE) $(HOSTCXX) 20endif 21 22# scan-build integration 23ifneq ($(CCC_ANALYZER_OUTPUT_FORMAT),) 24 25ifeq ($(CCC_ANALYZER_ANALYSIS),) 26export CCC_ANALYZER_ANALYSIS := -analyzer-opt-analyze-headers 27endif 28 29$(foreach arch,$(ARCH_SUPPORTED), \ 30 $(eval CC_$(arch):=CCC_CC="$(CC_$(arch))" $(CC) )) 31 32HOSTCC:=CCC_CC="$(HOSTCC)" $(CC) 33HOSTCXX:=CCC_CXX="$(HOSTCXX)" $(CXX) 34endif 35 36# include-what-you-use integration 37ifeq ($(CONFIG_IWYU),y) 38 39IWYU:=$(word 1,$(wildcard $(addsuffix /iwyu,$(subst :, ,$(PATH))))) 40ifeq ($(IWYU),) 41$(error include-what-you-use selected, but not found in PATH) 42endif 43 44$(foreach arch,$(ARCH_SUPPORTED), \ 45 $(eval CC_$(arch):=$(IWYU) )) 46 47CFLAGS_common := -Xiwyu --prefix_header_includes=remove -Xiwyu --no_comments -Xiwyu --no_fwd_decls $(CFLAGS_common) 48NOCOMPILE := 1 49endif 50 51COREBOOT_STANDARD_STAGES := decompressor bootblock verstage romstage ramstage 52MAP-decompressor := bootblock 53 54ARCHDIR-i386 := x86 55ARCHDIR-x86_32 := x86 56ARCHDIR-x86_64 := x86 57ARCHDIR-arm := arm 58ARCHDIR-arm64 := arm64 59ARCHDIR-riscv := riscv 60ARCHDIR-ppc64 := ppc64 61 62CFLAGS_arm += 63CFLAGS_arm64 += -mgeneral-regs-only 64CFLAGS_riscv += 65CFLAGS_x86_32 += 66CFLAGS_x86_64 += -mcmodel=large -mno-red-zone 67CFLAGS_ppc64 += 68 69GCC_ADAFLAGS_arm += 70GCC_ADAFLAGS_arm64 += -mgeneral-regs-only 71GCC_ADAFLAGS_riscv += 72GCC_ADAFLAGS_x86_32 += 73GCC_ADAFLAGS_x86_64 += -mcmodel=large -mno-red-zone 74GCC_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.) 89ifeq ($(CONFIG_COMPILER_GCC),y) 90CFLAGS_arm += -Wstack-usage=1536 91CFLAGS_arm64 += -Wstack-usage=1536 92CFLAGS_riscv += -Wstack-usage=1536 93CFLAGS_ppc64 += -Wstack-usage=1536 94endif 95 96toolchain_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 108map_stage = $(strip $(if $(MAP-$(1)),$(MAP-$(1)),$(1))) 109set_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. 116standard-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 125define 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)))) 129CC_$(1) := $(CC_$(2)) 130GCC_$(1) := $(GCC_CC_$(2)) 131LD_$(1) := $(LD_$(2)) 132NM_$(1) := $(NM_$(2)) 133AR_$(1) := $(AR_$(2)) 134GNATBIND_$(1) := $(GNATBIND_$(2)) 135OBJCOPY_$(1) := $(OBJCOPY_$(2)) 136OBJDUMP_$(1) := $(OBJDUMP_$(2)) 137STRIP_$(1) := $(STRIP_$(2)) 138READELF_$(1) := $(READELF_$(2)) 139CFLAGS_$(1) = $$(CFLAGS_common) $$(CFLAGS_$(2)) 140ADAFLAGS_$(1) = --RTS=$$(obj)/libgnat-$(2)/ $$(ADAFLAGS_common) $$(GCC_ADAFLAGS_$(2)) 141CPPFLAGS_$(1) = $$(CPPFLAGS_common) $$(CPPFLAGS_$(2)) -D__ARCH_$(2)__ 142COMPILER_RT_$(1) := $$(COMPILER_RT_$(2)) 143COMPILER_RT_FLAGS_$(1) := $$(COMPILER_RT_FLAGS_$(2)) 144LDFLAGS_$(1) = $$(LDFLAGS_common) $$(LDFLAGS_$(2)) 145endef 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 154define define_class 155classes-y += $(1) 156$(eval $(call create_class_compiler,$(1),$(2))) 157endef 158 159# initialize standard toolchain (CC,AS and others) for give stage 160# @1 : stage for which the toolchain is to be initialized 161init_standard_toolchain = \ 162 $(eval $(call set_stage_toolchain,$(1))) \ 163 $(eval $(call create_class_compiler,$(1),$(ARCH-$(1)-y))) 164 165init_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) 174ifneq ($(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 178COMPILERFAIL:=0 179IASLFAIL:=0 180 181ifneq ($(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 iasl doesn't match the current coreboot version, fail the test 192# TODO: Figure out if iasl is even needed for the build. 193$(if $(shell if [ -n "$(IASL)" ]; then \ 194 $(IASL) -v 2>&1 | grep -q "coreboot toolchain" || \ 195 echo not-coreboot; else echo not-coreboot; fi), \ 196 $(eval COMPILERFAIL:=1)$(eval IASLFAIL:=1)\ 197 $(warning The coreboot toolchain version of iasl \ 198 '$(shell util/crossgcc/buildgcc -s iasl)' was not found)) 199else #$(CONFIG_ANY_TOOLCHAIN) 200# If the coreboot toolchain isn't being used, verify that there is A toolchain 201$(foreach arch,$(sort \ 202 $(foreach stage,$(COREBOOT_STANDARD_STAGES),$(ARCH-$(stage)-y))), \ 203 $(if $(CC_$(arch)),, $(eval COMPILERFAIL:=1) \ 204 $(warning No compiler found for '$(arch)' architecture. \ 205 Install one or use the coreboot toolchain?)) ) 206# If iasl isn't present, fail 207# TODO: Figure out if iasl is even needed for the build. 208$(if $(IASL),, $(eval COMPILERFAIL:=1)$(eval IASLFAIL:=1) \ 209 $(warning iasl not found. \ 210 Please install it or use the coreboot toolchain.)) 211endif 212 213# If the compiler check failed, print out warnings 214ifeq ($(COMPILERFAIL),1) 215ifneq ($(XGCCPATH),) 216$(warning ) 217$(warning Path to your toolchain is currently set to '$(XGCCPATH)') 218endif 219$(warning ) 220$(warning To build the entire coreboot toolchain: run 'make crossgcc') 221ifeq ($(IASLFAIL),1) 222$(warning To build just IASL: run 'make iasl') 223endif #($(IASLFAIL),1) 224$(warning For more toolchain build targets: run 'make help_toolchain') 225$(warning ) 226ifneq ($(CONFIG_ANY_TOOLCHAIN),y) 227$(warning To try to use any toolchain in your path, \ 228 run 'make menuconfig', then select) 229$(warning the config option: 'General setup', \ 230 and 'Allow building with any toolchain') 231$(warning Note that this is NOT supported. \ 232 Using it means you're on your own.) 233$(warning ) 234endif #($(CONFIG_ANY_TOOLCHAIN),y) 235$(error Halting the build) 236endif #($(COMPILERFAIL),1) 237 238endif #($(NOCOMPILE),1) 239 240# Run the toolchain version checks if the requested target is 'test-toolchain' 241# Checks the versions of GCC, binutils, clang, and IASL 242ifneq ($(MAKECMDGOALS),) 243ifneq ($(filter test-toolchain,$(MAKECMDGOALS)),) 244$(foreach arch, $(ARCH_SUPPORTED), \ 245 $(if $(shell if [ -n "$(GCC_CC_$(arch))" ]; then \ 246 $(GCC_CC_$(arch)) --version 2>&1 | head -n1 | rev | \ 247 cut -d ' ' -f 1 | rev | \ 248 grep -q "$$(util/crossgcc/buildgcc -s gcc)" || \ 249 echo not-current; fi), \ 250 $(eval COMPILER_OUT_OF_DATE:=1) \ 251 $(warning The coreboot toolchain version of gcc for '$(arch)' \ 252 architecture is not the current version.) \ 253 $(warning $(arch) gcc version from buildgcc: \ 254 $(shell util/crossgcc/buildgcc -s gcc)) \ 255 $(warning $(arch) version of gcc executable: \ 256 $(shell $(GCC_CC_$(arch)) --version | head -n1 | \ 257 rev | cut -d ' ' -f 1 | rev))) \ 258 $(if $(shell if [ -n "$(CLANG_CC_$(arch))" ]; then \ 259 $(CLANG_CC_$(arch)) --version 2>&1 | \ 260 sed 's/.*clang version/clang version/' | \ 261 head -n1 | cut -d ' ' -f 3 | \ 262 grep -q "$(shell util/crossgcc/buildgcc -s clang)" || \ 263 echo not-current; fi), \ 264 $(eval COMPILER_OUT_OF_DATE:=1) \ 265 $(warning The coreboot toolchain version of clang for \ 266 '$(arch)' architecture is not the current version.) \ 267 $(warning $(arch) clang version from buildgcc: \ 268 $(shell util/crossgcc/buildgcc -s clang)) \ 269 $(warning $(arch) version of clang executable: \ 270 $(shell $(CLANG_CC_$(arch)) --version 2>&1 | \ 271 sed 's/.*clang version/clang version/' | \ 272 head -n1 | cut -d ' ' -f 3))) \ 273 $(if $(shell if [ "$(OBJDUMP_$(arch))" != "invalidobjdump" ]; then \ 274 $(OBJDUMP_$(arch)) -v 2>&1 | \ 275 grep -q "$(shell util/crossgcc/buildgcc -s binutils)" || \ 276 echo not-current; fi), \ 277 $(eval COMPILER_OUT_OF_DATE:=1)\ 278 $(warning The coreboot toolchain version of binutils for \ 279 '$(arch)' architecture is not the current version.)) \ 280) 281$(if $(shell if [ -n "$(IASL)" ]; then $(IASL) -v 2>&1 | \ 282 grep -q "$(shell util/crossgcc/buildgcc -s iasl)" || \ 283 echo not-coreboot; fi), \ 284 $(eval COMPILER_OUT_OF_DATE:=1)\ 285 $(warning The coreboot toolchain version of iasl \ 286 is not the current version) \ 287 $(warning $(arch) iasl version from buildgcc: \ 288 $(shell util/crossgcc/buildgcc -s iasl)) \ 289 $(warning $(arch) version of iasl executable: \ 290 $(shell $(IASL) -v 2>&1 | \ 291 grep ASL+ | rev | cut -f 1 -d ' ' | rev))) 292$(eval UPDATED_SUBMODULES:=1) 293endif #($(filter crossgcc_check%,$(MAKECMDGOALS)),) 294endif #($(MAKECMDGOALS),) 295