#! /bin/bash

# URLs and versions
if [ -z "${LINUX_VERS}" ]; then
	## Keep in sync with 00-linux-kernel
	LINUX_VERS='3.2.98'
fi
if [ -z "${GLIBC_VERS}" ]; then
	GLIBC_VERS='2.38'
	GLIBC_TARBALL_SHA256="16e51e0455e288f03380b436e41d5927c60945abd86d0c9852b84be57dd6ed5e"
fi
if [ -z "${GLIBC_URL}" ]; then
	GLIBC_URL="http://ftp.gnu.org/gnu/glibc/glibc-${GLIBC_VERS}.tar.gz"
fi
GLIBC_TARBALL="src/glibc-${GLIBC_VERS}.tar.gz"
GLIBC_DIR="glibc-${GLIBC_VERS}"

if [ -z "${GLIBC_PORTS_VERS}" ]; then
	GLIBC_PORTS_VERS='2.16.0'
	GLIBC_PORTS_TARBALL_SHA256="1092e81d0c9c1bc29343004c1d01fb0d89eb49dd0fd5339b2f2e64a44b582d10"
fi
if [ -z "${GLIBC_PORTS_URL}" ]; then
	GLIBC_PORTS_URL="http://ftp.gnu.org/gnu/glibc/glibc-ports-${GLIBC_PORTS_VERS}.tar.gz"
fi
GLIBC_PORTS_TARBALL="src/glibc-ports-${GLIBC_PORTS_VERS}.tar.gz"
GLIBC_PORTS_DIR="$(pwd)/glibc-ports-${GLIBC_PORTS_VERS}"

# Main script
CCNAME="$1"
CCDIR="$2"
PREFIX="$3"
STAGE="$4"

# Clean
if [ "$1" = "distclean" ]; then
	rm -f "${GLIBC_TARBALL}"

	set -- clean
fi

if [ "$1" = "clean" ]; then
	rm -rf "${GLIBC_DIR}"
	rm -rf "${GLIBC_PORTS_DIR}"
	rm -rf glibc-*-*-*

	exit 0
fi

# Only build glibc for linux-gnu platforms
if ! echo "${CCNAME}" | grep -- '-[^-]*-linux-gnu' >/dev/null; then
	exit 0
fi

# Determine additional addons
case "${GLIBC_VERS}" in
	2.0|2.1|2.2|2.3|2.4|2.5|2.6|2.7|2.8|2.9|2.10|2.11|2.12|2.13|2.14|2.15|2.16|2.17|2.18|2.19|2.0.*|2.1.*|2.2.*|2.3.*|2.4.*|2.5.*|2.6.*|2.7.*|2.8.*|2.9.*|2.10.*|2.11.*|2.12.*|2.13.*|2.14.*|2.15.*|2.16.*|2.17.*|2.18.*|2.19.*)
		GLIBC_ADDITIONAL_ADDONS="${GLIBC_ADDITIONAL_ADDONS},nptl"
		;;
esac


# Download source
. 'scripts/common'

if [ ! -d "${GLIBC_DIR}" ]; then
	download "${GLIBC_URL}" "${GLIBC_TARBALL}" "${GLIBC_TARBALL_SHA256}" || exit 1

	gzip -dc "${GLIBC_TARBALL}" | tar -xf -
fi

