From e5ba78ea6623766f5ba2fd501c5f791b71075033 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Wed, 5 Aug 2026 23:22:37 +0200 Subject: [PATCH] fix(apple): build opus from source so the xcframework stops depending on brew MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xcframework build failed its own deployment-target guard on any Mac with a Homebrew libopus installed: ERROR: .../libpunktfunk_core.a contains objects built for macOS 26.0 (> 14.0) The guard was right; its advice was not. This is not a stale cache, and the suggested `rm -rf target/{aarch64,x86_64}-apple-darwin` never fixes it — the objects come back on every clean rebuild. audiopus_sys probes pkg-config before falling back to its vendored copy, and on this machine it found /opt/homebrew/Cellar/opus/1.6.1 and linked it statically. Homebrew compiles for the HOST macOS, so 143 SILK objects (wrappers_FLP.o, VAD.o, stereo_*.o, resampler.o …) entered our staticlib carrying minos 26 while everything we compiled carried 11 or 14. That made a locally-built framework's validity depend on whether the developer happens to have run `brew install opus` — for an artifact every Apple build consumes and no one commits, which is exactly the kind of environmental coupling that produces "works on my machine". OPUS_NO_PKG_CONFIG forces the vendored build unconditionally; CMAKE_POLICY_VERSION_MINIMUM is what that vendored copy needs to configure under CMake 4, which removed support for the pre-3.5 minimum its CMakeLists still declares. The guard's error message now names both causes and shows how to identify the offending objects, since the misleading half cost real time. Verified: from a fully clean target dir and with no environment variables set, `bash scripts/build-xcframework.sh` completes and signs. `swift build` then compiles PunktfunkKit, and `swift test --filter PresentIntervalsTests` runs 10/10 green — which pays off the Apple typecheck owed by d0d23994. --- scripts/build-xcframework.sh | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/scripts/build-xcframework.sh b/scripts/build-xcframework.sh index eb7bbedb..3a475d0b 100755 --- a/scripts/build-xcframework.sh +++ b/scripts/build-xcframework.sh @@ -10,6 +10,18 @@ set -euo pipefail cd "$(dirname "$0")/.." +# Opus must be built FROM SOURCE, never picked up from the machine. `audiopus_sys` probes +# pkg-config first, and a Homebrew libopus is compiled for the HOST macOS — its objects land +# inside our staticlib carrying that minos (the deployment-target check at the end of this +# script then fails with 143 SILK objects at the host's version). Whether the bundle is +# usable would otherwise depend on whether the developer happens to have `brew install opus`, +# which is exactly the kind of thing an artifact consumed by every Apple build must not +# depend on. `OPUS_NO_PKG_CONFIG` forces the vendored build; the CMake policy floor is for +# that vendored copy, whose CMakeLists still declares a pre-3.5 minimum that CMake 4 removed +# support for. +export OPUS_NO_PKG_CONFIG=1 +export CMAKE_POLICY_VERSION_MINIMUM="${CMAKE_POLICY_VERSION_MINIMUM:-3.5}" + TARGETS_MAC=(aarch64-apple-darwin x86_64-apple-darwin) BUILD_IOS="${BUILD_IOS:-0}" # BUILD_IOS=1 adds iOS device + simulator slices (rustup targets aarch64-apple-ios{,-sim}) BUILD_TVOS="${BUILD_TVOS:-0}" # BUILD_TVOS=1 adds tvOS slices — TIER-3 Rust targets: needs `rustup toolchain install nightly` + `rustup component add rust-src --toolchain nightly` @@ -125,7 +137,14 @@ for obj in "$STAGE"/macos/libpunktfunk_core.a; do bad=$(otool -l "$obj" 2>/dev/null | awk '/minos/ {print $2}' | sort -uV | awk -F. '$1 > 14' | head -1) if [[ -n "$bad" ]]; then echo "ERROR: $obj contains objects built for macOS $bad (> 14.0)." >&2 - echo "Stale cache — rm -rf target/{aarch64,x86_64}-apple-darwin and rebuild." >&2 + echo "Two known causes:" >&2 + echo " 1. A system libopus linked instead of the vendored one (check the build" >&2 + echo " script output for a /opt/homebrew or /usr/local link-search path). This" >&2 + echo " script exports OPUS_NO_PKG_CONFIG=1 to prevent it — if you see it anyway," >&2 + echo " something overrode that." >&2 + echo " 2. A stale cache: cargo does not fingerprint MACOSX_DEPLOYMENT_TARGET." >&2 + echo " rm -rf target/{aarch64,x86_64}-apple-darwin and rebuild." >&2 + echo "Identify the offenders with: ar x $obj && otool -l *.o | grep -B1 minos" >&2 exit 1 fi done