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

6.5 KiB
Raw Blame History

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:

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):

# 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 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.