From 944187beedc044698d32cdfa8c86ced7e73ff0f5 Mon Sep 17 00:00:00 2001 From: Prakash Rudraraju <1471544+prakashrj@users.noreply.github.com> Date: Wed, 26 Aug 2026 16:05:35 -0700 Subject: [PATCH] build: produce a universal (arm64 + x86_64) macOS slice The macOS build is Apple-Silicon-only by construction, so an app embedding TailscaleKit cannot produce a universal macOS release build: TailscaleKit.xcframework is missing architecture(s) required by this target (x86_64), but may still be link-compatible Two places pin it. The root Makefile's `c-archive` builds libtailscale.a for the host arch, because no GOARCH is set. And swift/Makefile's `macos` target passes -destination 'platform=macOS,arch=arm64', so the framework is built for one arch even if the archive were fat. The iOS Simulator target already solves exactly this: separate GOARCH=arm64 and GOARCH=amd64 c-archives joined with lipo, each built through a clangwrap script that pins the SDK and arch. This mirrors that pattern for macOS rather than inventing a second approach: - clangwrap-macos-arm.sh / clangwrap-macos-x86.sh, matching the existing ios-sim wrappers and pinning -mmacos-version-min to MACOS_TARGET (15.0) - libtailscale_macos_arm64.a and libtailscale_macos_x86_64.a - c-archive-macos-universal, which lipos them into libtailscale.a - swift/Makefile's macos target now uses c-archive-macos-universal and builds with -destination 'generic/platform=macOS' ARCHS="arm64 x86_64" `make c-archive` is untouched, so anything building for the host only keeps its current behaviour. Verified on an Apple Silicon host: lipo -info libtailscale.a -> Architectures in the fat file: x86_64 arm64 make -C swift macos lipo -info swift/build/Build/Products/Release/TailscaleKit.framework/Versions/A/TailscaleKit -> Architectures in the fat file: x86_64 arm64 Updates tailscale/tailscale#20992 --- Makefile | 10 ++++++++++ swift/Makefile | 5 +++-- swift/script/clangwrap-macos-arm.sh | 11 +++++++++++ swift/script/clangwrap-macos-x86.sh | 11 +++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100755 swift/script/clangwrap-macos-arm.sh create mode 100755 swift/script/clangwrap-macos-x86.sh diff --git a/Makefile b/Makefile index cbbb224..5af89fd 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,16 @@ libtailscale_ios_sim_arm64.a: libtailscale_ios_sim_x86_64.a: GOOS=ios GOARCH=amd64 CC=$(PWD)/swift/script/clangwrap-ios-sim-x86.sh go build -v -ldflags -w -tags ios -o $@ -buildmode=c-archive +libtailscale_macos_arm64.a: + GOOS=darwin GOARCH=arm64 CC=$(PWD)/swift/script/clangwrap-macos-arm.sh $(DARWIN_DEPLOYMENT_TARGET) go build -v -ldflags -w -o $@ -buildmode=c-archive + +libtailscale_macos_x86_64.a: + GOOS=darwin GOARCH=amd64 CC=$(PWD)/swift/script/clangwrap-macos-x86.sh $(DARWIN_DEPLOYMENT_TARGET) go build -v -ldflags -w -o $@ -buildmode=c-archive + +.PHONY: c-archive-macos-universal +c-archive-macos-universal: libtailscale_macos_arm64.a libtailscale_macos_x86_64.a ## Builds a universal (arm64 + x86_64) libtailscale.a for macOS + lipo -create -output libtailscale.a libtailscale_macos_arm64.a libtailscale_macos_x86_64.a + .PHONY: c-archive-ios c-archive-ios: libtailscale_ios.a ## Builds libtailscale_ios.a for iOS (iOS SDK required) diff --git a/swift/Makefile b/swift/Makefile index 4071ff0..63a08c1 100644 --- a/swift/Makefile +++ b/swift/Makefile @@ -17,12 +17,13 @@ all: test ios macos ios-fat ## Runs the tests and builds all library targets macos: ## Builds TailscaleKit for macos to swift/build/Build/Products/Release (unsigned) @echo @echo "::: Building TailscaleKit.framework for macOS :::" - cd .. && make c-archive + cd .. && make c-archive-macos-universal mkdir -p build xcodebuild build -scheme "TailscaleKit (macOS)" \ -derivedDataPath build \ -configuration Release \ - -destination 'platform=macOS,arch=arm64' \ + -destination 'generic/platform=macOS' \ + ARCHS="arm64 x86_64" ONLY_ACTIVE_ARCH=NO \ CODE_SIGNING_ALLOWED=NO | $(XCPRETTIFIER) .PHONY: ios diff --git a/swift/script/clangwrap-macos-arm.sh b/swift/script/clangwrap-macos-arm.sh new file mode 100755 index 0000000..fa88630 --- /dev/null +++ b/swift/script/clangwrap-macos-arm.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +SDK=macosx +CLANGARCH=arm64 + +SDK_PATH=`xcrun --sdk $SDK --show-sdk-path` + +# cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang. +CLANG=`xcrun --sdk $SDK --find clang` + +exec "$CLANG" -arch $CLANGARCH -isysroot "$SDK_PATH" -mmacos-version-min=15.0 "$@" diff --git a/swift/script/clangwrap-macos-x86.sh b/swift/script/clangwrap-macos-x86.sh new file mode 100755 index 0000000..5849ade --- /dev/null +++ b/swift/script/clangwrap-macos-x86.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +SDK=macosx +CLANGARCH=x86_64 + +SDK_PATH=`xcrun --sdk $SDK --show-sdk-path` + +# cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang. +CLANG=`xcrun --sdk $SDK --find clang` + +exec "$CLANG" -arch $CLANGARCH -isysroot "$SDK_PATH" -mmacos-version-min=15.0 "$@"