#!/bin/sh
#
# Make whichever packages the system supports
#
# Copyright (c) 2012-2014 Red Hat.
# Copyright (c) 2004 Silicon Graphics, Inc.  All Rights Reserved.
# 
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
# 
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#

topdir=`pwd`
verbose=false
nonrpm=unknown
nondeb=unknown

if [ ! -d .git ]
then
    echo "Error: can only be run from within the PCP git repository"
    exit 1
fi

if [ ! -f VERSION.pcp ]
then
    echo "Error: can only be run from within the PCP source tree"
    exit 1
fi

# Find where a GNU tool is hiding, look for this line:
# "Report bugs to <bug-$gnutool@gnu.org>"
# or this line:
# "FreeBSD $gnutool YYYYMMDD"
# in the $gnutool --help output
#
gnu_tool()
{
    prefix="$1"
    shift
    envvar="$1"
    shift
    oldcmd="$1"
    shift

    # Not in the environment, go search for it in the known locations.
    #
    if [ -z "$envvar" ]
    then
	for command in $oldcmd $@
	do
	    exec=`which $command 2>/dev/null`
	    if [ -n "$exec" ]
	    then
		if $command --help 2>&1 | egrep -q "(bug-$oldcmd@gnu.org)|(FreeBSD $gnutool)"
		then
		    echo $exec
		    return 0
		fi
	    fi
	done
	echo "$prefix: can't find GNU $oldcmd in the commands $oldcmd or $@"
	[ $prefix = Error ] && exit 1
	return 1
    fi

    # Use the environment request and ensure it is a full path (do not
    # change this behaviour, it is required for backward-compatibility
    # - QA failures will result if you choose to ignore this warning).
    #
    command=`which $envvar 2>/dev/null`
    if [ -z "$command" ]
    then
	echo "$prefix: $oldcmd (from the environment) does not exist!" >&2
	[ $prefix = Error ] && exit 1
	return 1
    fi
    echo $command
    return 0
}

export MAKE=`gnu_tool Error "$MAKE" make gmake`
export TAR=`gnu_tool Warning "$TAR" tar gtar gnutar`
export ZIP=`gnu_tool Error "$ZIP" gzip gnuzip`

# check if tar supports --transform else we must use git-archive later on (e.g. RHEL5)
[ ! -z "$TAR" ] && $TAR --help | 2>&1 grep -q transform || USE_GIT_ARCHIVE=1

tmp=`mktemp -d /tmp/pcp.XXXXXXXXX` || exit 1
trap "rm -rf $tmp" 0 1 2 3 15

# Bog-standard options suitable for a package on any platform.
# Command line can be used to extend this set, and any whacko
# platform-specific requirements are also appended later on.
#
configure=./configure
configopts="--prefix=/usr --sysconfdir=/etc --localstatedir=/var"
target=`uname -s | cut -c-5 | tr 'A-Z' 'a-z'`

for opt in $*
do
    case "$opt" in
    -clean|--clean)
	# we always clean nowadays
	shift
	;;
    -verbose|--verbose)
	verbose=true
	shift
	;;
    --nonrpm)
	nonrpm=true
	shift
	;;
    --nondeb)
	nondeb=true
	shift
	;;
    --target)
	shift
	target=$1
	shift
	;;
    *)
	# Add remaining options to the ./configure command line
	configopts="$configopts $opt"
	shift
	;;
    esac
done

if [ "$nonrpm" = "unknown" ]
then
    nonrpm=true
    test -f /usr/bin/rpmbuild && nonrpm=false
fi
if [ "$nondeb" = "unknown" ]
then
    nondeb=true
    test -f /usr/bin/dpkg-buildpackage && nondeb=false
fi

case "$target"
in
    mingw)
	nonrpm=true
	configure="mingw64-configure"
	configopts="$configopts --disable-ssp --without-threads"
	MAKE="mingw64-make"
	;;
    linux)
	ARCH=`uname -m`
	[ -f /etc/slackware-version -a "$ARCH" = x86_64 ] && \
	configopts="$configopts --libdir=/usr/lib64"
	;;
    sunos)
	ARCH=`isainfo -k`
	[ "$ARCH" = amd64 -o "$ARCH" = sparcv9 ] && \
	configopts="$configopts --libdir=/usr/lib/64"
	;;
esac

. ./VERSION.pcp
VERSION=${PACKAGE_MAJOR}.${PACKAGE_MINOR}.${PACKAGE_REVISION}

