#! /bin/bash
#
# Copyright (C) 2002, Earnie Boyd <earnie@users.sf.net>
# Copyright (C) 2007, 2009, 2010 Cesar Strauss <cestrauss@gmail.com>
#
# This file is a part of MinGW.
#
# Based on the msysrlsbld script, part of msysDVLPR
#   http://www.mingw.org/MinGWiki/index.php/MSYSBuildEnvironment
# Inspired on ideas from cygport, part of Cygwin.
# Inspired on the msys-build-bash script by Charles Wilson.

# The following src_* functions can be overrided in package-specific
# pkgbuild.ini files.

src_build()
{
  do_build
}

src_prep()
{
  do_prep
}

src_patch()
{
  do_patch
}

src_configure()
{
  do_configure
}

src_compile()
{
  do_compile
}

src_install()
{
  do_install
}

src_post_install()
{
  do_post_install
}

src_package()
{
  :
}

src_pack_source()
{
  do_pack_source
}

src_clean()
{
  do_clean
}

src_download()
{
  do_download
}

src_check()
{
  do_check
}

# Configure, make, make install
#
do_build()
{
  mkdir $builddir && cd $builddir || fail
  if [ ! -d $srcdir ]; then
    src_prep || fail
    src_patch || fail
  fi
  src_configure || fail
  src_compile || fail
  src_install || fail
  src_post_install || fail
  src_package || fail
}

# Prepare the source and build directories
#
do_prep()
{
  if [ -z "$src_filenames" ]; then return; fi
  echo "Unpacking the original sources..."
  cd $workdir
  for src in $src_filenames; do
    tar -xf $src_basedir/$src || fail
  done
}

# Patch source files
#
do_patch()
{
  if [ -z "$src_patches" ]; then return; fi
  echo "Applying local patches..."
  cd $srcdir
  for p in $src_patches; do
    echo $p
    patch -p1 -i $patchdir/$p || fail
  done
}

# Configure the build system
#
do_configure()
{
  echo "Configuring..."
  cd $builddir && 
  $srcdir/configure --prefix=/mingw $install_dirs $configure_opt
}

# Compile the sources
#
do_compile()
{
  echo "Compiling..."
  cd $builddir &&
  make $compile_opt
}

# Install in a staging area
#
do_install()
{
  echo "Installing into a staging area..."
  cd $builddir &&
  make install prefix=$instdir $install_opt
}

# Post-install stuff, like packaging documentation
#
do_post_install()
{
  echo "Installing package docs..."
  rm -f $instdir/share/info/dir
  cd $srcdir
  if [ -n "$pkgdocfiles" -o -n "$licfiles" ]; then
    mkdir -p $instdir/$docdir
    for doc in $pkgdocfiles $licfiles; do
      if [ -f $doc ]; then
        cp -p $doc $instdir/$docdir
      fi
    done
  fi
  if [ -f $basedir/mingw-$pkg_name.RELEASE_NOTES.txt ]; then
    mkdir -p $instdir/share/doc/MinGW
    cp -p $basedir/mingw-$pkg_name.RELEASE_NOTES.txt \
      $instdir/share/doc/MinGW/$pkg_name-$pkg_version-$pkg_build${subsys_name:+-}$subsys_name.RELEASE_NOTES.txt
  fi
}

# Clean the workplace
#
do_clean()
{
  echo "Cleaning the workplace..."
  rm -rf $builddir $instdir
  # Only remove the source directory if it was unpacked by us.
  if [ -n "$src_filenames" ]; then
    rm -rf $srcdir
  fi
}

# Download the source
#
do_download()
{
  if [ -n "$download" ]; then
    if command -v wget > /dev/null; then
      cd $src_basedir
      mkdir -p partial
      for src in $src_filenames; do
        if [ ! -f $src ]; then
          if wget -c $download/$src -O partial/$src; then
            mv partial/$src $src
            rmdir partial
          else
            echo "Could not download $src"
            exit 1
          fi
        fi
      done
    else
      echo "wget is needed for downloading source archives."
      exit 1
    fi
  else
    echo "Download location was not specified."
    exit 1
  fi
}

# Package the build results
#
do_package()
{
  echo "Packaging the build results..."
}

# Create the source package
#
do_pack_source()
{
  echo "Creating the source package..."
  local pkgdir
  local pkg_filename
  pkg_filename=$pkg_name-$pkg_version-$pkg_build
  pkg_filename+=-$subsys_name${subsys_version:+-}$subsys_version
  pkgdir=$pkg_filename-src
  mkdir $workdir/$pkgdir
  cd $basedir
  ln $src_files $workdir/$pkgdir
  cp mingw-$pkg_name.RELEASE_NOTES.txt \
    $workdir/$pkg_filename.README.txt
  pack $pkg_name src $pkgdir
  rm -r $pkgdir
}

# Runs self-tests
#
do_check()
{
  echo "Running self-tests..."
  cd $builddir &&
  make -k check
}

