#!/bin/sh
#
# This script builds the m68k-elf- toolchain for use with uClinux.
#
# Before running you will need to obtain (if you don't have them in this
# directory):
#
#    binutils-2.10.tar.bz2         in current directory (or a gzipped version)
#    binutils-2.10-elfPICgot.patch in current directory
#    binutils-2.10-wdebug.patch    in current directory
#    gcc-2.95.3.tar.bz2            in current directory (or a gzipped version)
#    gcc-2.95.3-elfPICgot.patch    in current directory
#    elf2flt-20010606.tgz          in current directory
#    genromfs-0.3.1.tar.bz2        in current directory
#    genromfs-0.3.uclinuxdiff      in current directory
#
# You will also need
#
#    a current uClibc tree from opensource.lineo.com
#    a current uClinux kernel (2.0/2.4) from cvs.uclinux.org
#    to change the EDIT section below appropriately
#    to be root in order to run this script
#
# You can link the uClibc and uClinux-2.0.x or uClinux-2.4.x dirs into the
# current directory or change the values below.
#
# This script:
#
# DOES build all the gcc tools/libraries
#
# DOES NOT build target specific versions of libc but provides a mechanism
#          to do this with the "uclibc" argument if that is what you want.
#
# You must be root to run this script correctly.
#
# To build everything run "./build-m68k-elf.sh build 2>&1 | tee errs"
#
# WARNING: it removes all m68k-elf tools from /usr/local,  so back them up
#          first :-)
#
# Copyright (C) 2001, Lineo
# davidm@lineo.com
#
#############################################################
#
# our build starts here
#

BASEDIR="`pwd`"

#############################################################
#
# EDIT these to suit your system and source locations
#

MAKE=gmake
UCLIBC="$BASEDIR/uClibc"
KERNEL="$BASEDIR/uClinux-2.0.x"
TARGET=m68k-elf
#TARGET=arm-elf

#############################################################
#
# mark stage done
#

mark()
{
	echo "STAGE $1 - complete"
	touch "$BASEDIR/STAGE$1"
}

#
# check if stage should be built
#

schk()
{
	echo "--------------------------------------------------------"
	[ -f "$BASEDIR/STAGE$1" ] && echo "STAGE $1 - already built" && return 1
	echo "STAGE $1 - needs building"
	return 0
}

#
# extract most XYZ format files
#

extract()
{
	for i in "$@"; do
		case "$i" in
		*.tar.gz|*.tgz)   tar xzf "$i" ;;
		*.tar.bz2|*.tbz2) bunzip2 < "$i" | tar xf - ;;
		*.tar)            tar xf  "$i" ;;
		*)
			echo "Unknown file format $i" >&2
			return 1
			;;
		esac
	done
	return 0
}

#############################################################
#
# clean any previous runs, extract some stuff
#

stage1()
{
	schk 1 || return 0

	rm -rf binutils-2.10
	rm -rf gcc-2.95.3
	rm -rf /usr/local/${TARGET}*
	rm -rf /usr/local/lib/gcc-lib/${TARGET}*
	rm -rf /usr/local/bin/${TARGET}*
#
#	extract binutils, gcc and anything else we know about
#
	extract binutils-2.10.*
	extract gcc-2.95.3.*
#
#	apply any patches
#
	patch -p0 < gcc-2.95.3-elfPICgot.patch
	patch -p0 < binutils-2.10-elfPICgot.patch
	patch -p0 < binutils-2.10-wdebug.patch
	cd $BASEDIR
	mark 1
}

#############################################################
#
# build binutils
#

stage2()
{
	schk 2 || return 0

	rm -rf ${TARGET}-binutils
	mkdir ${TARGET}-binutils
	cd ${TARGET}-binutils
	../binutils-2.10/configure --target=${TARGET}
	${MAKE}
	${MAKE} install
	cd $BASEDIR
	mark 2
}

#############################################################
#
# hack the env up for gcc build
#

