/ 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),)