Skip to content

feat(cua-driver): add Intel Mac (x86_64) support via cross-compilation - #1469

Closed
r33drichards wants to merge 3 commits into
mainfrom
openclaw/cua-504-option-a
Closed

feat(cua-driver): add Intel Mac (x86_64) support via cross-compilation#1469
r33drichards wants to merge 3 commits into
mainfrom
openclaw/cua-504-option-a

Conversation

@r33drichards

@r33drichards r33drichards commented May 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes Intel Mac users being unable to install cua-driver via install.sh. The installer already detects uname -m and constructs cua-driver-{VERSION}-darwin-{ARCH}.tar.gz — the darwin-x86_64 artifact just never existed because the CD pipeline only ran on an Apple Silicon (macos-15) runner.

Changes

libs/cua-driver/scripts/build/build-release-notarized.sh

  • ARCH=$(uname -m)ARCH=${ARCH:-$(uname -m)} — allows arch override via env var
  • Swift build conditionally passes --arch $ARCH when cross-compiling (skipped for native builds to preserve current behavior)
  • Binary copy path is now arch-aware: cross-compiled x86_64 output goes to .build/x86_64-apple-macosx/release/cua-driver instead of the .build/release/ symlink

.github/workflows/cd-swift-cua-driver.yml

  • After the existing arm64 build+notarize pass, adds a second pass: ARCH=x86_64 LOG_LEVEL=minimal ./build-release-notarized.sh
  • Adds outputs and upload steps for the x86_64 tarball and pkg
  • Adds darwin-x86_64 artifacts to the Create Release step

Result

Each release now ships both cua-driver-{VERSION}-darwin-arm64.tar.gz and cua-driver-{VERSION}-darwin-x86_64.tar.gz. install.sh requires no changes — it already picks the right one based on uname -m.

Source code changes: none. The Swift codebase is fully architecture-neutral; all frameworks used (AppKit, CoreGraphics, ScreenCaptureKit, SkyLight) are available on Intel macOS 14+.

Closes linear issue CUA-504.

Summary by CodeRabbit

  • Chores
    • Build system now generates optimized releases for both ARM64 and x86_64 architectures, ensuring proper support for different processor types. Installers and archives are now available for both platforms.

Review Change Stack

@vercel

vercel Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview May 11, 2026 2:44am

Request Review

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 11319941-c244-4a3f-ba97-e431b3fb3acf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds cross-compilation support to the Swift CUA driver release pipeline. The build script now detects native architecture and respects an ARCH environment override, conditionally passing architecture flags to Swift and selecting the correct binary path. The CI workflow invokes the build script twice—once for native and once with ARCH=x86_64—captures both artifact outputs, uploads x86_64 binaries separately, and includes them in the GitHub release.

Changes

Cross-Architecture Build and Release

Layer / File(s) Summary
Build script architecture detection
libs/cua-driver/scripts/build/build-release-notarized.sh
Detects native CPU architecture via uname -m and accepts overridable ARCH environment variable. Passes --arch "$ARCH" to Swift build when target architecture differs from native.
Build script binary path selection
libs/cua-driver/scripts/build/build-release-notarized.sh
.app bundle assembly conditionally copies binary from .build/release/ (native) or .build/<arch>-apple-macosx/release/ (cross-compiled) based on ARCH value.
Build script archive section
libs/cua-driver/scripts/build/build-release-notarized.sh
Removes redundant ARCH=$(uname -m) redefinition; derives OS_IDENTIFIER from already-established ARCH for consistent cross-compilation flow.
Workflow build script invocations
.github/workflows/cd-swift-cua-driver.yml
Invokes build/notarization step twice: default native architecture and explicit ARCH=x86_64 cross-compile, both under minimal logging.
Workflow output variable collection
.github/workflows/cd-swift-cua-driver.yml
Captures artifact path variables for both architectures: native tarball_path/pkg_path and x86_64 x86_64_tarball_path/x86_64_pkg_path.
Workflow job output interface
.github/workflows/cd-swift-cua-driver.yml
Exports four outputs: tarball_path, pkg_path, x86_64_tarball_path, x86_64_pkg_path for downstream job use.
Workflow artifact uploads
.github/workflows/cd-swift-cua-driver.yml
Adds two new steps to upload x86_64 notarized tarball and installer package; fails if artifacts are missing.
Workflow GitHub release files
.github/workflows/cd-swift-cua-driver.yml
Updates release creation to include x86_64 tarball and installer package in addition to native artifacts.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Cross compiling swift with care,
arm64 and x86 build everywhere,
Arch flags passed with gentle hand,
Both binaries now released, oh grand!
hop hop hop 🎉

