mirror of
https://github.com/HeyPuter/blender-wasm.git
synced 2026-11-13 18:33:51 -10:00
GL backend (build-blender-gl, BLENDER_GPU=gl): wink/epoxy build scripts, cmake cache, Blender/Mesa patches, WGSL seed cache, demo wiring, and the compat/latency/GPU bench + profiling harnesses. numpy: scripts/build_numpy.sh cross-compiles numpy 2.3.4 and links its extension modules into blender.wasm as builtins (fixes glTF/FBX import, 'No module named numpy'). CPython: undo mimalloc's __wasi__ leak in timemodule.c so time.process_time() works (FBX export). Bump BLENDER_REF for the glTF/FBX add-on fixes. scripts/numpy_io_test.mjs covers numpy and glTF/FBX/OBJ/PLY/STL import/export in the browser. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_25da9696629446c4ae08c8603ff6ea2f
93 lines
4.3 KiB
Bash
93 lines
4.3 KiB
Bash
#!/usr/bin/env bash
|
|
# CPython 3.13.13 → wasm-sysroot (static libpython, embedded into Blender).
|
|
# Two-step emscripten cross-build per CPython's Tools/wasm/README.md:
|
|
# 1) a native build-python of the SAME version (freezes stdlib during cross-build)
|
|
# 2) the wasm cross-build with --enable-wasm-pthreads (matches our -pthread ABI)
|
|
set -euo pipefail
|
|
source "$(dirname "$0")/dep_common.sh"
|
|
PYSRC=$(fetch_extract \
|
|
"https://www.python.org/ftp/python/3.13.13/Python-3.13.13.tar.xz" \
|
|
"Python-3.13.13.tar.xz" "Python-3.13.13")
|
|
|
|
# The bundled mimalloc's internal.h does `#define __wasi__` on Emscripten, and it
|
|
# leaks into every core module through pycore_*.h. timemodule.c then takes its
|
|
# WASI-only (gh-115714) fallbacks, leaving time.process_time()/times() on clock(),
|
|
# which Emscripten doesn't implement -> RuntimeError (breaks e.g. the FBX
|
|
# exporter). Emscripten's CPU-time clocks work, so undo the leak in that file.
|
|
if ! grep -q "blender-wasm: mimalloc __wasi__ leak" "$PYSRC/Modules/timemodule.c"; then
|
|
python3 - "$PYSRC/Modules/timemodule.c" <<'PYEOF'
|
|
import sys
|
|
p = sys.argv[1]; s = open(p).read()
|
|
anchor = '#include <time.h> // clock()\n'
|
|
assert anchor in s
|
|
s = s.replace(anchor, anchor + (
|
|
'/* blender-wasm: mimalloc __wasi__ leak (see scripts/build_python.sh). */\n'
|
|
'#if defined(__EMSCRIPTEN__) && defined(__wasi__)\n'
|
|
'# undef __wasi__\n'
|
|
'#endif\n'), 1)
|
|
open(p, 'w').write(s)
|
|
PYEOF
|
|
log "patched timemodule.c (emscripten CPU-time clocks)"
|
|
fi
|
|
|
|
# 1) Native build-python (host interpreter used by the cross-build).
|
|
NATIVE="$BLD/python-native"
|
|
# Must be a COMPLETE build (incl. extension modules like binascii) — the wasm
|
|
# cross-build runs this interpreter for its freeze/codegen steps.
|
|
if [ ! -x "$NATIVE/python" ] || ! "$NATIVE/python" -c "import binascii, zlib" 2>/dev/null; then
|
|
log "building native build-python 3.13.13 (full)"
|
|
rm -rf "$NATIVE"; mkdir -p "$NATIVE"; ( cd "$NATIVE"
|
|
"$PYSRC/configure" -C >/dev/null
|
|
make -j"$NPROC" >/dev/null 2>&1 )
|
|
fi
|
|
BUILD_PY="$NATIVE/python"
|
|
"$BUILD_PY" --version
|
|
|
|
# 2) WASM cross-build → $SYSROOT.
|
|
WB="$BLD/python-wasm"; rm -rf "$WB"; mkdir -p "$WB"
|
|
( cd "$WB"
|
|
# -DPY_CALL_TRAMPOLINE: enable CPython's Emscripten C-function call trampoline.
|
|
# WASM call_indirect enforces exact signature match; CPython calls METH_NOARGS/
|
|
# METH_O C functions through a generic PyCFunctionWithKeywords pointer, which is
|
|
# a bad fpcast that traps ("null function or function signature mismatch") on
|
|
# wasm. The trampoline routes those calls through JS (wasmTable.get + arity
|
|
# reflection) so the real arity is honored. Not auto-defined by 3.13 configure.
|
|
CONFIG_SITE="$PYSRC/Tools/wasm/config.site-wasm32-emscripten" \
|
|
CFLAGS="-fexceptions -DPY_CALL_TRAMPOLINE" \
|
|
emconfigure "$PYSRC/configure" -C \
|
|
--host=wasm32-unknown-emscripten \
|
|
--build=x86_64-pc-linux-gnu \
|
|
--enable-wasm-pthreads \
|
|
--with-build-python="$BUILD_PY" \
|
|
--prefix="$SYSROOT" \
|
|
--disable-shared \
|
|
--disable-test-modules \
|
|
--with-ensurepip=no
|
|
emmake make -j"$NPROC"
|
|
emmake make install )
|
|
|
|
# The _decimal module's bundled libmpdec objects compile but are NOT archived
|
|
# into libpython3.13.a by CPython's static-wasm build, so _decimal.o is left with
|
|
# undefined mpd_* symbols at the final Blender link. Fold them into the archive.
|
|
# Several bundled modules compile their support sources but CPython's static-wasm
|
|
# build does NOT archive them into libpython3.13.a, leaving undefined symbols at
|
|
# the final Blender link: _decimal's libmpdec (mpd_*), pyexpat/_elementtree's
|
|
# vendored expat (PyExpat_XML_*), and hashlib's HACL SHA2 (python_hashlib_*).
|
|
# Fold them in. Prefix member names: libmpdec has context.o/io.o whose BASENAMES
|
|
# collide with core CPython objects in the flat-namespaced archive (`ar r` keys
|
|
# by basename and would silently overwrite Python's own context.o).
|
|
_mz=$(mktemp -d)
|
|
for _o in "$WB"/Modules/_decimal/libmpdec/*.o \
|
|
"$WB"/Modules/expat/xmlparse.o "$WB"/Modules/expat/xmltok.o "$WB"/Modules/expat/xmlrole.o \
|
|
"$WB"/Modules/_hacl/Hacl_Hash_SHA2.o; do
|
|
[ -f "$_o" ] && cp "$_o" "$_mz/pymod_$(basename "$_o")"
|
|
done
|
|
if ls "$_mz"/*.o >/dev/null 2>&1; then
|
|
emar r "$SYSROOT/lib/libpython3.13.a" "$_mz"/*.o
|
|
log "archived bundled libmpdec/expat/hacl objects into libpython3.13.a"
|
|
fi
|
|
rm -rf "$_mz"
|
|
|
|
log "installed python into $SYSROOT"
|
|
ls -la "$SYSROOT"/lib/libpython3.13*.a 2>&1
|