penpot/render-wasm/_build_env
Elena Torró a44c8aba88
🔧 Remove wasm warnings (#12291)
* 🔧 Drop emscripten verbose linker output from debug builds

* 🔧 Fix render-wasm warnings from Rust 1.99
2026-10-13 16:33:51 +02:00

237 lines
7.9 KiB
Bash

#!/usr/bin/env bash
export RUST_VERSION=1.99.0
export VERSION_TAG="${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="${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}";
# Skia prebuild with wasm SIMD and Wasm EH/SjLj (-ljmp-wasm). Must match
# EMCC_CFLAGS below. Override with SKIA_BINARIES_URL when needed.
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-ljmp-wasm.tar.gz"}
# Emscripten only: rustc wasm SIMD (native `./test` unchanged). Wasm
# setjmp/longjmp comes from EMCC_CFLAGS (-sSUPPORT_LONGJMP=wasm), which emcc
# appends on compile and link.
if [ "$CARGO_BUILD_TARGET" = "wasm32-unknown-emscripten" ]; then
export RUSTFLAGS="${RUSTFLAGS:-} -C target-feature=+simd128"
fi
# 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: wasm SIMD in the linked module (Skia -simd prebuild must match).
# -fwasm-exceptions / SUPPORT_LONGJMP=wasm: native Wasm EH and setjmp/longjmp
# (Skia -ljmp-wasm prebuild must match).
export EMCC_CFLAGS="--no-entry \
--js-library src/js/wapi.js \
-msimd128 \
-fwasm-exceptions \
-sSUPPORT_LONGJMP=wasm \
-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 \
-sFILESYSTEM=0 \
-sEXPORT_ES6=1";
export EM_CACHE="/tmp/emsdk_cache";
CARGO_ARGS=("${@:2}");
_CARGO_PROFILE_SET=0;
export CARGO_PROFILE_DIR="debug";
for (( _cargo_index=0; _cargo_index < ${#CARGO_ARGS[@]}; _cargo_index++ )); do
case "${CARGO_ARGS[_cargo_index]}" in
--release|-r)
_CARGO_PROFILE_SET=1;
export CARGO_PROFILE_DIR="release";
;;
--profile)
_CARGO_PROFILE_SET=1;
export CARGO_PROFILE_DIR="${CARGO_ARGS[_cargo_index + 1]}";
;;
--profile=*)
_CARGO_PROFILE_SET=1;
export CARGO_PROFILE_DIR="${CARGO_ARGS[_cargo_index]#--profile=}";
;;
--target-dir)
export CARGO_TARGET_DIR="${CARGO_ARGS[_cargo_index + 1]:-$CARGO_TARGET_DIR}";
;;
--target-dir=*)
export CARGO_TARGET_DIR="${CARGO_ARGS[_cargo_index]#--target-dir=}";
;;
esac
done
if [ "$_CARGO_PROFILE_SET" = "0" ]; then
if [ "$BUILD_MODE" = "profiling" ]; then
CARGO_ARGS=(--profile profiling "${CARGO_ARGS[@]}");
export CARGO_PROFILE_DIR="profiling";
elif [ "$BUILD_MODE" = "release" ]; then
case "$RENDER_TARGET" in
frontend)
CARGO_ARGS=(--release "${CARGO_ARGS[@]}");
export CARGO_PROFILE_DIR="release";
;;
export)
CARGO_ARGS=(--profile size "${CARGO_ARGS[@]}");
export CARGO_PROFILE_DIR="size";
;;
esac
fi
fi
case "$CARGO_PROFILE_DIR" in
profiling)
# Keep the wasm name section so profilers can resolve Rust frames.
export EMCC_CFLAGS="-O3 -sASSERTIONS=0 --profiling-funcs $EMCC_CFLAGS";
;;
release)
export EMCC_CFLAGS="-O3 -sASSERTIONS=0 $EMCC_CFLAGS";
;;
size)
export EMCC_CFLAGS="-Oz -sASSERTIONS=0 $EMCC_CFLAGS";
;;
*)
# TODO: Extra parameters that could be good to look into:
# -gseparate-dwarf
# -gsplit-dwarf
# -gsource-map
export EMCC_CFLAGS="-g -sASSERTIONS=1 $EMCC_CFLAGS";
;;
esac
if [ "$CARGO_PROFILE_DIR" = "dev" ]; then
export CARGO_PROFILE_DIR="debug";
fi
export RENDER_WASM_BUILD_INFO="${RENDER_WASM_BUILD_INFO:-$CARGO_TARGET_DIR/build-info.json}";
export FRONTEND_DEST="${FRONTEND_DEST:-../frontend/resources/public/js}";
export EXPORT_DEST="${EXPORT_DEST:-../exporter/resources/wasm}";
export FRONTEND_SHARED_DEST="${FRONTEND_SHARED_DEST:-../frontend/src/app/render_wasm/api/shared.js}";
export EXPORT_SHARED_DEST="${EXPORT_SHARED_DEST:-../exporter/src/app/wasm/shared.js}";
function clean {
cargo clean;
}
function setup_rust {
# Setup default rust version
rustup default $RUST_VERSION
rustup target add wasm32-unknown-emscripten
rustup component add clippy rustfmt --toolchain $RUST_VERSION
}
function setup {
setup_rust
pnpm install;
}
function build {
(
set -o pipefail;
cargo build --message-format=json-render-diagnostics "${CARGO_ARGS[@]}" \
| node ./scripts/cargo-build.cjs "$RENDER_WASM_BUILD_INFO" "$PWD/Cargo.toml";
)
}
function copy_artifacts {
local DEST="$1";
local SRC;
SRC=$(jq -r '.artifact_dir' -- "$RENDER_WASM_BUILD_INFO")
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
# Rewrite the generated JavaScript so it loads the renamed Wasm file with
# a version query, such as render-wasm.wasm?version=develop.
local WASM_URL="$BUILD_NAME.wasm?version=$VERSION_TAG";
WASM_URL=${WASM_URL//\\/\\\\};
WASM_URL=${WASM_URL//&/\\&};
WASM_URL=${WASM_URL//|/\\|};
sed -i "s|render_wasm\\.wasm|$WASM_URL|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 {
local DEST="$1";
local SHARED_FILE;
SHARED_FILE=$(jq -r '.shared_file' -- "$RENDER_WASM_BUILD_INFO")
mkdir -p -- "$(dirname -- "$DEST")";
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
if [ -n "${RENDER_WASM_SHARED_ARTIFACT:-}" ]; then
copy_shared_artifact "$RENDER_WASM_SHARED_ARTIFACT";
fi
}