Skip to content

Commit 4ff46e6

Browse files
fix: macOS build required a newer OS than the CI runner's OS that day
Confirmed directly: a native `zig build app` (no -Dtarget) bakes in the exact host machine's current macOS version as the binary's LC_BUILD_VERSION minos field (verified via `otool -l` on this machine, running 26.2 — produced `minos 26.2` exactly). Since GitHub's macos-latest runner's exact OS build can be ahead of any given user's installed version, this made real shipped builds fail to launch with "You can't use this version of the application 'Metanoia' with this version of macOS" — reported live by a user on macOS 26.2 (25C56) — the app was requiring whatever OS the CI runner happened to be on that day, not any real API dependency. Tried `-Dtarget=aarch64-macos.13.0` first and rejected it: it makes zig treat the build as cross-compiling even though it's the same arch+OS, which broke native system-library search — sqlite3 (which macOS ships as a system dylib at /usr/lib, not via Homebrew) could no longer be found, reproduced exactly via a local build attempt. Fixed instead with `vtool` (Apple's Mach-O load-command editor, part of Xcode Command Line Tools, present on every macOS GitHub Actions runner): rewrites LC_BUILD_VERSION's minos/sdk fields to 13.0 in place, after linking but before codesigning (patching after signing would invalidate it). 13.0 (Ventura, 2022) is a conservative multi-year-back floor, well below any realistically current user's OS while still modern enough for Homebrew's own gtk4/glib bottles. Verified end-to-end on this machine (not just reasoned through): ran the full updated build-macos.sh, confirmed `otool -l` shows minos 13.0, confirmed `codesign --verify` reports "valid on disk" (the ad-hoc signature is genuinely intact after the vtool patch, not broken), and actually launched the resulting Metanoia.app as a real running process. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent f3de8b3 commit 4ff46e6

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

packaging/build-macos.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,44 @@ zig build app -Doptimize=ReleaseFast
4545
APP_DIR="$ROOT/zig-out/${APP_NAME}.app"
4646
[ -d "$APP_DIR" ] || fail "expected $APP_DIR to exist after 'zig build app'"
4747

48+
# ── 0.5. Lower the binary's minimum macOS version ───────────────
49+
# `zig build` with no -Dtarget compiles "native", which bakes in the
50+
# EXACT host machine's current OS version as the binary's LC_BUILD_VERSION
51+
# minos (confirmed directly: a build on a machine running macOS 26.2
52+
# produced `minos 26.2`, via `otool -l`). Since GitHub's macos-latest
53+
# runner's exact OS build can be ahead of whatever a given user has
54+
# installed, that made the shipped app fail to launch on real user
55+
# machines with "You can't use this version of the application 'Metanoia'
56+
# with this version of macOS" — the app was silently requiring an OS
57+
# NEWER than what the runner happened to be on that day, not any real
58+
# API dependency.
59+
#
60+
# Fix: `vtool` (Apple's Mach-O load-command editor, part of Xcode Command
61+
# Line Tools, present on every macOS GitHub Actions runner) rewrites the
62+
# binary's LC_BUILD_VERSION minos/sdk fields in place, after linking but
63+
# BEFORE codesigning below (patching after signing would invalidate the
64+
# signature). Passing an explicit -Dtarget to zig instead of doing this
65+
# was tried and rejected: it makes zig treat the build as cross-compiling
66+
# even though it's the same arch+OS, which broke native system-library
67+
# search (Homebrew's gtk4 include paths no longer resolved sqlite3, which
68+
# macOS ships as a system dylib at /usr/lib — confirmed by reproducing the
69+
# exact failure locally) — vtool avoids all of that by never touching how
70+
# the binary is compiled/linked, only its post-link version metadata.
71+
#
72+
# 13.0 (Ventura, 2022) is a conservative, multi-year-back floor — well
73+
# below any realistically current user's OS, while still modern enough
74+
# for Homebrew's own gtk4/glib/etc. bottles (which target similarly
75+
# multi-year-back baselines, not bleeding-edge).
76+
MIN_MACOS="13.0"
77+
if command -v vtool >/dev/null 2>&1; then
78+
info "Lowering minimum macOS version to $MIN_MACOS (was $(otool -l "$APP_DIR/Contents/MacOS/metanoia" | awk '/minos/{print $2; exit}'))..."
79+
vtool -set-build-version macos "$MIN_MACOS" "$MIN_MACOS" -replace \
80+
-output "$APP_DIR/Contents/MacOS/metanoia" \
81+
"$APP_DIR/Contents/MacOS/metanoia"
82+
else
83+
fail "vtool not found — cannot set a portable minimum macOS version (shipping without this fix reproduces the exact 'can't use this version' bug on any user machine older than the CI runner's current OS)"
84+
fi
85+
4886
# ── 1. Ad-hoc codesign (no paid cert needed) ────────────────────
4987
# This does NOT satisfy Gatekeeper/notarization (users will still see an
5088
# "unidentified developer" prompt on first launch — right-click > Open, or

0 commit comments

Comments
 (0)