#! /bin/bash
#
# Script from Thiemo Seufert to build a toolchain for cross-building
# Modifications by Frans Pop:
# - Add workarounds for version skew in archive in version()
# - Also build gcc-4.3: required for gcc-*-base package
# - Define LD_LIBRARY_PATH to work around #453267
# - Only install gcc as it's all I need
#   (libstdc++6-<ver>-dbg seems uninstallable as not all its deps are built)

set -e

# target architecture
DEBARCH=${DEBARCH:="arm"}

# mirror for both binary and source packages
MIRROR=${MIRROR:="http://ftp.nl.debian.org/debian"}
#MIRROR=${MIRROR:="http://hattusa/debian"}

ROOTCMD=sudo
#ROOTCMD=

DEF_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
MY_LD_LIBRARY_PATH=/lib:/usr/lib:/lib32:/usr/lib32:/lib64:/usr/lib64
MY_LD_LIBRARY_PATH=$MY_LD_LIBRARY_PATH:/$DEBARCH-linux-gnu/lib
MY_LD_LIBRARY_PATH=$MY_LD_LIBRARY_PATH:/usr/$DEBARCH-linux-gnu/lib
MY_LD_LIBRARY_PATH=$MY_LD_LIBRARY_PATH:/$DEBARCH-linux-gnu/lib32
MY_LD_LIBRARY_PATH=$MY_LD_LIBRARY_PATH:/usr/$DEBARCH-linux-gnu/lib32
MY_LD_LIBRARY_PATH=$MY_LD_LIBRARY_PATH:/$DEBARCH-linux-gnu/lib64
MY_LD_LIBRARY_PATH=$MY_LD_LIBRARY_PATH:/usr/$DEBARCH-linux-gnu/lib64

#----------------------------------------------------------------------

# host architecture
HOSTARCH=$(dpkg-architecture -qDEB_HOST_ARCH)

#----------------------------------------------------------------------
# Useful shell functions

# check build-deps
checkinstalled () {
	while [ -n "$1" ]; do
		dpkg -l "$1" |grep -q "^ii" || {
			echo "$1 is not installed."
			exit 1
		}
		shift
	done
}

# find full version string: version <binarypackage>
# XXX: What about epochs?
version () {
	#if [ $1 = libgcc1 ]; then echo 4.3.0-1
	#elif [ $1 = gcc-4.2 ]; then echo 4.2.3-3
	#else
		grep-aptavail -PX $1 -s Version: -n |sed 's/[0-9]\+://'
	#fi
}

srcver () {
	local x=$(apt-cache showsrc $1 |grep ^Version: |sed 's/^Version: //' |sort -bru |head -1)
	echo $(echo $x |sed 's/\(.*\)\(-[0-9]*$\)/\1/')
}

# find upstream version string: upstreamversion <binarypackage>
upstreamversion () {
	echo $(version $1 |sed 's/\(.*\)\(-[0-9]*$\)/\1/')
}

# find debian revision string: debianrevision <binarypackage>
debianrevision () {
	echo $(version $1 |sed 's/\(.*-\)\([0-9]*$\)/\2/')
}

# find sourcepackage: sourcepackage <binarypackage>
sourcepackage () {
	local x=$(grep-status -PX $1 -s Source: -n | sed 's/\s.*//')
	local y=$1
	echo ${x:=$y}
}

# find source directory: sourcedir <sourcepackage>
sourcedir () {
	echo $1-$(srcver $1)
}

# make cross all package: make-cross-package <binarypackage>
make-cross-package () {
	local _version=$(version $1)
	local _sourcepkg=$(sourcepackage $1)
	local _hashdir=$(echo ${_sourcepkg} |sed 's/^\(lib.\|.\)\(.*\)/\1/')
	local _mirror="${MIRROR}/pool/main/${_hashdir}/${_sourcepkg}"
	local _origfile="${1}_${_version}_all.deb"
	local _crossfile="${1}-${DEBARCH}-cross_${_version}_all.deb"

	[ -f ${_origfile} ] || wget -nv -r -nd -N ${_mirror}/${_origfile}
	[ -f ${_crossfile} ] || dpkg-cross -A -a ${DEBARCH} -b ${_origfile}
	$ROOTCMD dpkg -i ${_crossfile}
}

# make cross $arch package: make-cross-arch-package <binarypackage>
make-cross-arch-package () {
	local _version=$(version $1)
	local _sourcepkg=$(sourcepackage $1)
	local _hashdir=$(echo ${_sourcepkg} |sed 's/^\(lib.\|.\)\(.*\)/\1/')
	local _mirror="${MIRROR}/pool/main/${_hashdir}/${_sourcepkg}"
	local _origfile="${1}_${_version}_${DEBARCH}.deb"
	local _crossfile="${1}-${DEBARCH}-cross_${_version}_all.deb"

	[ -f ${_origfile} ] || wget -nv -r -nd -N ${_mirror}/${_origfile}
	[ -f ${_crossfile} ] || dpkg-cross -a ${DEBARCH} -b ${_origfile}
	$ROOTCMD dpkg --force-depends -i ${_crossfile}
}