LOGDIR=$topdir/Logs
rm -rf $LOGDIR
mkdir -p "$LOGDIR"

source=pcp-${VERSION}
SRCDIR=$topdir/$source
SRCTAR=$topdir/build/tar/$source.src.tar.gz

build_failure()
{
    # only print in non-verbose mode, otherwise we see double
    if ! $verbose ; then
	echo $@ failed, see log in $LOGDIR/pcp
	tail $LOGDIR/pcp
    fi
    exit 1
}

clean_packaging()
{
    echo
    echo "== Cleaning build tree for packaging build"
    rm -rf "$SRCDIR" "$SRCTAR" .gitcensus
}

# Generate a list of all the files git knows about, create the
# source tarball and then unpack it.  We'll then do the package
# build in a guaranteed pristine environment.
#
src_tar_build()
{
    if [ -z "$TAR" -o ! -z "$USE_GIT_ARCHIVE" ]
    then
	# no suitable GNU tar is available, use git-archive(1) - no local changes
	git archive --format=tar --prefix=$source/ HEAD | $ZIP > $SRCTAR
    else
	# build git file list and make tarball by hand to pick up any changes
	git ls-files > .gitcensus
	$TAR -cz --transform="s,^,$source/," --files-from=.gitcensus \
		--file=$SRCTAR 
	rm .gitcensus
    fi
    echo "Wrote: $SRCTAR"
}

# On sanity checks :- this is sick, but I'm really tired of QA failing
# because of bad binaries being built from the Debian/Ubuntu toolchain
# for # i?86 platforms
# - Ken McDonell Apr 2010
#
sanity_check_settings()
{
    OPT=false
    ARCH=`uname -m | sed -e 's/i.86/ia32/'`
    if [ "$ARCH" != "ia32" ]
    then
	OPT=true	# no workarounds needed for non-i?86 platforms
    elif [ -f /etc/lsb-release ]
    then
	if grep -q 'DISTRIB_ID=Ubuntu' /etc/lsb-release
	then
	    eval `grep DISTRIB_RELEASE= /etc/lsb-release`
	    XDISTRIB_RELEASE=`echo $DISTRIB_RELEASE | sed -e 's/[^0-9]//g'`
	    [ -z "$XDISTRIB_RELEASE" ] && XDISTRIB_RELEASE=0000
	    if [ $XDISTRIB_RELEASE -gt 1110 ]
	    then
		# Hope the problem is fixed after Ubuntu 11.10
		OPT=true
	    fi
	fi
	$OPT || echo "Building without optimization for Ubuntu $DISTRIB_RELEASE"
    elif [ -f /etc/debian_version ]
    then
	DISTRIB_RELEASE=`cat /etc/debian_version`
	XDISTRIB_RELEASE=`echo $DISTRIB_RELEASE | sed -e 's/[^0-9]//g'`
	[ -z "$XDISTRIB_RELEASE" ] && XDISTRIB_RELEASE=0000
	if [ $XDISTRIB_RELEASE -ge 700 ]
	then
	    # Hope the problem is fixed in Debian 7.0.0
	    OPT=true
	fi
	$OPT || echo "Building without optimization for Debian $DISTRIB_RELEASE"
    fi

    if ! $OPT
    then
	ok=true
	if grep -q '^my $default_flags .*O2' /usr/bin/dpkg-buildpackage
	then
	    echo 'dpkg-buildpackage: need to remove O2 from $default_flags'
	    ok=false
	fi
	if grep -q '^[ 	]*LDFLAGS.*-Bsymbolic-functions' /usr/bin/dpkg-buildpackage
	then
	    echo 'dpkg-buildpackage: need to remove -Bsymbolic-function from LDFLAGS'
	    ok=false
	fi
	if ! $ok
	then
	    echo "Refer to Debian/Ubuntu notes in PCP's ./INSTALL"
	    exit 1
	fi
	# as of Debian 6.0.1 and Ubuntu 10.10, build flags are hidden and
	# extracted using dpkg-buildflags which fortunately honours some
	# environment variable settings
	#
	export DEB_CFLAGS_SET=''
	export DEB_CXXFLAGS_SET=''
	export DEB_LDFLAGS_SET=''
    fi
}