stage3()
{
	schk 3 || return 0

	#
	# fix up the uClibc auto gen files
	#
	cd ${UCLIBC}/.
	sed "s?^[ 	]*KERNEL_SOURCE=.*?KERNEL_SOURCE=${KERNEL}?" \
						< extra/Configs/Config.${_CPU} > Config
	rm -f ${KERNEL}/include/asm
	ln -s ${KERNEL}/include/asm-${_CPU}nommu ${KERNEL}/include/asm
	${MAKE} uClibc_config.h CROSS="${TARGET}-"
	chmod 644 uClibc_config.h

	rm -rf /usr/local/${TARGET}/sys-include
	rm -f ${UCLIBC}/include/asm
	cp -r ${UCLIBC}/include /usr/local/${TARGET}/sys-include
	rm -rf /usr/local/${TARGET}/sys-include/asm
	rm -rf /usr/local/${TARGET}/sys-include/bits
	cp -r ${UCLIBC}/libc/sysdeps/linux/${_CPU}/bits \
					/usr/local/${TARGET}/sys-include/.
	cp uClibc_config.h /usr/local/${TARGET}/sys-include/bits/.
	rm -rf /usr/local/${TARGET}/sys-include/linux
	cp -r ${KERNEL}/include/linux /usr/local/${TARGET}/sys-include/linux
	touch /usr/local/${TARGET}/sys-include/linux/autoconf.h
	cp -r ${KERNEL}/include/asm-${_CPU}nommu \
					/usr/local/${TARGET}/sys-include/.

	# 2.4 headers also need this (may not be there for some archs)
	cp -r ${KERNEL}/include/asm-${_CPU} /usr/local/${TARGET}/sys-include/.  ||\
			true

	ln -s /usr/local/${TARGET}/sys-include/asm-${_CPU}nommu \
					/usr/local/${TARGET}/sys-include/asm
	
	case ${TARGET} in
	arm*)
		ln -s /usr/local/${TARGET}/sys-include/asm-${_CPU}nommu/proc-armv \
						/usr/local/${TARGET}/sys-include/asm/proc
		;;
	esac

	#
	# clean out any CVS files,  don't fail on this one
	#
	set +e
	find /usr/local/${TARGET}/sys-include -name CVS | xargs rm -rf
	set -e

	mkdir -p /usr/local/lib/gcc-lib || true
	chmod 755 /usr/local/lib/gcc-lib

	cd $BASEDIR
	mark 3
}

#############################################################
#
# first pass,  just the C compiler so we can build uClibc
#

stage4()
{
	schk 4 || return 0

	rm -rf ${TARGET}-gcc
	mkdir ${TARGET}-gcc
	cd ${TARGET}-gcc
	../gcc-2.95.3/configure --enable-languages=c --target=${TARGET}
	${MAKE}
	${MAKE} install

	cd $BASEDIR
	mark 4
}

#############################################################
#
# build uCLibc with first pass compiler
#

stage5()
{
	schk 5 || return 0

	cd ${UCLIBC}/.
	sed "s?^[ 	]*KERNEL_SOURCE=.*?KERNEL_SOURCE=${KERNEL}?" \
						< extra/Configs/Config.${_CPU} > Config
	rm -f ${KERNEL}/include/asm
	ln -s ${KERNEL}/include/asm-${_CPU}nommu ${KERNEL}/include/asm
	${MAKE} clean CROSS="${TARGET}-"
	${MAKE} CROSS="${TARGET}-"

	cd $BASEDIR
	mark 5
}

#############################################################
#
# second pass,  build everything,  all compilers of use :-)
#