if [ ! -d "${GLIBC_PORTS_DIR}" ]; then
	download "${GLIBC_PORTS_URL}" "${GLIBC_PORTS_TARBALL}" "${GLIBC_PORTS_TARBALL_SHA256}" || exit 1

	gzip -dc "${GLIBC_PORTS_TARBALL}" | tar -xf -

	# Apply patches for glibc (only once both packages have been extracted)
	for patch in patches/glibc/*.diff; do
		if [ ! -f "${patch}" ]; then
			continue
		fi

		echo " ** Applying patches to glibc (version ${GLIBC_VERS})"
		echo "     ${patch}"

		cat "${patch}" | (
			cd "${GLIBC_DIR}" || exit 1

			patch -p1
		) || rm -rf "${GLIBC_DIR}"
	done
fi

# Ensure that a stdio.h exists, even if it is blank for autoconf scripts
touch "${PREFIX}/include/stdio.h"

CC_SAVE="${CC}"
CXX_SAVE="${CXX}"
rebuild_binutils_needed='0'
for arch in $(multilib); do
	CC="${CC_SAVE} $(multilib --cflags "${arch}")"
	CXX="${CXX_SAVE} $(multilib --cflags "${arch}")"
	arch_host="$(multilib --host "${arch}")"
	arch_libdir="$(multilib --libdir --noprefix "${arch}")"

	if [ -e "${PREFIX}/${arch_libdir}/glibc-${GLIBC_VERS}-completed-${STAGE}" ]; then
		continue
	fi

	# Inform the user of what we are doing
	echo " * Building GNU C Library (glibc version ${GLIBC_VERS}) for ${arch_host}"

	rm -rf "glibc-${CCNAME}-${arch_host}"
	mkdir "glibc-${CCNAME}-${arch_host}"
	cd "glibc-${CCNAME}-${arch_host}" || exit 1

	echo "slibdir = ${arch_libdir}" > configparms

	case "${STAGE}" in
		stage1)
			"../${GLIBC_DIR}/configure" --prefix='/' --libdir="${arch_libdir}" --host="${arch_host}" \
				--disable-profile --without-gd --without-cvs --without-selinux --enable-add-ons="${GLIBC_PORTS_DIR}${GLIBC_ADDITIONAL_ADDONS}" --with-tls \
				--disable-werror \
				libc_cv_forced_unwind=yes libc_cv_ctors_header=yes libc_cv_c_cleanup=yes libc_cv_ssp=no || exit 1
			echo '#define HAVE_TLS_SUPPORT 1' >> config.h

			${MAKE} ${BUILD_CC_MAKE_FLAGS} || exit 1

			${MAKE} ${BUILD_CC_MAKE_FLAGS} install_root="${PREFIX}" install || exit 1

			cd ..

			rm -rf "glibc-${CCNAME}-${arch_host}"
			mkdir "glibc-${CCNAME}-${arch_host}"
			cd "glibc-${CCNAME}-${arch_host}" || exit 1

			echo "slibdir = ${arch_libdir}" > configparms

			"../${GLIBC_DIR}/configure" --prefix='/' --libdir="${arch_libdir}" --host="${arch_host}" --enable-add-ons="${GLIBC_PORTS_DIR},libidn${GLIBC_ADDITIONAL_ADDONS}" \
				--disable-werror \
				libc_cv_forced_unwind=yes libc_cv_ctors_header=yes libc_cv_c_cleanup=yes libc_cv_ssp=no || exit 1
			rebuild_binutils_needed='1'
			;;
		stage2)
			"../${GLIBC_DIR}/configure" --prefix='/' --libdir="${arch_libdir}" --host="${arch_host}" --enable-add-ons="${GLIBC_PORTS_DIR},libidn${GLIBC_ADDITIONAL_ADDONS}" \
				--disable-werror --enable-kernel="${LINUX_VERS}" || exit 1
			;;
	esac

	${MAKE} ${BUILD_CC_MAKE_FLAGS} || exit 1

	${MAKE} ${BUILD_CC_MAKE_FLAGS} install_root="${PREFIX}" install || exit 1

	cd ..

	rm -rf "glibc-${CCNAME}-${arch_host}"

	touch "${PREFIX}/${arch_libdir}/glibc-${GLIBC_VERS}-completed-${STAGE}"
done

if [ "${rebuild_binutils_needed}" = '1' ]; then
	# Force rebuilding binutils
	touch "${CCDIR}/bin/${CCNAME}-rebuild-binutils"
fi

exit 0
