Kicad fork cleanup docs.
This commit is contained in:
parent
dcb8d69e91
commit
bfe4ae8be9
13 changed files with 1159 additions and 0 deletions
88
docs/features/fork-cleanup/01-revert-dead-code.md
Normal file
88
docs/features/fork-cleanup/01-revert-dead-code.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# 01 — Revert dead code
|
||||
|
||||
> ~480 lines of fork diff across ~22 upstream files compile **only in configurations the
|
||||
> shipping build never uses**. Reverting them is pure subtraction: zero behavior change to
|
||||
> the WASM product, and it removes the single largest tranche of divergence.
|
||||
|
||||
## A. `#ifdef KICAD_IPC_API` gating — 18 files, ~115 lines
|
||||
|
||||
**The gates are dead.** `scripts/kicad/build-kicad-target.sh:354` passes
|
||||
`-DKICAD_IPC_API=ON` and links a wasm-built `libprotobuf.a`
|
||||
(`-DProtobuf_LIBRARY=${SYSROOT}/lib/libprotobuf.a`). So every `#ifdef KICAD_IPC_API`
|
||||
guard is always taken — the protobuf path always compiles. The OFF configuration these
|
||||
gates nominally enable **cannot even link**: the class headers (`pad.h`, `zone.h`,
|
||||
`footprint.h`, `pcb_track.h:292,401,751`, …) still declare
|
||||
`void Serialize(google::protobuf::Any&) const override;` *unconditionally*, so compiling
|
||||
out the definitions would leave undefined vtable symbols. Upstream confirms this is
|
||||
deliberate — protobuf is "required even when the IPC API is not enabled" (dev-docs build
|
||||
page), so the gating is not upstreamable either.
|
||||
|
||||
Files to revert to pristine upstream (all from commit `e6a59ab94a`):
|
||||
|
||||
```
|
||||
common/eda_shape.cpp common/eda_text.cpp common/netclass.cpp
|
||||
include/api/api_utils.h pcbnew/api/api_pcb_utils.h pcbnew/board_connected_item.cpp
|
||||
pcbnew/board_stackup_manager/board_stackup.cpp pcbnew/footprint.cpp
|
||||
pcbnew/pad.cpp pcbnew/padstack.cpp pcbnew/pcb_dimension.cpp
|
||||
pcbnew/pcb_field.cpp pcbnew/pcb_group.cpp pcbnew/pcb_shape.cpp
|
||||
pcbnew/pcb_text.cpp pcbnew/pcb_textbox.cpp pcbnew/pcb_track.cpp
|
||||
pcbnew/zone.cpp
|
||||
```
|
||||
|
||||
Note an internal inconsistency that confirms the gates were never exercised: `netclass.cpp`
|
||||
adds `#else` stub bodies for the vtable, but `eda_shape.cpp`/`eda_text.cpp` do not — an
|
||||
actual `KICAD_IPC_API=OFF` build would fail to link regardless. **Just revert all 18.**
|
||||
|
||||
## B. `include/gal/opengl/kiglew.h` — +189/−1, dead
|
||||
|
||||
The +189-line `#if defined(__EMSCRIPTEN__)` block (GLEW stubs, `glewInit` no-op,
|
||||
`glVertex2d`→`glVertex2f` wrappers, display-list / lighting no-ops) was added for the old
|
||||
LEGACY_GL_EMULATION 3D-viewer path. But:
|
||||
|
||||
- The OpenGL GAL is compiled only `if(NOT EMSCRIPTEN)` (since the WebGL GAL split).
|
||||
- The live WebGL GAL uses its **own** new header, `include/gal/webgl/kiglew.h`.
|
||||
- The 3D viewer is not built (`KICAD_BUILD_3D_VIEWER_WASM=OFF`).
|
||||
|
||||
No wasm-compiled translation unit includes this header. The block only perturbs native
|
||||
builds. **Revert.** If the 3D viewer comes back via WebGL2 (see [10](10-3d-viewer.md)) it
|
||||
brings its own headers; if it ever needs a `GL/` shim, use an include-path-shadowed header
|
||||
in a new dir — the pattern is already proven by `include/gal/webgl/kiglew.h` and the
|
||||
existing `wasm/stubs/GL/`.
|
||||
|
||||
## C. `common/gal/opengl/opengl_gal.cpp` — +32/−31, dead
|
||||
|
||||
A `Connect(...)` → `Bind(...)` event-hookup refactor plus some `GAL::` qualifications, to
|
||||
dodge a multiple-inheritance ambiguity that appeared during an early wasm compile. The file
|
||||
is excluded from the Emscripten build (same OpenGL-GAL exclusion as B), so this now only
|
||||
changes *native* behavior. **Revert** (or, if you like the modernization, upstream it — but
|
||||
reverting is cleaner).
|
||||
|
||||
## D. Diagnostic call sites — ~30 lines, debugging a solved problem
|
||||
|
||||
The `KI_DIAG_GAL` / `KI_DIAG_COROUTINE` / `KI_DIAG_CTOR` macros (from
|
||||
`include/kicad_wasm_diag.h`, a fork-only header gated behind `--diag` build flags) were
|
||||
added to trace the Chrome Asyncify-rewind stall family — **which is solved** (see the
|
||||
`chrome-asyncify-rewind-crash` memory; fixed systemically by `wasm-opt -O2` after
|
||||
`--asyncify`). The call sites are marked "TEMPORARY … Remove once the crash is fixed":
|
||||
|
||||
- `common/tool/tool_manager.cpp` +11 (`dispatchInternal` coroutine call)
|
||||
- `common/draw_panel_gal.cpp` ~7 lines
|
||||
- `pcbnew/pcb_edit_frame.cpp` 15 `KI_DIAG_CTOR` lines tracing ctor phases
|
||||
- `common/confirm.cpp` +4 (unconditional `wxFprintf(stderr, ...)` before `ShowModal` —
|
||||
also affects native; move to the wx wasm modal shim if logging is still wanted)
|
||||
|
||||
**Delete the call sites now.** Keep the `include/kicad_wasm_diag.h` header itself (a new
|
||||
file, costs nothing) for ad-hoc reinsertion — its only *in-upstream-file* users disappear
|
||||
once the call sites go.
|
||||
|
||||
## Net
|
||||
|
||||
| Item | Files | ~Lines | Risk |
|
||||
|---|---|---|---|
|
||||
| IPC-API gates | 18 | 115 | none (dead) |
|
||||
| `kiglew.h` | 1 | 190 | none (dead in wasm; reverts a native-only change) |
|
||||
| `opengl_gal.cpp` | 1 | 63 | none (dead in wasm) |
|
||||
| Diagnostics | ~3 | 30 | none |
|
||||
| **Total** | **~23** | **~400** | reverts also undo 4 accidental native-build changes |
|
||||
|
||||
This is the recommended first action — see the [sequencing](README.md#suggested-sequencing).
|
||||
112
docs/features/fork-cleanup/02-cmake-dechurn.md
Normal file
112
docs/features/fork-cleanup/02-cmake-dechurn.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# 02 — CMake de-churn
|
||||
|
||||
> The build-system diff is **~1,600 changed lines across 17 `CMakeLists.txt` files**, and
|
||||
> **35–40% of it (~600 lines) is reindentation and duplication** — not logic. The logic
|
||||
> that *is* there (single-binary kiface linking, stub injection, the WebGL GAL) is mostly
|
||||
> legitimate; it's expressed in the most invasive way possible. This refactor keeps the
|
||||
> behavior and cuts the touched-line count to roughly **120–180** inside upstream files.
|
||||
|
||||
## The anti-patterns and their fixes
|
||||
|
||||
### 1. Wrap-and-reindent → early-return guard
|
||||
|
||||
`pcbnew/CMakeLists.txt`: the ~110-line Python-module install section was wrapped in
|
||||
`if(KICAD_SCRIPTING) … endif()` **and reindented**, turning ~110 lines into ~215 diff
|
||||
lines. The section runs to EOF, so a 3-line guard does the same job with ~5 diff lines:
|
||||
|
||||
```cmake
|
||||
if( NOT KICAD_SCRIPTING )
|
||||
return()
|
||||
endif()
|
||||
# ... upstream python-install body, unindented, byte-identical ...
|
||||
```
|
||||
|
||||
`scripting/CMakeLists.txt` already does the minimal version of this (top-level `if(...)` /
|
||||
bottom `endif()`, **no reindent**) — copy that discipline. Same treatment for the root
|
||||
`CMakeLists.txt` Python/SWIG discovery section (~100 lines of pure reindent today).
|
||||
|
||||
### 2. if/else source duplication → `list(REMOVE_ITEM)`
|
||||
|
||||
The additive pattern is already proven in-tree for the ngspice BSIM data files
|
||||
(`eeschema/CMakeLists.txt`): keep the upstream list byte-identical, then remove/replace
|
||||
under `if(EMSCRIPTEN)`:
|
||||
|
||||
```cmake
|
||||
# upstream SRCS list stays exactly as-is, then:
|
||||
if( EMSCRIPTEN )
|
||||
list( REMOVE_ITEM FOO_SRCS path/to/native_only.cpp )
|
||||
list( APPEND FOO_SRCS ${KICAD_WASM_LAYER}/stubs/foo_stub.cpp )
|
||||
endif()
|
||||
```
|
||||
|
||||
Apply to: the OpenGL-GAL sources in `common/gal/CMakeLists.txt` (currently moved into an
|
||||
`if(NOT EMSCRIPTEN)` block + reindented), the eeschema importer block, the
|
||||
`common/CMakeLists.txt` exclusions (`python_scripting.cpp`, `api_utils.cpp`, altium,
|
||||
database, webview), and the `PCBNEW_IO_LIBRARIES` altium dual-list in `pcbnew/CMakeLists.txt`.
|
||||
|
||||
### 3. pcb_calculator: whole file forked → block + `return()`
|
||||
|
||||
`pcb_calculator/CMakeLists.txt` (+130/−89) forks the *entire* file `if(EMSCRIPTEN) … else()`
|
||||
with the upstream body reindented in the `else`. Instead, insert the wasm single-binary
|
||||
block (duplicating only `make_lexer`) followed by `return()` *before* the upstream
|
||||
`add_executable`, leaving the upstream body untouched. ~160 diff lines → ~55 additive.
|
||||
|
||||
### 4. Shader calls: 85-line duplicate → redefine-the-function hook
|
||||
|
||||
`common/gal/CMakeLists.txt` duplicates all 10 upstream `add_shader(...)` calls in an
|
||||
`else()` branch for the ES3 variant. Instead, after upstream's `add_shader` definition,
|
||||
`include()` a wasm `.cmake` that *redefines* `add_shader` to the ES3 path (later definition
|
||||
wins) — upstream's 10 calls are then reused verbatim.
|
||||
|
||||
### 5. `BUILD_KIWAY_DLL` source-property forks (5 apps)
|
||||
|
||||
eeschema/pcbnew/gerbview/pl_editor/pcb_calculator each fork the `set_source_files_properties`
|
||||
defs `if/else`. Replace with a single additive `if(EMSCRIPTEN)` block *after* the upstream
|
||||
lines that re-sets the properties (last set wins). ~120 diff lines → ~35 additive.
|
||||
|
||||
### 6. navlib ×3: probably deletable entirely
|
||||
|
||||
`pcbnew/navlib`, `gerbview/navlib`, `pagelayout_editor/navlib` each fork their CMakeLists to
|
||||
build a stub from `wasm/stubs/nl_*_plugin_stub.cpp` with the upstream body reindented in the
|
||||
`else`. **But `eeschema/navlib` is unchanged** and builds its *real* sources under wasm
|
||||
against the bundled `thirdparty/3dxware_sdk` stub. Strong evidence the other three stub
|
||||
forks are unnecessary — try reverting all three CMakeLists and deleting the 3 stub `.cpp`
|
||||
files. (This also fixes a native bug — see [07](07-native-build-bugs-and-tooling.md) on the
|
||||
duplicate `add_subdirectory(navlib)`.) Fallback if a link fails: a 4-line early-return stub
|
||||
`include()` at the top of each, with zero reindent.
|
||||
|
||||
### 7. `kiapi` SHARED-vs-STATIC: variable, not duplicate list
|
||||
|
||||
`api/CMakeLists.txt` (+14/−5) duplicates the source list across an
|
||||
`add_library(kiapi SHARED)` / `STATIC` if/else. Collapse to `set(_KIAPI_TYPE ...)` + one
|
||||
`add_library(kiapi ${_KIAPI_TYPE} ...)`.
|
||||
|
||||
## Relocate the surviving `if(EMSCRIPTEN)` logic
|
||||
|
||||
The legitimate blocks (static-kiface linking, stub `target_sources`, the `symbol_editor`
|
||||
target, WebGL GAL sources) don't shrink in *content*, but they can move out of upstream
|
||||
files into a new merge-conflict-free directory:
|
||||
|
||||
- Create `kicad/cmake/wasm/*.cmake` and reduce each upstream `CMakeLists.txt` touch to a
|
||||
1–3 line `if(EMSCRIPTEN) include(wasm/foo.cmake) endif()` hook.
|
||||
- Replace the hardcoded `${CMAKE_SOURCE_DIR}/../wasm` paths (which reach outside the
|
||||
submodule and currently prevent it from configuring standalone) with a `KICAD_WASM_LAYER`
|
||||
cache variable, defaulted to `../wasm` and passed by `build-kicad-target.sh`.
|
||||
|
||||
## Mechanisms that were evaluated and rejected
|
||||
|
||||
- **`CMAKE_PROJECT_INCLUDE` / `CMAKE_PROJECT_KICAD_INCLUDE`**: runs at `project()` time —
|
||||
*before* upstream's `set(CMAKE_MODULE_PATH ...)` overwrite — so it can't even replace the
|
||||
1-line module-path fix, and can't reach subdirectory logic. Worth ~2% of the diff; skip.
|
||||
- **Super-project `add_subdirectory(kicad)` wrapper**: infeasible. KiCad uses
|
||||
`${CMAKE_SOURCE_DIR}` pervasively (incl. the `../wasm` reach-outs and install logic); it
|
||||
would re-root to the super-project and break.
|
||||
|
||||
## Net
|
||||
|
||||
Moves 1–7 alone cut the build-system diff from ~1,600 to roughly **500–600** lines; adding
|
||||
the `cmake/wasm/` relocation drops the lines touched *inside upstream files* to roughly
|
||||
**120–180**. Irreducible in-place edits that remain: the `CMAKE_MODULE_PATH` preserve
|
||||
(1 line), the wx-port regex `(msw|qt|gtk|osx)` → `(…|wasm)` (1 line), the `KICAD_SCRIPTING`
|
||||
option, root `add_subdirectory` gates, `kiapi` genex gates in `common`, and the
|
||||
`thirdparty/lemon` cross-compile block.
|
||||
81
docs/features/fork-cleanup/03-config-not-code.md
Normal file
81
docs/features/fork-cleanup/03-config-not-code.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# 03 — Config, not code
|
||||
|
||||
> Several `#ifdef __EMSCRIPTEN__` patches re-implement, in C++, behavior that KiCad already
|
||||
> exposes as a runtime setting or a CMake cache variable. Replacing the patch with a shipped
|
||||
> config file (or a `-D`) gives identical behavior, removes the source edit, and keeps the
|
||||
> knob user-changeable.
|
||||
|
||||
## 1. Zoom-to-cursor → `input.center_on_zoom`
|
||||
|
||||
**Patch today:** `common/view/wx_view_controls.cpp` (+9) and part of
|
||||
`common/draw_panel_gal.cpp` force `m_warpCursor = false` under `__EMSCRIPTEN__` (browsers
|
||||
can't warp the OS pointer, so center-on-zoom is wrong; zoom-to-cursor is correct).
|
||||
|
||||
**But this is already a user preference.** `common/settings/common_settings.cpp:228` defines
|
||||
`PARAM<bool>("input.center_on_zoom", …, true)` (the "Center and warp cursor on zoom"
|
||||
checkbox in Mouse & Touchpad). The two lines the fork patched are *exactly* the consumption
|
||||
sites: `wx_view_controls.cpp:172` and `draw_panel_gal.cpp:712`. The wheel handler already
|
||||
implements point-under-cursor-stays-fixed when the pref is false.
|
||||
|
||||
**Do instead:** seed the browser FS with a first-run `kicad_common.json` containing
|
||||
`"input": { "center_on_zoom": false }`. Covers both sites, stays toggleable. Belt-and-
|
||||
suspenders: the wasm kiplatform `WarpPointer()` should return `false` — callers
|
||||
(`wx_view_controls.cpp:342,972`) already handle that gracefully, so even if a user re-enables
|
||||
the pref it degrades, not breaks. Removes 2 source patches.
|
||||
|
||||
## 2. Backspace-deletes → default `user.hotkeys`
|
||||
|
||||
**Patch today:** `common/tool/actions.cpp` (+7) adds `DefaultHotkeyAlt(WXK_BACK)` to the
|
||||
delete action under `__EMSCRIPTEN__` so Mac-browser users' Backspace deletes.
|
||||
|
||||
**Do instead:** ship a default `user.hotkeys` file in the FS image mapping both
|
||||
Delete and Backspace to the delete action — pure runtime config.
|
||||
|
||||
> ⚠️ The companion change in `common/tool/action_manager.cpp` (+5) is **not** config — it's a
|
||||
> genuine upstream bug fix (`m_defaultHotKeyAlt` is never applied, so `DefaultHotkeyAlt()` is
|
||||
> dead upstream in default configs). That one belongs in [06](06-upstreamable-patches.md),
|
||||
> and the default-`user.hotkeys` route only needs it for the *default*-alt path; an explicit
|
||||
> user-hotkeys mapping works without it.
|
||||
|
||||
## 3. Profile timer → `HAVE_CLOCK_GETTIME`
|
||||
|
||||
**Patch today:** `libs/core/profile.cpp` (+9) adds an `#elif defined(__EMSCRIPTEN__)`
|
||||
branch to `GetRunningMicroSecs()` using `emscripten_get_now()`. The existing upstream
|
||||
branches gate on the configure-time macros `HAVE_CLOCK_GETTIME` / `HAVE_GETTIMEOFDAY_FUNC`.
|
||||
|
||||
**Do instead:** Emscripten supports `clock_gettime`, so set `HAVE_CLOCK_GETTIME` in the wasm
|
||||
CMake cache / toolchain and the existing branch compiles. Zero source change.
|
||||
|
||||
## 4. Static KIFACE startup → call `OnKifaceStart` from the shell
|
||||
|
||||
**Patch today:** `common/kiway.cpp` (+33) special-cases `KIWAY::KiFACE()` under
|
||||
`__EMSCRIPTEN__`: it treats `m_kiface_version == 0` as "OnKifaceStart not yet called" and
|
||||
either calls the statically-linked `KIFACE_GETTER` or backfills the version for a
|
||||
pre-`set_kiface()`'d face, then calls `OnKifaceStart`.
|
||||
|
||||
**Do instead:** the fork controls startup, so the wasm shell can call
|
||||
`kiface->OnKifaceStart(&Pgm(), ctl, &kiway)` itself at its `set_kiface()` call site. Then
|
||||
upstream's existing `if(m_kiface[aFaceId]) return m_kiface[aFaceId];` early-return path works
|
||||
unmodified, and the single static `KIFACE_GETTER` fallback also lives in the shell. Removes
|
||||
the 33-line in-source block.
|
||||
|
||||
## 5. Keep the scripting member unconditional
|
||||
|
||||
`include/pgm_base.h` (+2) wraps `std::unique_ptr<SCRIPTING> m_python_scripting` in
|
||||
`#ifdef KICAD_SCRIPTING`. A `unique_ptr` to a forward-declared type compiles without the
|
||||
full header and is simply never populated when scripting is off — so the member can stay
|
||||
unconditional and the header reverts. (The `.cpp` creation site in `common/pgm_base.cpp`
|
||||
still needs its guard; that's part of the coherent scripting-optional patch in
|
||||
[05](05-wx-layer-fixes.md)/[06](06-upstreamable-patches.md), not this doc.)
|
||||
|
||||
## Net
|
||||
|
||||
| Patch | Replacement | Removes |
|
||||
|---|---|---|
|
||||
| `wx_view_controls.cpp`, `draw_panel_gal.cpp` warpCursor | `kicad_common.json` default | 2 sites |
|
||||
| `actions.cpp` Backspace | default `user.hotkeys` | 1 site (+ see 06) |
|
||||
| `profile.cpp` timer | `HAVE_CLOCK_GETTIME` cache var | 1 file |
|
||||
| `kiway.cpp` static KIFACE | `OnKifaceStart` from shell | 33 lines |
|
||||
| `pgm_base.h` member guard | unconditional `unique_ptr` | 1 header |
|
||||
|
||||
The config files live in the `wasm/` / `web/` layer — no upstream footprint.
|
||||
77
docs/features/fork-cleanup/04-stub-tu-relocation.md
Normal file
77
docs/features/fork-cleanup/04-stub-tu-relocation.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# 04 — Relocate in-file stubs to new translation units
|
||||
|
||||
> Some patches put a wasm `#else` implementation *inside* an upstream `.cpp`, doubling the
|
||||
> file's divergence (the stub **plus** churn in the native half). The fix is the same in
|
||||
> each case: select a separate translation unit by CMake (`list(REMOVE_ITEM)` + append, see
|
||||
> [02](02-cmake-dechurn.md)), and the upstream file reverts to pristine. `wasm/stubs/` is
|
||||
> already a mature home for exactly this.
|
||||
|
||||
## 1. fontconfig — +154/−39, the biggest live source patch
|
||||
|
||||
`common/font/fontconfig.cpp` is split `#if KICAD_USE_FONTCONFIG` (native) `#else` (wasm).
|
||||
The wasm half is a self-contained stub: `Version()` returns `"WASM (no fontconfig)"`,
|
||||
`FindFont`/`ListFonts` match against `aEmbeddedFiles` filenames + the built-in stroke font.
|
||||
Fontconfig genuinely isn't built for wasm, so the stub is live — but it doesn't belong
|
||||
inline. The patch also **deletes ~39 lines of comments from the native half** (gratuitous
|
||||
churn).
|
||||
|
||||
**Do:** move the `#else` body to a new TU (`common/font/fontconfig_wasm.cpp`, or
|
||||
`wasm/stubs/`), select it by CMake, and restore the deleted comments. `include/font/fontconfig.h`
|
||||
(+13/−22) only guards the `<fontconfig/fontconfig.h>` include for the `.cpp`'s benefit —
|
||||
moving that include into the `.cpp` is an upstreamable cleanup; private helper decls don't
|
||||
need guarding (unused private non-virtuals need no definition). Header reverts to near-zero.
|
||||
|
||||
> This is also the seam where **system-font support** could later be added: the non-fontconfig
|
||||
> `FindFont`/`ListFonts` path is where the browser Local Font Access API would map in (wx
|
||||
> fontenum already works per `tests/WHATWORKS.md`). Moderate effort, optional.
|
||||
|
||||
## 2. libcontext — +333/−1 `.cpp`, +8/−1 header
|
||||
|
||||
`thirdparty/libcontext/libcontext.cpp` gains a complete Emscripten-fiber backend
|
||||
(`make_fcontext`/`jump_fcontext`/`release_fcontext` over `emscripten_fiber_*`) for a new
|
||||
`LIBCONTEXT_PLATFORM_wasm32`. It's one self-contained `#if defined(LIBCONTEXT_PLATFORM_wasm32)`
|
||||
region; the only edit to *pre-existing* code is wrapping the upstream no-op `release_fcontext`
|
||||
in `#if !defined(...)` to avoid a duplicate definition.
|
||||
|
||||
**Do:** move the wasm region to `thirdparty/libcontext/libcontext_emscripten.cpp` and have
|
||||
`thirdparty/libcontext/CMakeLists.txt` *replace* (not append) the source under `if(EMSCRIPTEN)`.
|
||||
Replacing makes `libcontext.cpp` byte-identical to upstream (everything else in it is
|
||||
platform-guarded asm that compiles to nothing on wasm) and removes the `#if !defined` guard
|
||||
need. The header's +8 platform branch becomes
|
||||
`target_compile_definitions(libcontext PUBLIC LIBCONTEXT_PLATFORM_wasm32 LIBCONTEXT_COMPILER_gcc LIBCONTEXT_CALL_CONVENTION=)` — verified to propagate to the only includer
|
||||
(`include/tool/coroutine.h`) via `common`'s PUBLIC link. (Keeping the 9-line additive header
|
||||
hunk is also fine if you prefer; it's tiny.)
|
||||
|
||||
## 3. SpaceMouse / navlib `#ifdef`s → throwing-ctor stubs
|
||||
|
||||
The 3D-viewer SpaceMouse integration is gated with `#ifdef __EMSCRIPTEN__` in four files
|
||||
(`3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp`/`.h`,
|
||||
`3d-viewer/dialogs/panel_preview_3d_model.cpp`/`.h`). Upstream already wraps the plugin
|
||||
construction in `try/catch` and null-checks every use, so a stub whose constructor *throws*
|
||||
(mirroring the existing `wasm/stubs/nl_pcbnew_plugin_stub.cpp`) reverts all four files.
|
||||
Emscripten doesn't define `__linux__`, so upstream's `#else` branch already selects the
|
||||
`NL_*` class — only the stub body is needed.
|
||||
|
||||
> These four files only matter once the 3D viewer is built (see [10](10-3d-viewer.md)). Do
|
||||
> this relocation as part of turning 3D on, not before. The CMake-level navlib stub forks
|
||||
> (`nl_pcbnew/gerbview/pl_editor_plugin_stub.cpp`) are addressed in [02](02-cmake-dechurn.md)
|
||||
> §6 — they may be deletable entirely.
|
||||
|
||||
## What stays inline (deliberately)
|
||||
|
||||
- **`thirdparty/thread-pool/bs_thread_pool.hpp` (+16)** — the run-inline-under-Asyncify
|
||||
patch in `detach_task()`. The alternative (wrapping KiCad's `thread_pool` typedef) touches
|
||||
3 KiCad-owned files, and subclass-shadowing doesn't work because `detach_task` is
|
||||
non-virtual and `submit_task` binds to it internally. The 16-line vendored patch is the
|
||||
smaller, self-documenting option. Re-apply on each re-vendor.
|
||||
- **`common/widgets/wx_progress_reporters.cpp` (+9)** — `updateUI()` returns `true` under
|
||||
`__EMSCRIPTEN__` to skip `wxProgressDialog`'s nested event loop (which unwinds Asyncify
|
||||
mid-load). The clean fix is making the wx wasm `wxProgressDialog::Update` non-pumping (see
|
||||
the [async dossier](../async/README.md)); until then the 9-line guard is defensible.
|
||||
|
||||
## Note on `exporter_vrml.cpp`
|
||||
|
||||
The +64-line in-file VRML-export stub is **not** relocated here — under the new policy VRML
|
||||
export comes *back* (it only needs the 3D model cache, no GL). Deleting the `#else` stub and
|
||||
linking the real exporter is covered in [10](10-3d-viewer.md). That's a divergence
|
||||
*reduction*, not a relocation.
|
||||
81
docs/features/fork-cleanup/05-wx-layer-fixes.md
Normal file
81
docs/features/fork-cleanup/05-wx-layer-fixes.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# 05 — Fix in the wxWidgets wasm port, not in KiCad
|
||||
|
||||
> Several KiCad-side `#ifdef __EMSCRIPTEN__` patches work around quirks of the wxUniversal /
|
||||
> wasm port. The project rule is to fix wasm-only bugs **in the wasm layer**. Moving these
|
||||
> into the `wxwidgets` fork's wasm port removes the KiCad divergence — and in the tooltip
|
||||
> case, *re-enables a whole class of UI*. The wx wasm port is the sanctioned place for this
|
||||
> work, so these don't count against the "minimize upstream edits" goal the way KiCad edits do.
|
||||
|
||||
## 1. HiDPI scale factor — currently changes native behavior
|
||||
|
||||
`common/gal/hidpi_gl_canvas.cpp` (+2/−2) changes `GetScaleFactor()` from
|
||||
`GetContentScaleFactor()` to `GetDPIScaleFactor()` **unconditionally** — and those two
|
||||
differ on MSW, so this silently alters native Windows builds (see
|
||||
[07](07-native-build-bugs-and-tooling.md)). Likewise `pcbnew/widgets/appearance_controls.cpp`
|
||||
(+4/−1) swaps `GetScaleFactor()`→`GetContentScaleFactor()` in `GetBestSize()`.
|
||||
|
||||
**Do:** implement `GetContentScaleFactor()` correctly (devicePixelRatio) in the wx wasm port
|
||||
and revert both KiCad edits.
|
||||
|
||||
## 2. `GetCurrentSelection()` on wxUniversal choices
|
||||
|
||||
`common/eda_draw_frame.cpp` (+8), `pcbnew/dialogs/panel_setup_layers.cpp` (+2/−2),
|
||||
`eeschema/dialogs/dialog_sim_command.cpp` (+1/−1) work around wxUniversal's
|
||||
wxChoice/wxComboBox where `GetCurrentSelection()` / `IsEmpty()` misbehave, by substituting
|
||||
`GetSelection()` / `GetCount()`.
|
||||
|
||||
**Do:** make `GetCurrentSelection()` delegate to `GetSelection()` in the wxUniv/wasm layer —
|
||||
removes all of these at once. (Some of these are also upstream-friendly as plain wx fixes;
|
||||
see [06](06-upstreamable-patches.md).)
|
||||
|
||||
## 3. Header self-sufficiency
|
||||
|
||||
`include/gal/hidpi_gl_canvas.h` (+1) adds `#include <wx/window.h>` before `wx/glcanvas.h`
|
||||
because the wx wasm port's `glcanvas.h` isn't self-sufficient.
|
||||
|
||||
**Do:** fix the include self-sufficiency in the wx wasm port's `glcanvas.h`; revert the
|
||||
KiCad include. (Trivially upstreamable as header hygiene either way.)
|
||||
|
||||
## 4. Tooltips — implement `wxToolTip` in the wasm port (this re-enables a feature)
|
||||
|
||||
`wxUSE_TOOLTIPS` is **0** in the generated wasm setup.h because upstream wxWidgets configure
|
||||
hard-disables tooltips for wxUniversal ("wxTooltip not supported yet in wxUniversal",
|
||||
`wxwidgets/configure.in:7316`) — there is no `src/univ/tooltip.cpp`. KiCad carries ~12 files
|
||||
of `wxUSE_TOOLTIPS` guards / `#ifndef __EMSCRIPTEN__ wxToolTip::Enable` to cope.
|
||||
|
||||
**Do (porting task, 2–4 days, in the wx fork):** add `src/wasm/tooltip.cpp` +
|
||||
`include/wx/wasm/tooltip.h` — a generic tooltip (hover timer + a `wxTipWindow`/`wxPopupWindow`
|
||||
near the pointer; popups are already proven working per `tests/WHATWORKS.md`), patch the
|
||||
configure gate for the wasm port, regen configure, wire into the makefiles.
|
||||
|
||||
**Then, KiCad-side, this becomes pure deletion:**
|
||||
|
||||
- Remove `#ifndef __EMSCRIPTEN__` around `wxToolTip::Enable(...)` in
|
||||
`common/pgm_base.cpp`, `common/dialogs/dialog_design_block_properties.cpp`,
|
||||
`eeschema/dialogs/dialog_sheet_properties.cpp`, `eeschema/dialogs/dialog_symbol_properties.cpp`.
|
||||
- The `#if wxUSE_TOOLTIPS` guards (`include/widgets/wx_dataviewctrl.h`,
|
||||
`common/dialogs/dialog_paste_special.cpp`, `common/widgets/wx_infobar.cpp`,
|
||||
`pcbnew/dialogs/dialog_board_reannotate.cpp`, `include/pcb_base_frame.h`) auto-activate —
|
||||
and can be dropped as fork diff, ~8 files reclaimed.
|
||||
|
||||
Big UX win: every `SetToolTip(...)` in KiCad lights up. (The interim upstream-friendly move
|
||||
is to re-spell the bare `#ifndef __EMSCRIPTEN__` guards as `#if wxUSE_TOOLTIPS` — see
|
||||
[06](06-upstreamable-patches.md) — so they're correct regardless of when the wx work lands.)
|
||||
|
||||
## 5. Other wx-port-shaped items
|
||||
|
||||
- `common/pgm_base.cpp` `wxToolTip::Enable/SetAutoPop` under `#ifndef __EMSCRIPTEN__` — folds
|
||||
into §4, or provide a no-op `wxToolTip` in the port.
|
||||
- `common/tool/actions.cpp` Backspace hotkey — handled by config in [03](03-config-not-code.md).
|
||||
- `wxUSE_FSWATCHER` (off): leave off — MEMFS has no change notification and nothing edits
|
||||
files externally in a single-user browser. KiCad's `#if wxUSE_FSWATCHER` guards are
|
||||
upstream-friendly as-is (see [06](06-upstreamable-patches.md)).
|
||||
|
||||
## Net
|
||||
|
||||
| KiCad edit | wx-port fix | Removes |
|
||||
|---|---|---|
|
||||
| `hidpi_gl_canvas.cpp`, `appearance_controls.cpp` | `GetContentScaleFactor()` | 2 files + a native bug |
|
||||
| `eda_draw_frame.cpp`, `panel_setup_layers.cpp`, `dialog_sim_command.cpp` | `GetCurrentSelection()` delegate | 3 files |
|
||||
| `hidpi_gl_canvas.h` | self-sufficient `glcanvas.h` | 1 header |
|
||||
| ~12 tooltip-guard files | `src/wasm/tooltip.cpp` | ~12 files **+ enables tooltips** |
|
||||
90
docs/features/fork-cleanup/06-upstreamable-patches.md
Normal file
90
docs/features/fork-cleanup/06-upstreamable-patches.md
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# 06 — Upstreamable patches
|
||||
|
||||
> Some of the diff is genuine bug fixes or standard portability guards that upstream KiCad /
|
||||
> wxWidgets would plausibly accept. Once merged upstream, the divergence **disappears on the
|
||||
> next submodule bump** — net-zero, and it's the right thing to do regardless. This doc is
|
||||
> the submit list. Trim fork-specific comments (e.g. references to `features/…` paths) before
|
||||
> sending.
|
||||
|
||||
## Submit-ready bug fixes
|
||||
|
||||
### RTree `ELEMTYPEREAL` overflow — `libs/kimath/src/geometry/shape_poly_set.cpp` (+9/−1)
|
||||
|
||||
`splitCollinearOutlines()` instantiated `RTree<intptr_t, intptr_t, 2, intptr_t>`. On wasm32
|
||||
`intptr_t` is 32-bit, but `ELEMTYPEREAL` holds `sumOfSquares` values ~10¹⁴ → overflow → the
|
||||
`rtree.h:1771` Classify assert fires on **every PCB load**. Every other KiCad RTree
|
||||
instantiation already uses `double`. The fix is `intptr_t` → `double` for the
|
||||
`ELEMTYPEREAL` template arg. This is an upstream typo, not a wasm issue — submit as-is.
|
||||
(Recorded in the `rtree-intptr-overflow-fix` memory.)
|
||||
|
||||
### Default alternate hotkey never applied — `common/tool/action_manager.cpp` (+5)
|
||||
|
||||
`processHotKey` never copies `m_defaultHotKeyAlt` → `m_hotKeyAlt`, so `DefaultHotkeyAlt()` is
|
||||
dead in default configs upstream. One-line fix (`aAction->m_hotKeyAlt = aAction->m_defaultHotKeyAlt;`).
|
||||
Submit as a standalone bug fix. (Note: this is the real fix behind the Backspace-delete
|
||||
behavior; see [03](03-config-not-code.md) §2.)
|
||||
|
||||
## Standard portability guards (no-ops for native builds)
|
||||
|
||||
These re-spell wasm-driven conditionals using the wx feature-test macros upstream already
|
||||
honors, so they're harmless on native and make the wasm build correct:
|
||||
|
||||
- **`wxUSE_TOOLTIPS` guards** — `include/widgets/wx_dataviewctrl.h` (the
|
||||
`DoSetToolTipText() override` only exists when the base virtual does),
|
||||
`common/dialogs/dialog_paste_special.cpp`, `common/widgets/wx_infobar.cpp`,
|
||||
`pcbnew/dialogs/dialog_board_reannotate.cpp`. Re-spell the bare `#ifndef __EMSCRIPTEN__`
|
||||
variants (in the dialogs from [05](05-wx-layer-fixes.md) §4) to `#if wxUSE_TOOLTIPS` and
|
||||
submit the lot.
|
||||
- **`wxUSE_FSWATCHER` guards** — `include/pcb_base_frame.h`, `pcbnew/pcb_base_frame.cpp`,
|
||||
`eeschema/sch_base_frame.cpp`/`.h` (watcher members + `setFPWatcher`/`OnFPChange` bodies).
|
||||
Standard feature test; upstream builds compile unchanged.
|
||||
- **ngspice header guard** — `common/build_version.cpp` (+3) shouldn't require
|
||||
`<ngspice/sharedspice.h>` when SPICE is off; the version-print dispatch already has an
|
||||
`"unknown"` fallback. (`#ifdef KICAD_SPICE` would be even cleaner.)
|
||||
|
||||
## Output-correctness fixes
|
||||
|
||||
- **UTF-8 s-expr output** — `common/io/kicad/kicad_io_utils.cpp` (+2/−2):
|
||||
`Print("(%ls …)", aKey.wc_str())` → `Print("(%s …)", aKey.ToUTF8().data())`. `%ls`
|
||||
misbehaves in the wasm libc printf path; UTF-8 is strictly more correct for the format.
|
||||
- **IWYU includes** — `gerbview/events_called_functions.cpp`, `gerbview/toolbars_gerber.cpp`,
|
||||
`gerbview/tools/gerbview_control.cpp` add `#include <wx/choice.h>` (transitively present on
|
||||
native ports, missing on wasm). Pure include hygiene.
|
||||
- **wxUniv choice fixes** — `eeschema/dialogs/dialog_sim_command.cpp`
|
||||
(`IsEmpty()`→`GetCount()>0`), `pcbnew/dialogs/panel_setup_layers.cpp`
|
||||
(`GetCurrentSelection()`→`GetSelection()`), `dialog_board_reannotate.cpp`
|
||||
(`wxS(" ")`→`wxT(" ")` ternary-type fix). Correct on all ports.
|
||||
|
||||
## Feature proposals (larger, medium prospects)
|
||||
|
||||
- **Drawing-sheet item KIID** — the collab/yjs feature adds `KIID m_Uuid` to `DS_DATA_ITEM`
|
||||
and an optional `(uuid …)` token in `.kicad_wks` (`common/drawing_sheet/drawing_sheet.keywords`,
|
||||
`drawing_sheet_parser.cpp` +24, `ds_data_model_io.cpp` +4, `include/drawing_sheet/ds_data_item.h`
|
||||
+4). This is a real file-format change — no runtime hook can substitute (there's no
|
||||
drawing-sheet listener API upstream, and persistence is the point). But "give drawing-sheet
|
||||
items stable identity like every other `EDA_ITEM`" is a defensible upstream proposal, and
|
||||
the parser ignores-unknown so it's forward-compatible. If accepted, the format fork
|
||||
vanishes. (Related: [10](10-3d-viewer.md) has no bearing here; the collab hook itself is in
|
||||
`pl_editor_frame.cpp` and stays — see below.)
|
||||
- **`python_scripting.h` header hygiene** — moving `#include <Python.h>` out of the header
|
||||
into the `.cpp` would dissolve the ~7 scripting include-gates across KiCad files
|
||||
(see [`../../../features/python/research.md`](../../../features/python/research.md)).
|
||||
- **Plugin self-registration** — moving the `REGISTER_PLUGIN` statics into each plugin's own
|
||||
`.cpp` (the pattern `PCB_IO_MGR` half-uses) lets the importer exclusions in
|
||||
[08](08-importers.md) be pure CMake instead of `#ifndef` blocks in `sch_io_mgr.cpp` /
|
||||
`pcb_io_mgr.cpp`.
|
||||
|
||||
## Not worth proposing
|
||||
|
||||
- **Optional protobuf** — upstream explicitly keeps protobuf mandatory ("required even when
|
||||
the IPC API is not enabled … likely to be used in other applications in the future"). It
|
||||
doesn't matter anyway: our IPC-API gates are dead and get reverted ([01](01-revert-dead-code.md)).
|
||||
|
||||
## The one collab hook that has no upstream home
|
||||
|
||||
`pagelayout_editor/pl_editor_frame.cpp` (+15) calls `kicadCollabOnModify()` from
|
||||
`OnModify()` under `__EMSCRIPTEN__`. There is **no** drawing-sheet listener/observer API
|
||||
upstream (pcbnew uses `BOARD_LISTENER` with zero source hooks; eeschema has
|
||||
`SCHEMATIC_LISTENER`; the drawing-sheet model has neither). So this hook genuinely stays —
|
||||
though 11 of its 15 lines are comment and can be trimmed. The clean exit is proposing a
|
||||
drawing-sheet `OnModify` notification upstream (low-medium prospect).
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
# 07 — Native-build regressions & tooling
|
||||
|
||||
> While shrinking the diff, the research surfaced **six places where the fork silently
|
||||
> changed *native* (non-wasm) build behavior** — these are bugs regardless of the cleanup,
|
||||
> worth fixing on their own. Plus: three dead build-script flags and a diff-stat tool that
|
||||
> lies about how far the fork has diverged.
|
||||
|
||||
## Native-build regressions
|
||||
|
||||
### 1. `COMMON_WIDGETS_SRCS` typo — drops a source from *all* builds
|
||||
|
||||
`common/CMakeLists.txt` appends the webview gating to a variable named `COMMON_WIDGETS_SRCS`,
|
||||
but the real list is `COMMON_WIDGET_SRCS` (singular). Result: `widgets/webview_panel.cpp` is
|
||||
silently dropped from **every** build, including native. Fix the name (and keep the wasm
|
||||
exclusion conditional).
|
||||
|
||||
### 2. Duplicate `add_subdirectory(navlib)` — breaks native macOS/Windows configure
|
||||
|
||||
`pcbnew/CMakeLists.txt` adds an **unconditional** `add_subdirectory(navlib)` near the top and
|
||||
puts `pcbnew_navlib` in `PCBNEW_KIFACE_LIBRARIES`. But upstream `common/CMakeLists.txt`
|
||||
(unchanged, ~line 1074) already does `add_subdirectory(../pcbnew/navlib ./navlib)` under
|
||||
`if(APPLE OR NOT UNIX)` → duplicate `pcbnew_navlib` target → configure failure on native
|
||||
macOS/Windows. Make the fork's addition `if(EMSCRIPTEN)`-only (and revisit the stub forks per
|
||||
[02](02-cmake-dechurn.md) §6).
|
||||
|
||||
### 3. HiDPI scale factor changed for native — `hidpi_gl_canvas.cpp`
|
||||
|
||||
`GetScaleFactor()` switched from `GetContentScaleFactor()` to `GetDPIScaleFactor()`
|
||||
*unconditionally*; these differ on MSW, so native Windows rendering is altered. Fix in the wx
|
||||
wasm port and revert ([05](05-wx-layer-fixes.md) §1).
|
||||
|
||||
### 4. Toolbar customization accidentally disabled on wasm — `pcbnew/pcbnew.cpp`
|
||||
|
||||
The `#ifndef __EMSCRIPTEN__` block that gates the 3D settings panels also swallows
|
||||
`PANEL_TOOLBAR_CUSTOMIZATION`, which is *not* a 3D panel — so toolbar customization settings
|
||||
are silently off on wasm. Re-scope the gate to the 3D panels only. (Goes away anyway when 3D
|
||||
is re-enabled — see [10](10-3d-viewer.md).)
|
||||
|
||||
### 5. `KICAD_IPC_API` default flipped — affects native
|
||||
|
||||
Root `CMakeLists.txt` flips the `KICAD_IPC_API` option default ON→OFF. The wasm build passes
|
||||
`=ON` explicitly, so this only changes *native* behavior. Revert the default.
|
||||
|
||||
### 6. `pl_editor` OBJECT-library restructure — all platforms
|
||||
|
||||
`pagelayout_editor/CMakeLists.txt` introduces a `pl_editor_kiface_objects` OBJECT library and
|
||||
leaves `add_library(pl_editor_kiface MODULE)` empty, for **all** platforms (it works via
|
||||
object-lib propagation, but it's an unconditional restructure of upstream build shape). Make
|
||||
it `EMSCRIPTEN`-only or upstream-shaped.
|
||||
|
||||
## Dead build-script flags
|
||||
|
||||
`scripts/kicad/build-kicad-target.sh` passes flags that **are not options in this KiCad
|
||||
version** — they configure nothing and mislead:
|
||||
|
||||
- `KICAD_SPICE=OFF` — no such option (only `KICAD_SPICE_QA` exists). The simulator is always
|
||||
built; the real disable is the `Findngspice.cmake` stub ([11](11-ngspice-simulator.md)).
|
||||
- `KICAD_PCM=OFF` — no such option. PCM is an unconditional library linked only into the
|
||||
`kicad` / `kicad-cli` targets, which aren't built for wasm.
|
||||
- `BUILD_GITHUB_PLUGIN=OFF` — no such option.
|
||||
|
||||
Remove all three so the script reflects reality.
|
||||
|
||||
## `kicad-diff-stats.sh` mis-detects the fork point
|
||||
|
||||
`scripts/kicad-diff-stats.sh` reports **0 fork commits** because it finds the fork point by
|
||||
walking `git log` and taking the first commit whose author email isn't in an allowlist
|
||||
(`OUR_AUTHORS` = only `viktor.vaczi@…` + `noreply@anthropic.com`). The submodule HEAD is
|
||||
authored by `balint.ipkovich@…`, so the loop terminates on iteration 1 and calls HEAD itself
|
||||
"upstream." The real fork history `4bfed3f174..HEAD` has **24 commits by 4 authors** (viktor
|
||||
×14, torcsvari.gergo ×5, balint ×4, matejcsok-ee ×1) — three of four are missing from the
|
||||
allowlist.
|
||||
|
||||
**Fix (any one):**
|
||||
|
||||
- Pin the fork-base SHA (`4bfed3f174`) in a script variable / file; or
|
||||
- Use the `upstream` remote that already exists: `git merge-base HEAD upstream/master`; or
|
||||
- Match the *upstream* side (KiCad maintainer commit domains) instead of enumerating "our"
|
||||
people.
|
||||
|
||||
The author-allowlist heuristic is inherently rot-prone; the merge-base approach is robust.
|
||||
(Secondary: the `AUTHOR_PATTERN` grep-building block is dead code — the loop does exact
|
||||
string matching.)
|
||||
76
docs/features/fork-cleanup/08-importers.md
Normal file
76
docs/features/fork-cleanup/08-importers.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# 08 — Re-enable file-format importers
|
||||
|
||||
> **Verdict: re-enable now.** The exclusions are stale or incidental, not technical. The
|
||||
> Altium blocker was fixed months ago (the fix is already force-included into every TU), and
|
||||
> the other five eeschema importers were cut for "MVP scoping" while their parsers compile
|
||||
> for wasm anyway. Re-enabling is **net-negative diff** — it deletes fork gates. Configure-
|
||||
> confident but runtime-untested: smoke-test each with a sample file before declaring done.
|
||||
|
||||
## Altium (eeschema + pcbnew) — the blocker is already fixed
|
||||
|
||||
**The recorded blocker was real:** `thirdparty/compoundfilereader/compoundfilereader.h:264`
|
||||
does `typedef std::basic_string<uint16_t> utf16string;`, and the libc++ shipped in Emscripten
|
||||
4.0.2 removed the generic `std::char_traits` base template (deprecated LLVM 18, removed LLVM
|
||||
19 via llvm/llvm-project#72694 — the same break hit nlohmann/json #4490, qpdf #1024). Plain
|
||||
`std::basic_string<uint16_t>` fails to compile with
|
||||
`implicit instantiation of undefined template 'std::char_traits<unsigned short>'`.
|
||||
|
||||
**The fix already exists and is already active.** `wasm/stubs/char_traits_uint16_workaround.h`
|
||||
defines `std::char_traits<unsigned short>` and is **force-included into every KiCad TU** via
|
||||
`-include` in `CMAKE_CXX_FLAGS` (`scripts/kicad/build-kicad-target.sh:343`). A standalone
|
||||
compile test with the project's own emsdk confirms `compoundfilereader.h` compiles clean with
|
||||
the specialization in scope. (Upstream KiCad hit the identical bug on Apple clang ≥17 and
|
||||
ships the same specialization gated `#ifdef __APPLE__` in the vendored header.) No other
|
||||
`basic_string<unsigned short>` use exists anywhere in the tree outside this header.
|
||||
|
||||
So the Altium exclusions are simply stale. **Remove these fork-added gates** (each removal
|
||||
*reduces* the diff):
|
||||
|
||||
```
|
||||
common/CMakeLists.txt # io/altium 4 files gated NOT EMSCRIPTEN
|
||||
eeschema/CMakeLists.txt # importer block; altium lines
|
||||
eeschema/sch_io/sch_io_mgr.cpp # #ifndef __EMSCRIPTEN__ includes + factory cases
|
||||
pcbnew/CMakeLists.txt # add_subdirectory(pcb_io/altium) gate + PCBNEW_IO_LIBRARIES dual list
|
||||
pcbnew/pcb_io/pcb_io_mgr.cpp # #ifndef blocks (CircuitMaker/Studio/Designer + Solidworks)
|
||||
```
|
||||
|
||||
`pcb_io/altium`'s deps (pcbcommon, compoundfilereader, magic_enum) are all already built for
|
||||
wasm. One root cause fixes both the eeschema and pcbnew sides.
|
||||
|
||||
## Eagle / CADSTAR / LTspice / EasyEDA / EasyEDA-Pro (eeschema) — incidental MVP cut
|
||||
|
||||
`eeschema/CMakeLists.txt` excludes these in an `if(NOT EMSCRIPTEN)` block with the comment
|
||||
"cross-tool importers we don't need for the MVP and they bring transitive incompatible
|
||||
dependencies in." The dependency half is **false today**, and there's strong evidence the
|
||||
cut was incidental:
|
||||
|
||||
- All their shared parsers already compile **unconditionally** in `common/CMakeLists.txt`
|
||||
(`io/cadstar/cadstar_archive_parser.cpp`, `io/eagle/eagle_parser.cpp`, `io/easyeda/*`,
|
||||
`io/easyedapro/*`).
|
||||
- **pcbnew's wasm build already ships the equivalents** — CADSTAR, EasyEDA, EasyEDA-Pro,
|
||||
Fabmaster, IPC-2581, ODB++, P-CAD (`pcbnew/CMakeLists.txt`), plus eagle + geda compiled
|
||||
straight into pcbcommon. Only Altium was excluded on the pcbnew side. If pcbnew builds them
|
||||
but eeschema doesn't, the eeschema exclusion is incidental.
|
||||
- Deps are all present: expat (eagle XML), nlohmann (easyeda), wxZip/zlib (easyedapro), plain
|
||||
text (ltspice, cadstar).
|
||||
|
||||
**Do:** move the five importer groups out of the `if(NOT EMSCRIPTEN)` block in
|
||||
`eeschema/CMakeLists.txt` and drop the matching `#ifndef __EMSCRIPTEN__` cases in
|
||||
`sch_io_mgr.cpp`. (Altium-sch additionally needs the Altium common code from the section
|
||||
above.) Net-negative fork diff; no platform deps.
|
||||
|
||||
## Stays impossible / policy
|
||||
|
||||
- **Database (`SCH_IO_DATABASE`)** — needs nanodbc → ODBC driver manager → native drivers
|
||||
opening TCP to a DB server. No browser path; keep stubbed. (`database_lib_settings.cpp`
|
||||
still compiles for settings-file compatibility — fine.)
|
||||
- **HTTP library (`SCH_IO_HTTP_LIB`)** — already compiled and *registered*, but dead at
|
||||
runtime because the curl stub returns NULL. Reviving it is the curl→fetch shim in
|
||||
[12](12-network-stack.md), not part of this refactor.
|
||||
|
||||
## Verification
|
||||
|
||||
Build, then import: an Eagle `.sch`, an Altium `.SchDoc`/`.PcbDoc`, and one of
|
||||
CADSTAR/EasyEDA. Confirm the importer appears in the File → Import menu and round-trips
|
||||
geometry. The import dialogs use `wxFileDialog` (PARTIAL per `tests/WHATWORKS.md`), so verify
|
||||
the file-open flow too.
|
||||
67
docs/features/fork-cleanup/09-symbol-libraries.md
Normal file
67
docs/features/fork-cleanup/09-symbol-libraries.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# 09 — Re-enable the symbol chooser & viewer
|
||||
|
||||
> **The chooser and viewer aren't broken — the browser FS just ships no libraries.** The
|
||||
> `#ifdef __EMSCRIPTEN__ return nullptr` gates in `eeschema.cpp` are *asset-availability*
|
||||
> gates, not code gates. Un-gating is ~10 lines deleted; the real work is a small library-
|
||||
> provisioning pipeline in the `web/` layer (no upstream footprint).
|
||||
|
||||
## What's actually gated
|
||||
|
||||
`eeschema/eeschema.cpp` returns `nullptr` for `FRAME_SCH_VIEWER` ("symbol viewer is not
|
||||
supported") and `FRAME_SYMBOL_CHOOSER` (comment: "no bundled libs"). Both frames' sources
|
||||
**are compiled** (`eeschema/CMakeLists.txt`). Callers currently hitting the nullptr:
|
||||
`dialog_change_symbols.cpp`, `grid_text_button_helpers.cpp` (symbol-browse buttons silently
|
||||
no-op), `sch_edit_frame.cpp`.
|
||||
|
||||
## Evidence the frames work
|
||||
|
||||
- `features/yjs-bridge/0007-eeschema-essential-ops-findings.md` records the in-process symbol
|
||||
**chooser dialog already opening and working** in wasm ("symbol chooser now center with OK
|
||||
reachable") — it just shows "0 items loaded" because `/usr/share/kicad/symbols` is absent.
|
||||
- Every UI dependency is proven working in wxUniv-wasm (`tests/WHATWORKS.md`): the
|
||||
`wxDataViewCtrl` LIB_TREE, the `wxHtmlWindow` details pane, the GAL preview canvas. The
|
||||
**symbol editor** — same LIB_TREE + preview machinery — is already a shipped, ported target.
|
||||
- pcbnew's footprint browse/choose paths are **already un-gated**; they start working the
|
||||
moment `fp-lib-table` has content.
|
||||
|
||||
## Why the FS is empty today
|
||||
|
||||
The boot path (`web/standalone/src/wasm/boot.ts`, mirrored by the test harness) ships only
|
||||
`images.tar.gz` (UI bitmaps) and seeds **empty** `sym-lib-table` / `fp-lib-table` /
|
||||
`design-block-lib-table`, plus `kicad_common.json` flags that suppress the first-run
|
||||
StartWizard (its modal loop crashes Asyncify — see the [async dossier](../async/README.md)).
|
||||
No symbol libraries, footprint libraries, 3D models, or templates are packaged. So un-gating
|
||||
*alone* yields an empty tree — correct behavior, just not useful.
|
||||
|
||||
> Background: designs embed the parts they use, so *opening an existing file* never needed the
|
||||
> libraries (see [`../libraries/0001-library-management.md`](../libraries/0001-library-management.md)).
|
||||
> The chooser/viewer are about *placing new* parts — that's what needs shipped libraries.
|
||||
|
||||
## Recipe
|
||||
|
||||
1. **Un-gate** (≈ −10 lines fork diff): delete the two `#ifdef __EMSCRIPTEN__` blocks in
|
||||
`eeschema/eeschema.cpp`.
|
||||
2. **Provision a starter library set** (web/wasm layer only, no upstream files):
|
||||
- Package a curated subset of `kicad-symbols` (e.g. Device, power, Connector, Switch, …)
|
||||
as an assets tarball, fetched and written into `/usr/share/kicad/symbols` in `preRun`
|
||||
(same mechanism as `images.tar.gz`). Optionally a `.pretty` footprint subset into
|
||||
`/usr/share/kicad/footprints`.
|
||||
- Write **real** `sym-lib-table` / `fp-lib-table` rows in `boot.ts` instead of the empty
|
||||
seeds.
|
||||
- For the full official set (~200 MB-class), prefer **lazy per-library fetch** into MEMFS
|
||||
on first reference rather than a giant preload — no engine obstacle, just engineering.
|
||||
|
||||
The repo doesn't currently vendor `kicad-symbols` (only `kicad/demos/*` and
|
||||
`qa/data/libraries/power.kicad_sym`), so step 2 introduces a new asset source — decide
|
||||
whether to vendor a curated subset or fetch from a CDN.
|
||||
|
||||
## Net
|
||||
|
||||
| Action | Layer | Diff impact |
|
||||
|---|---|---|
|
||||
| Delete viewer/chooser gates | `eeschema.cpp` | −10 lines |
|
||||
| Library asset tarball + lib-table seeding | `web/standalone/` | new web assets only |
|
||||
| Lazy per-lib MEMFS fetch (optional, for full set) | `web/`/`wasm/` | new code, no upstream |
|
||||
|
||||
Effort: gates are minutes; a usable curated-library bundle is ~1–2 days; full lazy-fetch is
|
||||
incremental on top.
|
||||
135
docs/features/fork-cleanup/10-3d-viewer.md
Normal file
135
docs/features/fork-cleanup/10-3d-viewer.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# 10 — Re-enable the 3D viewer
|
||||
|
||||
> **Verdict: port — and there's a cheap first step.** KiCad ships *two* 3D renderers: an
|
||||
> OpenGL one (pure fixed-function GL 1.x — far from WebGL2) and a **pure-CPU raytracer that
|
||||
> needs zero OpenGL**. The fork currently nulls the raytracer out. Turning 3D on via the
|
||||
> raytracer (**Route C**) is low-risk and brings the render-to-PNG job and VRML export back
|
||||
> nearly free; a WebGL2 port of the interactive renderer (**Route B**) is the follow-up.
|
||||
|
||||
## Why it's off (timeline, with primary sources)
|
||||
|
||||
| Date | Commit (kicad) | What |
|
||||
|---|---|---|
|
||||
| 2025-12-21 | `46bb16e86b` | "Enable 3D viewer build for WASM with OpenGL stubs" — compiled *only* so headers resolve. Message: "OpenGL rendering won't work at runtime … avoids complex stubbing." |
|
||||
| 2026-01-03 | `a61d2ea406` | OpenGL GAL on `-sLEGACY_GL_EMULATION`; added the +190-line `kiglew.h` `__EMSCRIPTEN__` branch (display lists + lighting as **no-ops**). 3D "built" but couldn't draw. |
|
||||
| 2026-01-10 | `d8a9ac4304` | "Disable 3D viewer functionality for WASM builds" — same day `WEBGL_GAL` landed and the build swapped emulation → `-sFULL_ES3`. Message: 3D "require[s] native OpenGL rendering (not WebGL)". Built with `KICAD_BUILD_3D_VIEWER_WASM=OFF`. |
|
||||
| 2026-03-20 | `4ddb9b47f5` | "Migrate to pure WebGL 2.0 without FULL_ES3 emulation" — 2D GAL goes pure WebGL2; the only GL link flag today is `-sMAX_WEBGL_VERSION=2`. |
|
||||
|
||||
Recorded rationale: `features/gl-article/README.md:274-276,421-422` — the 3D viewer is "a
|
||||
separate legacy-GL renderer, not GAL" needing "GLU + fixed-function", declared out of scope
|
||||
when the strategy became "progressively remove the Emscripten crutch." So it was a deliberate
|
||||
scoping decision when the emulation layer it depended on was removed — not a crash.
|
||||
|
||||
## What the OpenGL renderer actually uses
|
||||
|
||||
`3d-viewer/3d_rendering/opengl/` = 6 files, **4,555 lines**. It's pure GL 1.x fixed-function:
|
||||
|
||||
- **Immediate mode** — 153 tokens (`glBegin`/`glEnd` ×28, `glVertex*`/`glNormal3*`/`glTexCoord2*`).
|
||||
- **Display lists** — 36 refs in 2 files, and they're the **primary board-geometry path**:
|
||||
`layer_triangles.cpp:582-714` bakes every layer's triangles into `glGenLists`/`glNewList`
|
||||
wrapping a `glDrawArrays`; `render_3d_opengl.cpp:1303-1315` for the grid.
|
||||
- **Fixed-function matrix/lighting** — ~117 tokens (`glMaterialfv`, `glLightfv`,
|
||||
`glMatrixMode`/`glPush/PopMatrix`, `GL_LIGHTING`, …).
|
||||
- **Client-state arrays** — 49 tokens. **GLU** — 36 (`gluNewQuadric`/`gluCylinder`/`gluSphere`
|
||||
for vias/pads).
|
||||
- **Modern** — zero shaders, zero VAOs; only `3d_model.cpp` uses VBOs (GL 1.5 style).
|
||||
|
||||
Structurally friendlier than the raw counts suggest: geometry already lives in CPU triangle
|
||||
containers, display lists are thin `glDrawArrays` wrappers, `3d_model.cpp` is already VBO,
|
||||
camera/transforms are already glm.
|
||||
|
||||
## Route A — LEGACY_GL_EMULATION for the 3D viewer: REJECTED
|
||||
|
||||
- The flag is **module-global at link**: `GLEmulation.init()` replaces the module-wide JS
|
||||
bindings (`glDrawArrays`, `glEnable`, `glBindBuffer`, `glGetString`, …) for *all* contexts,
|
||||
including the flagship 2D `WEBGL_GAL`'s. Concretely it corrupts the GAL's ES3 shaders —
|
||||
emscripten prepends `#extension GL_OES_standard_derivatives` to any fragment shader using
|
||||
`dFdx` (`kicad_frag.glsl:138` does), and prepending anything before `#version 300 es` is a
|
||||
guaranteed ES3 compile error. Separate canvases/contexts do **not** isolate this (hooks are
|
||||
per-module).
|
||||
- Even ignoring that: emscripten never implemented display lists (issue #688 — the main board
|
||||
path draws nothing), GLU quadrics are absent, lighting emulation has `throw 'TODO'` holes.
|
||||
You'd rewrite the display-list and quadric paths anyway (the hard half of Route B) while
|
||||
regressing 2D and re-adding ~200 KB of the fragility the project already escaped. **Reject.**
|
||||
|
||||
## Route C — CPU raytracer + blit (do this first, low risk)
|
||||
|
||||
`RENDER_3D_RAYTRACE_RAM` (`render_3d_raytrace_ram.cpp`, 159 lines) is **100% GL-free**: it
|
||||
renders into a plain `uint8_t` RGBA buffer (`initPbo()` is just `new uint8_t[w*h*4]`) and
|
||||
exposes `GetBuffer()`. It's **progressive by design** — each `Redraw()` traces blocks up to a
|
||||
400/750 ms budget then yields, so a serial browser loop still animates. Both existing
|
||||
consumers already convert buffer → `wxImage` with no GL (`eda_3d_viewer_frame.cpp:846-866`
|
||||
screenshot; `pcbnew_jobs_handler.cpp:817-885` render job).
|
||||
|
||||
Recipe:
|
||||
|
||||
1. `KICAD_BUILD_3D_VIEWER_WASM=ON`, and **genex-out the GL renderer TUs**
|
||||
(`render_3d_opengl.cpp`, `layer_triangles.cpp`, …) the same way `render_3d_raytrace_gl.cpp`
|
||||
is already excluded (`3d-viewer/CMakeLists.txt:49`) — this sidesteps the legacy-GL link
|
||||
errors entirely. The raytracing subtree (12,232 lines) has no GL.
|
||||
2. Have `EDA_3D_CANVAS` instantiate `RENDER_3D_RAYTRACE_RAM` under `__EMSCRIPTEN__` (it's
|
||||
renderer-agnostic via `RENDER_3D_BASE`), and **blit** the buffer — either a plain wxWindow
|
||||
painting the `wxImage` through the wx-wasm 2D canvas DC (zero GL), or a ~100-line WebGL2
|
||||
textured quad (infra exists in `common/gal/webgl/fullscreen_quad.cpp`).
|
||||
3. **Delete the fork gates** — they're keyed on `__EMSCRIPTEN__`, *not* the CMake option, so
|
||||
flipping the flag alone isn't enough: `eda_3d_canvas.cpp` (raytracer nulled, raytracing
|
||||
request early-returned), `pcbnew/pcbnew.cpp` (3D settings panels — see the
|
||||
`PANEL_TOOLBAR_CUSTOMIZATION` bug in [07](07-native-build-bugs-and-tooling.md)),
|
||||
`pcbnew_jobs_handler.cpp`/`.h` (render job), and `exporter_vrml.cpp` (in-file stub). Delete
|
||||
the three big stub TUs too (`wasm/stubs/3d_viewer_stub.cpp`, `3d_canvas_stub.cpp`,
|
||||
`3d_scenegraph_stub.cpp`, ~1,200 lines).
|
||||
|
||||
Caveats: main tracing runs **serial** under the `bs_thread_pool` inline patch (still usable,
|
||||
because progressive); the preview / SSAO / DLAA passes use raw `std::thread` + a `sleep_for`
|
||||
spin-wait — pthreads *are* enabled in the build (`-pthread -sUSE_PTHREADS=1
|
||||
-sPTHREAD_POOL_SIZE=…`), so they run, but the spin-wait blocks the browser main thread per
|
||||
pass and is worth reviewing for jank.
|
||||
|
||||
## Route B — WebGL2 port of the interactive renderer (follow-up)
|
||||
|
||||
Scope is ~4,555 lines / 6 files — roughly **1/5 of the 2D GAL port** and far less novel (no
|
||||
compositor, no multi-FBO juggling). The work: display-list → VBO (mechanical, the lists wrap
|
||||
`glDrawArrays` of CPU triangle containers), client-state arrays → generic vertex attribs,
|
||||
fixed-function transforms → a small matrix-stack helper (already glm), ~2 shader pairs
|
||||
(Phong-lit per-material + flat), GLU quadrics → a triangle helper (small; vias/pads/gizmo).
|
||||
Reuse `common/gal/webgl/`'s shader infra + `convert_glsl_es3.py`.
|
||||
|
||||
Divergence: mirror the 2D precedent — new files (`3d_rendering/webgl/`), swapped via a CMake
|
||||
genex like the existing `render_3d_raytrace_gl.cpp` exclusion. Near-zero upstream-file diff
|
||||
beyond the swap + un-gating. Gives the **interactive** GPU-speed orbit/pan view. Risk: medium
|
||||
(GPU correctness; the e2e screenshot harness pattern exists). Prereq: model loading (below).
|
||||
|
||||
## Model loading (needed for both B and C to show components)
|
||||
|
||||
Upstream loads `plugins/3d/{vrml,oce,idf}` as **runtime DSOs** —
|
||||
`S3D_PLUGIN_MANAGER::loadPlugins()` scans a directory and `wxDynamicLibrary`-loads each. There
|
||||
is **no static-registration path upstream**, and `wasm/stubs/3d_scenegraph_stub.cpp` (440
|
||||
lines) currently stubs the whole `S3D_CACHE` + scenegraph + `S3D::WriteVRML`.
|
||||
|
||||
Static linking entails: compiling the plugin sources into the binary with **per-plugin symbol
|
||||
prefixes** (they export identical C ABI names — `Load`, `GetFileFilter`, … — so they collide;
|
||||
wrap each TU with `-Dname=vrml_name` or a wrapper), plus a small `__EMSCRIPTEN__` path (or a
|
||||
subclassed `KICAD_PLUGIN_LDR_3D`) with a 3-entry static registry — cleanest as one new
|
||||
wasm-layer file. Sizes: **vrml** (VRML1/2 + X3D, fully in-tree, **no external deps**) = 17,835
|
||||
lines; **oce** (STEP/IGES — needs OCC, which **is already built for wasm**: OCC 7.8 via
|
||||
`--with-occ`, verified `libTK*.a` in the sysroot) = 1,407; **idf** = 931. `kicad_3dsg` must
|
||||
become STATIC for wasm (it's `add_library(SHARED)` today). Plus: ship 3D model assets to the
|
||||
FS (models are *referenced*, not embedded — see
|
||||
[`../libraries/0001-library-management.md`](../libraries/0001-library-management.md)).
|
||||
|
||||
Start with the VRML plugin (no deps) for `.wrl` models; add OCE for STEP once VRML works.
|
||||
|
||||
## Render job & VRML export — free with either route
|
||||
|
||||
Both only need the 3D model cache / scenegraph / raytracer, **not** the GL renderer:
|
||||
|
||||
- `JobExportRender` (`pcbnew_jobs_handler.cpp:641-898`) is `RENDER_3D_RAYTRACE_RAM` +
|
||||
`BOARD_ADAPTER` + 3d_cache → board-render-to-PNG/JPEG works as soon as 3d-viewer links.
|
||||
- `exporter_vrml.cpp`'s real implementation needs `S3D_CACHE` + the SGNODE/IFSG API — un-stub
|
||||
by **deleting** the fork's `#else` block (a divergence *reduction*). Board-only export works
|
||||
immediately; embedding component models additionally needs the static VRML plugin above.
|
||||
|
||||
## Sequencing
|
||||
|
||||
**C first** (working 3D view + render job + VRML export, low risk, mostly deletes gates) →
|
||||
**B second** (interactive upgrade) → **A never**.
|
||||
63
docs/features/fork-cleanup/11-ngspice-simulator.md
Normal file
63
docs/features/fork-cleanup/11-ngspice-simulator.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# 11 — Re-enable the SPICE simulator
|
||||
|
||||
> **Verdict: port, ~1–2 weeks.** The groundwork is half-done in-repo: a wasm ngspice build
|
||||
> script already exists, the simulator sources already compile, and the only unavoidable
|
||||
> upstream-file edit is a ~25-line block swapping `wxDynamicLibrary` for direct static
|
||||
> symbols. Multiple working emscripten ngspice ports exist as precedent.
|
||||
|
||||
## Current state (more nuanced than "KICAD_SPICE=OFF")
|
||||
|
||||
- `-DKICAD_SPICE=OFF` in `build-kicad-target.sh` is **vestigial** — there's no such option in
|
||||
this KiCad (only `KICAD_SPICE_QA`). The simulator is *always* built; all `eeschema/sim/`
|
||||
sources compile for wasm.
|
||||
- The dep is satisfied by a header-only stub: `wasm/cmake/Findngspice.cmake` points includes
|
||||
at `wasm/stubs/ngspice/sharedspice.h` with an empty link line.
|
||||
- **Runtime kill-point:** `SIMULATOR_FRAME` ctor → `NGSPICE` init → `ngspice.cpp:474`
|
||||
`m_dll.Load(wxDynamicLibrary::CanonicalizeName("ngspice"))` fails (no `dlopen` without
|
||||
`-sMAIN_MODULE`) → throws → caught at `eeschema/eeschema.cpp:208-221` → simulator silently
|
||||
returns `nullptr`.
|
||||
|
||||
## The groundwork already here
|
||||
|
||||
- **A wasm ngspice build script exists:** `scripts/deps/build-ngspice.sh` (ngspice 45.2,
|
||||
static, cider + xspice, pthread; opt-in via `build-all-deps.sh --with-ngspice`).
|
||||
- **A known size landmine is already handled:** the 4 giant model-data initializers
|
||||
(`sim_model_ngspice_data_{bsim4,b3soi,b4soi,hsim}.cpp`) exceeded the JS engines' "too many
|
||||
locals" validation limit and are stubbed (`eeschema/CMakeLists.txt:292-305` +
|
||||
`wasm/stubs/eeschema_ngspice_data_stubs.cpp`).
|
||||
|
||||
## Why static linking works
|
||||
|
||||
KiCad resolves 9–11 ngspice function pointers via `GetSymbol` (`ngspice.cpp:503-517`) and
|
||||
registers C callbacks (`cbSendChar`, `cbBGThreadRunning`, … `ngspice.cpp:519`). With a
|
||||
**statically linked** `libngspice.a`, those become plain function pointers and direct symbol
|
||||
references — no `dlopen` needed. Threading: KiCad drives sims via `bg_run`/`bg_halt`
|
||||
(`ngspice.cpp:335,342`) using ngspice's internal pthread; the wasm build is already
|
||||
full-pthread, and native code already assumes callbacks fire on the bg thread — same model.
|
||||
|
||||
Precedent (all static, OpenMP off, shared-lib mode unsupported under emscripten):
|
||||
wokwi/ngspice-wasm, EEcircuit (eelab-dev), danchitnis/ngspice, plus upstream ngspice WASM
|
||||
patches (#96, #99).
|
||||
|
||||
## Recipe
|
||||
|
||||
1. Verify `scripts/deps/build-ngspice.sh` completes for 45.2.
|
||||
2. Make `wasm/cmake/Findngspice.cmake` return the **real** sysroot lib + headers when present
|
||||
(fall back to the stub otherwise).
|
||||
3. **The one unavoidable upstream-file edit:** a `#ifdef __EMSCRIPTEN__` branch in
|
||||
`eeschema/sim/ngspice.cpp` `init_dll()` that binds the `m_ngSpice_*` pointers directly to
|
||||
the statically-linked symbols instead of via `wxDynamicLibrary` (~25 lines, one block).
|
||||
4. Ship `spinit` / `.cm` codemodels into MEMFS if xspice device models are wanted.
|
||||
5. **Retest the model-data stubs** — the "too many locals" failure predates the now-default
|
||||
post-asyncify `wasm-opt -O2` pass that solved the same engine-limit family elsewhere (see
|
||||
the `chrome-asyncify-rewind-crash` memory). If it's resolved, restore the 4 real model-data
|
||||
files; if not, the simulator works minus BSIM4/SOI/HSIM device models.
|
||||
|
||||
## Residual risks (verify at runtime)
|
||||
|
||||
- `SIMULATOR_FRAME`'s plot widget behavior under wxUniversal (untested).
|
||||
- Asyncify vs. the ngspice bg-thread interplay during a running simulation (see the
|
||||
[async dossier](../async/README.md) for the suspension model).
|
||||
|
||||
Diff impact: ~25 lines in one upstream file (`ngspice.cpp`) + a `Findngspice.cmake` change
|
||||
(wasm layer). Everything else is the dep build and FS assets.
|
||||
80
docs/features/fork-cleanup/12-network-stack.md
Normal file
80
docs/features/fork-cleanup/12-network-stack.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# 12 — Network stack & the impossible catalog
|
||||
|
||||
> Three link-time stubs (`libcurl_stub.a`, `libgit2_stub.a`, `libnng_stub.a`) gate a cluster
|
||||
> of features. Two are revivable in the browser (HTTP libraries, local history); one is
|
||||
> genuinely impossible (the IPC socket transport). This doc covers those plus the full
|
||||
> catalog of what stays off and **why** — so the "everything web-feasible should work" policy
|
||||
> has a clear boundary.
|
||||
|
||||
## curl → emscripten Fetch (revives HTTP libraries)
|
||||
|
||||
`wasm/stubs/curl_stub.c` makes `curl_easy_init()` return `NULL`, so
|
||||
`KICAD_CURL_EASY`'s ctor throws `"Unable to initialize CURL session"`
|
||||
(`common/kicad_curl/kicad_curl_easy.cpp:127-130`). That kills: the HTTP schematic library
|
||||
(`SCH_IO_HTTP_LIB`, which is otherwise compiled and registered — see [08](08-importers.md)),
|
||||
the update check, and PCM downloads.
|
||||
|
||||
**The right move is *not* porting libcurl** (browsers can't do raw TCP; the real libcurl-wasm
|
||||
ports tunnel TCP over WebSocket proxies — wrong tool). Instead, replace the stub with a
|
||||
functional implementation of the ~12 `curl_easy_*` entry points `KICAD_CURL_EASY` actually
|
||||
uses (setopt URL/headers/POST/writefunction, perform, getinfo response-code) over the
|
||||
**emscripten Fetch API** — Asyncify-friendly (the build already runs full Asyncify), same
|
||||
pattern as the clipboard. New file in `wasm/stubs/`, **zero KiCad-file changes**. Constraint:
|
||||
target servers must send CORS headers. ~2–4 days. Same shim revives every other curl consumer
|
||||
(version checks in `pgm_base.cpp` / `build_version.cpp`, currently failing silently).
|
||||
|
||||
## libgit2 → real static build (fixes silently-broken local history)
|
||||
|
||||
`wasm/stubs/libgit2_stub.c` makes all git ops fail with -1. This kills two things:
|
||||
|
||||
- **Project git integration** — UI lives in the `kicad` project-manager (not a wasm target),
|
||||
so mostly moot.
|
||||
- **Local history** — **not moot.** `common/local_history.cpp` (git-backed save snapshots) is
|
||||
wired into the *shipped* editors (`pcb_edit_frame.cpp`, `files.cpp`, `sch_edit_frame.cpp`,
|
||||
`eda_base_frame.cpp`) and currently **fails silently on every save.** This is a real
|
||||
product gap worth a deliberate decision.
|
||||
|
||||
**Port (medium, ~1 week):** build a real static `libgit2.a` for wasm (wasm-git /
|
||||
petersalomonsen proves libgit2 compiles to emscripten cleanly) and drop the stub for the
|
||||
editors. Local-only commits need no network. Remote push/pull would additionally need
|
||||
wasm-git's HTTP smart-transport — skip that. **Alternatively**, if local history isn't a
|
||||
priority, disable the feature via config so it stops failing silently — but pick one; the
|
||||
current state (compiled-in, failing every save) is the worst option.
|
||||
|
||||
## nng / IPC API transport — keep stubbed (impossible)
|
||||
|
||||
`KICAD_IPC_API=ON` builds the API handlers + protobuf (that's what the ON flag is for), but
|
||||
`api_server.cpp` / `api_plugin_manager.cpp` are excluded and `kinng` isn't linked
|
||||
(`common/CMakeLists.txt`). nng is raw sockets and the IPC clients are **external OS
|
||||
processes** — neither exists in a browser sandbox. Keep `libnng_stub.a`.
|
||||
|
||||
> The mainline-aligned future for plugins (post-SWIG KiCad 11) is this same IPC API, reachable
|
||||
> from the browser only via a JS bridge (postMessage/WebSocket) implementing the request/reply
|
||||
> surface — a *different* transport, not nng. That's a separate project; see
|
||||
> [`../../../features/python/research.md`](../../../features/python/research.md).
|
||||
|
||||
## The impossible catalog (and why)
|
||||
|
||||
| Feature | Why it can't work in a browser |
|
||||
|---|---|
|
||||
| 3Dconnexion SpaceMouse / navlib | needs the native 3DxWare driver/daemon; WebHID can't replace the SDK protocol |
|
||||
| Dynamic KIFACE / DSO loading | no `dlopen` of native DSOs in wasm; the static single-kiface architecture is correct (`kiway.cpp` / `kiway.h`) |
|
||||
| ODBC database (`nanodbc`) | driver-manager + native driver model has no browser equivalent ([08](08-importers.md)) |
|
||||
| nng / IPC transport | raw sockets to external OS processes (above) |
|
||||
| `wxUSE_FSWATCHER` | no inotify/kqueue; MEMFS has no change notification and nothing edits files externally |
|
||||
| `wxUSE_WEBVIEW` | no browser backend for the wasm port; only the unshipped project-manager uses it |
|
||||
| OS keychain (`wxUSE_SECRETSTORE`) | no OS credential service; only insecure approximations (localStorage) exist |
|
||||
| Pointer warping (`WarpPointer`) | browsers can't move the OS pointer — handled by zoom-to-cursor ([03](03-config-not-code.md)) |
|
||||
| System trash / host env / process info | sandbox (kiplatform `environment.cpp`, `sysinfo.cpp`) |
|
||||
| `PYTHON_MANAGER` subprocess execution | no `fork`/subprocess in emscripten; an embedded interpreter is the only path (policy-off) |
|
||||
|
||||
## Policy-off (not impossible — chosen)
|
||||
|
||||
- **Python scripting** — `KICAD_SCRIPTING` OFF + stubs. Stays off per the standing decision;
|
||||
the mainline path is the IPC API, not SWIG (see
|
||||
[`../../../features/python/research.md`](../../../features/python/research.md)).
|
||||
- **PCM, update check** — networking features the team skipped; the curl shim above would
|
||||
revive the update check if ever wanted.
|
||||
- **`kicad` project manager, `cvpcb`, `bitmap2component`** — never given wasm targets; the web
|
||||
app is the "manager" and the product ships per-tool editors (pcbnew, eeschema, symbol_editor,
|
||||
gerbview, pl_editor, calculator).
|
||||
126
docs/features/fork-cleanup/README.md
Normal file
126
docs/features/fork-cleanup/README.md
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
# Fork cleanup: minimize divergence & re-enable web-feasible features
|
||||
|
||||
> **Status:** research / planning only. No code has been changed. Authored June 2026.
|
||||
> All `file:line` references are against the `kicad` submodule at its current HEAD
|
||||
> (`ac7d733787`), upstream merge-base `4bfed3f174`, and the root repo at the same time.
|
||||
> Verify line numbers before editing — they drift.
|
||||
|
||||
## Why this exists
|
||||
|
||||
Getting KiCad to build for the browser meant disabling, stubbing, and `#ifdef`-ing a
|
||||
lot of things "because we had to." Two goals now pull in the same direction:
|
||||
|
||||
1. **Keep the `kicad` and `wxwidgets` forks as close to mainline as possible.** Where we
|
||||
add things, they should live in *new files/folders* (or build flags, runtime config,
|
||||
the `wasm/` layer) — not as edits to upstream source.
|
||||
2. **Everything that *can* work in a browser should actually work.** The 3D viewer,
|
||||
importers, the symbol chooser — turn them back on. Only Python scripting and things
|
||||
that are genuinely impossible on the web stay off.
|
||||
|
||||
The key reframe that ties them together: **re-enabling features mostly *deletes* fork
|
||||
code.** Almost everything disabled is disabled by a fork-added gate, stub, or exclusion.
|
||||
Turning it back on removes that divergence. The two goals are one project.
|
||||
|
||||
## TL;DR — the baseline and the target
|
||||
|
||||
Fork state vs. merge-base `4bfed3f174` (24 commits):
|
||||
|
||||
| | Count |
|
||||
|---|---|
|
||||
| New files (policy-compliant) | 44 (~28k lines, mostly the WebGL GAL copy) |
|
||||
| Modified upstream files | **104** |
|
||||
| Changed lines in modified files | **~2,400** (~1,600 of it CMake) |
|
||||
|
||||
Estimated reachable end-state after the refactors below: **~15–20 modified files /
|
||||
~150–250 lines**, with the WASM product *gaining* the 3D viewer, render-to-PNG jobs,
|
||||
VRML export, five importers, the symbol browser, and optionally simulation, tooltips,
|
||||
HTTP libraries, and working local history.
|
||||
|
||||
Three facts do most of the work:
|
||||
|
||||
- **Big chunks of the diff are dead code.** All `#ifdef KICAD_IPC_API` gating, the
|
||||
+189-line `kiglew.h` shim, and the `opengl_gal.cpp` refactor compile in configurations
|
||||
the shipping build never uses. See [01](01-revert-dead-code.md).
|
||||
- **Several "disabled" features are disabled by stale mechanisms.** The Altium importer's
|
||||
blocker was fixed months ago (the fix is force-included into every TU); three
|
||||
build-script `-D` flags don't even exist as options in this KiCad version. See
|
||||
[08](08-importers.md) and [07](07-native-build-bugs-and-tooling.md).
|
||||
- **The 3D viewer has a cheap path.** KiCad ships a pure-CPU raytracer that needs zero
|
||||
OpenGL, and the fork currently *nulls it out*. See [10](10-3d-viewer.md).
|
||||
|
||||
## Master inventory
|
||||
|
||||
Every disabled/divergent item, with verdict. Detail + recipes in the linked docs.
|
||||
|
||||
### Reduce divergence (shrink the submodule diff — no behavior change)
|
||||
|
||||
| Item | Mechanism | Action | Doc |
|
||||
|---|---|---|---|
|
||||
| `#ifdef KICAD_IPC_API` gates (18 files) | dead code (build sets `=ON`) | revert | [01](01-revert-dead-code.md) |
|
||||
| `kiglew.h` +189, `opengl_gal.cpp` +32/−31 | dead (opengl GAL not built for wasm) | revert | [01](01-revert-dead-code.md) |
|
||||
| `KI_DIAG_*` call sites (~30 lines) | debugging a solved crash | delete | [01](01-revert-dead-code.md) |
|
||||
| ~600 lines of CMake reindent/duplication | wrap-and-reindent instead of additive | de-churn | [02](02-cmake-dechurn.md) |
|
||||
| zoom warp, Backspace, timer, kiface init | `#ifdef` behavior changes | runtime config | [03](03-config-not-code.md) |
|
||||
| fontconfig/libcontext/SpaceMouse stubs | in-file `#ifdef` | move to new TUs | [04](04-stub-tu-relocation.md) |
|
||||
| scale factor, selection, header hygiene | wx-port quirks patched in KiCad | fix in wx fork | [05](05-wx-layer-fixes.md) |
|
||||
| RTree fix, hotkey bug, `wxUSE_*` guards | upstreamable | send upstream | [06](06-upstreamable-patches.md) |
|
||||
| 6 native-build regressions + diff tooling | fork bugs | fix | [07](07-native-build-bugs-and-tooling.md) |
|
||||
|
||||
### Re-enable (web-feasible — mostly deletes gates)
|
||||
|
||||
| Item | Blocker today | Verdict | Doc |
|
||||
|---|---|---|---|
|
||||
| Altium importer (sch+pcb) | stale exclusion (fix already active) | **re-enable now** | [08](08-importers.md) |
|
||||
| Eagle/CADSTAR/LTspice/EasyEDA(Pro) sch | MVP-scoping exclusion | **re-enable now** | [08](08-importers.md) |
|
||||
| Symbol chooser + viewer | empty lib tables (asset gap) | un-gate + asset pipeline | [09](09-symbol-libraries.md) |
|
||||
| 3D viewer + render job + VRML export | `KICAD_BUILD_3D_VIEWER_WASM=OFF` + gates | port (raytracer first) | [10](10-3d-viewer.md) |
|
||||
| SPICE simulator | ngspice dep stubbed | port (~1–2 wk) | [11](11-ngspice-simulator.md) |
|
||||
| HTTP libraries / local history | curl & libgit2 stubbed | port | [12](12-network-stack.md) |
|
||||
| Tooltips | wxUniversal never implemented them | port in wx fork | [05](05-wx-layer-fixes.md) |
|
||||
|
||||
### Keep off
|
||||
|
||||
- **Impossible:** SpaceMouse/navlib, ODBC database, nng/IPC transport, fswatcher, webview,
|
||||
dynamic KIFACE `dlopen`, OS keychain, pointer warping. (See [12](12-network-stack.md) for
|
||||
the full catalog and *why* each is impossible.)
|
||||
- **Policy-off:** Python scripting (see [`../../../features/python/research.md`](../../../features/python/research.md)),
|
||||
PCM, update check, the `kicad` project-manager / `cvpcb` apps (never wasm targets).
|
||||
|
||||
## Suggested sequencing
|
||||
|
||||
1. **Quick wins + dead-code reverts** ([01](01-revert-dead-code.md), [07](07-native-build-bugs-and-tooling.md),
|
||||
[08](08-importers.md)) — one build, one e2e run; large diff reduction *and* new
|
||||
importers. Importers are configure-confident but runtime-untested → smoke-test with a
|
||||
sample Eagle + Altium file.
|
||||
2. **3D viewer Route C** ([10](10-3d-viewer.md)) — raytracer + blit; brings render job and
|
||||
VRML export back nearly free.
|
||||
3. **Symbol-library asset pipeline** ([09](09-symbol-libraries.md)).
|
||||
4. **CMake de-churn + config-not-code + stub relocation + wx fixes** ([02](02-cmake-dechurn.md)–[05](05-wx-layer-fixes.md))
|
||||
— the bulk of the remaining line-count reduction.
|
||||
5. **Upstream PRs** ([06](06-upstreamable-patches.md)) — divergence that vanishes on merge.
|
||||
6. **3D Route B (WebGL2) and Tier-3 ports** ([10](10-3d-viewer.md)–[12](12-network-stack.md)) per product priority.
|
||||
|
||||
## Document index
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| [01-revert-dead-code.md](01-revert-dead-code.md) | Diff that compiles only in unused configs: IPC-API gates, `kiglew.h`, `opengl_gal.cpp`, diagnostics. ~480 lines, zero behavior change. |
|
||||
| [02-cmake-dechurn.md](02-cmake-dechurn.md) | ~600 lines of CMake reindent/duplication → early-return guards, `list(REMOVE_ITEM)`, shader-hook, relocate `if(EMSCRIPTEN)` to `cmake/wasm/`. |
|
||||
| [03-config-not-code.md](03-config-not-code.md) | Patches that re-implement existing settings: zoom pref, hotkeys file, `HAVE_CLOCK_GETTIME`, kiface init from the shell. |
|
||||
| [04-stub-tu-relocation.md](04-stub-tu-relocation.md) | Move in-file `#else` stubs to new translation units: fontconfig, libcontext, SpaceMouse. |
|
||||
| [05-wx-layer-fixes.md](05-wx-layer-fixes.md) | KiCad patches that belong in the wxWidgets wasm port: scale factor, selection, header self-sufficiency, **tooltips**. |
|
||||
| [06-upstreamable-patches.md](06-upstreamable-patches.md) | Bug fixes & portability guards to send to KiCad/wxWidgets upstream so the diff disappears on merge. |
|
||||
| [07-native-build-bugs-and-tooling.md](07-native-build-bugs-and-tooling.md) | 6 regressions the fork introduced into *native* builds + dead build-script flags + the broken `kicad-diff-stats.sh`. |
|
||||
| [08-importers.md](08-importers.md) | Re-enable Altium + Eagle/CADSTAR/LTspice/EasyEDA(Pro). Net-negative diff. |
|
||||
| [09-symbol-libraries.md](09-symbol-libraries.md) | Un-gate the symbol chooser/viewer + ship a starter library set to the browser FS. |
|
||||
| [10-3d-viewer.md](10-3d-viewer.md) | Why it's off; Route C (CPU raytracer), Route B (WebGL2 port), Route A (rejected); model loading; render job; VRML export. |
|
||||
| [11-ngspice-simulator.md](11-ngspice-simulator.md) | Static-link a wasm ngspice + the one `init_dll` branch; retest the model-data stubs. |
|
||||
| [12-network-stack.md](12-network-stack.md) | curl→fetch shim, libgit2/local-history, and the catalog of genuinely-impossible features. |
|
||||
|
||||
## Related docs
|
||||
|
||||
- [`../async/README.md`](../async/README.md) — the Asyncify model these gates dance around.
|
||||
- [`../wasm-exceptions/README.md`](../wasm-exceptions/README.md) — the EH-model work that shrinks the binary.
|
||||
- [`../libraries/0001-library-management.md`](../libraries/0001-library-management.md) — why designs open without libraries (background for [09](09-symbol-libraries.md)).
|
||||
- [`../../../features/python/research.md`](../../../features/python/research.md) — Python re-enable research (stays off; IPC API is the mainline path).
|
||||
- [`../../../features/gl-article/README.md`](../../../features/gl-article/README.md) — the OpenGL→WebGL GAL migration history (context for [10](10-3d-viewer.md)).
|
||||
Loading…
Reference in a new issue