blob: 4780121dad4df479f86834e0853a7c7fc4cc9bf3 [file] [log] [blame]
#!/usr/bin/env bash
OS=`uname`
HOSTARCH=`uname -m`
PARALLEL=
FETCH=0
QUIET=0
STRIP=0
GNU_MIRROR=https://mirrors.kernel.org/gnu
# Get absolute path, will spawn a subshell then exit so our pwd is retained
SCRIPTROOT=$(cd "$(dirname $0)" && pwd)
PATCHES=$SCRIPTROOT/patches/
# Cause errors in pipes to return failure when necessary
set -o pipefail
function err() {
echo "doit: error during build"
if [ "$QUIET" = "1" ]; then
echo "doit: dumping last 50 lines of build log..."
echo "doit: see $OUTDIR/build.log for the full details"
tail -50 $OUTDIR/build.log
fi
exit 1
}
trap err ERR
function help()
{
echo "Options"
echo " -a <arch list> architectures to build"
echo " example: -a 'arm' or -a 'arm i386 x86_64' for multiple"
echo " -c use compilation cache (ccache must be installed)"
echo " -f fetch source releases from upstream"
echo " -h|-? display this help message"
echo " -j<#> use <#> parallel workers to build"
echo " -o <dir> output directory"
echo " -q make the build quieter"
echo " -s strip the binaries"
exit 1
}
function log()
{
if [ "$QUIET" = "1" ]; then
"$@" >> $OUTDIR/build.log 2>&1
else
"$@" 2>&1 | tee -a $OUTDIR/build.log
fi
}
function extract-tool()
{
#echo "extract-tool " $1 $2 $3 $4
TARFILE=${1}-${2}.tar$3
TARGETDIR=${1}-${2}
HASH="$4"
PATCH="$5"
if [ -f ${TARGETDIR}/.extracted ]; then
log echo "$TARFILE already extracted into $TARGETDIR, skipping"
return 0
fi
if [ ! -f $ARCHIVES/$TARFILE ]; then
log echo "error, missing $TARFILE"
exit 1
fi
echo "checking $TARFILE integrity"
if [ "$(shasum -a 256 -b "$ARCHIVES/$TARFILE" | cut -f1 -d' ')" != "$HASH" ]; then
log echo "$TARFILE failed integrity check"
exit 1
fi
echo extracting $TARFILE
pushd $OUTDIR
rm -rf $TARGETDIR
tar xf $ARCHIVES/$TARFILE || exit 1
if [ -n "$PATCH" ]; then
log echo patching $1
log patch -d $TARGETDIR -p1 < "$PATCH" || exit 1
fi
touch $TARGETDIR/.extracted || exit 1
popd
}
if [ "$OS" = "Linux" ]; then
COUNT=`grep processor /proc/cpuinfo | wc -l`
PARALLEL=-j`expr $COUNT + $COUNT`
fi
if [ "$OS" = "Darwin" ]; then
# needed to work around problem with clang compiler and some generated code in gcc
export CXXFLAGS="-fbracket-depth=1024"
fi
MAKE=make
if [ "$OS" = "FreeBSD" ]; then
MAKE=gmake
fi
if [ "$HOSTARCH" = "amd64" ]; then
HOSTARCH=x86_64
fi
if [ $# == "0" ]; then
help
fi
while getopts a:cfhj:o:qs? arg
do
case $arg in
a ) ARCHES=$OPTARG ;;
c ) CCACHE=1 ;;
j ) PARALLEL="-j$OPTARG" ;;
f ) FETCH=1 ;;
o ) OUTDIR=$OPTARG ;;
q ) QUIET=1 ;;
s ) STRIP=1 ;;
h ) help ;;
? ) help ;;
* ) echo "unrecognized option '$arg'" ; exit 1 ;;
esac
done
if [ -z "$ARCHES" ]; then
echo need to specify architectures to build
echo ie -a "arm sh"
exit 1
fi
if [ -z "$OUTDIR" ]; then
OUTDIR=`pwd`
fi
ARCHIVES=$OUTDIR/archives
if [ -z $(which makeinfo) ]; then
echo makeinfo not found. On debian/ubuntu this is provided by the texinfo package.
exit 1
fi
export CC="cc"
export CXX="c++"
if [ "$CCACHE" = "1" ]; then
export CC="ccache $CC"
export CXX="ccache $CXX"
fi
log date
log echo "ARCHES='$ARCHES' PARALLEL='$PARALLEL' FETCH='$FETCH' CCACHE='$CCACHE'"
# load GCC_VER and BINUTILS_VER
. toolvers
if [ "$FETCH" = "1" ]; then
if [ ! -f $ARCHIVES/binutils-$BINUTILS_VER.tar.bz2 ]; then
echo fetching binutils-$BINUTILS_VER
log wget -P $ARCHIVES -N $GNU_MIRROR/binutils/binutils-$BINUTILS_VER.tar.bz2
fi
if [ ! -f $ARCHIVES/gcc-$GCC_VER.tar.bz2 ]; then
echo fetching gcc-$GCC_VER
log wget -P $ARCHIVES -N $GNU_MIRROR/gcc/gcc-$GCC_VER/gcc-$GCC_VER.tar.bz2
fi
if [ ! -f $ARCHIVES/gdb-$GDB_VER.tar.xz ]; then
echo fetching gdb-$GDB_VER
log wget -P $ARCHIVES -N $GNU_MIRROR/gdb/gdb-$GDB_VER.tar.xz
fi
if [ ! -f $ARCHIVES/mpfr-$MPFR_VER.tar.bz2 ]; then
echo fetching mpfr-$MPFR_VER
log wget -P $ARCHIVES -N $GNU_MIRROR/mpfr/mpfr-$MPFR_VER.tar.bz2
fi
if [ ! -f $ARCHIVES/mpc-$MPC_VER.tar.gz ]; then
echo fetching mpc-$MPC_VER
log wget -P $ARCHIVES -N $GNU_MIRROR/mpc/mpc-$MPC_VER.tar.gz
fi
if [ ! -f $ARCHIVES/gmp-$GMP_VER.tar.bz2 ]; then
echo fetching gmp-$GMP_VER
log wget -P $ARCHIVES -N $GNU_MIRROR/gmp/gmp-$GMP_VER.tar.bz2
fi
fi
if [ ! -f $OUTDIR/.extracted-stamp ]; then
extract-tool binutils $BINUTILS_VER .bz2 $BINUTILS_HASH $PATCHES/binutils-patch.txt
extract-tool gcc $GCC_VER .bz2 $GCC_HASH $PATCHES/gcc-patch.txt
extract-tool gdb $GDB_VER .xz $GDB_HASH $PATCHES/gdb-patch.txt
extract-tool gmp $GMP_VER .bz2 $GMP_HASH
extract-tool mpc $MPC_VER .gz $MPC_HASH
extract-tool mpfr $MPFR_VER .bz2 $MPFR_HASH
touch $OUTDIR/.extracted-stamp
fi
# link the last three libs into gcc
pushd $OUTDIR/gcc-$GCC_VER
ln -sf ../gmp-$GMP_VER gmp
ln -sf ../mpc-$MPC_VER mpc
ln -sf ../mpfr-$MPFR_VER mpfr
popd
COMMON_CONFIG=--with-included-gettext
for ARCH in $ARCHES; do
echo building for arch \"$ARCH\"
if [ "$ARCH" == "arm" ]; then
TARGET=arm-eabi
else
TARGET=$ARCH-elf
fi
INSTALLPATH=$OUTDIR/$TARGET-$GCC_VER-$OS-$HOSTARCH
BINBUILDPATH=$OUTDIR/build-binutils-$BINUTILS_VER-$ARCH-$OS-$HOSTARCH
GCCBUILDPATH=$OUTDIR/build-gcc-$GCC_VER-$ARCH-$OS-$HOSTARCH
GDBBUILDPATH=$OUTDIR/build-gdb-$GDB_VER-$ARCH-$OS-$HOSTARCH
export PATH=$INSTALLPATH/bin:$PATH
# Building Binutils
if [ ! -f $BINBUILDPATH/built.txt ]; then
case "$ARCH" in
x86_64) EXTRA_TARGETS="--enable-targets=x86_64-pep" ;;
*) EXTRA_TARGETS="" ;;
esac
echo building binutils
mkdir -p $BINBUILDPATH
pushd $BINBUILDPATH
log ../binutils-$BINUTILS_VER/configure $COMMON_CONFIG --target=$TARGET --prefix=$INSTALLPATH --disable-werror --enable-initfini-array --enable-gold $EXTRA_TARGETS
log $MAKE $PARALLEL
log $MAKE install
touch built.txt
popd
fi
# Building GCC
if [ ! -f $GCCBUILDPATH/built.txt ]; then
echo building gcc
ARCH_OPTIONS=
if [ $ARCH == "arm" ]; then
ARCH_OPTIONS="--with-cpu=arm926ej-s --with-fpu=vfp"
fi
mkdir -p $GCCBUILDPATH
pushd $GCCBUILDPATH
log ../gcc-$GCC_VER/configure $COMMON_CONFIG --target=$TARGET --prefix=$INSTALLPATH --enable-languages=c,c++ $ARCH_OPTIONS --disable-werror
log $MAKE all-gcc $PARALLEL
log $MAKE all-target-libgcc $PARALLEL
log $MAKE install-gcc
log $MAKE install-target-libgcc
touch built.txt
popd
fi
if [ ! -f $GDBBUILDPATH/built.txt ]; then
case "$TARGET" in
aarch64-elf) EXTRA_TARGETS="--enable-targets=arm-eabi" ;;
*) EXTRA_TARGETS="" ;;
esac
echo building gdb
mkdir -p $GDBBUILDPATH
pushd $GDBBUILDPATH
log ../gdb-$GDB_VER/configure $COMMON_CONFIG --target=$TARGET --prefix=$INSTALLPATH --disable-werror $EXTRA_TARGETS
log make $PARALLEL
log make install
touch built.txt
popd
fi
# Optionally strip the binaries
if [ "${STRIP}" = "1" ]; then
find "${INSTALLPATH}/bin" -type f -exec strip {} \;
for filename in $(find "${INSTALLPATH}/libexec" -type f); do
(file "${filename}" | grep -q ELF) && strip "${filename}"
done
fi
done
echo all done