MSVC/WinSDK/WDK/DXSDK payloads run into the hundreds of MB to several
GB, so a dropped connection or a retry after a transient error used to
mean throwing away everything already fetched and starting over from
byte 0. Track progress in a dest+".part" file and resume it via an
HTTP Range request, falling back to a full restart when the server
doesn't honor Range (200 instead of 206) or the local part is stale
(416).
Found via manual audit plus a staticcheck run:
- collectDependencyClosure iterated a package's dependencies map
directly, so which package "won" a same-key collision (and the
order things got downloaded/unpacked in) could vary between runs
of the exact same download command. Sort the dependency targets
first, matching what --print-deps-tree's tree-printer already did.
Verified two consecutive --print-deps-tree runs now produce
byte-identical output.
- HTTP retry loops (manifest fetch, payload download) retried
immediately with no backoff, which just hammers a server harder
during exactly the kind of transient failure retries exist for.
Added a capped exponential backoff (1s/2s/4s/8s/10s).
- --architecture/--host-arch accepted any string silently; a typo'd
value matched nothing during package selection and surfaced as a
confusing downstream failure far from the actual mistake. Now
rejected up front with a clear error.
- pumpLines' bufio.Scanner silently stops (dropping the rest of a
tool's output) if a single line ever exceeds its buffer - narrow but
real for pathological cases like heavily templated C++ diagnostics.
Now at least reports that truncation happened instead of losing
output with no trace.
- Removed select.go's unused off() helper (staticcheck U1000).
Re-verified end-to-end after these changes: a real KMDF driver build
and a plain cl/link build both still succeed.
A single-binary Go tool for cross compiling with the real MSVC toolchain
on Linux via Wine. Behaves as cl/link/lib/rc/midl/mt/dumpbin/msbuild/
nmake/ml/ml64/armasm/armasm64/cmd/findstr depending on the name it's
invoked as, plus download/install/env/version management subcommands.
- download: fetches the MSVC/WinSDK installer manifest, resolves package
selection and dependencies, downloads and verifies payloads, unpacks
VSIX/MSI packages, and applies a handful of compatibility patches so
VsDevCmd.bat and MSBuild's SDK detection work without a Windows
Registry (which doesn't exist under Wine).
- install: locates the installed toolchain/SDK versions, normalizes
header/library name casing, lays out per-architecture tool symlinks
with an env.json config each, and compiles a small native launcher
(toolrelay.exe) that lets mt.exe's CMake-compatibility exit code
survive Wine's own exit-code truncation.
- The wrapper runtime rewrites absolute unix paths in tool arguments into
Wine's z:\... form, runs the real .exe under wine, and rewrites the
tool's output back to plain unix paths.
Verified end-to-end against a real MSVC/WinSDK download: cl, link, mt and
the resulting hello.exe all work under Wine, including through the
toolrelay.exe relay path and with paths containing non-ASCII characters.
Offline unit tests cover the wrapper's path-rewrite/output-filter logic,
install-time header lowercasing, and download package-selection/
dependency-resolution.