# Build Debian packages using the dpkg-buildpackage utility which runs
# the complete build, from configure through to final deb preparation.
#
debian_buildpackage()
{
    echo
    echo "== Building deb packages using dpkg-buildpackage"

    SUDO=${SUDO:-fakeroot}
    rm -f $tmp/failed
    if $verbose ; then
	(dpkg-buildpackage -r$SUDO || touch $tmp/failed) | tee -a $LOGDIR/pcp
    else
	(dpkg-buildpackage -r$SUDO || touch $tmp/failed) >> $LOGDIR/pcp
    fi
    [ -f $tmp/failed ] && build_failure debian buildpackage
}

prepare_debian_sources()
{
    # shortcut for dpkg-buildpackage which does everything itself from here
    SRCDIR="${topdir}/build/deb"
    mkdir -p "$SRCDIR" 2>/dev/null
    cd "$SRCDIR" || exit 1
    $TAR -zxf "$SRCTAR" || exit 1
    cd "$SRCDIR/$source" || exit 1
}

prepare_debian_control()
{
    echo
    echo "== Preparing source tree for dpkg-buildpackage"
    rm -f $tmp/failed debian/control
    if $verbose ; then
	($MAKE -C debian control 2>&1 || touch $tmp/failed) | tee -a $LOGDIR/pcp
    else
	($MAKE -C debian control 2>&1 || touch $tmp/failed) >> $LOGDIR/pcp
    fi
    [ -f $tmp/failed ] && build_failure debian control
}

debian_build()
{
    prepare_debian_sources
    configure_pcp
    prepare_debian_control
    sanity_check_settings
    debian_buildpackage
    exit 0
}

prepare_build()
{
    echo
    echo "== Preparing fresh build tree for packaging build"

    if [ ! -d "$SRCDIR" ]; then
	# extract gzipped tar archive
	$TAR -xz --file="$SRCTAR" || exit 1
    fi
}

configure_pcp()
{
    echo
    echo "== Configuring pcp, log is in $LOGDIR/pcp ($configopts)"

    rm -f $tmp/failed
    if $verbose
    then
	($configure $configopts 2>&1 || touch $tmp/failed) | tee -a $LOGDIR/pcp
    else
	($configure $configopts 2>&1 || touch $tmp/failed) >> $LOGDIR/pcp
    fi
    [ -f $tmp/failed ] && build_failure Configure
}

default_build()
{
    echo
    echo "== Building pcp, log is in $LOGDIR/pcp"

    rm -f $tmp/failed
    if $verbose ; then
	($MAKE default_pcp 2>&1 || touch $tmp/failed) | tee -a $LOGDIR/pcp
    else
	($MAKE default_pcp 2>&1 || touch $tmp/failed) >> $LOGDIR/pcp
    fi
    [ -f $tmp/failed ] && build_failure Make default_pcp
}

packaging_pcp()
{
    echo
    echo "== Packaging pcp, log is in $LOGDIR/pcp" | tee -a $LOGDIR/pcp

    rm -f $tmp/failed
    if $verbose ; then
	($MAKE -C build pack_pcp 2>&1 || touch $tmp/failed) | tee -a $LOGDIR/pcp
    else
	($MAKE -C build pack_pcp 2>&1 || touch $tmp/failed) >> $LOGDIR/pcp
    fi
    [ -f $tmp/failed ] && build_failure Packaging via pack_pcp
}

packaging_rpm()
{
    echo
    echo "== Building rpm packages, log is in $LOGDIR/pcp" | tee -a $LOGDIR/pcp

    rm -f $tmp/failed
    export DIST_ROOT=${topdir}/build/rpm/${source}
    if $verbose ; then
	($MAKE -C build/rpm pack_pcp 2>&1 || touch $tmp/failed) | tee -a $LOGDIR/pcp
    else
	($MAKE -C build/rpm pack_pcp 2>&1 || touch $tmp/failed) >> $LOGDIR/pcp
    fi
    [ -f $tmp/failed ] && build_failure Packaging RPMs via pack_pcp
}

# real build starts here
clean_packaging
src_tar_build

# short-circuit for performing builds with dpkg-buildpackage
$nondeb || debian_build

prepare_build

# shift into the clean packaging build tree from here onward
cd "$SRCDIR"

configure_pcp

# short-circuit for performing rpm-only builds with rpmbuild
# (skips over the default_build stage as rpmbuild does that).
if $nonrpm
then
    default_build	# perform a complete build in-situ
    packaging_pcp	# create all known package formats
else
    packaging_rpm
fi

# success!
if ! $verbose ; then
    grep '^Wrote:' $LOGDIR/pcp | sed -e 's/\.\.\/\.\.\///'
fi
exit 0
