Zig 多版本管理

由于 Zig 还在快速开发迭代中,因此项目很有可能出现新版本 Zig 无法编译的情况,这时候一方面可以跟踪上游进展,看看是否有 workaround,另一个就是使用固定的版本来开发这个项目,显然这种方式更靠谱一些,因此这篇文章就来介绍一些管理多个 Zig 版本的方式。

Zig version manager

现在 Zig 的版本管理工具主要有如下几个:

marler8997/zigup
Download and manage zig compilers
tristanisham/zvm
Lets you easily install/upgrade between different versions of Zig
hendriknielaender/zvm
Fast and simple zig version manager

他们工作方式类似,大致步骤:

  1. index.json 解析所有版本,然后根据当前系统架构确定要安装的二进制,
  2. 创建一个类似 current 软链用来表示当前的 Zig 安装目录,
  3. 根据项目下 .zig-version 文件中指定的版本,修改 current 软链的指向,保证 PATH 中的 Zig 版本是正确的

相关实现:

通用版本管理工具 asdf

鉴于社区之前的 asdf-zig 已经年久失修,zigcc 已经 fork 过来,对下载的软件包增加了 checksum 校验,防止出现中间人攻击,欢迎大家使用。

多版本管理是个常见的需求,比如 Python 中的 pyenv、Ruby 中的 rvm,甚至还有一个通用的框架:asdf,名字简单暴力,敲起来得心应手。安装方式可以参考官方文档的 Getting Started

它们的工作原理也都比较类似,通过修改 Shell 中的环境变量实现。在执行具体命令(比如:python、zig)时,会拦截到一个中转的工具(学名叫 shims,翻译为“垫片”),由它来确定要执行的版本(比如项目根目录的 .python-version ),然后将实际参数派发过去。

社区也有 Zig 的插件,安装也比较简单:

1
asdf plugin-add zig https://github.com/asdf-community/asdf-zig.git

常用命令

1
2
3
4
5
6
7
8
9
# 列举所有可安装的版本
asdf list-all zig

asdf install zig <version>
asdf uninstall zig <version>
# 设置全局默认版本,会写到 $HOME/.tool-versions 文件
asdf global zig <version>
# 设置当前目录使用的版本,会写到 $(pwd)/.tool-versions 文件
asdf local zig <version>

这里说明一点,可以使用 asdf install zig master 的方式来安装 master 分支的 Zig,但是由于 Zig 的 master 一直在变,因此本次安装的版本可以会滞后,一个简单的办法是先卸载,再重新安装。

如果想保留,可以手动把 master 目录改个名字,然后修改 zig 的 shims 让其识别到这个版本,之后就可以继续安装最新的 master 版本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ tree -L 1 ~/.asdf/installs/zig
installs/zig
├──0.11.0
├──0.12.0-dev.891+2254882eb
└──master

$ cat ~/.asdf/shims/zig
#!/usr/bin/env bash
# asdf-plugin: zig 0.11.0
# asdf-plugin: zig master
# asdf-plugin: zig 0.12.0-dev.891+2254882eb
exec /opt/homebrew/Cellar/asdf/0.13.1/libexec/bin/asdf exec "zig" "$@" # asdf_allow: ' asdf '

上面的 0.12.0-dev.891+2254882eb 即是从 master 重命名出来的版本。下面这个脚本可以自动把 master 的版本固定下来:

1
2
3
4
5
6
7
8
V=$(zig version)

mv ~/.asdf/installs/zig/master ~/.asdf/installs/zig/${V}

# 如果是 Linux,直接用 sed -i 就好了,不需要后面的引号,macOS 上需要
sed -i '' "1a\\
# asdf-plugin: zig ${V}
"  ~/.asdf/shims/zig

问题排查

asdf 现在不支持 verbose 选项,因此安装过程中如果卡在某个地方,没法排查。一般来说,主要是下载 tar 包慢了,毕竟这取决于网络环境,可以这么改一下 install 文件

1
2
3
4
   echo "∗ Downloading and installing Zig..."
-  curl --fail --silent --location --create-dirs --output "$source_path" "$download_url"
+  curl --fail --progress-bar --location --create-dirs --output "$source_path" "$download_url"
   tar -xf "$source_path" -C "$install_path" --strip-components=1

这样就可以看到进度了:

1
2
3
4
curl --fail --progress-bar --location --create-dirs --output \
     ~/.asdf/installs/zig/master/zig-macos-aarch64-master.tar.xz \
     https://ziglang.org/builds/zig-macos-aarch64-0.12.0-dev.1127+32bc07767.tar.xz
#####################################                                              27.8%