Skip to content

Commit e113ed3

Browse files
committed
ci(windows): add Ninja Multi-Config + sccache evaluation jobs for Windows
The two Windows native build jobs are the only uncached native builds: the Visual Studio generator ignores CMAKE_{C,CXX}_COMPILER_LAUNCHER, so sccache cannot be wired into them. Upstream llama.cpp ships its windows-cuda artifact with Ninja Multi-Config + MSVC, proving the combination works on the same tree. - build.bat: add an sccache probe guard mirroring build.sh's sccache_can_wrap_compiler() — when USE_CACHE=true and sccache is on PATH, compile a trivial TU through `sccache cl.exe`; only on success pass -DCMAKE_{C,CXX}_COMPILER_LAUNCHER=sccache and print `sccache --show-stats`. A missing/crashing sccache falls back to a green uncached build. Inert for the VS generator jobs (they do not set USE_CACHE). - publish.yml: add two evaluation-only jobs, build-windows-x86_64-ninja and build-windows-x86-ninja (windows-2025-vs2026, ilammy/msvc-dev-cmd@v1, sccache v0.16.0, Depot WebDAV env, `build.bat -G "Ninja Multi-Config"`). Artifacts are named Windows-*-ninja (NOT *-libraries) so the package job's `pattern: "*-libraries"` does not consume them; package's `needs:` is unchanged. They run in parallel with the trusted VS jobs. - TODO.md: flip the Windows cache section from "implementation notes" to "evaluation in progress"; document what remains (confirm cache hits, then rename artifacts to *-libraries, wire into package `needs`, retire VS jobs). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SfvSZ76NW4e1qX1PjL4RKq
1 parent 1277580 commit e113ed3

3 files changed

Lines changed: 198 additions & 16 deletions

File tree

.github/build.bat

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,49 @@ REM
44
REM SPDX-License-Identifier: MIT
55

66
@echo off
7+
setlocal enabledelayedexpansion
8+
9+
REM ---------------------------------------------------------------------------
10+
REM Optional shared compiler cache: sccache fronting Depot Cache (WebDAV).
11+
REM Mirrors build.sh's sccache_can_wrap_compiler() probe. Because sccache *is*
12+
REM the compiler launcher (cmake runs `sccache cl.exe ...` for every TU), a
13+
REM present-but-crashing sccache would red every build; so we trust it only after
14+
REM a trivial TU compiles *through* it. Enabled only when USE_CACHE=true AND
15+
REM sccache is on PATH AND the probe succeeds; otherwise the build proceeds
16+
REM uncached and green. The Visual Studio generator jobs do NOT set USE_CACHE, so
17+
REM this stays inert for them (and the VS generator ignores
18+
REM CMAKE_{C,CXX}_COMPILER_LAUNCHER anyway -- only Ninja/Makefiles honor it).
19+
REM ---------------------------------------------------------------------------
20+
set "LAUNCH="
21+
if /I "%USE_CACHE%"=="true" (
22+
where sccache >nul 2>&1
23+
if errorlevel 1 (
24+
echo build.bat: USE_CACHE=true but sccache not on PATH; building WITHOUT cache.
25+
) else (
26+
set "PROBE_DIR=%TEMP%\sccache-probe-%RANDOM%"
27+
mkdir "!PROBE_DIR!" >nul 2>&1
28+
(echo int sccache_probe_verify = 0;)> "!PROBE_DIR!\probe.c"
29+
sccache cl.exe /nologo /c "!PROBE_DIR!\probe.c" /Fo"!PROBE_DIR!\probe.obj" > "!PROBE_DIR!\probe.log" 2>&1
30+
if errorlevel 1 (
31+
echo build.bat: sccache probe FAILED wrapping cl.exe -- building WITHOUT cache.
32+
type "!PROBE_DIR!\probe.log"
33+
) else (
34+
echo build.bat: sccache probe OK ^(wrapped cl.exe^).
35+
set "LAUNCH=-DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache"
36+
)
37+
rmdir /s /q "!PROBE_DIR!" >nul 2>&1
38+
)
39+
)
740

841
mkdir build
9-
cmake -Bbuild %*
42+
cmake -Bbuild %LAUNCH% %*
43+
if errorlevel 1 exit /b %ERRORLEVEL%
1044
cmake --build build --config Release
45+
if errorlevel 1 exit /b %ERRORLEVEL%
1146

