#!/bin/bash
# $Header: /var/emdebian/svn/tools/buildcross/trunk/buildcross,v 0.1 2006/10/04 01:10:03 zumbi Exp $

# Distributed under the terms of the GNU General Public License v2

# Copyright 1999-2007 Emdebian
# Originally (c) 2006 Thiemo Seufer
# Modified by Hector Oron

# Do not forget	: $ chmod a+x buildcross

# TODO:
#	http://wiki.debian.org/EmdebianToolchain
#


# Latest version of this file can be downloaded from:
#       http://buildd.emdebian.org/repos/tools/buildcross/trunk/
# but it might need some fix for you to work.
# ----------------------------------------------------------------------
# References

source conf_vars.sh

PKG=$1
ARCH=$2

if [ ${ARCH} == "armel" ]; then
	# MIRROR=${MIRROR:="http://armel-debs.applieddata.net/debian/"}
	MIRROR=${MIRROR:="http://kfreebsd-gnu.debian.net/debian/"}
	# MIRROR=${MIRROR:="http://www.gtlib.gatech.edu/pub/gnuab/debian/"}

fi

INSTALLPKGSN=NO

echo "W: buildcross triggered"

if [ ! -d $LOGPATH ]; then
	mkdir -p $LOGPATH
fi
# Sets build as failed
echo 1 > $LOGPATH/$HOST-$ARCH-$PKG.log

if [ "" = "${1}" ]; then
   echo -e "Usage: \n\tbuildcross [all || libs || gdb || binutils || 3.3 || 3.4 || 4.0 || 4.1] [arch] [suite] [mirror]\n\ti.e.: ./buildcross 4.1 arm unstable http://ftp.uk.debian.org/debian\n"
  exit 1
elif [ "all" = "${1}" ]; then
  BUILDGCC="all"
  GCCVER=${GCCVER:="4.1"}
elif [ "libs" = "${1}" ]; then
  BUILDGCC="libs"
  GCCVER=${GCCVER:="4.2"}
elif [ "binutils" = "${1}" ]; then
  BUILDGCC="binutils"
  GCCVER=${GCCVER:="4.2"}
elif [ "gdb" = "${1}" ]; then
  BUILDGCC="gdb"
  GCCVER=${GCCVER:="4.2"}
else
  BUILDGCC=${1}
  GCCVER=${BUILDGCC}
fi


if [ "" != "$2" ]; then
  ARCHLIST=$2
fi

if [ "" != "$3" ]; then
  SUITE=$3
fi

if [ "" != "$4" ]; then
  MIRROR=$4
fi


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

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

sanitycheck () {
	# sanity check build environment
	echo "Sanity check..."
	checkinstalled dpkg-cross
#	checkinstalled wget
	#checkinstalled dctrl-tools 
	checkinstalled grep-dctrl 
	checkinstalled sudo
	checkinstalled fakeroot
	checkinstalled dpatch
	checkinstalled patchutils
	checkinstalled tar
	checkinstalled bzip2
	checkinstalled lsb-release
	checkinstalled autoconf
	checkinstalled autoconf2.13
	checkinstalled automake1.9
	checkinstalled libtool
	checkinstalled autogen
	checkinstalled gawk
	checkinstalled bison
	checkinstalled flex
	checkinstalled realpath
	checkinstalled texinfo
	checkinstalled devscripts
	checkinstalled reprepro
	checkinstalled less 
	checkinstalled coreutils
	checkinstalled automake1.4
	checkinstalled automake1.7
	checkinstalled dh-make
	checkinstalled debhelper
	checkinstalled apt-cross
	checkinstalled emdebian-tools
	
	# Following lines are gdb dependencies
	checkinstalled tetex-bin 
	checkinstalled libncurses5-dev 
	checkinstalled libreadline5-dev 
	#checkinstalled gcj 
	checkinstalled gobjc 
	checkinstalled cdbs  
 	checkinstalled quilt 
 	checkinstalled type-handling
	echo "Sanity check passed."
}

#----------------------------------------------------------------------
# find full version string: version <binarypackage>
# XXX: What about epochs?
version () {
	rmadison -a ${ARCH} ${1} | grep ${SUITE} | cut -d'|' -f2 | tr -d ' ' | cut -d'+' -f1 |sed 's/1://'|tail -n 1
}

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

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


