#!/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)
#    gcc-2.95.2.tar.bz2         in current directory (or a gzipped version)
#    gcc-2.95.2-elfPICgot.patch in current directory
#    elf2flt-20010222.tgz       in current directory
#    genromfs-0.3.1.tar.bz2     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
#
#############################################################
#
# EDIT these to suit your system and source locations
#

BASEDIR="`pwd`"
UCLIBC="$BASEDIR/uClibc"
KERNEL="$BASEDIR/uClinux-2.0.x"

#############################################################
#
# 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) tar xIf "$i" ;;
		*.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.2
	rm -rf /usr/local/m68k-elf-*
	rm -rf /usr/local/lib/gcc-lib/m68k-elf-*
	rm -rf /usr/local/bin/m68k-elf-*
#
#	extract binutils, gcc and anything else we know about
#
	extract binutils-2.10.*
	extract gcc-2.95.2.*
#
#	apply any patches
#
	patch -p0 < gcc-2.95.2-elfPICgot.patch
	cd $BASEDIR
	mark 1
}

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

stage2()
{
	schk 2 || return 0

	rm -rf m68k-elf-binutils
	mkdir m68k-elf-binutils
	cd m68k-elf-binutils
	../binutils-2.10/configure --target=m68k-elf
	make
	make install
	cd $BASEDIR
	mark 2
}

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

stage3()
{
	schk 3 || return 0

	rm -rf /usr/local/m68k-elf/sys-include
	rm -f ${UCLIBC}/include/asm
	cp -r ${UCLIBC}/include /usr/local/m68k-elf/sys-include
	rm -rf /usr/local/m68k-elf/sys-include/asm
	rm -rf /usr/local/m68k-elf/sys-include/bits
	cp -r ${UCLIBC}/sysdeps/linux/m68k/bits \
					/usr/local/m68k-elf/sys-include/.
	rm -rf /usr/local/m68k-elf/sys-include/linux
	cp -r ${KERNEL}/include/linux /usr/local/m68k-elf/sys-include/linux
	touch /usr/local/m68k-elf/sys-include/linux/autoconf.h
	cp -r ${KERNEL}/include/asm-m68knommu \
					/usr/local/m68k-elf/sys-include/.

	# 2.4 headers also need this
	cp -r ${KERNEL}/include/asm-m68k /usr/local/m68k-elf/sys-include/.

	ln -s /usr/local/m68k-elf/sys-include/asm-m68knommu \
					/usr/local/m68k-elf/sys-include/asm

	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 m68k-elf-gcc
	mkdir m68k-elf-gcc
	cd m68k-elf-gcc
	../gcc-2.95.2/configure --enable-languages=c --target=m68k-elf
	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}?" \
						< Config.m68k > Config
	rm -f ${KERNEL}/include/asm
	ln -s ${KERNEL}/include/asm-m68knommu ${KERNEL}/include/asm
	make clean
	make

	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}/libc.a /usr/local/m68k-elf/lib/.
	cp ${UCLIBC}/crt0.o /usr/local/m68k-elf/lib/.

	rm -rf m68k-elf-gcc
	mkdir m68k-elf-gcc
	cd m68k-elf-gcc
	../gcc-2.95.2/configure --enable-languages=c,c++ --target=m68k-elf \
			--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 m68k-elf -name $lib.a -print | while read file
		do
			MLIB=`expr $file : "m68k-elf\(.*\)"`
			MLIB=`expr $MLIB : "\(.*\)/[^/]*/$lib.a"`
			echo "  $MLIB/$lib.a"
			cp $file /usr/local/m68k-elf/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/m68k-elf/lib/libc.a
	rm -f /usr/local/m68k-elf/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
	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-20010222
	extract elf2flt-20010222*
	cd elf2flt-20010222
	mv Makefile Makefile.tmp
	sed 's?^[ 	]*PREFIX.*=.*$?PREFIX=../m68k-elf-binutils?' \
						< Makefile.tmp > Makefile
	cp $KERNEL/include/linux/flat.h .
	make
	cp elf2flt /usr/local/bin/.
	chmod 755 /usr/local/bin/elf2flt
	[ -f /usr/local/bin/m68k-elf-ld.real ] || \
		cp /usr/local/bin/m68k-elf-ld /usr/local/bin/m68k-elf-ld.real
	[ -f /usr/local/m68k-elf/bin/ld.real ] || \
		cp /usr/local/m68k-elf/bin/ld /usr/local/m68k-elf/bin/ld.real
	cp ld-elf2flt /usr/local/bin/m68k-elf-ld
	cp ld-elf2flt /usr/local/m68k-elf/bin/ld
	cp elf2flt.ld /usr/local/m68k-elf/lib/.

	cd $BASEDIR
	mark 8
}

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

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

	ALL_BUILDS="-Wa,--bitwise-or"

	while read mlibdir cflags
	do
		sed -e "s?^[ 	]*KERNEL_SOURCE[ 	]*=.*?KERNEL_SOURCE=${KERNEL}?g" \
		    -e "s?^[ 	]*ARCH_CFLAGS[ 	]*=.*?ARCH_CFLAGS=${cflags}?g" \
		    < Config.m68k > Config
		make clean
		make

		cp libc.a /usr/local/m68k-elf/lib/$mlibdir/libc.a || exit 1
		cp crt0.o /usr/local/m68k-elf/lib/$mlibdir/crt0.o || exit 1

		chmod 644 /usr/local/m68k-elf/lib/$mlibdir/libc.a || exit 1
		chmod 644 /usr/local/m68k-elf/lib/$mlibdir/crt0.o || exit 1
	done <<!EOF
		.                    $ALL_BUILDS
		msoft-float          $ALL_BUILDS -msoft-float
		m5200                $ALL_BUILDS -m5200 -Wa,-m5200
		m5200/msep-data      $ALL_BUILDS -m5200 -Wa,-m5200 -msep-data
		m68000               $ALL_BUILDS -m68000
		m68000/msep-data     $ALL_BUILDS -m68000 -msep-data
		mcpu32               $ALL_BUILDS -mcpu32
		mcpu32/msep-data     $ALL_BUILDS -mcpu32 -msep-data
!EOF

	cd $BASEDIR
}

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

build_tar_file()
{
	# set -x
	cd /

	tar cvzf m68k-elf-tools.tar.gz \
		./usr/local/m68k-elf \
		./usr/local/lib/gcc-lib/m68k-elf \
		./usr/local/bin/m68k-elf-* \
		./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.2
	rm -rf genromfs-0.3.1
	rm -rf elf2flt-20010130
	rm -rf m68k-elf-gcc
	rm -rf m68k-elf-binutils
}

#############################################################
#
# main - put everything together in order.
#
# 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 sidtribution 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 "--------------------------------------------------------"

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

