Skip to content

feat(release): Backplane KiCad for Apple-silicon Macs; fix the headless plot crash on macOS - #5

Open
Grim-Raid wants to merge 3 commits into
BackplaneWorks:mainfrom
Grim-Raid:backplane/macos-runtime
Open

Grim-Raid wants to merge 3 commits into
BackplaneWorks:mainfrom
Grim-Raid:backplane/macos-runtime

Conversation

@Grim-Raid

Copy link
Copy Markdown

Builds the Backplane KiCad runtime for Apple-silicon Macs in the release workflow, beside the Linux one, and fixes the macOS crash that took the headless IPC server down. Stacked on #2 (its first commit is that PR's enum-visibility fix).

Release

  • New macos-runtime job (macos-15). The draft release now carries backplane-kicad-macos-arm64-<version>.tar.gz next to the Linux archive, under one combined SHA256SUMS. The Linux job itself is unchanged.
  • The archive matches the Linux layout: KiCad.app, bin/ launchers (kicad-cli, kicad, pcbnew, eeschema...), share/kicad with the pinned libraries, manifest.json (now with platform).
  • scripts/backplane-macos-build.sh: KiCad.app built against Homebrew with the Linux release's options. It uses wxWidgets 3.2 (what KiCad 10 targets; Homebrew's default is 3.3), libngspice, a staged Python.framework (Homebrew's site-packages is a symlink the install cannot copy over), and KICAD_APPLE_MAKE_RELOCATEABLE_BUNDLE.
  • scripts/backplane-macos-relocate.py: copies what still loads from Homebrew into the bundle (mostly Python's extension modules), rewrites the references, drops outside rpaths and symlinks, and re-signs ad hoc. --check fails if anything still points outside.
  • scripts/backplane-macos-package.sh: assembles the archive, then tests it after moving the build away: the IPC smoke test, every regression suite, and the library smoke test.
  • scripts/backplane-fetch-libraries.sh: the pinned library fetch as a script for the Mac job (the same steps as the Linux job's inline ones).
  • The IPC test venv takes the protobuf runtime matching Homebrew's protoc (36.2 → 7.36.2).

Fixes

  • pcbnew/pcb_plotter.cpp: the plotter called wxSafeYield() after each page. On macOS that opens a modal session on the active event loop. In kicad-cli api-server that loop is a console loop, so the modal window, and then null, landed on its dispatcher pointer, and the next turn crashed (EXC_BAD_ACCESS in wxConsoleEventLoop::DispatchTimeout). The second board job of every session took the server down. Found with a hardware watchpoint. It now yields only in a GUI app (Pgm().IsGUI()); GUI builds behave as before.
  • kicad/project_tree.cpp: the SetStateImages branch assumed every macOS build uses KiCad's patched wxWidgets 3.2. A stock 3.2 (KICAD_STOCK_WX_MAC, set by the Mac build script) takes the image-list path the other platforms use.

Tested (macOS 26, arm64)

  • Full build and install; relocation leaves 0 outside references in 300 Mach-O files; codesign --verify --deep --strict passes.
  • After relocation, with the build folder moved away: kicad-cli --version, api-server --help, the IPC smoke test and all 12 regression suites pass (81 checks).
  • Not yet run: the workflow on GitHub's runner (the first run is the first full one), and the library smoke test with the pinned libraries (several GB of LFS models; skipped locally).

🤖 Generated with Claude Code

Grim-Raid and others added 3 commits September 24, 2026 12:34
api_enums.cpp moved from the static common library into the shared
kicommon library, which builds with -fvisibility=hidden. Its
FromProtoEnum/ToProtoEnum specializations were never exported, and
clang also keeps them local because their protobuf enum arguments are
hidden. Linking _pcbnew.kiface on macOS failed with undefined
ToProtoEnum<PCB_LAYER_ID, BoardLayer> and related symbols.

Mark each specialization APIVISIBLE (default visibility on GCC/clang,
empty on MSVC) so the kifaces resolve them from kicommon.

Verified on macOS 26 arm64 with the Backplane runtime flags: full build,
install, kicad-cli api-server, and PCB/schematic IPC smoke tests pass.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The release workflow gains a macos-15 job beside the Linux one, and the
draft release carries both archives under one SHA256SUMS.

- scripts/backplane-macos-build.sh: KiCad.app against Homebrew with the
  Linux release's options, wxWidgets 3.2, libngspice, a staged
  Python.framework, KICAD_APPLE_MAKE_RELOCATEABLE_BUNDLE
- scripts/backplane-macos-relocate.py: copies what still loads from
  Homebrew into the bundle, rewrites references, drops outside rpaths and
  symlinks, re-signs ad hoc; --check fails on anything left outside
- scripts/backplane-macos-package.sh: the Linux layout (KiCad.app,
  bin/ launchers, share/kicad, manifest.json), tested after relocation
  with the IPC smoke and regression suites
- scripts/backplane-fetch-libraries.sh: the pinned library fetch, shared
- kicad/project_tree.cpp: a stock wxWidgets 3.2 on macOS
  (KICAD_STOCK_WX_MAC) uses the image list, not KiCad's backported
  SetStateImages

Co-Authored-By: Claude Opus 5.5 <[email protected]>
PCB_PLOTTER::Plot called wxSafeYield() after each page. On macOS that
opens a modal session (wxGUIEventLoop::BeginModalSession) on the active
event loop; in kicad-cli api-server that loop is a wxConsoleEventLoop, so
the modal window and then null were written over its dispatcher and the
next turn of the loop crashed (EXC_BAD_ACCESS in
wxConsoleEventLoop::DispatchTimeout): the second board job of a session
always took the server down. Found with a hardware watchpoint on the
dispatcher. A headless run has nothing to repaint: yield only in a GUI
app (Pgm().IsGUI()).

Verified on macOS 26 arm64: the relocated runtime passes the IPC smoke
test and every regression suite (81 checks).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant