xwin: MSVC CRT and Windows SDK headers without a Windows machine
A utility for downloading and packaging the Microsoft CRT & Windows SDK headers and libraries needed for compiling and linking programs targeting Windows.
At a glance
- What is it?
- Jake-Shadle/xwin downloads and repacks the Microsoft CRT and Windows SDK into a directory that clang and LLVM based toolchains can use for cross compiling, with symlinks that fix Windows casing assumptions on case-sensitive filesystems.
- Who is it for?
- Use xwin if you cross compile to Windows with clang or LLVM and need the real Microsoft headers and import libraries instead of a MinGW or open source substitute. Do not reach for it on a native Windows build host, where the installed SDK already covers the same ground, and do not use it if your licensing policy forbids redistributing Microsoft runtime components.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 73 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A cross compilation target built from downloaded packages
Cross compiling to Windows usually means choosing between two kinds of toolchain. You can use a MinGW style GCC build, or you can point clang at the genuine Microsoft CRT and Windows SDK files so that the produced binaries match what Microsoft's own compiler would produce. xwin exists for the second case, and it does it without asking you to install Windows or run a virtual machine.
The stated goal is to create a root directory for both the CRT and the Windows SDK, where each contains all the includes and libraries needed for an application to compile and link from a non-Windows platform using a native cross compiling toolchain like clang and LLVM. The project is written in Rust, distributed through crates.io, and licensed Apache-2.0 OR MIT.
The interesting part is the file layout it produces. The splat output separates a crt directory, holding the C runtime includes and a lib directory per architecture, from an sdk directory, holding the SDK includes and the ucrt and um libraries. Both halves sit side by side under one root so that a compiler can be pointed at a single include path and a single library path.
Casing is the problem symlinks solve
The reason xwin does more than unzip files is spelled out in the documentation. The Windows SDK is written for a case-insensitive filesystem, so an include written as `#include <windows.h>` breaks on Linux or macOS, where the actual path in the `WindowsSDK` directory is `Windows.h`.
The same trap exists in the CRT, and the documentation makes the point that correcting your own casing does not save you, because the internal headers also use incorrect casing in most cases. So a project with a clean include list can still fail to build.
The fix is a pass that adds symlinks to correct the casing, applied to both the CRT and the `WindowsSDK`. By default those symlinks are created, and a `--disable-symlinks` option turns them off if you would rather deal with the real paths. The same pass also prunes files that are not needed.
This is the design decision that distinguishes xwin from a plain archive extractor. The output is not a byte for byte copy of the SDK, it is a directory shaped so that a case-sensitive toolchain can consume it.
Installing xwin and fetching the packages
The project is a normal Rust crate, so installation from source is a single cargo command:
cargo install xwin --lockedIf you would rather not compile it, the Releases page publishes prebuilt binaries, and the documentation lists three targets:
x86_64-unknown-linux-musl
x86_64-apple-darwin
aarch64-apple-darwinNote what is absent from that list: there is no Windows binary, which matches the purpose, since the tool exists to build Windows targets from elsewhere. There is also no aarch64 Linux target listed.
The first real run is the splat command, which is described as the main command you will want to run because it downloads and unpacks automatically and places the headers at the path given by `--output`, defaulting to `./.xwin-cache/splat`. Downloads are cached on disk under `./.xwin-cache` by default, so a second run does not fetch everything again.
download, unpack, splat are three separate stages
The command set separates the pipeline into three verbs, and understanding the split explains most of the flags.
`xwin download` fetches the top level manifest and any vsix, msi or cab files that are needed and are not already in the download cache. `xwin unpack` decompresses all of the downloaded package contents to disk, and download runs automatically first. `xwin splat` is the step that fixes the packages to prune unneeded files, adds the casing symlinks and moves the final artifacts into the output directory, and unpack runs automatically as needed.
The stages exist for practical reasons. If a build machine has restricted network access, you can run download somewhere with access and move the cache. If you need to inspect what was downloaded before it is reorganised, unpack gives you that view. If a job needs to run repeatedly, the cache directory keeps the expensive part local.
Version selection is driven by the manifest. `--manifest-version` defaults to 17, `--sdk-version` and `--crt-version` override which versions are used, and `--channel` picks the product channel, defaulting to release. Passing `--manifest` lets you supply a top level manifest yourself, which the documentation points at as a way to ensure the output is reproducible.
Choosing an architecture, a variant, and a target layout
Three flags decide what you actually get, and the documentation is candid about where the edges are.
`--arch <arch>` selects the architectures to include, defaulting to `x86_64`, with `x86`, `x86_64`, `aarch` and `aarch64` as the possible values. The documentation warns that aarch and x86 have not been fully tested and that issues may exist. `--variant <variant>...` selects the variants, defaulting to `desktop`, with `desktop`, `onecore` and `spectre` as the possible values. Only `desktop` has been fully tested, and a fourth `store` variant is described as not implemented at all.
Architecture naming is another source of friction. By default the tool converts the Microsoft specific `x64`, `arm` and `arm64` names into the canonical `x86_64`, `aarch` and `aarch64` used by LLVM, and `--preserve-ms-arch-notation` keeps the original names instead. That flag matters when your build scripts reference the Microsoft spelling.
There is also a layout switch. `--use-winsysroot-style` produces the `/winsysroot` layout so that clang-cl's `/winsysroot` flag can be used directly, rather than needing both `-vctoolsdir` and `-winsdkdir`. The documentation suggests combining it with `--preserve-ms-arch-notation` and `--disable-symlinks` when you are using clang-cl on Windows.
Trimming the output: debug libs, symbols, copies and maps
A full SDK download is large, and the splat options exist to control what ends up in your output directory.
`--include-debug-libs` keeps the MSVCRT debug versions of the libraries, and `--include-debug-symbols` keeps the PDB files for several of the libraries. The documentation describes both as generally uninteresting for most usage, which is a fair default for a build that only needs to link and ship.
`--copy` copies files from the unpack directory to the splat directory instead of moving them. The tradeoff is spelled out: it preserves the original unpack directories but increases overall execution time and disk usage. That is the right choice when you want to keep the downloaded tree intact for inspection or for a second splat with different options.
Finally there is `--map`, an optional file that configures what files are splatted and which additional symlinks to create. That is the extension point for anyone whose build needs a header or library that the default pruning would remove, and it is the first flag to look at when a link fails on a missing symbol rather than on a missing header.
Licensing, provenance and the limits of the test coverage
xwin distributes Microsoft components, and the documentation treats the licence acceptance as a first-class step rather than an afterthought. The `--accept-license` flag skips the prompt, and the same effect is available through the `XWIN_ACCEPT_LICENSE=1` environment variable. `https_proxy` is the one environment variable the documentation lists for network configuration, which matters on build machines behind a proxy.
Because the tool copies licensed runtime components and redistributable libraries into a directory you control, what you do with that directory afterwards is your responsibility, and this review does not give legal advice on the redistribution question.
On the engineering side, the honest limitation is the narrow test coverage described earlier: one architecture and one variant are fully tested, the `store` variant does not exist, and the download is a live fetch of current Microsoft packages, so the exact bytes you get depend on the manifest you resolve. The crate itself is versioned sensibly, with 0.10.0 released on 2026-08-12 after 0.9.0 on 2026-04-20 and 0.8.0 on 2026-02-06, and the repository ships an Earthfile, a Dockerfile and a deny.toml for dependency and licence checks in CI.
Editorial conclusion
Use xwin if you cross compile to Windows with clang or LLVM and need the real Microsoft headers and import libraries instead of a MinGW or open source substitute. Do not reach for it on a native Windows build host, where the installed SDK already covers the same ground, and do not use it if your licensing policy forbids redistributing Microsoft runtime components. Check first which architectures and variants you actually need, because the documentation states only the desktop variant and x86_64 have been fully tested, and the last push was on 2026-08-12 alongside the 0.10.0 release.
Frequently asked questions
What does xwin actually download and where does it put the result?
It downloads the Microsoft CRT and Windows SDK headers and libraries, then splats them into a root directory that defaults to `./.xwin-cache/splat`. The layout has a `crt` directory and an `sdk` directory, each with `include` and `lib` subdirectories.
Why do I need xwin when I already have a Windows SDK?
xwin is for building Windows targets from a non-Windows platform, using clang or LLVM instead of the Microsoft compiler. On a native Windows machine the installed SDK already provides those headers and libraries, so the tool is not needed there.
Which xwin architectures and SDK variants are known to work?
The documentation states that only the `desktop` variant has been fully tested, and that aarch and x86 have not been fully tested either, with `x86_64` as the default. The `store` variant is not implemented.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jake-shadle-xwin)Was this useful?