mb/starlabs/{lite_adl,byte_adl}: Don't select MAINBOARD_HAS_TPM2
[coreboot2.git] / util / xcompile / xcompile
blob3fb0cb75915ba561f781cdbc81d61e3a45033e93
1 #!/usr/bin/env bash
3 # SPDX-License-Identifier: GPL-2.0-only
5 # Usage: [--debug] [path to xgcc/bin directory]
7 # Enable debug output
8 if [ "$1" = "--debug" ]; then
9 shift
10 set -x
13 # GENERIC_COMPILER_PREFIX defaults to empty but can be used to override
14 # compiler search behavior
15 TMPFILE=""
16 XGCCPATH=$1
18 # payloads under payloads/external crossgcc path
19 if [ -d "$(pwd)/../../../../util/crossgcc/xgcc/bin/" ]
20 then
21 XGCCPATH=${XGCCPATH:-"$(pwd)/../../../../util/crossgcc/xgcc/bin/"}
24 # libpayload crossgcc path
25 if [ -d "$(pwd)/../../util/crossgcc/xgcc/bin/" ]
26 then
27 XGCCPATH=${XGCCPATH:-"$(pwd)/../../util/crossgcc/xgcc/bin/"}
30 # coreboot crossgcc path
31 if [ -d "$(pwd)/util/crossgcc/xgcc/bin/" ]
32 then
33 XGCCPATH=${XGCCPATH:-"$(pwd)/util/crossgcc/xgcc/bin/"}
36 die() {
37 echo "ERROR: $*" >&2
38 exit 1
41 clean_up() {
42 if [ -n "$TMPFILE" ]; then
43 rm -f "$TMPFILE" "$TMPFILE.c" "$TMPFILE.o"
47 trap clean_up EXIT
50 program_exists() {
51 type "$1" >/dev/null 2>&1
55 if [ "$("${XGCCPATH}/iasl" 2>/dev/null | grep -c ACPI)" -gt 0 ]; then
56 IASL=${XGCCPATH}/iasl
57 elif [ "$(iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then
58 IASL=iasl
61 if program_exists "${XGCCPATH}/nasm" ; then
62 NASM="${XGCCPATH}/nasm"
63 elif program_exists nasm; then
64 NASM=nasm
67 if program_exists "${XGCCPATH}/gcc"; then
68 HOSTCC="${XGCCPATH}/gcc"
69 elif program_exists gcc; then
70 HOSTCC=gcc
71 elif program_exists cc; then
72 HOSTCC=cc
73 else
74 die "no host compiler found"
77 # Look for a C++ compiler (for kconfig's qconf), but don't fail if there is
78 # none, just set the compiler to false(1) which will break early enough if
79 # used while being less confusing than errors about "g not found" when
80 # "$HOSTCXX -g" evaluates to "-g" and make drops the leading dash.
81 if program_exists "${XGCCPATH}/g++"; then
82 HOSTCXX="${XGCCPATH}/g++"
83 elif program_exists g++; then
84 HOSTCXX=g++
85 elif program_exists c++; then
86 HOSTCXX=c++
87 else
88 HOSTCXX=false
91 # try to find the core count using various methods
92 CORES="$(getconf _NPROCESSORS_ONLN 2>/dev/null)"
93 if [ -z "$CORES" ]; then
94 NPROC=$(command -v nproc)
95 if [ -n "$NPROC" ]; then
96 CORES="$($NPROC)"
99 if [ -z "$CORES" ]; then
100 SYSCTL=$(command -v sysctl)
101 if [ -n "$SYSCTL" ]; then
102 CORES="$(${SYSCTL} -n hw.ncpu 2>/dev/null)"
105 if [ -z "$CORES" ] && [ -f /proc/cpuinfo ]; then
106 CORES="$(grep 'processor' /proc/cpuinfo 2>/dev/null | wc -l)"
109 cat <<EOF
110 # platform agnostic and host tools
111 XGCCPATH:=${XGCCPATH}
112 NASM:=${NASM}
113 IASL:=${IASL}
114 HOSTCC?=${HOSTCC}
115 HOSTCXX?=${HOSTCXX}
116 CPUS?=${CORES}
120 testcc() {
121 local cc="$1"
122 local cflags="$2"
123 local tmp_c="$TMPFILE.c"
124 local tmp_o="$TMPFILE.o"
125 rm -f "$tmp_c" "$tmp_o"
126 echo "void _start(void) {}" >"$tmp_c"
127 "$cc" -nostdlib -Werror $cflags -c "$tmp_c" -o "$tmp_o" >/dev/null 2>&1
130 testld() {
131 local gcc="$1"
132 local cflags="$2"
133 local ld="$3"
134 local ldflags="$4"
135 local tmp_o="$TMPFILE.o"
136 local tmp_elf="$TMPFILE.elf"
137 rm -f "$tmp_elf"
138 testcc "$gcc" "$cflags" &&
139 $ld -nostdlib -static $ldflags -o "$tmp_elf" "$tmp_o" >/dev/null 2>&1
142 testas() {
143 local gccprefix="$1"
144 local twidth="$2"
145 local arch="$3"
146 local use_dash_twidth="$4"
147 local endian="$5"
148 local obj_file="$TMPFILE.o"
149 local full_arch="elf$twidth-$arch"
151 rm -f "$obj_file"
152 [ -n "$use_dash_twidth" ] && use_dash_twidth="--$twidth"
153 [ -n "$endian" ] && endian="-$endian"
154 "${gccprefix}as" $use_dash_twidth $endian -o "$obj_file" "$TMPFILE" \
155 2>/dev/null || return 1
157 # Check output content type.
158 local obj_type="$(LANG=C LC_ALL='' "${gccprefix}"objdump -p "$obj_file" 2>/dev/null)"
159 local obj_arch="$(expr "$obj_type" : '.*format \(.[a-z0-9-]*\)')"
160 [ "$obj_arch" = "$full_arch" ] || return 1
162 unset ASFLAGS LDFLAGS
163 unset FLAGS_GCC CFLAGS_GCC CFLAGS_CLANG
165 if [ -n "$use_dash_twidth" ]; then
166 ASFLAGS="--$twidth"
167 FLAGS_GCC="-m$twidth"
168 CFLAGS_CLANG="-m$twidth"
169 LDFLAGS="-b $full_arch"
173 # Special parameters only available in dash_twidth mode.
174 [ -n "$use_dash_twidth" ] && case "$full_arch" in
175 "elf32-i386" )
176 LDFLAGS="$LDFLAGS -melf_i386"
177 FLAGS_GCC="$FLAGS_GCC -Wl,-b,elf32-i386 -Wl,-melf_i386"
178 CFLAGS_CLANG="$CFLAGS_CLANG -Wl,-b,elf32-i386 -Wl,-melf_i386"
180 esac
182 return 0
185 detect_special_flags() {
186 local architecture="$1"
187 # Check for an operational -m32/-m64
188 testcc "$GCC" "$FLAGS_GCC -m$TWIDTH " &&
189 FLAGS_GCC="$FLAGS_GCC -m$TWIDTH "
191 # Use bfd linker instead of gold if available:
192 testcc "$GCC" "$FLAGS_GCC -fuse-ld=bfd" &&
193 FLAGS_GCC="$FLAGS_GCC -fuse-ld=bfd" && LINKER_SUFFIX='.bfd'
195 testcc "$GCC" "$FLAGS_GCC -fno-stack-protector" &&
196 FLAGS_GCC="$FLAGS_GCC -fno-stack-protector"
197 testcc "$GCC" "$FLAGS_GCC -Wl,--build-id=none" &&
198 FLAGS_GCC="$FLAGS_GCC -Wl,--build-id=none"
200 testcc "$GCC" "$CFLAGS_GCC -Wno-address-of-packed-member $FLAGS_GCC" &&
201 CFLAGS_GCC="$CFLAGS_GCC -Wno-address-of-packed-member"
202 testcc "$GCC" "$CFLAGS_GCC --param=min-pagesize=1024 $FLAGS_GCC" &&
203 CFLAGS_GCC="$CFLAGS_GCC --param=min-pagesize=1024"
205 testcc "$GCC" "$CFLAGS_GCC -Wflex-array-member-not-at-end" &&
206 CFLAGS_GCC="$CFLAGS_GCC -Wflex-array-member-not-at-end"
208 testcc "$GCC" "$CFLAGS_GCC -Wcalloc-transposed-args" &&
209 CFLAGS_GCC="$CFLAGS_GCC -Wcalloc-transposed-args"
211 testcc "$GCC" "$CFLAGS_GCC -Wno-unused-parameter" &&
212 CFLAGS_GCC="$CFLAGS_GCC -Wno-unused-parameter"
214 testcc "$GCC" "$CFLAGS_GCC -Wno-sign-compare" &&
215 CFLAGS_GCC="$CFLAGS_GCC -Wno-sign-compare"
217 testcc "$GCC" "$CFLAGS_GCC -Wno-empty-body" &&
218 CFLAGS_GCC="$CFLAGS_GCC -Wno-empty-body"
220 testcc "$GCC" "$CFLAGS_GCC -Wno-missing-field-initializers" &&
221 CFLAGS_GCC="$CFLAGS_GCC -Wno-missing-field-initializers"
223 testcc "$GCC" "$CFLAGS_GCC -Wno-override-init" &&
224 CFLAGS_GCC="$CFLAGS_GCC -Wno-override-init"
226 testcc "$GCC" "$CFLAGS_GCC -Wno-ignored-qualifiers" &&
227 CFLAGS_GCC="$CFLAGS_GCC -Wno-ignored-qualifiers"
229 testcc "$GCC" "$CFLAGS_GCC -Wno-shift-negative-value" &&
230 CFLAGS_GCC="$CFLAGS_GCC -Wno-shift-negative-value"
232 testcc "$GCC" "$CFLAGS_GCC -Wno-unused-but-set-parameter" &&
233 CFLAGS_GCC="$CFLAGS_GCC -Wno-unused-but-set-parameter"
235 testcc "$GCC" "$CFLAGS_GCC -Wno-type-limits" &&
236 CFLAGS_GCC="$CFLAGS_GCC -Wno-type-limits"
238 testcc "$GCC" "$CFLAGS_GCC -Wno-cast-function-type" &&
239 CFLAGS_GCC="$CFLAGS_GCC -Wno-cast-function-type"
241 testcc "$GCC" "$CFLAGS_GCC -Wextra" &&
242 CFLAGS_GCC="$CFLAGS_GCC -Wextra"
244 # Disable warning on segments with RWX.
245 # All loadable sections are placed in the same segment for simplicity.
246 testld "$GCC" "$FLAGS_GCC" "${GCCPREFIX}ld${LINKER_SUFFIX}" \
247 "$LDFLAGS --no-warn-rwx-segments" && \
248 LDFLAGS="$LDFLAGS --no-warn-rwx-segments"
250 case "$architecture" in
251 x86)
253 x64)
255 arm64)
256 testld "$GCC" "$FLAGS_GCC" "${GCCPREFIX}ld${LINKER_SUFFIX}" \
257 "$LDFLAGS --fix-cortex-a53-843419" && \
258 LDFLAGS_ARM64_A53_ERRATUM_843419+=" --fix-cortex-a53-843419"
259 # https://bugs.llvm.org/show_bug.cgi?id=30792
260 # LLVM/clang runs into problems when encountering SIMD registers in assembly
261 # with -mgeneral-regs-only. -mno-implicit-float achieves the same though.
262 CFLAGS_GCC="$CFLAGS_GCC -mgeneral-regs-only" &&
263 CFLAGS_CLANG="$CFLAGS_CLANG -mno-implicit-float"
265 riscv)
266 testcc "$GCC" "$FLAGS_GCC -march=rv64iadc_zicsr_zifencei" &&
267 ARCH_SUFFIX="_zicsr_zifencei"
269 esac
272 detect_compiler_runtime() {
273 test -z "$GCC" || \
274 CC_RT_GCC="$(${GCC} ${CFLAGS_GCC} ${FLAGS_GCC} -print-libgcc-file-name)"
275 if [ ${CLANG_RUNTIME} = "libgcc" ]; then
276 CC_RT_CLANG=${CC_RT_GCC}
277 else
278 test -z "$CLANG" || \
279 CC_RT_CLANG="$(${CLANG} ${CFLAGS_CLANG} -print-libgcc-file-name 2>/dev/null)"
283 report_arch_toolchain() {
284 cat <<EOF
285 # elf${TWIDTH}-${TBFDARCH} toolchain (${GCC})
286 ARCH_SUPPORTED+=${TARCH}
287 SUBARCH_SUPPORTED+=${TSUPP-${TARCH}}
288 ARCH_SUFFIX_${TARCH}:=${ARCH_SUFFIX}
290 # GCC
291 GCC_CC_${TARCH}:=${GCC}
292 GCC_CFLAGS_${TARCH}:=${CFLAGS_GCC} ${FLAGS_GCC}
293 # Generally available for GCC's cc1:
294 GCC_CFLAGS_${TARCH}+=-fno-delete-null-pointer-checks -Wlogical-op
295 GCC_ADAFLAGS_${TARCH}:=${FLAGS_GCC}
296 GCC_COMPILER_RT_${TARCH}:=${CC_RT_GCC}
297 GCC_COMPILER_RT_FLAGS_${TARCH}:=${CC_RT_EXTRA_GCC}
299 if [ "${TARCH}" = "x86_64" ]; then
300 cat <<EOF
301 GCC_CFLAGS_${TARCH} += -malign-data=abi
304 cat <<EOF
306 # Clang
307 CLANG_CC_${TARCH} := ${CLANG}
308 CLANG_CFLAGS_${TARCH} := ${CFLAGS_CLANG}
309 CLANG_CFLAGS_${TARCH} += -Qunused-arguments
310 CLANG_CFLAGS_${TARCH} += -m${TWIDTH}
311 # tone down clang compiler warnings
312 CLANG_CFLAGS_${TARCH} += -Wno-unused-variable
313 CLANG_CFLAGS_${TARCH} += -Wno-unused-function
314 CLANG_CFLAGS_${TARCH} += -Wno-tautological-compare
315 CLANG_CFLAGS_${TARCH} += -Wno-shift-overflow
316 CLANG_CFLAGS_${TARCH} += -Wno-address-of-packed-member
317 CLANG_CFLAGS_${TARCH} += -Wno-initializer-overrides
318 CLANG_CFLAGS_${TARCH} += -fbracket-depth=2048
319 CLANG_CFLAGS_${TARCH} += -mllvm
320 CLANG_CFLAGS_${TARCH} += -asm-macro-max-nesting-depth=1000
321 CLANG_COMPILER_RT_${TARCH}:=${CC_RT_CLANG}
322 CLANG_COMPILER_RT_FLAGS_${TARCH}:=${CC_RT_EXTRA_CLANG}
323 # Leak the target arch into the preprocessor flags with clang.
324 # This is needed to preprocess linker scripts
325 CLANG_CPPFLAGS_${TARCH}:=${CPPFLAGS_CLANG}
327 # GCC/Clang Common
328 ifeq (\$(CONFIG_COMPILER_GCC)\$(CONFIG_LP_COMPILER_GCC),y)
329 CC_${TARCH}:=\$(GCC_CC_${TARCH})
330 CFLAGS_${TARCH}:=\$(GCC_CFLAGS_${TARCH})
331 COMPILER_RT_${TARCH}:=\$(GCC_COMPILER_RT_${TARCH})
332 COMPILER_RT_FLAGS_${TARCH}:=\$(GCC_COMPILER_RT_FLAGS_${TARCH})
333 else
334 CC_${TARCH}:=\$(CLANG_CC_${TARCH})
335 CFLAGS_${TARCH}:=\$(CLANG_CFLAGS_${TARCH})
336 CPPFLAGS_${TARCH}:=\$(CLANG_CPPFLAGS_${TARCH})
337 COMPILER_RT_${TARCH}:=\$(CLANG_COMPILER_RT_${TARCH})
338 COMPILER_RT_FLAGS_${TARCH}:=\$(CLANG_COMPILER_RT_FLAGS_${TARCH})
339 endif
342 # Generally the x86 should build for i686 -- no sse/mmx
343 # instructions since SMM modules are compiled using these
344 # flags. Note that this doesn't prevent a project using
345 # xcompile to explicitly specify -mmsse, etc flags.
346 # The Quark processor doesn't support the instructions
347 # introduced with the Pentium 6 architecture, so allow it
348 # to use i586 instead.
349 if [ "${TARCH}" = "x86_64" ]; then
350 cat <<EOF
351 CFLAGS_${TARCH} += -march=nocona
355 if [ "${TARCH}" = "x86_32" ]; then
356 cat <<EOF
358 CFLAGS_${TARCH} += -march=i686
362 cat <<EOF
364 CPP_${TARCH}:=${GCCPREFIX}cpp
365 AS_${TARCH}:=${GCCPREFIX}as ${ASFLAGS}
366 LD_${TARCH}:=${GCCPREFIX}ld${LINKER_SUFFIX} ${LDFLAGS}
367 GCOV_${TARCH}:=${GCCPREFIX}gcov
370 if [ "${TARCH}" = "arm64" ] && \
371 [ -n "${LDFLAGS_ARM64_A53_ERRATUM_843419}" ]; then
372 cat <<EOF
374 ifeq (\$(CONFIG_ARM64_A53_ERRATUM_843419),y)
375 LD_${TARCH}+=${LDFLAGS_ARM64_A53_ERRATUM_843419}
376 endif
379 fi # if [ "${TARCH}" = "arm64" ]...
381 cat <<EOF
382 ifeq (\$(CONFIG_COMPILER_GCC)\$(CONFIG_LP_COMPILER_GCC),y)
383 NM_${TARCH}:=${GCCPREFIX}gcc-nm
384 AR_${TARCH}:=${GCCPREFIX}gcc-ar
385 else
386 NM_${TARCH}:=${GCCPREFIX}nm
387 AR_${TARCH}:=${GCCPREFIX}ar
388 endif
389 OBJCOPY_${TARCH}:=${GCCPREFIX}objcopy
390 OBJDUMP_${TARCH}:=${GCCPREFIX}objdump
391 READELF_${TARCH}:=${GCCPREFIX}readelf
392 STRIP_${TARCH}:=${GCCPREFIX}strip
393 GNATBIND_${TARCH}:=${GCCPREFIX}gnatbind
394 CROSS_COMPILE_${TARCH}:=${GCCPREFIX}
398 #The two blank lines above are intentional separators
401 # Architecture definitions
402 SUPPORTED_ARCHITECTURES="arm arm64 riscv x64 x86 ppc64"
404 # TARCH: local name for the architecture
405 # (used as CC_${TARCH} in the build system)
406 # TBFDARCHS: architecture name in binutils (eg elf32-${TBFDARCH})
407 # TCLIST: first part of the compiler triplet (eg i386 in i386-elf)
408 # TWIDTH: numerical argument for cpu mode: gcc -m${TWIDTH}
409 # TSUPP: supported subarchs (for -mcpu=...)
410 # TABI: typically elf, eabi or linux
412 arch_config_arm() {
413 TARCH="arm"
414 TBFDARCHS="littlearm"
415 TCLIST="armv7-a armv7a arm"
416 TWIDTH="32"
417 TSUPP="arm armv4 armv7 armv7_m armv7_r"
418 TABI="eabi"
421 arch_config_arm64() {
422 TARCH="arm64"
423 TBFDARCHS="littleaarch64"
424 TCLIST="aarch64"
425 TWIDTH="64"
426 TSUPP="arm64 armv8_64"
427 TABI="elf"
430 arch_config_riscv() {
431 TARCH="riscv"
432 TBFDARCHS="littleriscv"
433 TCLIST="riscv64 riscv"
434 TWIDTH="64"
435 TABI="elf"
438 arch_config_x64() {
439 TARCH="x86_64"
440 TBFDARCHS="x86-64"
441 TCLIST="x86_64"
442 TWIDTH="64"
443 TABI="elf"
446 arch_config_x86() {
447 TARCH="x86_32"
448 TBFDARCHS="i386"
449 TCLIST="i386 x86_64"
450 TWIDTH="32"
451 TABI="elf"
452 CC_RT_EXTRA_GCC="--wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3"
455 arch_config_ppc64() {
456 TARCH="ppc64"
457 TBFDARCHS="powerpc"
458 TCLIST="powerpc64"
459 TWIDTH="64"
460 TSUPP="ppc64"
461 TABI="linux-gnu" # there is no generic ABI on ppc64
464 # Right now, the clang reference toolchain is not building compiler-rt builtins
465 # for any of the cross compile architectures. Hence we use libgcc for now,
466 # because that is available and lets us proceed with getting coreboot clang
467 # ready. Toggle CLANG_RUNTIME if you want to experiment with compiler-rt.
469 CLANG_RUNTIME="libgcc"
470 # CLANG_RUNTIME="compiler-rt"
472 test_architecture() {
473 local architecture=$1
474 local endian gccprefix search
476 GCCPREFIX="invalid"
477 unset TABI TARCH TBFDARCH TCLIST TENDIAN TSUPP TWIDTH
478 unset CC_RT_EXTRA_GCC CC_RT_EXTRA_CLANG
479 unset GCC CLANG
480 unset ARCH_SUFFIX
481 if type "arch_config_$architecture" > /dev/null; then
482 "arch_config_$architecture"
483 else
484 die "no architecture definition for $architecture"
487 # To override toolchain, define CROSS_COMPILE_$arch or CROSS_COMPILE as
488 # environment variable.
489 # Ex: CROSS_COMPILE_arm="armv7a-cros-linux-gnueabi-"
490 # CROSS_COMPILE_x86="i686-pc-linux-gnu-"
491 search="$(eval echo "\$CROSS_COMPILE_$architecture" 2>/dev/null)"
492 search="$search $CROSS_COMPILE"
493 for toolchain in $TCLIST; do
494 search="$search $XGCCPATH$toolchain-$TABI-"
495 search="$search $toolchain-$TABI-"
496 search="$search $toolchain-linux-gnu-"
497 search="$search $toolchain-linux-"
498 search="$search $toolchain-"
499 search="$search $toolchain-linux-gnueabi-"
500 done
501 echo "###########################################################################"
502 echo "# $architecture"
503 echo "# TARCH_SEARCH=$search"
505 # Search toolchain by checking assembler capability.
506 for TBFDARCH in $TBFDARCHS; do
507 for gccprefix in $search "$GENERIC_COMPILER_PREFIX"; do
508 program_exists "${gccprefix}as" || continue
509 for endian in $TENDIAN ""; do
510 { testas "$gccprefix" "$TWIDTH" "$TBFDARCH" \
511 "" "$endian" ||
512 testas "$gccprefix" "$TWIDTH" "$TBFDARCH" \
513 "TRUE" "$endian" ; } && \
514 testcc "${gccprefix}gcc" "$CFLAGS_GCC" "$FLAGS_GCC" && \
515 GCCPREFIX="$gccprefix" && \
516 break 3
517 done
518 done
519 done
520 if [ "invalid" != "$GCCPREFIX" ]; then
521 GCC="${GCCPREFIX}gcc"
524 for clang_arch in $TCLIST invalid; do
525 for clang_prefix in $search $XGCCPATH "$GENERIC_COMPILER_PREFIX"; do
526 testcc "${clang_prefix}clang" "-target ${clang_arch}-none-unknown-${TABI} -c" && break 2
527 done
528 done
530 if [ "invalid" != "$clang_arch" ]; then
531 # FIXME: this may break in a clang && !gcc configuration,
532 # but that's more of a clang limitation. Let's be optimistic
533 # that this will change in the future.
534 CLANG="${clang_prefix}clang"
535 CLANG_TARGET="-target ${clang_arch}-none-unknown-${TABI}"
536 CFLAGS_CLANG="$CLANG_TARGET $CFLAGS_CLANG"
537 CPPFLAGS_CLANG="$CLANG_TARGET $CPPFLAGS_CLANG"
541 OUT="$(mktemp /tmp/temp.XXXXXX 2>/dev/null || echo /tmp/temp.coreboot.$RANDOM)"
542 rm -f $OUT
544 for architecture in $SUPPORTED_ARCHITECTURES; do
546 TMPFILE="$(mktemp /tmp/temp.XXXXXX 2>/dev/null || echo /tmp/temp.coreboot.$RANDOM)"
547 touch $TMPFILE
548 test_architecture "$architecture"
549 detect_special_flags "$architecture"
550 detect_compiler_runtime "$architecture"
551 report_arch_toolchain
552 clean_up
553 ) > $OUT.$architecture &
554 done
555 wait
557 for architecture in $SUPPORTED_ARCHITECTURES; do
558 cat $OUT.$architecture
559 rm -f $OUT.$architecture
560 done
561 echo XCOMPILE_COMPLETE:=1