stage6()
{
	schk 6 || return 0

	#
	# We need these files for the configure parts of this stage
	#
	cp ${UCLIBC}/lib/libc.a /usr/local/${TARGET}/lib/.
	cp ${UCLIBC}/lib/crt0.o /usr/local/${TARGET}/lib/.

	rm -rf ${TARGET}-gcc
	mkdir ${TARGET}-gcc
	cd ${TARGET}-gcc
	../gcc-2.95.3/configure --enable-languages=c,c++ --target=${TARGET} \
			--enable-multilib
	${MAKE} LIBS=-lc
	${MAKE} install

	#
	# for some reason "make install" doesn't install all the multilib
	# libraries in the right place.  We have to do this ourselves.
	# the directories should exist, so failing if they don't is ok
	#
	for lib in libio libiostream
	do
		echo "Manual install of $lib.a ..."
		find ${TARGET} -name $lib.a -print | while read file
		do
			MLIB=`expr $file : "${TARGET}\(.*\)"`
			MLIB=`expr $MLIB : "\(.*\)/[^/]*/$lib.a"`
			echo "  $MLIB/$lib.a"
			cp $file /usr/local/${TARGET}/lib/$MLIB/$lib.a || exit 1
		done || exit 1
	done || exit 1

	#
	# Don't leave these around as they will not work for all targets
	# If you want uClibc-multilib,  build that later
	#
	rm -f /usr/local/${TARGET}/lib/libc.a
	rm -f /usr/local/${TARGET}/lib/crt0.o

	cd $BASEDIR
	mark 6
}

#############################################################
#
# build genromfs
#

stage7()
{
	schk 7 || return 0
	rm -rf genromfs-0.3.1
	extract genromfs-0.3.1*
	cd genromfs-0.3.1
	patch -p1 < ../genromfs-0.3.uclinuxdiff
	${MAKE}
	cp genromfs /usr/local/bin/.
	chmod 755 /usr/local/bin/genromfs

	cd $BASEDIR
	mark 7
}

#############################################################
#
# build elf2flt
#

stage8()
{
	schk 8 || return 0


	rm -rf elf2flt-20010606
	extract elf2flt-20010606*
	cd elf2flt-20010606
	mv Makefile Makefile.tmp
	sed "s?^[ 	]*PREFIX.*=.*\$?PREFIX=../${TARGET}-binutils?" \
						< Makefile.tmp > Makefile
	cp $KERNEL/include/linux/flat.h .
	${MAKE}
	cp elf2flt /usr/local/bin/${TARGET}-elf2flt
	ln -f /usr/local/bin/${TARGET}-elf2flt /usr/local/bin/elf2flt
	ln -f /usr/local/bin/${TARGET}-elf2flt /usr/local/${TARGET}/bin/elf2flt
	chmod 755 /usr/local/bin/elf2flt
	[ -f /usr/local/bin/${TARGET}-ld.real ] || \
		cp /usr/local/bin/${TARGET}-ld /usr/local/bin/${TARGET}-ld.real
	[ -f /usr/local/${TARGET}/bin/ld.real ] || \
		cp /usr/local/${TARGET}/bin/ld /usr/local/${TARGET}/bin/ld.real
	cp ld-elf2flt /usr/local/bin/${TARGET}-ld
	cp ld-elf2flt /usr/local/${TARGET}/bin/ld
	cp elf2flt.ld /usr/local/${TARGET}/lib/.

	cd $BASEDIR
	mark 8
}

#############################################################
#
# build multilib versions of uCLibc for a fuller install
#