🚥 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 (x86_64) support through cross-compilation, which is the core objective of this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch openclaw/cua-504-option-a

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/cd-swift-cua-driver.yml:
- Around line 175-176: The workflow overwrites .release/CuaDriver.app when
cross-compiling x86_64 (ARCH=x86_64) which later causes the bare-binary
packaging to pick up the wrong-arch app using native `uname -m`; update the
build/packaging steps so each arch writes an arch-suffixed app directory (e.g.
.release/CuaDriver-x86_64.app and .release/CuaDriver-arm64.app) or make the
bare-binary step explicitly point to the correct arched app (e.g. use
.release/CuaDriver-arm64.app when packaging the native runner) instead of
relying on the unsuffixed .release/CuaDriver.app; adjust calls around
build-release-notarized.sh, the ARCH variable usage, and the bare-binary
packaging invocation to reference the suffixed app name.

In `@libs/cua-driver/scripts/build/build-release-notarized.sh`:
- Around line 69-73: The script runs swift build for ARCH-specific and native
builds without failing immediately on build errors or missing artifacts; update
the blocks that invoke swift build (the conditional using ARCH and NATIVE_ARCH
and the later similar block at 83-91) to check the exit status of the swift
build command and verify that the expected $BINARY_PATH exists and is non-empty
right after each build, and if either check fails call echo with a descriptive
error mentioning the ARCH and exit with a non-zero status so the script
hard-fails instead of producing a broken payload.
- Around line 236-237: The cleanup step currently uses a wildcard that removes
artifacts from other-architecture runs; modify the cleanup to only remove
archives for the current architecture by using the OS_IDENTIFIER (set to
"darwin-${ARCH}") or ARCH variable when matching archive filenames in
build-release-notarized.sh so each invocation only deletes its own artifacts
(scope the glob/pattern to ${OS_IDENTIFIER} or ${ARCH} instead of a broad
wildcard).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 416be182-e536-4c52-ae36-2818da3dbc88

📥 Commits

Reviewing files that changed from the base of the PR and between 708b423 and 56764e4.

📒 Files selected for processing (2)
  • .github/workflows/cd-swift-cua-driver.yml
  • libs/cua-driver/scripts/build/build-release-notarized.sh

Comment on lines +175 to +176
# Cross-compile for Intel Mac (x86_64) on this arm64 runner
ARCH=x86_64 LOG_LEVEL=minimal ./build-release-notarized.sh

@coderabbitai coderabbitai Bot May 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Second pass overwrites .release/CuaDriver.app, which can mislabel the bare-binary artifact.

After Line 176, .release/CuaDriver.app is x86_64, but the later bare-binary step names output using native uname -m (arm64 on this runner). That can publish a wrongly labeled binary tarball.

One practical approach
 LOG_LEVEL=minimal ./build-release-notarized.sh
+cp -R .release/CuaDriver.app .release/CuaDriver-arm64.app
 
 # Cross-compile for Intel Mac (x86_64) on this arm64 runner
 ARCH=x86_64 LOG_LEVEL=minimal ./build-release-notarized.sh

