diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e0b2955..40621a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,17 +48,17 @@ jobs: tag="${{ inputs.tag || github.ref_name }}" version="${tag#v}" go build -trimpath -ldflags="-s -w -X main.version=${version}" \ - -o "msvc-go-wine-linux-${{ matrix.goarch }}" ./cmd/msvc-go-wine + -o "vintner-linux-${{ matrix.goarch }}" ./cmd/vintner - name: Verify it runs if: matrix.goarch == 'amd64' - run: ./msvc-go-wine-linux-amd64 version + run: ./vintner-linux-amd64 version - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: msvc-go-wine-linux-${{ matrix.goarch }} - path: msvc-go-wine-linux-${{ matrix.goarch }} + name: vintner-linux-${{ matrix.goarch }} + path: vintner-linux-${{ matrix.goarch }} if-no-files-found: error retention-days: 14 @@ -71,11 +71,11 @@ jobs: - name: Download all architectures uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - pattern: msvc-go-wine-linux-* + pattern: vintner-linux-* merge-multiple: true - name: Checksums - run: sha256sum msvc-go-wine-linux-* > SHA256SUMS + run: sha256sum vintner-linux-* > SHA256SUMS - name: Create or update GitHub Release env: @@ -85,10 +85,10 @@ jobs: tag="${{ inputs.tag || github.ref_name }}" if ! gh release view "$tag" >/dev/null 2>&1; then gh release create "$tag" \ - --title "msvc-go-wine $tag" \ + --title "vintner $tag" \ --notes "Linux amd64/arm64 binaries built by CI from this tag. See README.md for install instructions." fi gh release upload "$tag" \ - msvc-go-wine-linux-* \ + vintner-linux-* \ SHA256SUMS \ --clobber diff --git a/.gitignore b/.gitignore index 18451b6..0dab7c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -/msvc-go-wine +/vintner *.test .claude/ diff --git a/LICENSE.txt b/LICENSE.txt index d8ad75f..334c752 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -20,6 +20,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -This license covers msvc-go-wine's own source code. It does not cover the -Microsoft Visual C++ Build Tools / Windows SDK that `msvc-go-wine download` +This license covers vintner's own source code. It does not cover the +Microsoft Visual C++ Build Tools / Windows SDK that `vintner download` fetches and unpacks, which remain governed by Microsoft's own license terms. diff --git a/README.md b/README.md index 3b24526..670ce7e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# msvc-go-wine +# vintner Cross compile with MSVC on Linux, using Wine — a single-binary Go tool inspired by [mstorsjo/msvc-wine](https://github.com/mstorsjo/msvc-wine)'s @@ -6,13 +6,14 @@ approach (download the real MSVC/WinSDK, wrap the compiler under Wine), implemented independently. Once installed, you invoke the real Microsoft toolchain exactly like on -Windows: `cl`, `link`, `lib`, `rc`, `midl`, `mt`, `dumpbin`, `msbuild`, -`nmake`, `ml`, `ml64`, `armasm`, `armasm64` all just work from your `PATH`. +Windows: `cl`, `link`, `lib`, `rc`, `midl`, `mc`, `mt`, `dumpbin`, `msbuild`, +`nmake`, `ml`, `ml64`, `armasm`, `armasm64`, plus trivial `cmd`/`findstr` +shims, all just work from your `PATH`. ## How it works -`msvc-go-wine` is one Go binary that behaves differently depending on the -name it's invoked as (a "multi-call binary", like busybox): +`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-architecture `env.json`, builds the `INCLUDE`/`LIB`/`WINEPATH` environment Wine needs, @@ -21,22 +22,23 @@ name it's invoked as (a "multi-call binary", like busybox): runs the real `.exe` under `wine`/`wine64`, and rewrites the tool's output back from `z:\...` paths to plain unix paths so your build system's error parsing keeps working. -- Invoked as `msvc-go-wine` → it exposes the `download`, `install`, `env` and - `version` management subcommands described below. +- Invoked as `vintner` → it exposes the `download`, `install`, `env` and + `version` management subcommands described below (each also has a short + alias: `dl`, `i`, `e`, `v`; `help`/`h` prints usage). ## Quick start ```bash -# 1. Download and unpack MSVC + Windows SDK into ~/.msvc-go-wine (requires +# 1. Download and unpack MSVC + Windows SDK into ~/.vintner (requires # accepting Microsoft's Visual Studio Build Tools license, and msitools # for unpacking .msi payloads). Pass --dest for a different location. -msvc-go-wine download --accept-license +vintner download --accept-license # 2. Wire up the tool wrappers -msvc-go-wine install +vintner install # 3. Add the toolchain to PATH and build -export PATH=~/.msvc-go-wine/bin/x64:$PATH +export PATH=~/.vintner/bin/x64:$PATH cl /nologo /EHsc hello.cpp ``` @@ -56,20 +58,23 @@ pkcon install wine msitools ## Commands ``` -msvc-go-wine download --accept-license [--dest ] [options] fetch and unpack MSVC/WinSDK -msvc-go-wine install [dir] wire up wrappers for a downloaded MSVC -msvc-go-wine env --bin /bin/ print INCLUDE/LIB for native clang-cl/lld-link use -msvc-go-wine version print the version +vintner download (dl) --accept-license [--dest ] [options] fetch and unpack MSVC/WinSDK/WDK +vintner install (i) [dir] wire up wrappers for a downloaded MSVC +vintner env (e) --bin /bin/ print INCLUDE/LIB for native clang-cl/lld-link use +vintner version (v) print the version +vintner help (h) print usage ``` -`--dest`/`[dir]` both default to `~/.msvc-go-wine` when omitted. +`--dest`/`[dir]` both default to `~/.vintner` when omitted. -`download` supports `--msvc-version`, `--sdk-version`, `--architecture`, -`--host-arch`, `--with-*` component toggles, `--ignore`, `--only-download`, -`--only-unpack`, `--keep-unpack`, `--cache`, `--language`, -`--include-optional`, `--skip-recommended`, `--major`, `--preview`, -`--manifest`, `--list-workloads`, `--list-components`, `--print-deps-tree`. -Run `msvc-go-wine download -h` for the full list. +`download`'s main options: `--msvc-version`, `--sdk-version`, +`--architecture`, `--host-arch`, `--only-host`, `--with-wdk` (also fetch the +Windows Driver Kit, for building KMDF/UMDF drivers), `--ignore`, +`--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 @@ -78,13 +83,31 @@ 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 --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](https://github.com/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) are in English by +default. Set `VINTNER_LANG=ru` (or have a `ru`-prefixed `LC_ALL`/ +`LC_MESSAGES`/`LANG`, e.g. `ru_RU.UTF-8`) for Russian. 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 headers and libraries with Clang/LLD in MSVC-compatible mode: ```bash -eval "$(msvc-go-wine env --bin ~/.msvc-go-wine/bin/x64)" +eval "$(vintner env --bin ~/.vintner/bin/x64)" clang-cl -c hello.c lld-link hello.obj -out:hello.exe ``` @@ -92,7 +115,7 @@ lld-link hello.obj -out:hello.exe ## Building from source ```bash -go build -o msvc-go-wine ./cmd/msvc-go-wine +go build -o vintner ./cmd/vintner ``` Go 1.23+ is all you need to build it; `wine`/`msitools` are only needed at @@ -124,14 +147,14 @@ telemetry, and don't hard-fail devcmd setup when an optional component ## Known gaps -- `download` doesn't yet support installing the Windows Driver Kit via - `--with-wdk-installers`; the core selection/download/unpack/install - pipeline, dependency tree printing, and workload/component listing are all - fully implemented. +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 -MIT, see [LICENSE.txt](LICENSE.txt) - covers msvc-go-wine's own source only. -The MSVC Build Tools / Windows SDK that `download` fetches remain governed +MIT, see [LICENSE.txt](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. diff --git a/assets/patches/Common7/Tools/VsDevCmd.bat.patch b/assets/patches/Common7/Tools/VsDevCmd.bat.patch index 8ac84a9..873d0e8 100644 --- a/assets/patches/Common7/Tools/VsDevCmd.bat.patch +++ b/assets/patches/Common7/Tools/VsDevCmd.bat.patch @@ -1,4 +1,4 @@ -msvc-go-wine: skip VsDevCmd's telemetry upload. +vintner: skip VsDevCmd's telemetry upload. There's no telemetry endpoint reachable (or wanted) under Wine. Rather than touching the conditional logic below, just set the opt-out switch the diff --git a/assets/patches/Common7/Tools/vsdevcmd/core/vsdevcmd_start.bat.patch b/assets/patches/Common7/Tools/vsdevcmd/core/vsdevcmd_start.bat.patch index 43d0e29..b699822 100644 --- a/assets/patches/Common7/Tools/vsdevcmd/core/vsdevcmd_start.bat.patch +++ b/assets/patches/Common7/Tools/vsdevcmd/core/vsdevcmd_start.bat.patch @@ -1,4 +1,4 @@ -msvc-go-wine: always record the starting directory. +vintner: always record the starting directory. vsdevcmd_start.bat only saved __VSCMD_CURRENT_DIR when the caller passed -startdir=none, which doesn't hold up under Wine's cmd.exe (see diff --git a/assets/patches/Common7/Tools/vsdevcmd/core/winsdk.bat.patch b/assets/patches/Common7/Tools/vsdevcmd/core/winsdk.bat.patch index 3fc976a..89843ca 100644 --- a/assets/patches/Common7/Tools/vsdevcmd/core/winsdk.bat.patch +++ b/assets/patches/Common7/Tools/vsdevcmd/core/winsdk.bat.patch @@ -1,4 +1,4 @@ -msvc-go-wine: find the Windows SDK/UCRT dirs on disk before trying the registry. +vintner: find the Windows SDK/UCRT dirs on disk before trying the registry. winsdk.bat locates the Windows 10/11 SDK and Universal CRT SDK by querying the Windows Registry, which doesn't have real SDK installation entries diff --git a/assets/patches/Common7/Tools/vsdevcmd/ext/ConnectionManagerExe.bat.patch b/assets/patches/Common7/Tools/vsdevcmd/ext/ConnectionManagerExe.bat.patch index 7eb7d49..2caff0f 100644 --- a/assets/patches/Common7/Tools/vsdevcmd/ext/ConnectionManagerExe.bat.patch +++ b/assets/patches/Common7/Tools/vsdevcmd/ext/ConnectionManagerExe.bat.patch @@ -1,4 +1,4 @@ -msvc-go-wine: don't hard-fail devcmd setup when ConnectionManagerExe is missing. +vintner: don't hard-fail devcmd setup when ConnectionManagerExe is missing. Not every MSVC/WinSDK download selection includes the Linux ConnectionManagerExe component; a missing optional component shouldn't diff --git a/assets/patches/Common7/Tools/vsdevcmd/ext/cmake.bat.patch b/assets/patches/Common7/Tools/vsdevcmd/ext/cmake.bat.patch index 11e53a3..1967ad7 100644 --- a/assets/patches/Common7/Tools/vsdevcmd/ext/cmake.bat.patch +++ b/assets/patches/Common7/Tools/vsdevcmd/ext/cmake.bat.patch @@ -1,4 +1,4 @@ -msvc-go-wine: don't hard-fail devcmd setup when the bundled CMake/Ninja is missing. +vintner: don't hard-fail devcmd setup when the bundled CMake/Ninja is missing. Same reasoning as the ConnectionManagerExe fix: a missing optional component shouldn't abort the whole Developer Command Prompt setup. diff --git a/assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/msvc-go-wine.props.remove b/assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/msvc-go-wine.props.remove new file mode 100644 index 0000000..e69de29 diff --git a/assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/msvc-go-wine.props b/assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/vintner.props similarity index 94% rename from assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/msvc-go-wine.props rename to assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/vintner.props index e01cfa7..05d3f0a 100644 --- a/assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/msvc-go-wine.props +++ b/assets/patches/MSBuild/Microsoft/VC/v180/ImportBefore/Default/vintner.props @@ -1,5 +1,5 @@