/ util / xcompile / xcompile
xcompile
  1  #!/usr/bin/env bash
  2  #
  3  # SPDX-License-Identifier: GPL-2.0-only
  4  
  5  # Usage: [--debug] [path to xgcc/bin directory]
  6  
  7  # Enable debug output
  8  if [ "$1" = "--debug" ]; then
  9  	shift
 10  	set -x
 11  fi
 12  
 13  # GENERIC_COMPILER_PREFIX defaults to empty but can be used to override
 14  # compiler search behavior
 15  TMPFILE=""
 16  XGCCPATH=$1
 17  
 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/"}
 22  fi
 23  
 24  # libpayload crossgcc path
 25  if [ -d "$(pwd)/../../util/crossgcc/xgcc/bin/" ]
 26  then
 27  	XGCCPATH=${XGCCPATH:-"$(pwd)/../../util/crossgcc/xgcc/bin/"}
 28  fi
 29  
 30  # coreboot crossgcc path
 31  if [ -d "$(pwd)/util/crossgcc/xgcc/bin/" ]
 32  then
 33  	XGCCPATH=${XGCCPATH:-"$(pwd)/util/crossgcc/xgcc/bin/"}
 34  fi
 35  
 36  die() {
 37  	echo "ERROR: $*" >&2
 38  	exit 1
 39  }
 40  
 41  clean_up() {
 42  	if [ -n "$TMPFILE" ]; then
 43  		rm -f "$TMPFILE" "$TMPFILE.c" "$TMPFILE.o"
 44  	fi
 45  }
 46  
 47  trap clean_up EXIT
 48  
 49  
 50  program_exists() {
 51  	type "$1" >/dev/null 2>&1
 52  }
 53  
 54  
 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
 59  fi
 60  
 61  if program_exists "${XGCCPATH}/nasm" ; then
 62  	NASM="${XGCCPATH}/nasm"
 63  elif program_exists nasm; then
 64  	NASM=nasm
 65  fi
 66  
 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"
 75  fi
 76  
 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
 89  fi
 90  
 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)"
 97  	fi
 98  fi
 99  if [ -z "$CORES" ]; then
