Introduction
In my post about building and running programs in Iron.Io, I needed to switched over to my Ubuntu VM to build linux versions of my test programs locally. I love the ability to have Ubuntu available to me for building and testing my code. However, if I can stay on the Mac side it is better.
I have wanted to learn how to cross compile my Go programs for the two platforms I use, darwin/amd64 and linux/amd64. This way I could create final builds of my programs and publish everything from my Mac OS. After a couple of hours I am finally able to do this.
If you don’t have the need to cross compile your code then I recommend you stick with the traditional distribution packages and installs for Go. If this is something you need, then it all starts with downloading the current release of the Go source code.
Installing Git
The Go source code is stored in a DVCS called Github and is located on github.com/golang/go. The first thing you need to do is install Git if you don’t already have it.
Go to the download page on the Git website: http://git-scm.com/downloads
Cloning Go Source Codehttp://golang.org/doc/install/sourceOpen up a Terminal session and go to your $HOME directory and clone the current release of the Go source code. This will create a folder named Go, make sure this does not already exist:
cd $HOME
git clone https://go.googlesource.com/go
If everything works correctly you should see the following output or something similar:
Cloning into 'go'...
remote: Sending approximately 57.30 MiB ...
remote: Counting objects: 6825, done
remote: Finding sources: 100% (1345/1345)
remote: Total 194730 (delta 160700), reused 194473 (delta 160700)
Receiving objects: 100% (194730/194730), 55.07 MiB | 2.92 MiB/s, done.
Resolving deltas: 100% (161032/161032), done.
Checking connectivity... done.
Once that is done you now have a folder called
go inside of the $HOME directory with the source code under
src. Now change your directory to the
go folder and checkout the latest version:
cd go
git checkout go1.4.1
If everything works correctly you should see the following output or something similar:
Note: checking out 'go1.4.1'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at 886b02d... [release-branch.go1.4] go1.4.1
Building Go For Each TargetNow you need to build the Go code for the targets you need. For now just build darwin/amd64 and linux/amd64.
First build the Go code for the darwin/amd64 target which is for the host machine:
cd src
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 ./make.bash --no-clean
If everything builds correctly you should see the build end like this:
---
Installed Go for darwin/amd64 in /Users/name/go
Installed commands in /Users/name/go/bin
If you get the following error on your Mac there is a fix:
crypto/x509 root_darwin.go:9:43: error: CoreFoundation/CoreFoundation.h: No such file or directory root_darwin.go:10:31: error: Security/Security.h: No such file or directory mime/multipart net/mail
This means you don't have the Command Line Tools for Xcode installed on your machine. To install the command line tools on 10.9 follow these instructions:
[http://www.computersnyou.com/2025/2013/06/install-command-line-tools-in-osx-10-9-mavericks-how-to/](/broken-link)
Click the Install button for the Command Line Tools. Once that is done try building the Go code again.
Once the build is successful, open the Go folder. You should see everything you need for building Go programs on the Mac 64 bit environment:
You have the go, godoc and gofmt tools and all the package related libraries and tools. Next you need to fix your PATH to point to the bin folder so you can start using the tools.
export PATH=$HOME/go/bin:$PATH
You may want to set that in .bashrc or .bash_profile file from inside the $HOME directory.
With the path set, check that Go is working. Check the version and the environment:
go version
go version go1.4.1 darwin/amd64
go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/Users/name/go"
GOTOOLDIR="/Users/name/go/pkg/tool/darwin_amd64"
CC="gcc"
GOGCCFLAGS="-g -O2 -fPIC -m64"
CGO_ENABLED="1"
If everything looks good, now build a version of Go that will let you build linux/amd64 binaries:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 ./make.bash --no-clean
You can't use CGO when cross compiling. Make sure CGO_ENABLED is set to 0
If everything builds correctly you should see the build end like this:
---
Installed Go for linux/amd64 in /Users/name/go
Installed commands in /Users/name/go/bin
If you look at the Go folder again you should see some new folders for linux/amd64:
Now it is time to test if you can build Go programs for both the Mac and Linux operating systems. Set up a quick GOPATH and Go program. In Terminal run the following commands:
cd $HOME
mkdir example
mkdir src
mkdir simple
export GOPATH=$HOME/example
cd example/src/simple
Create a file called main.go inside of the simple folder with this code:
package main
import (
"fmt"
)
func main() {
fmt.Printf("Hello Gophers\n")
}
First build the Mac version and make sure it is a Mac executable using the file command:
go build
file simple
simple: Mach-O 64-bit executable x86_64
The file command tells us what type of file our program is. It is certainly a Mac executable file.
Now build the code for linux/amd64:
export GOARCH="amd64"
export GOOS="linux"
go build
file simple
Simple: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
You need to change either one or both of the OS/ARCH environment variables to point to the target platform and architecture. Then you can build the code. After the build you can see the file command is reporting the program is a linux executable.
As a reference, here are the different platforms and architectures you can build for cross compilation:
$GOOS $GOARCH
darwin 386 -- 32 bit MacOSX
darwin amd64 -- 64 bit MacOSX
freebsd 386
freebsd amd64
linux 386 -- 32 bit Linux
linux amd64 -- 64 bit Linux
linux arm -- RISC Linux
netbsd 386
netbsd amd64
openbsd 386
openbsd amd64
plan9 386
windows 386 -- 32 bit Windows
windows amd64 -- 64 bit Windows
Installing Go ToolingOnce you finish building Go for the targets you want, you will want to install these Go tools for the default target.
go get golang.org/x/tools/cmd/godoc
go get golang.org/x/tools/cmd/vet
go get golang.org/x/tools/cmd/goimports
go get golang.org/x/tools/cmd/gorename
go get golang.org/x/tools/cmd/oracle
go get golang.org/x/tools/cmd/gotype
go get github.com/golang/lint/golint
Release UpdatesIf you are performing an update be sure to remove the pkg folder from your GOPATH. These archive files will no longer be valid.
Then you will want to update the source code to the current release:
**NOTE: Read This First: http://golang.org/s/go14nopkg
cd $HOME/go/src
git fetch
git checkout go<tag>
Then you will want to build your targets again:
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 ./make.bash --no-clean
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 ./make.bash --no-clean
Finally re-build the tools. Before doing so, remove it is a good idea to remove the pkg folder from your GOPATH.
go get -u golang.org/x/tools/cmd/godoc
go get -u golang.org/x/tools/cmd/vet
go get -u golang.org/x/tools/cmd/goimports
go get -u golang.org/x/tools/cmd/gorename
go get -u golang.org/x/tools/cmd/oracle
go get -u golang.org/x/tools/cmd/gotype
go get -u github.com/golang/lint/golint
You may want to remove everything from the bin folder as well and
go get them to re-build and install.
ConclusionThis is the documentation for building Go from the source:
http://golang.org/doc/install/sourceThis is a document written by Dave Cheney about cross compilation. He has build a script that you can download. It makes all of this real simple to perform:
http://dave.cheney.net/2013/07/09/an-introduction-to-cross-compilation-with-go-1-1Mitchell Hashimoto built this great tool called
gox. This tool makes it real easy to build your program for all the different targets without the need to manually change the GOARCH and GOOS environment variables.