Tuesday, 31 May 2011

Cross Compiling with Google Go

Since this is what I was doing 5 minutes ago, it seems like a reasonable first article for the reboot of the blog. A little side project I've been working on over the last couple of months has been an implementation of n-body physical simulation as part of the SICSA Multicore Challenge. The intention behind the challenge was to get as many different implementations of n-body simulation as possible, using a wide variety of languages, target architectures, and so on. I decided to give Google Go a spin, as I was interested in potentially using it as a research vehicle for my static analysis research. I will perhaps talk about my experiences of using Google Go and the n-body implementation in a later post - for the impatient, you may be able to glean some information from the presentation I gave at the workshop, or by looking at my horrible code.

When developing the implementation, I was using my trusty Macbook. However, I was intending to run the experiments on a linux based 8-core Xeon monster in the department, and was also interested in comparing performance of 32-bit and 64-bit binaries. I soon discovered that the standard Go compiler can do cross-compilation, though it wasn't obvious from the documentation how to do this, exactly. So, here's what to do. Firstly, build the compiler from source as you would normally:

> hg clone -u release https://go.googlecode.com/hg/ go
> cd go/src
> ./all.bash


This should go through without any errors. Though, if you're behind a proxy you may need to disable the network tests before running all.bash:

> export DISABLE_NET_TESTS=1

With a working build of Go, you should be able to happily develop away on your current machine. However, when you want to build a binary for a different operating system or architecture, you'll also need to build the tool chain (actually, the packages mostly) for the other platform. To do this, you'll need to set the environment variables GOOS and GOARCH to the appropriate values. See the Getting Started page for the list of options. With the environment variables set, you can run make.bash to build the appropriate packages for this alternate architecture.


> export GOOS=linux
> export GOARCH=386
> ./make.bash


I built versions for darwin, linux and freebsd in both 32-bit (386) and 64-bit (amd64) flavours.

Now, when it comes to building your program, if you followed the advice in "How to write Go code" you will probably just be running gomake. Now, before you do this simply set the GOOS and GOARCH values to the platform you wish to target. This will produce a statically linked binary for that os/arch combo, which you can then copy to your target machine to run. Simple!

To simplify things, I wrote a little script that would compile the binary for all the platforms I cared about. You can see this script here, though essentially all it does is

export GOOS=...
export GOARCH=...
gomake clean
gomake
mv -f binary binary_$GOOS_$GOARCH


This could be simplified for many os/arch combinations using a little function inside the script, but copy paste was just as fast for me :)

No comments:

Post a Comment