@@ -41,46 +41,50 @@ jobs:
4141 fail-fast : false
4242 matrix :
4343 include :
44- # Apple Silicon — macos-latest resolves to an M-series ARM64 runner.
45- - runner : macos-latest
46- arch : aarch64
44+ # Apple Silicon — native build on ARM64 runner.
45+ - arch : aarch64
46+ target : aarch64-apple-darwin
47+ cross : false
4748
48- # Intel x86_64 — macos-13 was retired Dec 2025; macos-15-large is
49- # the current Intel runner. Intel support ends Fall 2027.
50- - runner : macos-15-large
51- arch : x86_64
49+ # Intel x86_64 — cross-compiled from ARM64 runner (free tier).
50+ # macos-13 was retired Dec 2025; paid large runners not needed.
51+ - arch : x86_64
52+ target : x86_64-apple-darwin
53+ cross : true
54+
55+ # Both legs run on the free ARM64 runner.
56+ runs-on : macos-latest
5257
5358 steps :
5459 - name : Checkout repository
5560 uses : actions/checkout@v4
5661
5762 - name : Install Rust stable
5863 uses : dtolnay/rust-toolchain@stable
64+ with :
65+ targets : ${{ matrix.target }}
5966
6067 # Cache ~/.cargo/registry, ~/.cargo/git, and the target directory.
6168 # The cache key includes Cargo.lock so a lockfile change busts the cache.
6269 - name : Cache Cargo registry and build artifacts
6370 uses : Swatinem/rust-cache@v2
71+ with :
72+ key : ${{ matrix.target }}
6473
6574 # Build all three binary crates in a single workspace compile.
66- # The resulting binaries land in target/release/{clx,clx-hook,clx-mcp} .
75+ # Cross-compiled binaries land in target/<target>/ release/.
6776 - name : Build release binaries
68- run : cargo build --release --workspace
77+ run : cargo build --release --workspace --target ${{ matrix.target }}
6978
70- # Verify the actual CPU architecture matches the matrix expectation.
71- # This guards against silent runner reclassification by GitHub.
72- - name : Verify architecture
79+ # Verify the produced binaries have the expected architecture.
80+ - name : Verify binary architecture
7381 run : |
74- ACTUAL_ARCH=$(uname -m)
75- echo "Runner reports architecture: $ACTUAL_ARCH"
76- if [[ "$ACTUAL_ARCH" != "${{ matrix.arch }}" ]]; then
77- # arm64 is macOS's name for aarch64; treat them as equivalent.
78- if [[ "$ACTUAL_ARCH" == "arm64" && "${{ matrix.arch }}" == "aarch64" ]]; then
79- echo "arm64 == aarch64, continuing"
80- else
81- echo "ERROR: expected ${{ matrix.arch }}, got $ACTUAL_ARCH" >&2
82- exit 1
83- fi
82+ BINARY="target/${{ matrix.target }}/release/clx"
83+ file "$BINARY"
84+ if [[ "${{ matrix.arch }}" == "x86_64" ]]; then
85+ file "$BINARY" | grep -q "x86_64" || { echo "ERROR: binary is not x86_64" >&2; exit 1; }
86+ else
87+ file "$BINARY" | grep -q "arm64" || { echo "ERROR: binary is not arm64" >&2; exit 1; }
8488 fi
8589
8690 # Bundle all three binaries and the pre-built install script into one tarball.
@@ -96,13 +100,14 @@ jobs:
96100 run : |
97101 TARBALL_STEM="clx-${{ matrix.arch }}-apple-darwin"
98102 STAGE_DIR="${TARBALL_STEM}"
103+ BIN_DIR="target/${{ matrix.target }}/release"
99104
100105 mkdir -p "${STAGE_DIR}/bin"
101106
102107 # Copy the three binary crates.
103- cp target/release/ clx "${STAGE_DIR}/bin/"
104- cp target/release/ clx-hook "${STAGE_DIR}/bin/"
105- cp target/release/ clx-mcp "${STAGE_DIR}/bin/"
108+ cp "${BIN_DIR}/ clx" "${STAGE_DIR}/bin/"
109+ cp "${BIN_DIR}/ clx-hook" "${STAGE_DIR}/bin/"
110+ cp "${BIN_DIR}/ clx-mcp" "${STAGE_DIR}/bin/"
106111
107112 # Copy the installer script from the repository root.
108113 cp install.sh "${STAGE_DIR}/install.sh"
0 commit comments