penpot/render-wasm/_build_env
Andrey Antukh 46cf000635 🔥 Retire the legacy app.* tree from the exporter
Port the last live namespaces adapted to the new tree (config,
mime, object, resources, the wasm engines) with the temp ownership
folded into tmpdir, and delete src/app/ outright: 28 legacy files
gone, every behavior covered by the new suite.

The render env (uris, management key, tmpdir, image cache) now
travels in the lease message; the worker thread reads no config
and no globals. The generated shared.js moves next to the new
enums (build env, gitignore and docs follow it). Legacy tests fall
with a case-by-case parity check against the new suite.

Parity: api->consumer-api (7/7 same), worker->consumer+worker
slices, config/plan/jobs/shell/pool suites superseded, svg fills
moved to the new tree over the real module.

AI-assisted-by: muse-spark-1.3-contributor
2026-10-09 12:20:22 +00:00

163 lines
5.4 KiB
Bash

#!/usr/bin/env bash
export VERSION_TAG=${VERSION:-develop};
export RENDER_TARGET="${RENDER_TARGET:-${1:-frontend}}";
case "$RENDER_TARGET" in
frontend|export) ;;
*)
echo "ERROR: unknown render target '$RENDER_TARGET' (expected 'frontend' or 'export')" >&2;
exit 1;
;;
esac
if [ "$NODE_ENV" = "production" ]; then
export BUILD_MODE="release";
else
export BUILD_MODE=${BUILD_MODE:-debug};
fi
export BUILD_NAME="${BUILD_NAME:-render-wasm}"
export CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET:-"wasm32-unknown-emscripten"};
export CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-"target/$RENDER_TARGET"};
export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-binaries/releases/download/0.153.3/skia-binaries-b7f043e0b1e2a850e702-wasm32-unknown-emscripten-gl-svg-textlayout-binary-cache-webp-pdf-simd.tar.gz"}
# 256 MB of initial heap to perform less
# initial calls to memory grow.
export EM_INITIAL_HEAP=$((256 * 1024 * 1024))
# 1.0 doubles the heap on every growth.
export EM_MEMORY_GROWTH_GEOMETRIC_STEP="0.8"
# Malloc implementation to use.
# - dlmalloc: a powerful general-purpose malloc.
# - emmalloc: a simple and compact malloc designed for emscripten.
# - emmalloc-debug: use emmalloc and add extra assertion checks.
# - emmalloc-memvalidate: use emmalloc with assertions+heap consistency checking.
# - emmalloc-verbose: use emmalloc with assertions + verbose logging.
# - emmalloc-memvalidate-verbose: use emmalloc with assertions + heap consistency checking + verbose logging.
# Default: dlmalloc
export EM_MALLOC="dlmalloc"
# -msimd128: allow wasm SIMD in the linked module. Skia prebuilts must be
# built with the same flag (penpot/skia-binaries, WASM_SIMD=1) for Skia/skcms
# kernels to actually contain v128 ops; engines do not autovec scalar wasm.
export EMCC_CFLAGS="--no-entry \
--js-library src/js/wapi.js \
-msimd128 \
-sMALLOC=$EM_MALLOC \
-sINVOKE_RUN=0 \
-sALLOW_TABLE_GROWTH=0 \
-sALLOW_MEMORY_GROWTH=1 \
-sINITIAL_HEAP=$EM_INITIAL_HEAP \
-sMEMORY_GROWTH_GEOMETRIC_STEP=$EM_MEMORY_GROWTH_GEOMETRIC_STEP \
-sERROR_ON_UNDEFINED_SYMBOLS=0 \
-sMAX_WEBGL_VERSION=2 \
-sEXPORT_NAME=createRustSkiaModule \
-sEXPORTED_RUNTIME_METHODS=GL,UTF8ToString,stringToUTF8,HEAPU8,HEAP32,HEAPU32,HEAPF32 \
-sENVIRONMENT=web,worker,node \
-sMODULARIZE=1 \
-sDISABLE_EXCEPTION_CATCHING=1 \
-sFILESYSTEM=0 \
-sEXPORT_ES6=1";
export EM_CACHE="/tmp/emsdk_cache";
export CARGO_PARAMS="${@:2}";
export CARGO_PROFILE_DIR="debug";
if [ "$BUILD_MODE" = "profiling" ]; then
# Optimized like release, but keeps the wasm name section so the Firefox
# profiler can resolve Rust frames (release strips them). `--profiling-funcs`
# preserves function names through wasm-opt without pulling in DWARF.
export CARGO_PARAMS="--profile profiling $CARGO_PARAMS";
export CARGO_PROFILE_DIR="profiling";
export EMCC_CFLAGS="-O3 -sASSERTIONS=0 --profiling-funcs $EMCC_CFLAGS";
elif [ "$BUILD_MODE" = "release" ]; then
case "$RENDER_TARGET" in
frontend)
export CARGO_PARAMS="--release $CARGO_PARAMS";
export CARGO_PROFILE_DIR="release";
export EMCC_CFLAGS="-O3 -sASSERTIONS=0 $EMCC_CFLAGS";
;;
export)
export CARGO_PARAMS="--profile size $CARGO_PARAMS";
export CARGO_PROFILE_DIR="size";
export EMCC_CFLAGS="-Oz -sASSERTIONS=0 $EMCC_CFLAGS";
;;
esac
else
# TODO: Extra parameters that could be good to look into:
# -gseparate-dwarf
# -gsplit-dwarf
# -gsource-map
export EMCC_CFLAGS="-g -sASSERTIONS=1 -sVERBOSE=1 $EMCC_CFLAGS"
fi
export FRONTEND_DEST="../frontend/resources/public/js";
export EXPORT_DEST="../exporter/resources/wasm";
export FRONTEND_SHARED_DEST="../frontend/src/app/render_wasm/api/shared.js";
export EXPORT_SHARED_DEST="../exporter/src/exporter/wasm/shared.js";
function clean {
cargo clean;
}
function setup {
pnpm install;
}
function build {
cargo build $CARGO_PARAMS;
}
function copy_artifacts {
DEST=$1;
SRC="$CARGO_TARGET_DIR/$CARGO_BUILD_TARGET/$CARGO_PROFILE_DIR";
mkdir -p $DEST;
cp $SRC/render_wasm.js $DEST/$BUILD_NAME.js;
cp $SRC/render_wasm.wasm $DEST/$BUILD_NAME.wasm;
if [ -f $SRC/render_wasm.wasm.map ]; then
cp $SRC/render_wasm.wasm.map $DEST/$BUILD_NAME.wasm.map;
fi
sed -i "s/render_wasm.wasm/$BUILD_NAME.wasm?version=$VERSION_TAG/g" $DEST/$BUILD_NAME.js;
# The worker bundle is a browser concern; the exporter imports the ESM
# module directly under Node.
if [ "$RENDER_TARGET" = "frontend" ]; then
pnpm exec esbuild $SRC/render_wasm.js \
--log-level=error \
--outfile=$DEST/worker/render.js \
--platform=neutral \
--format=iife \
--global-name=WasmModule;
fi
}
function copy_shared_artifact {
DEST=$1;
SHARED_FILE=$(find $CARGO_TARGET_DIR/$CARGO_BUILD_TARGET -name render_wasm_shared.js | head -n 1);
cp $SHARED_FILE $DEST;
}
# Copies whatever the current RENDER_TARGET produced to where that target's
# consumer reads it.
function copy_target_artifacts {
case "$RENDER_TARGET" in
frontend)
copy_artifacts "$FRONTEND_DEST";
copy_shared_artifact "$FRONTEND_SHARED_DEST";
;;
export)
copy_artifacts "$EXPORT_DEST";
copy_shared_artifact "$EXPORT_SHARED_DEST";
;;
esac
}