#!/bin/sh
# Builds SuperTuxKart 1.5 (https://github.com/supertuxkart/stk-code, GPL-3.0-or-later
# code, data CC-BY-SA, CC-BY, CC0, GPL and public domain) for the site, from
# upstream source, with the changes in stk.diff beside this script. It starts
# from ading2210's web port (github.com/ading2210/stk-code, branch wasm) and
# differs from it in these ways:
# - no threads, so the page needs no cross-origin isolation (that would break
#   the ads): sounds play on the main loop, textures load on the main loop,
#   add-ons and online play are off, and CPU texture compression is off;
# - WebGL 2 with the full shader renderer, not the legacy one;
# - before each race the game asks the page whether the track's files are in
#   (Module.wgTrackReady), and if not goes back to the menus with a short
#   message (Cancel stops waiting) and starts the race once they are;
# - wg_save() writes best times, progress and settings when the page asks,
#   since a page never quits (the desktop game writes some only as it quits),
#   and Esc on the main menu doesn't offer to quit;
# - the window size and full screen belong to the page: wg_resize() sets the
#   size, and the resolution and full screen options are hidden;
# - main() is run by the play page (INVOKE_RUN=0) and the data is read from
#   /data, written there by the play page from the zips below.
# The data is the 1.5 release's, shrunk with upstream's own Android script
# (android/generate_assets.sh: textures at most 512 px, mono music), then split
# by pack.py beside this script (see there) into zips for R2.
#
# Needs git, cmake, make, autotools, python3, curl, imagemagick, vorbis-tools,
# pngquant, optipng, advancecomp, libjpeg-turbo-progs, hexdump and emsdk 4.0.7
# (source emsdk_env.sh first).
# Usage: sh build.sh [work dir]
# Writes supertuxkart.js, supertuxkart.wasm and packs.json next to this script,
# and the zips for R2 to <work dir>/r2/supertuxkart/ (upload them to
# wasmgame-files under the same keys). For a newer SuperTuxKart, copy this
# folder to supertuxkart-<new rev>-p1 and change the version below; a change to
# the build here takes the next -p number.
set -eu

STK_TAG=1.5
STK_REV=1fb491f507216c5d181ccd85f29ff08eca003827
EMSDK_VERSION=4.0.7

here=$(cd "$(dirname "$0")" && pwd)
work=${1:-${TMPDIR:-/tmp}/supertuxkart-build}
mkdir -p "$work"

case "$(emcc --version | head -1)" in
  *" $EMSDK_VERSION "*) ;;
  *) echo "warning: built and tested with emsdk $EMSDK_VERSION" >&2 ;;
esac

# Emscripten fetches SDL as a GitHub archive; clone it instead.
. "$here/ports.sh"
port sdl2 libsdl-org/SDL release-2.32.0 SDL-release-2.32.0 https://github.com/libsdl-org/SDL/archive/release-2.32.0.zip

# Libraries, built with the same exception and setjmp settings as the game.
prefix=$work/deps
src=$work/libs
mkdir -p "$prefix" "$src"
export PKG_CONFIG_PATH="$prefix/lib/pkgconfig"
export CFLAGS="-O2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm"
export CXXFLAGS="$CFLAGS"
export LDFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm"
jobs=${JOBS:-$(nproc)}
clone() { [ -d "$src/$1" ] || git -c advice.detachedHead=false clone -q --depth 1 -b "$3" "https://github.com/$2.git" "$src/$1"; }
if [ ! -f "$prefix/lib/libogg.a" ]; then
  clone ogg xiph/ogg v1.3.5 && cd "$src/ogg" && ./autogen.sh &&
    emconfigure ./configure --host=none-linux --prefix="$prefix" --disable-shared && emmake make -j"$jobs" && make install
fi
if [ ! -f "$prefix/lib/libvorbis.a" ]; then
  clone vorbis xiph/vorbis v1.3.7 && cd "$src/vorbis" && ./autogen.sh &&
    emconfigure ./configure --host=none-linux --prefix="$prefix" --with-ogg="$prefix" --disable-shared --disable-examples --disable-oggtest &&
    emmake make -j"$jobs" && make install
fi
if [ ! -f "$prefix/lib/libcrypto.a" ]; then
  clone openssl openssl/openssl openssl-3.3.0 && cd "$src/openssl" &&
    emconfigure ./Configure linux-x32 -no-asm -static -no-afalgeng -no-dso -no-threads -DOPENSSL_SYS_NETWARE -DSIG_DFL=0 -DSIG_IGN=0 -DHAVE_FORK=0 -DOPENSSL_NO_AFALGENG=1 -DOPENSSL_NO_SPEED=1 -DOPENSSL_NO_DYNAMIC_ENGINE -DDLOPEN_FLAG=0 &&
    sed -i 's|^CROSS_COMPILE.*$|CROSS_COMPILE=|g' Makefile && emmake make -j"$jobs" build_generated libssl.a libcrypto.a &&
    cp -r include/openssl "$prefix/include" && cp libcrypto.a libssl.a "$prefix/lib"
