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,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Cheviiot/msvc-go-wine/internal/wineenv"
|
||||
)
|
||||
|
||||
// runEnv prints shell `export` statements for INCLUDE/LIB (converted from
|
||||
// wine's "z:\..." notation to plain unix paths) and TARGET_TRIPLE, for
|
||||
// driving clang-cl/lld-link directly without Wine.
|
||||
// Usage: eval "$(msvc-go-wine env --bin <dest>/bin/<arch>)"
|
||||
func runEnv(args []string) int {
|
||||
fs := flag.NewFlagSet("env", flag.ContinueOnError)
|
||||
bin := fs.String("bin", "", "the <dest>/bin/<arch> directory produced by `msvc-go-wine install`")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return 2
|
||||
}
|
||||
if *bin == "" {
|
||||
fmt.Fprintln(os.Stderr, "usage: msvc-go-wine env --bin <dest>/bin/<arch>")
|
||||
return 1
|
||||
}
|
||||
|
||||
cfg, err := wineenv.Load(*bin)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "msvc-go-wine env:", err)
|
||||
return 1
|
||||
}
|
||||
baseUnix, err := wineenv.FindBaseUnix(*bin)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "msvc-go-wine env:", err)
|
||||
return 1
|
||||
}
|
||||
paths := wineenv.NewPaths(cfg, baseUnix)
|
||||
|
||||
triple, ok := targetTriples[cfg.Arch]
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "msvc-go-wine env: unknown arch %q\n", cfg.Arch)
|
||||
return 1
|
||||
}
|
||||
|
||||
fmt.Printf("export INCLUDE=%q\n", toUnixPathList(paths.Include))
|
||||
fmt.Printf("export LIB=%q\n", toUnixPathList(paths.Lib))
|
||||
fmt.Printf("export TARGET_TRIPLE=%q\n", triple)
|
||||
return 0
|
||||
}
|
||||
|
||||
var targetTriples = map[string]string{
|
||||
"x86": "i686-windows-msvc",
|
||||
"x64": "x86_64-windows-msvc",
|
||||
"arm": "armv7-windows-msvc",
|
||||
"arm64": "aarch64-windows-msvc",
|
||||
}
|
||||
|
||||
// toUnixPathList does a blanket removal of the "z:" drive prefix and
|
||||
// backslash->slash conversion across the whole semicolon-joined path list.
|
||||
func toUnixPathList(s string) string {
|
||||
s = strings.ReplaceAll(s, "z:", "")
|
||||
s = strings.ReplaceAll(s, `\`, "/")
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user