Bumps kicad to 6f82742e68 (in-place CMake de-dup pass A-F complete) and updates the fork-cleanup docs: CMake churn 1,702 -> 1,019, build-graph proven byte-identical pre/post (zero behavior change), only Phase-B cmake/wasm relocation remaining. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
120 lines
6.5 KiB
Markdown
120 lines
6.5 KiB
Markdown
# 02 — CMake de-churn
|
||
|
||
> **Status — the in-place de-dup pass (batches A–F) is COMPLETE** (kicad `6f82742e68` on `b5ac6dcbe4`,
|
||
> root `0b4d830`): Move 0 (`KICAD_WASM_LAYER` var) + moves #1–#7 across all apps, incl. #5 for
|
||
> gerbview/pl_editor and #6 (navlib, behavior-preserving stub de-churn). **Not yet done:** only the
|
||
> `cmake/wasm/` **relocation (Phase B)**. CMake churn: **1,702 → 1,019** (−683), validated by an `-O1`
|
||
> WASM build (pcbnew/eeschema/calculator) + 9/9 e2e with no screenshot change, **and a build-graph
|
||
> equivalence proof** (compile + link + custom commands byte-identical pre/post across the whole tree) →
|
||
> zero behavior change. The recipes below describe the full design (Phase-B relocation still pending).
|
||
|
||
> 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.
|