#!/bin/sh
#
# parameters <machine> <haiku sourcedir> <buildtools dir> <haiku output dir>

# get and check the parameters
if [ $# -lt 4 ]; then
	echo Usage: $0 '<machine> <haiku sourcedir> <buildtools dir>' \
		'<haiku output dir>' >&2
	exit 1
fi

haikuMachine=$1
haikuSourceDir=$2
buildToolsDir=$3
haikuOutputDir=$4
shift 4
additionalMakeArgs=$*

case `uname` in
FreeBSD|OpenBSD)
	MAKE=gmake
	;;
*)
	MAKE=make
	;;
esac
export MAKE

case $haikuMachine in
x86_64-*)
	# GCC's default is to enable multilib, but there is a bug when
	# explicitly using --enable-multilib that causes a build
	# failure
	binutilsConfigureArgs=""
	gccConfigureArgs=""
	kernelCcFlags="-mno-red-zone"
	;;
m68k-*)
	binutilsConfigureArgs="--enable-multilib"
	gccConfigureArgs="--enable-multilib"
	;;
arm-*)
	binutilsConfigureArgs="--enable-multilib"
	gccConfigureArgs="--enable-multilib"
	;;
*)
	binutilsConfigureArgs="--disable-multilib"
	gccConfigureArgs="--disable-multilib"
	kernelCcFlags=
	;;
esac

if [ ! -d $haikuSourceDir ]; then
	echo "No such directory: \"$haikuSourceDir\"" >&2
	exit 1
fi

if [ ! -d $buildToolsDir ]; then
	echo "No such directory: \"$buildToolsDir\"" >&2
	exit 1
fi


# create the output dir
mkdir -p $haikuOutputDir || exit 1


# get absolute paths
currentDir=$(pwd)

cd $haikuSourceDir
haikuSourceDir=$(pwd)
cd $currentDir

cd $buildToolsDir
buildToolsDir=$(pwd)
cd $currentDir

cd $haikuOutputDir
haikuOutputDir=$(pwd)

binutilsSourceDir=$buildToolsDir/binutils
gccSourceDir=$buildToolsDir/gcc


# get gcc version
gccVersion=$(cat $gccSourceDir/gcc/BASE-VER)

if [ -z "$gccVersion" ]; then
	echo "Failed to find out gcc version." >&2
	exit 1
fi

# touch all info files in order to avoid the dependency on makeinfo
# (which apparently doesn't work reliably on all the different host 
# configurations and changes files which in turn appear as local changes
# to the VCS).
find $binutilsSourceDir $gccSourceDir -name \*.info -print0 | xargs -0 touch

# create the object and installation directories for the cross compilation tools
installDir=$haikuOutputDir/cross-tools
objDir=$haikuOutputDir/cross-tools-build
binutilsObjDir=$objDir/binutils
gccObjDir=$objDir/gcc
stdcxxObjDir=$objDir/stdcxx
tmpIncludeDir=$objDir/sysincludes
tmpLibDir=$objDir/syslibs

rm -rf $installDir $objDir

mkdir -p $installDir $objDir $binutilsObjDir $gccObjDir $stdcxxObjDir \
	$tmpIncludeDir $tmpLibDir || exit 1
mkdir -p $installDir/lib/gcc/$haikuMachine/$gccVersion

if [ "$HAIKU_USE_GCC_GRAPHITE" = 1 ]; then
	cloogSourceDir=$buildToolsDir/cloog
	gmpSourceDir=$buildToolsDir/gcc/gmp
	pplSourceDir=$buildToolsDir/ppl

	pplObjDir=$objDir/ppl
	gmpObjDir=$objDir/gmp
	cloogObjDir=$objDir/cloog
	mkdir -p $pplObjDir $gmpObjDir $cloogObjDir || exit 1
	
	gccConfigureArgs="$gccConfigureArgs --with-cloog=$installDir \
		--enable-cloog-backend=isl --with-ppl=$installDir \
		--disable-cloog-version-check --with-gmp=$installDir \
		--with-host-libstdcxx=\"-lstdc++\""
fi

# force the POSIX locale, as the build (makeinfo) might choke otherwise
export LC_ALL=POSIX

# build binutils
cd $binutilsObjDir
CFLAGS="-O2" CXXFLAGS="-O2" $binutilsSourceDir/configure \
	--prefix=$installDir --target=$haikuMachine --disable-nls \
	--disable-shared --disable-werror $binutilsConfigureArgs || exit 1
