在M1 Mac上编译使用arm64原生go

2020.12.19更新:go官方已经发布1.16 beta版,现在可以直接从官网下载安装包即可:

https://golang.org/dl/#go1.16beta1

可以不用自行编译啦~


go会在2021年2月发布的1.16版中正式支持Apple Silicon – 即使用arm64架构M1新芯片的Mac操作系统。虽然1.16版还未发布,但目前已经进入feature freeze期,即只是会再修修bug,改进文档等,喜欢尝鲜的朋友,其实已经可以在m1 mac里面下载go最新的源码,然后编译原生arm64版的go出来。

以下操作我全部在m1 mac mini上完成;并假设go的工具链安装在 $HOME/goroots 路径下。

mac上需要确保安装有 rosetta 2。

安装go 1.15

自go 1.4开始,go的编译器已经实现了自举,即我们可以使用go本身来编译go,那么,为了在mac上使用arm64的go 1.16尝鲜版,我们首先需要amd64的go 1.15。

说是安装,但其实只需要下载就可以了:

mkdir $HOME/goroots
cd $HOME/goroots
wget https://dl.google.com/go/go1.15.6.darwin-amd64.tar.gz
tar xzf go1.15.6.darwin-amd64.tar.gz

获得go源码

直接clone go源码仓库:

cd $HOME/goroots
git clone https://go.googlesource.com/go gosource

克隆github上的go源码镜像(https://github.com/golang/go)也行。

clone出来之后目前master分支便是 1.16 的预发布分支。

预编译darwin/arm64

要编译go的话,需要先预编译 bootstrap 响应的工具链,这个工具链本身也是需要是arm64版,不然最后make出来的还会是x86。

cd $HOME/goroots/gosource/src
arch --x86_64 env GOROOT_BOOTSTRAP=$HOME/goroots/go GODEBUG=asyncpreemptoff=1 GOOS=darwin GOARCH=arm64 ./bootstrap.bash

注意上面的编译环境变量参数中有 GODEBUG=asyncpreemptoff=1 ,这是因为我们的go 1.15是amd64版,直接在m1 mac中运行时需要依赖 rosetta 2,而目前似乎rosetta 2对于go的协程异步抢占还有bug,因此需要关闭;否则编译时会死锁并出现错误:

rosetta error: ulock_wait failure: 105

完成这步后,我们便可在 $HOME/goroots/go-darwin-arm64-bootstrap 路径下获得编译完整go的arm64工具链

编译arm64原生go

cd $HOME/goroots/gosource/src
arch --arm64e env GOROOT_BOOTSTRAP=$HOME/goroots/go-darwin-arm64-bootstrap ./make.bash

这样我们便可在 $HOME/goroots/gosource/bin/go 获得arm64的go啦~export $HOME/goroots/gosource/bin 路径去PATH,便可以在系统中使用原生的go了 :)

性能参考

我的gorazor项目:sipin/gorazor 在windows i7700k CPU下跑go test大概需要2.52秒:

而在m1 mini下是使用上面编译的原生go版本是 0.57秒:

通过rosetta 2跑amd64的go 1.15则是:0.82 秒。

撒花~

来源:知乎 www.zhihu.com

作者:玩家翁伟

【知乎日报】千万用户的选择,做朋友圈里的新鲜事分享大牛。
点击下载