New tooling in tests/tools/screenshots/ (TypeScript via tsx): - compare.ts: one pixelmatch engine (AA-excluded), connected-component "where to look" boxes, old|new+boxes|heatmap triptych, per-engine floors. - promote.ts: churn-free updater — overwrite a baseline only when decoded pixels differ beyond the floor, copying CI bytes verbatim (no re-encode churn); pulls a CI run via `gh run download` or a local --from dir. - post-discord.ts: always-on CI-on-main report (SHA + e2e status + the track-only runtime-perf table), then screenshot triptychs, batched + size-capped + flood-collapsed + 429-aware. - perf-report.ts: perf table with Δ vs the previous main run (via gh). - changelog.ts: no-build git-history baseline differ (Discord trigger B). - noise.ts / gen-manifest.ts: calibration + manifest generation. CI wiring: - wasm-build.yml: post-test step runs the gate + report on the already- produced test-results (no extra build); report-only (continue-on-error), posts only on push to main, inert without DISCORD_WEBHOOK_URL. - ci-ubicloud.yml: secrets: inherit (pass the webhook through). - screenshot-changelog.yml: ~30s no-build changelog on baseline changes. screenshot-manifest.json: canonical 354-name set + best-effort engine tags (313 chromium-swiftshader / 41 firefox-llvmpipe). Normalize scale:'device'->'css' across 18 spec files (no-op at CI DSF=1) so committed baselines are uniformly css-scaled. Design: CI's Linux render is the single source of truth; no pinned container (accept rare env drift -> re-promote); dev commits via promote. Replaces the byte-cmp compare-screenshots.sh + file-size-proxy update-baseline-screenshots.sh (kept for now until the first re-baseline). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
246 lines
8.2 KiB
Markdown
246 lines
8.2 KiB
Markdown
# 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
|
|
./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)
|
|
./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
|
|
│ ├── 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
|
|
|
|
Curated design docs and research notes for each feature live in
|
|
[`docs/features/<branch-name>/`](docs/features/) (committed).
|
|
|
|
`./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`
|
|
|
|
See [docs/build.md](docs/build.md) for detailed build documentation.
|
|
|
|
#### Creating an isolated worktree (with submodule branches)
|
|
|
|
For an experiment or feature you can work in a disposable git worktree so the
|
|
main checkout stays pristine. This repo has four submodules
|
|
(`kicad`, `wxwidgets`, `binaryen`, `web/pcbjam-shared`); a new worktree starts
|
|
with them empty, so initialize and branch each one:
|
|
|
|
```bash
|
|
# 1. Create the worktree on a new branch (off main), at a sibling path
|
|
git worktree add -b experiment/my-thing ../kicad-wasm-my-thing main
|
|
|
|
# 2. Check out the submodules INSIDE the worktree (working trees only;
|
|
# git objects are shared with the main checkout)
|
|
cd ../kicad-wasm-my-thing
|
|
git submodule update --init kicad wxwidgets binaryen web/pcbjam-shared
|
|
|
|
# 3. Create a matching branch in each submodule (they start at detached HEAD)
|
|
git checkout -b experiment/my-thing # root already on it via -b above
|
|
for sm in kicad wxwidgets binaryen web/pcbjam-shared; do
|
|
git -C "$sm" checkout -b experiment/my-thing
|
|
done
|
|
```
|
|
|
|
Then build from inside the worktree. Use an **isolated** Docker project — do NOT
|
|
set `COMPOSE_PROJECT_NAME` to another branch's project (e.g. `kicad-wasm-main`),
|
|
which can collide with other workflows; `docker/build.sh` auto-derives an isolated
|
|
project name from the worktree branch. The first build provisions deps
|
|
(wxWidgets + OCC) from scratch. To keep the machine responsive / bound wasm-opt
|
|
RAM, cap parallelism and skip the slow release optimization:
|
|
|
|
```bash
|
|
KICAD_DOCKER_CPUS=4 BINARYEN_CORES=4 BINARYEN_OPT_LEVEL=-O1 \
|
|
./docker/build.sh pcbnew -j 4
|
|
```
|
|
|
|
Tear down afterward with `git worktree remove ../kicad-wasm-my-thing` (and
|
|
`docker compose -p <project> down -v` to drop the isolated volumes).
|
|
|
|
#### 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
|
|
./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.
|
|
|
|
### Screenshots
|
|
|
|
CI's Linux render is the source of truth for baseline screenshots. On each `main`
|
|
push, CI compares its render against the committed baselines and posts the diff
|
|
(plus the runtime-perf numbers) to Discord. To update baselines after an intended
|
|
render change, promote a CI run's render — only meaningfully-changed images
|
|
restage, so it stays churn-free:
|
|
|
|
```bash
|
|
cd tests
|
|
npm run screenshots:check # local gate: current vs baselines
|
|
npm run screenshots:promote -- --run <ci-run-id> # adopt a CI run's render, then commit
|
|
```
|
|
|
|
See [tests/tools/screenshots/README.md](tests/tools/screenshots/README.md).
|
|
|
|
## 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
|
|
|
|
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
|
|
- [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.
|