#!/bin/sh

# This script runs as a mortal user, and builds a cross-development
# toolchain, plus kernel, for arm-linux in general, and in particular
# the SA1100 on a Bright Star Engineering nanoEngine board.  Only
# slight adjustments should be needed for other StrongARM boards,
# and the basic flow holds for building any other cross-build
# environment.
#
# This script only very weakly depends on the host system, as long as it
# has a halfway-working gcc and gmake.  Tested on i686-unknown-linux-gnu,
# kernel-2.0.36, gcc-2.95.3, gmake-3.79.1, glibc-2.0.7.  Eariler versions
# were tested with gcc-2.7.2.
# 
#
# Mostly follows "HOW-To build a cross Tool Chain in brief by George France"
#
# todo:
#   more initial sanity checks

set -e

ARCH=arm
TARGET=$ARCH-linux

if [ ! -d $PRISTINE -o ! -d $BUILD -o ! -d $PREFIX ]; then
   echo "$0: configuration error"
   exit 1
fi

if [ "X$UID" = "X0" ]; then
   echo "$0: script too dangerous to run as root"
   exit 1
fi

KHOME=$BUILD/linux-2.4.18-rmk7-lrd1
HOST_SYS=i386-linux     # only needed for glibc configure --build=$HOST_SYS
PATH=$PREFIX/bin:$PATH

# ...................................
# build, and install binutils
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
echo "================binutils============="; date
cd $BUILD
mkdir binutils-2.10.1-$ARCH
cd binutils-2.10.1-$ARCH
$PRISTINE/binutils-2.10.1/configure --prefix=$PREFIX --target=$TARGET
make
make install


# ....................
# configure the kernel
# ^^^^^^^^^^^^^^^^^^^^
echo "================kernel_config============="; date
cd $KHOME
#
# Don't need to touch up ARCH and CROSS_COMPILE,
# because diff-2.4.0-test4-np1.gz did that already.
# mv Makefile Makefile.orig
# sed -e '/^CROSS_COMPILE/s/=$/= arm-linux-/' -e '/^ARCH/{s/^/#/
# a \
# ARCH=arm
# }' <Makefile.orig >Makefile
#
# XXXX really, really needs to have all defaults covered
# XXXX issue: CONFIG_CMDLINE can't be blank
cp arch/arm/def-configs/nanoengine .config
# XXXX fix a problem here, instead of making a new patch file
sed -e 's/CMDLINE="root=1f04/CMDLINE="root=\/dev\/ram/' <arch/arm/def-configs/nanoengine >.config
# XXXX gets into minor trouble because the Makefile attempts to see if the
#      compiler takes '-fno-strict-aliasing', but $TARGET-gcc isn't built yet.
#      Maybe we can shift the 'configure-kernel' step until after building
#      the first gcc?
make oldconfig
#
# $PREFIX/$TARGET/include was created by the install of binutils
# Should we "cp -a" instead of "ln -s"?
# certainly not now, because it doesn't include version.h yet.
#
# gcc config (coming up) will look for $PREFIX/$TARGET/sys-include/limits.h,
# to decide whether or not to chain its limits.h via #include_next.
# We need that test to succeed.
#
( cd $PREFIX/$TARGET
  mkdir -p include
  ln -s include sys-include
  cd include
  ln -s $KHOME/include/asm-$ARCH asm
  ln -s $KHOME/include/linux linux
)


# ........................
# build first round of gcc
# ^^^^^^^^^^^^^^^^^^^^^^^^
echo "================gcc_nolibc============="; date
# consider using gcc-2.95.x-$ARCH-nolibc, totally separate from second build
cd $BUILD
mkdir gcc-2.95.3-$ARCH
cd gcc-2.95.3-$ARCH
# what about --with-headers and --with-libs?  --enable-shared?
$PRISTINE/gcc-2.95.3/configure -target=$TARGET  --prefix=$PREFIX --enable-languages=c -disable-threads -with-cpu=strongarm110
#
# patch gcc/Make-target and gcc/Makefile for the first compile phase, that
# happens without use of glibc.  The Makefiles really ought to leave a better
# hook for this step.  I tried overriding the variables from the command line,
# but they don't propagate to make in the gcc subdir.
( cd gcc
  mv Make-target Make-target.orig
  sed -e '/^TARGET_LIBGCC2_CFLAGS/s/$/ -Dinhibit_libc -D__gthr_posix_h/' \
      -e 's/ _dvmd_lnx$/ _dvmd_tls/' \
      <Make-target.orig >Make-target
  mv Makefile Makefile.orig
  sed -e '/^TARGET_LIBGCC2_CFLAGS/s/$/ -Dinhibit_libc -D__gthr_posix_h/' \
      -e 's/ _dvmd_lnx$/ _dvmd_tls/' \
      <Makefile.orig >Makefile
)
make
#
# Q: Why do we get
# checking whether the C compiler (/mnt/rffe/ldoolitt/gcc-2.95.3-arm/gcc/xgcc -B/mnt/rffe/ldoolitt/gcc-2.95.3-arm/gcc/ -B/home/ldoolitt/rffe/arm-devel/arm-linux/bin/ -g -O2 ) works... no
# configure: error: installation or configuration problem: C compiler cannot create executables.
# near the end of that last "make"?
#
# A: ld: cannot open crt1.o: No such file or directory
#
make install
# Double check $PREFIX/bin doesn't have anything in it that
# keeps us from building native code; like cpp?

