#!/bin/sh

## This program is not part of PSPP but is used to help build PSPP
## Copyright (C) 2021 John Darrington
##
## 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 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 should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.

# This script downloads (if necessary) and builds the required
# dependencies of PSPP. You may find it useful when cross building.
# Sadly, it it very likely that you'll have to tweak the order of the
# packages, the versions of the packages, their CFLAGS and other
# details in order to succesfully build for any particular
# architecture.  In its current form, it has been tweaked for building
# for mingw archs.

required_native_programs="awk sha256sum tar sed gtk-encode-symbolic-svg ninja meson cat grep pkg-config"

for p in $required_native_programs; do
    if ! type "$p" > /dev/null; then
        echo $p must be installed and in PATH;
        exit 1
    fi
done

while test $# -gt 0; do
    case $1 in
        --arch=*)
            arch=${1##--arch=};;
        --sandbox=*)
            SANDBOX=${1##--sandbox=};;
        --tarballs=*)
            SRC_TARBALL_DIR=${1##--tarballs=};;
        --no-clean)
            noclean=yes;;
        *)
            printf "Usage: $0 --arch=<arch> --sandbox=<dir> [--tarballs=<dir>]\n";
            exit 1;
        ;;
    esac
    shift 1;
done

if test -z "$SANDBOX" -o -z "$arch"; then
            printf "Usage: $0 --arch=<arch> --sandbox=<dir> [--tarballs=<dir>]\n";
    exit 1;
fi

SANDBOX=`eval echo $SANDBOX`

if test -z "$SRC_TARBALL_DIR"; then
    SRC_TARBALL_DIR="$SANDBOX/tarballs"
fi

SRC_TARBALL_DIR=`eval echo $SRC_TARBALL_DIR`

test "x$noclean" = "xyes" || rm -rIf $SANDBOX

default_build_procs=$(expr $(cat /proc/cpuinfo | grep -c '^processor') + 1)

mkdir -p $SRC_TARBALL_DIR

mkdir -p $SANDBOX

export DESTDIR=""

cat > $SANDBOX/cross-file.txt <<EOF
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

[binaries]
c = '$arch-gcc'
cpp = '$arch-g++'
ar = '$arch-ar'
ld = '$arch-ld'
objcopy = '$arch-objcopy'
strip = '$arch-strip'
pkgconfig = 'pkg-config'
windres = '$arch-windres'
glib-compile-resources = 'glib-compile-resources'
glib-compile-schemas = 'glib-compile-schemas'
EOF

tarballs="zlib-1.3.1.tar.gz"
tarballs="$tarballs libiconv-1.18.tar.gz"
tarballs="$tarballs gettext-0.21.tar.xz"
tarballs="$tarballs libffi-3.4.8.tar.gz"
tarballs="$tarballs pixman-0.40.0.tar.gz"
tarballs="$tarballs libpng-1.6.37.tar.gz"
tarballs="$tarballs libxml2-2.12.9.tar.xz"
tarballs="$tarballs freetype-2.10.4.tar.xz"
tarballs="$tarballs fribidi-1.0.10.tar.xz"
tarballs="$tarballs harfbuzz-11.4.5.tar.xz"
tarballs="$tarballs pcre2-10.44.tar.bz2"
tarballs="$tarballs glib-2.84.4.tar.xz"
tarballs="$tarballs cairo-1.18.4.tar.xz"
tarballs="$tarballs pango-1.56.4.tar.xz"
tarballs="$tarballs atk-2.36.0.tar.xz"
tarballs="$tarballs gdk-pixbuf-2.42.2.tar.xz"
tarballs="$tarballs libepoxy-1.5.5.tar.xz"
tarballs="$tarballs gtk-3.24.50.tar.xz"
tarballs="$tarballs gsl-2.8.tar.gz"
tarballs="$tarballs gtksourceview-4.8.4.tar.xz"
tarballs="$tarballs spread-sheet-widget-0.10.tar.gz"
tarballs="$tarballs hicolor-icon-theme-0.17.tar.xz"
tarballs="$tarballs adwaita-icon-theme-3.38.0.tar.xz"

