This page tracks every external SDK, header set, metadata file, and runtime the build and tooling
depend on: the version, where it is pinned, how it is obtained, and how the pin is validated. It
covers build/tooling and runtime dependencies (Windows SDK, WDK, WinRT contracts, libclang,
Windows App SDK, WebView2). It does not cover the crates.io Rust dependencies in Cargo.toml,
which are already centralized under [workspace.dependencies].
There is no central version registry. Every external dependency has a single owning tool that
declares the pin as a const, downloads/consumes the artifact at that exact version, and runs in CI
(.github/workflows/gen.yml) - so running the tool proves the pin is current, in one of two ways:
- Generators (
tool_win32,tool_winrt,tool_webview,tool_reactor) regenerate committed artifacts;gen.ymlruns each thengit diff --exit-code, so a stale pin produces a diff and fails. - Validators (
tool_clang, and guards inside generators) assert invariants and write nothing; a violation panics loudly, failing the job with a clean tree.
When one crate must track a pin another crate owns, the owner reads the peer's constant straight
from source with helpers::read_str_const and asserts they
agree. Pins are never copied - they are read back and checked. windows-clang stays a clean
libclang library and is not a shared home for SDK/runtime versions.
| Dependency | Version | Owner (pin) | Obtained by | Validated by |
|---|---|---|---|---|
| libclang | 22.1.8 |
LIBCLANG_VERSION - crates/libs/clang/src/provision.rs |
download (NuGet: libclang.runtime.win-<arch> + git sparse checkout of LLVM headers) |
tool_clang validator + runtime assert |
| Windows SDK | 10.0.28000.2270 |
SDK_VERSION - crates/tools/win32/src/main.rs |
download (NuGet) | tool_win32 zero-diff regen |
| Windows WDK | 10.0.28000.1839 |
WDK_VERSION - crates/tools/win32/src/km.rs |
download (NuGet) | tool_win32 zero-diff regen |
| SDK Contracts (WinRT) | 10.0.28000.2270 |
CONTRACTS_VERSION - crates/tools/winrt/src/main.rs |
download (NuGet) | tool_winrt zero-diff regen |
| WebView2 SDK headers | 1.0.4078.44 |
WEBVIEW2_VERSION - crates/tools/webview/src/main.rs |
download (NuGet) | tool_webview zero-diff regen |
WinUI / Windows App SDK metadata (.winmd files) |
2.3.1 |
WINDOWS_APP_SDK_VERSION - crates/tools/reactor/src/main.rs |
download (NuGet) | tool_reactor zero-diff regen of the committed metadata |
| Windows App SDK runtime | 2.3.1 |
RUNTIME_VER - crates/libs/reactor-setup/src/lib.rs |
download (NuGet) + committed bootstrap DLLs | tool_reactor guard: == WINDOWS_APP_SDK_VERSION, and reactor.yml matches |
| WebView2 runtime projection | 1.0.4078.44 |
WEBVIEW2_VER - crates/libs/reactor-setup/src/lib.rs |
download (NuGet) | tool_reactor guard: == WEBVIEW2_VERSION |
| LLVM / libclang (CI) | 22.1.8 |
LIBCLANG_VERSION - crates/libs/clang/src/provision.rs |
download (NuGet) via tool_clang path |
tool_clang: loads the pin and asserts its version |
The header scrapers (tool_win32, tool_webview) parse C/C++ with libclang. The
version is pinned because clang's macro-capture behavior drifts across majors, which would silently
change the generated metadata.
- Owner:
provision.rsdeclaresLIBCLANG_VERSION = "22.1.8".libclang.dllcomes from thelibclang.runtime.win-<arch>NuGet packages (dotnet/clangsharp, .NET Foundation) fetched at that version. The paired clang builtin resource headers (needed only for the non-x64 arch passes, to reconcile the aarch64__prefetchbuiltin) come from a blobless, shallow, sparsegitcheckout ofclang/lib/Headersat the derivedllvmorg-<ver>tag - so the DLL and headers are the same single-const pin and can never drift. - Obtained: if
LIBCLANG_PATHis unset,ensure_libclangfetches the pinnedlibclang.runtime.win-<arch>package vianuget_package(the shared NuGet global cache, same as the SDK/WDK/WebView2 pins) and pointsLIBCLANG_PATHat itsruntimes/<rid>/native/; non-x64 passes also fetch the pinned LLVM resource headers viagit.LIBCLANG_PATH/CLANG_RESOURCE_DIRoverride for offline machines. All three scrapers call it, so theirgen.ymljobs need no LLVM install - they always parse with the pinned22.1.8, in CI and on a fresh checkout alike. - CI: every workflow self-provisions the pinned libclang from NuGet - no CI job installs LLVM.
The
gen.ymlscrapers callensure_libclang;clippy.ymlloads no libclang at all (cargo clippynever parses); andtest.yml, whosetest_clangsuite loads libclang at runtime, exportsLIBCLANG_PATHfrom the same pin via `echo "LIBCLANG_PATH=$(cargo run -q -p tool_clang -- path)""$GITHUB_ENV"
.tool_clang pathprintswindows_clang::libclang_dir(), keeping theunsafeset_var` off the multithreaded test runner. The Linux CI jobs build code that needs no libclang. - Validated by
tool_clang: fetches, loads, and version-asserts the pin (the same provisioning the scrapers run). Writes nothing. - To update: bump
LIBCLANG_VERSION- a single const that drives both the NuGet DLL and thellvmorg-<ver>git tag for the headers, so there is nothing else to touch. Runtool_clang(must pass) and regenerate all metadata. No prebuilt-asset ceiling: the DLL comes from NuGet and the headers from a git tag, both of which track current LLVM.
Each feeds an in-house generator producing a committed .winmd in windows-default. The metadata
is embedded for Rust build tools and remains available as files for external tools. Provenance is
documented in crates/libs/default/readme.md.
windows-bindgen, windows-rdl, and windows-clang depend on windows-default so their builders
can select this metadata without filesystem paths. Binaries linking those crates include both
metadata files.
| Package | Owner (pin) | Produces |
|---|---|---|
Microsoft.Windows.SDK.CPP[.<arch>] |
SDK_VERSION - tool_win32 |
um scrape half of Windows.Win32.winmd |
Microsoft.Windows.WDK.x64 |
WDK_VERSION - tool_win32 |
km scrape half of Windows.Win32.winmd |
Microsoft.Windows.SDK.Contracts |
CONTRACTS_VERSION - tool_winrt |
Windows.winmd |
- Obtained:
windows_clang::nuget_package(id, version)restores from the NuGet global cache or downloads from nuget.org (NUGET_PACKAGESoverrides the cache). tool_win32runs both scrapes, so the WDK km scrape reuses the sameSDK_VERSIONheaders as the um scrape (they share the crate);WDK_VERSIONis a separate pin inkm.rs.- The "marketing" include/lib folder nested in each package (e.g.
10.0.28000.0) is derived from the version viahelpers::marketing_dir(first three components +.0), so the version is the single edit - never a second folder constant to keep in sync. - To update: bump the owning constant, run
cargo run -p tool_<win32|winrt>, and commit the regenerated.rdlsnapshot(s) and.winmd.
CONTRACTS_VERSION happens to share the 10.0.28000 build number with SDK_VERSION, but it is a
distinct NuGet package with its own pin - the two are not coupled and can diverge.
WebView2 ships only C/C++ SDK headers, so windows-webview is scraped from them. The WinRT Core
metadata and runtime projection DLL are separate artifacts.
| Artifact | Owner / location | Used by |
|---|---|---|
WebView2.h, WebView2Interop.h |
WEBVIEW2_VERSION - tool_webview (downloaded, not vendored) |
tool_webview -> webview/src/bindings.rs |
Microsoft.Web.WebView2.Core.winmd |
regenerated into crates/tools/reactor/winmd/ by tool_reactor at WEBVIEW2_VERSION |
tool_webview, tool_reactor |
Runtime projection (Core.dll), WEBVIEW2_VER |
crates/libs/reactor-setup/src/lib.rs |
self-contained apps |
| Evergreen runtime | .github/workflows/webview.yml |
CI test host |
- Headers are downloaded, not vendored:
tool_webviewfetches the pinned NuGet package vianuget_packageand parses the headers from it. A bump is a one-lineWEBVIEW2_VERSIONedit. - Pinned libclang: like
tool_win32,tool_webviewcallsensure_libclang+assert_libclang_version, so it parses with the exact pinned22.1.8(itsgen.ymljob needs no LLVM install - only the SDK include paths for the system headersWebView2.hpulls in). - Runtime projection: bump
WEBVIEW2_VERinreactor-setup; it must equalWEBVIEW2_VERSION-tool_reactorasserts this. Core.winmdis refreshed into the reactor metadata bytool_reactoratWEBVIEW2_VERSION(see below).
For the full pipeline and COM<->WinRT bridge, see windows-webview.
windows-reactor is generated from WinUI / Windows App SDK .winmd; windows-reactor-setup stages
the matching runtime so reactor apps run. Metadata and runtime are two faces of one release, tied to
a single number.
Metadata is regenerated, not hand-copied. tool_reactor owns
WINDOWS_APP_SDK_VERSION = "2.3.1". On every run it downloads the umbrella
Microsoft.WindowsAppSDK metapackage at that version, reads the exact component versions
(Foundation / InteractiveExperiences / WinUI) pinned in its nuspec, downloads each component, and
copies their .winmd - plus Microsoft.Web.WebView2.Core.winmd at WEBVIEW2_VERSION - into the
committed metadata at crates/tools/reactor/winmd/. It also refreshes the committed bootstrap DLLs
(crates/libs/reactor-setup/bootstrap/<arch>/) from that same Foundation package's
runtimes/<rid>/native/, so metadata and staged runtime provably come from one pin. gen.yml
re-runs the tool and fails on any diff, so both provably match the pin. (extras.winmd in that
directory is generated by tool_reactor from Windows.Win32.winmd, not a package.) The metadata
stays committed because tool_webview and tool_composition also read it.
| Artifact | Owner / location | Used by |
|---|---|---|
WinUI / Windows App SDK .winmd + WebView2.Core.winmd |
regenerated into crates/tools/reactor/winmd/ at WINDOWS_APP_SDK_VERSION |
tool_reactor, tool_webview, tool_composition |
Microsoft.WindowsAppSDK.Runtime, RUNTIME_VER |
crates/libs/reactor-setup/src/lib.rs |
app runtime deploy |
| Bootstrap DLLs (x86/x64/arm64) | regenerated into crates/libs/reactor-setup/bootstrap/ at WINDOWS_APP_SDK_VERSION |
framework-dependent apps |
resources.pri, app.manifest, runtime.txt |
crates/libs/reactor-setup/assets/ (committed) |
runtime staging |
| Runtime installer | .github/workflows/reactor.yml |
CI test host |
windows-reactor-setup is a published runtime helper with no generated artifact, so its pins can't
be proven by regen. Instead tool_reactor guards them on every run, asserting (and failing
loudly on drift) that:
-
WINDOWS_APP_SDK_VERSION(metadata) equalsRUNTIME_VER(runtime) - one number drives both; -
WEBVIEW2_VERequalsWEBVIEW2_VERSION, so the staged WebView2 runtime matches the ABI the bindings target; and -
reactor.yml's installer URL installsRUNTIME_VER(.../windowsappsdk/<major.minor>/<ver>/), so CI's self-tests exercise the runtime apps ship. -
To update metadata + runtime: bump
WINDOWS_APP_SDK_VERSION(tool_reactor) andRUNTIME_VER(reactor-setup) together, update thereactor.ymlinstaller URL, then runcargo run -p tool_reactorand commit the refreshed metadata and bootstrap DLLs. The guard enforces the version agreement; the regen enforces the metadata and the bootstrap binaries. -
assets/app.manifest/assets/resources.priare generated activation assets with no committed generator -app.manifesttransforms the App SDKpackage.appxfragmentfiles into SxS fusion format (source versions in its header). They are forward-compatible, so refreshed only when the reactor control set needs newly-moved classes, not on every bump.
See windows-reactor and windows-reactor-setup.
Two independent NuGet paths, both using https://www.nuget.org/api/v2/package/{id}/{version}:
windows_clang::nuget_package- used by the scraping/codegen tools (tool_win32,tool_winrt,tool_webview,tool_reactor). Restores into the NuGet global cache (NUGET_PACKAGESoverrides), else downloads via bundledcurl/tar. Layout-agnostic - each caller indexes the subtree it needs.reactor-setup's staging - runs in thebuild.rsof every consuming app to stage the App SDK runtime and WebView2 projection. Dependency-free (std + thecurl.exe/tar.exeshipped with Windows), which is why it does not reusenuget_package.
| Tool | Proves | How |
|---|---|---|
tool_win32 |
SDK_VERSION, WDK_VERSION |
zero-diff regen of Windows.Win32.winmd (um + km scrapes and their merge) |
tool_winrt |
CONTRACTS_VERSION |
zero-diff regen of Windows.winmd |
tool_webview |
WEBVIEW2_VERSION |
zero-diff regen of webview/src/bindings.rs |
tool_clang |
LIBCLANG_VERSION (drives NuGet DLL + llvmorg-<ver> header tag) |
pure-check assertion |
tool_reactor |
WINDOWS_APP_SDK_VERSION; reactor-setup sync |
zero-diff regen of the winmd files + bindings + bootstrap DLLs; guard reads reactor-setup constants |
All cross-file reads go through helpers::read_str_const, so each pin is declared once by its owner
and read back everywhere else.