#!/bin/sh
# Builds again the libraries of OpenSCAD's base image (openscad/wasm-base)
# that throw C++ exceptions or use setjmp (Boost, GMP's C++ part, lib3mf and
# FreeType), with the flags in $FLAGS, over the ones it holds: from the same
# releases and the same steps as the base image's recipe
# (openscad/openscad-wasm), checksums checked (ADR 63). With THREADS=1 they
# are built for threads, and oneTBB too, which Manifold's parallel
# algorithms use (ADR 64).
# Each step on its own line: set -e passes over a failure inside a && list.
set -eu
SYSROOT=/emsdk/upstream/emscripten/cache/sysroot
RECIPE_REF=501694addd7a7c9bd307b38d8591a4faad5381e8
export CFLAGS="$FLAGS -O3" CXXFLAGS="$FLAGS -O3" LDFLAGS="$FLAGS -O3"
mkdir -p /libs && cd /libs

curl -fsSLO https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-b2-nodocs.tar.xz
echo "3abd7a51118a5dd74673b25e0a3f0a4ab1752d8d618f4b8cea84a603aeecc680  boost-1.87.0-b2-nodocs.tar.xz" | sha256sum -c -
tar xf boost-1.87.0-b2-nodocs.tar.xz
(cd boost-1.87.0 && ./bootstrap.sh && ./b2 --disable-icu --prefix=$SYSROOT --with-filesystem --with-program_options --with-regex --with-system \
       address-model=32 cxxflags="-std=c++17 -stdlib=libc++ $FLAGS" install link=static \
       linkflags="-stdlib=libc++ $FLAGS" release runtime-link=static toolset=emscripten \
       $( [ "${THREADS:-0}" = 1 ] && echo threading=multi ))
rm -rf boost-1.87.0*

# From GNU's mirror, or gmplib.org, which refuses connections at times.
curl -fsSLO https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz || curl -fsSLO https://gmplib.org/download/gmp/gmp-6.3.0.tar.xz
echo "a3c2b80201b89e68616f4ad30bc66aee4927c3ce50e33929ca819d5c43538898  gmp-6.3.0.tar.xz" | sha256sum -c -
tar xf gmp-6.3.0.tar.xz
(set -e; cd gmp-6.3.0; emconfigure ./configure --disable-assembly --host none --enable-cxx --prefix=$SYSROOT HOST_CC=gcc
 make -j4; make install)
rm -rf gmp-6.3.0*

curl -fsSL -o recipe.tar.gz https://github.com/openscad/openscad-wasm/archive/$RECIPE_REF.tar.gz
echo "de15ea60d9caa05c76be3d5e8557ce823b75fcc905e06006811c0483526da088  recipe.tar.gz" | sha256sum -c -
tar xzf recipe.tar.gz
git clone -q --recurse --depth 1 --branch v2.3.2 https://github.com/3MFConsortium/lib3mf.git
git -C lib3mf apply ../openscad-wasm-$RECIPE_REF/patches/lib3mf.patch
emcmake cmake -S lib3mf -B lib3mf-build -DLIB3MF_TESTS=OFF -DUSE_INCLUDED_ZLIB=OFF -DUSE_INCLUDED_LIBZIP=OFF -G Ninja
cmake --build lib3mf-build --parallel 4
cmake --install lib3mf-build
rm -rf lib3mf lib3mf-build

git clone -q --depth 1 --branch VER-2-13-3 https://github.com/freetype/freetype.git
emcmake cmake -S freetype -B freetype-build -DFT_REQUIRE_ZLIB=TRUE
cmake --build freetype-build
cmake --install freetype-build
rm -rf freetype freetype-build

if [ "${THREADS:-0}" = 1 ]; then
  git clone -q --depth 1 --branch v2022.3.0 https://github.com/uxlfoundation/oneTBB.git
  # Without its allocator, which Manifold does not use and which asks for
  # emulated exceptions.
  emcmake cmake -S oneTBB -B tbb-build -G Ninja -DCMAKE_BUILD_TYPE=Release -DTBB_TEST=OFF -DTBB_EXAMPLES=OFF \
    -DTBB_STRICT=OFF -DBUILD_SHARED_LIBS=OFF -DTBB_DISABLE_HWLOC_AUTOMATIC_SEARCH=ON -DTBBMALLOC_BUILD=OFF \
    -DTBBMALLOC_PROXY_BUILD=OFF -DCMAKE_INSTALL_PREFIX=$SYSROOT
  cmake --build tbb-build --parallel 4
  cmake --install tbb-build
  test -f $SYSROOT/lib/libtbb.a
  rm -rf oneTBB tbb-build

  # And the libraries whose objects forbid shared memory without threads
  # (MPFR's thread-local data, HarfBuzz's and Fontconfig's atomics), at the
  # versions the base image holds.
  curl -fsSLO https://www.mpfr.org/mpfr-4.2.1/mpfr-4.2.1.tar.xz
  echo "277807353a6726978996945af13e52829e3abd7a9a5b7fb2793894e18f1fcbb2  mpfr-4.2.1.tar.xz" | sha256sum -c -
  tar xf mpfr-4.2.1.tar.xz
  (set -e; cd mpfr-4.2.1; emconfigure ./configure --host none --with-gmp=$SYSROOT --prefix=$SYSROOT
   make -j4; make install)
  rm -rf mpfr-4.2.1*

  git clone -q --depth 1 --branch 11.2.1 https://github.com/harfbuzz/harfbuzz.git
  # HarfBuzz builds without exceptions, for which Emscripten would pick its
  # JavaScript setjmp, which clashes with them: WebAssembly's own instead.
  CXXFLAGS="$CXXFLAGS -sSUPPORT_LONGJMP=wasm" CFLAGS="$CFLAGS -sSUPPORT_LONGJMP=wasm" \
    emcmake cmake -S harfbuzz -B harfbuzz-build -G Ninja -DHB_HAVE_FREETYPE=ON
  cmake --build harfbuzz-build --parallel 4
  cmake --install harfbuzz-build
  rm -rf harfbuzz harfbuzz-build

  git clone -q --depth 1 --branch 2.16.2 https://gitlab.freedesktop.org/fontconfig/fontconfig.git
  git -C fontconfig apply ../openscad-wasm-$RECIPE_REF/patches/fontconfig.patch
  (set -e; cd fontconfig
   export FREETYPE_CFLAGS="-I$SYSROOT/include/freetype2" FREETYPE_LIBS="-lfreetype -lz"
   emconfigure ./autogen.sh --host none --disable-docs --disable-shared --enable-static --sysconfdir=/ \
     --localstatedir=/ --with-default-fonts=/fonts --enable-libxml2 --prefix=$SYSROOT
   emmake make; emmake make install)
  rm -rf fontconfig
fi
rm -rf /libs

# Nothing left that emulates them: the libraries OpenSCAD links have no
# calls into JavaScript's exception or setjmp handling.
cd $SYSROOT/lib
for lib in libboost_regex.a libboost_program_options.a libgmpxx.a lib3mf.a libfreetype.a; do
  if /emsdk/upstream/bin/llvm-nm -u $lib 2>/dev/null | grep -q "__resumeException\|__cxa_find_matching_catch\|invoke_\|emscripten_longjmp"; then
    echo "$lib still emulates exceptions"; exit 1
  fi
done
