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