pcbjam/README.md

192 lines
5.9 KiB
Markdown
Raw Normal View History

# KiCad WebAssembly Port
Run KiCad PCBnew in the browser using WebAssembly.
## Quick Start
### Full Build (KiCad + All Tests)
```bash
# 1. Initialize submodules
git submodule update --init --recursive
# 2. Build KiCad WASM (Docker, ~10 min incremental, ~1-2 hours full)
./docker/build.sh
# 3. Build wxWidgets for local testing
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
./scripts/build-wx-wasm.sh
# 4. Build wxWidgets test apps
./scripts/build-wasm-test.sh
# 5. Run all tests
cd tests && npm install
npm test # wxWidgets tests (256 tests)
npm run test:kicad # KiCad tests (2 tests)
```
### wxWidgets Only (No Docker)
```bash
# Requires: Node.js 18+ (Emscripten SDK auto-installed on first build)
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
./scripts/build-wx-wasm.sh
./scripts/build-wasm-test.sh
cd tests && npm install && npm test
```
## Project Structure
```
kicad-wasm/
├── kicad/ # KiCad source (git submodule)
├── wxwidgets/ # wxWidgets source (git submodule)
├── wasm/ # WASM compatibility layer
│ ├── bindings/ # Embind bindings for JavaScript
│ ├── cmake/ # CMake find modules
│ ├── kiplatform/ # Platform abstraction (app, UI, printing)
│ ├── libcontext/ # Coroutine/fiber implementation
│ ├── shims/ # Runtime JavaScript shims
│ └── stubs/ # Stub implementations (libgit2, curl)
├── scripts/ # Build scripts
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
│ ├── build-wx-wasm.sh # Build wxWidgets for WASM
│ ├── build-wasm-test.sh # Build wxWidgets test apps
│ ├── deps/ # Dependency build scripts
│ ├── kicad/ # KiCad build scripts
│ ├── common/ # Shared utilities
│ └── config/ # Build config wrappers
├── docker/ # Docker build environment
├── tests/ # Playwright E2E tests
│ ├── e2e/ # Test specs
│ └── apps/ # WASM test applications
├── tools/ # External tools (binaryen)
└── output/ # Build output (pcbnew.js, pcbnew.wasm)
```
## Feature Branches
2026-06-05 12:15:54 +02:00
Curated design docs and research notes for each feature live in
[`docs/features/<branch-name>/`](docs/features/) (committed).
2026-06-05 12:15:54 +02:00
`./scripts/create-feature-patches.sh [branch-name]` generates per-branch patches
(`root.patch`, `kicad.patch`, `wxwidgets.patch`) into a local `features/<branch-name>/`
scratch dir. That dir is gitignored — the patches are local history, not committed.
## Two Build Workflows
### 1. KiCad Build (Docker)
Full KiCad PCBnew build using Docker:
```bash
# Build KiCad WASM
./docker/build.sh
# Copy output to test directory
./tests/scripts/setup-kicad-wasm.sh
# Run KiCad tests
cd tests && npm install && npm run test:kicad
```
Output: `output/pcbnew.js`, `output/pcbnew.wasm`
2026-06-05 12:15:54 +02:00
See [docs/build.md](docs/build.md) for detailed build documentation.
#### Fresh worktree provisioning
Some test artifacts are gitignored and are NOT produced by the build pipeline,
so they don't carry into a newly-created git worktree — without them the
`gal-webgl` tests 404 ("Loading WASM...") and the `collab` specs fail with
`Could not resolve "@pcbjam/shared"`. After building (`docker/build.sh` +
`scripts/build-wx-wasm.sh`) and `cd tests && npm i`, run once per worktree:
```bash
./scripts/setup-worktree.sh # idempotent: sysroot headers, gal-webgl harness, web/ pnpm install, collab bundle
```
### 2. wxWidgets Test Apps (Local)
Build standalone wxWidgets test apps for feature testing:
```bash
# Build wxWidgets for WASM
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
./scripts/build-wx-wasm.sh
# Build test apps
./scripts/build-wasm-test.sh
# Run wxWidgets tests
cd tests && npm install && npm test
```
Output: `tests/apps/standalone/`
## Prerequisites
### For KiCad Build (Docker)
- Docker Desktop with 16GB+ RAM allocated
- 10+ GB disk space for build cache
### For wxWidgets Build (Local)
- Node.js 18+ (for tests)
- Emscripten SDK (auto-installed on first build)
```bash
# Initialize submodules
git submodule update --init --recursive
# Install Emscripten SDK (auto-runs on first build, or run manually)
./scripts/setup-emsdk.sh
```
## Testing
```bash
cd tests
npm install
# Run all tests
npm test
# Run specific tests
npm run test:kicad # KiCad tests only
npx playwright test menu # Menu tests only
```
See [tests/README.md](tests/README.md) for test documentation.
## Current Status
- **wxWidgets WASM**: Core widgets working (menus, dialogs, grids, trees, OpenGL)
- **KiCad PCBnew**: Builds and loads in browser, canvas rendering working
- **In Progress**: Testing wxWidgets features used by KiCad
## Documentation
2026-06-05 12:15:54 +02:00
See **[docs/README.md](docs/README.md)** for the full documentation map. Highlights:
- [Build System](docs/build.md) - Docker build details
- [Docker README](docker/README.md) - Container setup
2026-06-05 12:15:54 +02:00
- [Debugging Guide](docs/debugging/DEBUG.md) - Asyncify/WASM debugging
- [Tests README](tests/README.md) - Test infrastructure
## Landing page / website
The marketing site and landing page live in [`site/`](site/) (Astro), deployed as
static assets to Cloudflare R2.
**On every release, bump the build SHA.** `site/src/components/Footer.astro` has a
hardcoded `BUILD_SHA` constant that is shown in the footer and links to the
corresponding commit. Because the main-repo commit pins the KiCad and wxWidgets
submodule revisions implicitly, this is our GPLv3 **corresponding-source** pointer
(surfaced on `/licenses`). The site is static, so nothing sets it automatically —
update `BUILD_SHA` by hand to the deployed `pcbjam` commit each time you release.
## License
KiCad is GPL-3.0. This project follows the same license.
The site combines KiCad (GPLv3) with the wxWidgets fork; the wxWidgets WebAssembly
port files are LGPL v2 (without the wxWindows binary exception). See the
`/licenses` page (`site/src/content/legal/licenses.md`) for the full breakdown and
the corresponding-source offer.