@@ -255,3 +255,146 @@ 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 : Install xmake (for bootstrap)
319+ run : brew install xmake
320+
321+ - name : Bootstrap-compile mcpp (xmake + LLVM)
322+ run : |
323+ export LLVM_ROOT="$LLVM_ROOT"
324+ bash scripts/bootstrap-macos.sh "$LLVM_ROOT"
325+ ./target/bootstrap/bin/mcpp --version
326+
327+ - name : Self-host rebuild (mcpp builds mcpp)
328+ run : |
329+ # Put bootstrapped mcpp on PATH so build.ninja can find it for dyndep
330+ export PATH="$PWD/target/bootstrap/bin:$PATH"
331+ mcpp build
332+ # Find the self-hosted binary
333+ SELFHOST=$(find target -path "*/bin/mcpp" -not -path "*/bootstrap/*" -not -path "*/build/*" | head -1)
334+ test -x "$SELFHOST"
335+ "$SELFHOST" --version
336+ echo "SELFHOST=$SELFHOST" >> "$GITHUB_ENV"
337+
338+ - name : Package macOS release
339+ id : stage
340+ run : |
341+ VERSION="${{ steps.resolve.outputs.version }}"
342+ TARBALL_NAME="mcpp-${VERSION}-darwin-arm64.tar.gz"
343+ WRAPPER="mcpp-${VERSION}-darwin-arm64"
344+
345+ # Create release layout
346+ STAGING=$(mktemp -d)
347+ mkdir -p "$STAGING/$WRAPPER/bin"
348+ cp "$SELFHOST" "$STAGING/$WRAPPER/bin/mcpp"
349+ # Strip (Mach-O)
350+ strip "$STAGING/$WRAPPER/bin/mcpp" 2>/dev/null || true
351+ # Copy metadata
352+ cp LICENSE "$STAGING/$WRAPPER/" 2>/dev/null || true
353+ cp README.md "$STAGING/$WRAPPER/" 2>/dev/null || true
354+
355+ # Shell launcher (same as Linux)
356+ cat > "$STAGING/$WRAPPER/mcpp" << 'LAUNCHER'
357+ #!/bin/sh
358+ exec "$(dirname "$0")/bin/mcpp" "$@"
359+ LAUNCHER
360+ chmod +x "$STAGING/$WRAPPER/mcpp"
361+
362+ # Bundle xlings for install.sh consumers
363+ XLINGS_BIN="$HOME/.xlings/subos/default/bin/xlings"
364+ if [ -x "$XLINGS_BIN" ]; then
365+ mkdir -p "$STAGING/$WRAPPER/registry/bin"
366+ cp "$XLINGS_BIN" "$STAGING/$WRAPPER/registry/bin/xlings"
367+ chmod +x "$STAGING/$WRAPPER/registry/bin/xlings"
368+ fi
369+
370+ # Create tarball
371+ mkdir -p dist
372+ (cd "$STAGING" && tar -czf "$GITHUB_WORKSPACE/dist/${TARBALL_NAME}" "$WRAPPER")
373+ # Versionless alias
374+ cp "dist/${TARBALL_NAME}" "dist/mcpp-darwin-arm64.tar.gz"
375+ # SHA256
376+ (cd dist && shasum -a 256 "${TARBALL_NAME}" > "${TARBALL_NAME}.sha256")
377+ (cd dist && shasum -a 256 "mcpp-darwin-arm64.tar.gz" > "mcpp-darwin-arm64.tar.gz.sha256")
378+
379+ echo "tarball=${TARBALL_NAME}" >> "$GITHUB_OUTPUT"
380+ ls -la dist/
381+
382+ - name : Smoke-test the tarball
383+ run : |
384+ VERSION="${{ steps.resolve.outputs.version }}"
385+ TARBALL_NAME="${{ steps.stage.outputs.tarball }}"
386+ WRAPPER="${TARBALL_NAME%.tar.gz}"
387+ SMOKE=$(mktemp -d)
388+ tar -xzf "dist/${TARBALL_NAME}" -C "$SMOKE"
389+ "$SMOKE/$WRAPPER/bin/mcpp" --version
390+ "$SMOKE/$WRAPPER/mcpp" --version | grep -q "$VERSION"
391+
392+ - name : Upload macOS artifacts to release
393+ uses : softprops/action-gh-release@v2
394+ with :
395+ tag_name : ${{ steps.resolve.outputs.tag }}
396+ files : |
397+ dist/mcpp-${{ steps.resolve.outputs.version }}-darwin-arm64.tar.gz
398+ dist/mcpp-${{ steps.resolve.outputs.version }}-darwin-arm64.tar.gz.sha256
399+ dist/mcpp-darwin-arm64.tar.gz
400+ dist/mcpp-darwin-arm64.tar.gz.sha256
0 commit comments