########################################################################
#
#			mini-crosstool.sh
#
#  This script is a wickedly-condensed version of Dan Kegel's "crosstool"
# script for creating a cross-compile toolchain.  (Dan's full version
# can be found at http://www.kegel.com/crosstool.)
#
#  This shorter version does a lot of simplification, makes a lot of
# assumptions and does virtually no error checking (kind of like a lot
# of production software).  In addition, it tries as much as possible
# to follow the standards in Karim Yaghmour's book in terms of naming
# conventions.  This script is primarily for teaching purposes to show
# you the general structure of building a toolchain, after which you
# can move on up to the real "crosstool".
#
#  Some of the assumptions made here WRT to "crosstool":
#
#  1) You already have all of the .bz2-format tarballs for the
#	components you're going to use on your system (most of them
#	are available at ftp.gnu.org).
#  2) You're going to use sanitized kernel headers and not a full
#	kernel source tree.
#  3) You're going to use the SYSROOT option for configures.
#  4) You're going to use leading-edge components for your build (this
#	script doesn't make any effort to support legacy software.
#	Sorry.)
#
#  One final note:  each step in the build process is mostly independent
# from the other steps, so you can see *exactly* what it takes to do each
# phase in the build process.  This means it should technically be 
# possible to break this script apart and run each step separately with
# only a little work.  (It also means that I try not to do any processing
# until that processing is actually necessary for that stage.)
#
#  Comments/feedback/corrections to rpjday (at) mindspring (dot) com.
#
#######################################################################

#######################################################################
#  Utility functions.
#######################################################################

unpack_and_patch_all() {
	unpack_and_patch linux-libc-headers ${HEADERS_VERSION}
	unpack_and_patch binutils ${BINUTILS_VERSION}
	unpack_and_patch glibc ${GLIBC_VERSION}
	unpack_and_patch gcc ${GCC_VERSION}
}

