Skip to content

feat: Add Intel (x86_64) Mac support via universal binary builds - #534

Closed
pmochine wants to merge 3 commits into
manaflow-ai:mainfrom
pmochine:feat/universal-binary-x86_64-support
Closed

pmochine wants to merge 3 commits into
manaflow-ai:mainfrom
pmochine:feat/universal-binary-x86_64-support

Conversation

@pmochine

@pmochine pmochine commented Feb 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #293 — cmux currently ships as arm64-only, preventing installation on Intel Macs.

This PR makes 3 minimal changes to produce a Universal Binary (arm64 + x86_64):

  1. GhosttyKit.xcframework: Build with -Dxcframework-target=universal instead of native/unspecified in all release & nightly build paths
  2. Xcode project: Set ONLY_ACTIVE_ARCH = NO for the main app Release configuration so Xcode compiles Swift code for both architectures

Files changed (4 files, 4 lines)

File Change
scripts/build-sign-upload.sh:64 -Dxcframework-target=native → universal
.github/workflows/release.yml:117 Added -Dxcframework-target=universal (was missing)
.github/workflows/nightly.yml:123 -Dxcframework-target=native → universal
GhosttyTabs.xcodeproj/project.pbxproj:799 ONLY_ACTIVE_ARCH = YES → NO (Release config only)

What was NOT changed (by design)

  • scripts/setup.sh: Keeps no explicit xcframework-target — builds for the developer's native architecture (works on both Intel and Apple Silicon for local dev)
  • Debug configurations: Keep ONLY_ACTIVE_ARCH = YES for fast dev builds
  • Test target configs: Keep ONLY_ACTIVE_ARCH = YES

Why this works

  • Ghostty's Zig build system already supports -Dxcframework-target=universal, which cross-compiles both arm64 and x86_64 slices into the xcframework (Ghostty itself ships as a Universal Binary)
  • Zig handles cross-compilation natively — no additional CI runners or toolchains needed
  • The self-hosted CI runner (Apple Silicon) can cross-compile x86_64 via Zig
  • All Swift/AppKit code is architecture-agnostic — no arch-specific code exists in cmux
  • Code signing, notarization, and Sparkle updates work identically with universal binaries

Verification

After building, the output can be verified with:

lipo -archs build/Build/Products/Release/cmux.app/Contents/MacOS/cmux
# Expected: arm64 x86_64

lipo -archs GhosttyKit.xcframework/macos-arm64_x86_64/GhosttyKit.framework/GhosttyKit
# Expected: arm64 x86_64

Test plan

  • CI builds successfully with universal GhosttyKit.xcframework
  • Release DMG contains universal binary (both arm64 and x86_64 slices)
  • App launches on Apple Silicon Mac
  • App launches on Intel Mac (ideally real hardware or x86_64 VM)
  • Embedded CLI (Contents/Resources/bin/cmux) is also universal
  • Code signing and notarization pass
  • Sparkle update from current arm64-only build to new universal build works

Summary by CodeRabbit

  • Chores
    • Build workflows and scripts updated to produce universal xcframeworks by default, with logic to rebuild when slices are missing.
    • Release build configurations adjusted to disable "only active architecture" for Release builds.
  • Bug Fixes
    • Improved build reliability and messaging around skipping or forcing framework rebuilds.

Build GhosttyKit.xcframework with -Dxcframework-target=universal instead
of native/unspecified, and set ONLY_ACTIVE_ARCH=NO for the main app
Release configuration so Xcode produces a universal (arm64 + x86_64)
binary.

Closes manaflow-ai#293
@vercel

vercel Bot commented Feb 26, 2026

Copy link
Copy Markdown

@pmochine is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@pmochine

Copy link
Copy Markdown
Contributor Author

✅ Build verified on Apple Silicon

I built this locally and can confirm:

$ lipo -archs build/Build/Products/Release/cmux.app/Contents/MacOS/cmux
x86_64 arm64

$ lipo -archs build/Build/Products/Release/cmux.app/Contents/Resources/bin/cmux
x86_64 arm64

Both the app binary and the embedded CLI are universal. The app launches and runs fine on Apple Silicon.

🧪 Test build available for Intel Mac testers

I uploaded an unsigned test build for anyone who wants to verify on Intel hardware:

👉 Download cmux-universal-unsigned.zip

