#!/bin/sh
#
# configure [ <options> ]

# usage
#
# Prints usage.
#
usage()
{
	cat << EOF

Usage: $0 <options>
options:
  --bochs-debug               Enables bochs serial debug emulation (activated
                              via kernel settings file).
  --build-cross-tools <build tools dir>
                              Assume cross compilation. <build tools dir>
                              defines the location of the build tools sources.
                              They will be compiled and placed in the output
                              directory under "cross-tools". The HAIKU_* tools
                              variables will be set accordingly.
  --build-cross-tools-gcc4 <arch> <build tools dir>
                              Like "--build-cross-tools" just that gcc 4 will
                              be used for cross-compilation. Note, that the
                              resulting Haiku installation built with gcc 4
                              will not be binary compatible with BeOS R5.
                              <arch> specifies the target architecture, either
                              "x86" or "ppc".
  --alternative-gcc-output-dir <dir>
                              Build a Haiku installation that supports running
                              executables built with a gcc version incompatible
                              with the primary gcc (e.g. gcc 2 executables under
                              a gcc 4 Haiku or vice versa). <dir> specifies the
                              output directory of the other gcc. The directory
                              must already be fully configured.
                              Note, that a sub-jam will be executed when
                              building Haiku. When using a jam that is not
                              simply invoked by "jam", the JAM build variable
                              needs to be set accordingly.
                              To disable building the alternative libraries
                              the variable HAIKU_ADD_ALTERNATIVE_GCC_LIBS can be
                              unset in the UserBuildConfig file.
  --cross-tools-prefix <prefix>
                              Assume cross compilation. <prefix> should be a
                              path to the directory where the cross
                              compilation tools are located, plus the platform
                              prefix, e.g. "/path/to/tools/i586-pc-haiku-".
                              This overrides the HAIKU_* tool variables.
  --distro-compatibility <level>
                              The distribution's level of compatibility with
                              the official Haiku distribution. The generated
                              files will contain the respective trademarks
                              accordingly.
                              official -- the official Haiku distribution.
                              compatible -- a Haiku Compatible (tm) distro.
                              default -- any other distro (default value).
  --help                      Prints out this help.
  --include-gpl-addons        Include GPL licensed add-ons.
  --include-3rdparty          Include 3rdparty/ in the build system.
  --enable-multiuser          Enable experimental multiuser support.
  --target=TARGET             Select build target platform. [default=${target}]
                              valid targets=r5,bone,dano,haiku
  --use-gcc-pipe              Build with GCC option -pipe. Speeds up the build
                              process, but uses more memory.
  --use-32bit                 Use -m32 flag on 64bit host gcc compiler.
  --use-xattr                 Use Linux xattr support for BeOS attribute
                              emulation. Warning: Make sure your file system
                              supports sufficient attribute sizes (4 KB per
                              file for all attributes won't suffice).

environment variables:
  HAIKU_AR                    The static library archiver. Defaults to "ar".
  HAIKU_CC                    The compiler. Defaults to "gcc".
  HAIKU_LD                    The linker. Defaults to "ld".
  HAIKU_OBJCOPY               The objcopy to be used. Defaults to "objcopy".
  HAIKU_RANLIB                The static library indexer. Defaults to "ranlib".
  HAIKU_YASM                  The yasm assembler (x86 only).
  HAIKU_CPPFLAGS              The preprocessor flags. Defaults to "".
  HAIKU_CCFLAGS               The C flags. Defaults to "".
  HAIKU_CXXFLAGS              The C++ flags. Defaults to "".
  HAIKU_LDFLAGS               The linker flags. Defaults to "".
  HAIKU_ARFLAGS               The flags passed to HAIKU_AR for archiving.
                              Defaults to "ru".
  HAIKU_UNARFLAGS             The flags passed to HAIKU_AR for unarchiving.
                              Defaults to "x".

Non-standard output directories:
  By default all objects, build configuration, and other related files are
  stored in /path/to/haiku_source/generated.  To store objects in a non-default
  location, run "../../relative/path/to/haiku_source/configure <options>" from
  within your non-default location.  "jam [ options ] targets" can then be run
  directly inside your non-default location.  Another option is to invoke "jam
  [ options ] targets" from within haiku_source.  This can be accomplished by
  either "export HAIKU_OUTPUT_DIR=your non-default location" before invoking
  jam or by creating a symlink of haiku_source/generated pointing to your
  non-default location and running jam.


EOF
}

# assertparam
#
# Checks whether at least one parameter is left.
#
assertparam()
{
	if [ $2 -lt 2 ]; then
		echo $0: \`$1\': Parameter expected.
		exit 1
	fi
}

# assertparams
#
# Checks whether at least a certain number of parameters is left.
#
assertparams()
{
	if [ $3 -le $2 ]; then
		echo $0: \`$1\': Not enough parameters.
		exit 1
	fi
}

# standard_gcc_settings
#
# Sets the variables for a GCC platform.
#
standard_gcc_settings()
{
	# PLATFORM_LINKLIBS
	gcclib=`$HAIKU_CC -print-libgcc-file-name`
	gccdir=`dirname ${gcclib}`

	haikuGCCVersion=`$HAIKU_CC -dumpversion`
	haikuGCCMachine=`$HAIKU_CC -dumpmachine`

	HAIKU_GCC_LIB_DIR=${gccdir}
	HAIKU_GCC_LIBGCC=${gccdir}/libgcc.a
	HAIKU_GCC_GLUE_CODE="crtbegin.o crtend.o"
	HAIKU_GCC_HEADERS_DIR="${gccdir}/include
		${gccdir}/include-fixed"
	HAIKU_GCC_LIBGCC_OBJECTS=`$HAIKU_AR t ${HAIKU_GCC_LIBGCC} | grep -v eabi.o`
		# Note: We filter out eabi.o. It's present in gcc's libgcc for PPC and
		# neither needed nor wanted.

	case $haikuGCCVersion in
		4.*)
			# for gcc 4 we use the libstdc++ and libsupc++ that come with the
			# compiler
			haikuStaticLibStdCxx=`$HAIKU_CC -print-file-name=libstdc++.a`
			haikuSharedLibStdCxx=`$HAIKU_CC -print-file-name=libstdc++.so`
			haikuStaticLibSupCxx=`$HAIKU_CC -print-file-name=libsupc++.a`
			haikuSharedLibSupCxx=`$HAIKU_CC -print-file-name=libsupc++.so`

			local headers
			if [ -d $gccdir/../../../../$haikuGCCMachine/include/c++/$haikuGCCVersion ]; then
				headers=$gccdir/../../../../$haikuGCCMachine/include/c++/$haikuGCCVersion
			else
				headers=$gccdir/../../../../include/c++/$haikuGCCVersion
			fi

			haikuCxxHeadersDir=$headers
			for d in $haikuGCCMachine backward ext; do
				# Note: We need the line break, otherwise the line might become
				# too long for jam (512 bytes max).
				haikuCxxHeadersDir="$haikuCxxHeadersDir
					$headers/$d"
			done


			# when not building the crosscompiler, to use cpp headers from
			# tree first, but fallback to local C++ system headers (like <new>)
			# if [ "$buildCrossTools" = "" ]; then
			#	haikuCxxHeadersDir="headers/cpp $haikuCxxHeadersDir"
			# fi

			if [ $haikuStaticLibStdCxx = libstdc++.a ]; then
				haikuStaticLibStdCxx=
			fi
			if [ $haikuSharedLibStdCxx = libstdc++.so ]; then
				haikuSharedLibStdCxx=
			fi
			if [ $haikuStaticLibSupCxx = libsupc++.a ]; then
				haikuStaticLibSupCxx=
			fi
			if [ $haikuSharedLibSupCxx = libsupc++.so ]; then
				haikuSharedLibSupCxx=
			fi
		;;
		2.9*)
			# check for correct (most up-to-date) legacy compiler and complain
			# if an older one is installed
			if [ $haikuGCCVersion != $haikuRequiredLegacyGCCVersion ]; then
				echo "GCC version $haikuRequiredLegacyGCCVersion is required!";
				echo "Please download it from www.haiku-os.org...";
				exit 1;
			fi
		;;
	esac
}

# set_default_value
#
# Set the value for a variable, if no value is set yet.
#
set_default_value()
{
	eval "$1=\${$1-$2}"
}

# get_build_tool_path
#
# Gets a usable absolute path of a build tool.
#
get_build_tool_path()
{
	local var="HAIKU_$1"
	local tool=$2
	local path="${crossToolsPrefix}$tool"

	if [ -f "$path" ]; then
		# get absolute path
		local oldPwd="`pwd`"
		cd "`dirname "$path"`"
		path="`pwd`/`basename "$path"`"
		cd $oldPwd
	else
		which "$path" &> /dev/null || {
			echo "Build tool \"$path\" not found." >&2
			exit 1
		}
	fi

	eval "$var=$path"
}

# get cwd and the source directory
currentDir=`pwd`
cd `dirname "$0"`
sourceDir=`pwd`
cd "$currentDir"

# default parameter values
#
platform=`uname`
platformMachine=`uname  -m`
haikuGCCVersion=
haikuGCCMachine=i586-pc-haiku
haikuStaticLibStdCxx=
haikuSharedLibStdCxx=
haikuStaticLibSupCxx=
haikuSharedLibSupCxx=
haikuCxxHeadersDir=
hostGCCVersion=`gcc -dumpversion`
bochsDebug=0
includeGPLAddOns=0
include3rdParty=0
enableMultiuser=0
distroCompatibility=default
target=haiku
targetArch=x86
useGCCPipe=0
use32bit=0
useXattr=0
crossToolsPrefix=
buildCrossTools=
buildCrossToolsScript="$sourceDir/build/scripts/build_cross_tools"
buildCrossToolsMachine=
alternativeGCCOutputDir=
addAlternativeGCCLibs=

haikuRequiredLegacyGCCVersion="2.95.3-haiku-081024"
export haikuRequiredLegacyGCCVersion
	# version of legacy gcc required to build haiku

set_default_value HAIKU_AR			ar
set_default_value HAIKU_CC			gcc
set_default_value HAIKU_LD			ld
set_default_value HAIKU_OBJCOPY		objcopy
set_default_value HAIKU_RANLIB		ranlib
set_default_value HAIKU_YASM		yasm
set_default_value HAIKU_CPPFLAGS	""
set_default_value HAIKU_CCFLAGS		""
set_default_value HAIKU_CXXFLAGS	""
set_default_value HAIKU_LDFLAGS		""
set_default_value HAIKU_ARFLAGS		ru
set_default_value HAIKU_UNARFLAGS	x

# parse parameters
#
while [ $# -gt 0 ] ; do
	case "$1" in
		--bochs-debug)	bochsDebug=1; shift 1;;
		--build-cross-tools) assertparam "$1" $#; buildCrossTools=$2; shift 2;;
		--build-cross-tools-gcc4)
			assertparams "$1" 2 $#
			buildCrossTools=$3
			buildCrossToolsScript="${buildCrossToolsScript}_gcc4"
			case "$2" in
				x86)	haikuGCCMachine=i586-pc-haiku;;
				ppc)	haikuGCCMachine=powerpc-apple-haiku; targetArch=ppc;;
				m68k)	haikuGCCMachine=m68k-unknown-haiku; targetArch=m86k;;
				arm)	haikuGCCMachine=arm-unknown-haiku; targetArch=arm;;
				mipsel)	haikuGCCMachine=mipsel-unknown-haiku; targetArch=mips;;
				*)		echo "Unsupported target architecture: $2"
						exit 1;;
			esac
			buildCrossToolsMachine=$haikuGCCMachine
			shift 3
			;;
		--alternative-gcc-output-dir)
			assertparam "$1" $#
			cd $2 || exit 1
			alternativeGCCOutputDir=`pwd`
			addAlternativeGCCLibs=1
			cd $currentDir
			shift 2
			;;
		--cross-tools-prefix)
			assertparam "$1" $#
			crossToolsPrefix=$2
			shift 2
			;;
		--help | -h)	usage; exit 0;;
		--include-gpl-addons)	includeGPLAddOns=1; shift 1;;
		--include-3rdparty)	include3rdParty=1; shift 1;;
		--enable-multiuser)	enableMultiuser=1; shift 1;;
		--distro-compatibility)
			assertparam "$1" $#
			distroCompatibility=$2
			case "$distroCompatibility" in
				official)	;;
				compatible)	;;
				default)	;;
				*)			echo "Invalid distro compatibility" \
								"level: $distroCompatibility"
							exit 1;;
			esac
			shift 2
			;;
		--target=*)     target=`echo $1 | cut -d'=' -f2-`; shift 1;;
		--use-gcc-pipe)	useGCCPipe=1; shift 1;;
		--use-32bit)	use32bit=1; shift 1;;
		--use-xattr)	useXattr=1; shift 1;;
		*)				echo Invalid argument: \`$1\'; exit 1;;
	esac
done

# check for a 64bit platform
case "${platformMachine}" in
	x86_64)	use32bit=1 ;;
	*)	echo Assuming 32-bit machine: "$platformMachine"
		use32bit=0 ;;
esac

# detect the build platform
case "${platform}" in
	BeOS)	revision=`uname -r`
			case "$revision" in
				6.*)	buildPlatform=dano ;;
				5.1)	buildPlatform=dano ;;
				5.0.4)	buildPlatform=bone ;;
				5.0*)	buildPlatform=r5 ;;
				*)		echo Unknown BeOS version: $revision
						exit 1 ;;
			esac
			;;
	Darwin)	buildPlatform=darwin ;;
	FreeBSD)	buildPlatform=freebsd
				if [ "$use32bit" = 1 ] ; then
					echo Unsupported platform: FreeBSD ${platformMachine}
					exit 1
				fi	;;
	Haiku)	buildPlatform=haiku_host ;;
	Linux)	buildPlatform=linux ;;
	OpenBSD) buildPlatform=openbsd ;;
	SunOS)	buildPlatform=sunos ;;
	CYGWIN_NT-*) buildPlatform=cygwin ;;
	*)		echo Unsupported platform: ${platform}
			exit 1 ;;
esac

# check yasm version
if [ $targetArch = "x86" ]; then
	$HAIKU_YASM --version > /dev/null || {
		echo "The yasm assembler version 0.7.0 or later must be installed."
		echo "Download from: http://www.tortall.net/projects/yasm/wiki/Download"
		exit 1
	}

	set -- $($HAIKU_YASM --version | head -n 1)
	versionOK=0
	case $2 in
		0.[0-6].*)		;;
		*)				versionOK=1 ;;
	esac

	if [ $versionOK = 0 ]; then
		echo "The yasm assembler version 0.7.0 or later must be installed."
		echo "The installed version is $2."
		echo "Download from: http://www.tortall.net/projects/yasm/wiki/Download"
		exit 1
	fi
fi

# create output directory
if [ "$currentDir" = "$sourceDir" ]; then
	outputDir=$currentDir/generated
else
	outputDir=$currentDir
fi
buildOutputDir="$outputDir/build"
buildAttributesDir="$outputDir/attributes"
mkdir -p "$buildOutputDir" || exit 1

# build cross tools from sources
if [ -n "$buildCrossTools" ]; then
	"$buildCrossToolsScript" $buildCrossToolsMachine "$sourceDir" \
		"$buildCrossTools" "$outputDir" || exit 1
	crossToolsPrefix="$outputDir/cross-tools/bin/${haikuGCCMachine}-"
fi

# cross tools
if [ -n "$crossToolsPrefix" ]; then
	get_build_tool_path AR ar
	get_build_tool_path CC gcc
	get_build_tool_path LD ld
	get_build_tool_path OBJCOPY objcopy
	get_build_tool_path RANLIB ranlib
fi

# prepare gcc settings
standard_gcc_settings

# check whether the Haiku compiler really targets Haiku or BeOS
case "$haikuGCCMachine" in
	*-*-haiku)	;;
	*-*-beos)	;;
	*) echo The compiler specified as Haiku target compiler is not a valid \
			Haiku cross-compiler. Please see ReadMe.cross-compile. >&2
	   echo compiler: $HAIKU_CC
	   echo compiler is configured for target: $haikuGCCMachine
	   exit 1 ;;
esac

# Generate BuildConfig
cat << EOF > "$buildOutputDir/BuildConfig"
# BuildConfig
# Note: This file has been automatically generated by configure.

TARGET_PLATFORM 			?= "${target}" ;
HOST_PLATFORM				?= "${buildPlatform}" ;

BOCHS_DEBUG_HACK					?= "${bochsDebug}" ;
INCLUDE_GPL_ADDONS					?= "${includeGPLAddOns}" ;
HAIKU_INCLUDE_3RDPARTY				?= "${include3rdParty}" ;
HAIKU_ENABLE_MULTIUSER				?= "${enableMultiuser}" ;
HAIKU_DISTRO_COMPATIBILITY			?= "${distroCompatibility}" ;
HAIKU_USE_GCC_PIPE					?= "${useGCCPipe}" ;
HAIKU_HOST_USE_32BIT				?= "${use32bit}" ;
HAIKU_HOST_USE_XATTR				?= "${useXattr}" ;
HAIKU_ALTERNATIVE_GCC_OUTPUT_DIR	?= ${alternativeGCCOutputDir} ;
HAIKU_ADD_ALTERNATIVE_GCC_LIBS		?= ${addAlternativeGCCLibs} ;

HAIKU_GCC_RAW_VERSION		?= ${haikuGCCVersion} ;
HAIKU_GCC_MACHINE			?= ${haikuGCCMachine} ;
HAIKU_GCC_LIB_DIR			?= ${HAIKU_GCC_LIB_DIR} ;
HAIKU_GCC_HEADERS_DIR		?= ${HAIKU_GCC_HEADERS_DIR} ;
HAIKU_GCC_LIBGCC			?= ${HAIKU_GCC_LIBGCC} ;

HAIKU_STATIC_LIBSTDC++		?= ${haikuStaticLibStdCxx} ;
HAIKU_SHARED_LIBSTDC++		?= ${haikuSharedLibStdCxx} ;
HAIKU_STATIC_LIBSUPC++		?= ${haikuStaticLibSupCxx} ;
HAIKU_SHARED_LIBSUPC++		?= ${haikuSharedLibSupCxx} ;
HAIKU_C++_HEADERS_DIR		?= ${haikuCxxHeadersDir} ;

HAIKU_BUILD_ATTRIBUTES_DIR	?= ${buildAttributesDir} ;

HAIKU_AR					?= ${HAIKU_AR} ;
HAIKU_CC					?= ${HAIKU_CC} ;
HAIKU_LD					?= ${HAIKU_LD} ;
HAIKU_OBJCOPY				?= ${HAIKU_OBJCOPY} ;
HAIKU_RANLIB				?= ${HAIKU_RANLIB} ;
HAIKU_YASM					?= ${HAIKU_YASM} ;
HAIKU_CPPFLAGS				?= ${HAIKU_CPPFLAGS} ;
HAIKU_CCFLAGS				?= ${HAIKU_CCFLAGS} ;
HAIKU_CXXFLAGS				?= ${HAIKU_CXXFLAGS} ;
HAIKU_LDFLAGS				?= ${HAIKU_LDFLAGS} ;
HAIKU_ARFLAGS				?= ${HAIKU_ARFLAGS} ;
HAIKU_UNARFLAGS				?= ${HAIKU_UNARFLAGS} ;

HOST_GCC_RAW_VERSION		?= ${hostGCCVersion} ;

EOF

# Libgcc.a objects

cat << EOF > "$buildOutputDir/libgccObjects"
# libgcc.a objects to be linked against libroot.so
# Note: This file has been automatically generated by configure.

HAIKU_GCC_LIBGCC_OBJECTS	?= ${HAIKU_GCC_LIBGCC_OBJECTS} ;
EOF

# Generate Timezones binaries bindings

timezoneSources="africa antarctica asia australasia europe northamerica
	southamerica pacificnew etcetera factory backward"

cat << EOF > "$buildOutputDir/Timezones"
# Timezones used for the build
# Note: This file has been automatically generated by configure.

HAIKU_TIME_ZONE_SOURCES = ${timezoneSources} ;

EOF

for source in ${timezoneSources}; do
	f=$sourceDir/src/data/etc/timezones/$source

TZOBJECTS=`gawk '/^Zone/ { print $2 } /^Link/ { print $3 } ' "$f" `

cat << EOF >> "$buildOutputDir/Timezones"
TZ_OBJECTS on <timezone-source>${source} ?= $TZOBJECTS ;
EOF
done

# Generate a boot strap Jamfile in the output directory.

cat << EOF > $outputDir/Jamfile
# automatically generated Jamfile

HAIKU_TOP			= ${sourceDir} ;
HAIKU_OUTPUT_DIR	= ${outputDir} ;

include [ FDirName \$(HAIKU_TOP) Jamfile ] ;

EOF