---
outline: deep
comments: false
showVersion: false
---

# `0.12.0`

2024/4/20，`0.12.0` 终于发布了，历时 8 个月，有 268 位贡献者，一共进行了 3688 次提交！

> 过去的发行说明都异常的长，因为试图记录所有在开发周期中所有的变化，本次更新则进行了适当地删减，便于读者和维护者阅读！

::: info

注意： 存在一部分变动并未在本次的发行说明中提及，其中包括 API 的 `Break Change`。

:::

::: warning

有关于各平台和架构的支持情况，本次更新并未进行更改，故在此处不再提及！

:::

## API 变更

可以参考：[0.12.0 升级指南](/update/upgrade-0.12.0)

## Autodoc 重构

目前我们已经可以使用全新的 `Autodoc`，新的实现带来了更棒的文档阅读体验！

### 旧的实现

文件结构为：

```sh
   5987 src/Autodoc.zig
   435 src/autodoc/render_source.zig
 10270 lib/docs/commonmark.js
  1245 lib/docs/index.html
  5242 lib/docs/main.js
  2146 lib/docs/ziglexer.js
 25325 total
```

编译产物结构（演示使用的标准库文档）为：

```sh
272K commonmark.js
3.8M data-astNodes.js
360K data-calls.js
767K data-comptimeExprs.js
2.2M data-decls.js
896K data-exprs.js
 13K data-files.js
  45 data-guideSections.js
 129 data-modules.js
  15 data-rootMod.js
 294 data-typeKinds.js
3.2M data-types.js
 38K index.html
158K main.js
 36M src/ (470 .zig.html files)
 78K ziglexer.js
```

总输出大小为 **47M**，经过gzip处理后为 **5.7M**！

- `src/Autodoc.zig` 用于处理 ZIR 代码（zig 编译时产生的中间代码），输出 json 以便 js 使用，这就导致很多代码无法通过某些数据（这些数据很可能是无效的），重建 AST 语法树

- `lib/docs/commonmark.js` 是一个第三方的 markdown 实现，但它的特性有点太多了，例如，我们并不希望在文档注释中使用HTML标签，因为这样会让源代码的注释无比丑陋，应当只渲染源代码和 markdown。

