| #!/bin/sh |
| # |
| # 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. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write to the Free Software |
| # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| # |
| |
| TMPFILE="" |
| |
| die() { |
| echo "ERROR: $*" >&2 |
| exit 1 |
| } |
| |
| clean_up() { |
| if [ -n "$TMPFILE" ]; then |
| rm -f "$TMPFILE" "$TMPFILE.c" "$TMPFILE.o" |
| fi |
| } |
| |
| program_exists() { |
| type "$1" >/dev/null 2>&1 |
| } |
| |
| testcc() { |
| local tmp_c="$TMPFILE.c" |
| local tmp_o="$TMPFILE.o" |
| rm -f "$tmp_c" "$tmp_o" |
| echo "void _start(void) {}" >"$tmp_c" |
| "$1" -nostdlib -Werror $2 "$tmp_c" -o "$tmp_o" >/dev/null 2>&1 |
| } |
| |
| testas() { |
| local gccprefixes="$1" |
| local twidth="$2" |
| local arch="$3" |
| local use_dash_twidth="$4" |
| local obj_file="$TMPFILE.o" |
| local full_arch="elf$twidth-$arch" |
| |
| rm -f "$obj_file" |
| [ -n "$use_dash_twidth" ] && use_dash_twidth="--$twidth" |
| ${gccprefixes}as $use_dash_twidth -o "$obj_file" $TMPFILE 2>/dev/null || |
| return 1 |
| |
| # Check output content type. |
| local obj_type="$(${gccprefixes}objdump -p $obj_file)" |
| local obj_arch="$(expr "$obj_type" : '.*format \(.[a-z0-9-]*\)')" |
| [ "$obj_arch" = "$full_arch" ] || return 1 |
| |
| # Architecture matched. |
| GCCPREFIX="$gccprefixes" |
| |
| if [ -z "$use_dash_twidth" ]; then |
| ASFLAGS="" |
| CFLAGS="" |
| LDFLAGS="" |
| else |
| ASFLAGS="--$twidth" |
| CFLAGS="-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="$CFLAGS -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 "$CC" "$CFLAGS -Wno-unused-but-set-variable " && |
| CFLAGS="$CFLAGS -Wno-unused-but-set-variable " |
| |
| # Use bfd linker instead of gold if available: |
| testcc "$CC" "$CFLAGS -fuse-ld=bfd" && |
| CFLAGS="$CFLAGS -fuse-ld=bfd" && LINKER_SUFFIX='.bfd' |
| |
| testcc "$CC" "$CFLAGS -Wa,--divide" && |
| CFLAGS="$CFLAGS -Wa,--divide" |
| testcc "$CC" "$CFLAGS -fno-stack-protector"&& |
| CFLAGS="$CFLAGS -fno-stack-protector" |
| testcc "$CC" "$CFLAGS -Wl,--build-id=none" && |
| CFLAGS="$CFLAGS -Wl,--build-id=none" |
| |
| case "$architecture" in |
| armv7 ) |
| ARMFLAGS="" |
| testcc "$CC" "$CFLAGS $ARMFLAGS"&&CFLAGS="$CFLAGS $ARMFLAGS" |
| ;; |
| aarch64 ) |
| ARMFLAGS="" |
| testcc "$CC" "$CFLAGS $ARMFLAGS"&&CFLAGS="$CFLAGS $ARMFLAGS" |
| ;; |
| esac |
| } |
| |
| report_arch_toolchain() { |
| cat <<EOF |
| # elf${TWIDTH}-${TBFDARCH} toolchain (${GCCPREFIX}gcc) |
| CC_${TARCH}:=${GCCPREFIX}gcc ${CFLAGS} |
| CPP_${TARCH}:=${GCCPREFIX}cpp |
| AS_${TARCH}:=${GCCPREFIX}as ${ASFLAGS} |
| LD_${TARCH}:=${GCCPREFIX}ld${LINKER_SUFFIX} ${LDFLAGS} |
| NM_${TARCH}:=${GCCPREFIX}nm |
| OBJCOPY_${TARCH}:=${GCCPREFIX}objcopy |
| OBJDUMP_${TARCH}:=${GCCPREFIX}objdump |
| READELF_${TARCH}:=${GCCPREFIX}readelf |
| STRIP_${TARCH}:=${GCCPREFIX}strip |
| AR_${TARCH}:=${GCCPREFIX}ar |
| |
| EOF |
| } |
| |
| # Create temporary file(s). |
| TMPFILE="$(mktemp /tmp/temp.XXXX 2>/dev/null || echo /tmp/temp.78gOIUGz)" |
| touch "$TMPFILE" |
| trap clean_up EXIT |
| |
| # Architecture definition |
| SUPPORTED_ARCHITECTURE="x86 armv7 aarch64" |
| |
| # ARM Architecture |
| TARCH_armv7="armv7" |
| TBFDARCH_armv7="littlearm" |
| TCLIST_armv7="armv7a armv7-a" |
| TWIDTH_armv7="32" |
| |
| # AARCH64 -- armv8 |
| TARCH_aarch64="aarch64" |
| TBFDARCH_aarch64="littleaarch64" |
| TCLIST_aarch64="aarch64" |
| TWIDTH_aarch64="64" |
| |
| # X86 Architecture |
| TARCH_x86="i386" |
| TBFDARCH_x86="i386" |
| TCLIST_x86="i386 x86_64" |
| TWIDTH_x86="32" |
| XGCCPATH=${1:-"`pwd`/util/crossgcc/xgcc/bin/"} |
| |
| # This loops over all supported architectures. |
| for architecture in $SUPPORTED_ARCHITECTURE; do |
| GCCPREFIX="invalid" |
| TARCH="$(eval echo \$TARCH_$architecture)" |
| TBFDARCH="$(eval echo \$TBFDARCH_$architecture)" |
| TCLIST="$(eval echo \$TCLIST_$architecture)" |
| TWIDTH="$(eval echo \$TWIDTH_$architecture)" |
| [ -z "$TARCH" -o -z "$TCLIST" -o -z "$TWIDTH" ] && |
| die "Missing architecture definition for $architecture." |
| |
| # 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-elf-" |
| search="$search $toolchain-elf-" |
| search="$search $toolchain-linux-gnu-" |
| search="$search $XGCCPATH$toolchain-eabi-" |
| search="$search $toolchain-eabi-" |
| done |
| echo "# $architecture TARCH_SEARCH=$search" |
| |
| # Search toolchain by checking assembler capability. |
| for gccprefixes in $search ""; do |
| program_exists "${gccprefixes}as" || continue |
| testas "$gccprefixes" "$TWIDTH" "$TBFDARCH" "" && break |
| testas "$gccprefixes" "$TWIDTH" "$TBFDARCH" "TRUE" && break |
| done |
| |
| if [ "$GCCPREFIX" = "invalid" ]; then |
| echo "Warning: no suitable GCC for $architecture." >&2 |
| continue |
| fi |
| CC="${GCCPREFIX}"gcc |
| |
| detect_special_flags "$architecture" |
| report_arch_toolchain |
| done |
| |
| if [ "$(${XGCCPATH}/iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then |
| IASL=${XGCCPATH}iasl |
| else |
| IASL=iasl |
| fi |
| |
| if program_exists gcc; then |
| HOSTCC=gcc |
| else |
| HOSTCC=cc |
| fi |
| |
| cat <<EOF |
| IASL:=${IASL} |
| |
| # native toolchain |
| HOSTCC:=${HOSTCC} |
| EOF |