fix(wasm): Fix asyncify rewind with asyncify-aware dynCall shims
Emscripten 4.x removed dynCall_* WASM exports, breaking asyncify
rewind through indirect calls (modal dialogs, event handlers).
Generate JS shims that track Asyncify.exportCallStack and register
in wasmExports so doRewind can find them.
Also fixes empty callback functions ((() => {})) generated by
Emscripten 4.x + pthreads for HTML5 events, pthread entry,
sighandler, async timer, and main loop callbacks.
Build pipeline improvements:
- Stub wasm-opt/finalize in Docker (RAM limits), run on host
- Add setup-emsdk.sh for reproducible Emscripten setup
- Simplify env.sh and version management
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
51b158f6b1
commit
b46b4b69f1
13 changed files with 150 additions and 65 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -30,6 +30,9 @@ cmake-build-*/
|
||||||
# Emscripten cache
|
# Emscripten cache
|
||||||
.emscripten_cache/
|
.emscripten_cache/
|
||||||
|
|
||||||
|
# Local emsdk installation (managed by scripts/setup-emsdk.sh)
|
||||||
|
/tools/emsdk/
|
||||||
|
|
||||||
# Clean clone for reproducible builds (generated by build-wxwidgets-wasm-clean.sh)
|
# Clean clone for reproducible builds (generated by build-wxwidgets-wasm-clean.sh)
|
||||||
wxwidgets-clean/
|
wxwidgets-clean/
|
||||||
|
|
||||||
|
|
|
||||||
10
README.md
10
README.md
|
|
@ -28,7 +28,7 @@ npm run test:kicad # KiCad tests (2 tests)
|
||||||
### wxWidgets Only (No Docker)
|
### wxWidgets Only (No Docker)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Requires: Emscripten SDK 4.0+, Node.js 18+
|
# Requires: Node.js 18+ (Emscripten SDK auto-installed on first build)
|
||||||
./scripts/build-wxuniversal-wasm.sh
|
./scripts/build-wxuniversal-wasm.sh
|
||||||
./scripts/build-wasm-test.sh
|
./scripts/build-wasm-test.sh
|
||||||
cd tests && npm install && npm test
|
cd tests && npm install && npm test
|
||||||
|
|
@ -117,15 +117,15 @@ Output: `tests/apps/standalone/`
|
||||||
- 10+ GB disk space for build cache
|
- 10+ GB disk space for build cache
|
||||||
|
|
||||||
### For wxWidgets Build (Local)
|
### For wxWidgets Build (Local)
|
||||||
- Emscripten SDK 4.0+
|
|
||||||
- Node.js 18+ (for tests)
|
- Node.js 18+ (for tests)
|
||||||
|
- Emscripten SDK (auto-installed on first build)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# macOS
|
|
||||||
brew install emscripten node
|
|
||||||
|
|
||||||
# Initialize submodules
|
# Initialize submodules
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
# Install Emscripten SDK (auto-runs on first build, or run manually)
|
||||||
|
./scripts/setup-emsdk.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Use ARM64-native image for Apple Silicon (M1/M2/M3/M4)
|
# Use ARM64-native image for Apple Silicon (M1/M2/M3/M4)
|
||||||
FROM emscripten/emsdk:4.0.22-arm64
|
FROM emscripten/emsdk:4.0.2-arm64
|
||||||
|
|
||||||
# Install build tools required for KiCad WASM build
|
# Install build tools required for KiCad WASM build
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ docker compose -f docker/docker-compose.yml up -d
|
||||||
# This avoids the timestamp mismatch cycle that caused full rebuilds every time.
|
# This avoids the timestamp mismatch cycle that caused full rebuilds every time.
|
||||||
# Transferred files get current container time, so make detects them correctly.
|
# Transferred files get current container time, so make detects them correctly.
|
||||||
echo "Syncing source code to container..."
|
echo "Syncing source code to container..."
|
||||||
|
# rsync exit code 24 = "some files vanished before transfer" (harmless race condition)
|
||||||
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
|
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
|
||||||
rsync -r --delete --checksum \
|
rsync -r --delete --checksum \
|
||||||
--exclude="build-wasm" \
|
--exclude="build-wasm" \
|
||||||
|
|
@ -41,7 +42,8 @@ docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
|
||||||
--exclude="logs" \
|
--exclude="logs" \
|
||||||
--exclude=".idea" \
|
--exclude=".idea" \
|
||||||
--exclude="node_modules" \
|
--exclude="node_modules" \
|
||||||
/workspace-host/ /workspace/
|
--exclude="tools/emsdk" \
|
||||||
|
/workspace-host/ /workspace/ || [ $? -eq 24 ]
|
||||||
|
|
||||||
# Run build command (without asyncify - handled on host due to memory requirements)
|
# Run build command (without asyncify - handled on host due to memory requirements)
|
||||||
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
|
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ set -e
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
# Source common environment (sets up Python 3.10+ for Emscripten)
|
# Source common environment (sets up local emsdk)
|
||||||
QUIET=1 source "$SCRIPT_DIR/common/env.sh"
|
QUIET=1 source "$SCRIPT_DIR/common/env.sh"
|
||||||
|
|
||||||
TEST_DIR="$PROJECT_ROOT/tests/gal-regression/wasm"
|
TEST_DIR="$PROJECT_ROOT/tests/gal-regression/wasm"
|
||||||
|
|
@ -35,7 +35,7 @@ echo " clang: $(which clang)"
|
||||||
|
|
||||||
# Verify em++ is available
|
# Verify em++ is available
|
||||||
if ! command -v em++ &> /dev/null; then
|
if ! command -v em++ &> /dev/null; then
|
||||||
echo "ERROR: em++ not found. Please install via: brew install emscripten"
|
echo "ERROR: em++ not found. Run: ./scripts/setup-emsdk.sh"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
# Redirect all output to a log file (re-execs script with redirection)
|
# Redirect all output to a log file (re-execs script with redirection)
|
||||||
source "$(dirname "$0")/common/logging.sh"
|
source "$(dirname "$0")/common/logging.sh"
|
||||||
|
|
||||||
# Source common environment (sets up EMSDK_PYTHON for Emscripten 4.0.22+)
|
# Source common environment (sets up local emsdk)
|
||||||
source "$(dirname "$0")/common/env.sh"
|
source "$(dirname "$0")/common/env.sh"
|
||||||
# This builds the GUI-enabled wxWidgets needed for KiCad
|
# This builds the GUI-enabled wxWidgets needed for KiCad
|
||||||
#
|
#
|
||||||
# Prerequisites:
|
# Prerequisites:
|
||||||
# - Emscripten SDK installed and activated
|
# - Emscripten SDK (auto-installed by env.sh via scripts/setup-emsdk.sh)
|
||||||
# - autoconf (for regenerating configure from configure.in)
|
# - autoconf (for regenerating configure from configure.in)
|
||||||
#
|
#
|
||||||
# To regenerate Makefile.in from bakefiles (after modifying files.bkl):
|
# To regenerate Makefile.in from bakefiles (after modifying files.bkl):
|
||||||
|
|
@ -23,14 +23,6 @@ source "$(dirname "$0")/common/env.sh"
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Ensure 'python' command is available (macOS only has python3)
|
|
||||||
# Homebrew's python libexec has the python -> python3 symlink
|
|
||||||
if [[ -d "/opt/homebrew/opt/python/libexec/bin" ]]; then
|
|
||||||
export PATH="/opt/homebrew/opt/python/libexec/bin:$PATH"
|
|
||||||
elif [[ -d "/usr/local/opt/python/libexec/bin" ]]; then
|
|
||||||
export PATH="/usr/local/opt/python/libexec/bin:$PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||||
BUILD_DIR="$PROJECT_ROOT/build-wasm/wxwidgets-universal"
|
BUILD_DIR="$PROJECT_ROOT/build-wasm/wxwidgets-universal"
|
||||||
|
|
|
||||||
|
|
@ -36,47 +36,18 @@ export WX_BUILD="$BUILD_ROOT/wxwidgets-universal"
|
||||||
# Emscripten settings
|
# Emscripten settings
|
||||||
export EMSDK_QUIET=1
|
export EMSDK_QUIET=1
|
||||||
|
|
||||||
# Homebrew Emscripten configuration
|
# Local emsdk: auto-install if missing, then source its environment
|
||||||
# The em++ script uses EMSDK_PYTHON (not PYTHON env var) for the Python interpreter
|
# The emsdk bundles its own Python, Node, and LLVM — no Homebrew needed
|
||||||
# and finds clang via PATH - Emscripten bundles its own LLVM with WebAssembly support
|
_EMSDK_DIR="$_KICAD_WASM_PROJECT_ROOT/tools/emsdk"
|
||||||
if [[ -d "/opt/homebrew/Cellar/emscripten" ]]; then
|
_EMSDK_ENV="$_EMSDK_DIR/emsdk_env.sh"
|
||||||
_EM_VERSION=$(ls /opt/homebrew/Cellar/emscripten/ | sort -V | tail -1)
|
|
||||||
_EM_LLVM_BIN="/opt/homebrew/Cellar/emscripten/$_EM_VERSION/libexec/llvm/bin"
|
if [ ! -f "$_EMSDK_ENV" ]; then
|
||||||
if [[ -d "$_EM_LLVM_BIN" ]]; then
|
echo "Emscripten SDK not found. Installing..."
|
||||||
# Add bundled LLVM to PATH so Emscripten finds its clang (not /usr/bin/clang)
|
"$_KICAD_WASM_SCRIPTS_DIR/setup-emsdk.sh"
|
||||||
export PATH="$_EM_LLVM_BIN:$PATH"
|
|
||||||
fi
|
|
||||||
elif [[ -d "/usr/local/Cellar/emscripten" ]]; then
|
|
||||||
_EM_VERSION=$(ls /usr/local/Cellar/emscripten/ | sort -V | tail -1)
|
|
||||||
_EM_LLVM_BIN="/usr/local/Cellar/emscripten/$_EM_VERSION/libexec/llvm/bin"
|
|
||||||
if [[ -d "$_EM_LLVM_BIN" ]]; then
|
|
||||||
export PATH="$_EM_LLVM_BIN:$PATH"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Emscripten 4.0.22+ requires Python 3.10+ (uses match statement and type union syntax)
|
if [ -f "$_EMSDK_ENV" ]; then
|
||||||
# The em++ shell script checks EMSDK_PYTHON first, then falls back to `which python3`
|
source "$_EMSDK_ENV" 2>/dev/null
|
||||||
# Set EMSDK_PYTHON to Homebrew's Python to ensure correct version is used
|
|
||||||
if [[ -d "/opt/homebrew/opt/python@3.14/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/opt/homebrew/opt/python@3.14/bin/python3.14"
|
|
||||||
elif [[ -d "/opt/homebrew/opt/python@3.13/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/opt/homebrew/opt/python@3.13/bin/python3.13"
|
|
||||||
elif [[ -d "/opt/homebrew/opt/python@3.12/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/opt/homebrew/opt/python@3.12/bin/python3.12"
|
|
||||||
elif [[ -d "/opt/homebrew/opt/python@3.11/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/opt/homebrew/opt/python@3.11/bin/python3.11"
|
|
||||||
elif [[ -d "/opt/homebrew/opt/python@3.10/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/opt/homebrew/opt/python@3.10/bin/python3.10"
|
|
||||||
elif [[ -d "/usr/local/opt/python@3.14/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/usr/local/opt/python@3.14/bin/python3.14"
|
|
||||||
elif [[ -d "/usr/local/opt/python@3.13/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/usr/local/opt/python@3.13/bin/python3.13"
|
|
||||||
elif [[ -d "/usr/local/opt/python@3.12/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/usr/local/opt/python@3.12/bin/python3.12"
|
|
||||||
elif [[ -d "/usr/local/opt/python@3.11/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/usr/local/opt/python@3.11/bin/python3.11"
|
|
||||||
elif [[ -d "/usr/local/opt/python@3.10/bin" ]]; then
|
|
||||||
export EMSDK_PYTHON="/usr/local/opt/python@3.10/bin/python3.10"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Common compiler flags
|
# Common compiler flags
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ setup_error_trap() {
|
||||||
# Verify Emscripten is available
|
# Verify Emscripten is available
|
||||||
verify_emscripten() {
|
verify_emscripten() {
|
||||||
if ! command -v emcc &> /dev/null; then
|
if ! command -v emcc &> /dev/null; then
|
||||||
log_error "Emscripten not found. Please run: source /path/to/emsdk/emsdk_env.sh"
|
log_error "Emscripten not found. Run: ./scripts/setup-emsdk.sh"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
log_info "Using Emscripten: $(emcc --version | head -1)"
|
log_info "Using Emscripten: $(emcc --version | head -1)"
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,35 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Download and cache Binaryen wasm-opt
|
# Get path to Binaryen wasm-opt
|
||||||
#
|
#
|
||||||
# Usage: ./scripts/tools/get-wasm-opt.sh
|
# Usage: ./scripts/common/get-wasm-opt.sh
|
||||||
# Output: Prints path to wasm-opt executable
|
# Output: Prints path to wasm-opt executable
|
||||||
#
|
#
|
||||||
# Binaryen v121 is used because v125 has a regression causing asyncify crashes.
|
# Prefers the emsdk-bundled Binaryen (tools/emsdk/upstream/bin/) so that the
|
||||||
# The binary is cached in tools/binaryen-121/
|
# wasm-opt and wasm-emscripten-finalize versions match the Emscripten that
|
||||||
|
# generated the JS glue. A version mismatch between the compiler's Binaryen
|
||||||
|
# (e.g. v121+72 dev) and a standalone release (v121) corrupts asyncify
|
||||||
|
# metadata, causing "func is not a function" errors at runtime.
|
||||||
|
#
|
||||||
|
# Falls back to downloading standalone Binaryen v121 if emsdk is not installed
|
||||||
|
# locally (e.g. CI environments that only use Docker).
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||||
|
|
||||||
|
# --- Prefer emsdk-bundled Binaryen (matches the Emscripten that compiled the WASM) ---
|
||||||
|
EMSDK_WASM_OPT="${PROJECT_ROOT}/tools/emsdk/upstream/bin/wasm-opt"
|
||||||
|
if [ -x "${EMSDK_WASM_OPT}" ]; then
|
||||||
|
EMSDK_VERSION=$("${EMSDK_WASM_OPT}" --version 2>&1 || true)
|
||||||
|
echo "Using emsdk-bundled Binaryen: ${EMSDK_VERSION}" >&2
|
||||||
|
echo "${EMSDK_WASM_OPT}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Fallback: download standalone Binaryen (for CI or environments without local emsdk) ---
|
||||||
|
echo "emsdk Binaryen not found at ${EMSDK_WASM_OPT}, falling back to standalone download..." >&2
|
||||||
|
|
||||||
BINARYEN_VERSION="121"
|
BINARYEN_VERSION="121"
|
||||||
BINARYEN_DIR="${PROJECT_ROOT}/build-wasm/tools/binaryen-${BINARYEN_VERSION}"
|
BINARYEN_DIR="${PROJECT_ROOT}/build-wasm/tools/binaryen-${BINARYEN_VERSION}"
|
||||||
WASM_OPT="${BINARYEN_DIR}/bin/wasm-opt"
|
WASM_OPT="${BINARYEN_DIR}/bin/wasm-opt"
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,11 @@ cat > "$SHIM_FILE" << 'HEADER'
|
||||||
// === dynCall shims for Emscripten exception handling ===
|
// === dynCall shims for Emscripten exception handling ===
|
||||||
// Auto-generated: maps dynCall_SIG() calls to getWasmTableEntry()
|
// Auto-generated: maps dynCall_SIG() calls to getWasmTableEntry()
|
||||||
// This fixes "dynCall_* is not defined" errors in Emscripten 4.x
|
// This fixes "dynCall_* is not defined" errors in Emscripten 4.x
|
||||||
|
//
|
||||||
|
// These shims are asyncify-aware: they track Asyncify.exportCallStack so that
|
||||||
|
// asyncify can rewind through indirect calls (e.g., main loop callbacks,
|
||||||
|
// timer callbacks, event handlers). Without this tracking, asyncify's doRewind
|
||||||
|
// fails because it can't find the entry function to re-enter the WASM module.
|
||||||
HEADER
|
HEADER
|
||||||
|
|
||||||
for sig in $SIGNATURES; do
|
for sig in $SIGNATURES; do
|
||||||
|
|
@ -55,12 +60,31 @@ for sig in $SIGNATURES; do
|
||||||
call_args="${call_args}a$i"
|
call_args="${call_args}a$i"
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "var dynCall_$sig = ($args) => getWasmTableEntry(index)($call_args);" >> "$SHIM_FILE"
|
cat >> "$SHIM_FILE" << SHIMEOF
|
||||||
|
function dynCall_$sig($args) {
|
||||||
|
var tableFunc = getWasmTableEntry(index);
|
||||||
|
if (typeof Asyncify !== 'undefined') {
|
||||||
|
var rewindKey = '__dyn_${sig}_' + index;
|
||||||
|
if (!wasmExports[rewindKey]) wasmExports[rewindKey] = tableFunc;
|
||||||
|
Asyncify.exportCallStack.push(rewindKey);
|
||||||
|
try {
|
||||||
|
return tableFunc($call_args);
|
||||||
|
} finally {
|
||||||
|
if (!ABORT) {
|
||||||
|
Asyncify.exportCallStack.pop();
|
||||||
|
Asyncify.maybeStopUnwind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tableFunc($call_args);
|
||||||
|
}
|
||||||
|
SHIMEOF
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "" >> "$SHIM_FILE"
|
echo "" >> "$SHIM_FILE"
|
||||||
echo "// === End dynCall shims ===" >> "$SHIM_FILE"
|
echo "// === End dynCall shims ===" >> "$SHIM_FILE"
|
||||||
|
|
||||||
|
|
||||||
# Find the insertion point: after getWasmTableEntry definition
|
# Find the insertion point: after getWasmTableEntry definition
|
||||||
# The pattern is:
|
# The pattern is:
|
||||||
# var getWasmTableEntry = funcPtr => {
|
# var getWasmTableEntry = funcPtr => {
|
||||||
|
|
@ -169,6 +193,18 @@ if [ "$COUNT_BEFORE" -gt 0 ]; then
|
||||||
TOTAL_FIXED=$((TOTAL_FIXED + FIXED))
|
TOTAL_FIXED=$((TOTAL_FIXED + FIXED))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Fix 5: _emscripten_set_main_loop empty iterFunc callback - signature v (void, no args)
|
||||||
|
# Pattern: var iterFunc = (() => {});
|
||||||
|
# The 'func' variable is the function pointer passed to _emscripten_set_main_loop
|
||||||
|
COUNT_BEFORE=$(grep -c 'var iterFunc = (() => {});' "$JS_FILE" || true)
|
||||||
|
if [ "$COUNT_BEFORE" -gt 0 ]; then
|
||||||
|
sed -i '' 's/var iterFunc = (() => {});/var iterFunc = () => dynCall_v(func);/g' "$JS_FILE"
|
||||||
|
COUNT_AFTER=$(grep -c 'var iterFunc = (() => {});' "$JS_FILE" || true)
|
||||||
|
FIXED=$((COUNT_BEFORE - COUNT_AFTER))
|
||||||
|
echo " Fixed $FIXED main loop callback(s) (dynCall_v)"
|
||||||
|
TOTAL_FIXED=$((TOTAL_FIXED + FIXED))
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$TOTAL_FIXED" -gt 0 ]; then
|
if [ "$TOTAL_FIXED" -gt 0 ]; then
|
||||||
echo "Total: Fixed $TOTAL_FIXED empty callback(s)"
|
echo "Total: Fixed $TOTAL_FIXED empty callback(s)"
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
# Dependency versions for KiCad WASM build
|
# Dependency versions for KiCad WASM build
|
||||||
# These versions match KiCad 8.99 requirements from CMakeLists.txt and vcpkg.json
|
# These versions match KiCad 8.99 requirements from CMakeLists.txt and vcpkg.json
|
||||||
|
|
||||||
|
# Emscripten SDK version (single source of truth for Docker and local builds)
|
||||||
|
export EMSCRIPTEN_VERSION="4.0.2"
|
||||||
|
|
||||||
# KiCad submodule version
|
# KiCad submodule version
|
||||||
export KICAD_COMMIT="4bfed3f1746e8cc0a7d942767770f56fa28b393c"
|
export KICAD_COMMIT="4bfed3f1746e8cc0a7d942767770f56fa28b393c"
|
||||||
export KICAD_VERSION="8.99"
|
export KICAD_VERSION="8.99"
|
||||||
|
|
|
||||||
60
scripts/setup-emsdk.sh
Executable file
60
scripts/setup-emsdk.sh
Executable file
|
|
@ -0,0 +1,60 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Install and activate the Emscripten SDK (emsdk) locally
|
||||||
|
#
|
||||||
|
# This script is idempotent - it skips installation if the correct version
|
||||||
|
# is already installed. The emsdk is installed into tools/emsdk/ which is
|
||||||
|
# gitignored (~1.5GB).
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/setup-emsdk.sh # Install/activate pinned version
|
||||||
|
# ./scripts/setup-emsdk.sh --force # Force reinstall
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
# Source version constants
|
||||||
|
source "$SCRIPT_DIR/common/versions.sh"
|
||||||
|
|
||||||
|
EMSDK_DIR="$PROJECT_ROOT/tools/emsdk"
|
||||||
|
VERSION="$EMSCRIPTEN_VERSION"
|
||||||
|
|
||||||
|
echo "=== Emscripten SDK Setup ==="
|
||||||
|
echo " Version: $VERSION"
|
||||||
|
echo " Location: $EMSDK_DIR"
|
||||||
|
|
||||||
|
# Check if already installed with correct version (unless --force)
|
||||||
|
if [ "$1" != "--force" ] && [ -f "$EMSDK_DIR/emsdk" ]; then
|
||||||
|
if "$EMSDK_DIR/emsdk" list 2>/dev/null | grep -q "^[[:space:]]*${VERSION}[[:space:]]*INSTALLED"; then
|
||||||
|
echo "Emscripten $VERSION is already installed and active."
|
||||||
|
echo "Use --force to reinstall."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clone emsdk if not present
|
||||||
|
if [ ! -d "$EMSDK_DIR" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Cloning emsdk..."
|
||||||
|
mkdir -p "$PROJECT_ROOT/tools"
|
||||||
|
git clone https://github.com/emscripten-core/emsdk.git "$EMSDK_DIR"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "Updating emsdk..."
|
||||||
|
(cd "$EMSDK_DIR" && git pull)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install and activate the pinned version
|
||||||
|
echo ""
|
||||||
|
echo "Installing Emscripten $VERSION..."
|
||||||
|
"$EMSDK_DIR/emsdk" install "$VERSION"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Activating Emscripten $VERSION..."
|
||||||
|
"$EMSDK_DIR/emsdk" activate "$VERSION"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Setup complete ==="
|
||||||
|
echo "Emscripten $VERSION is ready."
|
||||||
|
echo "Source env.sh to use it: source scripts/common/env.sh"
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit dd370ac191d5f20ea847b1bce4a611464f5baa65
|
Subproject commit c5aaa19ca9cffe739d9ccbc99003bc712eda031e
|
||||||
Loading…
Reference in a new issue