How to Cross-Compile Go Programs for Different Platforms
In this tutorial, you'll learn about How to Cross. We cover key concepts, practical examples, and best practices.
The Problem
You developed a Go application on your Linux machine and need to distribute it to users on Windows, macOS, and ARM devices. Without cross-compilation, you would need a separate build machine for each target platform.
Quick Fix
Step 1: Build for Linux (default)
go build -o myapp-linux ./cmd/myapp
This is the default when building on Linux. No environment variables are needed.
Step 2: Build for Windows
GOOS=windows GOARCH=amd64 go build -o myapp.exe ./cmd/myapp
Expected output: myapp.exe — a 64-bit Windows executable.
Step 3: Build for macOS
GOOS=darwin GOARCH=amd64 go build -o myapp-macos-intel ./cmd/myapp
GOOS=darwin GOARCH=arm64 go build -o myapp-macos-arm64 ./cmd/myapp
The first is for Intel Macs, the second for Apple Silicon (M1/M2).
Step 4: Build for ARM Linux (Raspberry Pi)
GOOS=linux GOARCH=arm GOARM=7 go build -o myapp-armv7l ./cmd/myapp
GOOS=linux GOARCH=arm64 go build -o myapp-arm64 ./cmd/myapp
GOARM=7 targets ARMv7 (Raspberry Pi 2/3). arm64 targets 64-bit ARM (Raspberry Pi 3/4 with 64-bit OS).
Step 5: Build for all platforms with a script
for os in linux darwin windows; do
for arch in amd64 arm64; do
output="myapp-${os}-${arch}"
if [ "$os" = "windows" ]; then
output="${output}.exe"
fi
GOOS=$os GOARCH=$arch go build -o "$output" ./cmd/myapp
done
done
This produces 6 binaries in a single command.
Step 6: Verify the binary target
file myapp-linux-amd64
Expected:
myapp-linux-amd64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
Step 7: List all supported targets
go tool dist list
Expected:
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/amd64
darwin/arm64
dragonfly/amd64
freebsd/386
...
Step 8: Disable CGO for static builds
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o myapp-static ./cmd/myapp
Disabling CGO produces a fully static binary with no external library dependencies. It runs on any Linux system regardless of libc version.
Step 9: Set build flags for smaller binaries
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o myapp-small ./cmd/myapp
The -s -w flags strip debug information, reducing the binary size by 30-50%.
Alternative Solutions
Use GoReleaser for automated multi-platform releases with GitHub integration:
# .goreleaser.yaml
builds:
- goos: [linux, darwin, windows]
goarch: [amd64, arm64]
Prevention
- Set
CGO_ENABLED=0for portable static binaries when C libraries are not required. - Test each cross-compiled binary in the target environment before distribution.
- Use GoReleaser or a Makefile target for repeatable cross-platform builds.
- Document the target platforms and build commands in your README.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro