Compile C++/WinRT for Windows, from Linux. Companion to openappx, which packages, signs and deploys the result.
Status: what is built here runs on a console.
examples/hello-uwphas been launched and observed running on an Xbox Series S dev kit — and not just the example: an existing UWP project of 216 translation units, a large third-party inference library among them, compiled and linked from its own.vcxprojfiles without changing a line of its source, packed, signed, installed and observed running on the same console — its own log shows the window activated and a GGUF model loaded through the inference library (2026-08-08, after the reroutes of n°23). docs/porting-a-vcxproj.md is the recipe; Known limits is the honest edge (one console, one OS build).
yay -S uwp-crossbuild # Arch, from the AURor from a checkout:
make install # into ~/.local; ~/.local/bin must be on PATH
sudo make install PREFIX=/usr # system-wideThe scripts land under $PREFIX/lib/uwp-crossbuild and are exposed as
uwp-build, uwp-build-app, uwp-check-deps and so on. They are installed as
a tree rather than as loose files: build.sh reads include/msvc-compat.h from
beside itself. make uninstall removes everything.
Running from a checkout works too — every example below does — and needs no installation at all.
scripts/check-deps.sh # what is missing, before downloading
# xwin comes first: fetch-sdk.sh reads the C++/WinRT version out of the headers
# it installs, and pinning cppwinrt.exe to anything else fails every build.
# --cache-dir, or xwin leaves a 424 MB .xwin-cache in whatever directory you
# happened to be in — the project you are building, usually.
xwin --accept-license --arch x86_64 \
--cache-dir ~/.cache/uwp-crossbuild/xwin-download \
splat --output ~/.cache/uwp-crossbuild/xwin
scripts/fix-header-case.sh ~/.cache/uwp-crossbuild/xwin/sdk/include/cppwinrt/winrt --canonical
scripts/fetch-sdk.sh # SDK tools, ~1.1 GB, cached
# a console program, to check the toolchain end to end
scripts/build.sh --out hello.exe examples/hello-winrt/app.cpp
wine hello.exe
# domain=example.com path=/path
# vector size=3
# a real UWP application: idl -> winmd -> projection -> PE -> pri -> layout
scripts/build-app.sh --project examples/hello-uwp --out /tmp/hello-layout
# an existing Visual Studio project, read rather than reconstructed
scripts/build-project.sh --project uwp/app.vcxproj --out /tmp/layout
# onto the console: packed, signed, installed, launched (openappx does the wire)
scripts/run-on-device.sh --layout /tmp/hello-layoutrun-on-device.sh reads the device half of its configuration from
~/.config/uwp-crossbuild/device-env — UWP_DEVICE_URL, UWP_DEVICE_USER and
OPENAPPX_DEVICE_PASSWORD, as shown in Dev Home → Remote Access — and signs
with ~/.config/uwp-crossbuild/dev.pfx, whose subject must equal the
manifest's Publisher and whose .cer the console must trust once
(openappx deploy … --install-cert). Neither file belongs in a repository.
It requires openappx 0.6.3 or newer (pipx install 'openappx>=0.6.3'):
earlier releases build the launch request wrong and every start fails as an
opaque 0x8D160120, so the script refuses them up front.
| Step | Tool | Status |
|---|---|---|
| Compile + link C++/WinRT | clang-cl + lld-link |
✅ PE32+ that runs |
.idl → .winmd |
midlrt.exe under Wine |
✅ valid metadata |
.winmd → projection headers |
cppwinrt.exe under Wine |
✅ App.g.h+module.g.cpp |
resources → resources.pri |
makepri.exe (32-bit) under Wine |
✅ (optional — see below) |
| App-container executable | lld-link /appcontainer |
✅ DllCharacteristics 0x1000 |
| An unmodified VS source tree | include/msvc-compat.h, force-included |
✅ 216/216 of a real project |
| C and C++ in one project | build.sh, one pass |
✅ per-language standards |
Reading a .vcxproj |
read-vcxproj.py, an MSBuild subset |
✅ or a refusal, never a guess |
| ARM64 | --platform ARM64, same pipeline |
✅ ARM64 PE — see Known limits |
| Link a whole application | lld-link |
✅ 7.5 MB PE32+ |
| Package, sign, deploy | openappx | ✅ installed on an Xbox |
| Launch, on the console | run-on-device.sh, Device Portal |
✅ observed running (Series S) |
/MD via the store CRT |
fetch-vclibs.sh + build.sh --store-crt |
✅ imports match a VS build's |
| Activation contract, checked | pe-import-audit.sh, after every link |
✅ trips on every desktop PE |
- Runs, on one console.
examples/hello-uwp, built bybuild-project.shand deployed byrun-on-device.sh, has been launched and observed running on an Xbox Series S (OS 26100.8866) — process in the task list, text on the screen. The earlier record here said the console refused to launch every sideloaded package with0x8D160120, Microsoft Edge included; that turned out to be two bugs in openappx's Device Portal client (an AUMID built with a double underscore, and a missingpackageparameter), and it never said anything about the console or the packages. One console is not a matrix: other OS builds and devices remain untried. resources.priturns out to be optional for install. Packaged with and without it, both variants installed. Kept inbuild-app.shby default because localised resources need it at runtime, which is not testable while launching is;--no-priskips the step, and with it the only reason makepri exists here.- ARM64 builds, and has never executed. With the aarch64 libraries splatted
(
xwin --arch x86_64 --arch aarch64 …),--platform ARM64on either front door (build-project.sh,build-app.sh) — orUWP_TARGET=aarch64-pc-windows-msvc UWP_ARCH_DIR=aarch64for the scripts below them — produces anIMAGE_FILE_MACHINE_ARM64image with the app-container bit, through the same midlrt/cppwinrt/makepri pipeline. Verified by reading the PE header; per the first limit, no device has run it. The manifest ships verbatim and both front doors refuse one whoseProcessorArchitecturedisagrees with the platform —examples/hello-uwpdeclaresx64, so its ARM64 build starts by setting that attribute toarm64, exactly as the refusal says. Re-runfix-header-case.sh --canonicalafter any re-splat: xwin rewrites the cppwinrt headers and undoes the aliases. - No
.xamlfiles, ever. The XAML compiler has no Linux equivalent and does not run under Wine. Build the UI in code, asexamples/hello-uwpdoes. - The PCH is ~190 MB per project, in the object directory.
Measured on this example (3 translation units, LLVM 22.1.8). The XAML projection is what costs: every translation unit that includes it pays ~30 s.
without --pch |
with --pch |
|
|---|---|---|
| first build | 98 s | 41 s |
| rebuild | 98 s | 1.3 s |
build-app.sh passes --pch whenever the project has a pch.h. The
precompiled header is ~190 MB and is reused until the header itself changes.
| Dependency | Why | Verified with |
|---|---|---|
clang-cl, lld-link |
compiling and linking for the MSVC ABI | LLVM 22.1.8 |
llvm (readobj, dlltool, lib, ar, nm) |
the PE audit after every UWP link; import libraries and archives | LLVM 22.1.8 |
wine |
running midlrt / makepri / cppwinrt | 11.14 |
winetricks → msxml6 |
makepri validates its schema through MSXML | 20260125 |
xwin |
CRT and SDK headers/libraries | 0.9.0 |
p7zip, curl |
unpacking the NuGet and SDK payloads | — |
python3 |
fix-header-case.sh --canonical |
3.14 |
Nothing from Microsoft is redistributed: both fetch-sdk.sh and xwin download
from Microsoft's CDN at run time under the SDK licence. CI must re-run them
rather than cache the result in an artefact store.
Every location, version and target the scripts assume can be overridden:
| Variable | Default | What it changes |
|---|---|---|
UWP_XWIN_ROOT |
~/.cache/uwp-crossbuild/xwin |
where xwin splat put the CRT and SDK headers and libraries |
UWP_SDK_ROOT |
~/.cache/uwp-crossbuild/sdk |
where fetch-sdk.sh extracts the SDK tools and metadata |
UWP_SDK_WORK |
~/.cache/uwp-crossbuild/work |
the installer download and layout cache |
UWP_SDK_VERSION |
10.0.22621.0 |
the version directory the tools and metadata live under |
UWP_SDK_URL |
Microsoft's fwlink for that SDK | the web installer fetch-sdk.sh downloads |
UWP_CPPWINRT_VERSION |
read from xwin's base.h |
the cppwinrt.exe pin — must match the winrt/ headers (n°13) |
UWP_CPPWINRT_EXE |
$UWP_SDK_ROOT/cppwinrt/bin/… |
the cppwinrt.exe Wine runs (CPPWINRT_EXE still works) |
UWP_CPPWINRT_INCLUDE |
unset | project-pinned winrt/ headers, placed before xwin's (must come from the same cppwinrt.exe as UWP_CPPWINRT_EXE) |
UWP_TARGET |
x86_64-pc-windows-msvc |
clang's -target; build-project.sh --platform sets it |
UWP_ARCH_DIR |
x86_64 |
the architecture subdirectory of the CRT and SDK libraries |
UWP_CXX_STD |
c++20 |
/std: for C++ — c++17 cannot work (n°1) |
UWP_C_STD |
c17 |
/std: for .c sources |
UWP_OBJ_DIR |
<out>.objs (<out>.build for a layout) |
objects, PCH and generated files |
UWP_NUGET_FEED |
https://www.nuget.org/api/v2/package |
where restore-nuget.sh downloads from |
UWP_VCLIBS_ROOT |
~/.cache/uwp-crossbuild/vclibs |
the store CRT cache fetch-vclibs.sh fills (n°19) |
UWP_VCLIBS_URL |
none — there is no stable public link | where fetch-vclibs.sh --url downloads the framework appx |
UWP_VCLIBS_ACCEPT_LICENSE |
unset | 1 accepts Microsoft's terms for that download, as a flag would |
UWP_DEVICE_ENV |
~/.config/uwp-crossbuild/device-env |
the file run-on-device.sh sources for the device variables |
UWP_DEVICE_URL / _USER |
from that file | the Device Portal, as in Dev Home → Remote Access |
UWP_DEVICE_PFX |
~/.config/uwp-crossbuild/dev.pfx |
the signing certificate; subject must equal the Publisher |
OPENAPPX_DEVICE_PASSWORD belongs to openappx and completes the device trio;
wine-tool.sh also honours WINEDEBUG, defaulting it to -all.
Every one of these fails while pointing somewhere else. The scripts handle them; this is the record of why they exist.
-
/std:c++17cannot work. C++/WinRT falls back to<experimental/coroutine>, whose first line is an#errorrefusing clang. Use/std:c++20, where<coroutine>is standard. A.vcxprojsaying<LanguageStandard>stdcpp17has to be overridden, not honoured. -
Projection header casing cannot be guessed.
#include <winrt/Windows.ApplicationModel.Activation.h>meets a file namedwindows.applicationmodel.activation.h, and capitalising each segment givesApplicationmodel.fix-header-case.sh --canonicalreads the namespace out of each header instead, where it is spelled correctly — but only to fix that file's own casing. Let a header claim any namespace it declares andbase.h, which forward-declares half of them and sorts first, takesWindows.Foundation.hfor itself. The real one holdsbox_value, so the symptom is a missing function. -
WindowsApp.libis not optional. Without it the link fails onWINRT_IMPL_CoInitializeExand friends, which reads like a broken toolchain rather than a missing library. -
-mcx16, or an undefined__atomic_compare_exchange_16. MSVC assumes cmpxchg16b on x64; clang does not. C++/WinRT's factory cache needs it. The link error names no header and no source line. -
#undef GetCurrentTimeafter<windows.h>.winbase.hdefines it as a macro, XAML'sTimelinedeclares a method by that name, and the projection header stops parsing. The error blames the header. -
An STL header must precede
winrt/base.h. base.h enables coroutines with#ifdef __cpp_lib_coroutinebefore including<coroutine>. Under MSVC the macro is already there from whichever STL header came first; apch.hopening with<windows.h>leaves clang without it, and coroutine support compiles out silently. An ordinaryIAsyncActionis then reported as "this function cannot be a coroutine", pointing at your code.Handled for you:
include/msvc-compat.his force-included ahead of every translation unit, so a source tree written for Visual Studio compiles unmodified. That is where this andGetCurrentTimelive. -
<cstdlib>underWINAPI_FAMILY_APPneeds a compile-time bridge.--uwpsets/DWINAPI_FAMILY=WINAPI_FAMILY_APP(same as Visual Studio UWP) so the headers keep desktop-only Win32 and CRT out of the compile. The ucrt then gatesgetenv/systemon_CRT_USE_WINAPI_FAMILY_DESKTOP_APP, while the MSVC STL still doesusing _CSTD getenv;/using _CSTD system;unconditionally — every TU that includes<cstdlib>fails with "no member named 'getenv'".include/msvc-compat.hprovides C declarations for those two names under non-desktop families so theusingresolves. Declaration only: no bodies, no re-opened desktop partition, no license to call them in an AppContainer.
-
midlrt shells out to
cl.exe, reportingMIDL1005: cannot find C preprocessor. Pass/no_cpp; a normal UWP.idlhas no directives. -
WinRTBase.idlvswinrtbase.idl. Same file on NTFS, two files here.fix-header-case.sh --lowerhandles the include directories. -
MAX_PATH, silently. A
.winmdpath over 260 characters arrives truncated —...UniversalApiContract.w?— and is rejected as "not a winmd". Nothing mentions length. Build from a short directory. -
Windows.winmdships in its own MSI (Windows SDK Facade Windows WinMD Versioned), separate from the tools and the contracts. Without/metadata_dirpointing atUnionMetadata/, midlrt fails withMIDL4034. -
midlrt's
/outrejects a Unix path withMIDL1012: argument illegal for switch.gen-projection.shruns it from the destination directory instead. Its lexer also refuses a backtick anywhere in the file, comments included:MIDL2025: Illegal character (0x60). -
cppwinrt.exe and the
winrt/headers must be the same version. The generated projection carries astatic_asserton it, so the newest NuGet against xwin's headers fails every build with "Mismatched C++/WinRT headers".fetch-sdk.shreads the version out ofbase.h. -
makepri needs MSXML6, then only its 32-bit build survives. Without MSXML:
PRI175: Initializing Indexer / Schema Validation Failed. With it, the x64 build page-faults inside MSXML while the x86 one works. Same.prieither way;wine-tool.shpicks the right one. It also reads the manifest strictly: a--inside an XML comment getsPRI191: Appx manifest not found or is invalid, which is true — that is not legal XML — but says nothing about comments. -
GDI collides with every shape XAML draws — fixed by the app family.
wingdi.hdeclaresPolyline,Rectangle,Ellipse,PolygonandPath; XAML has a class for each. With the desktop family those names land in the global namespace and a page that saysPolyline{}afterusing namespace …Xaml::Shapesstops on "reference to 'Polyline' is ambiguous". Visual Studio never sees them:wingdi.hputs them behindWINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP), and--uwpsetsWINAPI_FAMILY=WINAPI_FAMILY_APP(n°7). The partition does the work; no separateNOGDIworkaround. -
msiexec /atakes a Windows path for the package, not just for TARGETDIR. An administrative install copies the package into TARGETDIR by appending the path it was given, so a Unix path sends it toTARGETDIR\home\you\…, which does not exist. It fails on its first file withERROR_PATH_NOT_FOUND, then rolls back and deletes TARGETDIR — so the next attempt starts by finding nothing and reads as a broken Wine prefix.WINEDEBUG=+msi,+fileis what shows the path it tried.
-
XAML wants its first Application access from the MTA.
wWinMaincallswinrt::init_apartment()— the multi-threaded default — beforeApplication::Start, and it is not a nicety: with no apartment, or with a single-threaded one, the factory call insideStartthrowswinrt::hresult_wrong_thread, nothing catches it, and the process dies interminate -> abortbefore any window exists. The activation manager reports that as0x8027025B, which names nothing; the actual origination message — "The Application Object must initially be accessed from the multi-thread apartment" — surfaces only in a crash dump (/api/debug/dump/usermode/crashcontrol, then read the dump). The same source built by Visual Studio behaves identically; the difference is only who wrote the entry point. Observed on Xbox OS 26100.8866. -
EncodePointerlives in an apiset the app container does not have. xwin'skernel32.libimportsEncodePointer/DecodePointerfromapi-ms-win-core-util-l1-1-0.dll; on the Xbox that apiset is absent, the loader fails the launch, and the Device Portal reports0x80070002"file not found" without saying which file. No application code is involved: the static CRT reaches for the pair in its/O2initialisation paths, so the same project can launch as a debug build and die as a release one.--uwplinksinclude/appcontainer-pointers.defandinclude/appcontainer-ntdll.def(as import libraries, generated at build time) ahead ofkernel32.lib, rerouting a short list of names to DLLs that really export them and are present in every app-container process — see n°23 for how the list grew and how each name's destination was verified. -
/MDin the app container needs the store CRT, and Microsoft no longer ships its import libraries. MSBuild's UWP toolset satisfies the DLL runtimes withVCRUNTIME140_APP.dlland friends, delivered by theMicrosoft.VCLibsframework package; modern MSVC ships no import libraries for them, so xwin cannot carry any. Linked/MDagainst the desktop libraries instead, the executable importsVCRUNTIME140.dll, which does not resolve inside the container: the package installs, and activation fails as0x80270300(observed end-to-end on Xbox OS 26100.8866; the same application statically linked launches). Default here: map the DLL runtimes to their static counterparts wheneverAppContainerApplicationis true (/MT) — still the one place the evaluator deliberately changes what MSBuild would do rather than mirroring or refusing it. Opt-in store/MD: setUWP_STORE_CRT=1and runfetch-vclibs.shso the generated*_appimport libraries exist;build.sh --store-crtthen shuts outmsvcprt.lib/vcruntime.liband links the*_appset. See n°21 for what that path still cannot do. -
The Device Portal registers a package whose dependencies are missing. A store-CRT build needs the
Microsoft.VCLibs.140.00framework declared as a<PackageDependency>and installed on the device; the install step verifies neither, completes without complaint, and the loader then fails the launch as0x80070002, naming nothing — the same code as n°18, from the portal indistinguishable.build-project.shrefuses a store-CRT build whose manifest omits the dependency (printing the exact element to paste), andrun-on-device.shwarns after install when the device does not list a framework the manifest names. -
Store
/MDneeds the MD static STL surface, notlibcpmt.msvcp140_app.dlldoes not export__std_fs_*, some__std_find_*, orstd::_Facet_Register. Those live as object members insidemsvcprt.lib, already compiledRuntimeLibrary=MD_DynamicRelease(the import stubs for desktopMSVCP140.dllshare the same archive and must stay out of the container).libcpmt.libholds the same symbols as MT and linking it into/MDfails withFAILIFMISMATCH— never use it to close the gap.--store-crtrunsgen-msvcprt-app-static.shto extract the.objmembers intomsvcprt_app_static.liband links that after the*_appimport libs (VS parity for filesystem-heavy apps). Default without the opt-in remains/MTin the container (n°19). -
UWP
StaticLibraryprojects must compile as the app family too.--uwpon an executable alone is not enough: a referenced static lib (the 216-TU port's ggml library, for one) built withoutWINAPI_FAMILY=APPstill emitsRegOpenKeyExA/SetThreadAffinityMaskinto the archive, the linking app inherits them, and Xbox activation fails as0x8027025b. Visual Studio setsAppContainerApplication=trueon those libs and compiles them under the app family. Here:read-vcxprojexposesapp_container;build-project.shpasses--static-lib --uwpfor those projects;build.shapplies the family define at compile time and skips/appcontainer(link-only) for archives. Gate:scripts/pe-import-audit.shchecks the whole activation contract on the PE — banlist symbols, desktop CRT DLLs, subsystem ≥ 6.02, the AppContainer bit — andbuild-app.sh/build-project.shrun it after every link (with--allow-kernel32;UWP_SKIP_IMPORT_AUDIT=1opts out,UWP_AUDIT_FORBIDextends the banlist). -
The SDK routes more names through apisets the console does not have — and
KERNELBASE.dllcannot take them all. Beyond n°18's pair, a crossbuilt PE of a real project importedapi-ms-win-core-file-l1-2-2(AreFileApisANSI, reached by the MD static STL's filesystem objects),api-ms-win-core-processthreads-l1-1-1(IsProcessorFeaturePresent) andapi-ms-win-core-rtlsupport-l1-1-0(the unwinder'sRtlCaptureContext/RtlLookupFunctionEntry/RtlVirtualUnwind) — and refused activation, while the CI MSVC PE of the same app imports none of them. The first two names go toKERNELBASE.dll; theRtl*trio does not — the console's own KERNELBASE export table (read out of a crash dump's mapped module, the only authority:kernelbase.libunderstates the DLL) lacks the family, and a PE that asks KERNELBASE for it fails activation as0x8027015B. They go tontdll.dll, which exports all three, is loaded in every process and is not apiset-versioned — verified launching on the console. Hence two.deffiles, one per providing DLL. -
The Xbox package list hides frameworks, and a crash dump is the only debugger you get.
Microsoft.VCLibsnever appears in the Device Portal's package listing, even while Dev Home holds it open — do not read its absence as "not installed" (run-on-device.shno longer does), and do not read a standalone framework install's0x80073D02("in use by Dev Home") as failure: it means the framework is already there. When a package installs and refuses to start, enable per-package crash dumps (POST /api/debug/dump/usermode/crashcontrol?packageFullName=…— capital N,Content-Length: 0, CSRF cookie handshake; re-enable after every reinstall), launch, and fetch the.dmp.build.shwrites the linker map to<objdir>/link.mapat every link because that map is the only symbolication there is: the Xbox flight-build PDBs are not on any public symbol server.
scripts/check-deps.sh what is installed and what is not
scripts/fetch-sdk.sh SDK tools + metadata, via the official installer under Wine
scripts/wine-tool.sh midlrt / makepri / cppwinrt with the flags they need
scripts/fix-header-case.sh case aliases for a case-sensitive filesystem
scripts/gen-projection.sh .idl -> .winmd -> App.g.h + module.g.cpp + winrt/
scripts/gen-resources.sh a layout -> resources.pri
scripts/build.sh clang-cl + lld-link, with PCH and parallel compiles
scripts/fetch-vclibs.sh store CRT import libraries, out of Microsoft's VCLibs appx (n°19)
scripts/build-app.sh all of the above: a project directory -> a layout
scripts/read-vcxproj.py a Visual Studio project -> what it builds, as JSON
scripts/restore-nuget.sh packages.config -> packages/, from nuget.org
scripts/build-project.sh a .vcxproj -> a layout, references and DLLs included
scripts/run-on-device.sh a layout -> the console: packed, signed, installed, launched
scripts/pe-import-audit.sh activation-contract gate: imports, subsystem, AppContainer bit
scripts/gen-msvcprt-app-static.sh MD static STL helpers from msvcprt.lib (store /MD)
scripts/common.sh sourced by all of them: errors, downloads, layout rules
include/msvc-compat.h force-included: what clang needs that MSVC assumes
include/appcontainer-pointers.def apiset names rerouted to KERNELBASE (n°18, n°23)
include/appcontainer-ntdll.def the unwinder's Rtl* rerouted to ntdll (n°23)
Makefile install / uninstall / check
packaging/PKGBUILD Arch package
packaging/publish-aur.sh update and publish it, by hand or from CI
examples/hello-winrt/ C++/WinRT console program that exercises real APIs
examples/hello-uwp/ a UWP application in the shape that cross-compiles
tests/run-tests.sh everything checkable without downloading the SDK
docs/porting-a-vcxproj.md taking a real Visual Studio project through all of it
Every script takes --help and prints its own usage; installed, that is
uwp-build --help and so on.
The CHANGELOG's newest version and packaging/PKGBUILD's pkgver have to
agree — CI checks it — so both move in the same commit, before the tag:
# 1. CHANGELOG.md: close the section, date it
# 2. packaging/PKGBUILD: pkgver=0.1.1, then `makepkg --printsrcinfo > .SRCINFO`
git commit -am "Release 0.1.1"
git tag -a v0.1.1 -m "…" && git push origin main v0.1.1aur.yml then updates the AUR package by running packaging/publish-aur.sh,
which is also the manual path:
packaging/publish-aur.sh --version 0.1.1 --dry-run # build and check only
packaging/publish-aur.sh --version 0.1.1 # and push to the AURIt rewrites pkgver, downloads the release tarball to compute its checksum,
regenerates .SRCINFO and builds the package with its tests before pushing, so
a hand-edited checksum can never describe a different tarball. That is also why
sha256sums reads SKIP in this repository between releases: the tarball for
the next version does not exist yet, a checksum kept from the previous one would
describe the wrong file, and the script refuses to publish while it still says
SKIP. The published AUR package always carries a real one. Only a local run
copies the result back into packaging/; after a tag-triggered publication the
files here stay as committed.
Without the AUR_SSH_KEY secret the workflow does a dry run instead of failing —
a release should not go red because a downstream package is not set up yet.
The scripts are MIT (LICENSE). Nothing from Microsoft is
redistributed: fetch-sdk.sh and xwin fetch the SDK and CRT from Microsoft's
CDN at run time, under the Windows SDK licence, into a cache this repository
never touches. restore-nuget.sh fetches NuGet packages from nuget.org the same
way, under their own licences. fetch-vclibs.sh reads the VCLibs framework
appx — a file you point it at, or a download it refuses without an explicit
--accept-license — under Microsoft's terms, and its generated import
libraries stay in the same untouched cache. No .winmd, .pri, header, library or package
from any of those downloads belongs in a commit.
- More of MSBuild, as projects need it.
read-vcxproj.pyrefuses what it cannot evaluate rather than guessing, so a project that stops it names exactly what is missing: a compiler setting with no entry in the mapping table, a property only Visual Studio supplies, a target that generates sources. Each is a table row and a fixture, not an investigation. - A second device. Everything observed running has run on one Xbox Series S
and one OS build. Another console — or another device family entirely — is
what would turn two header-level verifications into real ones: the ARM64
image, and whether the loader accepts what
makepriwrites at runtime. - Watch the 216-translation-unit project live longer. It has been observed
running (2026-08-08), but only past an already-provisioned first boot: the
fire_and_forgetprovisioning path and long uptime are still unproven. A cold first boot and a long session are what would close them — or name the next gotcha.