Windows installer for a Go or Rust app (cross-compiled from any OS)
Cross-compile a Go or Rust program for Windows, embed an icon, hide the console for GUI apps, and wrap the single .exe (plus any assets) in a Setup.exe with shortcuts and an uninstaller.
Updated October 31, 2026 · 3 min read
Go and Rust both produce a single static .exe for Windows from a Mac or a Linux box, which is a big part of their appeal for desktop tools. Users still expect to install that .exe rather than keep it in Downloads. This guide covers the build flags that matter and how to turn the binary into a Setup.exe without touching Windows until it's time to test.
Go
Cross-compile with the target set in the environment:
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o MyApp.exe .
-s -wstrips symbol tables and debug info, shrinking the binary.- For a GUI app (Fyne, Wails, Walk, a webview), add
-H windowsguiinside-ldflagsso no console window opens:-ldflags "-s -w -H windowsgui". - Set
GOARCH=386for a 32-bit build,arm64for Windows on ARM.
Icon and version info. Go has no built-in way to embed a Windows icon. go-winres generates a .syso resource file from a small JSON description and your .ico; drop the .syso in the package and go build picks it up. Without it, the .exe shows the generic icon, though the installer's shortcuts will still use the icon you upload.
Rust
On Windows, the default target works:
cargo build --release
From macOS or Linux, target the GNU toolchain, which cross-compiles with MinGW installed:
rustup target add x86_64-pc-windows-gnu
cargo build --release --target x86_64-pc-windows-gnu
cargo-xwin is an alternative that cross-compiles for the MSVC target.
- For a GUI app, add
#![windows_subsystem = "windows"]at the top ofmain.rsto suppress the console window. - To embed an icon and version info, use the
winresorembed-resourcecrate frombuild.rswith an.rcfile referencingapp.ico. - Set
opt-level = "z",lto = trueandstrip = truein the release profile for a smaller binary.
What to upload
A single .exe: upload it directly to ExeTup; no zip needed. The installer gives it a Program Files (or per-user) home, shortcuts and an uninstaller.
An .exe plus assets (a config template, web assets for a webview app, a data/ folder): zip them together with the folder structure the program expects at run time, and upload the zip. Alternatively, upload the .exe and add the extras in the "Other files" step; both land next to the program.
Then enter the name, version, publisher, pick the scope and architecture, upload the .ico, and build. Test the result on Windows; see options for testing without a Windows PC.
Command-line tools
Installers are built for desktop apps, but a CLI benefits too: a known location, an uninstall entry, and silent deployment with /S for IT teams. Two caveats:
- The installer does not add the folder to
PATH. Tell users the install folder, or have the tool offer to add itself on first run. - Per-user installs land in
%LOCALAPPDATA%\Programs\MyApp, which users can reach without admin rights.
For developer-facing tools, winget or scoop manifests may suit your audience better than an installer; they can point at the same signed .exe.
Notes
- Antivirus heuristics. Fresh, unsigned, statically linked binaries from Go and Rust sometimes trip heuristic scanners. An installer that puts the program in Program Files helps a little; code signing helps a lot. See the SmartScreen guide.
- No runtime, no prerequisites. Both languages link their runtime in. The installer ships the binary as is.
- Updates. A new installer with a higher version replaces the files in place.
FAQ
Can I upload just the .exe?
Yes. A single .exe is accepted on its own, and the installer still provides shortcuts, an uninstaller and the entry in Windows Settings.
Do I need Windows to build the installer?
No. Build the binary on your OS, upload it, and ExeTup compiles the installer in the cloud. Windows is only needed to test the result.
Why does my Go GUI app open a black console window?
Build with -ldflags "-H windowsgui". In Rust, add #![windows_subsystem = "windows"] to main.rs.
How do I get my icon on the .exe itself?
Embed it as a Windows resource: go-winres for Go, the winres or embed-resource crate for Rust. Upload the same .ico in ExeTup for the installer and shortcuts.
Related guides
- Create a Windows installer on a Mac or LinuxYour options for building a Setup.exe when you develop on macOS or Linux, from cross-compiling NSIS to a browser-only build, and how to test the result without owning a Windows PC.
- Turn an .exe into a Windows installer (exe to Setup.exe)How to convert a plain .exe, or a folder with an .exe in it, into a real Windows installer with shortcuts and an uninstaller, without writing an installer script.
- Silent install for a Setup.exe: the /S switch, custom folders and deploymentHow to run an NSIS-based Setup.exe silently with /S, choose the folder with /D=, uninstall silently, and roll the installer out with Intune, PDQ or a script.