Skip to content

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 -w strips symbol tables and debug info, shrinking the binary.
  • For a GUI app (Fyne, Wails, Walk, a webview), add -H windowsgui inside -ldflags so no console window opens: -ldflags "-s -w -H windowsgui".
  • Set GOARCH=386 for a 32-bit build, arm64 for 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 of main.rs to suppress the console window.
  • To embed an icon and version info, use the winres or embed-resource crate from build.rs with an .rc file referencing app.ico.
  • Set opt-level = "z", lto = true and strip = true in 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