Skip to content

Commit d12a132

Browse files
committed
feat: macOS release support — bootstrap script + release workflow
- mcpp.toml: add `macos = "llvm@20.1.7"` toolchain declaration - scripts/bootstrap-macos.sh: one-shot bootstrap compiler for macOS (uses clang-scan-deps P1689 + topological module compilation) - release.yml: add macOS ARM64 job (bootstrap → self-host → package) - ci-macos.yml: add bootstrap + self-host validation steps
1 parent 27d0e97 commit d12a132

4 files changed

Lines changed: 457 additions & 0 deletions

File tree

.github/workflows/ci-macos.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,18 @@ jobs:
267267
Darwin-x86_64) echo "PASS: would select darwin-x86_64" ;;
268268
*) echo "FAIL: unexpected platform"; exit 1 ;;
269269
esac
270+
271+
- name: Bootstrap mcpp from source
272+
run: |
273+
export LLVM_ROOT="$LLVM_ROOT"
274+
bash scripts/bootstrap-macos.sh "$LLVM_ROOT"
275+
./target/bootstrap/bin/mcpp --version
276+
277+
- name: Self-host (mcpp builds mcpp)
278+
run: |
279+
MCPP="./target/bootstrap/bin/mcpp"
280+
"$MCPP" build
281+
SELFHOST=$(find target -path "*/bin/mcpp" -not -path "*/bootstrap/*" | head -1)
282+
test -x "$SELFHOST"
283+
"$SELFHOST" --version
284+
echo ":: Self-host successful!"

.github/workflows/release.yml

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

mcpp.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ include_dirs = ["src/libs/json"]
1313

1414
[toolchain]
1515
default = "gcc@16.1.0"
16+
macos = "llvm@20.1.7"
1617

1718
# Per-target overrides: `mcpp build --target x86_64-linux-musl` (or the
1819
# four-segment form `x86_64-unknown-linux-musl`) picks musl-gcc 15.1 + full

0 commit comments

Comments
 (0)