By all means cross-compiling a new language/stack is not going to be pretty, but it didn't turn out that bad.
A few weeks back, I was told that go code which uses cgo (that is utilising C api calls to shared libraries exporting C interface) cannot be cross-compiled. Well, if it's just calling out a C compiler it should totally be easy to cross compile, since so much of our platform is.
So there we go, first I've picked a moderately small project which only does a couple cgo calls, and check that it compiles correctly:
I didn't want to polute my system, so I quickly created a chroot with go, build-dependencies in armhf architectures and cross-compiler:
A few weeks back, I was told that go code which uses cgo (that is utilising C api calls to shared libraries exporting C interface) cannot be cross-compiled. Well, if it's just calling out a C compiler it should totally be easy to cross compile, since so much of our platform is.
So there we go, first I've picked a moderately small project which only does a couple cgo calls, and check that it compiles correctly:
$ sudo apt-get build-dep ubuntu-push-clientWell, when your gcc is all is easy.
$ go get launchpad.net/ubuntu-push/...
$ cd $GOPATH/src/launchpad.net/ubuntu-push/
$ go build ubuntu-push-client.go
I didn't want to polute my system, so I quickly created a chroot with go, build-dependencies in armhf architectures and cross-compiler:
# Get a chroot with build-dependencies installed, I am basing on top of a click-chrootAfter that the tricky bit was advising go to cross-compile:
# one should be able to use any chroot which is armhf multiarch enabled.
$ sudo click chroot -aarmhf -fubuntu-sdk-14.04 -s utopic create
$ sudo click chroot -aarmhf -fubuntu-sdk-14.04 -s utopic maint apt-get install golang-go golang-go-linux-arm golang-go-dbus-dev golang-go-xdg-dev golang-gocheck-dev golang-gosqlite-dev golang-uuid-dev libgcrypt11-dev:armhf libglib2.0-dev:armhf libwhoopsie-dev:armhf libubuntuoneauth-2.0-dev:armhf libdbus-1-dev:armhf libnih-dbus-dev:armhf libsqlite3-dev:armhf crossbuild-essential-armhf
$ click chroot -aarmhf -fubuntu-sdk-14.04 -s utopic run CGO_ENABLED=1 GOARCH=arm GOARM=7 PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig GOPATH=/usr/share/gocode/:~/go CC=arm-linux-gnueabihf-gcc go build -ldflags '-extld=arm-linux-gnueabihf-gcc' ubuntu-push-client.go
Ignoring the click chroot wrapper:
- CGO_ENABLED=1 - by default cgo is disabled when cross-compiling, but really shouldn't be as compiler names are standard $(GNU_TRIPPLET) prefixed tools
- GOARCH=arm - set the target arch
- GOARM=7 - set ABI level
- PKG_CONFIG_LIBDIR - the ugly beast to pass where pkg-config should search for .pc files. With autoconf one simply sets PKG_CONFIG environment variable pointing at a cross-pkg-config, $(GNU_TRIPPLET)-pkg-config but go tool doesn't support it. I've raised merge proposal to get that added https://codereview.appspot.com/104960043/
- Next I just set GOPATH to where my packages are and CC as to which compiler to use
- The last portion to the puzzle was to pash "-ldflags '-extld=$CC'" because the linker tool (5l) didn't use environmental variable CC and simply defaults to gcc. I'll raise a merge proposal for this.
Overall that's it. Given that all of above can be re-factored into standard variables (e.g. use $GNU_TRIPPLET prefix, and offer to override it), I see no reason why cross-compilation in go with cgo cannot eventually become a simple
GOARCH=arm go build
Comments
Post a Comment