pcbjam/docs/features/fork-cleanup/02-cmake-dechurn.md
Istvan Matejcsok c35005589d refactor(cmake): batch F (gerbview/pl_editor #5 + navlib #6) + docs
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>
2026-06-22 18:50:08 +02:00

120 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 02 — CMake de-churn
> **Status — the in-place de-dup pass (batches AF) 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
> **3540% 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 **120180** 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
13 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 17 alone cut the build-system diff from ~1,600 to roughly **500600** lines; adding
the `cmake/wasm/` relocation drops the lines touched *inside upstream files* to roughly
**120180**. 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.