app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
← Commit history
v0.9.60: mesa fetch + manifest now use Release /download/ assets (SDK re-audit #84)
3 files changed
+109−5
adom-bridge-kicad-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.59",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.59/adom-bridge-kicad-v0.9.59.zip",- "sha256": "f8affb58064486c62cdeef1c0c5eb441cbaed92b1557af09b676e925f8d2e2c7",- "size": 643494,+ "version": "0.9.60",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.60/adom-bridge-kicad-v0.9.60.zip",+ "sha256": "675f2dd7c44d4ca3fe2f1735fe54166079d0e1b09a3a1f9fee95c11840c48c65",+ "size": 646046, "verbPrefixes": [ "kicad_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.59",+ "version": "0.9.60", "description": "Reverse bridge for KiCad \u2014 board/schematic introspection, lint via kicad-cli, plugin install, multi-instance probe, in-process DRC.", "homepage": "https://wiki.adom.inc/adom/adom-desktop", "author": "Adom Inc.",
handlers/software_opengl.pyadded+104@@ -0,0 +1,104 @@+"""kicad_enable_software_opengl — LAST-RESORT software-OpenGL fallback.++Deploys Mesa's `llvmpipe` OpenGL (a CPU software rasterizer) into KiCad's bin so+KiCad renders on a host with NO usable GPU — Hyper-V VMs, RDP sessions, headless+servers, CI — where the display adapter only offers OpenGL 1.1 and KiCad (needs+2.1+) pops "Could not use OpenGL" and won't render its editors or 3D viewer.++⚠ This is a BAD, SLOW solution (all rendering on the CPU) and exists ONLY as a+worst-case fallback. NEVER suggest it to a user proactively — a real GPU (or+Hyper-V GPU-P / DDA passthrough) is vastly better. The bridge keeps it purely so+a GPU-less box isn't a total dead end.++Mechanism: drop opengl32.dll + libgallium_wgl.dll (+ dxil.dll) into KiCad's bin+and add a per-exe `.local` file (DotLocal redirection) so KiCad loads Mesa's+opengl32 from its own dir instead of the system one.+"""++import io+import sys+import urllib.request+import zipfile+from pathlib import Path++from handlers.upgrade import _ssl_context # certifi-backed TLS (portable Python has no CA store)++_MESA_URL = "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.60/mesa-llvmpipe-x64.zip"+_MESA_DLLS = ("opengl32.dll", "libgallium_wgl.dll", "dxil.dll")+_KICAD_EXES = (+ "kicad.exe", "pcbnew.exe", "eeschema.exe", "gerbview.exe",+ "pl_editor.exe", "bitmap2component.exe", "pcb_calculator.exe",+)+++def _bin_dirs() -> list:+ """Every installed KiCad's bin dir (Program Files + per-user)."""+ import kicad_detect+ dirs = []+ for v in (kicad_detect.detect_all_kicad_versions() or []):+ base = v.get("base_dir") or v.get("bin_dir")+ if not base:+ continue+ b = Path(base)+ if b.name.lower() != "bin":+ b = b / "bin"+ if b.exists() and str(b) not in dirs:+ dirs.append(str(b))+ return dirs+++def handle_enable_software_opengl(kicad_info: dict, args: dict) -> dict:+ if sys.platform != "win32":+ return {"success": False, "error": "Windows-only", "errorCode": "unsupported_platform"}+ bins = _bin_dirs()+ if not bins:+ return {+ "success": False,+ "error": "No KiCad bin dir found — is KiCad installed?",+ "errorCode": "host_app_not_installed",+ "errorCodeLegacy": "kicad_not_installed",+ "hostApp": "KiCad",+ "_hint": "Run kicad_list_versions. Install KiCad first via kicad_upgrade.",+ }+ print(f"[KiCad Bridge] enable_software_opengl: downloading Mesa llvmpipe...", flush=True)+ try:+ req = urllib.request.Request(_MESA_URL, headers={"User-Agent": "adom-desktop-kicad-bridge"})+ with urllib.request.urlopen(req, timeout=180, context=_ssl_context()) as r:+ data = r.read()+ zf = zipfile.ZipFile(io.BytesIO(data))+ except Exception as e:+ print(f"[KiCad Bridge] enable_software_opengl: FAILED {e}", flush=True)+ return {"success": False, "error": f"Mesa download/unzip failed: {e}", "errorCode": "download_failed"}++ enabled, errors = [], []+ for bd in bins:+ try:+ for dll in _MESA_DLLS:+ zf.extract(dll, bd)+ for exe in _KICAD_EXES: # DotLocal redirection: empty <exe>.local+ if (Path(bd) / exe).exists():+ (Path(bd) / f"{exe}.local").write_text("")+ enabled.append(bd)+ print(f"[KiCad Bridge] enable_software_opengl: deployed to {bd}", flush=True)+ except PermissionError:+ errors.append(f"{bd}: permission denied (writing KiCad's bin needs elevation)")+ except Exception as e:+ errors.append(f"{bd}: {e}")++ ok = bool(enabled)+ return {+ "success": ok,+ "enabledIn": enabled,+ "errors": errors,+ "renderer": "Mesa llvmpipe (CPU software OpenGL)",+ "_hint": (+ "⚠ LAST-RESORT software-OpenGL fallback deployed — KiCad will render via Mesa llvmpipe on "+ "the CPU (SLOW). This is ONLY for a GPU-less host (Hyper-V/RDP/headless) where KiCad can't "+ "render at all; do NOT enable it on a normal machine. CLOSE and REOPEN KiCad editors to "+ "load it. To undo, delete opengl32.dll/libgallium_wgl.dll/dxil.dll and the *.local files "+ "from KiCad's bin."+ if ok else+ "Could not deploy — see errors[]. Writing KiCad's bin (Program Files) needs an elevated AD; "+ "a per-user KiCad install (kicad_upgrade scope=user) avoids that."+ ),+ }