fi
if [ ! -f "$prefix/lib/libz.a" ]; then
  # zlib's build races on libz.a with more than one job.
  clone zlib madler/zlib v1.3.1 && cd "$src/zlib" && emconfigure ./configure --prefix="$prefix" --static && emmake make -j1 && make install
fi
if [ ! -f "$prefix/lib/libcurl.a" ]; then
  # Linked but never used: the web build stays offline.
  clone curl curl/curl curl-8_8_0 && cd "$src/curl" && autoreconf -fi &&
    emconfigure ./configure --host none-linux --prefix="$prefix" --without-ssl --with-zlib="$prefix" --disable-shared --disable-threaded-resolver --without-libpsl --disable-netrc --disable-ipv6 --disable-tftp --disable-ntlm-wb --disable-docs --disable-manual &&
    emmake make -j"$jobs" -C lib && make -C lib install && make -C include install
fi
if [ ! -f "$prefix/lib/libjpeg.a" ]; then
  clone jpeg libjpeg-turbo/libjpeg-turbo 3.0.3 && mkdir -p "$src/jpeg/build" && cd "$src/jpeg/build" &&
    emcmake cmake .. -DCMAKE_INSTALL_PREFIX="$prefix" -DCMAKE_INSTALL_LIBDIR=lib -DWITH_SIMD=0 -DENABLE_SHARED=0 && emmake make -j"$jobs" && make install
fi
if [ ! -f "$prefix/lib/libpng16.a" ]; then
  clone png pnggroup/libpng v1.6.43 && cd "$src/png" &&
    emconfigure ./configure --host none-linux --prefix="$prefix" --disable-shared CPPFLAGS="-I$prefix/include" LDFLAGS="$LDFLAGS -L$prefix/lib" &&
    emmake make -j"$jobs" && make install
fi
freetype() {
  clone freetype freetype/freetype VER-2-13-2 && rm -rf "$src/freetype/build" && mkdir -p "$src/freetype/build" && cd "$src/freetype/build" &&
    emcmake cmake .. -DCMAKE_INSTALL_PREFIX="$prefix" -DZLIB_LIBRARY="$prefix/lib/libz.a" -DZLIB_INCLUDE_DIR="$prefix/include" \
      -DPNG_LIBRARY="$prefix/lib/libpng.a" -DPNG_PNG_INCLUDE_DIR="$prefix/include" -DFT_DISABLE_BZIP2=ON -DFT_DISABLE_BROTLI=ON "$@" &&
    emmake make -j"$jobs" && make install
}
if [ ! -f "$prefix/lib/libharfbuzz.a" ]; then
  # Harfbuzz needs freetype, and freetype is then built again with it.
  freetype
  clone harfbuzz harfbuzz/harfbuzz 8.5.0 && cd "$src/harfbuzz" && NOCONFIGURE=1 ./autogen.sh &&
    emconfigure ./configure --host=none-linux --prefix="$prefix" --disable-shared --with-glib=no --with-cairo=no --with-icu=no --with-gobject=no &&
    emmake make -j"$jobs" -C src libharfbuzz.la && make -C src install
  rm -rf "$prefix/include/freetype2"
  freetype -DHarfBuzz_LIBRARY="$prefix/lib/libharfbuzz.a" -DHarfBuzz_INCLUDE_DIR="$prefix/include/harfbuzz/" -DFT_REQUIRE_HARFBUZZ=TRUE
fi

# The game.
if [ ! -d "$work/stk-code" ]; then
  git clone -q --filter=blob:none https://github.com/supertuxkart/stk-code.git "$work/stk-code"
fi
cd "$work/stk-code"
git checkout -q -f $STK_REV
git apply "$here/stk.diff"
emcmake cmake -S . -B "$work/build" -DCMAKE_BUILD_TYPE=Release -DSTK_WASM_PREFIX="$prefix" -DNO_SHADERC=on -DCHECK_ASSETS=off
make -j"$jobs" -C "$work/build" supertuxkart
cp "$work/build/bin/supertuxkart.js" "$work/build/bin/supertuxkart.wasm" "$here/"

# The data: the release's assets, shrunk by upstream's Android script (run
# from this checkout, whose data/ holds the code's own files).
if [ ! -d "$work/SuperTuxKart-$STK_TAG-src" ]; then
  curl -sSL -o "$work/src.tar.gz" "https://github.com/supertuxkart/stk-code/releases/download/$STK_TAG/SuperTuxKart-$STK_TAG-src.tar.gz"
  tar xzf "$work/src.tar.gz" -C "$work"
fi
if [ ! -f "$work/assets/data/stk_config.xml" ]; then
  (cd android && ASSETS_PATHS="$work/SuperTuxKart-$STK_TAG-src/data" OUTPUT_PATH="$work/assets" TEXTURE_SIZE=512 ./generate_assets.sh)
fi
rm -rf "$work/packs" "$work/r2" && mkdir -p "$work/r2/supertuxkart"
python3 "$here/pack.py" "$work/assets/data" "$work/packs"
cp "$work/packs/packs.json" "$here/"
for z in "$work"/packs/*.zip; do
  n=$(basename "$z" .zip)
  cp "$z" "$work/r2/supertuxkart/$n-$(sha256sum "$z" | cut -c1-12).zip"
done
ls -l "$work/r2/supertuxkart"
