Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save acoutts/2cf5a90a8e8a62f351543f055d3df61f to your computer and use it in GitHub Desktop.
Save acoutts/2cf5a90a8e8a62f351543f055d3df61f to your computer and use it in GitHub Desktop.
Compile Go for Apple Silicon (M1)

Compile Go for Apple Silicon (M1)

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).

Brief introduction

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.

Initial preparations

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.

Bootstrapping the toolchain

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

Compiling the runtime

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment