#!/usr/bin/env bash # Use this to build -fPIC C or C++ code using zig. I like doing this, since zig is a very # compact and efficient way to CLANG/LLVM. Unfortunately (in mid 2022), zig doesn't directly # support building -fPIC code (the flag does nothing), which is of course absolutely required # to create and use a dynamic library with WebAssembly. Fortunately, zig includes wasm-ld # and clang, so we can work around this shortcoming. This script does so, basically by # add a bunch of obscure options to the command line. # # TODO: upstream this by improving the way zig handles -target=wasm32-emscripten, or # some other approach. # # Needed on macOS realpath() { OURPWD=$PWD cd "$(dirname "$1")" LINK=$(readlink "$(basename "$1")") while [ "$LINK" ]; do cd "$(dirname "$LINK")" LINK=$(readlink "$(basename "$1")") done REALPATH="$PWD/$(basename "$1")" cd "$OURPWD" echo "$REALPATH" } ZIG_EXE=`which zig` ZIG_EXE=`realpath $ZIG_EXE` ZIG_HOME=`dirname $ZIG_EXE` #echo "ZIG_EXE=$ZIG_EXE" INCLUDE="$ZIG_HOME/lib/zig/libc/include" # On MacOS the includes are in $ZIG_HOME/lib/zig/libc (etc), for some reason # on Linux it is just $ZIG_HOME/lib/libc, i.e., sometimes there's an extra zig in the path. if [ ! -d "$INCLUDE" ] then INCLUDE="$ZIG_HOME/lib/libc/include" fi #echo "INCLUDE=$INCLUDE" # These are the flags we need to make the -target=wasm32-emscripten actually work # with what's provided in the zig distribution. Note that we always set -shared, # the target wasm32-emscripten and -fPIC, since I can't think # of any reason to be using this script when you wouldn't have those set. FLAGS="\ -target wasm32-emscripten \ -fPIC \ -isystem $INCLUDE/wasm-wasi-musl \ -isystem $INCLUDE/generic-musl \ -D__wasi__ -D__EMSCRIPTEN_major__=3 -D__EMSCRIPTEN_minor__=1 -D__EMSCRIPTEN_tiny__=16 \ -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_PROCESS_CLOCKS -D_WASI_EMULATED_GETPID" echo "zig $@ $FLAGS" zig "$@" $FLAGS