mkdir -p $SANDBOX/Source
for t in $tarballs ; do
    url=""
    case $t in
        adwaita-icon-theme-3.38.0.tar.xz)
            url="https://download.gnome.org/sources/adwaita-icon-theme/3.38/adwaita-icon-theme-3.38.0.tar.xz";
            hash=6683a1aaf2430ccd9ea638dd4bfe1002bc92b412050c3dba20e480f979faaf97;;
        hicolor-icon-theme-0.17.tar.xz)
            url="https://icon-theme.freedesktop.org/releases/hicolor-icon-theme-0.17.tar.xz";
            hash=317484352271d18cbbcfac3868eab798d67fff1b8402e740baa6ff41d588a9d8;;
        gettext-0.21.tar.xz)
            url="https://ftpmirror.gnu.org/gnu/gettext/gettext-0.21.tar.xz";
            hash=d20fcbb537e02dcf1383197ba05bd0734ef7bf5db06bdb241eb69b7d16b73192;;
        spread-sheet-widget-0.10.tar.gz)
            url="https://alpha.gnu.org/gnu/ssw/spread-sheet-widget-0.10.tar.gz";
            hash=80692ec350271995e147dc759929cdd79d3b645e6b5efaa6b57f4d2d05e847e5;;
        gtksourceview-4.8.4.tar.xz)
            url="https://download.gnome.org/sources/gtksourceview/4.8/gtksourceview-4.8.4.tar.xz"
            hash=7ec9d18fb283d1f84a3a3eff3b7a72b09a10c9c006597b3fbabbb5958420a87d;;
        libepoxy-1.5.5.tar.xz)
            url="https://github.com/anholt/libepoxy/releases/download/1.5.5/libepoxy-1.5.5.tar.xz"
            hash=261663db21bcc1cc232b07ea683252ee6992982276536924271535875f5b0556;;
        gdk-pixbuf-2.42.2.tar.xz)
            url="https://download.gnome.org/sources/gdk-pixbuf/2.42/gdk-pixbuf-2.42.2.tar.xz";
            hash=83c66a1cfd591d7680c144d2922c5955d38b4db336d7cd3ee109f7bcf9afef15;;
        atk-2.36.0.tar.xz)
            url="https://download.gnome.org/sources/atk/2.36/atk-2.36.0.tar.xz";
            hash=fb76247e369402be23f1f5c65d38a9639c1164d934e40f6a9cf3c9e96b652788;;
        gtk-3.24.50.tar.xz)
            url="https://download.gnome.org/sources/gtk/3.24/gtk-3.24.50.tar.xz";
            hash=399118a5699314622165a11b769ea9b6ed68e037b6d46d57cfcf4851dec07529;;
        cairo-1.18.4.tar.xz)
            url="http://cairographics.org/releases/cairo-1.18.4.tar.xz";
            hash=445ed8208a6e4823de1226a74ca319d3600e83f6369f99b14265006599c32ccb;;
        harfbuzz-11.4.5.tar.xz)
            url="https://github.com/harfbuzz/harfbuzz/releases/download/11.4.5/harfbuzz-11.4.5.tar.xz";
            hash=0f052eb4ab01d8bae98ba971c954becb32be57d7250f18af343b1d27892e03fa;;
        fribidi-1.0.10.tar.xz)
            url="https://github.com/fribidi/fribidi/releases/download/v1.0.10/fribidi-1.0.10.tar.xz";
            hash=7f1c687c7831499bcacae5e8675945a39bacbad16ecaa945e9454a32df653c01;;
        libffi-3.4.8.tar.gz)
            url="https://github.com/libffi/libffi/releases/download/v3.4.8/libffi-3.4.8.tar.gz";
            hash=bc9842a18898bfacb0ed1252c4febcc7e78fa139fd27fdc7a3e30d9d9356119b;;
        zlib-1.3.1.tar.gz)
            url="https://zlib.net/fossils/zlib-1.3.1.tar.gz";
            hash=9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23;;
        pixman-0.40.0.tar.gz)
            url="https://www.cairographics.org/releases/pixman-0.40.0.tar.gz";
            hash=6d200dec3740d9ec4ec8d1180e25779c00bc749f94278c8b9021f5534db223fc;;
        libpng-1.6.37.tar.gz)
            url="https://download.sourceforge.net/libpng/libpng-1.6.37.tar.gz";
            hash=daeb2620d829575513e35fecc83f0d3791a620b9b93d800b763542ece9390fb4;;
        freetype-2.10.4.tar.xz)
            url="https://download.savannah.gnu.org/releases/freetype/freetype-2.10.4.tar.xz";
            hash=86a854d8905b19698bbc8f23b860bc104246ce4854dcea8e3b0fb21284f75784;;
        glib-2.84.4.tar.xz)
            url="https://download.gnome.org/sources/glib/2.84/glib-2.84.4.tar.xz";
            hash=8a9ea10943c36fc117e253f80c91e477b673525ae45762942858aef57631bb90;;
        pango-1.56.4.tar.xz)
            url="https://download.gnome.org/sources/pango/1.56/pango-1.56.4.tar.xz";
            hash=17065e2fcc5f5a5bdbffc884c956bfc7c451a96e8c4fb2f8ad837c6413cb5a01;;
        gsl-2.8.tar.gz)
            url="http://ftpmirror.gnu.org/gnu/gsl/gsl-2.8.tar.gz";
            hash=6a99eeed15632c6354895b1dd542ed5a855c0f15d9ad1326c6fe2b2c9e423190;;
        libiconv-1.18.tar.gz)
            url="http://ftpmirror.gnu.org/gnu/libiconv/libiconv-1.18.tar.gz";
            hash=3b08f5f4f9b4eb82f151a7040bfd6fe6c6fb922efe4b1659c66ea933276965e8;;
        libxml2-2.12.9.tar.xz)
            url="https://download.gnome.org/sources/libxml2/2.12/libxml2-2.12.9.tar.xz";
            hash=59912db536ab56a3996489ea0299768c7bcffe57169f0235e7f962a91f483590;;
        pcre2-10.44.tar.bz2)
            url="https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.44/pcre2-10.44.tar.bz2";
            hash=d34f02e113cf7193a1ebf2770d3ac527088d485d4e047ed10e5d217c6ef5de96;;
        *) hash=XX;;
    esac

    # Fetch the tarball if we don't already have it.
    if ! test -e $SRC_TARBALL_DIR/$t; then
        (cd $SRC_TARBALL_DIR && wget $url)
    fi

    case $t in
        pspp-*)
            # Don't check the hash for this since it's changing rapidly
        ;;
        *)    # Check that it hasn't been corrupted or compromised
              h=`(cd $SRC_TARBALL_DIR && sha256sum $t) | awk '{print $1}'`
              if ! test "$hash" = $h ; then
                  echo "Hash for $t is invalid" ;
                  exit 1
              fi
              ;;
    esac
done

# No network access should be necessary after this point
for t in $tarballs ; do
    # Unpack the tarballs into the Source directory
    case $t in
        *.zip)
            pkg=${t%%.zip}
            unarch="unzip -o"
            ;;
        *.tar.xz)
            pkg=${t%%.tar.xz}
            unarch="tar -xJf"
            ;;
        *.tar.gz)
            pkg=${t%%.tar.gz}
            unarch="tar -xzf"
            ;;
        *.tar.bz2)
            pkg=${t%%.tar.bz2}
            unarch="tar -xjf"
            ;;
        *)
            echo "Unknown archive suffix: $t";
            exit 1;
            ;;
    esac

    (cd $SANDBOX/Source && $unarch  $SRC_TARBALL_DIR/$t)

    # Build the package
    rm  -rf $SANDBOX/Build/$pkg
    mkdir -p $SANDBOX/Build/$pkg
    build_procs=$default_build_procs
    case $pkg in
        # Deal with the special cases here
        zlib-*)
            cd $SANDBOX/Build/$pkg && \
                CC=$arch-gcc AR=$arch-ar RANLIB=$arch-ranlib LDSHAREDLIBC="" $SANDBOX/Source/$pkg/configure --prefix="$SANDBOX/Install" && \
                make -j $build_procs && make install
            ;;
        # And now the generic cases
        *)
            depdir=$SANDBOX/Install
            build_system="autoconf"
            pre_configure=""
            prefix=$SANDBOX/Install
            meson_opts=""
            extra_cflags=""
            extra_ldflags=""
            extra_config_flags=""
            case $pkg in
                cairo-*)
                    build_system="meson"
                    extra_cflags="-fstack-protector";;
                gsl-*)
                    extra_config_flags="GSL_LDFLAGS=-XCClinker -fstack-protector";
                    extra_cflags="-fstack-protector";;
                libepoxy-*)
                    build_system="meson";
                    ;;
                gtk-*)
                    build_system="meson";
                    meson_opts="-Dintrospection=false -Dtests=false -Ddemos=false -Dexamples=false";
                    ;;
                gtksourceview-*)
                    build_system="meson";
                    meson_opts="-Dgir=false";
                    ;;
                gdk-pixbuf-*)
                    build_system="meson";
                    meson_opts="-Dintrospection=disabled -Dbuiltin_loaders=all -Dnative_windows_loaders=true -Dinstalled_tests=false -Dman=false";
                    ;;
                atk-*)
                    build_system="meson";
                    meson_opts=-Dintrospection=false;
                    ;;
                pcre2-*)
                    ;;
                glib-*)
                    build_system="meson";
                    meson_opts="-Dtests=false -Dintrospection=disabled";
                    #extra_cflags=-Wno-format;  #no-format seems to be necessary for 32 bit builds
                    ;;
                harfbuzz*)
                    build_system="meson";
                    meson_opts="-Dglib=disabled -Dtests=disabled -Dintrospection=disabled -Ddocs=disabled";
                    ;;
                freetype-*)
                    extra_config_flags="--enable-static=no";
                    ;;
                libxml2-*)
                    extra_config_flags=--without-python;
                    ;;
                gettext*)
                    extra_config_flags="--enable-shared=yes";
                    # We only need gettext-runtime
                    pre_configure="sed -i -e /^SUBDIRS/s/libtextstyle.gettext-tools// $SANDBOX/Source/$pkg/Makefile.in";
                    ;;
                pango-*)
                    build_system="meson";
                    extra_cflags="-fstack-protector";
                    extra_ldflags="-fstack-protector";
                    ;;
                spread-sheet-widget-*)
                    ;;
                pspp-*)
                    extra_config_flags="--enable-relocatable";
                    extra_build="make -j $build_procs install-html install-pdf";
                    prefix=$SANDBOX/Bundle;
                    ;;
            esac
            case $build_system in
                meson)
                    PKG_CONFIG_LIBDIR="$SANDBOX/Install/lib/pkgconfig" \
                    CFLAGS="-I$SANDBOX/Install/include" \
                    CPPFLAGS="-I$SANDBOX/Install/include" \
                    LDFLAGS="-L$SANDBOX/Install/lib" \
                                     meson setup --prefix=$prefix \
                                     --libdir=lib \
                                     --cross-file=$SANDBOX/cross-file.txt \
                                     -Dc_link_args="-L$SANDBOX/Install/lib $extra_ldflags" \
                                     -Dc_args="-I$SANDBOX/Install/include $extra_cflags" \
                                     --wrap-mode=nodownload \
                                     $meson_opts \
                                     $SANDBOX/Source/$pkg $SANDBOX/Build/$pkg &&
                        ninja -j $build_procs -C $SANDBOX/Build/$pkg &&
                        meson install -C $SANDBOX/Build/$pkg
                    ;;
                autoconf)
                    $pre_configure && \
                        cd $SANDBOX/Build/$pkg && \
                        $SANDBOX/Source/$pkg/configure \
                            --host="$arch" \
                            --prefix="$prefix" \
                            "$extra_config_flags" \
                            CFLAGS="$extra_cflags" \
                            CPPFLAGS="-I$depdir/include $extra_cppflags" \
                            LDFLAGS="-L$depdir/lib $extra_ldflags" \
                            PKG_CONFIG_LIBDIR="$depdir/lib/pkgconfig" &&
                        make -j $build_procs && make install && $extra_build
                    ;;
                *)
                    echo I have no idea how to build $SANDBOX/Source/$pkg
                    false
            esac
            ;;
    esac || exit 1;
echo Done $pkg;
done


printf "You can now configure pspp with a command similar to:\n"
printf "configure --host=\"$arch\" CPPFLAGS=\"-I $SANDBOX/Install/include\" LDFLAGS=\"-L$SANDBOX/Install/lib\" PKG_CONFIG_LIBDIR=\"$SANDBOX/Install/lib/pkgconfig\"\n"
