diff --git a/README.md b/README.md index d764f27..7bd0b1b 100644 --- a/README.md +++ b/README.md @@ -354,32 +354,53 @@ See `documentation/PROJECT__AE_Events_Launcher_Native_integration.md` Section 8 ### One-Time: Build the `display_control` Binary (macOS) -The `display_control` binary provides native CoreGraphics display mirror/extend without any Homebrew dependency. It must be compiled once on a Mac and committed to the repo so it is bundled into every packaged app. +The `display_control` binary provides native CoreGraphics display mirror/extend without any Homebrew dependency. It must be compiled on a Mac (Xcode CLT required) and committed to the repo so it is bundled into every packaged app. Produces a universal binary (x86_64 + arm64) that runs on both Intel and Apple Silicon Macs. + +Rebuild only if `scripts/display_control.m` changes. + +#### Option A — From the Linux workstation (preferred) + +Laptop 01 (`192.168.32.101`) is the designated build Mac — Xcode CLT is installed there. +The remote build script copies the source over SSH, compiles on that Mac, and pulls the binary back. ```bash -# Requires Xcode Command Line Tools (one-time install): -xcode-select --install +# From the repo root on the workstation: +./scripts/remote-build-display-control.sh -# From the repo root: +# Override the build Mac IP if needed: +./scripts/remote-build-display-control.sh 192.168.32.102 +``` + +The script prints `file resources/bin/display_control` at the end. Confirm both arches appear: +``` +resources/bin/display_control: Mach-O universal binary with 2 architectures: [x86_64] [arm64] +``` + +Then commit: +```bash +git add resources/bin/display_control +git commit -m "build: update display_control binary (universal)" +``` + +#### Option B — Directly on a Mac + +If you have repo access on the Mac itself (Xcode CLT required — `xcode-select --install`): + +```bash ./scripts/build-display-control.sh - -# The script compiles x86_64 and arm64 separately then links a universal binary. -# Expected output at the end: x86_64 arm64 +# Expected last output line: x86_64 arm64 # Test with a second display connected: ./resources/bin/display_control status ./resources/bin/display_control extend ./resources/bin/display_control mirror -# Commit the binary: git add resources/bin/display_control -git commit -m "build: add display_control binary (macOS CoreGraphics)" +git commit -m "build: update display_control binary (universal)" ``` Once committed, `brew install displayplacer` is no longer required on any venue Mac. The `displayplacer` fallback remains in the handler only for `configStr` per-device overrides. -Rebuild only if `scripts/display_control.m` changes. - --- ### Build Requirements (System Dependencies) diff --git a/scripts/remote-build-display-control.sh b/scripts/remote-build-display-control.sh new file mode 100755 index 0000000..4abc7d0 --- /dev/null +++ b/scripts/remote-build-display-control.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# scripts/remote-build-display-control.sh +# Build the display_control universal binary on a remote Mac via SSH, +# then pull the result back to resources/bin/display_control. +# +# Use this from the Linux workstation when you don't have a Mac locally. +# The target Mac must have Xcode Command Line Tools installed. +# +# USAGE: +# ./scripts/remote-build-display-control.sh # uses default Mac (laptop 01) +# ./scripts/remote-build-display-control.sh 192.168.32.102 +# +# The default IP is laptop 01 — the designated build Mac. +# Change DEFAULT_IP below if Xcode moves to a different laptop. +# +# SSH key must already be installed on the target: +# ssh-copy-id "speaker ready"@192.168.32.101 + +set -eo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +SRC="$SCRIPT_DIR/display_control.m" +OUT_BIN="$REPO_ROOT/resources/bin/display_control" + +SSH_USER="speaker ready" +DEFAULT_IP="192.168.32.101" +IP="${1:-$DEFAULT_IP}" + +REMOTE_TMP="/tmp/ae_display_control_build" + +echo "═══════════════════════════════════════════════" +echo " Remote build: display_control" +echo " Build Mac: $SSH_USER @ $IP" +echo "═══════════════════════════════════════════════" + +# ── Step 1: Copy source to remote ──────────────────────────────────────────── + +echo "" +echo "Step 1/4 — Copying source to $IP..." +ssh "$SSH_USER@$IP" "mkdir -p $REMOTE_TMP" +scp "$SRC" "$SSH_USER@$IP:$REMOTE_TMP/display_control.m" + +# ── Step 2: Build universal binary on remote ────────────────────────────────── + +echo "" +echo "Step 2/4 — Building on $IP..." +ssh "$SSH_USER@$IP" bash << 'ENDSSH' +set -e +REMOTE_TMP="/tmp/ae_display_control_build" +SRC="$REMOTE_TMP/display_control.m" +TMP_X86="$REMOTE_TMP/display_control_x86_64" +TMP_ARM="$REMOTE_TMP/display_control_arm64" +OUT="$REMOTE_TMP/display_control" + +echo " Compiling x86_64..." +clang -arch x86_64 -framework Cocoa -framework Carbon -o "$TMP_X86" "$SRC" + +echo " Compiling arm64..." +clang -arch arm64 -framework Cocoa -framework Carbon -o "$TMP_ARM" "$SRC" + +echo " Linking universal binary..." +lipo -create -output "$OUT" "$TMP_X86" "$TMP_ARM" +rm "$TMP_X86" "$TMP_ARM" +chmod +x "$OUT" + +echo " Archs: $(lipo -archs "$OUT")" +ENDSSH + +# ── Step 3: Pull binary back ────────────────────────────────────────────────── + +echo "" +echo "Step 3/4 — Pulling binary to resources/bin/..." +mkdir -p "$(dirname "$OUT_BIN")" +scp "$SSH_USER@$IP:$REMOTE_TMP/display_control" "$OUT_BIN" +chmod +x "$OUT_BIN" + +# ── Step 4: Clean up remote ─────────────────────────────────────────────────── + +echo "" +echo "Step 4/4 — Cleaning up remote..." +ssh "$SSH_USER@$IP" "rm -rf $REMOTE_TMP" + +# ── Done ────────────────────────────────────────────────────────────────────── + +echo "" +echo "═══════════════════════════════════════════════" +echo " Built: $OUT_BIN" +file "$OUT_BIN" +echo "" +echo " If both archs shown above, you're good:" +echo " git add resources/bin/display_control" +echo " git commit -m \"build: update display_control binary (universal)\"" +echo "═══════════════════════════════════════════════"