Then point the bare-binary packaging step to .release/CuaDriver-arm64.app/... for the native artifact (or produce explicitly arch-suffixed bare binaries from each app).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/cd-swift-cua-driver.yml around lines 175 - 176, The
workflow overwrites .release/CuaDriver.app when cross-compiling x86_64
(ARCH=x86_64) which later causes the bare-binary packaging to pick up the
wrong-arch app using native `uname -m`; update the build/packaging steps so each
arch writes an arch-suffixed app directory (e.g. .release/CuaDriver-x86_64.app
and .release/CuaDriver-arm64.app) or make the bare-binary step explicitly point
to the correct arched app (e.g. use .release/CuaDriver-arm64.app when packaging
the native runner) instead of relying on the unsuffixed .release/CuaDriver.app;
adjust calls around build-release-notarized.sh, the ARCH variable usage, and the
bare-binary packaging invocation to reference the suffixed app name.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

worth addressing @r33drichards

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines +69 to +73
if [ "$ARCH" != "$NATIVE_ARCH" ]; then
swift build -c release --product cua-driver --arch "$ARCH" > /dev/null
else
swift build -c release --product cua-driver > /dev/null
fi

@coderabbitai coderabbitai Bot May 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fail fast if ARCH-specific build output is missing.

Right now, a failed swift build or missing $BINARY_PATH won’t stop the script immediately, which can produce a signed/packageable but broken app payload.

Suggested hardening
 log "essential" "Building release version (arch: $ARCH)..."
 if [ "$ARCH" != "$NATIVE_ARCH" ]; then
-  swift build -c release --product cua-driver --arch "$ARCH" > /dev/null
+  if ! swift build -c release --product cua-driver --arch "$ARCH" > /dev/null; then
+    log "error" "swift build failed for ARCH=$ARCH"
+    exit 1
+  fi
 else
-  swift build -c release --product cua-driver > /dev/null
+  if ! swift build -c release --product cua-driver > /dev/null; then
+    log "error" "swift build failed for native ARCH=$NATIVE_ARCH"
+    exit 1
+  fi
 fi
@@
 if [ "$ARCH" != "$NATIVE_ARCH" ]; then
   BINARY_PATH=".build/${ARCH}-apple-macosx/release/cua-driver"
 else
   BINARY_PATH=".build/release/cua-driver"
 fi
+if [ ! -f "$BINARY_PATH" ]; then
+  log "error" "Expected binary not found at $BINARY_PATH"
+  exit 1
+fi
 cp -f "$BINARY_PATH" "$APP_BUNDLE/Contents/MacOS/cua-driver"

Also applies to: 83-91

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver/scripts/build/build-release-notarized.sh` around lines 69 -
73, The script runs swift build for ARCH-specific and native builds without
failing immediately on build errors or missing artifacts; update the blocks that
invoke swift build (the conditional using ARCH and NATIVE_ARCH and the later
similar block at 83-91) to check the exit status of the swift build command and
verify that the expected $BINARY_PATH exists and is non-empty right after each
build, and if either check fails call echo with a descriptive error mentioning
the ARCH and exit with a non-zero status so the script hard-fails instead of
producing a broken payload.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

worth addressing @r33drichards

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines +236 to 237
# ARCH is already set above (env override or native); derive OS identifier
OS_IDENTIFIER="darwin-${ARCH}"

@coderabbitai coderabbitai Bot May 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Scope archive cleanup to the current architecture.

With dual invocations, the wildcard cleanup on Line 244 deletes artifacts from the first pass (native) before the x86_64 pass finishes, so native upload paths can disappear.

Suggested fix
-# Clean up any existing artifacts first to avoid conflicts
-rm -f cua-driver-*.tar.gz cua-driver-*.pkg.tar.gz
+# Clean up only this arch's artifacts to keep outputs from other arch passes
+rm -f "cua-driver-${VERSION}-${OS_IDENTIFIER}.tar.gz" \
+      "cua-driver-${VERSION}-${OS_IDENTIFIER}.pkg.tar.gz"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/cua-driver/scripts/build/build-release-notarized.sh` around lines 236 -
237, The cleanup step currently uses a wildcard that removes artifacts from
other-architecture runs; modify the cleanup to only remove archives for the
current architecture by using the OS_IDENTIFIER (set to "darwin-${ARCH}") or
ARCH variable when matching archive filenames in build-release-notarized.sh so
each invocation only deletes its own artifacts (scope the glob/pattern to
${OS_IDENTIFIER} or ${ARCH} instead of a broad wildcard).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Builds unsigned darwin-arm64 and darwin-x86_64 binaries on every PR
touching libs/cua-driver, then posts download links as a PR comment.
This lets Intel Mac users test the binary before the PR is merged
without requiring Apple notarization credentials.

