refactor: platform abstraction layer + fix macOS stdin hang #111
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ci-windows | |
| # Windows CI for mcpp — same flow as Linux (ci.yml) and macOS (ci-macos.yml): | |
| # xlings install mcpp → self-host build → E2E → smoke → package | |
| on: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ci-windows-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build-and-test: | |
| name: build + test (windows x64, self-host) | |
| runs-on: windows-latest | |
| timeout-minutes: 45 | |
| env: | |
| MCPP_HOME: C:\Users\runneradmin\.mcpp | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Cache mcpp sandbox | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~\.mcpp | |
| key: mcpp-sandbox-${{ runner.os }}-${{ hashFiles('mcpp.toml', '.xlings.json') }} | |
| restore-keys: | | |
| mcpp-sandbox-${{ runner.os }}- | |
| - name: Cache xlings | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~\.xlings | |
| key: xlings-${{ runner.os }}-v2-${{ hashFiles('.xlings.json') }} | |
| restore-keys: | | |
| xlings-${{ runner.os }}-v2- | |
| - name: Bootstrap mcpp via xlings | |
| shell: bash | |
| env: | |
| XLINGS_NON_INTERACTIVE: '1' | |
| XLINGS_VERSION: '0.4.30' | |
| run: | | |
| WORK=$(mktemp -d) | |
| zipfile="xlings-${XLINGS_VERSION}-windows-x86_64.zip" | |
| curl -fsSL -o "${WORK}/${zipfile}" \ | |
| "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${zipfile}" | |
| cd "${WORK}" | |
| unzip -q "${zipfile}" | |
| "$WORK/xlings-${XLINGS_VERSION}-windows-x86_64/subos/default/bin/xlings.exe" self install | |
| export PATH="$USERPROFILE/.xlings/subos/default/bin:$PATH" | |
| echo "$USERPROFILE/.xlings/subos/default/bin" >> "$GITHUB_PATH" | |
| xlings.exe --version | |
| xlings.exe install mcpp -y | |
| echo "=== Searching for mcpp binary ===" | |
| find "$USERPROFILE/.xlings" -name "mcpp.exe" -o -name "mcpp" 2>/dev/null | head -10 | |
| MCPP=$(find "$USERPROFILE/.xlings" -name "mcpp.exe" -path "*/bin/*" 2>/dev/null | head -1) | |
| if [ -z "$MCPP" ]; then | |
| MCPP=$(find "$USERPROFILE/.xlings" -name "mcpp" -path "*/bin/*" 2>/dev/null | head -1) | |
| fi | |
| test -n "$MCPP" || { echo "FAIL: mcpp not found after xlings install"; exit 1; } | |
| echo "Found mcpp at: $MCPP" | |
| "$MCPP" --version | |
| echo "MCPP=$MCPP" >> "$GITHUB_ENV" | |
| XLINGS_BIN=$(cygpath -w "$USERPROFILE/.xlings/subos/default/bin/xlings.exe") | |
| echo "XLINGS_BIN=$XLINGS_BIN" >> "$GITHUB_ENV" | |
| - name: Build mcpp from source (self-host) | |
| shell: bash | |
| run: | | |
| export MCPP_VENDORED_XLINGS="$XLINGS_BIN" | |
| "$MCPP" build | |
| MCPP_SELF=$(find target -name "mcpp.exe" -path "*/bin/*" | head -1) | |
| test -n "$MCPP_SELF" || { echo "FAIL: no mcpp.exe"; exit 1; } | |
| MCPP_SELF=$(cd "$(dirname "$MCPP_SELF")" && pwd)/$(basename "$MCPP_SELF") | |
| echo "Self-hosted binary: $MCPP_SELF" | |
| "$MCPP_SELF" --version | |
| echo "MCPP_SELF=$MCPP_SELF" >> "$GITHUB_ENV" | |
| - name: Unit + integration tests via mcpp test | |
| shell: bash | |
| run: | | |
| export MCPP_VENDORED_XLINGS=$(cygpath -w "$USERPROFILE/.xlings/subos/default/bin/xlings.exe") | |
| "$MCPP_SELF" test | |
| - name: E2E suite | |
| shell: bash | |
| run: | | |
| export MCPP="$MCPP_SELF" | |
| export MCPP_VENDORED_XLINGS="$XLINGS_BIN" | |
| export MCPP_E2E_TOOLCHAIN_MIRROR=GLOBAL | |
| "$MCPP_SELF" self config --mirror GLOBAL 2>/dev/null || true | |
| "$MCPP_SELF" toolchain default llvm@20.1.7 2>/dev/null || true | |
| bash tests/e2e/run_all.sh | |
| - name: Self-host smoke (freshly-built mcpp builds itself again) | |
| shell: bash | |
| run: | | |
| export MCPP_VENDORED_XLINGS="$XLINGS_BIN" | |
| "$MCPP_SELF" build | |
| "$MCPP_SELF" --version | |
| echo ":: Self-host smoke PASS" | |
| - name: Fresh user experience (xlings install mcpp → new → run) | |
| continue-on-error: true | |
| shell: bash | |
| run: | | |
| # Test the real user flow with the xlings-distributed mcpp. | |
| # Currently xlings ships 0.0.17 which lacks Windows fixes. | |
| # This step will auto-pass once xlings updates to 0.0.19+. | |
| TMP=$(mktemp -d) | |
| cd "$TMP" | |
| "$MCPP" new hello | |
| cd hello | |
| "$MCPP" run | |
| - name: Package Windows release zip | |
| id: package | |
| shell: bash | |
| run: | | |
| VERSION=$(awk -F '"' '/^version[[:space:]]*=/{print $2; exit}' mcpp.toml) | |
| WRAPPER="mcpp-${VERSION}-windows-x86_64" | |
| ZIPNAME="${WRAPPER}.zip" | |
| STAGING=$(mktemp -d) | |
| mkdir -p "$STAGING/$WRAPPER/bin" "$STAGING/$WRAPPER/registry/bin" | |
| cp "$MCPP_SELF" "$STAGING/$WRAPPER/bin/mcpp.exe" | |
| printf '@echo off\r\n"%%~dp0bin\\mcpp.exe" %%*\r\n' > "$STAGING/$WRAPPER/mcpp.bat" | |
| cp README.md "$STAGING/$WRAPPER/" 2>/dev/null || true | |
| cp LICENSE "$STAGING/$WRAPPER/" 2>/dev/null || true | |
| XLINGS_EXE="$USERPROFILE/.xlings/subos/default/bin/xlings.exe" | |
| [ -f "$XLINGS_EXE" ] && cp "$XLINGS_EXE" "$STAGING/$WRAPPER/registry/bin/xlings.exe" | |
| mkdir -p dist | |
| (cd "$STAGING" && 7z a -tzip "$ZIPNAME" "$WRAPPER") | |
| cp "$STAGING/$ZIPNAME" "dist/$ZIPNAME" | |
| (cd dist && sha256sum "$ZIPNAME" > "$ZIPNAME.sha256") | |
| echo "zipname=$ZIPNAME" >> "$GITHUB_OUTPUT" | |
| ls -la dist/ | |
| - name: Smoke-test the packaged zip | |
| shell: bash | |
| run: | | |
| ZIPNAME="${{ steps.package.outputs.zipname }}" | |
| WRAPPER="${ZIPNAME%.zip}" | |
| SMOKE=$(mktemp -d) | |
| (cd "$SMOKE" && unzip -q "$GITHUB_WORKSPACE/dist/$ZIPNAME") | |
| "$SMOKE/$WRAPPER/bin/mcpp.exe" --version | |
| test -f "$SMOKE/$WRAPPER/registry/bin/xlings.exe" | |
| test -f "$SMOKE/$WRAPPER/mcpp.bat" | |
| echo "Smoke-test passed" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: mcpp-windows-x86_64 | |
| path: | | |
| dist/*.zip | |
| dist/*.sha256 |