unpack_and_patch() {
	SW=$1
	VERSION=$2
	FULL="${SW}-${VERSION}"
	echo "Unpacking ${FULL}."

	rm -rf ${UNPACK_DIR}/${FULL}
	tar ${VERBOSE_TAR}xjf ${TARBALLS_DIR}/${FULL}.tar.bz2 \
		-C ${UNPACK_DIR}

	echo "Patching ${FULL}."
	for PFILE in ${PATCHES_DIR}/${FULL}/*.patch ; do
		echo "Processing patch file ${PFILE}."
		patch \
			-d ${UNPACK_DIR}/${FULL} \
			--fuzz=1 \
			-p 1 \
			--force 	< ${PFILE}
	done
}
	
################################################################
#  Architecture settings.
################################################################

HOST=i686-pc-linux-gnu
TARGET=sh3-unknown-linux-gnu
ARCH=sh		# based on kernel directory include/asm-${ARCH}

################################################################
#  Software versions to use (based on downloaded tarballs).
################################################################

HEADERS_VERSION=2.6.12.0
BINUTILS_VERSION=2.16.1
GLIBC_VERSION=20051024
GCC_VERSION=4.1-20051029

################################################################
#  Directory locations to get stuff.
################################################################

TARBALLS_DIR=~/ct/tarballs
PATCHES_DIR=~/ct/patches

################################################################
#  Directory locations to put stuff.
################################################################
#
#  Directory layout:
#
#   ${UNPACK_DIR}/		(shareable across projects)
#     linux-libc-headers-??/
#     binutils-??/
#     glibc-??/
#     gcc-??/
#
#   ${RESULTS_DIR}/		(for *all* results if you want)
#     ${PROJECT}/		${PRJROOT}
#	build/			${BUILD_DIR}
# 	  build-binutils/
#	  build-glibc-headers
#	  ...
#	tools/			${PREFIX}
#	  bin/			(actual cross-compile commands)
#	  ${TARGET}/		${TARGET_PREFIX}
#	    sys-root/		${SYSROOT_DIR}
#	      usr/include/	${HEADERS_DIR}
#      

UNPACK_DIR=~/unpack			# unpacked and patched sources
RESULTS_DIR=~/results			# *all* toolchains go here
PROJECT=sh3				# give each build a "name"
PRJROOT=${RESULTS_DIR}/${PROJECT}
BUILD_DIR=${PRJROOT}/build
PREFIX=${PRJROOT}/tools
TARGET_PREFIX=${PREFIX}/${TARGET}
SYSROOT_DIR=${TARGET_PREFIX}/sys-root
HEADERS_DIR=${SYSROOT_DIR}/usr/include

PATH=${PREFIX}/bin:${PATH}

################################################################
#  Build/configuration variables (eg., SH3, little-endian).
################################################################

TARGET_CFLAGS="-O -m3 -ml"
GLIBC_CONFIGPARMS="no-z-defs=yes"
GLIBC_EXTRA_CONFIG="--without-fp"

################################################################
#  Variables to unset before going any further.
################################################################

unset CFLAGS
unset CXXFLAGS
unset LD_LIBRARY_PATH

################################################################
#  And now, to work ...
################################################################

rm -rf ${UNPACK_DIR} ; 		mkdir -p ${UNPACK_DIR}
unpack_and_patch_all

rm -rf ${BUILD_DIR} ;		mkdir -p ${BUILD_DIR}
rm -rf ${PREFIX} ;		mkdir -p ${PREFIX}

######################################################################
#  
#  1.	Install the appropriate header files into sys-root, based on
#	the architecture.
#
######################################################################

do_kernel_headers() {
	rm -rf ${HEADERS_DIR}
	mkdir -p ${HEADERS_DIR}

	HEADERS_SRC_DIR=${UNPACK_DIR}/linux-libc-headers-${HEADERS_VERSION}
	cp -r ${HEADERS_SRC_DIR}/include/linux ${HEADERS_DIR}
	cp -r ${HEADERS_SRC_DIR}/include/asm-${ARCH} ${HEADERS_DIR}/asm
}

do_kernel_headers

######################################################################
#  
#  2.	Configure, build and install the binutils.
#
######################################################################

do_binutils() {
	BINUTILS_SRC_DIR=${UNPACK_DIR}/binutils-${BINUTILS_VERSION}

	rm -rf ${BUILD_DIR}/build-binutils
	mkdir -p ${BUILD_DIR}/build-binutils

	cd ${BUILD_DIR}/build-binutils
	${BINUTILS_SRC_DIR}/configure \
		--host=${HOST} \
		--target=${TARGET} \
		--prefix=${PREFIX} \
		--with-sysroot=${SYSROOT_DIR} \
		--disable-nls \
		${BINUTILS_EXTRA_CONFIG}
	make all install
}

do_binutils

PATH=${PREFIX}/bin:$PATH

######################################################################
#  
#  3.	Configure, build and install glibc headers.
#
######################################################################

do_glibc_headers() {
	GLIBC_SRC_DIR=${UNPACK_DIR}/glibc-${GLIBC_VERSION}

	rm -rf ${BUILD_DIR}/build-glibc-headers
	mkdir -p ${BUILD_DIR}/build-glibc-headers

	cd ${BUILD_DIR}/build-glibc-headers

    	CC=gcc \
	${GLIBC_SRC_DIR}/configure \
		--prefix=/usr \
		--build=${HOST} \
		--host=${TARGET} \
		--without-cvs \
		--enable-add-ons=nptl \
		--with-tls \
		--with-headers=${SYSROOT_DIR}/usr/include

	make \
		cross_compiling=yes \
		install_root=${SYSROOT_DIR} \
		CFLAGS=-DBOOTSTRAP_GCC \
		install-headers
}

do_glibc_headers

######################################################################
#  
#  4.	Build the bootstrap gcc compiler, and install it in the build
# 	directory in gcc-core-prefix/. 
#
######################################################################

CORE_PREFIX=${BUILD_DIR}/gcc-core-prefix
PATH=${CORE_PREFIX}/bin:${PATH}

do_bootstrap_gcc() {

	GCC_SRC_DIR=${UNPACK_DIR}/gcc-${GCC_VERSION}

	rm -rf ${BUILD_DIR}/build-gcc-core
	mkdir -p ${BUILD_DIR}/build-gcc-core

	rm -rf ${CORE_PREFIX}
	mkdir -p ${CORE_PREFIX}

	#
	#  Fix some header issues left over from the previous step -- some 
	# header files that have to be manually installed.  All of that is
	# being done *here* since it's related to *this* step, not the previous
	# one.
	#

	GLIBC_HEADERS_DIR=${BUILD_DIR}/build-glibc-headers
	cp ${GLIBC_HEADERS_DIR}/bits/stdio_lim.h ${HEADERS_DIR}/bits
	touch ${HEADERS_DIR}/gnu/stubs.h

	#
	#  Copy cross-compiling binutils utilities.  (Can this be avoided by
	# a judicious use of PATH?)
	#

	mkdir -p ${CORE_PREFIX}/${TARGET}/bin
	for util in ar as ld strip ; do
		cp ${PREFIX}/${TARGET}/bin/${util} ${CORE_PREFIX}/${TARGET}/bin
	done

	cd ${BUILD_DIR}/build-gcc-core
	${GCC_SRC_DIR}/configure \
		--host=${HOST} \
		--target=${TARGET} \
		--prefix=${CORE_PREFIX} \
		--with-local-prefix=${SYSROOT_DIR} \
		--with-sysroot=${SYSROOT_DIR} \
		--disable-multilib \
		--with-newlib \
		--with-tls \
		--disable-nls \
		--disable-shared \
		--enable-threads=yes \
		--enable-symvers=gnu \
		--enable-__cxa_atexit \
		--enable-languages=c

	make all-gcc install-gcc
}

do_bootstrap_gcc

######################################################################
#  
#  5.	glibc, built with NPTL only, no linuxthreads.
#
######################################################################

do_glibc() {
	
	GLIBC_SRC_DIR=${UNPACK_DIR}/glibc-${GLIBC_VERSION}

	rm -rf ${BUILD_DIR}/build-glibc
	mkdir -p ${BUILD_DIR}/build-glibc

	cd ${BUILD_DIR}/build-glibc

	echo ${GLIBC_CONFIGPARMS} > configparms

	BUILD_CC=gcc \
	CFLAGS="${TARGET_CFLAGS} ${EXTRA_TARGET_CFLAGS}" \
	CC="${TARGET}-gcc ${GLIBC_EXTRA_CC_ARGS}" \
	AR=${TARGET}-ar \
	RANLIB=${TARGET}-ranlib \
	${GLIBC_SRC_DIR}/configure \
		--build=${HOST} \
		--host=${TARGET} \
		${GLIBC_EXTRA_CONFIG} \
		--prefix=/usr \
		--enable-shared \
		--enable-kernel=2.6.0 \
		--disable-profile \
		--disable-debug \
		--without-cvs \
		--with-tls \
		--with-headers=${HEADERS_DIR} \
		--enable-add-ons=nptl

	make \
		LD=${TARGET}-ld  \
		RANLIB=${TARGET}-ranlib \
		lib

	# make \
		# install-root=${SYSROOT_DIR} \
		# install-lib-all install-headers
}

do_glibc
