Skip to content

Commit 6255c27

Browse files
committed
feat: Windows CI uses xlings to bootstrap mcpp (same as Linux/macOS)
Replace xmake bootstrap with `xlings install mcpp` — now that mcpp 0.0.17 is in the xlings ecosystem, Windows follows the same flow as Linux/macOS: 1. xlings install mcpp → get mcpp.exe 2. mcpp build → self-host (LLVM + MSVC STL import std) 3. Package self-hosted binary into zip Removed all LLVM validation steps (no longer needed for CI), xmake bootstrap step, and debug output. Clean, minimal workflow.
1 parent 8d76b57 commit 6255c27

1 file changed

Lines changed: 25 additions & 214 deletions

File tree

.github/workflows/ci-windows.yml

Lines changed: 25 additions & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
name: ci-windows
22

3-
# Windows validation CI for mcpp.
4-
# Step 1: Verify xlings LLVM toolchain capabilities on Windows.
5-
# Step 2: xmake bootstrap to produce first mcpp.exe.
6-
# Step 3: Self-host — use the bootstrapped mcpp.exe to build itself (LLVM + MSVC STL).
7-
# Step 4: Package the self-hosted binary into a distributable zip.
3+
# Windows CI for mcpp.
4+
# Step 1: Bootstrap mcpp via xlings (same as Linux/macOS).
5+
# Step 2: Self-host — use mcpp to build itself (LLVM + MSVC STL import std).
6+
# Step 3: Package the self-hosted binary into a distributable zip.
87

98
on:
109
push:
@@ -23,8 +22,8 @@ concurrency:
2322
cancel-in-progress: true
2423

