mirror of
https://github.com/Cheviiot/Vintner.git
synced 2026-08-03 15:57:24 +00:00
Initial implementation of msvc-go-wine
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.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package install
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestBuildToolRelay exercises the file shuffling around the actual
|
||||
// compiler invocation (write embedded source, run "cl", move the resulting
|
||||
// .exe into bin/, clean up the .obj and temp source) using a fake `cl`
|
||||
// shell script standing in for the real Wine-hosted compiler - this can
|
||||
// run fully offline, without wine or a real MSVC install.
|
||||
func TestBuildToolRelay(t *testing.T) {
|
||||
dest := t.TempDir()
|
||||
destBin := filepath.Join(dest, "bin")
|
||||
hostDir := filepath.Join(destBin, "x64")
|
||||
if err := os.MkdirAll(hostDir, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Fake `cl`: just drop toolrelay.exe/.obj next to the source it was
|
||||
// given, like the real cl.exe would when invoked without /Fe or /Fo.
|
||||
fakeCl := filepath.Join(hostDir, "cl")
|
||||
script := "#!/bin/sh\ntouch toolrelay.exe toolrelay.obj\n"
|
||||
if err := os.WriteFile(fakeCl, []byte(script), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := buildToolRelay(dest, destBin, "x64"); err != nil {
|
||||
t.Fatalf("buildToolRelay: %v", err)
|
||||
}
|
||||
|
||||
if !isFile(filepath.Join(destBin, "toolrelay.exe")) {
|
||||
t.Errorf("expected %s/toolrelay.exe to exist", destBin)
|
||||
}
|
||||
if exists(filepath.Join(dest, "toolrelay.obj")) {
|
||||
t.Errorf("toolrelay.obj should have been removed from %s", dest)
|
||||
}
|
||||
if exists(filepath.Join(dest, "toolrelay.cpp")) {
|
||||
t.Errorf("temp toolrelay.cpp source should have been removed from %s", dest)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildToolRelayNoClWrapper(t *testing.T) {
|
||||
dest := t.TempDir()
|
||||
destBin := filepath.Join(dest, "bin")
|
||||
if err := os.MkdirAll(destBin, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := buildToolRelay(dest, destBin, "x64"); err == nil {
|
||||
t.Fatal("expected an error when no host-arch cl wrapper exists")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user