From 3c90f96a6344b43370f02a6b1be82e1fb786105e Mon Sep 17 00:00:00 2001 From: janik Date: Thu, 23 Jul 2026 11:23:36 +0700 Subject: [PATCH] Per-OS setup instructions; skip pyamg on Linux aarch64 The README assumed Windows throughout. Setup now gives the interpreter path, deploy command and venv location for Windows, macOS and Linux (venv paths verified against KiCad 10 sources: GetUserCachePath + python-environments), plus a Platform notes section: macOS bundles Python 3.9.13 so pip resolves an older wheel stack (KiCad installs with --only-binary :all:), and windows there may open behind KiCad; Linux needs python3-venv on Debian/Ubuntu. pyamg has never published Linux aarch64 wheels, and with KiCad's wheels-only pip one unresolvable requirement kills the whole venv build - so an environment marker skips pyamg there and the solver falls back to Jacobi-CG, which it already supports. Co-Authored-By: Claude Fable 5 --- README.md | 60 +++++++++++++++++++++++++++++++++++++----------- pyproject.toml | 2 +- requirements.txt | 4 +++- uv.lock | 4 ++-- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 5afd9aa..69d171c 100644 --- a/README.md +++ b/README.md @@ -30,14 +30,25 @@ SWIG API. Requires KiCad **10.0.1+**. ## Setup (one-time) +The plugin runs on **Windows, Linux and macOS** — KiCad builds it a +private Python venv from `requirements.txt` on every platform, from +pre-built wheels only (no compiler needed). Steps 1–4 are the same +everywhere; OS specifics are spelled out per step and in *Platform +notes* below. + 1. **Enable the API server**: KiCad → Preferences → Plugins → check *Enable KiCad API*. -2. **Check the interpreter path** on the same page: should point at the - KiCad 10 Python, e.g. `C:\Program Files\KiCad\10.0\bin\pythonw.exe` - on Windows or `/usr/bin/python3` on Linux (after a 9→10 upgrade it - can point at KiCad 9). +2. **Check the interpreter path** on the same page (after a 9→10 + upgrade it can still point at KiCad 9): + - **Windows**: KiCad's own Python, + `C:\Program Files\KiCad\10.0\bin\pythonw.exe`; + - **macOS**: the Python bundled inside the app, + `/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3`; + - **Linux**: the first `python3` on `PATH` — needs Python ≥ 3.9 + with the `venv` module (Debian/Ubuntu: + `sudo apt install python3-venv`). 3. **Deploy** (dev checkout; end users install the PCM zip instead, see - *Packaging / publishing*): + *Packaging / publishing*). Windows: ```powershell powershell -ExecutionPolicy Bypass -File deploy.ps1 # junction (dev) powershell -ExecutionPolicy Bypass -File deploy.ps1 -Mode Copy @@ -47,14 +58,34 @@ SWIG API. Requires KiCad **10.0.1+**. python3 tools/deploy.py # symlink (dev) python3 tools/deploy.py --copy ``` + Plugin directory: `Documents/KiCad/10.0/plugins` on Windows and + macOS, `~/.local/share/kicad/10.0/plugins` on Linux. 4. **Restart KiCad**; first load builds the plugin venv (numpy, scipy, matplotlib, PySide6 — takes minutes; the Ω button appears when done). If stuck: in the PCB editor, Preferences → *PCB Editor → Action Plugins*, **right-click** the plugin's row → *Recreate Plugin Environment* (context menu only — there is no button). Manual - equivalent: delete - `%LOCALAPPDATA%\kicad\10.0\python-environments\th.co.b4l.fill-resistance` - and restart KiCad. + equivalent: delete the plugin's venv and restart KiCad — + - Windows: `%LOCALAPPDATA%\kicad\10.0\python-environments\th.co.b4l.fill-resistance` + - macOS: `~/Library/Caches/kicad/10.0/python-environments/th.co.b4l.fill-resistance` + - Linux: `~/.cache/kicad/10.0/python-environments/th.co.b4l.fill-resistance` + +### Platform notes + +- **Windows** is the development and test platform. KiCad's bundled + Python is 3.13, so the venv gets the current dependency stack. +- **macOS** (12+, KiCad's own minimum; Intel and Apple Silicon — + the dmg is universal): KiCad's bundled Python is **3.9**, so pip + resolves an older but fully functional stack (numpy 2.0, + scipy 1.13, matplotlib 3.9, PySide6 6.9/6.10). The plugin code is + kept 3.9-compatible. Plot and dialog windows may open **behind** + the KiCad window (they are raised best-effort) — check the Dock if + nothing seems to appear after a solve. +- **Linux**: the venv uses the system Python (3.9+), so the stack + matches your distribution. On **ARM64 (aarch64)** there are no + pyamg wheels — `requirements.txt` skips pyamg there and the solver + falls back to Jacobi-CG: same results, noticeably slower on large + grids. ## Usage @@ -86,7 +117,7 @@ SWIG API. Requires KiCad **10.0.1+**. multi-layer pours at fine cell sizes may run for minutes (on our test setup a typical real-board run finishes in ≈ 8 s). Then read R / voltage drop / total power in the figure titles and status - bar. Outputs land in `\fill_res_results\\`: + bar. Outputs land in `/fill_res_results//`: per-layer `1_raster_map` / `2_potential` / `3_current_density` / `4_power_density` PNGs, `summary.txt` (incl. the busiest vias with per-via current and dissipation, and the **current through each @@ -292,9 +323,9 @@ accordingly more trustworthy than absolute numbers. Every run writes `geometry_dump.json`; re-solve without KiCad: -```powershell -uv run python -m fill_resistance.standalone dump.json ` - [--current 40] [--cell-um 50] [--layers F.Cu,In1.Cu] [--no-show] ` +```sh +uv run python -m fill_resistance.standalone dump.json + [--current 40] [--cell-um 50] [--layers F.Cu,In1.Cu] [--no-show] [--out DIR] [--force-iterative] ``` @@ -302,7 +333,7 @@ Dev environment, tests, headless extraction — [uv](https://docs.astral.sh/uv/) manages the venv from `pyproject.toml`/`uv.lock` (`requirements.txt` stays: KiCad builds the plugin's runtime venv from it): -```powershell +```sh uv sync # one-time env setup uv run pytest -q # incl. exact analytic cases uv run python tools/api_probe.py # IPC API probe vs live KiCad @@ -332,7 +363,8 @@ GPL-3.0-or-later — see [LICENSE](LICENSE). - **No toolbar button**: venv still building (wait), or build failed → *Recreate Plugin Environment* (right-click the plugin's row in Preferences → *PCB Editor → Action Plugins*); check the interpreter - path (setup 2). + path (setup 2); on Linux make sure `python3-venv` is installed. Last + resort: delete the venv directory by hand (setup 4) and restart. - **"Could not connect to KiCad's IPC API"**: API server not enabled, or KiCad not running (no headless mode in KiCad 10). - **"KiCad is busy"**: a modal dialog is open in KiCad — close it, rerun. diff --git a/pyproject.toml b/pyproject.toml index a800bd6..835f8a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "kicad-python>=0.7.0", "numpy", "scipy", - "pyamg", + "pyamg ; sys_platform != 'linux' or platform_machine != 'aarch64'", "matplotlib", "PySide6", ] diff --git a/requirements.txt b/requirements.txt index da3eb5b..5258d09 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,8 @@ kicad-python>=0.7.0 numpy scipy -pyamg +# no pyamg wheels for Linux aarch64, and KiCad installs wheels-only +# (--only-binary): skip it there, the solver falls back to Jacobi-CG +pyamg ; sys_platform != "linux" or platform_machine != "aarch64" matplotlib PySide6 diff --git a/uv.lock b/uv.lock index bcc82b6..28d0eea 100644 --- a/uv.lock +++ b/uv.lock @@ -223,7 +223,7 @@ dependencies = [ { name = "matplotlib" }, { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, { name = "numpy", version = "2.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, - { name = "pyamg" }, + { name = "pyamg", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, { name = "pyside6" }, { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, @@ -239,7 +239,7 @@ requires-dist = [ { name = "kicad-python", specifier = ">=0.7.0" }, { name = "matplotlib" }, { name = "numpy" }, - { name = "pyamg" }, + { name = "pyamg", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, { name = "pyside6" }, { name = "scipy" }, ]