12-
if errorlevel 1 exit /b %ERRORLEVEL%
47+
REM Only query stats when sccache was actually wired in as the launcher; re-invoking
48+
REM a rejected/crashing sccache here would just repeat its failure output.
49+
if defined LAUNCH (
50+
echo build.bat: sccache --show-stats
51+
sccache --show-stats
52+
)

.github/workflows/publish.yml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,128 @@ jobs:
526526
name: Windows-x86-libraries
527527
path: ${{ github.workspace }}/src/main/resources/net/ladenthin/llama/
528528

529+
# ---------------------------------------------------------------------------
530+
# Windows Ninja Multi-Config + sccache — EVALUATION jobs (not yet released).
531+
# The Visual Studio generator ignores CMAKE_{C,CXX}_COMPILER_LAUNCHER, so the two
532+
# build-windows-* jobs above are the only uncached native builds. Upstream
533+
# llama.cpp ships its windows-cuda artifact with "Ninja Multi-Config" + MSVC,
534+
# which proves the combination works on the same tree. These two jobs run that
535+
# combination in parallel with the trusted VS jobs and front cl.exe with sccache
536+
# over Depot WebDAV (build.bat probe-guards it). Artifacts are named
537+
# `Windows-*-ninja` (NOT `*-libraries`) so the package job's `pattern: "*-libraries"`
538+
# does NOT pick them up — they are evaluation-only until cache hits are confirmed,
539+
# at which point the release path is switched over (see TODO.md). The package job's
540+
# `needs:` is intentionally left unchanged.
541+
# ---------------------------------------------------------------------------
542+
543+
build-windows-x86_64-ninja:
544+
name: Build and Test Windows 2025 x86_64 (Ninja Multi-Config + sccache, eval)
545+
needs: [startgate, build-webui]
546+
runs-on: windows-2025-vs2026
547+
env:
548+
USE_CACHE: ${{ github.event_name != 'workflow_dispatch' || inputs.use_cache }}
549+
SCCACHE_WEBDAV_ENDPOINT: https://cache.depot.dev
550+
SCCACHE_WEBDAV_TOKEN: ${{ secrets.DEPOT_TOKEN }}
551+
steps:
552+
- uses: actions/checkout@v7
553+
- name: Download shared WebUI assets
554+
uses: actions/download-artifact@v8
555+
with:
556+
name: webui-generated
557+
path: ${{ github.workspace }}/webui-generated/
558+
- name: Set up MSVC developer environment (x64)
559+
uses: ilammy/msvc-dev-cmd@v1
560+
with:
561+
arch: x64
562+
- name: Install sccache (shared compiler cache)
563+
if: env.USE_CACHE == 'true'
564+
continue-on-error: true
565+
shell: pwsh
566+
run: |
567+
$ver = "0.16.0"
568+
$rel = "sccache-v$ver-x86_64-pc-windows-msvc"
569+
$url = "https://github.com/mozilla/sccache/releases/download/v$ver/$rel.zip"
570+
Write-Host "Downloading $url"
571+
Invoke-WebRequest -Uri $url -OutFile "$env:RUNNER_TEMP\sccache.zip"
572+
Expand-Archive -Path "$env:RUNNER_TEMP\sccache.zip" -DestinationPath "$env:RUNNER_TEMP\sccache" -Force
573+
Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\sccache\$rel"
574+
- name: Display CPU Info
575+
shell: pwsh
576+
run: |
577+
Write-Host "=== CPU Information (Get-CimInstance - All Properties) ==="
578+
Get-CimInstance Win32_Processor | Select-Object * | Format-List
579+
Write-Host ""
580+
Write-Host "=== CPU Information (systeminfo) ==="
581+
systeminfo | Select-String "Processor"
582+
Write-Host ""
583+
Write-Host "=== CPU Information (Get-ComputerInfo) ==="
584+
Get-ComputerInfo -Property "CsProcessors*" 2>$null || Write-Host "Get-ComputerInfo not available"
585+
- name: Build libraries
586+
shell: cmd
587+
run: |
588+
.github\build.bat -G "Ninja Multi-Config" -DOS_NAME=Windows -DOS_ARCH=x86_64 -DBUILD_TESTING=ON
589+
- name: Run C++ unit tests
590+
run: ctest --test-dir build --output-on-failure
591+
- name: Upload artifacts
592+
uses: actions/upload-artifact@v7
593+
with:
594+
name: Windows-x86_64-ninja
595+
path: ${{ github.workspace }}/src/main/resources/net/ladenthin/llama/
596+
597+
build-windows-x86-ninja:
598+
name: Build and Test Windows 2025 x86 (Ninja Multi-Config + sccache, eval)
599+
needs: [startgate, build-webui]
600+
runs-on: windows-2025-vs2026
601+
env:
602+
USE_CACHE: ${{ github.event_name != 'workflow_dispatch' || inputs.use_cache }}
603+
SCCACHE_WEBDAV_ENDPOINT: https://cache.depot.dev
604+
SCCACHE_WEBDAV_TOKEN: ${{ secrets.DEPOT_TOKEN }}
605+
steps:
606+
- uses: actions/checkout@v7
607+
- name: Download shared WebUI assets
608+
uses: actions/download-artifact@v8
609+
with:
610+
name: webui-generated
611+
path: ${{ github.workspace }}/webui-generated/
612+
- name: Set up MSVC developer environment (x86)
613+
uses: ilammy/msvc-dev-cmd@v1
614+
with:
615+
arch: x86
616+
- name: Install sccache (shared compiler cache)
617+
if: env.USE_CACHE == 'true'
618+
continue-on-error: true
619+
shell: pwsh
620+
run: |
621+
$ver = "0.16.0"
622+
$rel = "sccache-v$ver-x86_64-pc-windows-msvc"
623+
$url = "https://github.com/mozilla/sccache/releases/download/v$ver/$rel.zip"
624+
Write-Host "Downloading $url"
625+
Invoke-WebRequest -Uri $url -OutFile "$env:RUNNER_TEMP\sccache.zip"
626+
Expand-Archive -Path "$env:RUNNER_TEMP\sccache.zip" -DestinationPath "$env:RUNNER_TEMP\sccache" -Force
627+
Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\sccache\$rel"
628+
- name: Display CPU Info
629+
shell: pwsh
630+
run: |
631+
Write-Host "=== CPU Information (Get-CimInstance - All Properties) ==="
632+
Get-CimInstance Win32_Processor | Select-Object * | Format-List
633+
Write-Host ""
634+
Write-Host "=== CPU Information (systeminfo) ==="
635+
systeminfo | Select-String "Processor"
636+
Write-Host ""
637+
Write-Host "=== CPU Information (Get-ComputerInfo) ==="
638+
Get-ComputerInfo -Property "CsProcessors*" 2>$null || Write-Host "Get-ComputerInfo not available"
639+
- name: Build libraries
640+
shell: cmd
641+
run: |
642+
.github\build.bat -G "Ninja Multi-Config" -DOS_NAME=Windows -DOS_ARCH=x86 -DBUILD_TESTING=ON
643+
- name: Run C++ unit tests
644+
run: ctest --test-dir build --output-on-failure
645+
- name: Upload artifacts
646+
uses: actions/upload-artifact@v7
647+
with:
648+
name: Windows-x86-ninja
649+
path: ${{ github.workspace }}/src/main/resources/net/ladenthin/llama/
650+
529651
# ---------------------------------------------------------------------------
530652
# CI-only jobs — no release artifact, purely for test coverage
531653
# ---------------------------------------------------------------------------

