#!/bin/ash
# FatdogArm/Fatdog64 package build script
# Copyright (C) James Budiono, 2013, 2014, 2015, 2016
# License: GNU GPL Version 3 or later
#
# This is the version of build-pkg that will build a single package
# from *within* FatdogArm/Fatdog64.
#
# The usual build pre-requisites (toolchain, make, bison, etc) 
# must alread be installed.
#
# $1-pkgname (any variation)

[ $(id -u) -ne 0 ] && exit # must run as root
export LANG=C # make it run a bit faster

### configuration settings (overridable)
[ $BOOTSTATE_PATH ] && [ -e $BOOTSTATE_PATH ] && 
. $BOOTSTATE_PATH # AUFS_ROOT_ID
BUILD_DIR_PREFIX=${BUILD_DIR_PREFIX:-/tmp}
BUILD_DIR=$(mktemp -d -p $BUILD_DIR_PREFIX build-pkg.XXXXXXXX)
CHROOT_DIR=/tmp/chroot-${BUILD_DIR##*/}
#UNIONFS_FUSE=${UNIONFS_FUSE-unionfs} # leave blank to use aufs

SANDBOX_ROOT=/mnt/sb # enable unionfs by default if we are inside sandbox
grep -q $SANDBOX_ROOT /sys/fs/aufs/$AUFS_ROOT_ID/br0 &&
UNIONFS_FUSE=${UNIONFS_FUSE-unionfs}

DEF_PKGARCH=x86_64
PKG=${1##*/}; PKG=${PKG%/}
PKGARCH=${PKGARCH:-$DEF_PKGARCH}
PKG_TYPE=${PKG_TYPE:-txz}
PKG_DIR=${PKG_DIR:-pkg}
SRC_DIR=$(readlink -f ${SRC_DIR:-src})
PATCHES_DIR=$(readlink -f ${PATCHES_DIR:-patches})
OUTPUT_DIR=$(readlink -f ${OUTPUT_DIR:-output})
#KEEP_DIR=1
PKG_COPY=${PKG_COPY:-usr/src/pkgbuild/source} # keep a copy of the pkg here
PKG_COPY=${PKG_COPY#/} # make sure not absolute path
MAKEPKG=makepkg
#FINDPKG_CACHE= # inherited - to speed up find_pkg

# load our helper functions 
. ${0%/*}/build-lib.sh 

########### ACTIONS ###########
###
trap 'cleanup; exit $RESULT' INT TERM HUP 0
CLEANED="" RESULT=1
cleanup() {
	[ $CLEANED ] && return; CLEANED=yes

	if mountpoint -q $CHROOT_DIR; then
		busybox fuser -m $CHROOT_DIR | xargs kill 2> /dev/null
		sleep 1
		busybox fuser -m $CHROOT_DIR | xargs kill -9 2> /dev/null
		for p in dev/pts dev sys proc /; do
			umount $CHROOT_DIR/$p
		done
	fi
	rmdir $CHROOT_DIR
	[ -z $KEEP_DIR ] && ! [ -e $BUILD_DIR/keep ] && 
	rm -r $BUILD_DIR
	echo done
}

###
init() {
	# clean slate
	PKG_NOMAKEPKG= PKG_NOBUILD= PKG_NOSTRIP=

	if [ $UNIONFS_FUSE ]; then
		# check whether we have the binary and can use this mode
		type $UNIONFS_FUSE > /dev/null || UNIONFS_FUSE=""
	fi

	chmod 0755 $BUILD_DIR # mktemp always creates 0700
	mkdir -p $PKG_DIR $SRC_DIR $OUTPUT_DIR $CHROOT_DIR
	if [ $UNIONFS_FUSE ]; then
		unionfs -o cow -o hide_meta_files $BUILD_DIR=RW:/ $CHROOT_DIR || exit
		mkdir -p $BUILD_DIR/.unionfs-fuse/tmp_HIDDEN~ $BUILD_DIR/tmp # hide the real /tmp for building
	else
		local robranches
		[ -z "$AUFS_ROOT_ID" ] && AUFS_ROOT_ID=$(
awk '{ if ($2 == "/" && $3 == "aufs") { match($4,/si=[0-9a-f]*/); print "si_" substr($4,RSTART+3,RLENGTH-3) } }' \
/proc/mounts | tail -n 1
)
		if [ $AUFS_ROOT_ID ]; then
			robranches=$(ls -v /sys/fs/aufs/$AUFS_ROOT_ID/br[0-9]* | xargs sed 's|=rw|=ro|' | tr '\n' ':') 
		else
			# not using aufs - assuming we can use root as aufs branch
			robranches=/
		fi	
		mount -t aufs aufs -o br:$BUILD_DIR:$robranches $CHROOT_DIR || exit
		rm -rf $CHROOT_DIR/tmp/* # clean /tmp for building
	fi
	for p in sys proc dev dev/pts; do
		mount -o bind /$p $CHROOT_DIR/$p
	done
}

###
prepare() {
	find_pkg $PKG_DIR $PKG $FINDPKG_CACHE || return 1
	echo preparing $PKG
		
	# create generic build script, can be overridden if need be
	cat > $CHROOT_DIR/tmp/build.sh << EOF
#!/bin/sh
[ -e /tmp/functions.sh ] && . /tmp/functions.sh
[ -e /tmp/env.sh ] && . /tmp/env.sh
[ -e /tmp/pkg/recipe ] && . /tmp/pkg/recipe
type setup_arch_vars > /dev/null && setup_arch_vars
type pkg_build > /dev/null && pkg_build || 
{ echo "Build error $PKG, dropping to temporary shell."; sh < /dev/tty > /dev/tty 2>/dev/tty; }
EOF
	chmod +x $CHROOT_DIR/tmp/build.sh
	
	# load default functions and env, and reload package info (override ones in function/env)
	[ -e functions.sh ] && . ./functions.sh && cp functions.sh $CHROOT_DIR/tmp
	[ -e env.sh ] && . ./env.sh && cp env.sh $CHROOT_DIR/tmp
	. $PKG_FULL_PATH/recipe
	type setup_arch_vars > /dev/null && setup_arch_vars
	
	# copy pkg files to build dir
	cp -a $PKG_FULL_PATH $CHROOT_DIR/tmp/pkg
	
	# run prepare
	type pkg_prepare > /dev/null && ( cd $CHROOT_DIR; pkg_prepare; )
	[ $? -ne 0 ] && echo "Failed prepare phase." && return 1
	return 0
}

###
build() {
	echo building $PKG
	#chroot $CHROOT_DIR /tmp/build.sh
	[ "$PKG_NOBUILD" ] && return 0

	LD_LIBRARY_PATH= chroot $CHROOT_DIR /bin/env -i HOME=/root USER=root TERM=$TERM \
	   BUILD32="-m32" BUILD64="-m64" CLFS_TARGET32="i686-pc-linux-gnu" \
	   PKG_CONFIG_PATH32=/usr/lib/pkgconfig PKG_CONFIG_PATH64=/usr/lib64/pkgconfig \
	   PS1='\u:\w# ' PATH=/usr/bin:/usr/sbin:/bin:/sbin:/tools/bin \
	   /tmp/build.sh
	[ $? -ne 0 ] && echo "Failed build phase." && return 1
	return 0
}

###
package() {
	echo packaging $PKG
	#mkdir -p $CHROOT_DIR/$PKG_COPY && cp $PKG_FULL_PATH $CHROOT_DIR/$PKG_COPY
	mkdir -p $CHROOT_DIR/$PKG_COPY && 
	tar -C ${PKG_FULL_PATH%/*} -czf $CHROOT_DIR/$PKG_COPY/$PKG.tar.gz ${PKG_FULL_PATH##*/}
	if type pkg_package > /dev/null; then # pkg_package is optional
		( cd $CHROOT_DIR; pkg_package; )
	fi &&
	(
		cd $BUILD_DIR
		if [ $UNIONFS_FUSE ]; then
			rm -rf .unionfs-fuse		
		else
			rm -rf .wh..wh.orph .wh..wh.plnk tmp # for aufs		
			find . -name ".wh.*" -delete 2>/dev/null # for aufs
		fi
		rm -rf tmp root/.cache root/.ccache usr/share/info/dir root/.distcc
		[ -z "$PKG_NOSTRIP" ] && find . -type f -print0 | xargs -0 strip --strip-unneeded 2> /dev/null
		[ -z "$PKG_NOMAKEPKG" ] && ! [ -e no-makepkg ] && 
		$MAKEPKG -c n -l n $OUTPUT_DIR/$PKG.$PKG_TYPE > /dev/null 2>&1 || return 0
	)
	[ $? -ne 0 ] && echo "Failed packaging phase." && return 1
	return 0
}

### main
init
prepare && build && package; RESULT=$?
cleanup