- `lib/docs/ziglexer.js` 是 js 中针对 zig 的语义标记实现。事实上，zig 已经在标准库中公开了由 zig 实现的语义标记。有趣的是，**andrewrk** 看到这个东西被添加进来的时候应该两眼一黑，具体可以见 [Issue 16306](https://github.com/ziglang/zig/pull/16306) [Issue 16490](https://github.com/ziglang/zig/issues/16490) 。

- `src/autodoc/render_source.zig` 是一种将 `.zig` 文件转换为带有语法高亮但不是交互式的 `.zig.html` 文件。

### 新的实现

文件结构为：

```sh
   942 lib/docs/main.js
   403 lib/docs/index.html
   933 lib/docs/wasm/markdown.zig
   226 lib/docs/wasm/Decl.zig
  1500 lib/docs/wasm/markdown/Parser.zig
   254 lib/docs/wasm/markdown/renderer.zig
   192 lib/docs/wasm/markdown/Document.zig
   941 lib/docs/wasm/main.zig
  1038 lib/docs/wasm/Walk.zig
  6630 total
```

编译产物结构（演示使用的标准库文档）为：

```sh
 12K index.html
 32K main.js
192K main.wasm
 12M sources.tar
```

总输出大小为: **12M**，经过gzip处理后为 **2.3M**！

可以看到，新的实现的代码和产物都很简洁，产物刚刚好只有 4 个文件，并且文件大小直接缩减到了 **1/4** 。

新的实现不仅仅是表面看上去更简单，实际上它较之旧实现更加的强大，因为新的实现并不会处理 ZIR，而是直接读取解析源代码文件（`sources.tar` 就是打包的源代码），这意味着它拥有完整的源代码信息，不需要进行一些乱七八糟的推断。

此方案是使用 zig 编写的 WebAssembly 模块，这允许其重用编译器中的组件，例如分词器，解析器和其他用于对 zig 代码进行操作的一些程序。

通过 HTTP 请求`sources.tar` 文件并解压后，会将其直接送入 Wasm 模块的内存中，针对 tar 文件使用 `std.tar` 进行解析，源代码就地进行解析，并额外进行一些计算添加 hash 表。

针对目前的实现，优化空间可以使用多线程来加速解析，但目前来看单线程已经足够快了，似乎没有必要。

### 携带标准库文档

在 zig 的 `0.11.0` 中，zig 发行时会带有一个 `docs/std/` 目录，其中包含着旧autodoc 实现构建产物（足足 47M 大小）。

在本次重写中，直接删除这些构建产物，作为代替，提供了 `zig std` 命令，这允许使用自带的 autodoc 生成器来打开一个浏览器窗口查看文档说明，首次使用此命令时，会先执行一次针对 `lib/compiler/std-docs.zig` 的编译操作。

HTTP 服务器会动态创建请求的文件，包括 main.wasm 重建（如果任何源文件发生更改）和构造 sources.tar ，这意味着在查看文档时，对文档文件或 autodoc 系统本身的任何源更改都会立即反映出来。在 URL 前面加上 /debug URL 会使用 WebAssembly 模块的调试版本。

这意味着贡献者可以通过在浏览器窗口中按刷新来测试对 Zig 标准库文档以及 autodocs 功能的更改，只需要 Zig 的二进制发行版。

总之，这使的zig的安装大小从 317M 减少到了 268M （-15%）。

编译器的 ReleaseSmall 版本从 10M 缩小到 9.8M （-1%）。

### 构建文档时间

Autodocs 生成现在作为编译器 pipeline 的一部分完成，而不是在最后添加。它也不再依赖于 pipeline 的其他部分。

以下是构建标准库文档所需要的时间：

```sh
Benchmark 1 (3 runs): old/zig test /home/andy/dev/zig/lib/std/std.zig -fno-emit-bin -femit-docs=docs
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          13.3s  ±  405ms    12.8s  … 13.6s           0 ( 0%)        0%
  peak_rss           1.08GB ±  463KB    1.08GB … 1.08GB          0 ( 0%)        0%
  cpu_cycles         54.8G  ±  878M     54.3G  … 55.8G           0 ( 0%)        0%
  instructions        106G  ±  313K      106G  …  106G           0 ( 0%)        0%
  cache_references   2.11G  ± 35.4M     2.07G  … 2.14G           0 ( 0%)        0%
  cache_misses       41.3M  ±  455K     40.8M  … 41.7M           0 ( 0%)        0%
  branch_misses       116M  ± 67.8K      116M  …  116M           0 ( 0%)        0%
Benchmark 2 (197 runs): new/zig build-obj -fno-emit-bin -femit-docs=docs ../lib/std/std.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          24.6ms ± 1.03ms    22.8ms … 28.3ms          4 ( 2%)        ⚡- 99.8% ±  0.3%
  peak_rss           87.3MB ± 60.6KB    87.2MB … 87.4MB          0 ( 0%)        ⚡- 91.9% ±  0.0%
  cpu_cycles         38.4M  ±  903K     37.4M  … 46.1M          13 ( 7%)        ⚡- 99.9% ±  0.2%
  instructions       39.7M  ± 12.4K     39.7M  … 39.8M           0 ( 0%)        ⚡-100.0% ±  0.0%
  cache_references   2.65M  ± 89.1K     2.54M  … 3.43M           3 ( 2%)        ⚡- 99.9% ±  0.2%
  cache_misses        197K  ± 5.71K      186K  …  209K           0 ( 0%)        ⚡- 99.5% ±  0.1%
  branch_misses       184K  ± 1.97K      178K  …  190K           6 ( 3%)        ⚡- 99.8% ±  0.0%
```

过去需要 13 秒以上，而现在只需要 25 毫秒。

### Autodoc 新特性

- 更加可靠的链接：由于拥有完整的源代码，故我们拥有所有元信息，并且可以编写更强大的代码来从它们出现的上下文中查找标识符。

- 交互式源列表：只要按下 **u**，你可以立刻查看当前声明或者定义的源代码（通过更改 location 哈希实现）！

- 更加清晰的列表

- 搜索支持注释

- 更加友好的错误集合展示（支持通过其他的声明进行跳转）

- 函数说明也会展示错误类型说明

- 正确的类型检测（旧实现可能会猜错）

- 浏览历史的正确记录（依赖于 `popstate` 事件 和历史记录 api）

::: info

更加全面的信息，可以查看 [commit diff](https://github.com/andrewrk/autodoc/commit/6d96a63430b39c8a08158410b25dd0ecafea28db)。

:::

## 编译器

### x86 后端

x86 后端现在通过了行为测试套件的 1765/1828（97%），与 LLVM 后端相比。由于它提供了显著更快的编译速度，所以在开发过程中有时会发现它很有用：

```sh
Benchmark 1 (8 runs): zig-0.12.0 build-exe hello.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           667ms ± 26.7ms     643ms …  729ms          1 (13%)        0%
  peak_rss            175MB ± 19.3MB     168MB …  223MB          1 (13%)        0%
  cpu_cycles         3.42G  ±  532M     3.21G  … 4.74G           1 (13%)        0%
  instructions       6.20G  ± 1.05G     5.83G  … 8.79G           1 (13%)        0%
  cache_references    241M  ± 19.9M      234M  …  291M           1 (13%)        0%
  cache_misses       48.3M  ± 1.26M     47.7M  … 51.4M           1 (13%)        0%
  branch_misses      35.3M  ± 4.07M     33.7M  … 45.4M           1 (13%)        0%
Benchmark 2 (26 runs): zig-0.12.0 build-exe hello.zig -fno-llvm -fno-lld
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           196ms ± 5.77ms     187ms …  208ms          0 ( 0%)        ⚡- 70.6% ±  1.7%
  peak_rss           88.7MB ±  721KB    87.8MB … 90.4MB          2 ( 8%)        ⚡- 49.3% ±  4.3%
  cpu_cycles          842M  ± 6.01M      836M  …  866M           1 ( 4%)        ⚡- 75.4% ±  6.0%
  instructions       1.60G  ± 9.62K     1.60G  … 1.60G           0 ( 0%)        ⚡- 74.1% ±  6.5%
  cache_references   56.6M  ±  378K     56.0M  … 57.3M           0 ( 0%)        ⚡- 76.6% ±  3.2%
  cache_misses       8.43M  ±  104K     8.30M  … 8.79M           2 ( 8%)        ⚡- 82.5% ±  1.0%
  branch_misses      7.20M  ± 30.2K     7.15M  … 7.28M           2 ( 8%)        ⚡- 79.6% ±  4.4%
```

当为 `x86_64` 目标编译时，可以通过传递 CLI 选项 `-fno-llvm -fno-lld`，或者在 `std.Build.Step.Compile` 上设置构建系统标志 `use_llvm` 和 `use_lld` 为 `false` 来访问这个后端。这个后端现在能够编译许多Zig项目，包括编译器本身。

直到使用它作为默认后端前的任务：

- 100% 行为测试通过
- 改进调试信息
- 提高运行时性能

## Windows 资源

Zig 现在支持编译（和交叉编译）Windows资源脚本（`.rc`文件）和 `.manifest` 文件，并将结果`.res` 文件链接到 PE/COFF 二进制文件的资源表中。

- [Add a .rc -> .res compiler to the Zig compiler](https://github.com/ziglang/zig/pull/17069)
- [Add zig rc subcommand, a (cross-platform) drop-in replacement for rc.exe](https://github.com/ziglang/zig/pull/17412)
- [Add preliminary support for Windows .manifest files](https://github.com/ziglang/zig/pull/17448)

查看 [Zig is now also a Windows resource compiler](https://github.com/ziglang/zig/pull/17412)，了解这个功能的一些用例和使用细节。

## 链接器

Zig 现在支持 x86_64、aarch64 的 ELF 链接，并部分支持 riscv64。对 LLD 的依赖预计将在下一个发布周期中被删除。可以使用 `-fno-lld` 标志来使用当前不是默认的 Zig 链接器。

## 缓存系统

这个相当烦人的错误现在已经修复了：[error: StreamTooLong when recompiling; duplicate source files in cache manifest](https://github.com/ziglang/zig/issues/16149)。

修复方法是对缓存清单中列出的文件进行去重，这使得缓存命中速度显著提高。数据点：使用静态 musl libc 构建 hello world 缓存命中

```sh
Benchmark 1 (61 runs): master/zig build-exe hello.c -target native-native-musl -lc
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          81.4ms ± 1.76ms    77.7ms … 87.1ms          1 ( 2%)        0%
  peak_rss           64.6MB ± 77.7KB    64.4MB … 64.7MB          0 ( 0%)        0%
  cpu_cycles         97.2M  ± 1.04M     95.1M  …  101M           1 ( 2%)        0%
  instructions        153M  ± 11.1K      152M  …  153M           0 ( 0%)        0%
  cache_references   2.21M  ± 97.1K     2.05M  … 2.54M           2 ( 3%)        0%
  cache_misses        529K  ± 24.4K      486K  …  600K           4 ( 7%)        0%
  branch_misses       409K  ± 6.45K      397K  …  437K           1 ( 2%)        0%
Benchmark 2 (189 runs): cache-dedup/zig build-exe hello.c -target native-native-musl -lc
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          25.8ms ± 1.26ms    23.9ms … 30.7ms         11 ( 6%)        ⚡- 68.4% ±  0.5%
  peak_rss           65.2MB ± 61.8KB    65.1MB … 65.4MB          2 ( 1%)        💩+  1.0% ±  0.0%
  cpu_cycles         41.2M  ±  608K     40.1M  … 46.3M           4 ( 2%)        ⚡- 57.6% ±  0.2%
  instructions       64.3M  ± 12.6K     64.3M  … 64.4M           2 ( 1%)        ⚡- 57.8% ±  0.0%
  cache_references   1.28M  ± 34.5K     1.21M  … 1.35M           0 ( 0%)        ⚡- 41.9% ±  0.7%
  cache_misses        348K  ± 18.6K      297K  …  396K           0 ( 0%)        ⚡- 34.2% ±  1.1%
  branch_misses       199K  ± 1.34K      197K  …  206K           6 ( 3%)        ⚡- 51.2% ±  0.2%
```

## Bug 修复

[本次发布周期一共修复了 502 个 bug](https://github.com/ziglang/zig/issues?q=is%3Aclosed+is%3Aissue+label%3Abug+milestone%3A0.12.0)。

## Comptime 指针访问

Zig 在编译期访问指针有几个长期存在的错误。当试图以特殊的方式的方式访问指针，例如加载数组的切片或重新解引用内存时，你有时会遇到一个错误的编译错误，编译器会要求 comptime 解引用需要具有明确定义的布局的类型。

[#19630](https://github.com/ziglang/zig/pull/19630) 的合并解决了这个问题。在 `0.12.0` 中，编译器在进行与编译期内存有关的复杂操作时，不再报告错误的编译错误。这个改变也包括对编译期 `@bitCast` 逻辑的一些修复；特别是，包含指针的位转换聚合不再错误地强制在运行时进行操作。

## 当前版本包含的 Bugs

Zig 目前存在一些 [已知的 bugs](https://github.com/ziglang/zig/issues?q=is%3Aopen+is%3Aissue+label%3Abug)，甚至包含一些 [编译错误](https://github.com/ziglang/zig/issues?q=is%3Aopen+is%3Aissue+label%3Amiscompilation)！

Zig 目前仍不成熟，即使是使用 `0.12.0` 也可能需要参与 zig 开发才能使之顺利在某些项目开发上正常工作！

当 Zig 达到 `1.0.0` 时，[一级支持](https://ziglang.org/download/0.12.0/release-notes.html#Tier-1-Support) 将获得一个额外的错误策略作为要求。

## 工具链

### LLVM 17

当前发布的新版本已经更新至 LLVM 17.0.6！

Zig 现在直接生成 LLVM bitcode 模块文件，然后将这些文件传递给 LLVM 。这意味着一个没有 LLVM 库的 Zig 编译器仍然可以生成 .bc 文件，然后这些文件可以传递给 clang 进行编译。

### musl 1.2.4

尽管musl v1.2.5 现在在上游可用，但这个版本的 Zig 仍然提供 v1.2.4 。预计 Zig 的下一个版本将使用新的的 musl。

### glibc 2.38

当进行交叉编译时，现在可以使用 glibc 版本 2.35、2.36、2.37 和 2.38。

### mingw-w64

根据 [Martin Storsjö](https://github.com/sponsors/mstorsjo) 的建议，Zig 现在跟踪 mingw-w64 的最新主分支提交。

## 路线图

0.13.0 发布周期的主要主题将是 **编译速度**。

在 0.13.0 发布周期中尽量实现一些里程碑特性：

- 将 x86 后端作为调试模式的默认后端。
- 链接器支持 COFF，移除对 LLD 的依赖。
- 启用增量编译以快速重建。
- 引入并发性到语义分析以进一步提高编译速度。

目前的思路是，优先考虑更快的编译将提高编译器本身的开发速度，从而在接下来的发布周期中修复更多的错误并完成更多的功能。

> 加快编译速度也可能会对语言本身做出一些调整。

## `Async/Await` 特性进度

在 `0.11.0` 版本发布后，异步函数被冻结。由于多个尚未解决的问题，尚不知未来如何处理该特性：

- LLVM 无法优化它们。
- 第三方调试器无法调试它们。
- [取消问题](https://github.com/ziglang/zig/issues/5913)。
- 异步函数指针阻止了堆栈大小的知晓。

这些问题是可以克服的，但需要时间，Zig团队目前正在关注其他优先事项。

## 贡献者和赞助者名单

请查看官方的 [发行说明](https://ziglang.org/download/0.12.0/release-notes.html#toc-Thank-You-Contributors)！