TODO.md

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,34 @@ primary goal: agentic tool-calling with Qwen):
8585
- **Gemma 4 tool-calling validation.** Confirm the pinned llama.cpp (`b9682`) includes the Gemma 4
8686
tool-call parser fixes; if not, bump per the upgrade procedure.
8787

88-
### Windows compiler cache (sccache) — deferred: needs Ninja; evaluate dual-artifact
89-
90-
The two Windows native build jobs (`build-windows-x86_64`, `build-windows-x86`) are the **only
91-
remaining uncached** native builds — the 3 macOS jobs and all 5 dockcross jobs now cache via
92-
sccache + Depot. Windows is not yet wired up because of a hard CMake constraint, and the chosen
93-
path is to validate it carefully rather than flip the working build in place.
88+
### Windows compiler cache (sccache) — evaluation in progress (Ninja eval jobs landed)
89+
90+
The two **release** Windows native build jobs (`build-windows-x86_64`, `build-windows-x86`) are
91+
still the **only uncached** native builds — the 3 macOS jobs and all 5 dockcross jobs cache via
92+
sccache + Depot. Windows can't cache under the Visual Studio generator (hard CMake constraint,
93+
below), and the chosen path is to validate the Ninja alternative carefully in parallel rather
94+
than flip the working build in place.
95+
96+
**Status — evaluation jobs have landed (this is the in-progress step):**
97+
- `.github/build.bat` now has an sccache **probe guard** mirroring `build.sh`'s
98+
`sccache_can_wrap_compiler()`: when `USE_CACHE=true` and `sccache` is on PATH, it compiles a
99+
trivial TU through `sccache cl.exe`; only on success does it pass
100+
`-DCMAKE_{C,CXX}_COMPILER_LAUNCHER=sccache` and print `sccache --show-stats`. A missing/crashing
101+
sccache falls back to a green uncached build. Inert for the VS jobs (they don't set `USE_CACHE`).
102+
- `.github/workflows/publish.yml` now has two **evaluation-only** jobs,
103+
`build-windows-x86_64-ninja` and `build-windows-x86-ninja`: `windows-2025-vs2026`,
104+
`ilammy/msvc-dev-cmd@v1` (`arch: x64`/`x86`), sccache v0.16.0 from the GitHub release zip, the
105+
Depot WebDAV env, and `build.bat -G "Ninja Multi-Config"`. Their artifacts are named
106+
`Windows-{x86_64,x86}-ninja` (**not** `*-libraries`) so the `package` job's `pattern: "*-libraries"`
107+
does **not** consume them; `package`'s `needs:` is unchanged. They run alongside the trusted VS
108+
jobs and do not affect any release artifact.
109+
110+
**What remains (wire into the release path once CI confirms cache hits):** after the Ninja jobs
111+
run green **with confirmed `sccache --show-stats` hits in the job log**, rename their uploads from
112+
`Windows-*-ninja` to `Windows-{x86_64,x86}-libraries`, add `build-windows-x86_64-ninja` +
113+
`build-windows-x86-ninja` to the `package` job's `needs:`, point `test-java-windows-x86_64` at the
114+
Ninja artifact, and retire the two VS generator jobs. That closes the Windows cache gap. Publishing
115+
is gated behind `publish_to_central`, so no broken evaluation artifact can reach Central/Releases.
94116

95117
**Why the obvious fix doesn't work.** Our cache mechanism is the CMake *compiler launcher*
96118
(`-DCMAKE_C_COMPILER_LAUNCHER=sccache`, set by `build.sh`). ggml has its own equivalent
@@ -122,18 +144,16 @@ and we can compare them before committing to one. That means the Windows native
122144
add the Ninja one alongside until it's proven equivalent. Only after the Ninja artifact is validated
123145
should we consider making it the sole Windows build (and retiring the second run).
124146

125-
**Implementation notes for when this is picked up:**
147+
**Reference notes (rationale behind the landed evaluation jobs):**
126148
- Cache backend: prefer **sccache + Depot WebDAV** (consistent with the other 8 jobs — one token,
127149
shared cross-branch) over upstream's ccache (GitHub per-branch cache, a second cache system).
128150
sccache supports MSVC `cl.exe`; Release config emits no debug info, so the `/Zi``/Z7` PDB caveat
129151
doesn't apply.
130-
- `build.bat` needs a Ninja path: pass `-G "Ninja Multi-Config"` + `-DCMAKE_BUILD_TYPE` is *not*
131-
needed (multi-config keeps `--config Release`); add an sccache presence/probe guard mirroring
132-
`build.sh` so a missing/crashing sccache falls back to a green uncached build.
133-
- Files to touch: `.github/workflows/publish.yml` (the two `build-windows-*` jobs — add the MSVC env
134-
step, the cache action, and the second artifact), `.github/build.bat` (generator + launcher wiring).
135-
- Risk is bounded: a broken Ninja build shows up as a red Windows job, and publishing is gated behind
136-
`publish_to_central`, so no broken artifact can reach Central/GitHub Releases.
152+
- `build.bat` Ninja path: pass `-G "Ninja Multi-Config"` (no `-DCMAKE_BUILD_TYPE` — multi-config
153+
keeps `--config Release`); the sccache presence/probe guard mirrors `build.sh` so a
154+
missing/crashing sccache falls back to a green uncached build. (Done.)
155+
- Risk is bounded: a broken Ninja build shows up as a red **evaluation** Windows job, and publishing
156+
is gated behind `publish_to_central`, so no broken artifact can reach Central/GitHub Releases.
137157

138158
### llama.cpp upstream feature exposure (queued, deferred by policy)
139159

0 commit comments

Comments
 (0)