Initial project setup for KiCad WebAssembly port
- Add KiCad fork as git submodule - Create project structure (patches, stubs, cmake, scripts, core, docs) - Add knowledge base and implementation plan documentation - Add README with project overview and goals 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
2d7c26feac
7 changed files with 1405 additions and 0 deletions
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Build directories
|
||||||
|
build/
|
||||||
|
build-*/
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Compiled objects
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# WebAssembly output
|
||||||
|
*.wasm
|
||||||
|
*.js.map
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Emscripten cache
|
||||||
|
.emscripten_cache/
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "kicad"]
|
||||||
|
path = kicad
|
||||||
|
url = git@github.com:VV-EE/kicad-source-mirror.git
|
||||||
55
README.md
Normal file
55
README.md
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
# KiCad WebAssembly Port
|
||||||
|
|
||||||
|
Experimental project to run KiCad's core logic in WebAssembly.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
kicad-wasm/
|
||||||
|
├── kicad/ # KiCad source (git submodule)
|
||||||
|
├── patches/ # Patches to make deps optional
|
||||||
|
├── stubs/ # Stub headers for disabled deps
|
||||||
|
├── cmake/ # CMake modules
|
||||||
|
├── scripts/ # Build and maintenance scripts
|
||||||
|
├── core/ # Extracted core library for Wasm
|
||||||
|
└── docs/ # Knowledge base and plans
|
||||||
|
```
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
1. **Phase 1**: Build KiCad with optional deps disabled (curl, git, OCC, ngspice)
|
||||||
|
2. **Phase 2**: Extract core computation code as standalone library
|
||||||
|
3. **Phase 3**: Compile core to WebAssembly
|
||||||
|
4. **Phase 4**: Run native GUI with Wasm worker backend
|
||||||
|
5. **Phase 5**: Browser-based UI
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Implementation Plan](docs/IMPLEMENTATION_PLAN.md)
|
||||||
|
- [Knowledge Base (Summary)](docs/KNOWLEDGE_BASE.md)
|
||||||
|
- [Knowledge Base (Full)](docs/KNOWLEDGE_BASE_FULL.md)
|
||||||
|
|
||||||
|
## Design Decisions
|
||||||
|
|
||||||
|
- **Memory**: Serialize/deserialize on every operation (proof of concept)
|
||||||
|
- **Threading**: Web Workers (browser-first design)
|
||||||
|
- **Updates**: Full board re-serialization
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone with submodules
|
||||||
|
git clone --recursive <repo-url>
|
||||||
|
|
||||||
|
# Apply patches
|
||||||
|
./scripts/prepare.sh
|
||||||
|
|
||||||
|
# Build with optional deps disabled
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DKICAD_USE_CURL=OFF -DKICAD_USE_GIT=OFF -DKICAD_USE_OCC=OFF
|
||||||
|
make -j$(nproc)
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
KiCad is GPL-3.0. This wrapper/tooling follows the same license.
|
||||||
335
docs/IMPLEMENTATION_PLAN.md
Normal file
335
docs/IMPLEMENTATION_PLAN.md
Normal file
|
|
@ -0,0 +1,335 @@
|
||||||
|
# KiCad Wasm Port - Implementation Plan
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Run KiCad with native wxWidgets GUI, but with core logic (file parsing, geometry, DRC, routing) executing in a WebAssembly module. This validates the Wasm build before tackling the browser UI.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: Minimal Build with Stubs
|
||||||
|
|
||||||
|
**Objective**: Get KiCad compiling with optional deps disabled via preprocessor guards.
|
||||||
|
|
||||||
|
### 1.1 Create Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
kicad-wasm/
|
||||||
|
├── kicad/ # Git submodule → upstream KiCad
|
||||||
|
├── patches/
|
||||||
|
│ └── 0001-optional-deps.patch
|
||||||
|
├── stubs/
|
||||||
|
│ └── include/
|
||||||
|
│ ├── git2.h # Minimal stub headers
|
||||||
|
│ └── curl/curl.h
|
||||||
|
├── cmake/
|
||||||
|
│ └── KicadWasmOptions.cmake
|
||||||
|
├── CMakeLists.txt
|
||||||
|
└── scripts/
|
||||||
|
├── prepare.sh # Apply patches
|
||||||
|
└── update-kicad.sh # Update to new KiCad version
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 Create the Patch
|
||||||
|
|
||||||
|
Add CMake options to `CMakeLists.txt` (after line 107):
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
option( KICAD_USE_CURL "Enable network features" ON )
|
||||||
|
option( KICAD_USE_GIT "Enable git integration" ON )
|
||||||
|
option( KICAD_USE_OCC "Enable OpenCASCADE for STEP" ON )
|
||||||
|
option( KICAD_USE_NGSPICE "Enable SPICE simulation" ON )
|
||||||
|
option( KICAD_USE_DATABASE "Enable database libraries" ON )
|
||||||
|
```
|
||||||
|
|
||||||
|
Wrap `find_package` calls conditionally:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
if( KICAD_USE_CURL )
|
||||||
|
find_package( CURL REQUIRED )
|
||||||
|
add_compile_definitions( KICAD_USE_CURL )
|
||||||
|
else()
|
||||||
|
add_library( CURL::libcurl INTERFACE IMPORTED )
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 Create Stub Headers
|
||||||
|
|
||||||
|
Minimal headers that let code compile without the actual libraries:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// stubs/include/git2.h
|
||||||
|
#pragma once
|
||||||
|
typedef struct git_repository git_repository;
|
||||||
|
// Stub functions return error codes
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.4 Add Preprocessor Guards to Source
|
||||||
|
|
||||||
|
Wrap implementations in `common/git/*.cpp`, `common/kicad_curl/*.cpp`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef KICAD_USE_GIT
|
||||||
|
// actual implementation
|
||||||
|
#else
|
||||||
|
// return error or throw "feature disabled"
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.5 Verify Native Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd kicad-wasm
|
||||||
|
./scripts/prepare.sh
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DKICAD_USE_CURL=OFF -DKICAD_USE_GIT=OFF -DKICAD_USE_OCC=OFF
|
||||||
|
make -j$(nproc)
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirm KiCad launches and can open/edit PCB files (without git/network/STEP features).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: Extract Core Library
|
||||||
|
|
||||||
|
**Objective**: Build core computation code as a standalone library that can be compiled to both native and Wasm.
|
||||||
|
|
||||||
|
### 2.1 Identify Core Components
|
||||||
|
|
||||||
|
Create `kicad-wasm/core/CMakeLists.txt` targeting:
|
||||||
|
|
||||||
|
| Component | Source Location | Notes |
|
||||||
|
|-----------|-----------------|-------|
|
||||||
|
| Math/Geometry | `libs/kimath/` | Pure C++, no deps |
|
||||||
|
| Core utilities | `libs/core/` | Pure C++ |
|
||||||
|
| KiCad file parser | `common/io/kicad/` | Needs minimal deps |
|
||||||
|
| S-expression parser | `libs/sexpr/` | Pure C++ |
|
||||||
|
| Board data model | `pcbnew/board*.cpp` | Extract carefully |
|
||||||
|
|
||||||
|
### 2.2 Define API Boundary
|
||||||
|
|
||||||
|
Create a C API for the core (easier Wasm interop than C++):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// kicad-wasm/core/include/kicad_core_api.h
|
||||||
|
extern "C" {
|
||||||
|
// File operations
|
||||||
|
void* kicad_load_pcb(const char* data, size_t len);
|
||||||
|
void kicad_free_pcb(void* board);
|
||||||
|
char* kicad_serialize_pcb(void* board);
|
||||||
|
|
||||||
|
// Query
|
||||||
|
int kicad_get_track_count(void* board);
|
||||||
|
|
||||||
|
// Modification
|
||||||
|
void kicad_add_track(void* board, /* params */);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 Build Core as Static Library
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# kicad-wasm/core/CMakeLists.txt
|
||||||
|
add_library(kicad_core STATIC
|
||||||
|
${KIMATH_SOURCES}
|
||||||
|
${SEXPR_SOURCES}
|
||||||
|
${IO_KICAD_SOURCES}
|
||||||
|
api/kicad_core_api.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(kicad_core PRIVATE
|
||||||
|
KICAD_CORE_ONLY=1
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: Compile Core to WebAssembly
|
||||||
|
|
||||||
|
**Objective**: Build `kicad_core.wasm` using Emscripten.
|
||||||
|
|
||||||
|
### 3.1 Emscripten Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source /path/to/emsdk/emsdk_env.sh
|
||||||
|
|
||||||
|
cd kicad-wasm
|
||||||
|
mkdir build-wasm && cd build-wasm
|
||||||
|
|
||||||
|
emcmake cmake ../core \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DKICAD_WASM_BUILD=ON
|
||||||
|
|
||||||
|
emmake make
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Export Functions
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# For Emscripten
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
set_target_properties(kicad_core PROPERTIES
|
||||||
|
LINK_FLAGS "-s EXPORTED_FUNCTIONS='[_kicad_load_pcb,_kicad_free_pcb,...]' \
|
||||||
|
-s EXPORTED_RUNTIME_METHODS='[ccall,cwrap]' \
|
||||||
|
-s MODULARIZE=1 \
|
||||||
|
-s EXPORT_NAME='KicadCore'"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Test Wasm Module
|
||||||
|
|
||||||
|
Create a simple test that loads a `.kicad_pcb` file:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// test/test_core.mjs
|
||||||
|
import KicadCore from './kicad_core.js';
|
||||||
|
|
||||||
|
const core = await KicadCore();
|
||||||
|
const pcbData = fs.readFileSync('test.kicad_pcb', 'utf8');
|
||||||
|
const board = core.ccall('kicad_load_pcb', 'number', ['string', 'number'],
|
||||||
|
[pcbData, pcbData.length]);
|
||||||
|
console.log('Track count:', core.ccall('kicad_get_track_count', 'number', ['number'], [board]));
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Native App with Wasm Worker
|
||||||
|
|
||||||
|
**Objective**: Run native KiCad GUI but delegate core operations to the Wasm module.
|
||||||
|
|
||||||
|
### 4.1 Choose Wasm Runtime
|
||||||
|
|
||||||
|
Options for running Wasm in native app:
|
||||||
|
- **Wasmtime** - Rust-based, mature, good C API
|
||||||
|
- **wasm3** - Small, fast interpreter
|
||||||
|
- **WAMR** - WebAssembly Micro Runtime, lightweight
|
||||||
|
|
||||||
|
Recommend: **Wasmtime** for development (better debugging), **wasm3** for size.
|
||||||
|
|
||||||
|
### 4.2 Create Wasm Bridge
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// kicad-wasm/bridge/wasm_bridge.h
|
||||||
|
class WasmBridge {
|
||||||
|
public:
|
||||||
|
WasmBridge(const std::string& wasmPath);
|
||||||
|
|
||||||
|
BOARD* LoadPCB(const std::string& data);
|
||||||
|
std::string SerializePCB(BOARD* board);
|
||||||
|
void RunDRC(BOARD* board);
|
||||||
|
|
||||||
|
private:
|
||||||
|
wasmtime_instance_t* m_instance;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 Integrate with KiCad
|
||||||
|
|
||||||
|
Modify KiCad to optionally use the Wasm bridge:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// In pcbnew loading code
|
||||||
|
#ifdef USE_WASM_CORE
|
||||||
|
auto board = WasmBridge::Get().LoadPCB(fileContent);
|
||||||
|
#else
|
||||||
|
auto board = IO_KICAD::Load(filename);
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 Validate Correctness
|
||||||
|
|
||||||
|
1. Load same PCB file via native code and via Wasm bridge
|
||||||
|
2. Compare serialized output (should be identical)
|
||||||
|
3. Run DRC via both paths, compare results
|
||||||
|
4. Profile performance difference
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5: Incremental Migration
|
||||||
|
|
||||||
|
**Objective**: Move more functionality to Wasm core, validate stability.
|
||||||
|
|
||||||
|
### Priority Order
|
||||||
|
|
||||||
|
1. **File I/O** - parsing and serialization
|
||||||
|
2. **DRC engine** - computationally intensive, isolated
|
||||||
|
3. **Router** - Push & Shove algorithms
|
||||||
|
4. **ERC** - schematic checks
|
||||||
|
|
||||||
|
### Validation Strategy
|
||||||
|
|
||||||
|
For each migrated component:
|
||||||
|
1. Keep both native and Wasm implementations
|
||||||
|
2. Add flag to switch between them
|
||||||
|
3. Run test suite with both
|
||||||
|
4. Benchmark performance
|
||||||
|
5. Remove native implementation once confident
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Milestones
|
||||||
|
|
||||||
|
| Milestone | Deliverable | Validation |
|
||||||
|
|-----------|-------------|------------|
|
||||||
|
| M1 | KiCad builds with deps disabled | Opens PCB files, basic editing works |
|
||||||
|
| M2 | Core library extracts cleanly | Compiles as standalone static lib |
|
||||||
|
| M3 | Core compiles to Wasm | Passes unit tests via Node.js |
|
||||||
|
| M4 | Native app loads Wasm worker | Can load/save PCB via Wasm bridge |
|
||||||
|
| M5 | DRC runs in Wasm | Results match native DRC |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Design Decisions
|
||||||
|
|
||||||
|
### Memory Management
|
||||||
|
|
||||||
|
**Decision**: Serialize/deserialize on every operation
|
||||||
|
|
||||||
|
- Proof of concept - simplicity over performance
|
||||||
|
- Clean interface between GUI and Wasm core
|
||||||
|
- Easy to debug
|
||||||
|
- Browser-friendly (no shared memory complexity)
|
||||||
|
- Can optimize later if needed
|
||||||
|
|
||||||
|
```
|
||||||
|
GUI Wasm Core
|
||||||
|
│ │
|
||||||
|
│──serialize(board)─────────────▶│
|
||||||
|
│ │──process
|
||||||
|
│◀─────────────serialize(board)──│
|
||||||
|
│ │
|
||||||
|
```
|
||||||
|
|
||||||
|
### Threading Model
|
||||||
|
|
||||||
|
**Decision**: Web Workers
|
||||||
|
|
||||||
|
- Target is browser, design for it from the start
|
||||||
|
- Each heavy operation (DRC, routing) runs in dedicated worker
|
||||||
|
- Clean message-passing interface
|
||||||
|
- No shared memory complexity
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Main thread spawns workers for heavy operations
|
||||||
|
const drcWorker = new Worker('drc-worker.js');
|
||||||
|
drcWorker.postMessage({ board: serializedBoard });
|
||||||
|
drcWorker.onmessage = (e) => updateUI(e.data.violations);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Incremental Updates
|
||||||
|
|
||||||
|
**Decision**: Re-serialize entire board
|
||||||
|
|
||||||
|
- Simple for proof of concept
|
||||||
|
- Board files typically <10MB, acceptable latency
|
||||||
|
- Can add delta operations later if performance requires it
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Fork KiCad repo, set up as submodule
|
||||||
|
2. Write the minimal patch for optional deps
|
||||||
|
3. Create stub headers
|
||||||
|
4. Verify native build with features disabled
|
||||||
|
5. Begin core library extraction
|
||||||
136
docs/KNOWLEDGE_BASE.md
Normal file
136
docs/KNOWLEDGE_BASE.md
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
# KiCad WebAssembly Port - Knowledge Base
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
KiCad is a modular EDA suite with these main components:
|
||||||
|
- **Project Manager** (`kicad/`) - launches other tools
|
||||||
|
- **PCB Editor** (`pcbnew/`) - board layout
|
||||||
|
- **Schematic Editor** (`eeschema/`) - circuit design
|
||||||
|
- **3D Viewer** (`3d-viewer/`) - 3D visualization
|
||||||
|
|
||||||
|
Shared code lives in:
|
||||||
|
- `common/` - shared library (kicommon), includes GUI, I/O, git, curl
|
||||||
|
- `libs/core/` - utilities
|
||||||
|
- `libs/kimath/` - geometry and math (pure C++, no deps)
|
||||||
|
|
||||||
|
## Key Dependencies
|
||||||
|
|
||||||
|
| Dependency | Purpose | Wasm Strategy |
|
||||||
|
|------------|---------|---------------|
|
||||||
|
| **wxWidgets** | All GUI | Keep native initially; replace with web UI later |
|
||||||
|
| **OpenGL** | 2D rendering via GAL | WebGL (Emscripten handles this) |
|
||||||
|
| **Cairo** | Fallback 2D rendering | Compile with Emscripten or skip |
|
||||||
|
| **OpenCASCADE** | STEP import/export, 3D | Disable for MVP; huge (~40MB) |
|
||||||
|
| **libcurl** | PCM, update check, HTTP libs | Stub out; replace with Fetch API |
|
||||||
|
| **libgit2** | Version control integration | Stub out; optional feature |
|
||||||
|
| **ngspice** | Circuit simulation | Stub out; separate concern |
|
||||||
|
| **nanoodbc** | Database libraries | Stub out; enterprise feature |
|
||||||
|
| **Freetype/HarfBuzz** | Font rendering | Compile with Emscripten (works) |
|
||||||
|
| **Boost** | Locale, unit tests | Minimize; locale needed for nanoodbc only |
|
||||||
|
|
||||||
|
## Graphics Abstraction Layer (GAL)
|
||||||
|
|
||||||
|
Location: `common/gal/`, `include/gal/`
|
||||||
|
|
||||||
|
KiCad abstracts rendering through GAL with two backends:
|
||||||
|
- `OPENGL_GAL` (`common/gal/opengl/`) - primary, uses GLSL shaders
|
||||||
|
- `CAIRO_GAL` (`common/gal/cairo/`) - fallback, vector graphics
|
||||||
|
|
||||||
|
Key files:
|
||||||
|
- `include/gal/graphics_abstraction_layer.h` - base interface
|
||||||
|
- `common/gal/opengl/opengl_gal.cpp` - OpenGL implementation
|
||||||
|
- `common/gal/shaders/` - GLSL shaders (need ES conversion for WebGL)
|
||||||
|
|
||||||
|
For Wasm: OpenGL ES subset via Emscripten maps to WebGL. Shaders need `#version` removal and precision qualifiers.
|
||||||
|
|
||||||
|
## File I/O System
|
||||||
|
|
||||||
|
Location: `common/io/`, `include/io/`
|
||||||
|
|
||||||
|
Plugin-based architecture supporting multiple formats:
|
||||||
|
- KiCad native (`.kicad_pcb`, `.kicad_sch`)
|
||||||
|
- Eagle, Altium, CADSTAR, EasyEDA imports
|
||||||
|
|
||||||
|
Key class: `IO_BASE` in `include/io/io_base.h`
|
||||||
|
|
||||||
|
Parsers are mostly pure C++ - good candidates for Wasm core.
|
||||||
|
|
||||||
|
## Python Scripting
|
||||||
|
|
||||||
|
Location: `scripting/`, `pcbnew/python/`
|
||||||
|
|
||||||
|
Uses SWIG to generate CPython bindings (~3,500 lines of `.i` files).
|
||||||
|
|
||||||
|
For Wasm: SWIG bindings won't work. Options:
|
||||||
|
1. Use Emscripten's `embind` instead
|
||||||
|
2. Use Pyodide with custom FFI
|
||||||
|
3. Skip Python for MVP
|
||||||
|
|
||||||
|
## Optional Features to Disable
|
||||||
|
|
||||||
|
These have minimal impact on core editing functionality:
|
||||||
|
|
||||||
|
| Feature | CMake Area | Files |
|
||||||
|
|---------|-----------|-------|
|
||||||
|
| Git integration | `common/git/` | 15 handler files |
|
||||||
|
| Network (PCM, updates) | `common/kicad_curl/`, `common/http_lib/` | ~5 files |
|
||||||
|
| Database libraries | `common/database/` | 2-3 files |
|
||||||
|
| STEP/3D export | `pcbnew/exporters/step/`, `plugins/3d/oce/` | Isolated |
|
||||||
|
| SPICE simulation | `eeschema/sim/` | Isolated subsystem |
|
||||||
|
|
||||||
|
## Build System Notes
|
||||||
|
|
||||||
|
Main CMake: `CMakeLists.txt`
|
||||||
|
|
||||||
|
Currently all deps are REQUIRED (lines 820-892). No options exist to disable curl/git/OCC.
|
||||||
|
|
||||||
|
Libraries link in `common/CMakeLists.txt:316-343`:
|
||||||
|
```cmake
|
||||||
|
target_link_libraries( kicommon
|
||||||
|
CURL::libcurl
|
||||||
|
${LIBGIT2_LIBRARIES}
|
||||||
|
...
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## IPC/Communication
|
||||||
|
|
||||||
|
`KIWAY` system (`include/kiway.h`, `include/kiway_holder.h`) handles inter-frame communication. Frames inherit from `KIWAY_PLAYER`.
|
||||||
|
|
||||||
|
For Wasm worker architecture: This could be adapted for message-passing between native GUI and Wasm worker.
|
||||||
|
|
||||||
|
## Potential Problem Areas
|
||||||
|
|
||||||
|
1. **Threading**: KiCad uses threads for DRC, rendering. Wasm has Web Workers but different threading model.
|
||||||
|
|
||||||
|
2. **File dialogs**: `wxFileDialog` throughout - needs abstraction for browser File API.
|
||||||
|
|
||||||
|
3. **Memory**: Large boards can use 1GB+. Wasm has 4GB limit, but browser tabs may have lower practical limits.
|
||||||
|
|
||||||
|
4. **Clipboard**: Native clipboard integration in multiple places.
|
||||||
|
|
||||||
|
5. **Printing**: Cairo-based printing system won't work in browser.
|
||||||
|
|
||||||
|
## Files of Interest for Core Extraction
|
||||||
|
|
||||||
|
Pure computation, no GUI deps - good Wasm candidates:
|
||||||
|
- `libs/kimath/` - all geometry code
|
||||||
|
- `libs/core/` - utilities
|
||||||
|
- `common/io/kicad/` - native format parser
|
||||||
|
- `pcbnew/router/` - Push & Shove routing algorithms
|
||||||
|
- `pcbnew/drc/` - Design Rule Check engine
|
||||||
|
- `eeschema/erc/` - Electrical Rule Check
|
||||||
|
|
||||||
|
## Reference Paths
|
||||||
|
|
||||||
|
| Component | Path |
|
||||||
|
|-----------|------|
|
||||||
|
| Main CMake | `CMakeLists.txt` |
|
||||||
|
| Common library | `common/CMakeLists.txt` |
|
||||||
|
| GAL system | `common/gal/`, `include/gal/` |
|
||||||
|
| File I/O | `common/io/` |
|
||||||
|
| PCB data model | `pcbnew/board.h`, `pcbnew/footprint.h` |
|
||||||
|
| Git integration | `common/git/` |
|
||||||
|
| Curl wrapper | `common/kicad_curl/` |
|
||||||
|
| Python bindings | `scripting/`, `pcbnew/python/swig/` |
|
||||||
|
| 3D/STEP | `pcbnew/exporters/step/`, `3d-viewer/` |
|
||||||
846
docs/KNOWLEDGE_BASE_FULL.md
Normal file
846
docs/KNOWLEDGE_BASE_FULL.md
Normal file
|
|
@ -0,0 +1,846 @@
|
||||||
|
# KiCad WebAssembly Port - Complete Knowledge Base
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
1. [Architecture Overview](#architecture-overview)
|
||||||
|
2. [Dependencies Deep Dive](#dependencies-deep-dive)
|
||||||
|
3. [Graphics System (GAL)](#graphics-system-gal)
|
||||||
|
4. [File I/O System](#file-io-system)
|
||||||
|
5. [Python Scripting](#python-scripting)
|
||||||
|
6. [Build System](#build-system)
|
||||||
|
7. [Features to Disable](#features-to-disable)
|
||||||
|
8. [Code Extraction Candidates](#code-extraction-candidates)
|
||||||
|
9. [Technical Challenges](#technical-challenges)
|
||||||
|
10. [Design Decisions](#design-decisions)
|
||||||
|
11. [File Reference](#file-reference)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
### Main Applications
|
||||||
|
|
||||||
|
| Application | Directory | Purpose |
|
||||||
|
|-------------|-----------|---------|
|
||||||
|
| `kicad` | `kicad/` | Project manager, launcher |
|
||||||
|
| `pcbnew` | `pcbnew/` | PCB layout editor |
|
||||||
|
| `eeschema` | `eeschema/` | Schematic capture |
|
||||||
|
| `gerbview` | `gerbview/` | Gerber file viewer |
|
||||||
|
| `cvpcb` | `cvpcb/` | Component-footprint association |
|
||||||
|
| `bitmap2component` | `bitmap2component/` | Image to footprint converter |
|
||||||
|
| `pcb_calculator` | `pcb_calculator/` | Engineering calculators |
|
||||||
|
| `pagelayout_editor` | `pagelayout_editor/` | Drawing sheet editor |
|
||||||
|
| `kicad-cli` | `kicad/cli/` | Command-line interface |
|
||||||
|
|
||||||
|
### Shared Libraries
|
||||||
|
|
||||||
|
| Library | Location | Purpose |
|
||||||
|
|---------|----------|---------|
|
||||||
|
| `kicommon` | `common/` | Shared UI, I/O, utilities (SHARED lib) |
|
||||||
|
| `kigal` | `common/gal/` | Graphics Abstraction Layer (SHARED lib) |
|
||||||
|
| `kimath` | `libs/kimath/` | Geometry and math (STATIC lib) |
|
||||||
|
| `core` | `libs/core/` | Base utilities (STATIC lib) |
|
||||||
|
| `sexpr` | `libs/sexpr/` | S-expression parser (STATIC lib) |
|
||||||
|
| `kiplatform` | `libs/kiplatform/` | Platform abstraction |
|
||||||
|
|
||||||
|
### Plugin Architecture (KIFACE)
|
||||||
|
|
||||||
|
Each major application is built as both:
|
||||||
|
- Standalone executable
|
||||||
|
- KIFACE module (`.kiface` on Linux/Mac, `.dll` on Windows)
|
||||||
|
|
||||||
|
This allows:
|
||||||
|
- Standalone operation
|
||||||
|
- Project manager integration via dynamic loading
|
||||||
|
|
||||||
|
Key files:
|
||||||
|
- `include/kiway.h` - KIWAY system for inter-module communication
|
||||||
|
- `include/kiway_holder.h` - Mixin for frames that participate in KIWAY
|
||||||
|
- `include/kiway_player.h` - Frame base class (`KIWAY_PLAYER : public wxFrame`)
|
||||||
|
|
||||||
|
### Frame Hierarchy
|
||||||
|
|
||||||
|
```
|
||||||
|
wxFrame
|
||||||
|
└── KIWAY_PLAYER (include/kiway_player.h)
|
||||||
|
└── EDA_BASE_FRAME (include/eda_base_frame.h)
|
||||||
|
├── PCB_BASE_FRAME (pcbnew/)
|
||||||
|
│ └── PCB_EDIT_FRAME
|
||||||
|
├── SCH_BASE_FRAME (eeschema/)
|
||||||
|
│ └── SCH_EDIT_FRAME
|
||||||
|
└── ...other frames
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependencies Deep Dive
|
||||||
|
|
||||||
|
### wxWidgets (GUI Framework)
|
||||||
|
|
||||||
|
**Version**: 3.2.0+
|
||||||
|
**Components used**: `gl aui adv html core net base propgrid xml stc richtext webview`
|
||||||
|
**Location**: Found via `find_package(wxWidgets)` in `CMakeLists.txt:1089`
|
||||||
|
|
||||||
|
KiCad requires GTK3 port on Linux. All GUI code depends on wxWidgets.
|
||||||
|
|
||||||
|
Key wxWidgets classes used:
|
||||||
|
- `wxFrame`, `wxDialog`, `wxPanel` - windows
|
||||||
|
- `wxGLCanvas` - OpenGL context
|
||||||
|
- `wxFileDialog` - file selection
|
||||||
|
- `wxAuiManager` - dockable panes
|
||||||
|
- `wxPropertyGrid` - property editors
|
||||||
|
|
||||||
|
**Wasm strategy**: Keep native initially. Eventually replace with web framework (React/Vue/Svelte).
|
||||||
|
|
||||||
|
### OpenGL / GLEW
|
||||||
|
|
||||||
|
**Purpose**: Hardware-accelerated 2D rendering via GAL
|
||||||
|
**Location**: `common/gal/opengl/`
|
||||||
|
|
||||||
|
Uses OpenGL 2.1+ with shaders. GLEW handles extension loading.
|
||||||
|
|
||||||
|
**Wasm strategy**: Emscripten maps OpenGL ES to WebGL automatically. Need to:
|
||||||
|
- Use OpenGL ES subset
|
||||||
|
- Convert shaders to GLSL ES (remove `#version`, add `precision` qualifiers)
|
||||||
|
|
||||||
|
### Cairo
|
||||||
|
|
||||||
|
**Version**: 1.12+
|
||||||
|
**Purpose**: Software 2D rendering fallback, printing, PDF export
|
||||||
|
**Location**: `common/gal/cairo/`
|
||||||
|
|
||||||
|
**Wasm strategy**: Can compile Cairo with Emscripten. Or skip for MVP (OpenGL-only).
|
||||||
|
|
||||||
|
### OpenCASCADE (OCC/OCCT)
|
||||||
|
|
||||||
|
**Version**: 7.5.0+
|
||||||
|
**Purpose**:
|
||||||
|
- STEP file import/export (mechanical CAD interchange)
|
||||||
|
- 3D model loading for component visualization
|
||||||
|
- Boolean operations on 3D geometry
|
||||||
|
|
||||||
|
**Files using OCC**:
|
||||||
|
- `pcbnew/exporters/step/step_pcb_model.cpp` - STEP export
|
||||||
|
- `pcbnew/exporters/step/exporter_step.cpp` - Export orchestration
|
||||||
|
- `plugins/3d/oce/loadmodel.cpp` - 3D model loading
|
||||||
|
- `plugins/3d/oce/oce.cpp` - Plugin entry point
|
||||||
|
|
||||||
|
**Headers imported** (from `step_pcb_model.cpp`):
|
||||||
|
```cpp
|
||||||
|
#include <IGESCAFControl_Reader.hxx>
|
||||||
|
#include <STEPCAFControl_Reader.hxx>
|
||||||
|
#include <STEPCAFControl_Writer.hxx>
|
||||||
|
#include <TopoDS.hxx>
|
||||||
|
#include <XCAFDoc_ShapeTool.hxx>
|
||||||
|
// ... ~30 more OCC headers
|
||||||
|
```
|
||||||
|
|
||||||
|
**Wasm strategy**: Disable for MVP. OCC is huge (~40MB compiled). Alternative: [opencascade.js](https://github.com/nicholaseasmith/opencascade.js) exists but experimental.
|
||||||
|
|
||||||
|
### libcurl
|
||||||
|
|
||||||
|
**Purpose**: HTTP requests for:
|
||||||
|
1. Plugin Content Manager (PCM) - `kicad/pcm/pcm.cpp`
|
||||||
|
2. Update checker - `kicad/update_manager.cpp`
|
||||||
|
3. HTTP component libraries - `common/http_lib/http_lib_connection.cpp`
|
||||||
|
|
||||||
|
**Wrapper**: `common/kicad_curl/kicad_curl_easy.cpp` (~400 lines)
|
||||||
|
|
||||||
|
**Key class**: `KICAD_CURL_EASY`
|
||||||
|
```cpp
|
||||||
|
class KICAD_CURL_EASY {
|
||||||
|
void SetURL(const std::string& url);
|
||||||
|
void Perform();
|
||||||
|
std::string GetBuffer();
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Wasm strategy**: Stub out. Replace with Emscripten Fetch API or JavaScript fetch via embind.
|
||||||
|
|
||||||
|
### libgit2
|
||||||
|
|
||||||
|
**Version**: 1.5+
|
||||||
|
**Purpose**: Built-in version control for projects
|
||||||
|
|
||||||
|
**Files** (`common/git/`):
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `git_clone_handler.cpp` | Clone repositories |
|
||||||
|
| `git_commit_handler.cpp` | Create commits |
|
||||||
|
| `git_push_handler.cpp` | Push to remote |
|
||||||
|
| `git_pull_handler.cpp` | Pull from remote |
|
||||||
|
| `git_branch_handler.cpp` | Branch management |
|
||||||
|
| `git_status_handler.cpp` | Status display |
|
||||||
|
| `git_revert_handler.cpp` | Revert changes |
|
||||||
|
| `kicad_git_common.cpp` | Common utilities |
|
||||||
|
| `kigit_pcb_merge.cpp` | Custom PCB merge driver |
|
||||||
|
|
||||||
|
**UI integration**:
|
||||||
|
- Project tree shows git status icons
|
||||||
|
- Menus for git operations
|
||||||
|
- Conflict resolution dialogs
|
||||||
|
|
||||||
|
**Wasm strategy**: Stub out entirely. Optional feature. Could use isomorphic-git in browser later.
|
||||||
|
|
||||||
|
### ngspice
|
||||||
|
|
||||||
|
**Purpose**: SPICE circuit simulation in eeschema
|
||||||
|
**Location**: `eeschema/sim/`
|
||||||
|
|
||||||
|
**Wasm strategy**: Stub out. Simulation is a separate concern. Could compile ngspice to Wasm later.
|
||||||
|
|
||||||
|
### nanoodbc (ODBC)
|
||||||
|
|
||||||
|
**Purpose**: Database Libraries feature - fetch component data from SQL databases
|
||||||
|
**Location**: `common/database/database_connection.cpp`
|
||||||
|
|
||||||
|
**What it does**: Connects to external databases (MySQL, PostgreSQL, SQLite, SQL Server) to fetch component information instead of using local `.kicad_sym` files.
|
||||||
|
|
||||||
|
**Enterprise feature** - most users don't use this.
|
||||||
|
|
||||||
|
**Wasm strategy**: Stub out. Would need REST API backend in browser.
|
||||||
|
|
||||||
|
### Boost
|
||||||
|
|
||||||
|
**Version**: 1.71.0+
|
||||||
|
**Components**: `locale`, `unit_test_framework`
|
||||||
|
|
||||||
|
`boost::locale` is used by nanoodbc for Unicode handling.
|
||||||
|
|
||||||
|
**Wasm strategy**: Minimize. If we disable database libraries, we may not need boost::locale.
|
||||||
|
|
||||||
|
### Freetype / HarfBuzz / Fontconfig
|
||||||
|
|
||||||
|
**Purpose**: Text rendering with outline fonts
|
||||||
|
**Versions**: Freetype 2.11.1+, HarfBuzz (any), Fontconfig (any)
|
||||||
|
|
||||||
|
**Location**: `common/font/`
|
||||||
|
|
||||||
|
**Wasm strategy**: Compile with Emscripten. These work. May need to bundle fonts or use browser fonts.
|
||||||
|
|
||||||
|
### Protobuf
|
||||||
|
|
||||||
|
**Purpose**: IPC API for external tool integration
|
||||||
|
**Location**: `api/`
|
||||||
|
|
||||||
|
**Wasm strategy**: Can compile Protobuf to Wasm. Or stub out IPC API for MVP.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Graphics System (GAL)
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ VIEW (common/view/) │
|
||||||
|
│ Manages what's visible, handles zoom │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ PAINTER (include/gal/painter.h) │
|
||||||
|
│ Converts board objects to draw calls │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ GAL (graphics_abstraction_layer) │
|
||||||
|
│ Abstract interface for drawing │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
┌─────────────────┐ ┌─────────────────┐
|
||||||
|
│ OPENGL_GAL │ │ CAIRO_GAL │
|
||||||
|
│ (Hardware accel)│ │ (Software/print)│
|
||||||
|
└─────────────────┘ └─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### GAL Base Class
|
||||||
|
|
||||||
|
**File**: `include/gal/graphics_abstraction_layer.h`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace KIGFX {
|
||||||
|
class GAL : public GAL_DISPLAY_OPTIONS_OBSERVER {
|
||||||
|
// Primitives
|
||||||
|
virtual void DrawLine(const VECTOR2D& start, const VECTOR2D& end);
|
||||||
|
virtual void DrawCircle(const VECTOR2D& center, double radius);
|
||||||
|
virtual void DrawArc(const VECTOR2D& center, double radius, ...);
|
||||||
|
virtual void DrawRectangle(const VECTOR2D& start, const VECTOR2D& end);
|
||||||
|
virtual void DrawPolygon(const std::deque<VECTOR2D>& points);
|
||||||
|
|
||||||
|
// State
|
||||||
|
virtual void SetFillColor(const COLOR4D& color);
|
||||||
|
virtual void SetStrokeColor(const COLOR4D& color);
|
||||||
|
virtual void SetLineWidth(float width);
|
||||||
|
|
||||||
|
// Transformations
|
||||||
|
virtual void Transform(const MATRIX3x3D& matrix);
|
||||||
|
virtual void Translate(const VECTOR2D& translation);
|
||||||
|
virtual void Scale(const VECTOR2D& scale);
|
||||||
|
virtual void Rotate(double angle);
|
||||||
|
|
||||||
|
// Layers
|
||||||
|
virtual void SetLayerDepth(double depth);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### OpenGL GAL
|
||||||
|
|
||||||
|
**Files**:
|
||||||
|
- `include/gal/opengl/opengl_gal.h`
|
||||||
|
- `common/gal/opengl/opengl_gal.cpp`
|
||||||
|
- `common/gal/opengl/shader.cpp` - GLSL shader management
|
||||||
|
- `common/gal/opengl/vertex_manager.cpp` - Vertex buffer management
|
||||||
|
- `common/gal/opengl/gpu_manager.cpp` - GPU memory management
|
||||||
|
- `common/gal/opengl/cached_container.cpp` - Geometry caching
|
||||||
|
|
||||||
|
**Canvas**: `HIDPI_GL_CANVAS` wraps `wxGLCanvas`
|
||||||
|
|
||||||
|
**Shader files** (`common/gal/shaders/`):
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `kicad_vert.glsl` | Main vertex shader |
|
||||||
|
| `kicad_frag.glsl` | Main fragment shader |
|
||||||
|
| `smaa_base.glsl` | SMAA antialiasing base |
|
||||||
|
| `smaa_pass_1_frag.glsl` | SMAA edge detection |
|
||||||
|
| `smaa_pass_2_frag.glsl` | SMAA blending weights |
|
||||||
|
| `smaa_pass_3_frag.glsl` | SMAA neighborhood blending |
|
||||||
|
|
||||||
|
Shaders are embedded as C strings at build time.
|
||||||
|
|
||||||
|
**For WebGL**: Need to convert shaders:
|
||||||
|
```glsl
|
||||||
|
// Before (desktop GLSL)
|
||||||
|
#version 120
|
||||||
|
varying vec4 color;
|
||||||
|
|
||||||
|
// After (WebGL/GLSL ES)
|
||||||
|
precision mediump float;
|
||||||
|
varying vec4 color;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cairo GAL
|
||||||
|
|
||||||
|
**Files**:
|
||||||
|
- `include/gal/cairo/cairo_gal.h`
|
||||||
|
- `common/gal/cairo/cairo_gal.cpp`
|
||||||
|
- `common/gal/cairo/cairo_compositor.cpp` - Layer compositing
|
||||||
|
- `common/gal/cairo/cairo_print.cpp` - Printing support
|
||||||
|
|
||||||
|
Used for:
|
||||||
|
- Software rendering fallback
|
||||||
|
- Printing
|
||||||
|
- PDF/SVG export
|
||||||
|
|
||||||
|
### Draw Panel
|
||||||
|
|
||||||
|
**File**: `include/class_draw_panel_gal.h`
|
||||||
|
|
||||||
|
`EDA_DRAW_PANEL_GAL` wraps GAL and handles:
|
||||||
|
- Mouse events
|
||||||
|
- Keyboard events
|
||||||
|
- Tool dispatching
|
||||||
|
- View management
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File I/O System
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
Plugin-based system with base class `IO_BASE`:
|
||||||
|
|
||||||
|
**File**: `include/io/io_base.h`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class IO_BASE {
|
||||||
|
struct IO_FILE_DESC {
|
||||||
|
wxString m_Description;
|
||||||
|
std::vector<std::string> m_FileExtensions;
|
||||||
|
bool m_CanRead;
|
||||||
|
bool m_CanWrite;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual std::vector<IO_FILE_DESC> GetFileDescriptors();
|
||||||
|
virtual void SetReporter(REPORTER* reporter);
|
||||||
|
virtual void SetProgressReporter(PROGRESS_REPORTER* reporter);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Format Plugins
|
||||||
|
|
||||||
|
**KiCad Native** (`common/io/kicad/`):
|
||||||
|
- S-expression based format
|
||||||
|
- `.kicad_pcb`, `.kicad_sch`, `.kicad_sym`, `.kicad_mod`
|
||||||
|
|
||||||
|
**Import Plugins** (`common/io/`):
|
||||||
|
| Plugin | Location | Formats |
|
||||||
|
|--------|----------|---------|
|
||||||
|
| Eagle | `common/io/eagle/` | `.brd`, `.sch` |
|
||||||
|
| Altium | `common/io/altium/` | `.PcbDoc`, `.SchDoc` |
|
||||||
|
| CADSTAR | `common/io/cadstar/` | `.cpa`, `.csa` |
|
||||||
|
| EasyEDA | `common/io/easyeda/` | `.json` |
|
||||||
|
| EasyEDA Pro | `common/io/easyedapro/` | `.epro` |
|
||||||
|
|
||||||
|
### S-Expression Parser
|
||||||
|
|
||||||
|
**Location**: `libs/sexpr/`
|
||||||
|
|
||||||
|
KiCad native files use S-expressions:
|
||||||
|
```lisp
|
||||||
|
(kicad_pcb (version 20221018)
|
||||||
|
(generator pcbnew)
|
||||||
|
(layers
|
||||||
|
(0 "F.Cu" signal)
|
||||||
|
(31 "B.Cu" signal))
|
||||||
|
(footprint "Package_SO:SOIC-8"
|
||||||
|
(at 100 100)
|
||||||
|
(pad "1" smd rect (at -1.905 -2.475) (size 0.6 1.5))))
|
||||||
|
```
|
||||||
|
|
||||||
|
Parser is pure C++, good candidate for Wasm.
|
||||||
|
|
||||||
|
### PCB Data Model
|
||||||
|
|
||||||
|
**Key classes** (in `pcbnew/`):
|
||||||
|
|
||||||
|
| Class | File | Purpose |
|
||||||
|
|-------|------|---------|
|
||||||
|
| `BOARD` | `board.h` | Top-level PCB container |
|
||||||
|
| `FOOTPRINT` | `footprint.h` | Component footprint |
|
||||||
|
| `PAD` | `pad.h` | Footprint pad |
|
||||||
|
| `PCB_TRACK` | `pcb_track.h` | Trace segment |
|
||||||
|
| `PCB_VIA` | `pcb_track.h` | Via |
|
||||||
|
| `ZONE` | `zone.h` | Copper pour |
|
||||||
|
| `PCB_SHAPE` | `pcb_shape.h` | Graphical shape |
|
||||||
|
| `PCB_TEXT` | `pcb_text.h` | Text |
|
||||||
|
|
||||||
|
**Hierarchy**:
|
||||||
|
```
|
||||||
|
BOARD
|
||||||
|
├── FOOTPRINT[]
|
||||||
|
│ ├── PAD[]
|
||||||
|
│ ├── PCB_SHAPE[]
|
||||||
|
│ └── PCB_TEXT[]
|
||||||
|
├── PCB_TRACK[]
|
||||||
|
├── PCB_VIA[]
|
||||||
|
├── ZONE[]
|
||||||
|
├── PCB_SHAPE[]
|
||||||
|
└── PCB_TEXT[]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Python Scripting
|
||||||
|
|
||||||
|
### SWIG Bindings
|
||||||
|
|
||||||
|
**Location**: `scripting/`, `common/swig/`, `pcbnew/python/swig/`
|
||||||
|
|
||||||
|
**Interface files** (`.i`):
|
||||||
|
| File | Lines | Purpose |
|
||||||
|
|------|-------|---------|
|
||||||
|
| `kicadplugins.i` | 695 | Plugin framework |
|
||||||
|
| `wx.i` | 348 | wxWidgets types |
|
||||||
|
| `board.i` | 201 | BOARD class |
|
||||||
|
| `board_item.i` | 222 | Base item class |
|
||||||
|
| `footprint.i` | 200 | FOOTPRINT class |
|
||||||
|
| `pad.i` | 128 | PAD class |
|
||||||
|
| `pcbnew.i` | 148 | Main pcbnew module |
|
||||||
|
| Others | ~1600 | Various classes |
|
||||||
|
| **Total** | ~3500 | |
|
||||||
|
|
||||||
|
### How SWIG Works
|
||||||
|
|
||||||
|
1. SWIG reads `.i` interface files
|
||||||
|
2. Generates C++ wrapper code for CPython
|
||||||
|
3. Wrapper compiled to shared library (`_pcbnew.so`)
|
||||||
|
4. Python imports the module
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pcbnew
|
||||||
|
board = pcbnew.GetBoard()
|
||||||
|
for track in board.GetTracks():
|
||||||
|
print(track.GetStart(), track.GetEnd())
|
||||||
|
```
|
||||||
|
|
||||||
|
### Plugin Types
|
||||||
|
|
||||||
|
| Type | Purpose | Interface |
|
||||||
|
|------|---------|-----------|
|
||||||
|
| FootprintWizard | Generate footprints programmatically | `FootprintWizardPlugin` |
|
||||||
|
| ActionPlugin | Custom toolbar actions | `ActionPlugin` |
|
||||||
|
| FilePlugin | Custom file formats | `FilePlugin` |
|
||||||
|
|
||||||
|
### Wasm Strategy
|
||||||
|
|
||||||
|
SWIG generates CPython-specific code. Options for Wasm:
|
||||||
|
|
||||||
|
1. **Emscripten embind**: Rewrite bindings (~3500 lines to port)
|
||||||
|
```cpp
|
||||||
|
#include <emscripten/bind.h>
|
||||||
|
EMSCRIPTEN_BINDINGS(pcbnew) {
|
||||||
|
class_<BOARD>("Board")
|
||||||
|
.function("GetTracks", &BOARD::Tracks);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Pyodide**: If we want Python in browser, use Pyodide with custom FFI
|
||||||
|
|
||||||
|
3. **Skip for MVP**: Python scripting is optional for basic editing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build System
|
||||||
|
|
||||||
|
### Main CMakeLists.txt Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
CMakeLists.txt
|
||||||
|
├── Project setup (lines 1-100)
|
||||||
|
├── Options (lines 110-290)
|
||||||
|
│ ├── KICAD_SPICE_QA
|
||||||
|
│ ├── KICAD_USE_SENTRY
|
||||||
|
│ ├── KICAD_BUILD_I18N
|
||||||
|
│ ├── KICAD_BUILD_QA_TESTS
|
||||||
|
│ ├── KICAD_SCRIPTING_WXPYTHON
|
||||||
|
│ ├── KICAD_UPDATE_CHECK
|
||||||
|
│ └── ... more options
|
||||||
|
├── Compiler setup (lines 300-800)
|
||||||
|
├── Dependencies (lines 800-1200)
|
||||||
|
│ ├── find_package(ZLIB)
|
||||||
|
│ ├── find_package(CURL) # Line 825 - REQUIRED
|
||||||
|
│ ├── find_package(libgit2) # Line 842 - REQUIRED
|
||||||
|
│ ├── find_package(ngspice) # Line 877 - REQUIRED
|
||||||
|
│ ├── find_package(OCC) # Line 880 - FATAL if not found
|
||||||
|
│ └── ... more deps
|
||||||
|
├── wxWidgets setup (lines 1080-1140)
|
||||||
|
└── Subdirectories (lines 1250+)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Library Build
|
||||||
|
|
||||||
|
**File**: `common/CMakeLists.txt`
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# KICOMMON_SRCS includes:
|
||||||
|
# - git/*.cpp (lines 75-95)
|
||||||
|
# - kicad_curl/*.cpp (lines 140-141)
|
||||||
|
# - database/*.cpp
|
||||||
|
# - All UI code
|
||||||
|
|
||||||
|
target_link_libraries(kicommon
|
||||||
|
CURL::libcurl # Line 325
|
||||||
|
${LIBGIT2_LIBRARIES} # Line 330
|
||||||
|
# ...
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding CMake Options for Optional Deps
|
||||||
|
|
||||||
|
Need to add after line 107:
|
||||||
|
```cmake
|
||||||
|
option( KICAD_USE_CURL "Enable network features" ON )
|
||||||
|
option( KICAD_USE_GIT "Enable git integration" ON )
|
||||||
|
option( KICAD_USE_OCC "Enable STEP/3D via OpenCASCADE" ON )
|
||||||
|
option( KICAD_USE_NGSPICE "Enable SPICE simulation" ON )
|
||||||
|
option( KICAD_USE_DATABASE "Enable database libraries" ON )
|
||||||
|
```
|
||||||
|
|
||||||
|
Then wrap find_package calls:
|
||||||
|
```cmake
|
||||||
|
if( KICAD_USE_CURL )
|
||||||
|
find_package( CURL REQUIRED )
|
||||||
|
add_compile_definitions( KICAD_USE_CURL )
|
||||||
|
else()
|
||||||
|
add_library( CURL::libcurl INTERFACE IMPORTED )
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features to Disable
|
||||||
|
|
||||||
|
### Git Integration
|
||||||
|
|
||||||
|
**Files to stub** (`common/git/`):
|
||||||
|
- `git_add_to_index_handler.cpp`
|
||||||
|
- `git_branch_handler.cpp`
|
||||||
|
- `git_clone_handler.cpp`
|
||||||
|
- `git_commit_handler.cpp`
|
||||||
|
- `git_config_handler.cpp`
|
||||||
|
- `git_compare_handler.cpp`
|
||||||
|
- `git_init_handler.cpp`
|
||||||
|
- `git_pull_handler.cpp`
|
||||||
|
- `git_push_handler.cpp`
|
||||||
|
- `git_remove_from_index_handler.cpp`
|
||||||
|
- `git_remove_vcs_handler.cpp`
|
||||||
|
- `git_resolve_conflict_handler.cpp`
|
||||||
|
- `git_revert_handler.cpp`
|
||||||
|
- `git_status_handler.cpp`
|
||||||
|
- `git_switch_branch_handler.cpp`
|
||||||
|
- `git_sync_handler.cpp`
|
||||||
|
- `kicad_git_common.cpp`
|
||||||
|
- `git_backend.cpp`
|
||||||
|
- `libgit_backend.cpp`
|
||||||
|
- `project_git_utils.cpp`
|
||||||
|
|
||||||
|
**Stub header needed**: `stubs/include/git2.h`
|
||||||
|
|
||||||
|
### Network Features (curl)
|
||||||
|
|
||||||
|
**Files to stub** (`common/kicad_curl/`):
|
||||||
|
- `kicad_curl.cpp`
|
||||||
|
- `kicad_curl_easy.cpp`
|
||||||
|
|
||||||
|
**Files to stub** (`common/http_lib/`):
|
||||||
|
- `http_lib_connection.cpp`
|
||||||
|
|
||||||
|
**Files affected** (`kicad/`):
|
||||||
|
- `pcm/pcm.cpp` - Plugin Content Manager
|
||||||
|
- `pcm/pcm_task_manager.cpp`
|
||||||
|
- `update_manager.cpp`
|
||||||
|
|
||||||
|
**Stub header needed**: `stubs/include/curl/curl.h`
|
||||||
|
|
||||||
|
### OpenCASCADE (STEP/3D)
|
||||||
|
|
||||||
|
**Files to exclude**:
|
||||||
|
- `pcbnew/exporters/step/*.cpp`
|
||||||
|
- `plugins/3d/oce/*.cpp`
|
||||||
|
|
||||||
|
**Approach**: Don't build these targets rather than stubbing.
|
||||||
|
|
||||||
|
### SPICE Simulation
|
||||||
|
|
||||||
|
**Files affected**: `eeschema/sim/`
|
||||||
|
|
||||||
|
**Approach**: Disable simulator UI, don't build sim targets.
|
||||||
|
|
||||||
|
### Database Libraries
|
||||||
|
|
||||||
|
**Files to stub** (`common/database/`):
|
||||||
|
- `database_connection.cpp`
|
||||||
|
- `database_cache.cpp`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Extraction Candidates
|
||||||
|
|
||||||
|
### Tier 1: Pure Computation (No Dependencies)
|
||||||
|
|
||||||
|
| Component | Location | Lines (approx) | Notes |
|
||||||
|
|-----------|----------|----------------|-------|
|
||||||
|
| Math library | `libs/kimath/src/` | ~5000 | Vectors, matrices, geometry |
|
||||||
|
| Core utilities | `libs/core/src/` | ~2000 | String utils, exceptions |
|
||||||
|
| S-expr parser | `libs/sexpr/` | ~1500 | Pure parsing |
|
||||||
|
|
||||||
|
### Tier 2: File I/O (Minimal Dependencies)
|
||||||
|
|
||||||
|
| Component | Location | Notes |
|
||||||
|
|-----------|----------|-------|
|
||||||
|
| KiCad PCB parser | `common/io/kicad/` | Needs kimath, sexpr |
|
||||||
|
| Board data model | `pcbnew/*.cpp` | Core classes only |
|
||||||
|
| Schematic parser | `common/io/eeschema/` | Needs kimath |
|
||||||
|
|
||||||
|
### Tier 3: Algorithms (May Need Adaptation)
|
||||||
|
|
||||||
|
| Component | Location | Notes |
|
||||||
|
|-----------|----------|-------|
|
||||||
|
| DRC engine | `pcbnew/drc/` | May use threading |
|
||||||
|
| Router | `pcbnew/router/` | Push & Shove |
|
||||||
|
| ERC | `eeschema/erc/` | Electrical checks |
|
||||||
|
| Connectivity | `pcbnew/connectivity/` | Net analysis |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Challenges
|
||||||
|
|
||||||
|
### Threading
|
||||||
|
|
||||||
|
**Current usage**:
|
||||||
|
- DRC runs checks in parallel
|
||||||
|
- Router uses threading for optimization
|
||||||
|
- Background jobs system
|
||||||
|
|
||||||
|
**Wasm limitation**: Single-threaded by default.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
1. **Web Workers**: Spawn separate Wasm instances
|
||||||
|
2. **Wasm threads** (experimental): SharedArrayBuffer + pthreads
|
||||||
|
3. **Sequential fallback**: Slower but works
|
||||||
|
|
||||||
|
**Decision**: Use Web Workers. Design for async message-passing.
|
||||||
|
|
||||||
|
### Memory Management
|
||||||
|
|
||||||
|
**Challenge**: Need to share board state between native GUI and Wasm core.
|
||||||
|
|
||||||
|
**Options**:
|
||||||
|
1. **Serialize/deserialize**: Simple, proof of concept
|
||||||
|
2. **Shared memory**: Complex, requires careful synchronization
|
||||||
|
3. **Authoritative Wasm copy**: GUI requests views
|
||||||
|
|
||||||
|
**Decision**: Serialize/deserialize. Proof of concept, simplicity over performance.
|
||||||
|
|
||||||
|
### File Access
|
||||||
|
|
||||||
|
**Native**: Direct filesystem, `wxFileDialog`
|
||||||
|
|
||||||
|
**Browser**: No filesystem access without user interaction
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
- Emscripten virtual filesystem (MEMFS, IDBFS)
|
||||||
|
- File System Access API (Chrome)
|
||||||
|
- IndexedDB for persistence
|
||||||
|
- Drag & drop / file picker
|
||||||
|
|
||||||
|
### Clipboard
|
||||||
|
|
||||||
|
**Native**: `wxClipboard`, platform integration
|
||||||
|
|
||||||
|
**Browser**: Async Clipboard API (permissions required)
|
||||||
|
|
||||||
|
### Fonts
|
||||||
|
|
||||||
|
**Native**: System fonts via Fontconfig
|
||||||
|
|
||||||
|
**Browser**: Bundle fonts or use CSS fonts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Design Decisions
|
||||||
|
|
||||||
|
### Memory Management
|
||||||
|
|
||||||
|
**Decision**: Serialize/deserialize on every operation
|
||||||
|
|
||||||
|
**Rationale**:
|
||||||
|
- Proof of concept phase
|
||||||
|
- Simplicity over performance
|
||||||
|
- Clean interface between GUI and core
|
||||||
|
- Easy to debug
|
||||||
|
- Browser-friendly (no shared memory complexity)
|
||||||
|
|
||||||
|
**Implementation**:
|
||||||
|
```cpp
|
||||||
|
// GUI → Wasm: Send operation + serialized state
|
||||||
|
std::string boardJson = SerializeBoard(board);
|
||||||
|
wasmCore.ApplyOperation(boardJson, operation);
|
||||||
|
std::string newBoardJson = wasmCore.GetBoardState();
|
||||||
|
board = DeserializeBoard(newBoardJson);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Threading Model
|
||||||
|
|
||||||
|
**Decision**: Web Workers
|
||||||
|
|
||||||
|
**Rationale**:
|
||||||
|
- Target is browser
|
||||||
|
- Clean message-passing interface
|
||||||
|
- Each worker is isolated Wasm instance
|
||||||
|
- No shared memory complexity
|
||||||
|
|
||||||
|
**Implementation**:
|
||||||
|
```javascript
|
||||||
|
// Main thread
|
||||||
|
const worker = new Worker('kicad-core-worker.js');
|
||||||
|
worker.postMessage({ type: 'runDRC', board: boardData });
|
||||||
|
worker.onmessage = (e) => { handleDRCResults(e.data); };
|
||||||
|
|
||||||
|
// Worker
|
||||||
|
importScripts('kicad_core.js');
|
||||||
|
onmessage = async (e) => {
|
||||||
|
const core = await KicadCore();
|
||||||
|
if (e.data.type === 'runDRC') {
|
||||||
|
const results = core.runDRC(e.data.board);
|
||||||
|
postMessage(results);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Incremental Updates
|
||||||
|
|
||||||
|
**Decision**: Re-serialize entire board (for now)
|
||||||
|
|
||||||
|
**Rationale**:
|
||||||
|
- Simple implementation
|
||||||
|
- Board files are typically <10MB
|
||||||
|
- Performance acceptable for proof of concept
|
||||||
|
- Can optimize later with deltas if needed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Reference
|
||||||
|
|
||||||
|
### Core Headers
|
||||||
|
|
||||||
|
| Purpose | File |
|
||||||
|
|---------|------|
|
||||||
|
| GAL interface | `include/gal/graphics_abstraction_layer.h` |
|
||||||
|
| OpenGL GAL | `include/gal/opengl/opengl_gal.h` |
|
||||||
|
| Cairo GAL | `include/gal/cairo/cairo_gal.h` |
|
||||||
|
| Draw panel | `include/class_draw_panel_gal.h` |
|
||||||
|
| Base frame | `include/eda_base_frame.h` |
|
||||||
|
| KIWAY | `include/kiway.h` |
|
||||||
|
| KIWAY holder | `include/kiway_holder.h` |
|
||||||
|
| I/O base | `include/io/io_base.h` |
|
||||||
|
| Board | `pcbnew/board.h` |
|
||||||
|
| Footprint | `pcbnew/footprint.h` |
|
||||||
|
| Track | `pcbnew/pcb_track.h` |
|
||||||
|
|
||||||
|
### Build Files
|
||||||
|
|
||||||
|
| Purpose | File |
|
||||||
|
|---------|------|
|
||||||
|
| Main build | `CMakeLists.txt` |
|
||||||
|
| Common lib | `common/CMakeLists.txt` |
|
||||||
|
| GAL lib | `common/gal/CMakeLists.txt` |
|
||||||
|
| PCBnew | `pcbnew/CMakeLists.txt` |
|
||||||
|
| Eeschema | `eeschema/CMakeLists.txt` |
|
||||||
|
| 3D viewer | `3d-viewer/CMakeLists.txt` |
|
||||||
|
|
||||||
|
### SWIG Bindings
|
||||||
|
|
||||||
|
| Purpose | File |
|
||||||
|
|---------|------|
|
||||||
|
| Main entry | `scripting/kicadplugins.i` |
|
||||||
|
| Common | `common/swig/kicad.i` |
|
||||||
|
| wxWidgets | `common/swig/wx.i` |
|
||||||
|
| Math | `common/swig/math.i` |
|
||||||
|
| Shapes | `common/swig/shape.i` |
|
||||||
|
| Board | `pcbnew/python/swig/board.i` |
|
||||||
|
| PCBnew main | `pcbnew/python/swig/pcbnew.i` |
|
||||||
|
|
||||||
|
### Git Integration
|
||||||
|
|
||||||
|
| Purpose | File |
|
||||||
|
|---------|------|
|
||||||
|
| Common class | `common/git/kicad_git_common.cpp` |
|
||||||
|
| Clone | `common/git/git_clone_handler.cpp` |
|
||||||
|
| Commit | `common/git/git_commit_handler.cpp` |
|
||||||
|
| Push | `common/git/git_push_handler.cpp` |
|
||||||
|
| Pull | `common/git/git_pull_handler.cpp` |
|
||||||
|
| Status | `common/git/git_status_handler.cpp` |
|
||||||
|
| PCB merge | `pcbnew/git/kigit_pcb_merge.cpp` |
|
||||||
|
|
||||||
|
### Curl/Network
|
||||||
|
|
||||||
|
| Purpose | File |
|
||||||
|
|---------|------|
|
||||||
|
| Curl wrapper | `common/kicad_curl/kicad_curl_easy.cpp` |
|
||||||
|
| Curl init | `common/kicad_curl/kicad_curl.cpp` |
|
||||||
|
| HTTP lib | `common/http_lib/http_lib_connection.cpp` |
|
||||||
|
| PCM | `kicad/pcm/pcm.cpp` |
|
||||||
|
| Updates | `kicad/update_manager.cpp` |
|
||||||
|
|
||||||
|
### OpenCASCADE/STEP
|
||||||
|
|
||||||
|
| Purpose | File |
|
||||||
|
|---------|------|
|
||||||
|
| STEP model | `pcbnew/exporters/step/step_pcb_model.cpp` |
|
||||||
|
| STEP export | `pcbnew/exporters/step/exporter_step.cpp` |
|
||||||
|
| OCC plugin | `plugins/3d/oce/oce.cpp` |
|
||||||
|
| Model loader | `plugins/3d/oce/loadmodel.cpp` |
|
||||||
1
kicad
Submodule
1
kicad
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 4bfed3f1746e8cc0a7d942767770f56fa28b393c
|
||||||
Loading…
Reference in a new issue