ARG EMSDK_VERSION=3.1.50
ARG ZLIB_VERSION=1.3.1
ARG GLIB_SERIES=2.75
ARG GLIB_VERSION=2.75.0
ARG FFI_COMMIT=adbcf2b247696dde2667ab552cb93e0c79455c84

FROM emscripten/emsdk:${EMSDK_VERSION} AS base
ENV TARGET=/build/target
ENV CFLAGS="-O2 -matomics -mbulk-memory -DNDEBUG -sWASM_BIGINT -DWASM_BIGINT -pthread -sMALLOC=mimalloc -sASYNCIFY=1"
ENV CXXFLAGS="$CFLAGS"
ENV LDFLAGS="-L$TARGET/lib -O2"
ENV CPATH="$TARGET/include"
ENV PKG_CONFIG_PATH="$TARGET/lib/pkgconfig"
ENV EM_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
ENV CHOST=wasm32-unknown-linux
ENV MAKEFLAGS=-j2
RUN apt-get update && apt-get install -y \
    autoconf build-essential libglib2.0-dev libtool ninja-build pkgconf python3-pip
RUN pip3 install meson==1.5.0 tomli
WORKDIR /build
RUN mkdir -p "$TARGET"

FROM base AS zlib
ARG ZLIB_VERSION
RUN mkdir /zlib \
    && curl -Ls "https://zlib.net/fossils/zlib-${ZLIB_VERSION}.tar.gz" \
       | tar xzC /zlib --strip-components=1
WORKDIR /zlib
RUN emconfigure ./configure --prefix="$TARGET" --static && make install

FROM base AS libffi
ARG FFI_COMMIT
RUN git clone https://github.com/libffi/libffi /libffi \
    && git -C /libffi checkout "$FFI_COMMIT"
WORKDIR /libffi
RUN autoreconf -fiv \
    && emconfigure ./configure --host="$CHOST" --prefix="$TARGET" \
       --enable-static --disable-shared --disable-dependency-tracking \
       --disable-builddir --disable-multi-os-directory --disable-raw-api \
       --disable-structs --disable-docs \
    && emmake make install SUBDIRS=include

FROM base AS glib
ARG GLIB_SERIES
ARG GLIB_VERSION
COPY --from=zlib /build/ /build/
COPY --from=libffi /build/ /build/
RUN mkdir /stub \
    && printf '%s\n' '#include <netdb.h>' \
       'int res_query(const char *n, int c, int t, unsigned char *d, int l) { h_errno = HOST_NOT_FOUND; return -1; }' \
       >/stub/res_query.c \
    && emcc $CFLAGS -c /stub/res_query.c -fPIC -o /stub/libresolv.o \
    && ar rcs "$TARGET/lib/libresolv.a" /stub/libresolv.o
RUN mkdir /glib \
    && curl -Lks "https://download.gnome.org/sources/glib/${GLIB_SERIES}/glib-${GLIB_VERSION}.tar.xz" \
       | tar xJC /glib --strip-components=1
WORKDIR /glib
ENV CFLAGS="-Wno-error=incompatible-function-pointer-types -O2 -matomics -mbulk-memory -DNDEBUG -pthread -sWASM_BIGINT -sMALLOC=mimalloc -sASYNCIFY=1"
ENV CXXFLAGS="$CFLAGS"
RUN printf '%s\n' \
    '#!/bin/bash' \
    'set -euo pipefail' \
    'cmd="$1"; shift' \
    'args=()' \
    'for arg in "$@"; do args+=("${arg/-Werror=unused-command-line-argument/-Wno-error=unused-command-line-argument}"); done' \
    '"$cmd" "${args[@]}"' \
    >/emcc-meson-wrap.sh && chmod +x /emcc-meson-wrap.sh
RUN printf '%s\n' \
    '[host_machine]' \
    "system = 'emscripten'" \
    "cpu_family = 'wasm32'" \
    "cpu = 'wasm32'" \
    "endian = 'little'" \
    '' \
    '[binaries]' \
    "c = ['bash', '/emcc-meson-wrap.sh', 'emcc']" \
    "cpp = ['bash', '/emcc-meson-wrap.sh', 'em++']" \
    "ar = 'emar'" \
    "ranlib = 'emranlib'" \
    "pkgconfig = ['pkg-config', '--static']" \
    >/cross.meson
RUN meson setup _build --prefix="$TARGET" --cross-file=/cross.meson \
      --default-library=static --buildtype=release --force-fallback-for=pcre2,gvdb \
      -Dselinux=disabled -Dxattr=false -Dlibmount=disabled -Dnls=disabled \
      -Dtests=false -Dglib_assert=false -Dglib_checks=false \
    && sed -i -E '/#define HAVE_(CLOSE_RANGE|EPOLL_CREATE|KQUEUE|POSIX_SPAWN|FALLOCATE) 1/d' _build/config.h \
    && meson install -C _build

FROM base
COPY --from=glib /build/ /build/
WORKDIR /build
CMD ["sleep", "infinity"]
