fix: install xmake via xlings on Windows (psget.text unreliable) #4
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 validation CI for mcpp. | |
| # Step 1: Verify xlings LLVM toolchain capabilities on Windows. | |
| # Step 2: xmake bootstrap to produce first mcpp.exe. | |
| 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-llvm-validation: | |
| name: Windows x64 — LLVM toolchain validation | |
| runs-on: windows-latest | |
| timeout-minutes: 30 | |
| 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" | |
| echo "xlings dir: $XLINGS_DIR" | |
| ls "$XLINGS_DIR/bin/" | |
| "$XLINGS_DIR/subos/default/bin/xlings.exe" self install | |
| echo "$USERPROFILE/.xlings/subos/default/bin" >> "$GITHUB_PATH" | |
| echo "$USERPROFILE/.xlings/bin" >> "$GITHUB_PATH" | |
| - name: Verify xlings | |
| shell: bash | |
| run: | | |
| xlings.exe --version || xlings --version || echo "xlings not found in PATH" | |
| - name: Install LLVM via xlings | |
| shell: bash | |
| run: | | |
| xlings.exe install llvm -y || xlings.exe install llvm@20.1.7 -y || { | |
| echo "::warning::xlings install llvm failed" | |
| exit 1 | |
| } | |
| # Find LLVM root | |
| LLVM_ROOT=$(find "$USERPROFILE/.xlings" -path "*/xpkgs/xim-x-llvm/*/bin/clang.exe" 2>/dev/null | head -1) | |
| if [ -n "$LLVM_ROOT" ]; then | |
| LLVM_ROOT=$(dirname "$(dirname "$LLVM_ROOT")") | |
| fi | |
| echo "LLVM_ROOT=$LLVM_ROOT" | |
| echo "LLVM_ROOT=$LLVM_ROOT" >> "$GITHUB_ENV" | |
| - name: Inspect LLVM package structure | |
| shell: bash | |
| run: | | |
| echo "=== bin/ ===" | |
| ls "$LLVM_ROOT/bin/" | grep -iE "clang|lld|llvm-ar|scan" | head -20 | |
| echo "=== lib/ ===" | |
| ls "$LLVM_ROOT/lib/" 2>/dev/null | head -10 | |
| echo "=== include/c++/ ===" | |
| ls "$LLVM_ROOT/include/c++/" 2>/dev/null || echo "(no libc++ headers)" | |
| echo "=== share/libc++/ ===" | |
| find "$LLVM_ROOT" -name "std.cppm" 2>/dev/null || echo "(no std.cppm)" | |
| echo "=== clang++.cfg ===" | |
| cat "$LLVM_ROOT/bin/clang++.cfg" 2>/dev/null || echo "(no cfg)" | |
| echo "=== clang version ===" | |
| "$LLVM_ROOT/bin/clang++.exe" --version 2>/dev/null || "$LLVM_ROOT/bin/clang++" --version 2>/dev/null | |
| echo "=== Target triple ===" | |
| "$LLVM_ROOT/bin/clang++.exe" -dumpmachine 2>/dev/null || "$LLVM_ROOT/bin/clang++" -dumpmachine 2>/dev/null | |
| - name: Test — non-module C++ compilation (clang++) | |
| shell: bash | |
| run: | | |
| WORK=$(mktemp -d) | |
| cd "$WORK" | |
| CXX="$LLVM_ROOT/bin/clang++.exe" | |
| test -x "$CXX" || CXX="$LLVM_ROOT/bin/clang++" | |
| cat > main.cpp << 'EOF' | |
| #include <iostream> | |
| int main() { | |
| std::cout << "Hello from clang++ on Windows!" << std::endl; | |
| return 0; | |
| } | |
| EOF | |
| echo "=== Compile ===" | |
| "$CXX" -std=c++23 -o hello.exe main.cpp 2>&1 || { | |
| echo "::warning::clang++ compilation failed, trying with MSVC headers" | |
| # clang++ on Windows may need MSVC include paths | |
| "$CXX" -std=c++23 --target=x86_64-pc-windows-msvc -o hello.exe main.cpp 2>&1 || true | |
| } | |
| if [ -f hello.exe ]; then | |
| echo "=== Run ===" | |
| ./hello.exe | |
| else | |
| echo "::warning::Compilation did not produce hello.exe" | |
| fi | |
| - name: Test — clang-cl compilation | |
| shell: bash | |
| run: | | |
| WORK=$(mktemp -d) | |
| cd "$WORK" | |
| CLANGCL="$LLVM_ROOT/bin/clang-cl.exe" | |
| test -x "$CLANGCL" || CLANGCL="$LLVM_ROOT/bin/clang-cl" | |
| cat > main.cpp << 'EOF' | |
| #include <iostream> | |
| int main() { | |
| std::cout << "Hello from clang-cl on Windows!" << std::endl; | |
| return 0; | |
| } | |
| EOF | |
| echo "=== Compile with clang-cl ===" | |
| "$CLANGCL" /std:c++latest /EHsc main.cpp /Fe:hello.exe 2>&1 || { | |
| echo "::warning::clang-cl compilation failed" | |
| echo "clang-cl may need Visual Studio installation for MSVC headers/libs" | |
| } | |
| if [ -f hello.exe ]; then | |
| echo "=== Run ===" | |
| ./hello.exe | |
| fi | |
| - name: Check libc++ availability for import std | |
| shell: bash | |
| run: | | |
| echo "=== Checking for libc++ in LLVM package ===" | |
| find "$LLVM_ROOT" -name "*.cppm" 2>/dev/null | head -5 || echo "No .cppm files found" | |
| find "$LLVM_ROOT" -path "*/c++/v1" -type d 2>/dev/null | head -3 || echo "No libc++ include dir" | |
| find "$LLVM_ROOT" -name "libc++*" 2>/dev/null | head -5 || echo "No libc++ library files" | |
| echo | |
| echo "=== Checking MSVC STL for import std ===" | |
| # Visual Studio on GitHub runners includes MSVC STL with module support | |
| VSDIR="/c/Program Files/Microsoft Visual Studio/2022/Enterprise" | |
| if [ -d "$VSDIR" ]; then | |
| echo "Visual Studio found at: $VSDIR" | |
| find "$VSDIR" -name "std.ixx" 2>/dev/null | head -3 || echo "No std.ixx found" | |
| find "$VSDIR" -path "*/modules" -name "*.ixx" 2>/dev/null | head -5 || echo "No .ixx module files" | |
| else | |
| echo "Visual Studio not found at expected path" | |
| ls "/c/Program Files/Microsoft Visual Studio/" 2>/dev/null || true | |
| fi | |
| - name: Summary | |
| shell: bash | |
| run: | | |
| echo "=== Windows LLVM Validation Summary ===" | |
| echo "LLVM Root: $LLVM_ROOT" | |
| echo "Clang version: $("$LLVM_ROOT/bin/clang++.exe" --version 2>/dev/null | head -1 || echo 'N/A')" | |
| echo "Target: $("$LLVM_ROOT/bin/clang++.exe" -dumpmachine 2>/dev/null || echo 'N/A')" | |
| echo | |
| echo "Has libc++: $([ -d "$LLVM_ROOT/include/c++/v1" ] && echo YES || echo NO)" | |
| echo "Has std.cppm: $(find "$LLVM_ROOT" -name 'std.cppm' 2>/dev/null | head -1 | grep -q . && echo YES || echo NO)" | |
| echo "Has clang-scan-deps: $([ -f "$LLVM_ROOT/bin/clang-scan-deps.exe" ] && echo YES || echo NO)" | |
| echo "Has clang-cl: $([ -f "$LLVM_ROOT/bin/clang-cl.exe" ] && echo YES || echo NO)" | |
| echo "Has lld-link: $([ -f "$LLVM_ROOT/bin/lld-link.exe" ] && echo YES || echo NO)" | |
| - name: Install xmake via xlings | |
| shell: bash | |
| run: | | |
| xlings.exe install xmake -y || xlings install xmake -y | |
| xmake.exe --version || xmake --version | |
| - name: Build mcpp with xmake (MSVC) | |
| shell: pwsh | |
| run: | | |
| # Generate xmake.lua for bootstrap | |
| @" | |
| add_rules("mode.release") | |
| set_languages("c++23") | |
| package("cmdline") | |
| set_homepage("https://github.com/mcpplibs/cmdline") | |
| add_urls("https://github.com/mcpplibs/cmdline/archive/refs/tags/`$(version).tar.gz") | |
| add_versions("0.0.1", "3fb2f5495c1a144485b3cbb2e43e27059151633460f702af0f3851cbff387ef0") | |
| on_install(function (package) | |
| import("package.tools.xmake").install(package) | |
| end) | |
| package_end() | |
| add_requires("cmdline 0.0.1") | |
| target("mcpp") | |
| set_kind("binary") | |
| add_files("src/main.cpp") | |
| add_files("src/**.cppm") | |
| add_packages("cmdline") | |
| add_includedirs("src/libs/json") | |
| set_policy("build.c++.modules", true) | |
| "@ | Out-File -Encoding utf8 xmake.lua | |
| xmake f -p windows -m release -y | |
| xmake build -y mcpp | |
| $mcpp = Get-ChildItem -Recurse build -Filter mcpp.exe -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| if ($mcpp) { | |
| Write-Host ":: mcpp.exe built at: $($mcpp.FullName)" | |
| & $mcpp.FullName --version | |
| } else { | |
| Write-Host ":: Build produced files:" | |
| Get-ChildItem -Recurse build -Filter *.exe | ForEach-Object { Write-Host " $($_.FullName)" } | |
| exit 1 | |
| } |