Build both and combine
# Build for Intel
cargo build --release --target x86_64-apple-darwin
# Build for Apple Silicon
cargo build --release --target aarch64-apple-darwin
# Combine into a universal binary
lipo -create \
target/x86_64-apple-darwin/release/myapp \
target/aarch64-apple-darwin/release/myapp \
-output target/universal/myapp
lipo is Apple's tool for combining architecture slices into a single binary. It ships with Xcode Command Line Tools.
Tauri's built-in support
Tauri v2 handles this for you:
cargo tauri build --target universal-apple-darwin
One command. Tauri builds both architectures, runs lipo, packages the DMG. Done.
The sidecar problem
If your app bundles sidecar binaries (Swift CLIs, ADB, ffmpeg, etc.), each one also needs to be a universal binary.
For binaries you compile yourself:
# Build Swift CLI for both architectures
swiftc -target x86_64-apple-macosx10.15 MyUtil.swift -o MyUtil-x86
swiftc -target arm64-apple-macosx11.0 MyUtil.swift -o MyUtil-arm64
lipo -create MyUtil-x86 MyUtil-arm64 -output MyUtil
For third-party binaries (like ADB): check if the vendor provides a universal binary. If not, you'll need to bundle both and select the right one at runtime based on std::env::consts::ARCH.
Verifying the output
file target/universal/myapp
# myapp: Mach-O universal binary with 2 architectures:
# [x86_64:Mach-O 64-bit executable x86_64]
# [arm64:Mach-O 64-bit executable arm64]
lipo -info target/universal/myapp
# Architectures in the fat file: x86_64 arm64
If you see both architectures, you're done.
Binary size
Universal binaries are roughly 2x the size of a single-architecture binary. For a typical Tauri app this means going from ~5MB to ~10MB. Acceptable for a DMG download.
Hiyoko PDF Vault → https://hiyokoko.gumroad.com/l/HiyokoPDFVault
X → @hiyoyok