To install:

  1. Unzip and move cmux.app to /Applications/
  2. Run xattr -cr /Applications/cmux.app in Terminal
  3. Open cmux

⚠️ Unsigned — for testing only. Feedback welcome!

@lawrencecchen

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 104af83c17

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if [ ! -d "GhosttyKit.xcframework" ]; then
echo "Building GhosttyKit..."
cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native -Doptimize=ReleaseFast && cd ..
cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=universal -Doptimize=ReleaseFast && cd ..

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Rebuild GhosttyKit for universal release builds

This now requests a universal GhosttyKit build, but build-sign-upload.sh still skips the build whenever GhosttyKit.xcframework already exists (the common case after scripts/setup.sh, which builds/seeds a native-arch framework). With this commit also setting app Release builds to ONLY_ACTIVE_ARCH=NO, local release builds will attempt x86_64 and fail to link against an existing arm64-only GhosttyKit slice. Please force a rebuild (or validate slices) in release packaging instead of reusing any preexisting xcframework directory.

Useful? React with 👍 / 👎.

@lawrencecchen

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 104af83c17

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 62 to +64
if [ ! -d "GhosttyKit.xcframework" ]; then
echo "Building GhosttyKit..."
cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native -Doptimize=ReleaseFast && cd ..
cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=universal -Doptimize=ReleaseFast && cd ..

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rebuild GhosttyKit when producing universal release builds

With Release now set to build all architectures (ONLY_ACTIVE_ARCH = NO in GhosttyTabs.xcodeproj/project.pbxproj), this conditional skip can leave a previously built native-only GhosttyKit.xcframework in place, which is common after scripts/setup.sh (it builds GhosttyKit without a universal target). In that state, ./scripts/build-sign-upload.sh can fail during Release xcodebuild or otherwise miss the intended universal dependency slices; the script should verify the existing xcframework has both arm64 and x86_64 slices (or always rebuild universal for release packaging).

Useful? React with 👍 / 👎.

The release script previously skipped the GhosttyKit build whenever
the xcframework directory existed, even if it only contained a
native (arm64-only) build from setup.sh. With ONLY_ACTIVE_ARCH=NO
the Release build now needs both slices, so check for the
macos-arm64_x86_64 directory before reusing the cached framework.

Addresses review feedback from Codex.
@coderabbitai

coderabbitai Bot commented Feb 27, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a1f92d and bae64d6.

📒 Files selected for processing (1)
  • GhosttyTabs.xcodeproj/project.pbxproj

📝 Walkthrough

Walkthrough

Updates CI and build tooling to produce universal (arm64 + x86_64) xcframeworks: workflow flags changed, Xcode Release configs set to build non-only-active-arch, and the build script now detects missing x86_64 slices and triggers a universal rebuild when needed.

Changes

Cohort / File(s) Summary
Workflows
​.github/workflows/nightly.yml, ​.github/workflows/release.yml
Changed xcframework build flag to -Dxcframework-target=universal (was native / unspecified) to produce universal xcframeworks.
Xcode Project
GhosttyTabs.xcodeproj/project.pbxproj
Set ONLY_ACTIVE_ARCH = NO in Release configurations (two entries) to allow building multiple architectures.
Build Script
scripts/build-sign-upload.sh
Added NEED_BUILD detection and logic to rebuild GhosttyKit.xcframework if missing or lacking macOS x86_64 slice; switched build invocation to produce universal xcframework and updated messages/cleanup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰
Hop, hop — the build grew two-feet wide,
Arm and Intel now jump side by side.
I nibble code and polish the crate,
Universal treats at the update gate. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding Intel Mac support via universal binary builds, which aligns with the primary objective of the PR.
Linked Issues check ✅ Passed All code changes directly address issue #293 requirements: build system now produces universal binaries (arm64+x86_64) for both the app and embedded CLI, enabling Intel Mac support.
Out of Scope Changes check ✅ Passed All changes are scoped to delivering universal binary support: build workflow modifications, Xcode project configuration, and build script logic to prevent stale xcframework reuse.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@GhosttyTabs.xcodeproj/project.pbxproj`:
- Line 799: The cmux-cli Release build is inheriting the project-level config
(A5001081) which lacks ONLY_ACTIVE_ARCH, causing cmux-cli (target
B9000009A1B2C3D4E5F60719) to build only the active arch; add ONLY_ACTIVE_ARCH =
NO; to the cmux-cli Release configuration block (the cmux-cli target's Release
config) so it matches GhosttyTabs' Release setting and produces a universal
binary.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2dea894 and 8a1f92d.

📒 Files selected for processing (4)
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • GhosttyTabs.xcodeproj/project.pbxproj
  • scripts/build-sign-upload.sh

Comment thread GhosttyTabs.xcodeproj/project.pbxproj
@pmochine

Copy link
Copy Markdown
Contributor Author

Addressed Codex review feedback

Pushed a follow-up commit (8a1f92d) that fixes the stale xcframework reuse issue flagged by the review.

The problem: build-sign-upload.sh skipped the GhosttyKit build whenever the directory existed — but after setup.sh it could be arm64-only, which would break Release builds now that ONLY_ACTIVE_ARCH=NO.

The fix: Check for the macos-arm64_x86_64 directory before reusing the cached framework. If only a native (single-arch) build exists, it rebuilds as universal.

# Before: blind existence check
if [ ! -d "GhosttyKit.xcframework" ]; then

# After: also checks for universal slices
if [ ! -d "GhosttyKit.xcframework" ]; then
  NEED_BUILD="true"
elif [ ! -d "GhosttyKit.xcframework/macos-arm64_x86_64" ]; then
  echo "GhosttyKit.xcframework exists but is not universal, rebuilding..."
  NEED_BUILD="true"
fi

Explicitly set the CLI target to build for all architectures in
Release, rather than relying on Xcode defaults. Ensures the
embedded CLI binary is always universal.

Addresses CodeRabbit review feedback.
@pmochine

pmochine commented Mar 3, 2026

Copy link
Copy Markdown
Contributor Author

Addressed CodeRabbit feedback

Pushed bae64d6 — added explicit ONLY_ACTIVE_ARCH = NO to the cmux-cli Release target.

Our build already produced a universal CLI binary (verified with lipo -archs), but this makes the intent explicit rather than relying on Xcode defaults.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

@noahvandal

Copy link
Copy Markdown

I tested this and it works great on my Intel Silicon Mac!

#534 (comment)

@teamleaderleo

Copy link
Copy Markdown
Collaborator

cmux-reconcile: close-candidate

Usefulness verdict: Close the initial universal-build proposal as superseded.

The release workflow already builds ARCHS="arm64 x86_64", builds the universal Ghostty helper, and verifies architecture slices. The nightly workflow also has universal handling. The inspected PR changes old release wiring and GhosttyTabs.xcodeproj to add that basic support; its arm64-only premise no longer applies. #4744 is separate guard-consolidation work, not a dependency for initial Intel support.

Reviewed patch head: bae64d6f95ef04ef722a2e8dd3ca741c3a220508. Source/diff triage on September 18, 2026; no new build or runtime validation. No issue state, label, or merge decision changed.

Older issue/PR tracking index — remaining scope and competing implementations are recorded there.

@pmochine

Copy link
Copy Markdown
Contributor Author

Agreed, this can close.

The universal build landed in #2287, which sets ARCHS="arm64 x86_64" and ONLY_ACTIVE_ARCH=NO in the stable release workflow and adds an architecture verification step. The nightly track went universal earlier, in #1067. This PR also edits GhosttyTabs.xcodeproj, which no longer exists, so there is nothing here worth rebasing.

For anyone who reaches this from #293 later, the short history:

  • 2026-02-26: Opened, with a local lipo -archs check and an unsigned universal test build for Intel testers.
  • 2026-02-27: Codex review addressed. build-sign-upload.sh reused a cached GhosttyKit.xcframework on a plain existence check, and that framework can be arm64-only after setup.sh. The fix checks for the macos-arm64_x86_64 slice before reusing it.
  • 2026-03-03: CodeRabbit review addressed. ONLY_ACTIVE_ARCH = NO set explicitly on the cmux-cli Release target.
  • 2026-03-17: @noahvandal confirmed a working build on Intel hardware.
  • 2026-03-28: Build universal binary in stable release workflow #2287 merged, with the same two build settings.

Thanks @noahvandal for testing on real Intel hardware, and thanks for the reconciliation pass. Closing.

@pmochine pmochine closed this Sep 19, 2026
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.

Intel (x86_64) Mac support

4 participants