# build and install libraries needed to build the cross toolchain
build-libs () {
#	make-cross-arch-package linux-kernel-headers
	make-cross-arch-package linux-libc-dev
	make-cross-package tzdata
	make-cross-arch-package libc6
	make-cross-arch-package libc6-dev
	make-cross-arch-package libgcc1
}


# build and install cross binutils
build-binutils () {
	local _upver=$(upstreamversion binutils)
	local _version=$(version binutils)
	local _dir=$(sourcedir binutils)

	if [ ! -d binutils-${_version} ]; then
		rm -rf $_dir
		apt-get source binutils
		pushd $_dir
		echo "${DEBARCH}" > debian/target
		popd
		mv $_dir binutils-${_version}
	fi
	pushd binutils-${_version}
#	dpkg-buildpackage -us -uc -B -rfakeroot
	TARGET=${DEBARCH} fakeroot debian/rules binary-cross
	popd

	$ROOTCMD dpkg -i \
		binutils-${DEBARCH}-linux-gnu_${_version}_${HOSTARCH}.deb
}


# build cross gcc versions: build-gcc <majorversion>
build-gcc () {
	local _upver=$(upstreamversion gcc-$1)
	local _version=$(version gcc-$1)
	local _dir=$(sourcedir gcc-$1)

	if [ ! -d gcc-$1-${_version} ]; then
		rm -rf $_dir
		apt-get source gcc-$1
		pushd $_dir
		echo "${DEBARCH}" > debian/target
		fakeroot debian/rules control
		popd
		mv $_dir gcc-$1-${_version}
	fi
	pushd gcc-$1-${_version}
	export LD_LIBRARY_PATH=$MY_LD_LIBRARY_PATH
	dpkg-buildpackage -us -uc -B -rfakeroot
	export LD_LIBRARY_PATH=$DEF_LD_LIBRARY_PATH
	popd
}

# install cross gcc versions: install-gcc <majorversion>
install-gcc () {
	local _version=$(version gcc-$1)
#	local _filelist="cpp-$1-${DEBARCH}-linux-gnu_${_version}_${HOSTARCH}.deb \
# g++-$1-${DEBARCH}-linux-gnu_${_version}_${HOSTARCH}.deb \
# gcc-$1-${DEBARCH}-linux-gnu_${_version}_${HOSTARCH}.deb \
# libstdc++6-$1-dbg-${DEBARCH}-cross_${_version}_all.deb \
# libstdc++6-$1-dev-${DEBARCH}-cross_${_version}_all.deb \
# libstdc++6-$1-pic-${DEBARCH}-cross_${_version}_all.deb \
# libstdc++6-${DEBARCH}-cross_${_version}_all.deb"
	local _filelist="gcc-$1-${DEBARCH}-linux-gnu_${_version}_${HOSTARCH}.deb"


	if [ -f libgcc1-${DEBARCH}-cross_${_version}_all.deb ]; then
		_filelist="$_filelist libgcc1-${DEBARCH}-cross_${_version}_all.deb"
	fi
	if [ -f gcc-$1-${DEBARCH}-linux-gnu-base_${_version}_${HOSTARCH}.deb ]; then
		_filelist="$_filelist gcc-$1-${DEBARCH}-linux-gnu-base_${_version}_${HOSTARCH}.deb"
	fi
	$ROOTCMD dpkg -i $_filelist
}

# build and install cross gcc-4.0
build-gcc-4.0 () {
	build-gcc 4.0
#	install-gcc 4.0
}

# build cross gcc-4.1
build-gcc-4.1 () {
	build-gcc 4.1
#	install-gcc 4.1
}

# build cross gcc-4.2
build-gcc-4.2 () {
	build-gcc 4.2
#	install-gcc 4.2
}

# build cross gcc-4.3
build-gcc-4.3 () {
	build-gcc 4.3
	install-gcc 4.3
}

# build cross gcc-snapshot
build-gcc-snapshot () {
	# Hack, hack.
	pushd /usr/lib
	$ROOTCMD ln -sf /usr gcc-snapshot
	popd

	build-gcc snapshot
#	install-gcc snapshot
}

#----------------------------------------------------------------------
# Finally, do the work.

# sanity check build environment
checkinstalled dpkg-cross

# dpkg-cross version check
if [[ "1.17" > $(dpkg-cross --help 2>&1 |awk '{print $3; exit;}') ]]; then
	echo "dpkg-cross is too old."
	exit 1
fi

# make everything
build-libs
build-binutils
#build-gcc-4.0
build-gcc-4.1
build-gcc-4.2
build-gcc-4.3
build-gcc-snapshot