# make cross ${ARCH} package: make-cross-package <binarypackage>
make-cross-package () {
	local _version=$(version $1)
	if [ $1 = "linux-kernel-headers" ] ; then
		if [ -f ${1}_${_version}_${ARCH}.deb ] || [ -f ${1}-${ARCH}-cross-_${_version}_all.deb ]; then
			echo "I am not building $1 because it is latest version already been built." 
		else
			apt-cross -a ${ARCH} -S ${SUITE} -m ${MIRROR}  -b $1 
		fi
	
	else
		if [ -f ${1}_${_version}_${ARCH}.deb ] || [ -f ${1}-${ARCH}-cross-_${_version}_all.deb ]; then
			echo "I am not building $1 because it is latest version already been built." 
		else
			apt-cross -v -v -a ${ARCH} -S ${SUITE} -m ${MIRROR}   -b $1 
			apt-cross -v -v -a ${ARCH} -S ${SUITE} -m ${MIRROR}   -i $1 
			apt-cross -v -v -a ${ARCH} -S ${SUITE} -m ${MIRROR}   -i $1 
		fi
	fi
	rm -rf ${1}_${_version}_${ARCH}.deb
		
}


# build and install libraries needed to build the cross toolchain
build-libs () {
#	make-cross-package linux-kernel-headers
	make-cross-package linux-libc-dev
	make-cross-package gcc-4.2-base
#	make-cross-arch-package gdb
        if [ ${ARCH} = "alpha" ] || [ ${ARCH} = "ia64" ] ; then
                make-cross-package libc6.1 
                make-cross-package libc6.1-dev 
	else
		make-cross-package libc6
		make-cross-package libc6-dev
	fi
	# EXPERIMENTAL: Commented two lines
	#make-cross-package libdb1-compat
	#make-cross-package libatomic-ops-dev
	#// GCC-4.1 build dependency
	if [ ${ARCH} = "ia64" ] ; then
		#make-cross-package libdb1-compat
		make-cross-package libatomic-ops-dev
		make-cross-package libunwind7
		make-cross-package libunwind7-dev
	fi
	#// y it is used to tell glibc hashdir
	if [ ${ARCH} = "powerpc" ]; then
		make-cross-package libc6-ppc64
#		make-cross-package lib64gcc1 
		make-cross-package libc6-dev-ppc64
#		make-cross-package libc6-powerpc
#		make-cross-package libc6-dev-powerpc
	fi
	if [ ${ARCH} = "i386" ]; then
	# EXPERIMENTAL: Commented two lines
		make-cross-package libc6-amd64
		make-cross-package lib64gcc1 
		make-cross-package libc6-dev-amd64
	fi
	if [ ${ARCH} = "sparc" ]; then
		make-cross-package libc6-sparc64
#		make-cross-package lib64gcc1 
		make-cross-package libc6-dev-sparc64
	fi
	if [ ${ARCH} = "s390" ]; then
		make-cross-package libc6-s390x
#		make-cross-package lib64gcc1 
		make-cross-package libc6-dev-s390x
	fi
#        if [ ${ARCH} = "hppa" ]; then
#		#// Currently, there is 4.0.3-8: hppa for libgcc2
#                make-cross-package libgcc4 n  
#        fi     

	#// Will be deprecated ?
	#// FIXME: Function make-cross-package won't find correct path, it is set to gcc-4.1 path
	if [ ${ARCH} = "hppa" ] && [ ${GCCVER} = "4.0" ]; then
		make-cross-package libgcc2
	fi
	if [ ${ARCH} = "hppa" ] && [ ${GCCVER} = "4.1" ]; then
		make-cross-package libgcc4 
	fi
	if [ ${ARCH} = "m68k" ] ; then
		make-cross-package libgcc2 
	else
		make-cross-package libgcc1
	fi

	#// Will be deprecated ?
	#// FIXME: Function make-cross-package won't find correct path, it is set to gcc-4.1 path
	if [ ${ARCH} = "m68k" ] && [ ${GCCVER} = "3.3" ]; then
		make-cross-package libgcc1 
	fi

	#// Added lib32gcc1 for testing
	if [ ${ARCH} = "amd64" ] ; then
		make-cross-package lib32gcc1 
	fi
	if [ ${ARCH} = "ia64" ] ; then
		make-cross-package lib32gcc1 
	fi
	

#	make-cross-package uclibc-toolchain
#	make-cross-package libuclibc0
#	make-cross-package libuclibc-dev
}

# applies patches 
apply_patch () {
	patch -p1 < ../../patches/$1
}
#// End patches

