#!/bin/bash # Build libflame as a WebAssembly static library using Emscripten. # # Usage: ./build-wasm.sh (single-threaded) # PTHREAD=1 ./build-wasm.sh (compile with -pthread so the library # can link into shared-memory/threaded wasm modules; installs as # libflame-mt.a alongside the single-threaded libflame.a) # Requires: emsdk (expected at ~/emsdk, or already on PATH) set -euo pipefail PTHREAD=${PTHREAD:-0} EXTRA_CFLAGS="" if [ "$PTHREAD" = "1" ]; then EXTRA_CFLAGS=" -pthread" fi cd "$(dirname "$0")" ROOT=$(pwd) PREFIX=$ROOT/install if ! command -v emcc >/dev/null 2>&1; then source ~/emsdk/emsdk_env.sh fi # 1. Clone if [ ! -d libflame ]; then git clone --depth 1 https://github.com/flame/libflame fi cd libflame # 2. Patch: libflame declares the Fortran-style BLAS as returning void, but the # f2c'd built-in BLAS defines those routines returning int. Harmless on # native targets, but a fatal signature mismatch under wasm-ld (calls # through mismatched signatures fail wasm validation). sed -i 's/^void F77_/int F77_/' src/base/flamec/blis/include/blis_prototypes_blas.h # 3. Configure. Notes: # - No --host triple: the bundled config.sub predates wasm; emcc via CC is enough. # - Fortran autodetection must be off (Emscripten has no Fortran compiler). # - builtin-blas uses the f2c C translations, so the library is self-contained. # - lapack2flame + legacy-lapack adds a full LAPACK API (f2c C sources, no Fortran). emconfigure ./configure \ --prefix="$PREFIX" \ --disable-autodetect-f77-ldflags \ --disable-autodetect-f77-name-mangling \ --enable-builtin-blas \ --enable-lapack2flame \ --enable-legacy-lapack \ --disable-dynamic-build \ --enable-static-build \ --enable-vector-intrinsics=none \ CC=emcc AR=emar RANLIB=emranlib # 4. configure doesn't know optimization flags for the "emcc" vendor; add -O2. sed -i "s/^COPTFLAGS := *\$/COPTFLAGS := -O2$EXTRA_CFLAGS/" config/*/config.mk # 5. Build. make -j"$(nproc)" # 6. Re-archive from the full object tree. The Makefile's incremental # archiving (ar_obj_list) only covers objects compiled in the current make # run, which can leave the archive stale or incomplete across rebuilds. LIBDIR=$(dirname "$(find lib -name libflame.a)") rm -f "$LIBDIR/libflame.a" find obj -name '*.o' | sort | xargs -n 500 emar crs "$LIBDIR/libflame.a" # 7. Install (single flattened FLAME.h + libflame.a). if [ "$PTHREAD" = "1" ]; then mkdir -p "$PREFIX/lib" cp "$LIBDIR/libflame.a" "$PREFIX/lib/libflame-mt.a" echo "Done. Library: $PREFIX/lib/libflame-mt.a" else make install echo "Done. Library: $PREFIX/lib/libflame.a Header: $PREFIX/include/FLAME.h" fi