Cross compile with CGO and GoReleaser

How to overcome errors using CGO and GoReleaser by using Docker

Rob De Feo
May 10 · 3 min read

I contribute to an open source project, Mailchain, developed in Golang. I want to easily create releases using CI/CD. Golang is a compiled language that allows for a simple way to compile your code, to execute on different operating systems. I found the fantastic tool, https://goreleaser.com/ which builds, releases, and publishes the binaries.

This is the command to build on a Mac.

Run goreleaser locally
  • A clean distribution directory is required this ensures it is removed.
  • By default a release is set to publish. This flag turns off this action.

When I ran this on my Mac, it fails when building the binary for linux.

• releasing using goreleaser 0.106.0...
• loading config file       file=.goreleaser.yml
... [TRUNCATED]
• BUILDING BINARIES
   • building                  binary=dist/darwin_amd64/mailchain
   • building                  binary=dist/linux_amd64/mailchain
   ⨯ release failed after 9.40s error=failed to build for linux_amd64: # os/user
/usr/local/Cellar/go/1.12.4/libexec/src/os/user/getgrouplist_unix.go:16:35: warning: passing 'gid_t *' (aka 'unsigned int *') to parameter of type 'int *' converts between pointers to integer types with different sign [-Wpointer-sign]
... [TRUNCATED] 
ld: warning: option -s is obsolete and being ignored
ld: warning: ignoring file 
... [TRUNCATED]
  "__cgoexp_07a0021afc18_secp256k1GoPanicError", referenced from:
      _secp256k1GoPanicError in 000023.o
  "__cgoexp_07a0021afc18_secp256k1GoPanicIllegal", referenced from:
      _secp256k1GoPanicIllegal in 000023.o
  "_crosscall2", referenced from:
      _secp256k1GoPanicIllegal in 000023.o
      _secp256k1GoPanicError in 000023.o
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Whats going on???

The problem is that one library has a dependency on C and requires CGO. I like having GoReleaser in my tool kit, a lot! I looked deeper into the issue. It’s a case of ensuring all the right libraries are installed for CGO to compile against different operating systems. Docker seems and excellent fit, there’s even a docker container for CGO.

Run goreleaser/goreleaser
  • Starts with a fresh docker container each time.
  • Creates a volume on the docker container with the contents on of the current directory.
  • Sets the working directory to the code that was created in the directory.

Note: remember to replace and with your repository details.

releasing using goreleaser 0.106.0...
loading config file       file=.goreleaser.
... [TRUNCATED]
building                  binary=dist/darwin_amd64/mailchain
⨯ release failed after 163.82s error=failed to build for darwin_amd64: go build github.com/ethereum/go-ethereum/crypto/secp256k1: build constraints exclude all Go files in /go/pkg/mod/github.com/ethereum/go-ethereum@v1.8.26/crypto/secp256k1
# github.com/ethereum/go-ethereum/rpc
/go/pkg/mod/github.com/ethereum/go-ethereum@v1.8.26/rpc/endpoints.go:96:19: undefined: ipcListen
/go/pkg/mod/github.com/ethereum/go-ethereum@v1.8.26/rpc/ipc.go:50:10: undefined: newIPCConnection

We are making progress…

But I get a different error this time that does not look related to CGO. It is though, is the location of the C dependency. Looks like I need is a docker container that has CGO libraries and is able to cross compile into Linux, OSX, and Windows. Enter goreleaser-xcgo, a docker container with all of the required binaries and the latest version of GoReleaser. Usage is similar to before.

Run with https://github.com/mailchain/goreleaser-xcgo

Success!!! :)

This time it creates all the binaries are built.

• releasing using goreleaser 0.106.0...
... [TRUNCATED]
• BUILDING BINARIES
  • building                  binary=dist/darwin_amd64/mailchain
  • building                  binary=dist/linux_amd64/mailchain
  • building                  binary=dist/windows_amd64/mailchain.exe
... [TRUNCATED]
• release succeeded after 330.99s

To see it working the configuration file is here, to see how its integrated with travis here is the configuration.

If you want to find out more about what we are building at Mailchain find us at https://github.com/mailchain/mailchain

Thanks