From 8f52e5861a12e4c04848a78359fd720298dcb417 Mon Sep 17 00:00:00 2001
From: Cheviiot <153805936+Cheviiot@users.noreply.github.com>
Date: Sat, 25 Jul 2026 01:38:47 +1000
Subject: [PATCH] Default download/install to ~/.msvc-go-wine when no dir is
given
--dest (download) and the positional dir (install) were previously
required, forcing every user to pick and remember a location. Both now
default to a single hidden ~/.msvc-go-wine, matching the convention most
CLI tools use for their own data dir - still overridable for anyone who
wants a different location.
---
README.md | 23 +++++++++++++----------
cmd/msvc-go-wine/download.go | 11 ++++++++---
cmd/msvc-go-wine/install.go | 18 +++++++++++++++---
cmd/msvc-go-wine/main.go | 7 +++++--
cmd/msvc-go-wine/paths.go | 17 +++++++++++++++++
5 files changed, 58 insertions(+), 18 deletions(-)
create mode 100644 cmd/msvc-go-wine/paths.go
diff --git a/README.md b/README.md
index 28ac894..05cbf5f 100644
--- a/README.md
+++ b/README.md
@@ -27,15 +27,16 @@ name it's invoked as (a "multi-call binary", like busybox):
## Quick start
```bash
-# 1. Download and unpack MSVC + Windows SDK (requires accepting Microsoft's
-# Visual Studio Build Tools license, and msitools for unpacking .msi payloads)
-msvc-go-wine download --accept-license --dest ~/my_msvc
+# 1. Download and unpack MSVC + Windows SDK into ~/.msvc-go-wine (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
# 2. Wire up the tool wrappers
-msvc-go-wine install ~/my_msvc
+msvc-go-wine install
# 3. Add the toolchain to PATH and build
-export PATH=~/my_msvc/bin/x64:$PATH
+export PATH=~/.msvc-go-wine/bin/x64:$PATH
cl /nologo /EHsc hello.cpp
```
@@ -55,12 +56,14 @@ pkcon install wine msitools
## Commands
```
-msvc-go-wine download --dest [options] fetch and unpack MSVC/WinSDK
-msvc-go-wine install 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
+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
```
+`--dest`/`[dir]` both default to `~/.msvc-go-wine` when omitted.
+
`download` supports `--msvc-version`, `--sdk-version`, `--architecture`,
`--host-arch`, `--with-*` component toggles, `--ignore`, `--only-download`,
`--only-unpack`, `--keep-unpack`, `--cache`, `--language`,
@@ -73,7 +76,7 @@ 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 ~/my_msvc/bin/x64)"
+eval "$(msvc-go-wine env --bin ~/.msvc-go-wine/bin/x64)"
clang-cl -c hello.c
lld-link hello.obj -out:hello.exe
```
diff --git a/cmd/msvc-go-wine/download.go b/cmd/msvc-go-wine/download.go
index 1597981..35ceb79 100644
--- a/cmd/msvc-go-wine/download.go
+++ b/cmd/msvc-go-wine/download.go
@@ -13,7 +13,7 @@ import (
func runDownload(args []string) int {
fs := flag.NewFlagSet("download", flag.ContinueOnError)
- dest := fs.String("dest", "", "directory to install into (required unless --only-download)")
+ dest := fs.String("dest", "", "directory to install into (default: ~/.msvc-go-wine)")
cacheDir := fs.String("cache", "", "directory to use as a persistent download cache (default: a temp dir, removed afterwards)")
major := fs.Int("major", 18, "the major VS version to download")
preview := fs.Bool("preview", false, "download the preview/insiders channel instead of release/stable")
@@ -122,8 +122,13 @@ func runDownload(args []string) int {
}
if !*onlyDownload && *dest == "" {
- fmt.Fprintln(os.Stderr, "msvc-go-wine download: --dest is required unless --only-download is set")
- return 1
+ def, err := defaultToolchainDir()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "msvc-go-wine download:", err)
+ return 1
+ }
+ *dest = def
+ fmt.Println("--dest not set, using default:", *dest)
}
if err := download.FetchPayloads(selected, cache, *onlyDownload); err != nil {
diff --git a/cmd/msvc-go-wine/install.go b/cmd/msvc-go-wine/install.go
index 6d864ba..5a19e71 100644
--- a/cmd/msvc-go-wine/install.go
+++ b/cmd/msvc-go-wine/install.go
@@ -8,11 +8,23 @@ import (
)
func runInstall(args []string) int {
- if len(args) != 1 || args[0] == "-h" || args[0] == "--help" {
- fmt.Fprintln(os.Stderr, "usage: msvc-go-wine install ")
+ if len(args) > 1 || (len(args) == 1 && (args[0] == "-h" || args[0] == "--help")) {
+ fmt.Fprintln(os.Stderr, "usage: msvc-go-wine install [dest] (default: ~/.msvc-go-wine)")
return 1
}
- dest := args[0]
+
+ var dest string
+ if len(args) == 1 {
+ dest = args[0]
+ } else {
+ def, err := defaultToolchainDir()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "msvc-go-wine install:", err)
+ return 1
+ }
+ dest = def
+ fmt.Println("No directory given, using default:", dest)
+ }
self, err := os.Executable()
if err != nil {
diff --git a/cmd/msvc-go-wine/main.go b/cmd/msvc-go-wine/main.go
index abbc8d5..ffbb4a2 100644
--- a/cmd/msvc-go-wine/main.go
+++ b/cmd/msvc-go-wine/main.go
@@ -63,11 +63,14 @@ func printUsage() {
fmt.Fprint(os.Stderr, `msvc-go-wine - cross compile with MSVC on Linux via Wine
Usage:
- msvc-go-wine download --dest [options] fetch and unpack MSVC/WinSDK
- msvc-go-wine install wire up wrappers for a downloaded MSVC
+ 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 print INCLUDE/LIB for native clang-cl/lld-link use
msvc-go-wine version print the version
+--dest/[dir] default to ~/.msvc-go-wine if omitted.
+
Once installed, add /bin/ to PATH and invoke the tools directly:
cl, link, lib, ml, ml64, mc, midl, mt, rc, dumpbin, msbuild, nmake, armasm, armasm64, cmd, findstr
`)
diff --git a/cmd/msvc-go-wine/paths.go b/cmd/msvc-go-wine/paths.go
new file mode 100644
index 0000000..981dd73
--- /dev/null
+++ b/cmd/msvc-go-wine/paths.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "os"
+ "path/filepath"
+)
+
+// defaultToolchainDir is where `download`/`install` operate when the user
+// doesn't specify a directory: a hidden ~/.msvc-go-wine, so it doesn't
+// clutter a plain `ls ~`.
+func defaultToolchainDir() (string, error) {
+ home, err := os.UserHomeDir()
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(home, ".msvc-go-wine"), nil
+}