Skip to content

feat: Windows CI uses xlings to bootstrap mcpp (same as Linux/macOS) #34

feat: Windows CI uses xlings to bootstrap mcpp (same as Linux/macOS)

feat: Windows CI uses xlings to bootstrap mcpp (same as Linux/macOS) #34

Workflow file for this run

name: ci-windows
# Windows CI for mcpp.
# Step 1: Bootstrap mcpp via xlings (same as Linux/macOS).
# Step 2: Self-host — use mcpp to build itself (LLVM + MSVC STL import std).
# Step 3: Package the self-hosted binary into a distributable zip.
on:
push:
branches: [ feat/windows-support ]
pull_request:
branches: [ main ]
paths:
- 'src/toolchain/**'
- 'src/build/**'
- 'src/cli.cppm'
- '.github/workflows/ci-windows.yml'
workflow_dispatch:
concurrency:
group: ci-windows-${{ github.ref }}
cancel-in-progress: true
jobs:
windows-build:
name: Windows x64 — build + self-host
runs-on: windows-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- name: System info
shell: bash
run: |
echo "OS: $(uname -s)"
echo "Arch: $(uname -m)"
echo "Runner: $RUNNER_OS"
- name: Install 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}"
XLINGS_DIR="${WORK}/xlings-${XLINGS_VERSION}-windows-x86_64"
"$XLINGS_DIR/subos/default/bin/xlings.exe" self install
echo "$USERPROFILE/.xlings/subos/default/bin" >> "$GITHUB_PATH"
echo "$USERPROFILE/.xlings/bin" >> "$GITHUB_PATH"
- name: Bootstrap mcpp via xlings
shell: bash
run: |
xlings.exe --version
xlings.exe install mcpp -y
MCPP="$USERPROFILE/.xlings/subos/default/bin/mcpp.exe"
test -f "$MCPP" || MCPP="$USERPROFILE/.xlings/subos/default/bin/mcpp"
test -f "$MCPP"
"$MCPP" --version
echo "MCPP=$MCPP" >> "$GITHUB_ENV"
echo "XLINGS_BIN=$USERPROFILE/.xlings/subos/default/bin/xlings.exe" >> "$GITHUB_ENV"
- name: Self-host — mcpp builds itself
shell: bash
run: |
echo "=== Self-host: mcpp builds mcpp ==="
"$MCPP" --version
# mcpp build uses LLVM on Windows (from mcpp.toml: windows = "llvm@20.1.7")
XLINGS_WIN=$(cygpath -w "$XLINGS_BIN")
export MCPP_VENDORED_XLINGS="$XLINGS_WIN"
# Pre-seed mcpp sandbox with the already-installed LLVM from xlings
MCPP_XPKGS="$USERPROFILE/.mcpp/registry/data/xpkgs"
XLINGS_XPKGS="$USERPROFILE/.xlings/data/xpkgs"
if [ -d "$XLINGS_XPKGS/xim-x-llvm" ]; then
mkdir -p "$MCPP_XPKGS"
rm -rf "$MCPP_XPKGS/xim-x-llvm"
cp -r "$XLINGS_XPKGS/xim-x-llvm" "$MCPP_XPKGS/xim-x-llvm"
echo "Pre-seeded LLVM from global xlings"
fi
"$MCPP" build
# Find the self-hosted binary
SELF_MCPP=$(find target -name "mcpp.exe" -path "*/bin/*" | head -1)
test -n "$SELF_MCPP" || {
echo "FAIL: self-host build did not produce mcpp.exe"
find target -name "*.exe" 2>/dev/null
exit 1
}
SELF_MCPP=$(cd "$(dirname "$SELF_MCPP")" && pwd)/$(basename "$SELF_MCPP")
echo "Self-hosted binary: $SELF_MCPP"
"$SELF_MCPP" --version
echo "MCPP_SELF=$SELF_MCPP" >> "$GITHUB_ENV"
- name: Package Windows release zip
id: package
shell: bash
run: |
VERSION=$(awk -F '"' '/^version[[:space:]]*=/{print $2; exit}' mcpp.toml)
PLAT="windows-x86_64"
WRAPPER="mcpp-${VERSION}-${PLAT}"
ZIPNAME="${WRAPPER}.zip"
echo "Packaging $ZIPNAME ..."
STAGING=$(mktemp -d)
mkdir -p "$STAGING/$WRAPPER/bin"
mkdir -p "$STAGING/$WRAPPER/registry/bin"
# Binary: self-hosted build
echo "Packaging binary: $MCPP_SELF"
cp "$MCPP_SELF" "$STAGING/$WRAPPER/bin/mcpp.exe"
# Launcher batch script
printf '@echo off\r\n"%%~dp0bin\\mcpp.exe" %%*\r\n' > "$STAGING/$WRAPPER/mcpp.bat"
# Metadata
cp README.md "$STAGING/$WRAPPER/" 2>/dev/null || true
cp LICENSE "$STAGING/$WRAPPER/" 2>/dev/null || true
# Bundle xlings
XLINGS_EXE="$USERPROFILE/.xlings/subos/default/bin/xlings.exe"
if [ -f "$XLINGS_EXE" ]; then
cp "$XLINGS_EXE" "$STAGING/$WRAPPER/registry/bin/xlings.exe"
echo "Bundled xlings.exe"
else
echo "::warning::xlings.exe not found at $XLINGS_EXE"
fi
# Create zip
mkdir -p dist
(cd "$STAGING" && 7z a -tzip "$ZIPNAME" "$WRAPPER")
cp "$STAGING/$ZIPNAME" "dist/$ZIPNAME"
# SHA256
(cd dist && sha256sum "$ZIPNAME" > "$ZIPNAME.sha256")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "zipname=$ZIPNAME" >> "$GITHUB_OUTPUT"
ls -la dist/
- name: Smoke-test the packaged zip
shell: bash
run: |
VERSION="${{ steps.package.outputs.version }}"
ZIPNAME="${{ steps.package.outputs.zipname }}"
WRAPPER="${ZIPNAME%.zip}"
SMOKE=$(mktemp -d)
(cd "$SMOKE" && unzip -q "$GITHUB_WORKSPACE/dist/$ZIPNAME")
echo "=== Layout ==="
find "$SMOKE/$WRAPPER" -type f
echo "=== Version check ==="
"$SMOKE/$WRAPPER/bin/mcpp.exe" --version
echo "=== xlings bundled ==="
test -f "$SMOKE/$WRAPPER/registry/bin/xlings.exe"
echo "=== Launcher ==="
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