#!/usr/bin/env bash # # This file is part of the coreboot project. # # Copyright (C) 2007-2010 coresystems GmbH # Copyright (C) 2012 Google Inc # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # TMPFILE="" XGCCPATH=$1 # libpayload crossgcc path if [ -d "$(pwd)/../../util/crossgcc/xgcc/bin/" ] then XGCCPATH=${XGCCPATH:-"$(pwd)/../../util/crossgcc/xgcc/bin/"} fi # coreboot crossgcc path if [ -d "$(pwd)/util/crossgcc/xgcc/bin/" ] then XGCCPATH=${XGCCPATH:-"$(pwd)/util/crossgcc/xgcc/bin/"} fi die() { echo "ERROR: $*" >&2 exit 1 } clean_up() { if [ -n "$TMPFILE" ]; then rm -f "$TMPFILE" "$TMPFILE.c" "$TMPFILE.o" fi } # Create temporary file(s). TMPFILE="$(mktemp /tmp/temp.XXXX 2>/dev/null || echo /tmp/temp.78gOIUGz)" touch "$TMPFILE" trap clean_up EXIT program_exists() { type "$1" >/dev/null 2>&1 } if [ "$("${XGCCPATH}/iasl" 2>/dev/null | grep -c ACPI)" -gt 0 ]; then IASL=${XGCCPATH}iasl elif [ "$(iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then IASL=iasl fi if program_exists gcc; then HOSTCC=gcc elif program_exists cc; then HOSTCC=cc else die "no host compiler found" fi # try to find the core count using various methods CORES="$(getconf _NPROCESSORS_ONLN 2>/dev/null)" if [ -z "$CORES" ]; then NPROC=$(command -v nproc) if [ -n "$NPROC" ]; then CORES="$($NPROC)" fi fi if [ -z "$CORES" ]; then SYSCTL=$(command -v sysctl) if [ -n "$SYSCTL" ]; then CORES="$(${SYSCTL} -n hw.ncpu 2>/dev/null)" fi fi if [ -z "$CORES" ] && [ -f /proc/cpuinfo ]; then CORES="$(grep 'processor' /proc/cpuinfo 2>/dev/null | wc -l)" fi cat <"$tmp_c" "$cc" -nostdlib -Werror $cflags -c "$tmp_c" -o "$tmp_o" >/dev/null 2>&1 } testld() { local gcc="$1" local cflags="$2" local ld="$3" local ldflags="$4" local tmp_o="$TMPFILE.o" local tmp_elf="$TMPFILE.elf" rm -f "$tmp_elf" testcc "$gcc" "$cflags" && $ld -nostdlib -static $ldflags -o "$tmp_elf" "$tmp_o" >/dev/null 2>&1 } testas() { local gccprefix="$1" local twidth="$2" local arch="$3" local use_dash_twidth="$4" local endian="$5" local obj_file="$TMPFILE.o" local full_arch="elf$twidth-$arch" rm -f "$obj_file" [ -n "$use_dash_twidth" ] && use_dash_twidth="--$twidth" [ -n "$endian" ] && endian="-$endian" "${gccprefix}as" $use_dash_twidth $endian -o "$obj_file" "$TMPFILE" \ 2>/dev/null || return 1 # Check output content type. local obj_type="$(LANG=C LC_ALL='' "${gccprefix}"objdump -p "$obj_file" 2>/dev/null)" local obj_arch="$(expr "$obj_type" : '.*format \(.[a-z0-9-]*\)')" [ "$obj_arch" = "$full_arch" ] || return 1 # Architecture matched. GCCPREFIX="$gccprefix" unset ASFLAGS LDFLAGS unset CFLAGS_GCC CFLAGS_CLANG if [ -n "$use_dash_twidth" ]; then ASFLAGS="--$twidth" CFLAGS_GCC="-m$twidth" CFLAGS_CLANG="-m$twidth" LDFLAGS="-b $full_arch" fi # Special parameters only available in dash_twidth mode. [ -n "$use_dash_twidth" ] && case "$full_arch" in "elf32-i386" ) LDFLAGS="$LDFLAGS -melf_i386" CFLAGS_GCC="$CFLAGS_GCC -Wl,-b,elf32-i386 -Wl,-melf_i386" CFLAGS_CLANG="$CFLAGS_GCC -Wl,-b,elf32-i386 -Wl,-melf_i386" ;; esac return 0 } detect_special_flags() { local architecture="$1" # GCC 4.6 is much more picky about unused variables. # Turn off it's warnings for now: testcc "$GCC" "$CFLAGS_GCC -Wno-unused-but-set-variable " && CFLAGS_GCC="$CFLAGS_GCC -Wno-unused-but-set-variable " # Check for an operational -m32/-m64 testcc "$GCC" "$CFLAGS_GCC -m$TWIDTH " && CFLAGS_GCC="$CFLAGS_GCC -m$TWIDTH " # Use bfd linker instead of gold if available: testcc "$GCC" "$CFLAGS_GCC -fuse-ld=bfd" && CFLAGS_GCC="$CFLAGS_GCC -fuse-ld=bfd" && LINKER_SUFFIX='.bfd' testcc "$GCC" "$CFLAGS_GCC -fno-stack-protector"&& CFLAGS_GCC="$CFLAGS_GCC -fno-stack-protector" testcc "$GCC" "$CFLAGS_GCC -Wl,--build-id=none" && CFLAGS_GCC="$CFLAGS_GCC -Wl,--build-id=none" case "$architecture" in x86) # Always build for i686 -- no sse/mmx instructions since SMM # modules are compiled using these flags. Note that this # doesn't prevent a project using xcompile to explicitly # specify -mmsse, etc flags. CFLAGS_GCC="$CFLAGS_GCC -march=i686" ;; x64) ;; arm64) testld "$GCC" "$CFLAGS_GCC" "${GCCPREFIX}ld${LINKER_SUFFIX}" \ "$LDFLAGS --fix-cortex-a53-843419" && \ LDFLAGS_ARM64_A53_ERRATUM_843419+=" --fix-cortex-a53-843419" ;; mipsel) testcc "$GCC" "$CFLAGS_GCC -mno-abicalls -fno-pic" && \ CFLAGS_GCC+=" -mno-abicalls -fno-pic" # Enforce little endian mode. testcc "$GCC" "$CFLAGS_GCC -EL" && \ CFLAGS_GCC+=" -EL" ;; esac } detect_compiler_runtime() { test -z "$CLANG" || \ CC_RT_CLANG="$(${CLANG} ${CFLAGS_CLANG} -print-librt-file-name 2>/dev/null)" test -z "$GCC" || \ CC_RT_GCC="$(${GCC} ${CFLAGS_GCC} -print-libgcc-file-name)" } report_arch_toolchain() { cat < /dev/null; then "arch_config_$architecture" else die "no architecture definition for $architecture" fi # To override toolchain, define CROSS_COMPILE_$arch or CROSS_COMPILE as # environment variable. # Ex: CROSS_COMPILE_arm="armv7a-cros-linux-gnueabi-" # CROSS_COMPILE_x86="i686-pc-linux-gnu-" search="$(eval echo "\$CROSS_COMPILE_$architecture" 2>/dev/null)" search="$search $CROSS_COMPILE" for toolchain in $TCLIST; do search="$search $XGCCPATH$toolchain-$TABI-" search="$search $toolchain-$TABI-" search="$search $toolchain-linux-gnu-" search="$search $toolchain-" done echo "###########################################################################" echo "# $architecture" echo "# TARCH_SEARCH=$search" # Search toolchain by checking assembler capability. for TBFDARCH in $TBFDARCHS; do for gccprefix in $search ""; do program_exists "${gccprefix}as" || continue for endian in $TENDIAN ""; do testas "$gccprefix" "$TWIDTH" "$TBFDARCH" \ "" "$endian" && break 3 testas "$gccprefix" "$TWIDTH" "$TBFDARCH" \ "TRUE" "$endian" && break 3 done done done if [ "invalid" != "$GCCPREFIX" ]; then GCC="${GCCPREFIX}gcc" fi for clang_arch in $TCLIST invalid; do testcc "${XGCCPATH}clang" "-target ${clang_arch}-$TABI -c" && break done if [ "invalid" != "$clang_arch" ]; then # FIXME: this may break in a clang && !gcc configuration, # but that's more of a clang limitation. Let's be optimistic # that this will change in the future. CLANG="${XGCCPATH}clang" CFLAGS_CLANG="-target ${clang_arch}-${TABI} $CFLAGS_CLANG -ccc-gcc-name ${GCC}" fi } # This loops over all supported architectures. for architecture in $SUPPORTED_ARCHITECTURES; do test_architecture "$architecture" detect_special_flags "$architecture" detect_compiler_runtime "$architecture" report_arch_toolchain done echo XCOMPILE_COMPLETE:=1