# build and install cross gdb
build-gdb () {
	local _upver=$(upstreamversion gdb)
	local _version=$(version gdb)
	local _dir=$(sourcedir gdb)
	local _debarch=${ARCH}

	if [ ! -d gdb-${_version} ]; then
		rm -rf $_dir
		apt-get source gdb
		# pushd $_dir
		# echo "${ARCH}" > debian/target
		#// Workarround patches
		# apply_patch binutils-cross-2.17.patch
		# popd
		mv $_dir binutils-${_version}
	fi
	pushd gdb-${_version}
#	dpkg-buildpackage -us -uc -B -rfakeroot
	TARGET=${ARCH} dpkg-buildpackage -rfakeroot -uc -us
	popd

#	$ROOTCMD dpkg -i gdb-${_debarch}-linux-gnu_${_version}_${HOSTARCH}.deb >> dpkg.log

	#// Do clean up
	rm -rf *.gz *.bz2 *.dsc *.tgz *.tar *.changes binutils-${_version}/ 

}

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

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

	$ROOTCMD dpkg -i binutils-*-linux-gnu*.deb >> dpkg.log

	#// Do clean up
	rm -rf *.gz *.bz2 *.dsc *.tgz *.tar *.changes binutils-${_version}/ 

}


# 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 "${ARCH}" > debian/target

#		# Workarround for GCC4.1
#		if [ ${GCCVER} = "4.1" ]; then
#			# apply_patch arm-libffi-maillist.patch
#		fi

		# Workaround for GCC4.2
		if [ ${1} = "4.2" ]; then
			apply_patch reverse_cross_fix.patch
			apply_patch gcc42-amd64-i386.patch
		fi
		# Patch gcc-3.3
                if [ ${GCCVER} = "3.3" ]; then
                        # cp ../../patches/gcc-3.3.6-emdebian-cross.dpatch debian/patches
                        # apply_patch gcc-3.3.patch

			# Disables multi-arch
                        apply_patch gcc-3.3.6.patch
                fi
#		if [ ${ARCH} = "s390" ]; then
#			apply_patch s390-naming.patch
#		fi
		
		DEB_CROSS=yes fakeroot debian/rules control
		popd
		mv $_dir gcc-$1-${_version}
	fi
	pushd gcc-$1-${_version}
	DEB_CROSS=yes dpkg-buildpackage -us -uc -B -rfakeroot
	popd
}

# install cross gcc versions: install-gcc <majorversion>
install-gcc () {
	local _version=$(version gcc-$1)
	local _versionrepo=$(echo gcc-$1 | sed -e 's/-//' | sed -e 's/\.//')
	
	if [ ${INSTALLPKGSN} = "YES" ]; then
		if [ ${ARCH} = "hppa" ]; then
			$ROOTCMD dpkg -i \
				libgcc4-${ARCH}-cross_${_version}_all.deb >> dpkg.log
		elif [ ${ARCH} = "m68k" ]; then
			if [ ${GCCVER} = "4.1" ]; then
				$ROOTCMD dpkg -i \
					libgcc2-${ARCH}-cross_${_version}_all.deb >> dpkg.log
			fi
		elif [ ${1} != "3.4" ]; then
			$ROOTCMD dpkg -i \
				libgcc1-${ARCH}-cross_${_version}_all.deb >> dpkg.log
		fi
		

		if [ ${1} = "3.3" ]; then
			$ROOTCMD dpkg -i \
				libstdc++5-$1-dev-${ARCH}-cross_${_version}_all.deb >> dpkg.log 
			$ROOTCMD dpkg -i \
				libstdc++5-$1-dbg-${ARCH}-cross_${_version}_all.deb \
				libstdc++5-$1-pic-${ARCH}-cross_${_version}_all.deb \
				libstdc++5-${ARCH}-cross_${_version}_all.deb >> dpkg.log
		elif [ ${1} = "3.4" ]; then
#			$ROOTCMD dpkg -i \
#				libstdc++6-dev-${ARCH}-cross_${_version}_all.deb \
#				libstdc++6-dbg-${ARCH}-cross_${_version}_all.deb \
#				libstdc++6-pic-${ARCH}-cross_${_version}_all.deb \
#				libstdc++6-${ARCH}-cross_${_version}_all.deb >> dpkg.log
			echo "WARNING: HACK!! Could be a BUG ? libstdc++6-arm-cross: Depends: libgcc1-arm-cross-arm-cross (>= 3.4.4) but it is not installable"
		else
			$ROOTCMD dpkg -i \
				libstdc++6-$1-dev-${ARCH}-cross_${_version}_all.deb \
				libstdc++6-$1-dbg-${ARCH}-cross_${_version}_all.deb \
				libstdc++6-$1-pic-${ARCH}-cross_${_version}_all.deb \
				libstdc++6-${ARCH}-cross_${_version}_all.deb >> dpkg.log
		fi
		
		if [ ${1} != "3.4" ]; then
			$ROOTCMD dpkg -i \
				cpp-$1-${ARCH}-linux-gnu_${_version}_${HOSTARCH}.deb \
				g++-$1-${ARCH}-linux-gnu_${_version}_${HOSTARCH}.deb \
				gcc-$1-${ARCH}-linux-gnu_${_version}_${HOSTARCH}.deb >> dpkg.log
		fi


	fi

	#// Do clean up
	rm -rf *.gz *.bz2 *.dsc *.tgz *.tar *.changes gcc-$1-${_version}/

}


