Rewrite README with real install paths, TOC, and current command surface

Adds the two installation options that now actually exist (Nivora
package, prebuilt GitHub Release binary) alongside building from
source, a table of contents, CI/release/license badges, and a
Language section for VINTNER_LANG. Moves the more implementation-
focused toolrelay.exe/compatibility-patches explanations into
collapsible sections so the top of the page stays focused on using
the tool rather than how it's built.
This commit is contained in:
Cheviiot
2026-07-25 04:16:33 +10:00
parent d11b534fa1
commit e0475101b2
+107 -52
View File
@@ -1,14 +1,32 @@
# vintner # vintner
Cross compile with MSVC on Linux, using Wine — a single-binary Go tool [![CI](https://github.com/Cheviiot/vintner/actions/workflows/ci.yml/badge.svg)](https://github.com/Cheviiot/vintner/actions/workflows/ci.yml)
inspired by [mstorsjo/msvc-wine](https://github.com/mstorsjo/msvc-wine)'s [![Release](https://img.shields.io/github/v/release/Cheviiot/vintner)](https://github.com/Cheviiot/vintner/releases/latest)
approach (download the real MSVC/WinSDK, wrap the compiler under Wine), [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
**vintner** cross compiles with the real MSVC toolchain on Linux, using Wine —
a single Go binary, inspired by [mstorsjo/msvc-wine](https://github.com/mstorsjo/msvc-wine)'s
approach (download the actual MSVC/WinSDK, wrap the compiler under Wine) and
implemented independently. implemented independently.
Once installed, you invoke the real Microsoft toolchain exactly like on Once installed, you invoke the real Microsoft toolchain exactly like on
Windows: `cl`, `link`, `lib`, `rc`, `midl`, `mc`, `mt`, `dumpbin`, `msbuild`, Windows: `cl`, `link`, `lib`, `rc`, `midl`, `mc`, `mt`, `dumpbin`, `msbuild`,
`nmake`, `ml`, `ml64`, `armasm`, `armasm64`, plus trivial `cmd`/`findstr` `nmake`, `ml`, `ml64`, `armasm`, `armasm64`, plus trivial `cmd`/`findstr`
shims, all just work from your `PATH`. shims, all work from your `PATH` — including full MSBuild projects and, with
`--with-wdk`, real KMDF/UMDF Windows drivers.
## Contents
- [How it works](#how-it-works)
- [Installation](#installation)
- [Quick start](#quick-start)
- [Commands](#commands)
- [Building drivers (WDK)](#building-drivers-wdk)
- [Language](#language)
- [Using clang-cl/lld-link instead of Wine](#using-clang-cllld-link-instead-of-wine)
- [Building from source](#building-from-source)
- [How the pieces fit together](#how-the-pieces-fit-together)
- [License](#license)
## How it works ## How it works
@@ -23,15 +41,50 @@ it's invoked as (a "multi-call binary", like busybox):
back from `z:\...` paths to plain unix paths so your build system's error back from `z:\...` paths to plain unix paths so your build system's error
parsing keeps working. parsing keeps working.
- Invoked as `vintner` → it exposes the `download`, `install`, `env` and - Invoked as `vintner` → it exposes the `download`, `install`, `env` and
`version` management subcommands described below (each also has a short `version` management subcommands described below (short aliases: `dl`,
alias: `dl`, `i`, `e`, `v`; `help`/`h` prints usage). `i`, `e`, `v`; `help`/`h` prints usage).
## Installation
**On ALT Linux, via [Nivora](https://github.com/Cheviiot/Nivora):**
```bash
stplr install nivora/vintner
```
**Prebuilt binary**, from the [latest release](https://github.com/Cheviiot/vintner/releases/latest):
```bash
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](#building-from-source).
Either way, `wine`/`wine64`, `msitools` (for `msiextract`) and `git` need to
be on `PATH` at run time (see [Prerequisites](#prerequisites) below); Nivora
installs already pull these in as package dependencies.
### Prerequisites
- `wine` (or `wine64`) — runs the real `cl.exe`/`link.exe`/etc.
- `msitools` (`msiextract`) — unpacks the `.msi` payloads MSVC/WinSDK ship as.
- `git` — used to apply the small compatibility patches bundled with
`download` (see [Compatibility patches](#compatibility-patches) below).
On ALT Linux:
```bash
pkcon install wine msitools git
```
## Quick start ## Quick start
```bash ```bash
# 1. Download and unpack MSVC + Windows SDK into ~/.vintner (requires # 1. Download and unpack MSVC + Windows SDK into ~/.vintner (requires
# accepting Microsoft's Visual Studio Build Tools license, and msitools # accepting Microsoft's Visual Studio Build Tools license). Pass
# for unpacking .msi payloads). Pass --dest <dir> for a different location. # --dest <dir> for a different location.
vintner download --accept-license vintner download --accept-license
# 2. Wire up the tool wrappers # 2. Wire up the tool wrappers
@@ -42,19 +95,6 @@ export PATH=~/.vintner/bin/x64:$PATH
cl /nologo /EHsc hello.cpp cl /nologo /EHsc hello.cpp
``` ```
### Prerequisites
- `wine` (or `wine64`) — runs the real `cl.exe`/`link.exe`/etc.
- `msitools` (`msiextract`) — unpacks the `.msi` payloads MSVC/WinSDK ship as.
- `git` — used to apply the small compatibility patches bundled with
`download` (see Compatibility patches below).
On ALT Linux:
```bash
pkcon install wine msitools
```
## Commands ## Commands
``` ```
@@ -68,40 +108,49 @@ vintner help (h) print usage
`--dest`/`[dir]` both default to `~/.vintner` when omitted. `--dest`/`[dir]` both default to `~/.vintner` when omitted.
`download`'s main options: `--msvc-version`, `--sdk-version`, `download`'s main options: `--msvc-version`, `--sdk-version`,
`--architecture`, `--host-arch`, `--only-host`, `--with-wdk` (also fetch the `--architecture` (repeatable: `x86`/`x64`/`arm`/`arm64`/`host`),
Windows Driver Kit, for building KMDF/UMDF drivers), `--ignore`, `--host-arch`, `--only-host`, `--with-wdk` (see below), `--ignore`
`--only-download`, `--only-unpack`, `--keep-unpack`, `--skip-patch`, (repeatable), `--only-download`, `--only-unpack`, `--keep-unpack`,
`--cache`, `--language`, `--include-optional`, `--skip-recommended`, `--skip-patch`, `--cache`, `--language`, `--include-optional`,
`--major`, `--preview`, `--manifest`, `--list-workloads`, `--skip-recommended`, `--major`, `--preview`, `--manifest`,
`--list-components`, `--print-deps-tree`. Run `vintner download -h` for the `--list-workloads`, `--list-components`, `--print-deps-tree`. Run
full list with descriptions. `vintner download -h` for the full list with descriptions.
`--list-workloads`/`--list-components` print every workload/component id `--list-workloads`/`--list-components` print every workload/component id
(with its human-readable title) available in the fetched manifest and exit (with its human-readable title) available in the fetched manifest and exit
without downloading anything - useful for discovering what to pass as a bare without downloading anything useful for discovering what to pass as a bare
package id or via `--with-*`. `--print-deps-tree` prints the dependency tree package id or via `--with-*`. `--print-deps-tree` prints the dependency tree
of whatever would actually be selected (honoring every other flag), also of whatever would actually be selected (honoring every other flag), also
without downloading. without downloading.
### Building drivers (WDK) ## Building drivers (WDK)
`vintner download --with-wdk` additionally fetches the Windows Driver Kit ```bash
(headers, import libs, and the MSBuild `WindowsKernelModeDriver10.0`/ vintner download --accept-license --with-wdk
`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 additionally fetches the Windows Driver Kit (headers, import libs, and the
end-to-end against a real sample driver from 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](https://github.com/microsoft/Windows-driver-samples). [microsoft/Windows-driver-samples](https://github.com/microsoft/Windows-driver-samples).
Only x64 and arm64 targets have a WDK package upstream (no x86/arm). Only x64 and arm64 targets have a WDK package upstream (no x86/arm).
### Language ## Language
CLI messages (usage text, progress lines, prompts) are in English by CLI messages (usage text, progress lines, prompts) default to English. Set
default. Set `VINTNER_LANG=ru` (or have a `ru`-prefixed `LC_ALL`/ `VINTNER_LANG=ru` (or have a `ru`-prefixed `LC_ALL`/`LC_MESSAGES`/`LANG`,
`LC_MESSAGES`/`LANG`, e.g. `ru_RU.UTF-8`) for Russian. Deeper error text e.g. `ru_RU.UTF-8`) for Russian:
bubbled up from internal packages stays in English.
### Using clang-cl/lld-link instead of Wine ```bash
VINTNER_LANG=ru vintner help
```
Deeper error text bubbled up from internal packages stays in English.
## Using clang-cl/lld-link instead of Wine
You don't need Wine at all if you drive the (nonredistributable) MSVC/WinSDK You don't need Wine at all if you drive the (nonredistributable) MSVC/WinSDK
headers and libraries with Clang/LLD in MSVC-compatible mode: headers and libraries with Clang/LLD in MSVC-compatible mode:
@@ -121,7 +170,15 @@ go build -o vintner ./cmd/vintner
Go 1.23+ is all you need to build it; `wine`/`msitools` are only needed at Go 1.23+ is all you need to build it; `wine`/`msitools` are only needed at
run time (`install`/tool invocation and `download` respectively). run time (`install`/tool invocation and `download` respectively).
## toolrelay.exe ```bash
go vet ./...
go test ./...
```
## How the pieces fit together
<details>
<summary><strong>toolrelay.exe</strong> — surviving Wine's exit-code truncation</summary>
`install` compiles `assets/vendor/toolrelay.cpp` (a small native Windows `install` compiles `assets/vendor/toolrelay.cpp` (a small native Windows
launcher, original to this project) with the freshly-installed host-arch launcher, original to this project) with the freshly-installed host-arch
@@ -135,26 +192,24 @@ observing the untranslated code via `GetExitCodeProcess()` can catch it
before Wine marshals the process exit back to Unix and drops everything but before Wine marshals the process exit back to Unix and drops everything but
the low byte. the low byte.
## Compatibility patches </details>
<details>
<summary><strong>Compatibility patches</strong> — making MSBuild work without a Windows Registry</summary>
`download` applies a handful of small patches (`assets/patches`) to the `download` applies a handful of small patches (`assets/patches`) to the
downloaded MSVC/WinSDK tree - independently written for this project - that downloaded MSVC/WinSDK tree independently written for this project that
make `VsDevCmd.bat` and MSBuild's SDK-detection props work without a make `VsDevCmd.bat` and MSBuild's SDK-detection props work without a
Windows Registry (which doesn't exist under Wine): they check the SDK Windows Registry (which doesn't exist under Wine): they check the SDK
directly under the VS install root instead of querying the registry, skip directly under the VS install root instead of querying the registry, skip
telemetry, and don't hard-fail devcmd setup when an optional component telemetry, and don't hard-fail devcmd setup when an optional component
(ConnectionManagerExe, bundled CMake/Ninja) wasn't downloaded. (ConnectionManagerExe, bundled CMake/Ninja) wasn't downloaded.
## Known gaps </details>
None currently tracked. Download/select/unpack/install, general MSBuild
projects, WDK driver builds, dependency-tree printing, and
workload/component listing are all implemented and verified against real
projects.
## License ## License
MIT, see [LICENSE.txt](LICENSE.txt) - covers vintner's own source only. The MIT, see [LICENSE.txt](LICENSE.txt) covers vintner's own source only. The
MSVC Build Tools / Windows SDK / WDK that `download` fetches remain governed MSVC Build Tools / Windows SDK / WDK that `download` fetches remain governed
by Microsoft's own license (accepted via `--accept-license`), same as with by Microsoft's own license (accepted via `--accept-license`), same as with
any other way of obtaining them. any other way of obtaining them.