pack()
{
  local pkg_id=$1; shift
  local pkg_type=$1; shift
  local pkg_files=$@
  local pkg_filename=$workdir/
  pkg_filename+=$pkg_id-$pkg_version-$pkg_build
  pkg_filename+=-$subsys_name${subsys_version:+-}$subsys_version
  if [ $pkg_type == "src" ]; then
    cd $workdir
  else
    cd $instdir
  fi
  local archive=$pkg_filename-$pkg_type.tar.lzma
  echo
  basename $archive
  tar --lzma -cvf $archive $pkg_files || fail
}

pack_dev()
{
  pack $pkg_name dev $devfiles
}

pack_bin()
{
  pack $pkg_name bin $binfiles
}

pack_dll()
{
  local pkg_id=$1
  local pkg_soname=$2
  local pkg_file=bin/$pkg_id-$pkg_soname.dll
  pack $pkg_id dll-$pkg_soname $pkg_file
}

pack_docdir()
{
  local abs_docfiles
  local pkg_type=$1; shift
  local pkg_files=$@
  for f in $pkg_files; do
    abs_docfiles+=" $docdir/$f"
  done
  if [ $pkg_type == "doc" ]; then
    abs_docfiles+=" $docfiles"
  fi
  pack $pkg_name $pkg_type $abs_docfiles
}

pack_doc()
{
  pack_docdir doc $pkgdocfiles
}

pack_lic()
{
  pack_docdir lic $licfiles
}

fail()
{
  echo
  echo "============="
  echo "Task failed."
  echo "============="
  exit 1
}

succeed()
{
  echo
  echo "================"
  echo "Task succeeded."
  echo "================"
}

show_help()
{
  echo "$0: Build packages from source"
  echo "Usage:"
  echo "  $0 [-h] [-e command]"
  echo "With no arguments, it builds from source and packages the result."
  echo "Use -h to show this message."
  echo "Use -e to run a specific phase. Commonly accepted ones are:"
  echo "        prep : Unpacks the original sources."
  echo "       patch : Apply custom patches."
  echo "   configure : Runs the configure script."
  echo "     compile : Runs make."
  echo "     install : Installs into a staging area."
  echo "post_install : Performs extra install activity (ex. docs)."
  echo "     package : Packages the build results."
  echo " pack_source : Re-creates the source package."
  echo "       check : Runs self-tests."
  echo "       clean : Cleans the workplace."
}

if [ "$1" == "-h" ]; then
  show_help
  exit
fi

# Locate the base directory
basedir=`dirname "$0"`
basedir=`cd "$basedir" && pwd`

# Working directory
workdir=$PWD

# Default compiler flags
export CFLAGS='-O3 -s -pipe'
export CXXFLAGS=$CFLAGS
export LDFLAGS='-Wl,-s'

# Read the package-specific build instructions.
#
if [ -f "$basedir/pkgbuild.ini" ]
then
  . "$basedir/pkgbuild.ini"
else
  echo "pkgbuild.ini file missing."
  exit 1
fi

# Read the system-wide preferences
#
if [ -f /etc/msysrlsbld.pref ]
then
  . /etc/msysrlsbld.pref
fi

# Read the user-specific preferences
#
if [ -f ${HOME}/msysrlsbld.pref ]
then
  . ${HOME}/msysrlsbld.pref
fi

# Location for the packed sources
: ${src_basedir:=$basedir}

# List of the filenames of the packed sources
: ${src_names:=$src_name}

# Name of the source archive
: ${src_filenames:=$src_filename}

if [ -z "$src_filenames" ]; then
  cd $src_basedir
  for item in $src_names; do
    for src in ${item}.tar.*; do
      if [ -f $src ]; then
        src_filenames+=" $src";
        break;
      fi
    done
  done
fi

# List of patches
: ${src_patches:=$src_patch}

# Location of the patches
: ${patchdir:=$basedir}

# Directory name of the extracted sources
: ${src_dirname:=${pkg_name}-${pkg_version}}

# Top-level source directory
: ${srcdir:=$workdir/$src_dirname}

# Location for building
: ${builddir:=$workdir/build}

# Location of staging directory
: ${instdir:=$workdir/nstl}

# Directory for placing package-specific documentation.
: ${docdir:=share/doc/${pkg_name}/${pkg_version}}

# Default install locations:
: ${install_dirs:="
  --datarootdir=\${prefix}/share
  --docdir=\${prefix}/$docdir
  --sbindir=\${prefix}/sbin
  --sysconfdir=/etc
  --localstatedir=/var
"}

# Package dev files
: ${devfiles:="include lib"}

# Package doc files
: ${pkgdocfiles:="AUTHORS Changelog NEWS README"}

# Doc files
: ${docfiles:="share/man share/info share/doc/MinGW"}

# Package lic files
: ${licfiles:="COPYING*"}

# Package bin files
: ${binfiles:="bin --exclude *.dll"}

# Package source files
: ${src_files:="
    $src_filenames
    $src_patches
    pkgbuild
    pkgbuild.ini
    mingw-$pkg_name.RELEASE_NOTES.txt
  "}

cmd=build

if [ -n "$1" ]; then
  case "$1" in
    -e) cmd=$2;;
    *)  echo "$0: $1: Unknown option. Use -h for help."; exit;;
  esac
fi

if src_$cmd; then
  succeed
else
  fail
fi