build_uclibc_mlib()
{
	# set -x
	cd ${UCLIBC}/.

	case "${_CPU}" in
	m68k*) ALL_BUILDS="-Wa,--bitwise-or -D__linux__=1" ;;
	*)     ALL_BUILDS="-D__linux__=1" ;;
	esac

	(
		echo ". $ALL_BUILDS"
		case "${_CPU}" in
		m68k*)
			echo "msoft-float       $ALL_BUILDS -msoft-float"
			echo "m5200             $ALL_BUILDS -m5200 -Wa,-m5200"
			echo "m5200/msep-data   $ALL_BUILDS -m5200 -Wa,-m5200 -msep-data"
			echo "m68000            $ALL_BUILDS -m68000"
			echo "m68000/msep-data  $ALL_BUILDS -m68000 -msep-data"
			echo "mcpu32            $ALL_BUILDS -mcpu32"
			echo "mcpu32/msep-data  $ALL_BUILDS -mcpu32 -msep-data"
			;;
		arm*)
			# don't know what is needed here yet
			;;
		esac
	) | while read mlibdir cflags
	do
		sed -e "s?^[ 	]*KERNEL_SOURCE[ 	]*=.*?KERNEL_SOURCE=${KERNEL}?g" \
		    -e "s?^[ 	]*ARCH_CFLAGS[ 	]*=.*?ARCH_CFLAGS=${cflags}?g" \
		    < extra/Configs/Config.${_CPU} > Config
		${MAKE} clean CROSS="${TARGET}-"
		${MAKE} CROSS="${TARGET}-"

		cp lib/crt0.o /usr/local/${TARGET}/lib/$mlibdir/crt0.o || exit 1
		cp lib/libc.a /usr/local/${TARGET}/lib/$mlibdir/libc.a || exit 1
		cp lib/libcrypt.a /usr/local/${TARGET}/lib/$mlibdir/libcrypt.a || exit 1
		cp lib/libm.a /usr/local/${TARGET}/lib/$mlibdir/libm.a || exit 1
		cp lib/libresolv.a /usr/local/${TARGET}/lib/$mlibdir/libresolv.a || \
				exit 1
		cp lib/libutil.a /usr/local/${TARGET}/lib/$mlibdir/libutil.a || exit 1

		chmod 644 /usr/local/${TARGET}/lib/$mlibdir/libc.a || exit 1
		chmod 644 /usr/local/${TARGET}/lib/$mlibdir/crt0.o || exit 1
	done

	cd $BASEDIR
}

#############################################################
#
# tar up everthing we have built
#

build_tar_file()
{
	# set -x
	cd /

	#
	# strip the binaries
	#
	strip /usr/local/bin/genromfs > /dev/null 2>&1 || true
	strip /usr/local/bin/${TARGET}-* > /dev/null 2>&1 || true
	strip /usr/local/${TARGET}/bin/* > /dev/null 2>&1 || true
	strip /usr/local/lib/gcc-lib/${TARGET}/2.95.3/* > /dev/null 2>&1 || true

	#
	# tar it all up
	#
	tar cvzf $BASEDIR/${TARGET}-tools-`date +%Y%m%d`.tar.gz \
		./usr/local/${TARGET} \
		./usr/local/lib/gcc-lib/${TARGET} \
		./usr/local/include/g++-3 \
		./usr/local/bin/${TARGET}-* \
		./usr/local/bin/genromfs \
		./usr/local/bin/elf2flt

	cd $BASEDIR
}

#############################################################
#
# cleanup
#

clean_all()
{
	echo "Cleaning everything up..."

	rm -f $BASEDIR/STAGE*
	rm -rf binutils-2.10
	rm -rf gcc-2.95.3
	rm -rf genromfs-0.3.1
	rm -rf elf2flt-20010606
	rm -rf ${TARGET}-gcc
	rm -rf ${TARGET}-binutils
}

#############################################################
#
# main - put everything together in order.
#
# Some setup
#

case ${TARGET} in
m68k*) _CPU=m68k ;;
arm*)  _CPU=arm  ;;
esac

#
# first check some args
#

case "$1" in
build)
	rm -f $BASEDIR/STAGE*
	;;
continue)
	# do nothing here
	;;
uclibc)
	build_uclibc_mlib
	exit 0
	;;
tar)
	build_tar_file
	exit 0
	;;
clean)
	clean_all
	exit 0
	;;
*)
	echo "usage: $0 (build|continue|clean)" >&2
	echo ""
	echo "       build    = build everything from scratch."
	echo "       continue = continue building from last error."
	echo "       uclibc   = build multilib versions of uClibc (if wanted)."
	echo "       tar      = build for distribution of binaries."
	echo "       clean    = clean all temporary files etc."
	exit 1
	;;
esac

#
# You have to root for this one
#

if id | grep root > /dev/null
then
	echo "Good, you are root :-)"
else
	echo "Bad,  you are not root."
	exit 1
fi

# set -x	# debug script
set -e		# if anything fails, stop

stage1
stage2
stage3
stage4
stage5
stage6
stage7
stage8

echo "--------------------------------------------------------"
echo "Build successful !"
echo "--------------------------------------------------------"

#############################################################