100  	SYSCTL=$(command -v sysctl)
101  	if [ -n "$SYSCTL" ]; then
102  		CORES="$(${SYSCTL} -n hw.ncpu 2>/dev/null)"
103  	fi
104  fi
105  if [ -z "$CORES" ] && [ -f /proc/cpuinfo ]; then
106  	 CORES="$(grep 'processor' /proc/cpuinfo 2>/dev/null | wc -l)"
107  fi
108  
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}
117  
118  EOF
119  
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
128  }
129  
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
140  }
141  
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"
150  
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
156  
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
161  
162  	unset ASFLAGS LDFLAGS
163  	unset FLAGS_GCC CFLAGS_GCC CFLAGS_CLANG
164  
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"
170  
171  	fi
172  
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"
179  			;;
180  	esac
181  
182  	return 0
183  }
184  
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 "
190  
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'
194  
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"
199  
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"
204  
205  	testcc "$GCC"      "$CFLAGS_GCC -Wflex-array-member-not-at-end" &&
206  		CFLAGS_GCC="$CFLAGS_GCC -Wflex-array-member-not-at-end"
207  
208  	testcc "$GCC"      "$CFLAGS_GCC -Wcalloc-transposed-args" &&
209  		CFLAGS_GCC="$CFLAGS_GCC -Wcalloc-transposed-args"
210  
211  	testcc "$GCC"      "$CFLAGS_GCC -Wno-unused-parameter" &&
212  		CFLAGS_GCC="$CFLAGS_GCC -Wno-unused-parameter"
213  
214  	testcc "$GCC"      "$CFLAGS_GCC -Wno-sign-compare" &&
215  		CFLAGS_GCC="$CFLAGS_GCC -Wno-sign-compare"
216  
217  	testcc "$GCC"      "$CFLAGS_GCC -Wno-empty-body" &&
218  		CFLAGS_GCC="$CFLAGS_GCC -Wno-empty-body"
219  
220  	testcc "$GCC"      "$CFLAGS_GCC -Wno-missing-field-initializers" &&
221  		CFLAGS_GCC="$CFLAGS_GCC -Wno-missing-field-initializers"
222  
223  	testcc "$GCC"      "$CFLAGS_GCC -Wno-override-init" &&
224  		CFLAGS_GCC="$CFLAGS_GCC -Wno-override-init"
225  
226  	testcc "$GCC"      "$CFLAGS_GCC -Wno-ignored-qualifiers" &&
227  		CFLAGS_GCC="$CFLAGS_GCC -Wno-ignored-qualifiers"
228  
229  	testcc "$GCC"      "$CFLAGS_GCC -Wno-shift-negative-value" &&
230  		CFLAGS_GCC="$CFLAGS_GCC -Wno-shift-negative-value"
231  
232  	testcc "$GCC"      "$CFLAGS_GCC -Wno-unused-but-set-parameter" &&
233  		CFLAGS_GCC="$CFLAGS_GCC -Wno-unused-but-set-parameter"
234  
235  	testcc "$GCC"      "$CFLAGS_GCC -Wno-type-limits" &&
236  		CFLAGS_GCC="$CFLAGS_GCC -Wno-type-limits"
237  
238  	testcc "$GCC"      "$CFLAGS_GCC -Wno-cast-function-type" &&
239  		CFLAGS_GCC="$CFLAGS_GCC -Wno-cast-function-type"
240  
241  	testcc "$GCC"      "$CFLAGS_GCC -Wextra" &&
242  		CFLAGS_GCC="$CFLAGS_GCC -Wextra"
243  
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"
249  
250  	case "$architecture" in
251  	x86)
252  		;;
253  	x64)
254  		;;
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"
264  		;;
265  	riscv)
266  		testcc "$GCC" "$FLAGS_GCC -march=rv64iadc_zicsr_zifencei" &&
267  		  ARCH_SUFFIX="_zicsr_zifencei"
268  		;;
269  	esac
270  }
271  
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)"
280  	fi
281  }
282  
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}
289  
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}
298  EOF
299  if [ "${TARCH}" = "x86_64" ]; then
300  cat <<EOF
301  	GCC_CFLAGS_${TARCH} += -malign-data=abi
302  EOF
303  fi
304  cat <<EOF
305  
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}
326  
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
340  EOF
341  
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
352  EOF
353  fi
354  
355  if [ "${TARCH}" = "x86_32" ]; then
356  cat <<EOF
357  
358  CFLAGS_${TARCH} += -march=i686
359  EOF
360  fi
361  
362  cat <<EOF
363  
364  CPP_${TARCH}:=${GCCPREFIX}cpp
365  AS_${TARCH}:=${GCCPREFIX}as ${ASFLAGS}
366  LD_${TARCH}:=${GCCPREFIX}ld${LINKER_SUFFIX} ${LDFLAGS}
367  GCOV_${TARCH}:=${GCCPREFIX}gcov
368  EOF
369  
370  	if [ "${TARCH}" = "arm64" ] && \
371  			[ -n "${LDFLAGS_ARM64_A53_ERRATUM_843419}" ]; then
372  		cat <<EOF
373  
374  ifeq (\$(CONFIG_ARM64_A53_ERRATUM_843419),y)
375  	LD_${TARCH}+=${LDFLAGS_ARM64_A53_ERRATUM_843419}
376  endif
377  
378  EOF
379  	fi # if [ "${TARCH}" = "arm64" ]...
380  
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}
395  
396  
397  EOF
398  #The two blank lines above are intentional separators
399  }
400  
401  # Architecture definitions
402  SUPPORTED_ARCHITECTURES="arm arm64 riscv x64 x86 ppc64"
403  
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
411  
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"
419  }
420  
421  arch_config_arm64() {
422  	TARCH="arm64"
423  	TBFDARCHS="littleaarch64"
424  	TCLIST="aarch64"
425  	TWIDTH="64"
426  	TSUPP="arm64 armv8_64"
427  	TABI="elf"
428  }
429  
430  arch_config_riscv() {
431  	TARCH="riscv"
432  	TBFDARCHS="littleriscv"
433  	TCLIST="riscv64 riscv"
434  	TWIDTH="64"
435  	TABI="elf"
436  }
437  
438  arch_config_x64() {
439  	TARCH="x86_64"
440  	TBFDARCHS="x86-64"
441  	TCLIST="x86_64"
442  	TWIDTH="64"
443  	TABI="elf"
444  }
445  
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"
453  }
454  
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
462  }
463  
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.
468  
469  CLANG_RUNTIME="libgcc"
470  # CLANG_RUNTIME="compiler-rt"
471  
472  test_architecture() {
473  	local architecture=$1
474  	local endian gccprefix search
475  
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"
485  	fi
486  
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"
504  
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"
522  	fi
523  
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
529  
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"
538  	fi
539  }
540  
541  OUT="$(mktemp /tmp/temp.XXXXXX 2>/dev/null || echo /tmp/temp.coreboot.$RANDOM)"
542  rm -f $OUT
543  
544  for architecture in $SUPPORTED_ARCHITECTURES; do
545  	(
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
556  
557  for architecture in $SUPPORTED_ARCHITECTURES; do
558  	cat $OUT.$architecture
559  	rm -f $OUT.$architecture
560  done
561  echo XCOMPILE_COMPLETE:=1