Alternate title: Cross compiling Windows/Darwin/Linux amd64/386/arm all from linux
After fumbling around trying to figure out the go toolchain and cross compilation configuration, I ran across the wiki page on Go's homepage. It's super helpful, and worked out of the box. I'm including the necessary scripts here in case they get changed or lost, and we can help Google find it (since it's the first real source I've found that "Just Worked"). http://code.google.com/p/go-wiki/wiki/WindowsCrossCompiling
I also went a step further, and built for windows/amd64 and linux/arm
Install go
hg clone -u release https://code.google.com/p/go
cd go/src
./all.bash
Grab the two helper scripts from: http://code.google.com/p/go-wiki/wiki/WindowsCrossCompiling
buildcmd
#!/bin/sh
set -e
for arch in 8 6; do
for cmd in a c g l; do
go tool dist install -v cmd/$arch$cmd
done
done
exit 0
buildpkg
#!/bin/sh
if [ -z "$1" ]; then
echo 'GOOS is not specified' 1>&2
exit 2
else
export GOOS=$1
if [ "$GOOS" = "windows" ]; then
export CGO_ENABLED=0
fi
fi
shift
if [ -n "$1" ]; then
export GOARCH=$1
fi
cd $GOROOT/src
go tool dist install -v pkg/runtime
go install -v -a std
Set yourself up for windows cross compile!
$ chmod +x ./buildcmd
$ chmod +x ./buildpkg
$ ./buildcmd
$ ./buildpkg windows 386
$ ./buildpkg windows amd64
$ ./buildpkg darwin amd64
Now, go build yourself a static windows go binary!
$ cat hello.go
package main
import "fmt"
func main() {
fmt.Printf("Hello\n")
}
$ GOOS=windows GOARCH=386 go build -o hello_i386.exe hello.go
$ GOOS=windows GOARCH=amd64 go build -o hello_amd64.exe hello.go
$ file hello_amd64.exe
geocode_amd64.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows
$ file hello_i386.exe
geocode_amd64.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows
$ wine ./hello_i386.exe 2>/dev/null
Hello
And just for kicks -- let's cross compile for darwin (OSX Native)
$ GOOS=darwin GOARCH=amd64 go build -o hello_osx_amd64 hello.go
$ GOOS=darwin GOARCH=386 go build -o hello_osx_386 hello.go
$ file hello_osx_386
server_osx_386: Mach-O executable i386
$ file hello_osx_amd64
server_osx_amd64: Mach-O 64-bit executable
Just be aware that there are some side effects in this method because CGO_ENABLED=0. With the latest versions of Go, however, I was able to run a small http server without issues, and another server that connects to postgres through a third party go library (although I didn't actually set up postgres on windows -- but the program ran and returned a standard database connection error message). Pretty slick!
Building for ARM is just as straight forward, except you have to re-run make.bash (because you have to switch your toolchain from x86 to ARM). If not, you'll do:
$ GOOS=linux GOARCH=arm go build -o geocode_arm geocode.go
go build runtime: linux/arm must be bootstrapped using make.bash
Back to the go build root -- get all set up for arm
$ cd $GOROOT/src
$ GOARCH=arm ./make.bash
Installed Go for linux/arm in /home/blaine/src/go
Installed commands in /home/blaine/src/go/bin
...
Now, we can try to compile again
``` bash
$ GOOS=linux GOARCH=arm go build -o hello_arm hello.go
$ file hello_arm
geocode_arm: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, not stripped
NICE!
Now that we've retooled the chain for ARM, we can't build for windows until we re-run the make.bash -- although interestingly, amd64 still works. Probably because both "arm" and "386" are technically "foreign" to my host x64 system, so perhaps the toolchain can only support a single foreign architecture at a time. This probably also explains why "go run file.go" still works fine -- amd64 is enabled by default, regardless of GOOS configuration.
$ GOOS=windows GOARCH=386 go build -o hello_i386.exe hello.go
go tool: no such tool "8g"
$ GOOS=windows GOARCH=amd64 go build -o hello_amd64.exe hello.go
$ file hello_amd64.exe
hello_amd64.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows
Re-tooling for 386
$ CD $GOROOT
$ GOARCH=386 ./make.bash
...
Installed Go for linux/386 in /home/blaine/src/go
Installed commands in /home/blaine/src/go/bin
And, just to test:
$ GOOS=windows GOARCH=386 go build -o hello_i386.exe geocode.go
$ file hello_i386.exe
hello_i386.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows