#!/bin/sh
#
# Helper script that builds yad as a static binary.
#
# NOTE: This script is expected to be run under Alpine Linux.
#

set -e # Exit immediately if a command exits with a non-zero status.
set -u # Treat unset variables as an error.

# Define software versions.
YAD_VERSION=0.42.43

# Use the same versions has Alpine 3.20.
PANGO_VERSION=1.52.2
GTK_VERSION=2.24.33
ATK_VERSION=2.38.0
GDKPIXBUF_VERSION=2.42.11
CAIRON_VERSION=1.18.0
PIXMAN_VERSION=0.43.4
BROTLI_VERSION=1.1.0

# Define software download URLs.
YAD_URL=https://github.com/step-/yad/archive/refs/tags/${YAD_VERSION}.tar.gz
PANGO_URL=https://download.gnome.org/sources/pango/${PANGO_VERSION%.*}/pango-${PANGO_VERSION}.tar.xz
GTK_URL=https://download.gnome.org/sources/gtk+/${GTK_VERSION%.*}/gtk%2B-${GTK_VERSION}.tar.xz
ATK_URL=https://download.gnome.org/sources/atk/${ATK_VERSION%.*}/atk-${ATK_VERSION}.tar.xz
GDKPIXBUF_URL=https://download.gnome.org/sources/gdk-pixbuf/${GDKPIXBUF_VERSION%.*}/gdk-pixbuf-${GDKPIXBUF_VERSION}.tar.xz
CAIRO_URL=https://gitlab.freedesktop.org/cairo/cairo/-/archive/${CAIRON_VERSION}/cairo-${CAIRON_VERSION}.tar.bz2
PIXMAN_URL=https://www.x.org/releases/individual/lib/pixman-${PIXMAN_VERSION}.tar.xz
BROTLI_URL=https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz

# Set same default compilation flags as abuild.
export CFLAGS="-Os -fomit-frame-pointer -Wno-expansion-to-defined"
export CXXFLAGS="$CFLAGS"
export CPPFLAGS="$CFLAGS"
export LDFLAGS="-fuse-ld=lld -Wl,--as-needed,-O1,--sort-common"

export CC=xx-clang
export CXX=xx-clang++

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

function log {
    echo ">>> $*"
}

#
# Install required packages.
#
HOST_PKGS="\
    curl \
    build-base \
    abuild \
    clang \
    lld \
    cmake \
    meson \
    autoconf \
    automake \
    intltool \
    pkgconfig \
    glib-dev \
    gtk-update-icon-cache \
"

TARGET_PKGS="\
    g++ \
    glib-dev \
    glib-static \
    util-linux-dev \
    util-linux-static \
    gettext-static \
    pcre2-dev \
    expat-static \
    libffi-dev \
    zlib-static \
    bzip2-static \
    graphite2-static \
    libpng-static \
    libx11-static \
    libxcb-static \
    libxdmcp-dev \
    libxau-dev \
    libxrender-dev \
    fribidi-dev \
    fribidi-static \
    harfbuzz-dev \
    harfbuzz-static \
    freetype-static \
    libxext-static \
    libeconf-dev \
"

log "Installing required Alpine packages..."
apk --no-cache add $HOST_PKGS
xx-apk --no-cache --no-scripts add $TARGET_PKGS

echo "[binaries]
pkgconfig = '$(xx-info)-pkg-config'

[properties]
sys_root = '$(xx-info sysroot)'
pkg_config_libdir = '$(xx-info sysroot)/usr/lib/pkgconfig'

[host_machine]
system = 'linux'
cpu_family = '$(xx-info arch)'
cpu = '$(xx-info arch)'
endian = 'little'
" > /tmp/meson-cross.txt

#
# Build pango
# The static library is not provided by Alpine repository, so we need to build
# it ourself.
#
mkdir /tmp/pango
log "Downloading pango..."
curl -# -L -f ${PANGO_URL} | tar -xJ --strip 1 -C /tmp/pango
log "Configuring pango..."
(
    cd /tmp/pango && abuild-meson \
        -Ddefault_library=static \
        -Dintrospection=disabled \
        -Dgtk_doc=false \
        --cross-file /tmp/meson-cross.txt \
        build \
)
log "Compiling pango..."
meson compile -C /tmp/pango/build
log "Installing pango..."
DESTDIR=$(xx-info sysroot) meson install --no-rebuild -C /tmp/pango/build

#
# Build fontconfig.
#
# Fontconfig is already built by an earlier stage in Dockerfile.  The static
# library will be used by JWM.  We need to compile our own version to adjust
# different paths used by fontconfig.
# Note that the fontconfig cache generated by fc-cache is architecture
# dependent.  Thus, we won't generate one, but it's not a problem since
# we have very few fonts installed.
#

log "Installing fontconfig..."
cp -av /tmp/fontconfig-install/usr $(xx-info sysroot)

#
# Build atk.
# The static library is not provided by Alpine repository, so we need to build
# it ourself.
#
mkdir /tmp/atk
log "Downloading atk..."
curl -# -L -f ${ATK_URL} | tar -xJ --strip 1 -C /tmp/atk
log "Configuring atk..."
(
    cd /tmp/atk && abuild-meson \
        -Ddefault_library=static \
        -Dintrospection=false \
        -Ddocs=false \
        --cross-file /tmp/meson-cross.txt \
        build \
)
log "Compiling atk..."
meson compile -C /tmp/atk/build
log "Installing atk..."
DESTDIR=$(xx-info sysroot) meson install --no-rebuild -C /tmp/atk/build

#
# Build GdkPixbuf.
# The static library is not provided by Alpine repository, so we need to build
# it ourself.
#
mkdir /tmp/gdkpixbuf
log "Downloading GdkPixbuf..."
curl -# -L -f ${GDKPIXBUF_URL} | tar -xJ --strip 1 -C /tmp/gdkpixbuf
log "Configuring GdkPixbuf..."
(
    cd /tmp/gdkpixbuf && abuild-meson \
        -Ddefault_library=both \
        -Dpng=enabled \
        -Dtiff=disabled \
        -Djpeg=disabled \
        -Dgif=disabled \
        -Dbuiltin_loaders=png \
        -Dgtk_doc=false \
        -Ddocs=false \
        -Dtests=false \
        -Dintrospection=disabled \
        -Dman=false \
        -Drelocatable=false \
        -Dnative_windows_loaders=false \
        -Dinstalled_tests=false \
        -Dgio_sniffing=false \
        --cross-file /tmp/meson-cross.txt \
        build \
)
log "Compiling GdkPixbuf..."
meson compile -C /tmp/gdkpixbuf/build
log "Installing GdkPixbuf..."
DESTDIR=$(xx-info sysroot) meson install --no-rebuild -C /tmp/gdkpixbuf/build

#
# Build GTK.
# The static library is not provided by Alpine repository, so we need to build
# it ourself.
#
mkdir /tmp/gtk
log "Downloading GTK..."
curl -# -L -f ${GTK_URL} | tar -xJ --strip 1 -C /tmp/gtk
log "Patching GTK..."
patch -p1 -d /tmp/gtk < "$SCRIPT_DIR"/gtk+-2.24.33-Fix-casts.patch
log "Configuring GTK..."
(
    cd /tmp/gtk && ./configure \
        --build=$(TARGETPLATFORM= xx-clang --print-target-triple) \
        --host=$(xx-clang --print-target-triple) \
        --prefix=/usr \
        --enable-static \
        --disable-shared \
        --enable-debug=no \
        --disable-xinerama \
        --disable-glibtest \
        --disable-modules \
        --disable-cups \
        --disable-papi \
        --enable-introspection=no \
        --disable-gtk-doc \
        --disable-gtk-doc-html \
        --disable-gtk-doc-pdf \
        --disable-man \
        --with-gdktarget=x11 \
        --with-xinput=no \
)
log "Compiling GTK..."
sed 's/^SRC_SUBDIRS = gdk gtk modules demos tests perf/SRC_SUBDIRS = gdk gtk/' -i /tmp/gtk/Makefile
make -C /tmp/gtk -j$(nproc)
log "Installing GTK..."
make DESTDIR=$(xx-info sysroot) -C /tmp/gtk install

#
# Build cairo.
# The library in Alpine repository is built with LTO, which causes static
# linking issue, so we need to build it ourself.
#
mkdir /tmp/cairo
log "Downloading cairo..."
curl -# -L -f ${CAIRO_URL} | tar -xj --strip 1 -C /tmp/cairo
log "Patching cairo..."
patch -p1 -d /tmp/cairo < "$SCRIPT_DIR"/cairo-meson-fix.patch
log "Configuring cairo..."
(
    cd /tmp/cairo && abuild-meson \
        -Ddefault_library=both \
        -Dtests="disabled" \
        -Dgtk_doc=false \
        --cross-file /tmp/meson-cross.txt \
        build \
)
log "Compiling cairo..."
meson compile -C /tmp/cairo/build
log "Installing cairo..."
DESTDIR=$(xx-info sysroot) meson install --no-rebuild -C /tmp/cairo/build

#
# Build pixman.
# The library in Alpine repository is built with LTO, which causes static
# linking issue, so we need to build it ourself.
#
mkdir /tmp/pixman
log "Downloading pixman..."
curl -# -L -f ${PIXMAN_URL} | tar -xJ --strip 1 -C /tmp/pixman
log "Configuring pixman..."
(
    cd /tmp/pixman && \
    LDFLAGS="$LDFLAGS -Wl,-z,stack-size=2097152" \
    abuild-meson \
        -Db_lto=false \
        -Ddefault_library=static \
        -Dtests=disabled \
        -Ddemos=disabled \
        --cross-file /tmp/meson-cross.txt \
        . build
)
log "Compiling pixman..."
meson compile -C /tmp/pixman/build
log "Installing pixman..."
DESTDIR=$(xx-info sysroot) meson install --no-rebuild -C /tmp/pixman/build

#
# Build brotli.
# The library in Alpine repository is built with LTO, which causes static
# linking issue, so we need to build it ourself.
#
mkdir /tmp/brotli
log "Downloading brotli..."
curl -# -L -f ${BROTLI_URL} | tar -xz --strip 1 -C /tmp/brotli
log "Configuring brotli..."
(
    mkdir /tmp/brotli/build && \
    cd /tmp/brotli/build && cmake \
        $(xx-clang --print-cmake-defines) \
        -DCMAKE_FIND_ROOT_PATH=$(xx-info sysroot) \
        -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
        -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
        -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY \
        -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
        -DCMAKE_INSTALL_PREFIX=/usr \
        -DCMAKE_BUILD_TYPE=None \
	-DBUILD_SHARED_LIBS=OFF \
        ..
)
log "Compiling brotli..."
make -C /tmp/brotli/build -j$(nproc)
log "Installing brotli..."
make DESTDIR=$(xx-info sysroot) -C /tmp/brotli/build install

#
# Build YAD.
#
mkdir /tmp/yad
log "Downloading YAD..."
curl -# -L -f ${YAD_URL} | tar xz --strip 1 -C /tmp/yad
log "Configuring YAD..."
export LDFLAGS="$LDFLAGS --static -static -Wl,--strip-all" && \
(
    cd /tmp/yad && \
    autoreconf -ivf && \
    intltoolize && \
    LIBS="-lX11 -lxcb -lXdmcp -lXau -lpcre2-8 -lpixman-1 -lffi -lpng -lz -lbz2 -lgraphite2 -lexpat -lXrender -luuid -lbrotlidec -lbrotlicommon -lmount -lblkid -lfreetype -leconf -lgmodule-2.0" \
    ./configure \
        --build=$(TARGETPLATFORM= xx-clang --print-target-triple) \
        --host=$(xx-clang --print-target-triple) \
        --prefix=/usr \
        --with-gtk=gtk2 \
        --disable-spell \
        --disable-sourceview \
        --disable-gio \
        --disable-icon-browser \
        --disable-html \
        --disable-pfd \
)
log "Compiling YAD..."
make -C /tmp/yad -j$(nproc)
log "Installing YAD..."
make DESTDIR=/tmp/yad-install -C /tmp/yad install

#
# Cleanup.
#
log "Performing cleanup..."
apk --no-cache del $HOST_PKGS
xx-apk --no-cache --no-scripts del $TARGET_PKGS
apk --no-cache add util-linux # Linux tools still needed and they might be removed if pulled by dependencies.
rm -rf /tmp/yad
