I have a small home project that requires binaries that work on darwin/amd64, linux/amd64, linux/arm and linux/arm64 architectures. As they depend on SQLite dialect for GORM, they have to be compiled with CGO_ENABLED=1

So if in your code you use Gorm with these imports, the article might help:

_ "github.com/jinzhu/gorm/dialects/sqlite"  

To build the applications I have a small CI/CD environment setup that uses self hosted drone.io platform which uses docker underneath to build and deploy applications. Since the platform is hosted on my VPC which runs 64bit Ubuntu, I had to cross-compile the binaries for Raspberry PI 3 and Odroid C2 from that architecture.

The following recipes allow to compile an image based on golang:latest to be built on linux/amd64.

Add packages to golang:latest or your build

golang:latest at the moment of writing this article corresponds to 1.10.3-stretch and is based on Debian stretch. You can either make your own golang image or just add the packages later, for stretch these are:

  • gcc-arm-linux-gnueabihf - for arm6+ devices
  • gcc-aarch64-linux-gnu - for arm8/64 devices

So it's a matter of doing apt update && apt install <packages>

Building with custom CC and CGO_ENABLED=1

Building SQLite dialect for Gorm requires CGO_ENABLED=1 flag. If you cross-compile you also have to manually specify which cross compiler should be used.

You can build your applications in the following way:

ARM7 (Raspberry Pi 3)
GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=1 CC=arm-linux-gnueabihf-gcc go build -o binary-linux-arm7  
ARM8/64 (Odroid C2)
GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 go build -o binary-linux-arm64