Ramblings of an aging IT geek
← Ramblings of an aging IT geek
golang

shipping a go binary to arm from a laptop that has never seen arm

Notes on cross-compiling a Go binary for an ARM device with GOARCH and GOARM, and the cgo trap that ends the easy path.

A laptop terminal building code for ARM

I keep coming back to how painless this is in Go, because every other language has made me suffer for it at some point. To build for an ARM board from an x86 laptop, you set two variables and run the build. That's the whole trick.

GOOS=linux GOARCH=arm GOARM=7 go build -o agent .

The GOARM value is the one to get right. ARMv6 for the older Pis and the Zero, ARMv7 for the Pi 2 and 3, and GOARCH=arm64 if the target is running a 64-bit kernel. Get it wrong and the binary refuses to start with an illegal instruction, which is a confusing error if you've forgotten you cross-compiled it.

The catch, always, is cgo. As long as you're pure Go this works from any machine to any target. The instant a dependency wants a C library, you're back to installing a cross-toolchain and setting CC to the right gcc, and the simplicity evaporates. So I treat "does this stay cgo-free" as a real design constraint for anything I want to ship to a small board. CGO_ENABLED=0 at the front of the build line is a cheap way to make the compiler shout at you the moment something sneaks a C dependency in, rather than finding out when the build mysteriously needs a toolchain you haven't got.