Skip to content

How to Cross-Compile Go Programs for Different Platforms

DodaTech 2 min read

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=0 for 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