#! /bin/sh
#  include-boost-src -- from the preferred upstream version
#  Copyright (C) 2013, 2014  Olaf Meeuwissen
#  Copyright (C) 2012  EPSON AVASYS CORPORATION
#
#  License: GPL-3.0+
#  Author : Olaf Meeuwissen
#
#  This file is part of the 'Utsushi' package.
#  This package 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 3 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.
#
#  You ought to have received a copy of the GNU General Public License
#  along with this package.  If not, see <http://www.gnu.org/licenses/>.

#  Show script usage documentation and exits the program with an
#  optional status passed as its first argument.

usage () {
    cat <<EOF
'`basename $0`' from the preferred upstream VERSION

Usage: $0 [--source=SOURCE] [VERSION [DIRECTORY]]
       $0 --help

Attempts to copy parts of the Boost upstream sources into the upstream
sources needed for this project.  It will only consider upstream Boost
versions that are at VERSION (default=$version).  Files will be copied
into DIRECTORY (default=$upstream_dir).

The script expects an extracted upstream Boost source directory in the
SOURCE directory.  It will download an archive with the upstream Boost
sources using \`wget\` from the official download site and extract that
if necessary.

The following options are supported:

  -h, --help              display this message and exit
      --source=SOURCE     download, extract and look for upstream sources
                          in SOURCE (default=$download_dir)

The DIRECTORY argument is for testing purposes and should normally not
be used.

TODO: support additional archive formats
EOF
    exit $1
}

#  Set initial values of global variables.

DO_HELP=no

#  Process command line options and arguments.

parsed_opts=`getopt \
    --options h \
    --longopt help,source: \
    -- "$@"`

if test 0 != $?; then
    echo "`basename $0`: error parsing command line options" >&2
    usage 1
fi

eval set -- "$parsed_opts"

while test x-- != "x$1"; do
    case "$1" in
        -h|--help)              DO_HELP=yes;;
        --source)               SOURCE="$2"; shift;;
        *)
            echo "`basename $0`: internal inconsistency" >&2
            exit 119            # Japanese emergency phone number ;-)
            ;;
    esac
    shift
done
shift                           # past the '--' marker

#  Using sed rather than autoconf -t here for two reasons:
#   1) autoconf -t is slow.  We use these variables in usage() and do not
#      want to wait that long.
#   2) tracing AX_BOOST_BASE requires an autom4te.cache.  When we want to
#      use this script to roll a source archive, i.e. during `make dist`,
#      that directory does not exist (nor do we want it to!).

configure_ac=`dirname $0`/../configure.ac
aux_dir=`sed -n \
    '/AC_CONFIG_AUX_DIR/s/[^(]*([[]\{0,1\}\([^])]*\)[])].*/\1/p' \
    $configure_ac`
version=`sed -n \
    '/AX_BOOST_BASE/s/[^(]*([[]\{0,1\}\([.0123456789]*\).*/\1/p' \
    $configure_ac | sed '/^$/d'`
upstream_dir=$aux_dir/boost
download_dir=$aux_dir/downloads

test xno != x$DO_HELP && usage

if test -n "$1"; then
    version=`echo $1 | sed 's/_/./g'`
    shift
fi
if test -n "$1"; then
    upstream_dir=$1
    shift
fi
if test 0 -ne $#; then
    usage 1
fi

test -z "$SOURCE" || download_dir=$SOURCE

test -d $upstream_dir || mkdir -p $upstream_dir
test -d $download_dir || mkdir -p $download_dir

_version_=`echo $version | sed 's/\./_/g'`
sources=$download_dir/boost_$_version_

url=http://sourceforge.net/projects/boost/files/boost
fmt=tar.bz2

if ! test -f $sources.stamp; then
    (cd $download_dir; \
        wget --timestamping --continue $url/$version/boost_$_version_.$fmt)
    if test 0 != $?; then
        echo "`basename $0`: error downloading Boost source archive" >&2
        exit 1
    else
        touch $sources.stamp
    fi
fi
if ! test -d $sources; then
    echo -n "Extracting Boost source archive ... "
    (cd $download_dir; tar xf boost_$_version_.$fmt --bzip2)
    if test 0 != $?; then
        echo "`basename $0`: error extracting Boost source archive" >&2
        exit 1
    fi
    echo "done"
fi

echo "Using $sources"

#  Figure out what Boost modules are needed for our code base.

uppercase=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lowercase=abcdefghijklmnopqrstuvwxyz
boost_modules=`sed -n "/AX_BOOST_/{ \
    /AX_BOOST_BASE/d; \
    s/.*AX_BOOST_\([_$uppercase]*\).*/\1/; \
    y/$uppercase/$lowercase/; \
    p }" $configure_ac`

#  Include those sources that our code base references (in)directly.
#  Then, includes full sources for bjam (now Boost.Build) and bcp as
#  well as the modules our code base used.  This will overwrite some
#  of the files included in the first step.

#  Full sources of referenced modules are included in order to build
#  the corresponding libraries that we may want to link against.  If
#  just shipping those sources found by bcp from our code base, some
#  files needed to build the library may not be included (because we
#  don't reference them at all).  In that case bjam cannot build the
#  library we need and we obviously cannot link against them.
#  The bjam sources are needed so we can refer to a usable bjam tool
#  when building the Boost libraries.  The bcp sources are needed so
#  we have a usable bcp tool to put our source archive together.

bcp --boost=$sources \
    --scan `find \( -path ./$aux_dir -prune -o -path './_*' -prune \) \
    -o \( -type f -a -regex '.*\.[chi]pp' \) | sed -n '/\.[chi]pp$/p'` \
    $upstream_dir
bcp --boost=$sources bcp build $boost_modules $upstream_dir

#  Make sure we include the Boost License text and root Jamfile.

cp $sources/LICENSE_1_0.txt $upstream_dir
cp $sources/Jamroot $upstream_dir
cp $sources/boostcpp.jam $upstream_dir

#  Patch up the Boost.Math sources so they build.  It seems that bcp
#  misses the dependency on the Boost.Math config directory.

if test -d $upstream_dir/libs/math; then
    if ! test -d $upstream_dir/libs/math/config; then
        cp -a $sources/libs/math/config $upstream_dir/libs/math
    fi
fi

#  Manually add any files that bcp cannot trace due to their #include
#  statements using macros to compute the file name.  The list likely
#  depends on compile-time preprocessor flag so we may miss some.
#  Note, bcp generates CAUTION: lines for such #include statements.
#
#  Also note that the list was created using Ubuntu 10.04LTS with an
#  upstream source tarball from the Ubuntu oneiric archives.  Expect
#  more recent bcp versions to do a better job.

for f in \
    boost/function_types/detail/components_impl/arity10_0.hpp \
    boost/function_types/detail/components_impl/arity10_1.hpp \
    boost/function_types/detail/components_impl/arity20_0.hpp \
    boost/function_types/detail/components_impl/arity20_1.hpp \
    boost/function_types/detail/components_impl/arity30_0.hpp \
    boost/function_types/detail/components_impl/arity30_1.hpp \
    boost/function_types/detail/components_impl/arity40_0.hpp \
    boost/function_types/detail/components_impl/arity40_1.hpp \
    boost/function_types/detail/components_impl/arity50_0.hpp \
    boost/function_types/detail/components_impl/arity50_1.hpp \
    boost/function_types/detail/pp_arity_loop.hpp \
    boost/function_types/detail/pp_cc_loop/preprocessed.hpp \
    boost/function_types/detail/pp_tags/cc_tag.hpp \
    boost/function_types/detail/pp_variate_loop/preprocessed.hpp \
    boost/proto/detail/local.hpp \
    ; do
    test -d $upstream_dir/`dirname $f` || mkdir -p $upstream_dir/`dirname $f`
    cp -a $sources/$f $upstream_dir/$f
done

#  Fix up the Boost.Test static library build.  Its documentation says
#  one ought to define BOOST_TEST_ALTERNATIVE_INIT_API when compiling
#  both the library and one's test runners in static linking scenarios.
#  Unless BOOST_TEST_NO_MAIN is defined when building the library, it
#  will include a definition of main(), which is highly undesirable as
#  we roll our own.

sed -i '/: requirements <link>shared:<define>BOOST_TEST_DYN_LINK=1/a\
                   <link>static:<define>BOOST_TEST_ALTERNATIVE_INIT_API=1\
                   <link>static:<define>BOOST_TEST_NO_MAIN=1' \
    $upstream_dir/libs/test/build/Jamfile.v2

exit