# build and install cross gcc-3.3
build-gcc-3.3 () {
	checkinstalled gcc-3.3
	GCCVER=${GCCVER:="3.3"}
	build-gcc 3.3
	install-gcc 3.3
}

# build and install cross gcc-3.4
build-gcc-3.4 () {
	checkinstalled gcc-3.4
	GCCVER=${GCCVER:="3.4"}
	build-gcc 3.4
	install-gcc 3.4
}

# build and install cross gcc-4.0
build-gcc-4.0 () {
	checkinstalled gcc-4.0
	GCCVER=${GCCVER:="4.0"}
	build-gcc 4.0
	install-gcc 4.0
}

# build cross gcc-4.1
build-gcc-4.1 () {
	checkinstalled gcc-4.1
	GCCVER=${GCCVER:="4.1"}
	#// Please check this url before trying to build gcc-4.1
	#// http://people.debian.org/~terpstra/thread/20061015.114041.d049319b.en.html
	#// FIXME: Need to workarround that bug.
	build-gcc 4.1
	install-gcc 4.1
}

# build cross gcc-4.2
build-gcc-4.2 () {
        checkinstalled gcc-4.2
        GCCVER=${GCCVER:="4.2"}
        build-gcc 4.2
        install-gcc 4.2
}

build-gcc-4.3 () {
        checkinstalled gcc-4.3
        GCCVER=${GCCVER:="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.

sanitycheck

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

# do we need to check more version from some packages ?

# for ARCH in ${ARCHLIST}; do

	# Clean dir ?
	#./cleandir.sh
	[ -d ${ARCH} ] || mkdir ${ARCH}
	pushd ${ARCH}
	echo "Updating apt-cross cache"
	apt-cross -a ${ARCH} -S ${SUITE} -m ${MIRROR} -u
	echo "Building for ARCH::${ARCH}" 
	#// make libs
	if [ ${BUILDGCC} = "libs" ]; then
		build-libs &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
	#// make binutils
	elif [ ${BUILDGCC} = "binutils" ]; then
		build-binutils  &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
	#// make gdb
	elif [ ${BUILDGCC} = "gdb" ]; then
		build-gdb  &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
	#// make everything
	elif [ ${BUILDGCC} = "all" ]; then
		build-libs  &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
		build-binutils  &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
	# GCC-3.3 gives error, check build.log.all
	#	build-gcc-3.3 &> ../$LOGPATH/$HOST-$ARCH-$PKG.log

        	GCCVER=${GCCVER:="3.4"}
		build-gcc-3.4 &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
        	GCCVER=${GCCVER:="4.1"}
		build-gcc-4.1 &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
        	GCCVER=${GCCVER:="4.2"}
		build-gcc-4.2 &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
	else
		build-gcc-${GCCVER} &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
	fi
#	build-gcc-snapshot  &> ../$LOGPATH/$HOST-$ARCH-$PKG.log
	popd

	# REPLACE: This quite does not work
	# echo 0 >> $LOGPATH/$HOST-$ARCH-$PKG.log
	TEST=`cat $LOGPATH/$HOST-$ARCH-$PKG.log | grep $HOST.deb`
	if [ -n ${TEST} ]; then
	 	echo 1 >> $LOGPATH/$HOST-$ARCH-$PKG.log
	else
	 	echo 0 >> $LOGPATH/$HOST-$ARCH-$PKG.log
	fi
	
# done

