#!/bin/sh

# This script written by Stephen Warren <swarren@wwwdotorg.org>.
# Release 2, 2005/03/27
#
# Mostly cobbled together from the scripts at these URLs,
# taking the bits of each one that actually work!
#
# http://www.sable.mcgill.ca/~dbelan2/crossdev/crossdev-powerpc-i686.html
# http://benoit.papillault.free.fr/notes/cross-gcc.php.en
#
# Plus, some inspiration and patches from crosstool, of course:
# http://kegel.com/crosstool/

# TODO:
# * Only build glibc against raw kernel headers.
#   Use the libc-headers project's cleaned-up headers for /usr/include?
#   (and hence main gcc build?)
#   But, /usr/include/{linux,asm} are supposed to be the headers glibc was
#   built against, which then wouldn't be the case???
# * Some of the target C++ libs aren't installed into SYSROOT?
# * Why doesn't glibc manual (texinfo stuff) build with NPTL enabled?
# * Split glibc patch into N atomic patches, instead of one mega patch
# * Integrate into crosstool - by either:
#   + Changes to the crosstool build script itself to integrate this
#     OR
#   + New top-level script for building NPTL toolchains, but using crosstool
#     infra-structure for download/extract/patch/etc.
# * root fs creation - similar to ptxdist,
#   but something that actually works for me...

set -e

cd `dirname $0`
BASE=`pwd`
if [ `basename ${BASE}` == "downloads" ]; then
  cd ..
  BASE=`pwd`
fi

KERNEL_VER=2.6.11
GLIBC_MIN_KERNEL_VER=2.6.4
BINUTILS_VER=2.15
GLIBC_VER=2.3.3
GCC_VER=3.4.3
BUILD_FOR=ppc603e

# FIXME: auto-detect this...
HOST_TRIPLET=i686-pc-linux-gnu
HOST_CFLAGS="-march=i686 -pipe"

if [ "${BUILD_FOR}" == "ppc603e" ]; then
  CROSS_TRIPLET=powerpc-unknown-linux-gnu
  CROSS_CFLAGS="-mcpu=603e -O3 -pipe"
  CROSS_ASFLAGS="-pipe"
  KERNEL_ARCH=ppc
  KERNEL_MAKE_TARGET=zImage
  KERNEL_IMAGE=arch/ppc/boot/images/vmlinux.gz
elif [ "${BUILD_FOR}" == "x86" ]; then
  CROSS_TRIPLET=i686-unknown-linux-gnu
  CROSS_CFLAGS="-march=i686 -O3 -pipe"
  CROSS_ASFLAGS="-pipe"
  KERNEL_ARCH=i386
  KERNEL_MAKE_TARGET=bzImage
  KERNEL_IMAGE=arch/i386/boot/bzImage
else
  echo Unknown BUILD_FOR ${BUILD_FOR}
  exit 1
fi

OUT_BASE=${BASE}/${CROSS_TRIPLET}
WORK=${OUT_BASE}/build
DEST=${OUT_BASE}/install
SYSROOT=${DEST}/target
CROSS_GCCLANG="c,c++"

export PATH=${DEST}/bin:${PATH}

# Setup destination directory structure

rm -rf ${OUT_BASE} ${WORK} ${DEST} ${SYSROOT}
mkdir -p ${WORK} ${DEST} ${SYSROOT}/usr/include

# Unpack tars

cd ${WORK}
rm -rf linux-${KERNEL_VER}
tar jxf ${BASE}/downloads/linux-${KERNEL_VER}.tar.bz2

cd ${WORK}
rm -rf binutils-${BINUTILS_VER}
tar zxf ${BASE}/downloads/binutils-${BINUTILS_VER}.tar.gz

cd ${WORK}
rm -rf gcc-${GCC_VER}
tar jxf ${BASE}/downloads/gcc-${GCC_VER}.tar.bz2

cd ${WORK}
rm -rf glibc-${GLIBC_VER}
tar jxf ${BASE}/downloads/glibc-${GLIBC_VER}.tar.bz2
cd glibc-${GLIBC_VER}
tar jxf ${BASE}/downloads/glibc-linuxthreads-${GLIBC_VER}.tar.bz2
patch -p1 < ${BASE}/downloads/patch-glibc-2.3.3-for-gcc-3.4.x.patch

# Build binutils

cd ${WORK}/binutils-${BINUTILS_VER}
CFLAGS=${HOST_CFLAGS} \
  ./configure \
    --target=${CROSS_TRIPLET} \
    --host=${HOST_TRIPLET} \
    --prefix=${DEST} \
    --with-sysroot=${SYSROOT} \
    --enable-shared
make
make install

# Setup kernel headers

cd ${WORK}/linux-${KERNEL_VER}
make ARCH=${KERNEL_ARCH} mrproper
cp ${BASE}/downloads/config-${CROSS_TRIPLET} .config
make ARCH=${KERNEL_ARCH} oldconfig
make ARCH=${KERNEL_ARCH} include/linux/version.h
cp -axf include/linux ${SYSROOT}/usr/include 
cp -axf include/asm-${KERNEL_ARCH} ${SYSROOT}/usr/include/asm-${KERNEL_ARCH}
cp -axf include/asm-generic ${SYSROOT}/usr/include/asm-generic
ln -sf asm-${KERNEL_ARCH} ${SYSROOT}/usr/include/asm
ln -sf ../target/usr/include ${DEST}/${CROSS_TRIPLET}/sys-include

# Setup glibc headers