# does $PREFIX/include need to be replaced with a symlink back to $PREFIX/include?
# why include, and not sys-include?  aargh!
#
# we just touched:
#   arm-linux/include   (but no files in it)
#   arm-linux/bin/gcc
#   bin/arm-linux-gcc
#   bin/arm-linux-protoize
#   bin/arm-linux-unprotoize
#   bin/cpp
#   bin/gcov
#   info/*
#   lib/gcc-lib/*
#   lib/libiberty.a
#   man/man1/arm-linux-gcc.1
#   man/man1/cccp.1
# There's only one of those that I can't accept, I fix it now:
###( cd $PREFIX/$TARGET
###  rmdir include
###  ln -s ../include include
###)
# since glibc's include directory is architecture-neutral.
# I'm also confused why host binaries are installed in arm-linux/bin,
# by both gcc and binutils.  Is this what --exec-prefix is for?
# That wouldn't really match glibc's usage, below.


# ..................
# build linux kernel
# ^^^^^^^^^^^^^^^^^^
# see below, has to happen before glibc build, and therefore also before
# the second gcc build.
echo "================kernel============="; date
cd $KHOME
make dep
make zImage
# builds, decompresses, initializes, runs.  Kewl!


# ...................................................
# build, and install glibc+crypt+linuxthreads
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
echo "================glibc============="; date
cd $BUILD
mkdir glibc-2.1.3-$ARCH
cd glibc-2.1.3-$ARCH
# but but but, no "--with-headers=$KHOME/include --with-binutils=$PREFIX/bin --disable-sanity-checks"?
# The following step needs to find <linux/version.h>, so it has to happen
# after a real build of the kernel.  Or, as the glibc FAQ 1.8 suggests, after
# `make include/linux/version.h'.
CC=$TARGET-gcc $PRISTINE/glibc-2.1.3/configure $TARGET --build=$HOST_SYS --prefix="" --enable-add-ons=linuxthreads,crypt --program-prefix=$TARGET-
make
# DANGER: You WILL screw up your system if you forget the install_root  
# part of the next command.  Well, if you were running as root, that is.
make install_root=$PREFIX/$TARGET install
#
# Fix up glibc ld script, which has paths that need to be used on the host
# XXX total hack, might not even be Right[TM]
echo "touching up $PREFIX/$TARGET/lib/libc.so"
( cd $PREFIX/$TARGET/lib
  mv libc.so libc.so.orig
  sed -e "/^GROUP/s, /lib/, $PREFIX/$TARGET/lib/,g" <libc.so.orig >libc.so
)


# .....................................................
# go back and re-build gcc with glibc, g++, and threads
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
echo "================gcc_final============="; date
cd $BUILD/gcc-2.95.3-$ARCH
$PRISTINE/gcc-2.95.3/configure -target=$TARGET  --prefix=$PREFIX --enable-languages=c,c++ -with-cpu=strongarm110
# I ran into problems with missing c++ include files "typeinfo"
# and "new", that went away after a "make clean".
make clean
make
make install

# ................
# build libtermcap
# ^^^^^^^^^^^^^^^^
echo "================termcap============="; date
cd $BUILD
mkdir termcap-1.3.1-$ARCH
cd termcap-1.3.1-$ARCH
CC=$TARGET-gcc RANLIB=$TARGET-ranlib $PRISTINE/termcap-1.3.1/configure
make
cp libtermcap.a $PREFIX/$TARGET/lib
cp $PRISTINE/termcap-1.3.1/termcap.h $PREFIX/$TARGET/include

# .....................................................
# build genext2fs for use on host
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
echo "================genext2fs============="; date
cd $BUILD
mkdir genext2fs-1.3-host
cd genext2fs-1.3-host
make -f $PRISTINE/genext2fs-1.3.orig/Makefile VPATH=$PRISTINE/genext2fs-1.3.orig 
cp genext2fs $PREFIX/bin

# .................................
# build nanofix, a boot-time helper
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
echo "================nanofix============="; date
cd $BUILD/nanofix
make combo KERNEL=$KHOME

echo "================done============="; date
# done with toolchain!