NOTICE: This guide is no longer relevant, as a lot has changed over time and Go supports Apple Silicon natively just fine now!
Follow these short instructions on how to compile Go for Apple Silicon (M1). From here on out, we may simply refer to it as the "ARM device".
This entire process should only take about 5-10 minutes, but please read through everything carefully, in order to avoid any potential issues along the way.
Note that at the time of writing this, Go was not yet officially available for Apple's ARM.
Additionally it should be noted that this guide expects you to only be working on the ARM device, and not to have Go installed (yet).
In order to compile the Go runtime, we will first need the Go toolchain. Since neither the Go runtime nor the toolchain exists for our target platform yet, we will have to compile both ourselves.
We will begin by using an x86 version of the Go runtime, which we will use to "bootstrap" (compile) our ARM toolchain.
Finally, we will finish it all off by compiling the Go runtime for ARM, using our previously compiled ARM toolchain.
We will need to prepare a working directory, which will contain all of our temporary files.
Start by running the following command:
export GO_TMP=$(mktemp -udt go-arm-bootstrap) && \
mkdir -p $GO_TMP && \
echo $GO_TMP
Verify that the output of the last command is similar to the following:
/var/folders/8x/8n5pkxt51f3c4qxgc1f00qyh0000gn/T/go-arm-bootstrap.iHw5D8RG
Next we will install the x86 version of the Go runtime, which will be used as our compiler for the custom toolchain (runs with Rosetta):
cd $GO_TMP && \
curl -Ls https://golang.org/dl/go1.15.5.darwin-amd64.tar.gz | tar -xjf -
Now we can move on to bootstrapping/compiling the toolchain, then finally compiling the Go runtime.
The following commands will download an Apple Silicon specific patch/commit of Go, then bootstrap the toolchain using the x86 Go runtime as the compiler, ultimately creating our custom ARM toolchain in a new directory:
git clone https://go.googlesource.com/go $GO_TMP/go-bootstrap && \
cd $GO_TMP/go-bootstrap && \
git fetch https://go.googlesource.com/go refs/changes/58/272258/1 && \
git checkout FETCH_HEAD && \
cd $GO_TMP/go-bootstrap/src && \
arch --x86_64 env GOROOT_BOOTSTRAP=$GO_TMP/go GODEBUG=asyncpreemptoff=1 GOOS=darwin GOARCH=arm64 ./bootstrap.bash
NOTE: We're running make.bash
instead of all.bash
, as at the time of writing this, the tests that are part of the building process partially fail.
Now that we have our custom ARM toolchain, we can compile our custom ARM runtime with similar commands (note that we're running the "installation" as root
):
export GO_RUNTIME=$GO_TMP/go-runtime && \
git clone https://go.googlesource.com/go $GO_RUNTIME && \
cd $GO_RUNTIME && \
git fetch https://go.googlesource.com/go refs/changes/58/272258/1 && \
git checkout FETCH_HEAD && \
cd $GO_RUNTIME/src && \
arch --arm64e env GOROOT_BOOTSTRAP=$GO_TMP/go-darwin-arm64-bootstrap ./make.bash && \
sudo --preserve-env=GO_RUNTIME zsh -c '\
mv $GO_RUNTIME /usr/local/opt/go && \
chown -R root:wheel /usr/local/opt/go'
At this point, all you need to do is add /usr/local/opt/go/bin
to your PATH
environment variable, eg. through your ~/.zshrc
configuration file. You may also need to set additional environment variables that are Go specific, such as GOROOT
or GOPATH
.
Here is an example of how you might set the path environment variables:
export GOPATH=$HOME/go
export PATH=$PATH:/usr/local/opt/go/bin:$GOPATH/bin
Works perfectly for me on a M1 MacBook Pro