cd ${WORK}
rm -rf glibc-${GLIBC_VER}-build-headers
mkdir glibc-${GLIBC_VER}-build-headers
cd glibc-${GLIBC_VER}-build-headers
../glibc-${GLIBC_VER}/configure \
  --build=${HOST_TRIPLET} \
  --host=${CROSS_TRIPLET} \
  --without-cvs \
  --disable-profile \
  --disable-debug \
  --without-gd \
  --enable-add-ons=linuxthreads \
  --with-tls \
  --without-__thread \
  --enable-kernel=${GLIBC_MIN_KERNEL_VER} \
  --with-headers=${SYSROOT}/usr/include \
  --prefix=/usr \
  --with-sysroot=${SYSROOT}

make install-headers install_root=${SYSROOT}
touch ${SYSROOT}/usr/include/gnu/stubs.h
cp bits/stdio_lim.h ${SYSROOT}/usr/include/bits

# Build bootstrap gcc

cd ${WORK}
rm -rf gcc-${GCC_VER}-build-bootstrap
mkdir gcc-${GCC_VER}-build-bootstrap
cd gcc-${GCC_VER}-build-bootstrap
CFLAGS="${HOST_CFLAGS} -Dinhibit_libc -static-libgcc" \
  ../gcc-${GCC_VER}/configure \
    --prefix=${DEST} \
    --host=${HOST_TRIPLET} \
    --target=${CROSS_TRIPLET} \
    --with-newlib \
    --disable-shared \
    --disable-threads \
    --enable-languages="c" \
    --disable-multilib \
    --disable-nls \
    --enable-symvers=gnu \
    --enable-__cxa_atexit \
    --with-sysroot=${SYSROOT} \
    --enable-static

make \
    ASFLAGS_FOR_TARGET="${CROSS_ASFLAGS}" \
    CFLAGS_FOR_TARGET="${CROSS_CFLAGS}" \
    CXXFLAGS_FOR_TARGET="${CFLAGS_FOR_TARGET}"

make install

# Build glibc

cd ${WORK}
rm -rf glibc-${GLIBC_VER}-build
mkdir glibc-${GLIBC_VER}-build
cd glibc-${GLIBC_VER}-build

rm -f config.cache
touch config.cache
echo "libc_cv_forced_unwind=yes" >> config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache

# Don't just say CC="${CROSS_TRIPLET}-gcc ${CFLAGS}" below
# Evidently, ${CC} gets used for .S files as well, and hence CFLAGS will be
# We don't want to do this, or when optimization is enabled, __i686 will be
# defined (or similar for other arch's) and this will break some assembly code
# that uses __i686 in section names, and expects this to be literal text, not
# a macro that's defined to 1.
# The alternative would be hacking sysdeps/i386/sysdep.h to redefine __i686 
# from 1 to __i686 for assembly language - see
# http://gcc.gnu.org/ml/gcc-bugs/2002-10/msg00293.html
# But, this is simpler, because there are no patches to apply...
# (that must be why the latest glibc CVS hasn't been "fixed" for this...)

BUILD_CC="gcc" \
    AR="${CROSS_TRIPLET}-ar" \
    ASFLAGS="${CROSS_ASFLAGS}" \
    CC=${CROSS_TRIPLET}-gcc \
    CFLAGS="${CROSS_CFLAGS}" \
    RANLIB="${CROSS_TRIPLET}-ranlib" \
    ../glibc-${GLIBC_VER}/configure \
    --build=${HOST_TRIPLET} \
    --host=${CROSS_TRIPLET} \
    --target=${CROSS_TRIPLET} \
    --without-cvs \
    --disable-profile \
    --disable-debug \
    --without-gd \
    --enable-add-ons=nptl \
    --with-tls \
    --with-__thread \
    --enable-kernel=${GLIBC_MIN_KERNEL_VER} \
    --with-headers=${SYSROOT}/usr/include \
    --prefix=/usr \
    --with-sysroot=${SYSROOT} \
    --enable-clocale=gnu \
    --cache-file=config.cache

make

make install install_root=${SYSROOT}

# Build full gcc

cd ${WORK}
rm -rf gcc-${GCC_VER}-build
mkdir gcc-${GCC_VER}-build
cd gcc-${GCC_VER}-build

CFLAGS="${HOST_CFLAGS}" \
  ../gcc-${GCC_VER}/configure \
    --prefix=${DEST} \
    --target=${CROSS_TRIPLET} \
    --host=${HOST_TRIPLET} \
    --disable-multilib \
    --disable-nls \
    --enable-shared \
    --enable-languages="${CROSS_GCCLANG}" \
    --without-included-gettext \
    --with-system-zlib \
    --enable-threads=posix \
    --enable-long-long \
    --enable-symvers=gnu \
    --disable-checking \
    --enable-cstdio=stdio \
    --enable-clocale=generic \
    --enable-__cxa_atexit \
    --enable-c99 \
    --enable-version-specific-runtime-libs \
    --with-sysroot=${SYSROOT}

make \
    ASFLAGS_FOR_TARGET="${CROSS_ASFLAGS}" \
    CFLAGS_FOR_TARGET="${CROSS_CFLAGS} -DHAVE_SYS_ERRLIST" \
    CXXFLAGS_FOR_TARGET="${CFLAGS_FOR_TARGET}"

make install

# Build kernel

cd ${WORK}/linux-${KERNEL_VER}
make ARCH=${KERNEL_ARCH} CROSS_COMPILE=${DEST}/bin/${CROSS_TRIPLET}- ${KERNEL_MAKE_TARGET}
mkdir -p ${SYSROOT}/boot
cp ${KERNEL_IMAGE} ${SYSROOT}/boot/kernel/`basename ${KERNEL_IMAGE}`-${KERNEL_VER}

