The footprint and symbol editors are no longer separate WASM bundles: the frontend loads the parent pcbnew/eeschema bundle and passes --frame=fpedit / --frame=symedit (TOOL_BUNDLE + TOOL_FRAME -> Module.arguments in boot). Drops the two duplicate build+deploy targets and their wrapper scripts + vestigial embind; adds low-level harnesses (footprint_editor.html, symbol_editor.html) and a runtime-frame spec. Bumps the kicad submodule to the runtime --frame launcher. The frame-runtime spec is listed in PCBNEW_FAMILY_SPECS so CI routes it to the chromium-ci (V8) project — its footprint case boots the pcbnew module, which OOMs SpiderMonkey on x86 CI. Includes the editor-unification dossier (research docs 01-04 + the as-built implementation record 05). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8.6 KiB
05 — Part 1: implementation record & current state
Status: Part 1 IMPLEMENTED and validated end-to-end (2026-07-02). This is the as-built companion to the
03plan: what actually changed, how the runtime mechanism works, what the research got slightly wrong, how it was verified, and the current git/build state. Part 2 (04) remains deferred by design.
One-paragraph summary
footprint_editor and symbol_editor are no longer separate WASM builds. The
pcbnew / eeschema bundle now opens the footprint / symbol editor at runtime,
selected by a --frame=<token> argument threaded through Emscripten's
Module.arguments and parsed in kicad/common/single_top.cpp (mirroring the upstream
--frame parser in kicad/kicad.cpp). The two duplicate build+deploy targets, their
launcher scripts, and a vestigial embind file are gone; the frontend re-points the two
library tools onto their parent bundle. Net effect: ~228 MB of duplicated deployed
WASM removed (plus their ~3 GB of debug DWARF sidecars) with zero download penalty,
since the footprint/symbol bundle was already a full copy of its twin.
What changed
C++ — kicad submodule (kept close to upstream; all new logic #ifdef __EMSCRIPTEN__)
| File | Change |
|---|---|
common/single_top.cpp |
On the WASM path, parse --frame=<token> into a FRAME_T (tokens: pcb, fpedit, sch, symedit, gerb, ds, calc), defaulting to the build-time TOP_FRAME; open it with Kiway.Player(topFrame, true). --frame is also added to the existing positional-file wxCmdLineParser desc so it's ignored there. The default data-file extension is derived from the resolved frame at runtime (kicad_pcb/kicad_mod/kicad_sch/kicad_sym) instead of the compile-time PGM_DATA_FILE_EXT (native still uses PGM_DATA_FILE_EXT). |
pcbnew/CMakeLists.txt |
Removed the WASM-only footprint_editor executable block (the pcbnew kiface already compiles footprint_edit_frame.cpp). |
eeschema/CMakeLists.txt |
Removed the WASM-only symbol_editor executable block. |
Native builds are byte-identical (topFrame == TOP_FRAME when no flag is passed; the
whole block is WASM-guarded).
Build & deploy — root repo
docker/build.sh—allnow expands to 5 apps (pcbnew eeschema calculator pl_editor gerbview);symbol_editor/footprint_editordropped from the valid-apps list, theallarray, the arg-validation case, andkicad_subdir_for.scripts/kicad/build-kicad-target.sh— removed the two apps' target/subdir,EMBIND_APP, andSTUB_APPcase arms + usage strings.- Deleted
scripts/kicad/build-symbol_editor.sh,scripts/kicad/build-footprint_editor.sh, and the vestigialwasm/bindings/symbol_editor_embind.cpp. scripts/deploy/publish-wasm.mjs— publish list trimmed to the 5 real bundles.
Frontend — web/standalone (the two tools stay visible in the UI; only how they boot changed)
src/wasm/constants.ts— newTOOL_BUNDLE(footprint_editor→pcbnew,symbol_editor→eeschema, others→self) andTOOL_FRAME(footprint_editor→"fpedit",symbol_editor→"symedit", others→undefined).src/wasm/wasm-assets.ts—resolveWasmBaseresolves the bundle's CDN folder/version (the manifest only lists the 5 published bundles now).src/wasm/boot.ts—BootOptions.frame; computesbundle = TOOL_BUNDLE[tool]; fetches<base>/<bundle>.{wasm,js}and the pthread worker from the bundle; setsModule.arguments = ["--frame=<token>"].src/components/WasmTool.tsx— passesframe: TOOL_FRAME[tool]intobootKicadTool.
Tests
tests/apps/kicad/symbol_editor.html— now loadseeschema.jswithModule.arguments=['--frame=symedit'](and the stale9.99config-seed dir corrected to10.0).tests/apps/kicad/footprint_editor.html— new; loadspcbnew.jswith--frame=fpedit.tests/kicad/frame-runtime.spec.ts— new; parametrized, asserts each harness lands on the library editor title (not its parent editor).tests/playwright-kicad.config.ts—frame-runtime.spec.tsadded toPCBNEW_FAMILY_SPECS: its footprint case boots the pcbnew module, which OOMs SpiderMonkey on x86 CI, so on CI the whole file runs on thechromium-ci(V8) project like every other pcbnew-booting spec. Local runs unaffected.tests/scripts/setup-kicad-wasm.sh— stops copying the two removed bundles.
How the runtime frame selection works
JS boot.ts: Module.arguments = ["--frame=fpedit"] (in the Module literal, before the glue runs)
│
Emscripten glue (built with -sINVOKE_RUN=0, callMain exported):
Module["arguments"] → arguments_ → run() → callMain(args) → main(argc, argv)
│
C++ single_top.cpp: wxCmdLineParser(App().argc, App().argv) → "--frame=fpedit"
→ FRAME_FOOTPRINT_EDITOR → Kiway.Player(FRAME_FOOTPRINT_EDITOR)
The pcbnew kiface's CreateKiWindow already has both FRAME_PCB_EDITOR and
FRAME_FOOTPRINT_EDITOR arms (eeschema likewise for FRAME_SCH /
FRAME_SCH_SYMBOL_EDITOR), and both frames of a pair map to the same FACE_T, so
one registered kiface serves both — see 02. No frame,
kiface, or dispatch code changed.
Findings that corrected the research
Module.argumentsis delivered toApp().argvin our wx WASM port. This was the one real unknown (files normally open via an embind call, not argv). A temporary diagnostic confirmedargc=2, argv[1]="--frame=symedit"in-browser — so the argv approach works and noEM_ASM/embind fallback was needed.PGM_DATA_FILE_EXTis set on all four launchers (kicad_pcb/kicad_mod/kicad_sch/kicad_sym), not just symbol —03said footprint had no extra define. The runtime extension map covers all four.- The
kiway.cpp"exactly one kiface" warning is not a Part-1 blocker. It concerns cross-face requests; both frames of a pair share one face, so registering one kiface serves both (exactly whatfootprint_editor.wasmdid before). - There is no
routes.tsin@pcbjam/sharedat the time of writing on this branch's base — extension→tool routing lives inschemas.ts+WasmTool.tsx'sfileTool. (A laterpcbjam-sharedbump addsroutes.ts; see git state below.)
Validation (all green)
Three tiers, screenshots checked at each:
- Runtime-frame harness (
frame-runtime.spec.ts, Firefox):symbol_editor.html→ title "… — Symbol Editor";footprint_editor.html→ "… — Footprint Editor" — each opening the library editor, not its parent (the parent bundle's default frame would title itself "Schematic/PCB Editor"). - Regression through the merged bundles:
pcbnew.spec(drew lines on the board),eeschema.spec(drew wires on the schematic),symbol_editor.spec(canvas + toolbars + registry) — all pass, wizard-free (the corrected10.0config seed skips the first-run wizard). - Real web app + demo project (
tools-open.spec.tsviaplaywright-web, frontend :3048 + reference backend :3060 servingtests/fixtures/demo):pcbnewopensdemo.kicad_pcb,eeschemaopensdemo.kicad_sch, andfootprint_editor/symbol_editorboot from the pcbnew / eeschema bundle via the actual React routing (resolveWasmBase→TOOL_BUNDLE,boot→--frame). 4 passed; screenshots show the footprint layer stack and the symbol library tree + Pins filter, with the real app chrome.
Build & git state
- Bundles built for validation via
main's warm docker cache at-O1:output/pcbnew.wasm(147 MB) andoutput/eeschema.wasm(82 MB).gerbview/pl_editor/calculatorwere not rebuilt — they're untouched by this change;docker/build.sh allproduces the full 5-bundle deploy set. - kicad submodule — branch
editor-unification, HEADe7a27b31(rebased onto thewasm-porttipe8db3d35): "feat(wasm): runtime --frame launcher; drop duplicate footprint/symbol editor targets". - root — branch
editor-unification, one feature commit ahead ofmain(05127af): "feat(wasm): unify editor builds — footprint/symbol editors via runtime --frame" — includes this dossier and the CI spec routing; pinskicad e7a27b31+pcbjam-shared 9a1a269. Clean tree. - Not pushed. Ship with
/git-feature-finish(or a manual push ofeditor-unificationin both repos).
What's next
- Nothing required for Part 1 — it's complete and validated.
- Part 2 (
04) — fuse the pcbnew + eeschema engines into one image — remains a deferred product call (real +download cost). Part 1 built the runtime-frame plumbing Part 2 would reuse.