pcbjam/docker/build.sh

311 lines
14 KiB
Shell
Raw Normal View History

#!/bin/bash
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
# Build a KiCad app (pcbnew, eeschema, calculator) inside Docker, then run
jspi: retire the asyncify pipeline — knob, post-link tail, binaryen hooks Phase 8 in the parent repo. Deleted: asyncify-scheduler.js, apply-asyncify.sh, apply-finalize.sh, inject-dyncall-shims.sh, asyncify-imports/removelist.txt, the wasm-opt/finalize stub pair, scripts/binaryen-hoist-pass/ (the fork stays a dormant submodule; removal is a follow-up), bench/wasm-opt-bench.sh (README marked historical), wasm/shims/context_sleep.cpp, and the sched-context harness app + Makefile targets. PCBJAM_ASYNC_BACKEND is gone: build-wx-wasm.sh hardcodes the jspi stamp (still force-cleans pre-migration trees), build-kicad-target.sh gives editors the JSPI link surface and the CLIs nothing (they pin ASYNCIFY=0), the stub dance is replaced by an unconditional .real-restore, build-wasm-test.sh lost its whole post-link loop, docker/build.sh's postprocess is the ENV shim only, and Makefile.wasm links every app JSPI with the scheduler shim as a tracked prerequisite. pcbjam_async_policy.h keys on __EMSCRIPTEN__. jspi-scheduler.js: wxWasmMainLoopPump dropped from the wrap census (the export died with the D5 detach); inert [TRACE] instrumentation removed. CI: wasm-build.yml rewritten for the single-cache pipeline (one output cache keyed on compile inputs; post-processed bytes cached after the shim); opt_level input removed from both callers. wasm-cache-hash.mjs inputs now cover patch-env-shim.mjs + jspi-scheduler.js + jspi-exports.txt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDeBaKKhQztd8KiVtHuyXr
2026-08-13 08:39:12 +02:00
# the ENV shim on the host.
#
# Usage:
# ./docker/build.sh <app>[,<app>...] [args...]
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
#
# Apps:
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
# kicad_editor merged PCB + schematic editor image — serves all four editors
# (PCB / Footprint / Schematic / Symbol) via runtime --frame
2026-06-02 13:35:37 +02:00
# calculator PCB calculator
# pl_editor drawing-sheet editor
2026-06-03 14:23:57 +02:00
# gerbview Gerber viewer
# all build all of the above
feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2) All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared wx/common/boost linked once). One editor per page load, as before; frames pcb / fpedit / sch / symedit. - wasm/editor/: the merged executable target (single_top + both kiface library sets, whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine Kiface/getter binding + ODR renames + dual-kiface launcher). - wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each shared JS name once, dispatching on the live frame. - Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" = kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run on kicad bumps). - Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish list = the 4 real bundles. - Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens; PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec covers all four frames from the one bundle. Validated so far: frame-runtime 4/4 (each frame boots with the right title, no aborts, no duplicate embind registration); 24-spec merged-module regression green; 3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock, fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:48:11 +02:00
# pcbnew standalone PCB engine (debug aid; not deployed — kicad_editor is)
# eeschema standalone schematic engine (debug aid; not deployed)
#
# A comma-separated list builds just those apps in order (e.g.
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# "calculator,pl_editor" — used to exercise the multi-app path cheaply).
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
#
# Any extra args are forwarded to scripts/kicad/build-<app>.sh (e.g. -j 8,
# --full, --release, --diag=gal).
#
# The build is split into two phases:
jspi: retire the asyncify pipeline — knob, post-link tail, binaryen hooks Phase 8 in the parent repo. Deleted: asyncify-scheduler.js, apply-asyncify.sh, apply-finalize.sh, inject-dyncall-shims.sh, asyncify-imports/removelist.txt, the wasm-opt/finalize stub pair, scripts/binaryen-hoist-pass/ (the fork stays a dormant submodule; removal is a follow-up), bench/wasm-opt-bench.sh (README marked historical), wasm/shims/context_sleep.cpp, and the sched-context harness app + Makefile targets. PCBJAM_ASYNC_BACKEND is gone: build-wx-wasm.sh hardcodes the jspi stamp (still force-cleans pre-migration trees), build-kicad-target.sh gives editors the JSPI link surface and the CLIs nothing (they pin ASYNCIFY=0), the stub dance is replaced by an unconditional .real-restore, build-wasm-test.sh lost its whole post-link loop, docker/build.sh's postprocess is the ENV shim only, and Makefile.wasm links every app JSPI with the scheduler shim as a tracked prerequisite. pcbjam_async_policy.h keys on __EMSCRIPTEN__. jspi-scheduler.js: wxWasmMainLoopPump dropped from the wrap census (the export died with the D5 detach); inert [TRACE] instrumentation removed. CI: wasm-build.yml rewritten for the single-cache pipeline (one output cache keyed on compile inputs; post-processed bytes cached after the shim); opt_level input removed from both callers. wasm-cache-hash.mjs inputs now cover patch-env-shim.mjs + jspi-scheduler.js + jspi-exports.txt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDeBaKKhQztd8KiVtHuyXr
2026-08-13 08:39:12 +02:00
# 1. Docker: Compile KiCad to WASM (fully finalized; JSPI links in-container)
# 2. Host: ENV merge shim on the glue (patch-env-shim.mjs)
2026-06-01 17:31:03 +02:00
# Auto-launch the live progress dashboard in this terminal (handled by logging.sh,
# which owns the TTY before it re-execs us with output redirected). Set KICAD_NO_MONITOR=1
# to disable. MUST be set before sourcing logging.sh — that's where the dashboard is
# launched, in the pre-re-exec process.
export KICAD_MONITOR=1
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
# Redirect all output to a log file (re-execs script with redirection).
# MUST be sourced before arg parsing — the re-exec relies on the original
# "$@", so any shifts before this point would strip args from the re-exec.
source "$(dirname "$0")/../scripts/common/logging.sh"
2026-06-01 17:31:03 +02:00
# Build-progress markers (parsed by scripts/build-monitor.sh).
source "$(dirname "$0")/../scripts/common/stages.sh"
feat(wasm-eh): migrate the WASM build to native wasm exceptions (+ 3D viewer default-on) Replace the legacy Emscripten JS-exceptions model with native wasm-EH (legacy encoding) across the whole build, keeping Asyncify coroutines working via a from-source Binaryen --hoist-cpp-catches pre-pass. Net result: native-EH is the only build mode, the 3D viewer is on by default, and pcbnew shrinks substantially. Highlights: - Binaryen submodule everywhere + --hoist-cpp-catches integration in apply-asyncify; post-link Asyncify covers every app wasm (not just standalone test wasm). - Build deps (incl. OpenCASCADE without OCC_CONVERT_SIGNALS) and all KiCad apps with -fwasm-exceptions; emscripten_sleep added to the post-link asyncify-imports. - libcontext fiber entry wired under native exceptions; while-loop main loop + currData shim injected into all wx apps. - Native-EH collab apply fixed: DEBUG-define the embind TU + match all out-of-CMake C++ TUs' ABI flags to the core, fixing the vtable-layout skew / mis-dispatch. - 3D viewer enabled by default (real raytracer linked, not the stub). - Retire the EH-spike scaffolding; flip the asyncify-races ablation pins to shim-redundancy pins (native-EH stays clean with the legacy shims ablated). - Fix the asyncify-races quiescence check to not require Asyncify.currData==0: under the native-EH per-frame-yield top loop the main stack is asyncify-suspended every frame, so currData legitimately churns (a freed-but-not-yet-nulled buffer, not a leak). Refresh the pcbnew toolbar screenshot baseline for the new kicad. - CI: drop the obsolete binaryen_version input/env (the build uses the binaryen submodule fork's wasm-opt, not a version download); key the wasm-output cache on the binaryen submodule SHA instead. Bumps the wxwidgets + binaryen submodules to their squashed feature commits. Validated green: all 7 apps native-EH (real 3D in pcbnew); KiCad e2e 63/63 Firefox + Chromium (3D viewer renders); wx 336; coroutine 34/34 both engines; asyncify 7/7 both engines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 19:50:18 +02:00
# Pinned toolchain version (single source of truth). Exported so the compose build.args can pass it
# into the Docker image's emsdk install — bumping the toolchain is then a one-line edit in versions.sh.
source "$(dirname "$0")/../scripts/common/versions.sh"
export EMSCRIPTEN_VERSION
set -e
# Stop the builder container when the build ends (any exit path). A lingering
# idle builder keeps the Docker Desktop VM ballooned — each project's builder
# is capped at ${KICAD_DOCKER_MEM:-32G}, and with per-worktree compose projects
# two forgotten containers once read as ~56 GB of host RAM (page cache +
# high-water ballooning). The container is pure scaffolding: all caches live in
# the named volumes and `up -d` restarts it in seconds. Set
# KICAD_KEEP_CONTAINER=1 to keep it running for interactive exec/debugging.
_COMPOSE_FILE="$(cd "$(dirname "$0")" && pwd)/docker-compose.yml"
stop_builder() {
if [[ "${KICAD_KEEP_CONTAINER:-0}" != "1" ]]; then
docker compose -f "${_COMPOSE_FILE}" stop >/dev/null 2>&1 || true
fi
}
2026-06-01 17:31:03 +02:00
# Emit a completion/failure marker no matter how the build ends, so the monitor
# can stop on a clean "done" or show an aborted state instead of hanging.
trap '_rc=$?; if [ $_rc -eq 0 ]; then kw_done; else kw_fail $_rc; fi; stop_builder' EXIT
2026-06-01 17:31:03 +02:00
# On Ctrl-C, mark the build aborted so the final dashboard frame shows failed
# (not a stale "running" state). The EXIT trap above also fires; the monitor reads
# the last marker, so the duplicate is harmless.
trap 'kw_fail 130; exit 130' INT TERM
cd "$(dirname "$0")/.."
VALID_APPS="kicad_editor | pcbnew | eeschema | calculator | pl_editor | gerbview | kicad_tools | occ_service | ngspice_service | all"
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
usage() {
echo "Usage: ./docker/build.sh <app>[,<app>...] [args...]" >&2
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
echo " <app>: ${VALID_APPS}" >&2
echo " args: forwarded to scripts/kicad/build-<app>.sh (e.g. -j 8, --release)" >&2
}
# First positional arg must be the app name. No default — picking one would
# silently build the wrong thing for someone who forgot the argument.
if [[ "${1:-}" == "-h" ]] || [[ "${1:-}" == "--help" ]]; then
usage
exit 0
fi
if [[ $# -lt 1 ]] || [[ "$1" == -* ]]; then
echo "Error: missing <app> argument" >&2
usage
exit 1
fi
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
APP_NAME="$1"
shift
# Expand the app argument into APPS[]: "all", a single app, or a comma list.
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# kicad_editor first in "all" — the merged image is the deployed bundle and the
# longest compile, so it starts first and surfaces failures earliest.
# pcbnew/eeschema stay buildable as standalone debug aids but are not part of
# "all" (not deployed). kicad_tools joined "all" for the runner-image CI
# (tasks-runner 0001 R2).
if [[ "$APP_NAME" == "all" ]]; then
APPS=(kicad_editor occ_service ngspice_service calculator pl_editor gerbview kicad_tools)
else
IFS=',' read -r -a APPS <<< "$APP_NAME"
for app in "${APPS[@]}"; do
case "$app" in
kicad_editor|pcbnew|eeschema|calculator|pl_editor|gerbview|kicad_tools|occ_service|ngspice_service) ;;
*)
echo "Error: unknown app '$app' (expected: ${VALID_APPS})" >&2
usage
exit 1
;;
esac
done
fi
# Use branch name as Docker Compose project name for isolated containers/volumes.
# Honor a pre-set COMPOSE_PROJECT_NAME so a build can target an existing volume
# (e.g. reuse another branch's already-provisioned deps).
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD | tr '/' '-' | tr '[:upper:]' '[:lower:]')
export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-kicad-wasm-${BRANCH_NAME}}"
echo "Using Docker project: ${COMPOSE_PROJECT_NAME}"
echo "Building app: ${APP_NAME}"
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# Build phase (cache split). The container compile emits the finalized wasm;
# the host tail is only the ENV merge shim on the glue. Splitting compile and
# postprocess lets CI cache the expensive compile once and re-run just the
# host tail — see .github/workflows/.
# (default) both — compile in-container, then host post-process.
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# --compile-only — only the in-container compile → wasm+glue in output/.
jspi: retire the asyncify pipeline — knob, post-link tail, binaryen hooks Phase 8 in the parent repo. Deleted: asyncify-scheduler.js, apply-asyncify.sh, apply-finalize.sh, inject-dyncall-shims.sh, asyncify-imports/removelist.txt, the wasm-opt/finalize stub pair, scripts/binaryen-hoist-pass/ (the fork stays a dormant submodule; removal is a follow-up), bench/wasm-opt-bench.sh (README marked historical), wasm/shims/context_sleep.cpp, and the sched-context harness app + Makefile targets. PCBJAM_ASYNC_BACKEND is gone: build-wx-wasm.sh hardcodes the jspi stamp (still force-cleans pre-migration trees), build-kicad-target.sh gives editors the JSPI link surface and the CLIs nothing (they pin ASYNCIFY=0), the stub dance is replaced by an unconditional .real-restore, build-wasm-test.sh lost its whole post-link loop, docker/build.sh's postprocess is the ENV shim only, and Makefile.wasm links every app JSPI with the scheduler shim as a tracked prerequisite. pcbjam_async_policy.h keys on __EMSCRIPTEN__. jspi-scheduler.js: wxWasmMainLoopPump dropped from the wrap census (the export died with the D5 detach); inert [TRACE] instrumentation removed. CI: wasm-build.yml rewritten for the single-cache pipeline (one output cache keyed on compile inputs; post-processed bytes cached after the shim); opt_level input removed from both callers. wasm-cache-hash.mjs inputs now cover patch-env-shim.mjs + jspi-scheduler.js + jspi-exports.txt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDeBaKKhQztd8KiVtHuyXr
2026-08-13 08:39:12 +02:00
# --postprocess-only — only the host post-process (ENV merge shim) on the
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# existing output/ glue; NO container needed.
# Extracted here so they are NOT forwarded to the inner build-<app>.sh scripts.
PHASE="both"
_FILTERED=()
for _arg in "$@"; do
case "$_arg" in
--compile-only) PHASE="compile" ;;
--postprocess-only) PHASE="postprocess" ;;
*) _FILTERED+=("$_arg") ;;
esac
done
set -- "${_FILTERED[@]+"${_FILTERED[@]}"}"
# Add -j 10 by default if no -j flag is given
ARGS=("$@")
if [[ ! " ${ARGS[*]} " =~ " -j " ]]; then
ARGS+=("-j" "10")
fi
# Container compile + source sync — skipped entirely for --postprocess-only,
# which is pure host work on the already-built base wasm in output/.
if [[ "$PHASE" != "postprocess" ]]; then
feat(wasm-eh): migrate the WASM build to native wasm exceptions (+ 3D viewer default-on) Replace the legacy Emscripten JS-exceptions model with native wasm-EH (legacy encoding) across the whole build, keeping Asyncify coroutines working via a from-source Binaryen --hoist-cpp-catches pre-pass. Net result: native-EH is the only build mode, the 3D viewer is on by default, and pcbnew shrinks substantially. Highlights: - Binaryen submodule everywhere + --hoist-cpp-catches integration in apply-asyncify; post-link Asyncify covers every app wasm (not just standalone test wasm). - Build deps (incl. OpenCASCADE without OCC_CONVERT_SIGNALS) and all KiCad apps with -fwasm-exceptions; emscripten_sleep added to the post-link asyncify-imports. - libcontext fiber entry wired under native exceptions; while-loop main loop + currData shim injected into all wx apps. - Native-EH collab apply fixed: DEBUG-define the embind TU + match all out-of-CMake C++ TUs' ABI flags to the core, fixing the vtable-layout skew / mis-dispatch. - 3D viewer enabled by default (real raytracer linked, not the stub). - Retire the EH-spike scaffolding; flip the asyncify-races ablation pins to shim-redundancy pins (native-EH stays clean with the legacy shims ablated). - Fix the asyncify-races quiescence check to not require Asyncify.currData==0: under the native-EH per-frame-yield top loop the main stack is asyncify-suspended every frame, so currData legitimately churns (a freed-but-not-yet-nulled buffer, not a leak). Refresh the pcbnew toolbar screenshot baseline for the new kicad. - CI: drop the obsolete binaryen_version input/env (the build uses the binaryen submodule fork's wasm-opt, not a version download); key the wasm-output cache on the binaryen submodule SHA instead. Bumps the wxwidgets + binaryen submodules to their squashed feature commits. Validated green: all 7 apps native-EH (real 3D in pcbnew); KiCad e2e 63/63 Firefox + Chromium (3D viewer renders); wx 336; coroutine 34/34 both engines; asyncify 7/7 both engines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 19:50:18 +02:00
# Start container if not running. --build so the image is rebuilt when the pinned EMSCRIPTEN_VERSION
# (build-arg from versions.sh) changes; Docker layer-caches it to a near no-op when unchanged.
docker compose -f docker/docker-compose.yml up -d --build
# Sync source code to container volume (fixes macOS Docker VirtioFS issues)
# Use --checksum to only transfer files with different CONTENT, not timestamps.
# This avoids the timestamp mismatch cycle that caused full rebuilds every time.
# Transferred files get current container time, so make detects them correctly.
2026-06-01 17:31:03 +02:00
kw_stage container-sync
jspi: migration phases 0-7 — build knob, scheduler shim, test successor suite Toolchain: emsdk 6.0.6 (versions.sh; cache-hash keys on it). Build knob PCBJAM_ASYNC_BACKEND=jspi|asyncify: build-kicad-target.sh links editors with -sJSPI + -sJSPI_EXPORTS=@scripts/common/jspi-exports.txt + --pre-js jspi-scheduler.js (no DYNCALLS, no post-link asyncify pipeline); wx build stamps the backend and forces clean on flip or unknown provenance; docker/build.sh passes the knob, seeds the emscripten ports cache from the volume every launch, jspi postprocess = patch-env-shim only. scripts/common/shims/jspi-scheduler.js: the JSPI successor scheduler — token-wait registry, resume turnstile (one armed resume between engine re-entries, SP swaps only at microtask boundaries), green-region spill stacks (16-aligned tops), S1 embind mutator FIFO lane + parker wraps, S6 shutdown, libctx integration hooks (suspend/end/quarantine + g_current arm/clear), SuspendError attributor, lost-wake + stuck-window watchdogs, __wxWaitDump observability. Embind: PARKER registrations get emscripten::async() under PCBJAM_JSPI (wasm/bindings/pcbjam_async_policy.h). nanosleep yields route via the shim. Tests: tests/asyncify -> tests/jspi successor suite (jspi-stack red/green shadow-stack battery, jspi-coroutine MiniCoro harness, suspend-races semantic scenarios + __wxWaitDump books coherence); projects jspi-firefox/ jspi-chrome (asyncify-webkit retired — no JSPI in WebKit); unconditional Firefox JSPI pref; guard-beacons -> wait-beacons (+wxScheduler/libctxJspi families); Makefile.wasm links test apps against JSPI with the shim as a tracked link prerequisite. Web: WasmTool setRo await + __wxWaitDump forensics, open-flow contained promise, scheduler-shim.test.ts retargeted (8 green). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDeBaKKhQztd8KiVtHuyXr
2026-08-13 07:06:24 +02:00
# Re-seed the emscripten ports cache from the persistent volume: /emsdk lives
# in the container layer, so any image-context edit recreates the container
# and wipes the cache — and the in-container github fetch is flaky. Seeds are
# staged once into the kicad-build-cache volume (emcache/ports); this copy
# survives every recreation. No-op when the staging dir is absent.
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder bash -c \
'if [ -d /workspace/build-wasm/emcache/ports ]; then \
mkdir -p /emsdk/upstream/emscripten/cache/ports && \
cp -a /workspace/build-wasm/emcache/ports/. /emsdk/upstream/emscripten/cache/ports/ && \
echo "seeded emscripten ports cache from volume"; fi' || true
echo "Syncing source code to container..."
2026-05-28 17:21:26 +02:00
# rsync into the macOS-backed volume intermittently hits transient VirtioFS glitches:
# temp-file rename failures (exit 23) or vanished-source files (exit 24, harmless).
# --inplace avoids the temp-file+rename pattern that triggers exit 23; retry up to 3x
# for any residual flakiness (--checksum makes each retry skip already-synced files).
sync_rc=0
for sync_attempt in 1 2 3; do
if docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
rsync -r --delete --checksum --inplace \
--exclude="build-wasm" \
--exclude="output" \
--exclude=".git" \
--exclude="logs" \
--exclude=".idea" \
--exclude="node_modules" \
--exclude="tools/emsdk" \
/workspace-host/ /workspace/
then
sync_rc=0
else
sync_rc=$?
fi
{ [ $sync_rc -eq 0 ] || [ $sync_rc -eq 24 ]; } && break
echo "rsync attempt ${sync_attempt} failed (exit ${sync_rc}); retrying in 2s..."
sleep 2
done
if [ $sync_rc -ne 0 ] && [ $sync_rc -ne 24 ]; then
echo "ERROR: source sync failed after retries (exit ${sync_rc})"; exit 1
fi
fi # end: container compile + sync guard ("$PHASE" != postprocess)
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
# Map an app name to its inner CMake build subdirectory. Most apps share their
# subdir name with the app name; pcb_calculator emits OUTPUT_NAME=calculator
# but lives under the pcb_calculator/ subtree.
kicad_subdir_for() {
case "$1" in
calculator) echo "pcb_calculator" ;;
pl_editor) echo "pagelayout_editor" ;;
*) echo "$1" ;;
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
esac
}
# Phase 1 of one app: compile in the container and copy the output to ./output.
2026-06-01 17:31:03 +02:00
# Args: <app> [index] [total] — index/total drive the monitor's app counter.
compile_app() {
local app="$1"
2026-06-01 17:31:03 +02:00
local index="${2:-1}"
local total="${3:-1}"
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
local subdir
subdir=$(kicad_subdir_for "$app")
2026-06-01 17:31:03 +02:00
kw_app "$app" "$index" "$total"
echo ""
2026-06-01 17:31:03 +02:00
echo "=== Building ${app} (${index}/${total}) ==="
refactor: collapse dual-mode plumbing — the DOM port is the only WASM build The canvas (wxUniversal) mode is gone (wxwidgets submodule); remove every piece of side-by-side plumbing so there is exactly one build and one test flow: - scripts/build-wxuniversal-wasm.sh -> scripts/build-wx-wasm.sh; no --dom/--enable-universal; builds into build-wasm/wxwidgets - build-wasm-test.sh: no DOM_BUILD / apps-dom rsync mirror / PORT=dom; apps build straight into tests/apps (Makefile.wasm PORT conditionals collapsed; wx.js + wx-dom.js always pre-js) - docker/build.sh, build-kicad-target.sh, env.sh: WX_PORT / -dom / -universal suffixes removed; kicad builds to kicad-<app>, outputs to output/; wx.js/wx-dom.js copied from the real source path (/workspace/wxwidgets/build/wasm — the old build-wasm path never existed and silently failed) - setup-kicad-wasm.sh: single target dir; the perl wx-dom.js injection is gone — the 7 checked-in kicad pages now reference wx-dom.js directly - playwright configs serve apps/; fixtures drop the test-results/dom and logs/wxwidgets/dom namespacing; boot.spec asserts wxDomPort unconditionally; pcbnew.spec uses one reference image; appearance.spec assertions unconditional - compare/update-baseline-screenshots.sh: --port removed - tests/gal-regression/wasm/Makefile: links build-wasm/wxwidgets and carries wx-dom.js as a second pre-js — the gal-webgl suite (30 specs) now actually builds and runs here (it needed host-side boost+glm via scripts/deps; the bundle had been missing, timing the whole spec out) - tests: clickCanvas() dispatches via page.mouse (DOM widgets legitimately cover the canvas; locator actionability refused the click); the comprehensive spec drives wxChoice through its native <select> (browser-owned popup cannot be coordinate-clicked) - docs: README/CLAUDE.md/build.md script names and dirs; features/wx-dom-port README reframed (DOM is THE port), visual-notes bugs 26-28; FindwxWidgets.cmake config label drops 'wasmuniv' - wxwidgets submodule -> 9dbacc9448 (DOM-only port, fork diff shrunk) Gate: full wx e2e suite 292 passed / 1 skipped / 0 failed — first run ever with the gal-webgl specs green (28 scenarios + load + sequential). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 10:18:16 +02:00
local out_dir="output"
local kicad_build="kicad-${app}"
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
# Run build inside the container.
# -e EMSDK=/emsdk: `docker compose exec` bypasses the entrypoint that sources
refactor(build): fold calculator into unified docker/build.sh dispatch Convert the calculator port (commit 0464470) from the parallel/copy-paste pattern to the dispatch pattern used by pcbnew + eeschema. - docker/build.sh: <app> is now required (no pcbnew default); missing, unknown, and --help paths all print "pcbnew | eeschema | calculator | all". Adds calculator to build_app() via kicad_subdir_for() (pcb_calculator inner subdir, calculator.* output basename). Also fixes the EMSDK=/emsdkkicad-wasm-builder typo that snuck in during the calc merge. - scripts/kicad/build-kicad-target.sh: accepts calculator; introduces KICAD_TARGET (pcb_calculator for calc, == APP_NAME otherwise) used for the make target, embind include path, and final-log line. - scripts/kicad/build-calculator.sh: 305-line copy of build-pcbnew.sh collapsed to a 7-line wrapper around build-kicad-target.sh. - tests/scripts/setup-kicad-wasm.sh: copy_app calculator added with the same pcb_calculator subdir mapping for the docker-volume fallback path. - tests/package.json: test:calculator* routed through the shared playwright-kicad.config.ts kicad/calculator.spec.ts (mirrors eeschema). - Delete: docker/build-calculator.sh, tests/scripts/setup-calculator-wasm.sh, tests/playwright-calculator.config.ts. Bumps wxwidgets d1d1627 -> 6fb2eac (origin/wasm-port). The new sha includes "unic/combobox: add GetCurrentSelection() inline default" which calc's kicad/pcb_calculator/widgets/unit_selector.cpp needs to compile. Without this bump the unified dispatch would expose calc as a buildable target but the build itself would fail. Verified: build.sh all completes clean across all three apps; pcbnew/eeschema e2e pass; calc compiles and launches (test stability separate from this refactor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:01:44 +02:00
# emsdk_env.sh, so the build shell would lack emcc/embuilder on PATH. Setting
# EMSDK lets scripts/common/env.sh source /emsdk/emsdk_env.sh and activate the toolchain.
# BUILD_3D_VIEWER passes through EMPTY when the host didn't set it, so
# build-kicad-target.sh can apply per-app defaults (ON for editors, OFF
# for headless CLIs like kicad_tools — the gl1 shim needs glm).
refactor: collapse dual-mode plumbing — the DOM port is the only WASM build The canvas (wxUniversal) mode is gone (wxwidgets submodule); remove every piece of side-by-side plumbing so there is exactly one build and one test flow: - scripts/build-wxuniversal-wasm.sh -> scripts/build-wx-wasm.sh; no --dom/--enable-universal; builds into build-wasm/wxwidgets - build-wasm-test.sh: no DOM_BUILD / apps-dom rsync mirror / PORT=dom; apps build straight into tests/apps (Makefile.wasm PORT conditionals collapsed; wx.js + wx-dom.js always pre-js) - docker/build.sh, build-kicad-target.sh, env.sh: WX_PORT / -dom / -universal suffixes removed; kicad builds to kicad-<app>, outputs to output/; wx.js/wx-dom.js copied from the real source path (/workspace/wxwidgets/build/wasm — the old build-wasm path never existed and silently failed) - setup-kicad-wasm.sh: single target dir; the perl wx-dom.js injection is gone — the 7 checked-in kicad pages now reference wx-dom.js directly - playwright configs serve apps/; fixtures drop the test-results/dom and logs/wxwidgets/dom namespacing; boot.spec asserts wxDomPort unconditionally; pcbnew.spec uses one reference image; appearance.spec assertions unconditional - compare/update-baseline-screenshots.sh: --port removed - tests/gal-regression/wasm/Makefile: links build-wasm/wxwidgets and carries wx-dom.js as a second pre-js — the gal-webgl suite (30 specs) now actually builds and runs here (it needed host-side boost+glm via scripts/deps; the bundle had been missing, timing the whole spec out) - tests: clickCanvas() dispatches via page.mouse (DOM widgets legitimately cover the canvas; locator actionability refused the click); the comprehensive spec drives wxChoice through its native <select> (browser-owned popup cannot be coordinate-clicked) - docs: README/CLAUDE.md/build.md script names and dirs; features/wx-dom-port README reframed (DOM is THE port), visual-notes bugs 26-28; FindwxWidgets.cmake config label drops 'wasmuniv' - wxwidgets submodule -> 9dbacc9448 (DOM-only port, fork diff shrunk) Gate: full wx e2e suite 292 passed / 1 skipped / 0 failed — first run ever with the gal-webgl specs green (28 scenarios + load + sequential). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 10:18:16 +02:00
docker compose -f docker/docker-compose.yml exec -e EMSDK=/emsdk \
-e BUILD_3D_VIEWER="${BUILD_3D_VIEWER:-}" \
kicad-wasm-builder \
"/workspace/scripts/kicad/build-${app}.sh" "${ARGS[@]}"
# Copy output to host-accessible directory.
# ${app}.wasm.debug.wasm contains DWARF debug info (when built with -gseparate-dwarf).
2026-06-01 17:31:03 +02:00
kw_stage copy-output
echo "Copying ${app} build output to ./${out_dir}/..."
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
bash -c "mkdir -p /workspace/${out_dir} && \
cp /workspace/build-wasm/${kicad_build}/${subdir}/${app}.{js,wasm,wasm.debug.wasm,wasm.map,worker.js} /workspace/${out_dir}/ 2>/dev/null || \
cp /workspace/build-wasm/${kicad_build}/${subdir}/${app}.{js,wasm} /workspace/${out_dir}/; \
cp /workspace/build-wasm/${kicad_build}/resources/images.tar.gz /workspace/${out_dir}/ 2>/dev/null || true; \
refactor: collapse dual-mode plumbing — the DOM port is the only WASM build The canvas (wxUniversal) mode is gone (wxwidgets submodule); remove every piece of side-by-side plumbing so there is exactly one build and one test flow: - scripts/build-wxuniversal-wasm.sh -> scripts/build-wx-wasm.sh; no --dom/--enable-universal; builds into build-wasm/wxwidgets - build-wasm-test.sh: no DOM_BUILD / apps-dom rsync mirror / PORT=dom; apps build straight into tests/apps (Makefile.wasm PORT conditionals collapsed; wx.js + wx-dom.js always pre-js) - docker/build.sh, build-kicad-target.sh, env.sh: WX_PORT / -dom / -universal suffixes removed; kicad builds to kicad-<app>, outputs to output/; wx.js/wx-dom.js copied from the real source path (/workspace/wxwidgets/build/wasm — the old build-wasm path never existed and silently failed) - setup-kicad-wasm.sh: single target dir; the perl wx-dom.js injection is gone — the 7 checked-in kicad pages now reference wx-dom.js directly - playwright configs serve apps/; fixtures drop the test-results/dom and logs/wxwidgets/dom namespacing; boot.spec asserts wxDomPort unconditionally; pcbnew.spec uses one reference image; appearance.spec assertions unconditional - compare/update-baseline-screenshots.sh: --port removed - tests/gal-regression/wasm/Makefile: links build-wasm/wxwidgets and carries wx-dom.js as a second pre-js — the gal-webgl suite (30 specs) now actually builds and runs here (it needed host-side boost+glm via scripts/deps; the bundle had been missing, timing the whole spec out) - tests: clickCanvas() dispatches via page.mouse (DOM widgets legitimately cover the canvas; locator actionability refused the click); the comprehensive spec drives wxChoice through its native <select> (browser-owned popup cannot be coordinate-clicked) - docs: README/CLAUDE.md/build.md script names and dirs; features/wx-dom-port README reframed (DOM is THE port), visual-notes bugs 26-28; FindwxWidgets.cmake config label drops 'wasmuniv' - wxwidgets submodule -> 9dbacc9448 (DOM-only port, fork diff shrunk) Gate: full wx e2e suite 292 passed / 1 skipped / 0 failed — first run ever with the gal-webgl specs green (28 scenarios + load + sequential). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 10:18:16 +02:00
cp /workspace/wxwidgets/build/wasm/wx.js /workspace/${out_dir}/ 2>/dev/null || true; \
cp /workspace/wxwidgets/build/wasm/wx-dom.js /workspace/${out_dir}/ 2>/dev/null || true"
# The container runs as root, so files in the bind-mounted ./output land
# root-owned on the host. macOS Docker Desktop remaps ownership to the host
jspi: retire the asyncify pipeline — knob, post-link tail, binaryen hooks Phase 8 in the parent repo. Deleted: asyncify-scheduler.js, apply-asyncify.sh, apply-finalize.sh, inject-dyncall-shims.sh, asyncify-imports/removelist.txt, the wasm-opt/finalize stub pair, scripts/binaryen-hoist-pass/ (the fork stays a dormant submodule; removal is a follow-up), bench/wasm-opt-bench.sh (README marked historical), wasm/shims/context_sleep.cpp, and the sched-context harness app + Makefile targets. PCBJAM_ASYNC_BACKEND is gone: build-wx-wasm.sh hardcodes the jspi stamp (still force-cleans pre-migration trees), build-kicad-target.sh gives editors the JSPI link surface and the CLIs nothing (they pin ASYNCIFY=0), the stub dance is replaced by an unconditional .real-restore, build-wasm-test.sh lost its whole post-link loop, docker/build.sh's postprocess is the ENV shim only, and Makefile.wasm links every app JSPI with the scheduler shim as a tracked prerequisite. pcbjam_async_policy.h keys on __EMSCRIPTEN__. jspi-scheduler.js: wxWasmMainLoopPump dropped from the wrap census (the export died with the D5 detach); inert [TRACE] instrumentation removed. CI: wasm-build.yml rewritten for the single-cache pipeline (one output cache keyed on compile inputs; post-processed bytes cached after the shim); opt_level input removed from both callers. wasm-cache-hash.mjs inputs now cover patch-env-shim.mjs + jspi-scheduler.js + jspi-exports.txt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDeBaKKhQztd8KiVtHuyXr
2026-08-13 08:39:12 +02:00
# user, but on a Linux CI runner the host-side ENV-shim step can't write
# into ./output. Hand ownership back.
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
chown -R "$(id -u):$(id -g)" /workspace/output || true
}
jspi: retire the asyncify pipeline — knob, post-link tail, binaryen hooks Phase 8 in the parent repo. Deleted: asyncify-scheduler.js, apply-asyncify.sh, apply-finalize.sh, inject-dyncall-shims.sh, asyncify-imports/removelist.txt, the wasm-opt/finalize stub pair, scripts/binaryen-hoist-pass/ (the fork stays a dormant submodule; removal is a follow-up), bench/wasm-opt-bench.sh (README marked historical), wasm/shims/context_sleep.cpp, and the sched-context harness app + Makefile targets. PCBJAM_ASYNC_BACKEND is gone: build-wx-wasm.sh hardcodes the jspi stamp (still force-cleans pre-migration trees), build-kicad-target.sh gives editors the JSPI link surface and the CLIs nothing (they pin ASYNCIFY=0), the stub dance is replaced by an unconditional .real-restore, build-wasm-test.sh lost its whole post-link loop, docker/build.sh's postprocess is the ENV shim only, and Makefile.wasm links every app JSPI with the scheduler shim as a tracked prerequisite. pcbjam_async_policy.h keys on __EMSCRIPTEN__. jspi-scheduler.js: wxWasmMainLoopPump dropped from the wrap census (the export died with the D5 detach); inert [TRACE] instrumentation removed. CI: wasm-build.yml rewritten for the single-cache pipeline (one output cache keyed on compile inputs; post-processed bytes cached after the shim); opt_level input removed from both callers. wasm-cache-hash.mjs inputs now cover patch-env-shim.mjs + jspi-scheduler.js + jspi-exports.txt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDeBaKKhQztd8KiVtHuyXr
2026-08-13 08:39:12 +02:00
# Phase 2 of one app: host-side post-processing (ENV merge shim). Pure host
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# work on output/${app}.js — no container needed.
postprocess_app() {
local app="$1"
refactor: collapse dual-mode plumbing — the DOM port is the only WASM build The canvas (wxUniversal) mode is gone (wxwidgets submodule); remove every piece of side-by-side plumbing so there is exactly one build and one test flow: - scripts/build-wxuniversal-wasm.sh -> scripts/build-wx-wasm.sh; no --dom/--enable-universal; builds into build-wasm/wxwidgets - build-wasm-test.sh: no DOM_BUILD / apps-dom rsync mirror / PORT=dom; apps build straight into tests/apps (Makefile.wasm PORT conditionals collapsed; wx.js + wx-dom.js always pre-js) - docker/build.sh, build-kicad-target.sh, env.sh: WX_PORT / -dom / -universal suffixes removed; kicad builds to kicad-<app>, outputs to output/; wx.js/wx-dom.js copied from the real source path (/workspace/wxwidgets/build/wasm — the old build-wasm path never existed and silently failed) - setup-kicad-wasm.sh: single target dir; the perl wx-dom.js injection is gone — the 7 checked-in kicad pages now reference wx-dom.js directly - playwright configs serve apps/; fixtures drop the test-results/dom and logs/wxwidgets/dom namespacing; boot.spec asserts wxDomPort unconditionally; pcbnew.spec uses one reference image; appearance.spec assertions unconditional - compare/update-baseline-screenshots.sh: --port removed - tests/gal-regression/wasm/Makefile: links build-wasm/wxwidgets and carries wx-dom.js as a second pre-js — the gal-webgl suite (30 specs) now actually builds and runs here (it needed host-side boost+glm via scripts/deps; the bundle had been missing, timing the whole spec out) - tests: clickCanvas() dispatches via page.mouse (DOM widgets legitimately cover the canvas; locator actionability refused the click); the comprehensive spec drives wxChoice through its native <select> (browser-owned popup cannot be coordinate-clicked) - docs: README/CLAUDE.md/build.md script names and dirs; features/wx-dom-port README reframed (DOM is THE port), visual-notes bugs 26-28; FindwxWidgets.cmake config label drops 'wasmuniv' - wxwidgets submodule -> 9dbacc9448 (DOM-only port, fork diff shrunk) Gate: full wx e2e suite 292 passed / 1 skipped / 0 failed — first run ever with the gal-webgl specs green (28 scenarios + load + sequential). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 10:18:16 +02:00
local out_dir="output"
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# The headless CLI and the OCC/ngspice services skip the ENV merge shim:
# it exists for the interactive apps' runtime env overrides (?trace=),
# which these targets never read.
if [ "$app" = "kicad_tools" ] || [ "$app" = "occ_service" ] || [ "$app" = "ngspice_service" ]; then
echo "Skipping host post-processing for ${app} (finalized in-container)"
return 0
fi
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# ENV merge shim: the emscripten glue never merges Module.ENV into the
jspi: retire the asyncify pipeline — knob, post-link tail, binaryen hooks Phase 8 in the parent repo. Deleted: asyncify-scheduler.js, apply-asyncify.sh, apply-finalize.sh, inject-dyncall-shims.sh, asyncify-imports/removelist.txt, the wasm-opt/finalize stub pair, scripts/binaryen-hoist-pass/ (the fork stays a dormant submodule; removal is a follow-up), bench/wasm-opt-bench.sh (README marked historical), wasm/shims/context_sleep.cpp, and the sched-context harness app + Makefile targets. PCBJAM_ASYNC_BACKEND is gone: build-wx-wasm.sh hardcodes the jspi stamp (still force-cleans pre-migration trees), build-kicad-target.sh gives editors the JSPI link surface and the CLIs nothing (they pin ASYNCIFY=0), the stub dance is replaced by an unconditional .real-restore, build-wasm-test.sh lost its whole post-link loop, docker/build.sh's postprocess is the ENV shim only, and Makefile.wasm links every app JSPI with the scheduler shim as a tracked prerequisite. pcbjam_async_policy.h keys on __EMSCRIPTEN__. jspi-scheduler.js: wxWasmMainLoopPump dropped from the wrap census (the export died with the D5 detach); inert [TRACE] instrumentation removed. CI: wasm-build.yml rewritten for the single-cache pipeline (one output cache keyed on compile inputs; post-processed bytes cached after the shim); opt_level input removed from both callers. wasm-cache-hash.mjs inputs now cover patch-env-shim.mjs + jspi-scheduler.js + jspi-exports.txt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDeBaKKhQztd8KiVtHuyXr
2026-08-13 08:39:12 +02:00
# runtime ENV (?trace= would be a silent no-op — see docs/features/libs/0013).
kw_stage env-shim
node ./scripts/common/patch-env-shim.mjs "${out_dir}/${app}.js"
}
TOTAL_APPS="${#APPS[@]}"
if [[ "$PHASE" == "compile" ]]; then
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# --compile-only: produce the wasm+glue in output/; no host post-process.
idx=1
for app in "${APPS[@]}"; do
compile_app "$app" "$idx" "$TOTAL_APPS"
idx=$((idx + 1))
done
elif [[ "$PHASE" == "postprocess" ]]; then
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
# --postprocess-only: pure host post-process on the existing output/ glue
# (no container).
for app in "${APPS[@]}"; do
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose The runtime is JSPI-only; this removes everything that still pretended otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove the inventory; every deletion verified by grep closure + full gates. Broken-right-now fixes: - deploy-staging.yml passed the retired opt_level input — the workflow could not even start. Removed. - env.sh carried dead exports with a live -sASYNCIFY=1 inside (WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason. - docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone. Dead weight removed: - binaryen submodule (nothing builds or invokes it), wasm-opt-bench workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess scaffolding (existed to parallelize the deleted wasm-opt phase; the postprocess is a seconds-long node script and now runs inline), build-monitor's dead asyncify rows, sched-context orphan build output, dead .gitignore entries, the .jspi-assets spike dir (the two wf-result research JSONs moved to docs/features/async/migration-evidence/). - bindings: fiber_park.h + its 12 embind registrations (broken-if- called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route, main_stack_runner.h + 5 includes, the always-null context-sleep weak hook in nanosleep_yield.c. - shim: the backend field (installed-flag idempotency instead), noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the WasmTool fallback and string-dump normalize branch). - web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts (gerber-demo keeps it: it loads the deployed CDN release, which predates emscripten 6 — noted inline). Conditionals: all 'backend === jspi' checks reduced to scheduler- presence checks; races_quiescent re-keyed from Asyncify.state (vacuous) to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive, which is the probing activation's own window by definition). Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→ JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS, kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests), collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→ wasmTrapSignatures (lists byte-identical). Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused asserts re-keyed to live JSPI beacons; eeschema-load's failure message no longer sends the developer to a deleted script; wait-beacons' dead families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is unconstructible); the embind test.fail re-gated with the JSPI reason (plain embind invokers cannot suspend — verified still failing); lint-determinism now scans tests/jspi (166 files clean); eeschema-collab local-move gated to chromium (~50% flaky on FF even solo; pcbnew twin covers both engines). Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md describes the single-phase build; docs/features/async/README.md banner-marked historical and repointed at the NEW 23-jspi-runtime.md (current architecture: export census, turnstile, libcontext ownership + refusal contract, embind call shapes, the em-pthread service-wrapper trick, exception policy, known gaps). Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the quiescence-probe fix; the 3 other reds were verified contention flakes solo-green or the documented FF gate), web 76/0, jspi 18/18 both engines, vitest 295/295 + 17/17, all lints green, live-app census clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
postprocess_app "$app"
done
else
# both, sequential.
idx=1
for app in "${APPS[@]}"; do
compile_app "$app" "$idx" "$TOTAL_APPS"
postprocess_app "$app"
idx=$((idx + 1))
done
fi
echo ""
echo "Build complete. Output files in ./output/"
ls -lh output/