Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env bash
- #
- # This file is part of the coreboot project.
- #
- # Copyright (C) 2007-2010 coresystems GmbH
- # Copyright (C) 2012 Google Inc
- # Copyright (C) 2016 Raptor Engineering, LLC
- #
- # 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.
- #
- # Usage: [--debug] [path to xgcc/bin directory]
- # Enable debug output
- if [ "$1" = "--debug" ]; then
- shift
- set -x
- fi
- TMPFILE=""
- XGCCPATH=$1
- # payloads under payloads/external crossgcc path
- if [ -d "$(pwd)/../../../../util/crossgcc/xgcc/bin/" ]
- then
- XGCCPATH=${XGCCPATH:-"$(pwd)/../../../../util/crossgcc/xgcc/bin/"}
- fi
- # 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.XXXXXX 2>/dev/null || echo /tmp/temp.coreboot.$RANDOM)"
- 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 <<EOF
- # platform agnostic and host tools
- IASL:=${IASL}
- HOSTCC?=${HOSTCC}
- CPUS?=${CORES}
- EOF
- testcc() {
- local cc="$1"
- local cflags="$2"
- local tmp_c="$TMPFILE.c"
- local tmp_o="$TMPFILE.o"
- rm -f "$tmp_c" "$tmp_o"
- echo "void _start(void) {}" >"$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
- 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"
- # 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)
- ;;
- 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 <<EOF
- # elf${TWIDTH}-${TBFDARCH} toolchain (${GCC})
- ARCH_SUPPORTED+=${TARCH}
- SUBARCH_SUPPORTED+=${TSUPP-${TARCH}}
- # GCC
- GCC_CC_${TARCH}:=${GCC}
- GCC_CFLAGS_${TARCH}:=${CFLAGS_GCC}
- GCC_COMPILER_RT_${TARCH}:=${CC_RT_GCC}
- GCC_COMPILER_RT_FLAGS_${TARCH}:=${CC_RT_EXTRA_GCC}
- EOF
- # Generally the x86 should 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.
- # The Quark processor doesn't support the instructions
- # introduced with the Pentium 6 architecture, so allow it
- # to use i586 instead.
- if [ "${TARCH}" = "x86_64" ] || [ "${TARCH}" = "x86_32" ]; then
- cat <<EOF
- ifeq (\$(CONFIG_USE_MARCH_586),y)
- GCC_CFLAGS_${TARCH} += -march=i586
- else
- GCC_CFLAGS_${TARCH} += -march=i686
- endif
- EOF
- fi
- cat <<EOF
- # Clang
- CLANG_CC_${TARCH}:=${CLANG}
- CLANG_CFLAGS_${TARCH}:=${CFLAGS_CLANG}
- CLANG_CFLAGS_${TARCH}+=-no-integrated-as -Qunused-arguments -m${TWIDTH}
- # tone down clang compiler warnings
- CLANG_CFLAGS_${TARCH}+=-Wno-unused-variable -Wno-unused-function -Wno-tautological-compare -Wno-shift-overflow
- CLANG_COMPILER_RT_${TARCH}:=${CC_RT_CLANG}
- CLANG_COMPILER_RT_FLAGS_${TARCH}:=${CC_RT_EXTRA_CLANG}
- ifeq (\$(CONFIG_COMPILER_GCC)\$(CONFIG_LP_COMPILER_GCC),y)
- CC_${TARCH}:=\$(GCC_CC_${TARCH})
- CFLAGS_${TARCH}:=\$(GCC_CFLAGS_${TARCH})
- COMPILER_RT_${TARCH}:=\$(GCC_COMPILER_RT_${TARCH})
- COMPILER_RT_FLAGS_${TARCH}:=\$(GCC_COMPILER_RT_FLAGS_${TARCH})
- else
- CC_${TARCH}:=\$(CLANG_CC_${TARCH})
- CFLAGS_${TARCH}:=\$(CLANG_CFLAGS_${TARCH})
- COMPILER_RT_${TARCH}:=\$(CLANG_COMPILER_RT_${TARCH})
- COMPILER_RT_FLAGS_${TARCH}:=\$(CLANG_COMPILER_RT_FLAGS_${TARCH})
- endif
- CPP_${TARCH}:=${GCCPREFIX}cpp
- AS_${TARCH}:=${GCCPREFIX}as ${ASFLAGS}
- LD_${TARCH}:=${GCCPREFIX}ld${LINKER_SUFFIX} ${LDFLAGS}
- EOF
- if [ "${TARCH}" = "arm64" ] && \
- [ -n "${LDFLAGS_ARM64_A53_ERRATUM_843419}" ]; then
- cat <<EOF
- ifeq (\$(CONFIG_ARM64_A53_ERRATUM_843419),y)
- LD_${TARCH}+=${LDFLAGS_ARM64_A53_ERRATUM_843419}
- endif
- EOF
- fi # if [ "${TARCH}" = "arm64" ]...
- cat <<EOF
- NM_${TARCH}:=${GCCPREFIX}nm
- OBJCOPY_${TARCH}:=${GCCPREFIX}objcopy
- OBJDUMP_${TARCH}:=${GCCPREFIX}objdump
- READELF_${TARCH}:=${GCCPREFIX}readelf
- STRIP_${TARCH}:=${GCCPREFIX}strip
- AR_${TARCH}:=${GCCPREFIX}ar
- GNATBIND_${TARCH}:=${GCCPREFIX}gnatbind
- CROSS_COMPILE_${TARCH}:=${GCCPREFIX}
- EOF
- #The two blank lines above are intentional separators
- }
- # Architecture definitions
- SUPPORTED_ARCHITECTURES="arm arm64 mipsel riscv x64 x86 power8 elbrus"
- # TARCH: local name for the architecture
- # (used as CC_${TARCH} in the build system)
- # TBFDARCHS: architecture name in binutils (eg elf32-${TBFDARCH})
- # TCLIST: first part of the compiler triplet (eg i386 in i386-elf)
- # TWIDTH: numerical argument for cpu mode: gcc -m${TWIDTH}
- # TSUPP: supported subarchs (for -mcpu=...)
- # TABI: typically elf, eabi or linux
- arch_config_arm() {
- TARCH="arm"
- TBFDARCHS="littlearm"
- TCLIST="armv7-a armv7a arm"
- TWIDTH="32"
- TSUPP="arm armv4 armv7 armv7_m armv7_r"
- TABI="eabi"
- }
- arch_config_arm64() {
- TARCH="arm64"
- TBFDARCHS="littleaarch64"
- TCLIST="aarch64"
- TWIDTH="64"
- TSUPP="arm64 armv8_64"
- TABI="elf"
- }
- arch_config_riscv() {
- TARCH="riscv"
- TBFDARCHS="littleriscv"
- TCLIST="riscv riscv64"
- TWIDTH="64"
- TABI="elf"
- }
- arch_config_x64() {
- TARCH="x86_64"
- TBFDARCHS="x86-64"
- TCLIST="x86_64"
- TWIDTH="64"
- TABI="elf"
- }
- arch_config_x86() {
- TARCH="x86_32"
- TBFDARCHS="i386"
- TCLIST="i386 x86_64"
- TWIDTH="32"
- TABI="elf"
- CC_RT_EXTRA_GCC="--wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3"
- }
- arch_config_mipsel() {
- TARCH="mips"
- TBFDARCHS="tradlittlemips littlemips"
- TCLIST="mipsel"
- TWIDTH="32"
- TSUPP="mips mipsel"
- TABI="elf"
- TENDIAN="EL"
- }
- arch_config_power8() {
- TARCH="power8"
- TBFDARCHS="powerpc"
- TCLIST="powerpc64"
- TWIDTH="64"
- TSUPP="power8"
- TABI="linux-gnu" # there is no generic ABI on ppc64
- CC_RT_EXTRA_GCC="-mcpu=power8 -mbig-endian"
- }
- arch_config_elbrus() {
- TARCH="elbrus"
- TBFDARCHS="elbrus"
- TCLIST="elbrus"
- TWIDTH="64"
- TSUPP="elbrus"
- TABI="elf"
- CC_RT_EXTRA_GCC=""
- }
- test_architecture() {
- local architecture=$1
- local endian gccprefix search
- GCCPREFIX="invalid"
- unset TABI TARCH TBFDARCH TCLIST TENDIAN TSUPP TWIDTH
- unset CC_RT_EXTRA_GCC CC_RT_EXTRA_CLANG
- unset GCC CLANG
- if type "arch_config_$architecture" > /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-linux-"
- search="$search $toolchain-"
- search="$search $toolchain-linux-gnueabi-"
- 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" ||
- testas "$gccprefix" "$TWIDTH" "$TBFDARCH" \
- "TRUE" "$endian" ; } && \
- testcc "${gccprefix}gcc" "$CFLAGS_GCC" && \
- GCCPREFIX="$gccprefix" && \
- 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
Add Comment
Please, Sign In to add comment