-
Notifications
You must be signed in to change notification settings - Fork 47
feat(docs): support 0.16.0 #320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jinzhongjia
wants to merge
1
commit into
main
Choose a base branch
from
016
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,125
−1
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| const version: string = "0.15.1"; | ||
| const version: string = "0.16.0"; | ||
|
|
||
| export { version }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,363 @@ | ||
| --- | ||
| outline: deep | ||
| comments: false | ||
| showVersion: false | ||
| --- | ||
|
|
||
| # `0.16.0` | ||
|
|
||
| 2026/4/13,`0.16.0` 发布,历时 8 个月,有 244 位贡献者参与,一共进行了 1183 次提交! | ||
|
|
||
| 如果要用一句话概括这个版本,那就是:**`0.16.0` 把上一轮预告过的大量基础设施重构真正落地了。** | ||
|
|
||
| `0.15.x` 还在为 `std.Io`、增量编译和新的工具链架构铺路,到了 `0.16.0`,这些方向已经进入可以大规模体验的阶段:I/O 统一为接口、`main` 可以直接拿到 `io` 和 `gpa`、增量编译进一步可用、新 ELF linker 开始接入默认流程,同时语言层也继续清理历史设计。 | ||
|
|
||
| ## 目标支持 | ||
|
|
||
| `0.16.0` 在目标支持上的一个重要变化,是 Zig 对“哪些平台值得持续投入工程质量”这件事变得更明确了。 | ||
|
|
||
| 比较值得注意的点有: | ||
|
|
||
| - `aarch64-freebsd`、`aarch64-netbsd`、`loongarch64-linux`、`powerpc64le-linux`、`s390x-linux`、`x86_64-freebsd`、`x86_64-netbsd`、`x86_64-openbsd` 这些目标现在都会在 Zig 的 CI 中原生测试 | ||
| - 新增 `aarch64-maccatalyst` 与 `x86_64-maccatalyst` 的交叉编译支持 | ||
| - 新增 `loongarch32-linux` 的初始支持,不过当前仍不支持 libc | ||
| - Alpha、KVX、MicroBlaze、OpenRISC、PA-RISC、SuperH 等架构加入了基础支持 | ||
| - Oracle Solaris、IBM AIX、z/OS 支持被移除;`illumos` 不受影响,仍然保留支持 | ||
| - 栈回溯支持进一步扩大,几乎所有主流目标在崩溃时都能得到更可靠的 stack trace | ||
|
|
||
| 对普通用户来说,这意味着 Zig 在常见 Linux / BSD / macOS / Windows 目标上的“可用性底线”又往前推了一步;而对于比较边缘的平台,官方也更清晰地区分了“支持”“实验性支持”和“不再支持”。 | ||
|
|
||
| ## 系统最低版本要求 | ||
|
|
||
| | 操作系统(Operating System) | 最低版本要求(Minimum Version) | | ||
| | :--------------------------- | :-----------------------------: | | ||
| | DragonFly BSD | 6.0 | | ||
| | FreeBSD | 14.0 | | ||
| | Linux | 5.10 | | ||
| | NetBSD | 10.1 | | ||
| | OpenBSD | 7.8 | | ||
| | macOS | 13.0 | | ||
| | Windows | 10 | | ||
|
|
||
| ## 语言变动 | ||
|
|
||
| ### `switch` 继续补齐语义 | ||
|
|
||
| `switch` 是这一轮里继续被打磨的语言特性之一。现在,`packed struct` 和 `packed union` 可以直接作为 prong item,比较规则按照 backing integer 来做;同时,decl literals、需要结果类型的表达式、union tag capture 等场景也获得了更一致的支持。 | ||
|
|
||
| 这类变更本身并不一定会让旧代码报错,但它明显减少了过去一些“语言明明应该支持、但实现上还没补齐”的边角问题。 | ||
|
|
||
| ### `@cImport` 正式进入“迁移期” | ||
|
|
||
| `0.16.0` 仍然保留了 `@cImport`,但已经明确将其标记为 deprecated。官方方向是把 C 头文件翻译迁到构建系统中,通过 `build.zig` 里的 `addTranslateC` 生成模块,再在 Zig 代码里使用 `@import("c")`。 | ||
|
|
||
| 这和 Zig 未来“逐步把对 LLVM / Clang 的库级依赖转向进程级依赖”的方向是一致的。 | ||
|
|
||
| 同时,`translate-c` 的实现现在已经从 `libclang` 切换到了 Aro / translate-c 方案。对大多数用户来说这是透明的,但如果你升级后发现 C 头文件翻译行为有差异,它更可能是实现 bug,而不是新的预期行为。 | ||
|
|
||
| ### `@Type` 被拆分为多个独立内建函数 | ||
|
|
||
| 这是 `0.16.0` 最明显的语言级 breaking change 之一。`@Type` 被移除,原来依赖它造类型的元编程代码,需要迁移到新的内建函数: | ||
|
|
||
| - `@EnumLiteral()` | ||
| - `@Int()` | ||
| - `@Tuple()` | ||
| - `@Pointer()` | ||
| - `@Fn()` | ||
| - `@Struct()` | ||
| - `@Union()` | ||
| - `@Enum()` | ||
|
|
||
| 这项改动的核心目标,是让“构造类型”这件事更直观,也让常见场景不必再绕一层 `std.meta.Int`、`std.meta.Tuple` 之类的辅助函数。 | ||
|
|
||
| ### packed / extern 相关规则更严格 | ||
|
|
||
| 这次发布继续收紧了位级布局和 ABI 边界的隐式行为: | ||
|
|
||
| - `packed union` 现在要求更明确的 backing integer 语义 | ||
| - `packed struct` / `packed union` 不再允许直接放指针字段 | ||
| - `extern` 场景下,`enum` 与 `packed` 类型不能再依赖隐式推断的底层整数类型 | ||
|
|
||
| 从设计上看,这些限制的方向非常统一:**凡是会影响 ABI 或精确内存布局的内容,Zig 都更倾向于要求你显式写出来。** | ||
|
|
||
| ### 向量语义进一步收紧 | ||
|
|
||
| `0.16.0` 禁止了运行时向量索引,同时也不再鼓励通过旧式内存强转在数组和向量之间来回转换。简单来说,向量更明确地被当成“值语义上的 SIMD 数据”,而不是“碰巧可以按数组方式随便访问的内存”。 | ||
|
|
||
| 另外,小整数类型在“绝对不会丢精度”的前提下,现在可以安全地隐式转换为浮点类型,这也让数值代码更顺手了一些。 | ||
|
|
||
| ### 类型解析与依赖环错误大幅重做 | ||
|
|
||
| `0.16.0` 还重做了编译器内部的类型解析流程。这个改动的影响非常深: | ||
|
|
||
| - 许多以前会误报 dependency loop 的代码现在可以正常工作 | ||
| - 增量编译和普通编译之间的一致性明显增强 | ||
| - 一小部分本来就存在真实依赖环的代码,现在会更早、更明确地报错 | ||
|
|
||
| 如果你升级后遇到以前没见过的 dependency loop,先别急着回退版本。因为 `0.16.0` 的错误报告已经能更清楚地指出环路是怎么形成的,通常只要打断其中一条依赖即可。 | ||
|
|
||
| ## 标准库 | ||
|
|
||
| ### I/O 作为 Interface | ||
|
|
||
| 这是 `0.16.0` 最重头的内容,没有之一。 | ||
|
|
||
| 从这个版本开始,所有输入输出相关能力都围绕 `std.Io` 展开。更准确地说,凡是可能阻塞控制流,或会引入非确定性的操作,都被纳入了 `Io` 的抽象边界内。 | ||
|
|
||
| 当前官方提供了几种典型实现: | ||
|
|
||
| - `Io.Threaded`:基于线程,功能最完整,也是从 `0.15.x` 升级时最接近旧行为的实现 | ||
| - `Io.Evented`:仍在实验阶段,用来推动接口演进 | ||
| - `Io.failing`:用于模拟“不支持任何操作”的环境 | ||
|
|
||
| 围绕它,标准库引入了整套新的任务和并发抽象: | ||
|
|
||
| - `Future` | ||
| - `Group` | ||
| - `Batch` | ||
| - `Select` | ||
| - `Queue(T)` | ||
| - 统一的 cancelation 模型 | ||
|
|
||
| 这不仅是 API 改名,而是 Zig 对“并发 I/O 应该怎样进入语言生态”给出的新答案。文件系统、网络、进程、同步原语、定时器等能力,都围绕这套接口重新组织了。 | ||
|
|
||
| ### `Juicy Main` | ||
|
|
||
| 为了配合新的 `std.Io`,`main` 也获得了一个很实用的新入口:`std.process.Init`。 | ||
|
|
||
| 只要把 `main` 写成: | ||
|
|
||
| ```zig | ||
| const std = @import("std"); | ||
|
|
||
| pub fn main(init: std.process.Init) !void { | ||
| const gpa = init.gpa; | ||
| const io = init.io; | ||
| _ = gpa; | ||
| _ = io; | ||
| } | ||
| ``` | ||
|
|
||
| 你就能直接拿到: | ||
|
|
||
| - `gpa` | ||
| - `io` | ||
| - `arena` | ||
| - `environ_map` | ||
| - `preopens` | ||
| - `minimal.args` / `minimal.environ` | ||
|
|
||
| 这让应用入口第一次真正成了“进程上下文的注入点”。对于应用开发来说,这个改动的体感甚至不亚于 `std.Io` 本身。 | ||
|
|
||
| ### 环境变量和进程参数不再是全局状态 | ||
|
|
||
| 和 `Juicy Main` 配套的另一项重要变化,是环境变量和进程参数都不再被鼓励当成全局状态来访问。 | ||
|
|
||
| 现在,环境变量原则上只存在于应用入口的 `Init` 里;需要使用它们的函数,应当显式接收需要的值,或者接收 `*const std.process.Environ.Map`。 | ||
|
|
||
| 这个方向很符合 Zig 一贯的设计哲学:尽量少依赖隐式的全局上下文,让副作用和依赖关系都显式体现在函数签名里。 | ||
|
|
||
| ### 线程与分配器模型继续更新 | ||
|
|
||
| 围绕新的 `std.Io`,标准库的并发相关设施也继续收敛: | ||
|
|
||
| - `std.Thread.Pool` 被移除,官方建议迁移到 `std.Io.async` / `std.Io.Group.async` | ||
| - `std.heap.ArenaAllocator` 变成了 thread-safe 且 lock-free | ||
| - `std.heap.ThreadSafeAllocator` 被移除 | ||
|
|
||
| 如果把这些变化放在一起看,会发现 Zig 正在逐步放弃一些“靠包装器补线程安全”的旧路子,转而更偏向于:让真正需要并发的基础组件自己具备合适的并发语义。 | ||
|
|
||
| ### 文件系统、路径与容器 API 持续整理 | ||
|
|
||
| 除了 `std.Io` 大迁移之外,这次标准库还有很多看起来零碎、但真实影响升级体验的整理工作: | ||
|
|
||
| - `std.io` 继续收敛到 `std.Io` | ||
| - `std.fs` 的一批常用入口迁到 `std.Io.Dir` / `std.Io.File` | ||
| - `std.process.getCwd*` 改名为 `currentPath*` | ||
| - `fs.path.relative` 变成纯函数,需要显式传入上下文 | ||
| - `File.Stat.atime` 变成可选值 | ||
| - `std.mem` 里 “index of” 系列统一更名为 “find” | ||
| - 一批容器继续向 unmanaged 方向迁移,`PriorityQueue` / `PriorityDequeue` 的命名也更统一了 | ||
|
|
||
| 这些调整单看都不算大新闻,但合在一起,就是一次很典型的 Zig 式“去历史包袱”整理。 | ||
|
|
||
| ### Windows 标准库实现继续下沉 | ||
|
|
||
| Windows 也是 `0.16.0` 里非常有意思的一条线: | ||
|
|
||
| - 网络 API 不再依赖 `ws2_32.dll`,而是直接基于 AFD 实现 | ||
| - 标准库继续向 NtDll 收敛 | ||
| - `std.Progress` 现在也支持 Windows 下的跨进程进度上报 | ||
|
|
||
| 这些工作虽然对多数用户不可见,但会真实影响程序的健壮性、性能,以及 cancelation / batch 模型在 Windows 上的完整度。 | ||
|
|
||
| ## 构建系统 | ||
|
|
||
| ### 依赖目录改到项目本地 `zig-pkg` | ||
|
|
||
| 从 `0.16.0` 开始,依赖包会被拉取到项目根目录旁边的 `zig-pkg` 目录,而不是继续使用过去那种全局解压缓存模式。 | ||
|
|
||
| 这个变化的好处很直接: | ||
|
|
||
| - 你可以更方便地阅读、搜索、修改依赖源码 | ||
| - 可以更自然地把依赖目录换成本地 git clone | ||
| - IDE 也更容易直接索引整棵依赖树 | ||
|
|
||
| ### `zig build --fork` | ||
|
|
||
| 构建系统新增了 `--fork=[path]` 参数,可以让你临时用本地目录里的 fork 覆盖依赖树中的匹配包。 | ||
|
|
||
| 这对生态 breakage 的排查非常有帮助:你可以在不改版本元数据的前提下,直接调试一整串依赖之间的兼容问题。 | ||
|
|
||
| ### 依赖元数据更严格 | ||
|
|
||
| `0.16.0` 还提高了 `build.zig.zon` 的要求: | ||
|
|
||
| - 缺少 `fingerprint` 会直接失败 | ||
| - `name` 不能再用字符串,必须写成 enum literal | ||
| - 旧 hash 格式支持已被移除 | ||
|
|
||
| 这意味着旧项目在升级时,最好顺手检查一遍所有依赖元数据,而不是等到 `zig build` 报错再逐个补。 | ||
|
|
||
| ### 新增测试超时与错误输出样式 | ||
|
|
||
| `zig build` 新增了几项很适合日常开发的参数: | ||
|
|
||
| - `--test-timeout` | ||
| - `--error-style` | ||
| - `--multiline-errors` | ||
|
|
||
| 同时,旧的 `--prominent-compile-errors` 被移除了,对应的新写法是 `--error-style minimal`。 | ||
|
|
||
| ### 临时文件 API 被重构 | ||
|
|
||
| `Build.makeTempPath` 和 `RemoveDir` step 都被清理掉了,新的推荐路径是: | ||
|
|
||
| - `Build.addTempFiles` | ||
| - `Build.addMutateFiles` | ||
| - `Build.tmpPath` | ||
|
|
||
| 这项重构背后的核心思路,是把“临时目录”“可变文件”“缓存语义”这些东西从一开始就表达清楚,而不是让旧 API 在 configure 阶段偷偷做一堆文件系统副作用。 | ||
|
|
||
| ## Compiler | ||
|
|
||
| ### `translate-c` 改用 Aro | ||
|
|
||
| 编译器内部的 `translate-c` 现在基于 Aro / translate-c,而不是 `libclang`。这使 Zig 离“摆脱对 LLVM 的库级依赖”又近了一步。 | ||
|
|
||
| 对普通用户来说,这更多体现为长期方向上的信号:Zig 仍在持续拆除自己对 LLVM 的深绑定。 | ||
|
|
||
| ### 类型解析重构 | ||
|
|
||
| 前面在“语言变动”里提过,`0.16.0` 大幅重做了类型解析。这件事对编译器本身还有两个非常重要的连锁收益: | ||
|
|
||
| - 依赖环报错更可解释 | ||
| - 增量编译和普通编译之间的一致性更强 | ||
|
|
||
| 这也是为什么你会发现,本版本许多看似分散的改动,最后都会回到“为了更可靠的增量编译”这个主题上。 | ||
|
|
||
| ### 增量编译继续前进 | ||
|
|
||
| `0.16.0` 的增量编译已经比 `0.15.x` 实用得多: | ||
|
|
||
| - 大多数场景下减少了“过度重编译” | ||
| - LLVM 后端也开始支持增量编译 | ||
| - ELF 目标在 `-fincremental` 下会默认启用新的 ELF linker | ||
| - 稳定性明显提升,虽然依然不是默认开启 | ||
|
|
||
| 官方现在明确鼓励大家实际使用: | ||
|
|
||
| ```sh | ||
| zig build -fincremental --watch | ||
| ``` | ||
|
|
||
| 当然,它仍然有已知 bug,甚至可能包含误编译;所以这项功能在 `0.16.0` 里依然不是默认值。 | ||
|
|
||
| ### 后端进展 | ||
|
|
||
| 这一轮里: | ||
|
|
||
| - x86 自托管后端修了 11 个 bug,仍然是 Debug 模式下的默认后端 | ||
| - aarch64 后端因为 `std.Io` 带来的标准库 churn 暂时放慢了节奏 | ||
| - Zig 的 WebAssembly 后端目前通过了 1813 / 1970(约 92%)项行为测试 | ||
|
|
||
| ## 链接器(Linker) | ||
|
|
||
| ### 新 ELF Linker | ||
|
|
||
| `0.16.0` 的新 ELF linker 可以通过 `-fnew-linker` 显式启用,或者在 build 脚本里设置 `exe.use_new_linker = true`。更重要的是:**在 `-fincremental` 且目标是 ELF 时,它现在会默认启用。** | ||
|
|
||
| 官方给出的一个数据点非常直观:对 Zig 编译器本体做单行改动时,旧 linker 需要大约 `194ms`,而新 linker 只需要 `65ms`,几乎接近“完全跳过链接”的速度。 | ||
|
|
||
| 这也意味着过去那种专门暴露 `-Dno-bin`、只求快速拿到编译错误的工作流,收益已经没有以前那么明显了。 | ||
|
|
||
| 不过要注意,新 linker 目前还没完全补齐旧 linker / LLD 的能力,例如生成物还缺少 DWARF 信息。所以它已经够快、够值得试,但还没有到“所有场景都能无脑切换”的程度。 | ||
|
|
||
| ## Fuzzer(模糊测试器) | ||
|
|
||
| ### `Smith` 取代 `[]const u8` | ||
|
|
||
| Fuzz 测试接口是 `0.16.0` 里另一个会直接影响用户代码的 breaking change。过去 fuzz test 习惯接收 `[]const u8` 输入;现在统一改成 `*std.testing.Smith`,由它来生成结构化值。 | ||
|
|
||
| 这套接口不仅更适合做复杂输入生成,还支持权重、范围、哈希相关性等能力,明显比过去的“原始字节切片”模式更强。 | ||
|
|
||
| ### 多进程、多核与 crash dump | ||
|
|
||
| 除了接口变化之外,fuzzer 本身也更强了: | ||
|
|
||
| - 现在可以利用多核,受 `-j` 控制 | ||
| - 多个 fuzz test 会自动轮换并优先运行更“有产出”的测试 | ||
| - 崩溃输入会自动落盘,便于复现 | ||
|
|
||
| ## Bug 修复 | ||
|
|
||
| 本轮发布周期内,Zig 一共关闭了 345 个 bug 报告。 | ||
|
|
||
| 不过官方也直说了:**这个版本仍然包含已知 bug、误编译和回归问题。** 对于稍微复杂一点的项目,使用 `0.16.x` 仍然意味着要准备好参与 issue 反馈、最小复现和版本试验。 | ||
|
|
||
| 这并不意外。因为 `0.16.0` 本质上是一个“大迁移版本”,它把很多还在演进中的长期工程方向一次性推到了用户面前。 | ||
|
|
||
| ## 工具链(Toolchain) | ||
|
|
||
| ### LLVM 21 | ||
|
|
||
| `0.16.0` 升级到了 LLVM `21.1.0`,覆盖了 Clang、libc++、libc++abi、libunwind、libtsan 等组件。 | ||
|
|
||
| 不过这里有一个非常值得注意的 caveat:为了规避 LLVM 上游的严重回归,Zig 在 `0.16.x` 中**完全禁用了 loop vectorization**。这会让某些代码生成结果比理想情况更保守,但它仍然比“在常见配置下误编译 Zig 编译器自身”要好得多。 | ||
|
|
||
| 官方预计这个性能回退不止会影响 `0.16.x`,甚至还会延续到 `0.17.x`,大概率要等到 `0.18.x` 才会彻底解决。 | ||
|
|
||
| ### libc 与系统头文件更新 | ||
|
|
||
| 这一轮工具链同时带来了: | ||
|
|
||
| - `musl 1.2.5`(附带安全修复回移) | ||
| - `glibc 2.43` | ||
| - Linux `6.19` headers | ||
| - macOS `26.4` headers | ||
| - FreeBSD `15.0` libc | ||
| - 交叉编译时支持动态链接的 OpenBSD libc | ||
|
|
||
| ### `zig libc` 继续扩张 | ||
|
|
||
| `zig libc` 继续吞并原来来自 musl、MinGW-w64、WASI libc 的一部分 C 实现。`0.16.0` 中,随 Zig 分发的 C 源文件总数从 `2270` 降到了 `1873`,减少了约 `17%`。 | ||
|
|
||
| 这里尤其值得一提的是:很多数学函数,以及 `malloc` 相关函数,现在都已经进入 `zig libc` 的实现范围。 | ||
|
|
||
| ### `zig cc` | ||
|
|
||
| `zig cc` / `zig c++` 现在基于 Clang `21.1.8`。这意味着 Zig 在“C / C++ 工具链外壳”这条线上,也继续和整体 LLVM 版本一同推进。 | ||
|
|
||
| ## 路线图(Roadmap) | ||
|
|
||
| 官方对 `0.17.0` 的规划很明确:这是一个相对短周期版本,主要目标是升级到 LLVM `22`,并完成“把构建执行阶段和 `build.zig` 配置阶段分离”的工作。 | ||
|
|
||
| 在这之后,更长期的大方向仍然是: | ||
|
|
||
| - 继续完成并稳定语言本身 | ||
| - 做完 aarch64 后端,并让它成为 Debug 模式默认后端 | ||
| - 继续增强链接器,减少对 LLD 的依赖,并服务增量编译 | ||
| - 继续增强内置 fuzzer | ||
| - 继续把对 LLVM 的依赖,从“链接库”转向“调用 Clang 进程” | ||
|
|
||
| 如果说 `0.15.x` 还是“这些方向马上就要影响到你了”,那 `0.16.0` 就是“它们已经开始真正影响你的日常开发了”。 | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