@@ -255,3 +255,147 @@ jobs:
255255 dist/SHA256SUMS
256256 dist/mcpp-${{ steps.stage.outputs.version }}.tar.gz
257257 dist/mcpp.lua
258+
259+ build-macos :
260+ name : build (macOS / ARM64)
261+ runs-on : macos-15
262+ needs : build-release
263+ permissions :
264+ contents : write
265+ timeout-minutes : 30
266+ steps :
267+ - uses : actions/checkout@v4
268+ with :
269+ fetch-depth : 0
270+
271+ - name : Resolve tag
272+ id : resolve
273+ run : |
274+ if [ "${{ github.event_name }}" = "push" ]; then
275+ TAG="${{ github.ref_name }}"
276+ elif [ -n "${{ github.event.inputs.tag }}" ]; then
277+ TAG="${{ github.event.inputs.tag }}"
278+ else
279+ VER=$(awk -F '"' '/^version[[:space:]]*=/{print $2; exit}' mcpp.toml)
280+ TAG="v$VER"
281+ fi
282+ echo "tag=$TAG" >> "$GITHUB_OUTPUT"
283+ echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
284+ if [ "${{ github.event_name }}" = "workflow_dispatch" ] \
285+ && git rev-parse --verify "refs/tags/$TAG" >/dev/null 2>&1; then
286+ git checkout --detach "refs/tags/$TAG"
287+ fi
288+
289+ - name : Cache xlings
290+ uses : actions/cache@v4
291+ with :
292+ path : ~/.xlings
293+ key : xlings-macos15-release-${{ hashFiles('.xlings.json') }}
294+ restore-keys : |
295+ xlings-macos15-release-
296+ xlings-macos15-arm64-
297+
298+ - name : Bootstrap xlings + LLVM
299+ env :
300+ XLINGS_NON_INTERACTIVE : ' 1'
301+ XLINGS_VERSION : ' 0.4.30'
302+ run : |
303+ if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then
304+ WORK=$(mktemp -d)
305+ tarball="xlings-${XLINGS_VERSION}-macosx-arm64.tar.gz"
306+ curl -fsSL -o "${WORK}/${tarball}" \
307+ "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${tarball}"
308+ tar -xzf "${WORK}/${tarball}" -C "${WORK}"
309+ "${WORK}/xlings-${XLINGS_VERSION}-macosx-arm64/subos/default/bin/xlings" self install
310+ fi
311+ export PATH="$HOME/.xlings/subos/default/bin:$PATH"
312+ xlings --version
313+ # Install LLVM
314+ xlings install llvm -y || xlings install llvm@20.1.7 -y
315+ LLVM_ROOT=$(find "$HOME/.xlings" -path "*/xpkgs/xim-x-llvm/*/bin/clang++" | head -1 | xargs dirname | xargs dirname)
316+ echo "LLVM_ROOT=$LLVM_ROOT" >> "$GITHUB_ENV"
317+
318+ - name : Bootstrap-compile mcpp
319+ env :
320+ PROJROOT : ${{ github.workspace }}
321+ run : |
322+ export LLVM_ROOT="$LLVM_ROOT"
323+ export CXX="$LLVM_ROOT/bin/clang++"
324+ bash scripts/bootstrap-macos.sh "$LLVM_ROOT"
325+ # Verify
326+ ./target/bootstrap/bin/mcpp --version
327+
328+ - name : Self-host rebuild (mcpp builds mcpp)
329+ run : |
330+ # Now use the bootstrapped mcpp to rebuild itself properly
331+ MCPP="./target/bootstrap/bin/mcpp"
332+ "$MCPP" build
333+ # Find the self-hosted binary
334+ SELFHOST=$(find target -path "*/bin/mcpp" -not -path "*/bootstrap/*" | head -1)
335+ test -x "$SELFHOST"
336+ "$SELFHOST" --version
337+ echo "SELFHOST=$SELFHOST" >> "$GITHUB_ENV"
338+
339+ - name : Package macOS release
340+ id : stage
341+ run : |
342+ VERSION="${{ steps.resolve.outputs.version }}"
343+ TARBALL_NAME="mcpp-${VERSION}-darwin-arm64.tar.gz"
344+ WRAPPER="mcpp-${VERSION}-darwin-arm64"
345+
346+ # Create release layout
347+ STAGING=$(mktemp -d)
348+ mkdir -p "$STAGING/$WRAPPER/bin"
349+ cp "$SELFHOST" "$STAGING/$WRAPPER/bin/mcpp"
350+ # Strip (Mach-O)
351+ strip "$STAGING/$WRAPPER/bin/mcpp" 2>/dev/null || true
352+ # Copy metadata
353+ cp LICENSE "$STAGING/$WRAPPER/" 2>/dev/null || true
354+ cp README.md "$STAGING/$WRAPPER/" 2>/dev/null || true
355+
356+ # Shell launcher (same as Linux)
357+ cat > "$STAGING/$WRAPPER/mcpp" << 'LAUNCHER'
358+ #!/bin/sh
359+ exec "$(dirname "$0")/bin/mcpp" "$@"
360+ LAUNCHER
361+ chmod +x "$STAGING/$WRAPPER/mcpp"
362+
363+ # Bundle xlings for install.sh consumers
364+ XLINGS_BIN="$HOME/.xlings/subos/default/bin/xlings"
365+ if [ -x "$XLINGS_BIN" ]; then
366+ mkdir -p "$STAGING/$WRAPPER/registry/bin"
367+ cp "$XLINGS_BIN" "$STAGING/$WRAPPER/registry/bin/xlings"
368+ chmod +x "$STAGING/$WRAPPER/registry/bin/xlings"
369+ fi
370+
371+ # Create tarball
372+ mkdir -p dist
373+ (cd "$STAGING" && tar -czf "$GITHUB_WORKSPACE/dist/${TARBALL_NAME}" "$WRAPPER")
374+ # Versionless alias
375+ cp "dist/${TARBALL_NAME}" "dist/mcpp-darwin-arm64.tar.gz"
376+ # SHA256
377+ (cd dist && shasum -a 256 "${TARBALL_NAME}" > "${TARBALL_NAME}.sha256")
378+ (cd dist && shasum -a 256 "mcpp-darwin-arm64.tar.gz" > "mcpp-darwin-arm64.tar.gz.sha256")
379+
380+ echo "tarball=${TARBALL_NAME}" >> "$GITHUB_OUTPUT"
381+ ls -la dist/
382+
383+ - name : Smoke-test the tarball
384+ run : |
385+ VERSION="${{ steps.resolve.outputs.version }}"
386+ TARBALL_NAME="${{ steps.stage.outputs.tarball }}"
387+ WRAPPER="${TARBALL_NAME%.tar.gz}"
388+ SMOKE=$(mktemp -d)
389+ tar -xzf "dist/${TARBALL_NAME}" -C "$SMOKE"
390+ "$SMOKE/$WRAPPER/bin/mcpp" --version
391+ "$SMOKE/$WRAPPER/mcpp" --version | grep -q "$VERSION"
392+
393+ - name : Upload macOS artifacts to release
394+ uses : softprops/action-gh-release@v2
395+ with :
396+ tag_name : ${{ steps.resolve.outputs.tag }}
397+ files : |
398+ dist/mcpp-${{ steps.resolve.outputs.version }}-darwin-arm64.tar.gz
399+ dist/mcpp-${{ steps.resolve.outputs.version }}-darwin-arm64.tar.gz.sha256
400+ dist/mcpp-darwin-arm64.tar.gz
401+ dist/mcpp-darwin-arm64.tar.gz.sha256
0 commit comments