$MAKE $additionalMakeArgs || exit 1
$MAKE $additionalMakeArgs install || exit 1

export PATH=$PATH:$installDir/bin

if [ "$HAIKU_USE_GCC_GRAPHITE" = 1 ]; then
	# build gmp
	cd $gmpObjDir
	$gmpSourceDir/configure --prefix=$installDir \
		--disable-shared --enable-cxx || exit 1
	$MAKE $additionalMakeArgs || exit 1
	$MAKE $additionalMakeArgs install || exit 1
	
	# build ppl
	cd $pplObjDir
	CFLAGS="-O2" CXXFLAGS="-O2" $pplSourceDir/configure --prefix=$installDir \
		--disable-nls --disable-shared --disable-watchdog \
		--disable-maintainer-mode || exit 1
	$MAKE $additionalMakeArgs AUTOCONF:=true AUTOHEADER:=true ACLOCAL:=true \
		AUTOMAKE:=true || exit 1
	$MAKE $additionalMakeArgs install AUTOCONF:=true AUTOHEADER:=true \
		ACLOCAL:=true AUTOMAKE:=true || exit 1

	# build cloog
	cd $cloogObjDir
	CFLAGS="-O2" CXXFLAGS="-O2" $cloogSourceDir/configure \
		--prefix=$installDir --disable-nls --disable-shared \
		--with-gmp-prefix=$installDir || exit 1
	$MAKE $additionalMakeArgs || exit 1
	$MAKE $additionalMakeArgs install || exit 1
fi

# build gcc

# prepare the include files
copy_headers()
{
	sourceDir=$1
	targetDir=$2

	headers="$(find $sourceDir -name \*\.h)"
	headers="$(echo $headers | sed -e s@$sourceDir/@@g)"
	for f in $headers; do
		headerTargetDir=$targetDir/$(dirname $f)
		mkdir -p $headerTargetDir
		cp $sourceDir/$f $headerTargetDir
	done
}

copy_headers $haikuSourceDir/headers/config $tmpIncludeDir/config
copy_headers $haikuSourceDir/headers/os $tmpIncludeDir/os
copy_headers $haikuSourceDir/headers/posix $tmpIncludeDir/posix

# configure gcc
cd $gccObjDir
CFLAGS="-O2" CXXFLAGS="-O2" $gccSourceDir/configure --prefix=$installDir \
	--target=$haikuMachine --disable-nls --disable-shared --with-system-zlib \
	--enable-languages=c,c++ --enable-lto --enable-frame-pointer \
	--with-headers=$tmpIncludeDir --with-libs=$tmpLibDir \
	$gccConfigureArgs || exit 1

# make gcc
$MAKE $additionalMakeArgs || {
	echo "ERROR: Building gcc failed." >&2
	exit 1
}

# install gcc
$MAKE $additionalMakeArgs install || {
	echo "ERROR: Installing the cross compiler failed." >&2
	exit 1
}

# build libraries for the kernel if the target arch requires it
if [ -n "$kernelCcFlags" ]; then
	$MAKE -C $haikuMachine/libgcc clean
	$MAKE -C $haikuMachine/libgcc CFLAGS="-g -O2 $kernelCcFlags" || {
		echo "Error: Building kernel libgcc failed." >&2
		exit 1
	}

	cp $haikuMachine/libgcc/libgcc.a \
		$installDir/$haikuMachine/lib/libgcc-kernel.a || exit 1

	$MAKE -C $haikuMachine/libstdc++-v3/libsupc++ clean
	$MAKE -C $haikuMachine/libstdc++-v3/libsupc++ CFLAGS="-g -O2 $kernelCcFlags" \
		CXXFLAGS="-g -O2 $kernelCcFlags" || {
		echo "Error: Building kernel libsupc++ failed." >&2
		exit 1
	}

	cp $haikuMachine/libstdc++-v3/libsupc++/.libs/libsupc++.a \
		$installDir/$haikuMachine/lib/libsupc++-kernel.a || exit 1
fi

# cleanup

# remove the system headers from the installation dir
# Only the ones from the source tree should be used.
sysIncludeDir=$installDir/$haikuMachine/sys-include
rm -rf $sysIncludeDir/os $sysIncludeDir/posix

# remove the objects dir
rm -rf $objDir


echo "binutils and gcc for cross compilation have been built successfully!"