2524
jobs:
26-
windows-llvm-validation:
27-
name: Windows x64 — LLVM toolchain validation
25+
windows-build:
26+
name: Windows x64 — build + self-host
2827
runs-on: windows-latest
2928
timeout-minutes: 45
3029
steps:
@@ -50,231 +49,43 @@ jobs:
5049
cd "${WORK}"
5150
unzip -q "${zipfile}"
5251
XLINGS_DIR="${WORK}/xlings-${XLINGS_VERSION}-windows-x86_64"
53-
echo "xlings dir: $XLINGS_DIR"
54-
ls "$XLINGS_DIR/bin/"
5552
"$XLINGS_DIR/subos/default/bin/xlings.exe" self install
5653
echo "$USERPROFILE/.xlings/subos/default/bin" >> "$GITHUB_PATH"
5754
echo "$USERPROFILE/.xlings/bin" >> "$GITHUB_PATH"
5855
59-
- name: Verify xlings
56+
- name: Bootstrap mcpp via xlings
6057
shell: bash
6158
run: |
62-
xlings.exe --version || xlings --version || echo "xlings not found in PATH"
63-
64-
- name: Install LLVM via xlings
65-
shell: bash
66-
run: |
67-
xlings.exe install llvm -y || xlings.exe install llvm@20.1.7 -y || {
68-
echo "::warning::xlings install llvm failed"
69-
exit 1
70-
}
71-
# Find LLVM root
72-
LLVM_ROOT=$(find "$USERPROFILE/.xlings" -path "*/xpkgs/xim-x-llvm/*/bin/clang.exe" 2>/dev/null | head -1)
73-
if [ -n "$LLVM_ROOT" ]; then
74-
LLVM_ROOT=$(dirname "$(dirname "$LLVM_ROOT")")
75-
fi
76-
echo "LLVM_ROOT=$LLVM_ROOT"
77-
echo "LLVM_ROOT=$LLVM_ROOT" >> "$GITHUB_ENV"
78-
79-
- name: Inspect LLVM package structure
80-
shell: bash
81-
run: |
82-
echo "=== bin/ ==="
83-
ls "$LLVM_ROOT/bin/" | grep -iE "clang|lld|llvm-ar|scan" | head -20
84-
echo "=== lib/ ==="
85-
ls "$LLVM_ROOT/lib/" 2>/dev/null | head -10
86-
echo "=== include/c++/ ==="
87-
ls "$LLVM_ROOT/include/c++/" 2>/dev/null || echo "(no libc++ headers)"
88-
echo "=== share/libc++/ ==="
89-
find "$LLVM_ROOT" -name "std.cppm" 2>/dev/null || echo "(no std.cppm)"
90-
echo "=== clang++.cfg ==="
91-
cat "$LLVM_ROOT/bin/clang++.cfg" 2>/dev/null || echo "(no cfg)"
92-
echo "=== clang version ==="
93-
"$LLVM_ROOT/bin/clang++.exe" --version 2>/dev/null || "$LLVM_ROOT/bin/clang++" --version 2>/dev/null
94-
echo "=== Target triple ==="
95-
"$LLVM_ROOT/bin/clang++.exe" -dumpmachine 2>/dev/null || "$LLVM_ROOT/bin/clang++" -dumpmachine 2>/dev/null
96-
97-
- name: Test — non-module C++ compilation (clang++)
98-
shell: bash
99-
run: |
100-
WORK=$(mktemp -d)
101-
cd "$WORK"
102-
CXX="$LLVM_ROOT/bin/clang++.exe"
103-
test -x "$CXX" || CXX="$LLVM_ROOT/bin/clang++"
104-
105-
cat > main.cpp << 'EOF'
106-
#include <iostream>
107-
int main() {
108-
std::cout << "Hello from clang++ on Windows!" << std::endl;
109-
return 0;
110-
}
111-
EOF
112-
113-
echo "=== Compile ==="
114-
"$CXX" -std=c++23 -o hello.exe main.cpp 2>&1 || {
115-
echo "::warning::clang++ compilation failed, trying with MSVC headers"
116-
# clang++ on Windows may need MSVC include paths
117-
"$CXX" -std=c++23 --target=x86_64-pc-windows-msvc -o hello.exe main.cpp 2>&1 || true
118-
}
119-
120-
if [ -f hello.exe ]; then
121-
echo "=== Run ==="
122-
./hello.exe
123-
else
124-
echo "::warning::Compilation did not produce hello.exe"
125-
fi
126-
127-
- name: Test — clang-cl compilation
128-
shell: bash
129-
run: |
130-
WORK=$(mktemp -d)
131-
cd "$WORK"
132-
CLANGCL="$LLVM_ROOT/bin/clang-cl.exe"
133-
test -x "$CLANGCL" || CLANGCL="$LLVM_ROOT/bin/clang-cl"
134-
135-
cat > main.cpp << 'EOF'
136-
#include <iostream>
137-
int main() {
138-
std::cout << "Hello from clang-cl on Windows!" << std::endl;
139-
return 0;
140-
}
141-
EOF
142-
143-
echo "=== Compile with clang-cl ==="
144-
"$CLANGCL" /std:c++latest /EHsc main.cpp /Fe:hello.exe 2>&1 || {
145-
echo "::warning::clang-cl compilation failed"
146-
echo "clang-cl may need Visual Studio installation for MSVC headers/libs"
147-
}
148-
149-
if [ -f hello.exe ]; then
150-
echo "=== Run ==="
151-
./hello.exe
152-
fi
153-
154-
- name: Check libc++ availability for import std
155-
shell: bash
156-
run: |
157-
echo "=== Checking for libc++ in LLVM package ==="
158-
find "$LLVM_ROOT" -name "*.cppm" 2>/dev/null | head -5 || echo "No .cppm files found"
159-
find "$LLVM_ROOT" -path "*/c++/v1" -type d 2>/dev/null | head -3 || echo "No libc++ include dir"
160-
find "$LLVM_ROOT" -name "libc++*" 2>/dev/null | head -5 || echo "No libc++ library files"
161-
162-
echo
163-
echo "=== Checking MSVC STL for import std ==="
164-
# Visual Studio on GitHub runners includes MSVC STL with module support
165-
VSDIR="/c/Program Files/Microsoft Visual Studio/2022/Enterprise"
166-
if [ -d "$VSDIR" ]; then
167-
echo "Visual Studio found at: $VSDIR"
168-
find "$VSDIR" -name "std.ixx" 2>/dev/null | head -3 || echo "No std.ixx found"
169-
find "$VSDIR" -path "*/modules" -name "*.ixx" 2>/dev/null | head -5 || echo "No .ixx module files"
170-
else
171-
echo "Visual Studio not found at expected path"
172-
ls "/c/Program Files/Microsoft Visual Studio/" 2>/dev/null || true
173-
fi
174-
175-
- name: Summary
176-
shell: bash
177-
run: |
178-
echo "=== Windows LLVM Validation Summary ==="
179-
echo "LLVM Root: $LLVM_ROOT"
180-
echo "Clang version: $("$LLVM_ROOT/bin/clang++.exe" --version 2>/dev/null | head -1 || echo 'N/A')"
181-
echo "Target: $("$LLVM_ROOT/bin/clang++.exe" -dumpmachine 2>/dev/null || echo 'N/A')"
182-
echo
183-
echo "Has libc++: $([ -d "$LLVM_ROOT/include/c++/v1" ] && echo YES || echo NO)"
184-
echo "Has std.cppm: $(find "$LLVM_ROOT" -name 'std.cppm' 2>/dev/null | head -1 | grep -q . && echo YES || echo NO)"
185-
echo "Has clang-scan-deps: $([ -f "$LLVM_ROOT/bin/clang-scan-deps.exe" ] && echo YES || echo NO)"
186-
echo "Has clang-cl: $([ -f "$LLVM_ROOT/bin/clang-cl.exe" ] && echo YES || echo NO)"
187-
echo "Has lld-link: $([ -f "$LLVM_ROOT/bin/lld-link.exe" ] && echo YES || echo NO)"
188-
189-
- name: Install xmake via xlings
190-
shell: bash
191-
run: |
192-
xlings.exe install xmake -y || xlings install xmake -y
193-
xmake.exe --version || xmake --version
194-
195-
- name: Bootstrap mcpp with xmake (MSVC)
196-
id: bootstrap
197-
shell: pwsh
198-
run: |
199-
# Generate xmake.lua for bootstrap
200-
@"
201-
add_rules("mode.release")
202-
set_languages("c++23")
203-
package("cmdline")
204-
set_homepage("https://github.com/mcpplibs/cmdline")
205-
add_urls("https://github.com/mcpplibs/cmdline/archive/refs/tags/`$(version).tar.gz")
206-
add_versions("0.0.1", "3fb2f5495c1a144485b3cbb2e43e27059151633460f702af0f3851cbff387ef0")
207-
on_install(function (package)
208-
import("package.tools.xmake").install(package)
209-
end)
210-
package_end()
211-
add_requires("cmdline 0.0.1")
212-
target("mcpp")
213-
set_kind("binary")
214-
add_files("src/main.cpp")
215-
add_files("src/**.cppm")
216-
add_packages("cmdline")
217-
add_includedirs("src/libs/json")
218-
set_policy("build.c++.modules", true)
219-
"@ | Out-File -Encoding utf8 xmake.lua
220-
221-
xmake f -p windows -m release -y
222-
xmake build -y mcpp
223-
224-
$mcpp = Get-ChildItem -Recurse build -Filter mcpp.exe -ErrorAction SilentlyContinue | Select-Object -First 1
225-
if ($mcpp) {
226-
Write-Host ":: mcpp.exe built at: $($mcpp.FullName)"
227-
& $mcpp.FullName --version
228-
# Export for subsequent steps
229-
"MCPP_BOOTSTRAP=$($mcpp.FullName)" | Out-File -Append $env:GITHUB_ENV
230-
} else {
231-
Write-Host ":: Build produced files:"
232-
Get-ChildItem -Recurse build -Filter *.exe | ForEach-Object { Write-Host " $($_.FullName)" }
233-
exit 1
234-
}
59+
xlings.exe --version
60+
xlings.exe install mcpp -y
61+
MCPP="$USERPROFILE/.xlings/subos/default/bin/mcpp.exe"
62+
test -f "$MCPP" || MCPP="$USERPROFILE/.xlings/subos/default/bin/mcpp"
63+
test -f "$MCPP"
64+
"$MCPP" --version
65+
echo "MCPP=$MCPP" >> "$GITHUB_ENV"
66+
echo "XLINGS_BIN=$USERPROFILE/.xlings/subos/default/bin/xlings.exe" >> "$GITHUB_ENV"
23567
23668
- name: Self-host — mcpp builds itself
23769
shell: bash
23870
run: |
239-
echo "=== Self-host: using bootstrapped mcpp.exe to build mcpp ==="
240-
# Save bootstrap binary before cleaning xmake artifacts
241-
mkdir -p /tmp/mcpp-bootstrap
242-
cp "$MCPP_BOOTSTRAP" /tmp/mcpp-bootstrap/mcpp.exe
243-
MCPP_EXE="/tmp/mcpp-bootstrap/mcpp.exe"
244-
245-
# Clean xmake artifacts so mcpp starts fresh
246-
rm -rf build xmake.lua .xmake
71+
echo "=== Self-host: mcpp builds mcpp ==="
72+
"$MCPP" --version
24773
248-
echo "Bootstrap binary: $MCPP_EXE"
249-
"$MCPP_EXE" --version
250-
251-
# mcpp build uses its own build system; mcpp.toml now has
252-
# windows = "llvm@20.1.7" so it will use the xlings LLVM.
253-
# Use Windows-native path for MCPP_VENDORED_XLINGS
254-
XLINGS_WIN=$(cygpath -w "$USERPROFILE/.xlings/subos/default/bin/xlings.exe")
255-
echo "MCPP_VENDORED_XLINGS=$XLINGS_WIN"
74+
# mcpp build uses LLVM on Windows (from mcpp.toml: windows = "llvm@20.1.7")
75+
XLINGS_WIN=$(cygpath -w "$XLINGS_BIN")
25676
export MCPP_VENDORED_XLINGS="$XLINGS_WIN"
25777
258-
echo "xlings exists: $(test -f "$USERPROFILE/.xlings/subos/default/bin/xlings.exe" && echo YES || echo NO)"
259-
260-
# Debug: test xlings directly
261-
"$USERPROFILE/.xlings/subos/default/bin/xlings.exe" --version || echo "xlings direct call failed"
262-
263-
# Pre-seed the mcpp sandbox with the already-installed LLVM from
264-
# the global xlings. xlings won't re-download if the package dir
265-
# exists, but it may create an empty stub. Copy instead of junction
266-
# to avoid Windows symlink permission issues on CI runners.
78+
# Pre-seed mcpp sandbox with the already-installed LLVM from xlings
26779
MCPP_XPKGS="$USERPROFILE/.mcpp/registry/data/xpkgs"
26880
XLINGS_XPKGS="$USERPROFILE/.xlings/data/xpkgs"
26981
if [ -d "$XLINGS_XPKGS/xim-x-llvm" ]; then
27082
mkdir -p "$MCPP_XPKGS"
27183
rm -rf "$MCPP_XPKGS/xim-x-llvm"
27284
cp -r "$XLINGS_XPKGS/xim-x-llvm" "$MCPP_XPKGS/xim-x-llvm"
273-
echo "Copied LLVM xpkg from global xlings"
274-
ls "$MCPP_XPKGS/xim-x-llvm/20.1.7/bin/" | head -5
85+
echo "Pre-seeded LLVM from global xlings"
27586
fi
27687
277-
"$MCPP_EXE" build
88+
"$MCPP" build
27889
27990
# Find the self-hosted binary
28091
SELF_MCPP=$(find target -name "mcpp.exe" -path "*/bin/*" | head -1)
@@ -304,11 +115,11 @@ jobs:
304115
mkdir -p "$STAGING/$WRAPPER/bin"
305116
mkdir -p "$STAGING/$WRAPPER/registry/bin"
306117
307-
# Binary: use the self-hosted build
118+
# Binary: self-hosted build
308119
echo "Packaging binary: $MCPP_SELF"
309120
cp "$MCPP_SELF" "$STAGING/$WRAPPER/bin/mcpp.exe"
310121
311-
# Launcher batch script (equivalent to the shell wrapper on Linux/macOS)
122+
# Launcher batch script
312123
printf '@echo off\r\n"%%~dp0bin\\mcpp.exe" %%*\r\n' > "$STAGING/$WRAPPER/mcpp.bat"
313124
314125
# Metadata
@@ -324,7 +135,7 @@ jobs:
324135
echo "::warning::xlings.exe not found at $XLINGS_EXE"
325136
fi
326137
327-
# Create zip (use 7z to avoid backslash path issues from Compress-Archive)
138+
# Create zip
328139
mkdir -p dist
329140
(cd "$STAGING" && 7z a -tzip "$ZIPNAME" "$WRAPPER")
330141
cp "$STAGING/$ZIPNAME" "dist/$ZIPNAME"

0 commit comments

Comments
 (0)