vintner completion bash|zsh prints a completion script meant to be sourced (source <(vintner completion bash)); completes subcommands (including short aliases), download's flags, and directory arguments for install/env --bin. Mentioned in the top-level usage text and documented in the README. The Nivora package doesn't auto-install these system-wide yet - it'd need Stapler's install-completion helper, whose calling convention isn't documented anywhere in this repo or Nivora's other packages, so guessing at it risked a broken package build for a nice-to-have. source <(vintner completion bash) works today regardless of install method (Nivora, prebuilt binary, or from source).
vintner
vintner cross compiles with the real MSVC toolchain on Linux, using Wine — a single Go binary, inspired by mstorsjo/msvc-wine's approach (download the actual MSVC/WinSDK, wrap the compiler under Wine) and implemented independently.
Once installed, you invoke the real Microsoft toolchain exactly like on
Windows: cl, link, lib, rc, midl, mc, mt, dumpbin, msbuild,
nmake, ml, ml64, armasm, armasm64, plus trivial cmd/findstr
shims, all work from your PATH — including full MSBuild projects and, with
--with-wdk, real KMDF/UMDF Windows drivers.
Contents
- How it works
- Installation
- Quick start
- Commands
- Building drivers (WDK)
- Language
- Shell completion
- Using clang-cl/lld-link instead of Wine
- Building from source
- How the pieces fit together
- License
How it works
vintner is one Go binary that behaves differently depending on the name
it's invoked as (a "multi-call binary", like busybox):
- Invoked as
cl,link,lib, ... → it loads a small per-architectureenv.json, builds theINCLUDE/LIB/WINEPATHenvironment Wine needs, rewrites absolute unix paths in the arguments into Wine'sz:\...form (working around a Wine/cl.exe include-path bug), runs the real.exeunderwine/wine64, and rewrites the tool's output back fromz:\...paths to plain unix paths so your build system's error parsing keeps working. - Invoked as
vintner→ it exposes thedownload,install,envandversionmanagement subcommands described below (short aliases:dl,i,e,v;help/hprints usage).
Installation
On ALT Linux, via Nivora:
stplr install nivora/vintner
Prebuilt binary, from the latest release:
curl -fLo vintner "https://github.com/Cheviiot/vintner/releases/latest/download/vintner-linux-$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')"
chmod +x vintner
sudo install vintner /usr/local/bin/vintner
From source — see Building from source.
Either way, wine/wine64, msitools (for msiextract) and git need to
be on PATH at run time (see Prerequisites below); Nivora
installs already pull these in as package dependencies.
Prerequisites
wine(orwine64) — runs the realcl.exe/link.exe/etc.msitools(msiextract) — unpacks the.msipayloads MSVC/WinSDK ship as.git— used to apply the small compatibility patches bundled withdownload(see Compatibility patches below).
On ALT Linux:
pkcon install wine msitools git
Quick start
# 1. Download and unpack MSVC + Windows SDK into ~/.vintner (requires
# accepting Microsoft's Visual Studio Build Tools license). Pass
# --dest <dir> for a different location.
vintner download --accept-license
# 2. Wire up the tool wrappers
vintner install
# 3. Add the toolchain to PATH and build
export PATH=~/.vintner/bin/x64:$PATH
cl /nologo /EHsc hello.cpp
Commands
vintner download (dl) --accept-license [--dest <dir>] [options] fetch and unpack MSVC/WinSDK/WDK
vintner install (i) [dir] wire up wrappers for a downloaded MSVC
vintner env (e) --bin <dir>/bin/<arch> print INCLUDE/LIB for native clang-cl/lld-link use
vintner version (v) print the version
vintner help (h) print usage
vintner completion bash|zsh print a shell completion script
--dest/[dir] both default to ~/.vintner when omitted.
download's main options: --msvc-version, --sdk-version,
--architecture (repeatable: x86/x64/arm/arm64/host),
--host-arch, --only-host, --with-wdk (see below), --ignore
(repeatable), --only-download, --only-unpack, --keep-unpack,
--skip-patch, --cache, --language, --include-optional,
--skip-recommended, --major, --preview, --manifest,
--list-workloads, --list-components, --print-deps-tree. Run
vintner download -h for the full list with descriptions.
--list-workloads/--list-components print every workload/component id
(with its human-readable title) available in the fetched manifest and exit
without downloading anything — useful for discovering what to pass as a bare
package id or via --with-*. --print-deps-tree prints the dependency tree
of whatever would actually be selected (honoring every other flag), also
without downloading.
Building drivers (WDK)
vintner download --accept-license --with-wdk
additionally fetches the Windows Driver Kit (headers, import libs, and the
MSBuild WindowsKernelModeDriver10.0/WindowsUserModeDriver10.0
PlatformToolsets) so msbuild can build real KMDF/UMDF drivers —
compiling, linking, INF stamping and the Inf2Cat signability check (with
SignMode=off) all work under Wine. Verified end-to-end against a real
sample driver from
microsoft/Windows-driver-samples.
Only x64 and arm64 targets have a WDK package upstream (no x86/arm).
Language
CLI messages (usage text, progress lines, prompts) default to English. Set
VINTNER_LANG=ru (or have a ru-prefixed LC_ALL/LC_MESSAGES/LANG,
e.g. ru_RU.UTF-8) for Russian:
VINTNER_LANG=ru vintner help
Deeper error text bubbled up from internal packages stays in English.
Shell completion
source <(vintner completion bash) # or add to ~/.bashrc
source <(vintner completion zsh) # or add to ~/.zshrc
Completes subcommands (including the short aliases), download's flags,
and directory arguments for install/env --bin.
Using clang-cl/lld-link instead of Wine
You don't need Wine at all if you drive the (nonredistributable) MSVC/WinSDK headers and libraries with Clang/LLD in MSVC-compatible mode:
eval "$(vintner env --bin ~/.vintner/bin/x64)"
clang-cl -c hello.c
lld-link hello.obj -out:hello.exe
Building from source
go build -o vintner ./cmd/vintner
Go 1.23+ is all you need to build it; wine/msitools are only needed at
run time (install/tool invocation and download respectively).
go vet ./...
go test ./...
How the pieces fit together
toolrelay.exe — surviving Wine's exit-code truncation
install compiles assets/vendor/toolrelay.cpp (a small native Windows
launcher, original to this project) with the freshly-installed host-arch
cl.exe (best-effort: if wine isn't present yet, or the compile fails,
install still succeeds and the wrapper runtime just falls back to invoking
tools directly through wine). When present, every non-MSBuild tool
invocation is routed through it via two named FIFOs. This is what lets
mt.exe's CMake-compatibility exit-code translation (0x41020001 → 0xbb)
survive Wine's own exit-code truncation: only a native Windows process
observing the untranslated code via GetExitCodeProcess() can catch it
before Wine marshals the process exit back to Unix and drops everything but
the low byte.
Compatibility patches — making MSBuild work without a Windows Registry
download applies a handful of small patches (assets/patches) to the
downloaded MSVC/WinSDK tree — independently written for this project — that
make VsDevCmd.bat and MSBuild's SDK-detection props work without a
Windows Registry (which doesn't exist under Wine): they check the SDK
directly under the VS install root instead of querying the registry, skip
telemetry, and don't hard-fail devcmd setup when an optional component
(ConnectionManagerExe, bundled CMake/Ninja) wasn't downloaded.
License
MIT, see LICENSE.txt — covers vintner's own source only. The
MSVC Build Tools / Windows SDK / WDK that download fetches remain governed
by Microsoft's own license (accepted via --accept-license), same as with
any other way of obtaining them.