#! /bin/bash

# URLs and versions
if [ -z "${MUSL_VERS}" ]; then
	MUSL_VERS='1.1.10'
	MUSL_TARBALL_SHA256="45bbe9b1c7f7a0f743477af1e103b6889bfe4dd9815e16f6c89f6c90831c8b7c"
fi
if [ -z "${MUSL_URL}" ]; then
	MUSL_URL="http://www.musl-libc.org/releases/musl-${MUSL_VERS}.tar.gz"
fi
MUSL_TARBALL="src/musl-${MUSL_VERS}.tar.gz"
MUSL_DIR="musl-${MUSL_VERS}"

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

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

	set -- clean
fi

if [ "$1" = "clean" ]; then
	rm -rf "${MUSL_DIR}"
	rm -rf musl-*-*-*

	exit 0
fi

# Do not compile if we already have built it
if find "${PREFIX}" -name 'musl-gcc.specs' 2>/dev/null | grep '^' >/dev/null; then
	exit 0
fi

# Determine if MUSL is supported on this platform
## From "musl-1.1.3" configure
MUSL_ARCH=''
case "${CCNAME}" in
	mips64*|powerpc64*) ;;
	arm*) MUSL_ARCH=arm ;;
	i?86*) MUSL_ARCH=i386 ;;
	x86_64-x32*|x32*|x86_64*x32) MUSL_ARCH=x32 ;;
	x86_64*) MUSL_ARCH=x86_64 ;;
	mips*) MUSL_ARCH=mips ;;
	microblaze*) MUSL_ARCH=microblaze ;;
	powerpc*) MUSL_ARCH=powerpc ;;
	sh[1-9bel-]*|sh|superh*) MUSL_ARCH=sh ;;
esac

# Verify that this is a platform we build on
case "${CCNAME}" in
	*-linux-musl)
		# Build MUSL libc for linuxmusl platforms
		shared='1'
		musllibc='1'
		fail='1'
		muslwrapper=''
		;;
	*-linux-*|*-linux)
		# Build for all Linux platforms so that MUSL will be available
		shared='0'
		musllibc='0'
		fail='0'
		muslwrapper="${CCDIR}/bin/${CCNAME}-gcc-musl"
		if [ -z "${MUSL_ARCH}" ]; then
			# If MUSL doesn't support this platform, abort immediately
			exit 0
		fi
		;;
	*)
		exit 0
		;;
esac

if [ "${shared}" = '0' ]; then
	MUSL_CONFIGURE_EXTRA="${MUSL_CONFIGURE_EXTRA} --disable-shared"
fi

if [ "${musllibc}" = '0' ]; then
	PREFIX="${PREFIX}/musl"
fi

# Load common script
. 'scripts/common'

# Determine if we are a multilib build
archs="$(multilib)"


if [ ! -d "${MUSL_DIR}" ]; then
	# Download source
	download "${MUSL_URL}" "${MUSL_TARBALL}" "${MUSL_TARBALL_SHA256}" || exit $fail

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

	# Merge headers for i386/x86_64 to enable multilib support
	(
		cd "${MUSL_DIR}/arch/x86_64" || exit 1
		find . -type f | while read file; do
			diff -u "${file}" "../i386/${file}" >/dev/null && continue

			(
				echo '#if __SIZEOF_POINTER__ == 8'
				cat "${file}"
				echo '#else'
				cat "../i386/${file}"
				echo '#endif'
			) > "${file}.new"
			cat "${file}.new" > "${file}"
			rm -f "${file}.new"
		done

		cd .. || exit 1
		rm -rf i386
		cp -rp x86_64 i386
	) || exit 1
fi

CC_SAVE="${CC}"
for arch in ${archs}; do
	CC="${CC_SAVE}"

	# Options for multilib
	arch_host="$(multilib --host "${arch}")"
	libdir="$(multilib --libdir "${arch}")"
	CC="${CC} $(multilib --cflags "${arch}")"

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

	rm -rf "musl-${CCNAME}-${arch_host}"
	cp -rp "${MUSL_DIR}" "musl-${CCNAME}-${arch_host}"

	cd "musl-${CCNAME}-${arch_host}" || exit $fail

	CFLAGS=-fno-toplevel-reorder
	export CFLAGS
	./configure --prefix="${PREFIX}" --bindir="${CCDIR}/bin" --libdir="${libdir}" --host="${arch_host}" --enable-gcc-wrapper ${MUSL_CONFIGURE_EXTRA} || exit $fail

	${MAKE} ${BUILD_CC_MAKE_FLAGS}

	${MAKE} ${BUILD_CC_MAKE_FLAGS} syslibdir="${PREFIX}/lib" install || exit $fail

	cd .. || exit $fail

	rm -rf "musl-${CCNAME}-${arch_host}"
done

if [ -n "${muslwrapper}" ]; then
	if false; then
		# XXX: Work In Progress; We need to generate a multilib compatible spec file
		cat << _EOF_ > ${libdir}/musl-gcc.specs
%rename cpp_options old_cpp_options

*cpp_options:
-nostdinc -isystem ${prefix}/include -isystem include%s %(old_cpp_options)

*cc1:
%(cc1_cpu) -nostdinc -isystem ${prefix}/include -isystem include%s

*link_libgcc:
-L${libdir} -L .%s

*libgcc:
libgcc.a%s %:if-exists(libgcc_eh.a%s)

*startfile:
%{!shared: ${libdir}/%{pie:S}crt1.o} ${libdir}/crti.o %{shared|pie:crtbeginS.o%s;:crtbegin.o%s}

*endfile:
%{shared|pie:crtendS.o%s;:crtend.o%s} ${libdir}/crtn.o

*link:
-dynamic-linker /lib/ld-musl-${MUSL_ARCH}.so.1 %{m32|mx32:;:-m elf_x86_64} %{m32:-m elf_i386} %{mx32:-m elf32_x86_64} -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic}

*esp_link:


*esp_options:


*esp_cpp_options:

_EOF_
	fi

	cat << _EOF_ >> "${muslwrapper}"
#! /usr/bin/env bash

exec '${CCDIR}/bin/${CCNAME}-gcc' "\$@" -specs '${libdir}/musl-gcc.specs'

exit 1
_EOF_
	chmod +x "${muslwrapper}"
fi

rm -f "${CCDIR}/bin/musl-gcc"

exit 0
