之前已经在x86的mac电脑上编译过substrate,按照官方指南上的操作就可以正常编译。但是在新款m1电脑上并没有编译通过,现在重新尝试在m1上编译substrate。
主要的准备过程参考如下文章
https://zhuanlan.zhihu.com/p/337224781
不过参考文章写于2020年12月16日,到现在(2021年3月10日)有部分状况已经发生了变化。针对和文章中不一样的状况稍作说明。
RUST
rust环境现在可以直接支持m1。所以使用rustup脚本可以直接安装rust,不需要额外设置。安装完成之后使用
rustup show
查看toolchain。则会发现是以aarch64开头的,原来的x86下面的tool-chain是
stable-x86_64-apple-darwin (default)
注意差别。
brew
mac上的包管理离不开brew,所以一定需要安装brew。brew现在也已经官方支持m1,不再需要像参考文章中的特殊设置,直接使用官方脚本安装即可。brew在mac下有两个目录,我们暂时只关心在m1下的原生文件目录。可以cd到一下目录查看
1 /opt/homebrew
确保文件存在,如果你使用的是zsh,则在.zshrc中设置如下,如果你使用bash则在~/.bash_profile添加如下
1 | export PATH="/opt/homebrew/bin/:$PATH" |
substrate 配套环境
安装好brew之后,你需要下面四个依赖
1 | brew install -s cmake |
依次安装即可。注意设置llvm的环境变量中。比如我使用zsh. 就在~/.zshrc中写入
1 | export PATH="/opt/homebrew/opt/llvm/bin:$PATH" |
以上安装注意看brew的提示。brew也会提示你设置以上环境变量。
每次写入环境变量记得source.
编译substrate
本文以官方教程为例
https://substrate.dev/docs/en/tutorials/create-your-first-substrate-chain/setup
我们使用2.0.1版本的substrate.截止目前(2020.3.10)substrate已经有3.0版本,但是本文以教程为准,使用2.01版本
在合适的目录克隆
1 | git clone -b v2.0.1 --depth 1 https://github.com/substrate-developer-hub/substrate-node-template |
进入到node-temple目录后,需要升级如下两个依赖库
1 | cargo update -p fs-swap |
substrate还需要依赖rustrocksdb
1 | $ cd ${anywhere} |
我和参考文章一样把rust-rocksdb放在了如下位置
/opt/homebrew/opt/
然后去修改~/.cargo目录下的config,注意默认情况下config文件是不存在的,首次设置之前你需要自己创建该文件。
然后在config文件中写入如下
1 | paths = ["/opt/homebrew/opt/rust-rocksdb/"] |
之所以修改是因为原本依赖中的三个问题。
- fs-swap原本的依赖在m1下无法编译,新版本解决了这个问题,所以需要使用cargo update升级
- ring同理
- rust-rocksdb也无法在m1下编译,所以感谢hdevalence,自己fork出来修改了问题。我们依赖这个fork出来的rocksdb
说明:在.cargp/config中使用这种path依赖并非最优选择,在项目本身中使用patch是更好的做法,稍后编译中会出现相应的警告提示这一点。关于如何使用patch请参考《cargo book》,本文不做讨论。此外提示,对于substrate这种以workspace组织起来的项目,patch信息写在根目录下面的Cargo.toml中。
接下来编译还会出现一个问题,报错的形式如下
1 | error[E0609]: no field `__rip` on type `__darwin_arm_thread_state64` |
关于这个错,我们可以参考
https://github.com/bytecodealliance/wasmtime/issues/2575
讨论中已经提到了这个问题的解决办法,所以我们直接把__ rip换成__ pc即可。提供一个最快捷的修改办法
直接进入到错误提示的源码处,直接修改依赖库的源码,把_ _ rip改成 _ _ pc。
注意:这么改是为了快捷,绝非良策。因为rust库的构建依赖cargo管理,我们直接去修改了库的源码,如果使用cargo update,或者其他触发了Cargo.lock变动的操作,依然可能编译不过。 好的办法还是fork下来使用patch依赖。
所有准备工作做完之后就可以
1 | cargo build --release |
大概七分钟左右就可以编译完成。比原本的x86 mac快很多。
本文的编译的环境汇总
- Rustc 使用1.50.0版本,可以使用rustup show查看
- Substrat-node-template 使用v2.0.1版本
- 硬件环境为 m1 mac
- 操作系统 macOS Big Sur 11.2.3
一些建议
经常看到讨论substrate编译不过问题的。经常面对这种问题可以做一个详细的文档来记录这些,文档中可以包含以下内容
- rust tool-chain的版本
- 可以编译操作系统信息 比如linux某版本 windows某版本,mac有m1版本和x86版本也需要额外说明
- 需要额外安装的依赖,比如这里提到的llvm protobuf
- 基于某个substrate版本开发的 比如本文基于v2.0.1
- 基于当前版本substrate需要做的某些调整,比如本文中提到的ring fs-swap升级 wasmtime的修改等。
- 如果版本升级了,需要配套更新以上这一套信息(这里的版本升级包含rust升级和substrate升级)
- 如果有必要可在项目下专门建立一个patch文件,来管理需要patch的包。
相信做到以上的7点,就不用反复的去解决编译不通过的问题。
本文完。