What's the proper way to cross-compile Go snaps?

Go natively supports cross-compiling. However, when I run snapcraft snap --target-arch=arm64, the output can be ran on amd64, which means cross-compiling isn’t that easy in Snapcraft.

I found out that using --destructive-mode made the build be done on the host machine instead of inside a container. Here’s how I managed to cross-compile in Go.

#!/bin/sh

snapcraft clean --destructive-mode
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=386      snapcraft snap --target-arch=i386     --destructive-mode --output build/permaweb-host_i386.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=amd64    snapcraft snap --target-arch=amd64    --destructive-mode --output build/permaweb-host_amd64.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=arm      snapcraft snap --target-arch=arm      --destructive-mode --output build/permaweb-host_arm.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=arm64    snapcraft snap --target-arch=arm64    --destructive-mode --output build/permaweb-host_arm64.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=mips     snapcraft snap --target-arch=mips     --destructive-mode --output build/permaweb-host_mips.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=mips64   snapcraft snap --target-arch=mips64   --destructive-mode --output build/permaweb-host_mips64.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=mips64le snapcraft snap --target-arch=mips64le --destructive-mode --output build/permaweb-host_mips64le.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=mipsle   snapcraft snap --target-arch=mipsle   --destructive-mode --output build/permaweb-host_mipsle.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=ppc64    snapcraft snap --target-arch=ppc64    --destructive-mode --output build/permaweb-host_ppc64.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=ppc64le  snapcraft snap --target-arch=ppc64le  --destructive-mode --output build/permaweb-host_ppc64le.snap
snapcraft clean --destructive-mode permaweb-host; env GOOS=linux GOARCH=s390x    snapcraft snap --target-arch=s390x    --destructive-mode --output build/permaweb-host_s390x.snap

Buuut that’s plain ugly and it installs other-arch stuff from gcc on my machine.

Is there a better way to cross-compile Go apps that actually works?

You could push your code to github and then use the build service which will create snaps for 32-bit and 64-bit x86 and arm, and s390x and ppc. Visit build.snapcraft.io for more details.

Another option would be to exercise the beta “remote build” option in snapcraft. The details are at Preview: Snapcraft remote build

There are a few issues with cross-compiling with snapcraft 3.X and using bases. See my reply at Cross compile snap on amd64 to arm for a more thorough explanation, however it does seem that using --destructive-mode is a sufficient workaround for your use case.

For the time being, I’d recommend going with one of the options that @popey mentioned.