Binaries are unsigned/unnotarized — users need:
  xattr -d com.apple.quarantine ./cua-driver
@github-actions

github-actions Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

🔧 Pre-release binaries (unsigned)

Built from commit dfc590c · CI run

Platform Download
macOS — Apple Silicon (arm64) 1469-darwin-arm64
macOS — Intel (x86_64) 1469-darwin-x86_64

⚠️ Unsigned binary — macOS will quarantine it on first download. To run:

# After extracting the tarball:
xattr -d com.apple.quarantine ./cua-driver
chmod +x ./cua-driver
./cua-driver --version

Artifact links require a GitHub login and expire after 90 days.

Three bugs flagged by CodeRabbit:

1. (Critical) Wildcard cleanup clobbers arm64 artifacts on x86_64 pass:
   rm -f cua-driver-*.tar.gz wiped the arm64 tarballs before the x86_64
   pass finished. Fixed by scoping the rm to the current arch's files only.

2. (Critical) swift build failures silently produced broken app bundles:
   Added 'if ! swift build ...' guards and binary path existence check
   so a failed build exits immediately instead of packaging a broken payload.

3. (Major) Bare-binary step used uname -m (always arm64 on runner) but
   CuaDriver.app was x86_64 after the second build pass, causing a
   mislabeled bare binary. Fixed by:
   - Writing arch-suffixed bundles: CuaDriver-arm64.app / CuaDriver-x86_64.app
   - Packaging each via a temporary CuaDriver.app symlink (install.sh compat)
   - Iterating both arches explicitly in the bare-binary packaging step
@r33drichards

Copy link
Copy Markdown
Collaborator Author

this is pending testing on a physical intel macos device

Comment on lines +175 to +176
# Cross-compile for Intel Mac (x86_64) on this arm64 runner
ARCH=x86_64 LOG_LEVEL=minimal ./build-release-notarized.sh

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

worth addressing @r33drichards

Comment on lines +69 to +73
if [ "$ARCH" != "$NATIVE_ARCH" ]; then
swift build -c release --product cua-driver --arch "$ARCH" > /dev/null
else
swift build -c release --product cua-driver > /dev/null
fi

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

worth addressing @r33drichards

Comment on lines +236 to 237
# ARCH is already set above (env override or native); derive OS identifier
OS_IDENTIFIER="darwin-${ARCH}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@f-trycua

Copy link
Copy Markdown
Collaborator

Thanks for tackling this! Closing as superseded by #1490 (merged), which added Intel Mac support via a different mechanism — matrix builds across macos-15 (arm64) and macos-13 (x86_64) runners in cd-swift-cua-driver.yml, rather than cross-compilation. Same outcome: each release now ships both darwin-arm64 and darwin-x86_64 tarballs.

If you want to verify, grab the latest cua-driver release and install.sh should pick the right one for your machine.

Going forward, we're consolidating on the Rust port (libs/cua-driver-rs/, see #1511) which builds natively on all three platforms — that path is BETA on macOS today and should be GA soon.

@f-trycua f-trycua closed this May 16, 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.

3 participants