0.17.0 Release Notes0.17.0 版本发布说明

Carmen the Allocgator

Download & Documentation 下载与文档

Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software. Zig 是一门通用编程语言及工具链,旨在维护健壮、高效且可复用的软件。

Zig development is funded via Zig Software Foundation, a 501(c)(3) non-profit organization. Please consider a recurring donation so that we can offer more billable hours to our core team members. This is the most straightforward way to accelerate the project along the Roadmap to 1.0. If you need donation receipts or are looking to migrate away from GitHub Sponsors, we recommend donating via Every.org. Zig 的开发由 Zig 软件基金会(Zig Software Foundation)资助,这是一个 501(c)(3) 非营利组织。请考虑进行定期捐赠,以便我们能为核心团队成员提供更多可计费工时。这是加速项目迈向 1.0 路线图最直接的方式。如果您需要捐赠收据,或希望从 GitHub Sponsors 迁移,我们建议通过 Every.org 进行捐赠。

This release features 5 months of work: changes from 206 different contributors, spread among 925 commits.本次发布汇集了 5 个月的工作成果:来自 206 位不同贡献者的代码贡献,共计 925 次提交。

Originally predicted to be shorter, this release cycle ended up substantial, with the Build System reworked, including the introduction of the Build Server Protocol, and the ELF Linker enhanced to the point where we expect Incremental Compilation to work for everyone on x86_64-linux. 最初预计本次发布周期会更短,但最终成果相当丰硕。构建系统(Build System)进行了重构,引入了构建服务器协议(Build Server Protocol),ELF 链接器也得到了增强,我们预期增量编译(Incremental Compilation)功能现在可在 x86_64-linux 上为所有用户正常工作。

Table of Contents §目录 §

Target Support §目标平台支持 §

Zero the Ziguana

Zig supports a wide range of architectures and operating systems. The Support Table and Additional Platforms sections cover the targets that Zig can build programs for, while the zig-bootstrap README covers the targets that the Zig Compiler itself can be easily cross-compiled to run on. Zig 支持多种架构和操作系统。“支持列表”和“其他平台”部分涵盖了 Zig 可构建程序的各种目标平台,而 zig-bootstrap 的 README 则涵盖了 Zig 编译器自身可轻松交叉编译以运行的目标平台。

Notable changes:显著变更:

Tier System §分级系统 §

Zig's level of support for various targets is broadly categorized into four tiers with Tier 1 being the highest. The goal is for Tier 1 targets to have zero disabled tests - this will become a requirement for post-1.0.0 Zig releases. Zig 对各种目标平台的支持程度大致分为四个级别,其中一级支持最高。我们的目标是让一级支持的目标平台实现零禁用测试——这将成为 1.0.0 版本之后 Zig 发布的必要条件。

Tier 1 §一级支持 §

Tier 2 §二级支持 §

Tier 3 §三级支持 §

Tier 4 §四级支持 §

Support Table §支持列表 §

In the following table, ✅ indicates full support, ❌ indicates no support, and ⚠️ indicates that there is partial support, e.g. only for some sub-targets, or with some notable known issues. ❔ indicates that the status is largely unknown, typically because the target is rarely exercised. Hover over other icons for details. 在下表中,✅ 表示完全支持,❌ 表示不支持,⚠️ 表示部分支持(例如仅支持某些子目标,或存在一些已知的显著问题)。❔ 表示状态基本未知,通常是因为该目标很少被使用。将鼠标悬停在其他图标上可查看详情。

Targets marked with 🪦 are obsolescent; the Zig compiler and standard library maintain best-effort support for them, but that support is expected to be removed eventually. 标记为 🪦 的目标已过时;Zig 编译器和标准库尽力维护对其的支持,但预计最终会移除该支持。

Tier Target Code Gen. Linker Lang. Feat. Std. Lib. Stack Traces Fuzzer libc CI
1 x86_64-linux 🖥️⚡ ✅ ✅ ✅ ✅ ✅ ✅ ✅

2 aarch64-freebsd 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 aarch64[_be]-linux 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 aarch64-maccatalyst 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 aarch64-macos 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 aarch64[_be]-netbsd 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 aarch64-openbsd 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 aarch64-windows 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 arm-freebsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 arm[eb]-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 arm[eb]-netbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 arm-openbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 hexagon-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 loongarch32-linux 🖥🛠 ✅ ❔ ✅ ✅ ❌ ✅ ⚠️
2 loongarch64-linux 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 mips[el]-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 mips[el]-netbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 mips64[el]-linux 🖥️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 mips64[el]-openbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 powerpc-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 powerpc-netbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 powerpc-openbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 powerpc64[le]-freebsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 powerpc64[le]-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 powerpc64-openbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 riscv32-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 riscv32-netbsd 🖥️ ✅ ✅ ✅ ✅ ✅ ✅ ⚠️
2 riscv64-freebsd 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ⚠️
2 riscv64-linux 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 riscv64-netbsd 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ⚠️
2 riscv64-openbsd 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 s390x-linux 🖥️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 sparc64-linux 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 thumb[eb]-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 wasm32-wasi 🖥️🛠️ ✅ ✅ ✅ ⚠️ ❌ ✅ ✅
2 x86-linux 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 x86-netbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 x86-openbsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ⚠️
2 🪦 x86-windows 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 x86_64-freebsd 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 🪦 x86_64-maccatalyst 🖥️⚡ ✅ ✅ ✅ ✅ ✅ ✅ ⚠️
2 🪦 x86_64-macos 🖥️⚡ ✅ ✅ ✅ ✅ ✅ ✅ ⚠️
2 x86_64-netbsd 🖥️🛠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅
2 x86_64-openbsd 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ✅ ✅
2 x86_64-windows 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ✅ ✅

3 aarch64-haiku 🖥️🛠️ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️
3 aarch64-ios 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ❌️ ❌️
3 aarch64-serenity 🖥️🛠️ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️
3 aarch64-tvos 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ❌️ ❌️
3 aarch64-visionos 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ❌️ ❌️
3 aarch64-watchos 🖥️🛠️ ✅ ✅ ✅ ✅ ❌ ❌️ ❌️
3 arm-haiku 🖥️ ✅ ✅ ✅ ✅ ❌ ❌️ ❌️
3 mips64[el]-netbsd 🖥️ ✅ ✅ ✅ ❌️ ✅ ❌️ ❌️
3 riscv64-haiku 🖥️🛠️ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️
3 riscv64-serenity 🖥️🛠️ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️
3 🪦 thumb-windows 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ❌️
3 wasm64-wasi 🖥️🛠️ ✅ ❔ ❌️ ⚠️ ❌ ❌️ ❌️
3 🪦 x86-freebsd 🖥️ ✅ ✅ ✅ ✅ ❌ ✅ ❌
3 x86-haiku 🖥️ ✅ ✅ ✅ ✅ ❌ ❌️ ❌️
3 🪦 x86-illumos 🖥️ ✅ ✅ ✅ ✅ ❌ ❌️ ❌️
3 x86_64-dragonfly 🖥️🛠️ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️
3 x86_64-haiku 🖥️⚡ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️
3 x86_64-illumos 🖥️🛠️ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️
3 x86_64-serenity 🖥️⚡ ✅ ✅ ✅ ✅ ❔ ❌️ ❌️

4 alpha-linux 📄 ❌️ ❔ ✅ ✅ ❌ ❌️ ❌️
4 alpha-netbsd 📄 ❌️ ❔ ✅ ✅ ❌ ❌️ ❌️
4 alpha-openbsd 📄 ❌️ ❔ ✅ ✅ ❌ ❌️ ❌️
4 arc[eb]-linux 📄 ❌️ ❔ ✅ ✅ ❌ ✅ ❌️
4 csky-linux 📄 ❌️ ❔ ✅ ✅ ❌ ✅ ❌️
4 hppa-linux 📄 ❌️ ❔ ❌️ ❌️ ❌ ❌️ ❌️
4 hppa-netbsd 📄 ❌️ ❔ ✅ ❌️ ❌ ❌️ ❌️
4 hppa-openbsd 📄 ❌️ ❔ ✅ ❌️ ❌ ❌️ ❌️
4 hppa64-linux 📄 ❌️ ❔ ❌️ ❌️ ❌ ❌️ ❌️
4 m68k-linux 🖥️ ❌️ ❔ ✅ ✅ ❌ ✅ ❌️
4 m68k-netbsd 🖥️ ❌️ ❔ ✅ ✅ ❌ ✅ ❌️
4 m88k-openbsd 📄 ❌️ ❔ ✅ ✅ ❌ ❌️ ❌️
4 microblaze[el]-linux 📄 ❌️ ❔ ✅ ❌️ ❌ ❌️ ❌️
4 or1k-linux 📄 ❌️ ❔ ✅ ✅ ❌ ❌️ ❌️
4 sh[eb]-linux 📄 ❌️ ❔ ✅ ❌️ ❌ ❌️ ❌️
4 sh[eb]-netbsd 📄 ❌️ ❔ ✅ ❌️ ❌ ❌️ ❌️
4 sh-openbsd 📄 ❌️ ❔ ✅ ❌️ ❌ ❌️ ❌️
4 sparc-linux 🖥️ ❌️ ❔ ✅ ✅ ❌ ✅ ❌️
4 sparc-netbsd 🖥️ ❌️ ❔ ✅ ❌️ ❌ ✅ ❌️
4 sparc64-netbsd 🖥️🛠️ ⚠️ ✅ ✅ ❌️ ✅ ✅ ❌️
4 sparc64-openbsd 🖥️🛠️ ⚠️ ✅ ✅ ❌️ ❌ ✅ ❌️
4 xtensa[eb]-linux 🖥️ ❌️ ❔ ✅ ❌️ ❌ ❌️ ❌️

OS Version Requirements §操作系统版本要求 §

The Zig standard library has minimum version requirements for some supported operating systems, which in turn affect the Zig compiler itself: Zig 标准库对某些受支持的操作系统有最低版本要求,这反过来也会影响 Zig 编译器本身:

OS Version
Darwin 15.0+
DragonFly BSD 6.4+
FreeBSD 14.0+
Linux 5.10+
NetBSD 10.1+
OpenBSD 7.8+
Windows 10+

Additional Platforms §其他平台 §

Zig also has varying levels of support for these targets, for which the tier system does not quite apply: Zig 对这些目标也有不同程度的支持,分级系统并不完全适用:

Language Changes §语言变更 §

Language Stability Progress §语言稳定性进展 §

Since the release of Zig 0.16.0, a lot of progress has been made towards stabilizing the language. This is a key step in our roadmap, and a requirement before tagging Zig 1.0.自 Zig 0.16.0 发布以来,在语言稳定性方面取得了很大进展。这是我们路线图中的关键一步,也是在发布 Zig 1.0 之前必须满足的要求。

In particular, since the last release, we have discussed and made decisions on many language proposals—accepting around 25 and rejecting around 125. At the time of writing, 23 undecided language proposals remain open on the Codeberg issue tracker, and 61 undecided language proposals remain open on the legacy GitHub issue tracker. Therefore, this effort represents a significant step towards finalizing the language design (although some major decisions remain).特别是自上个版本以来,我们讨论并决策了许多语言提案——采纳了约 25 个,拒绝了约 125 个。截至撰写本文时,Codeberg 问题追踪器上仍有 23 个未决的语言提案,旧版 GitHub 问题追踪器上仍有 61 个未决的语言提案。因此,这项工作代表了在最终确定语言设计方面迈出的重要一步(尽管仍有一些重大决策尚未做出)。

@bitCast changes §@bitCast 变更 §

Zig 0.17.0 changes the definition of the @bitCast builtin.Zig 0.17.0 更改了 @bitCast 内置函数的定义。

In many cases, the new behavior is equivalent to the old: in particular, casting between an integer type and another integer type is unaffected, as is casting between an integer type and a packed struct or packed union.在许多情况下,新行为与旧行为等效:特别是整数类型之间的转换不受影响,整数类型与紧凑结构体(packed struct)或紧凑联合体(packed union)之间的转换也不受影响。

However, the semantics of @bitCast calls involving array or vector types have changed. Unfortunately, this change has the potential to break existing code without triggering a compile error.. Therefore, it may be useful when upgrading to audit any @bitCast uses which involve array or vector types.然而,涉及数组或向量类型的 @bitCast 调用语义发生了变化。遗憾的是,此更改可能会破坏现有代码,且不会触发编译错误。因此,在升级时审计任何涉及数组或向量类型的 @bitCast 使用情况可能会有所帮助。

The new definition of @bitCast is that it reinterprets the logical bit representation of a value as a different type. The following types are considered to have logical bit representations:@bitCast 的新定义是:它将值的逻辑位表示重新解释为另一种类型。以下类型被认为具有逻辑位表示:

For integer and floating-point types, the logical bit representation starts with the least-significant bit and ends with the most-significant bit. For array and vector types, all elements' logical bit representations are concatenated in order starting with the first element.对于整数和浮点类型,逻辑位表示从最低有效位开始,到最高有效位结束。对于数组和向量类型,所有元素的逻辑位表示按顺序连接,从第一个元素开始。

In practice, this means that the new @bitCast definition largely aligns with the old behavior on little-endian targets. Unlike the old behavior, the new behavior is fully endian-agnostic, i.e. the operation behaves the same regardless of the target endian.实际上,这意味着新的 @bitCast 定义在小端序目标上很大程度上与旧行为保持一致。与旧行为不同的是,新行为完全与端序无关,即该操作的行为在不同目标端序下表现一致。

The new @bitCast definition disallows casts between some types which were previously allowed. In particular, casts involving extern struct or extern union types are no longer permitted. In most cases, code which was using such casts is aiming to reinterpret the value's in-memory representation (sometimes called "type punning")—to achieve this, use @ptrCast or an extern union.新的 @bitCast 定义禁止了某些以前允许的类型转换。特别是,不再允许涉及 extern struct 或 extern union 类型的转换。在大多数情况下,使用此类转换的代码旨在重新解释值的内存中表示(有时称为“类型双关”/type punning)——要实现这一点,请使用 @ptrCast 或 extern union。

bitcast_extern_struct.zigbitcast_extern_struct.zig
const TwoBytes = extern struct {
    b0: u8,
    b1: u8,
};
test "type pun extern struct" {
    const bytes: TwoBytes = .{ .b0 = 0x12, .b1 = 0xAB };
    const int: u16 = @bitCast(bytes);
    switch (std.lang.Endian.native) {
        .little => try expectEqual(0xAB_12, int),
        .big => try expectEqual(0x12_AB, int),
    }
}
const std = @import("std");
const expectEqual = std.testing.expectEqual;
ShellShell
$ zig test bitcast_extern_struct.zig
/home/ci/.cache/act/4d2db5a0202099f4/hostexecutor/src/download/0.17.0/release-notes/bitcast_extern_struct.zig:7:31: error: cannot @bitCast from 'bitcast_extern_struct.TwoBytes'
    const int: u16 = @bitCast(bytes);
                              ^~~~~
/home/ci/.cache/act/4d2db5a0202099f4/hostexecutor/src/download/0.17.0/release-notes/bitcast_extern_struct.zig:1:25: note: struct declared here
const TwoBytes = extern struct {
                 ~~~~~~~^~~~~~

⬇️

ptrcast_extern_struct.zigptrcast_extern_struct.zig
const TwoBytes = extern struct {
    b0: u8,
    b1: u8,
};
test "type pun extern struct" {
    const bytes: TwoBytes = .{ .b0 = 0x12, .b1 = 0xAB };
    const int_ptr: *align(1) const u16 = @ptrCast(&bytes);
    switch (std.lang.Endian.native) {
        .little => try expectEqual(0xAB_12, int_ptr.*),
        .big => try expectEqual(0x12_AB, int_ptr.*),
    }
}
const std = @import("std");
const expectEqual = std.testing.expectEqual;
Shell
$ zig test ptrcast_extern_struct.zig
1/1 ptrcast_extern_struct.test.type pun extern struct...OK
All 1 tests passed.

Formally Specified and Fuzzed Grammar §形式化规范与模糊测试语法 §

Zig's formal grammar.peg and the actual language implementation did not agree in many places. Probably, the formal grammar has never actually 100% matched the actual handwritten tokenizer and parser.Zig 的形式化 grammar.peg 与实际语言实现之间在许多地方并不一致。可能形式化语法从未与实际手写的词法分析器和解析器 100% 匹配过。

This problem is now fixed and unblocks future grammar changes and language specification work.这个问题现已修复,并为未来的语法变更和语言规范工作扫清了障碍。

At a high level, the approach was to write a tool that accepts Zig's grammar.peg as input and outputs a simple recursive descent parser. This generated parser is then used as an oracle for fuzz testing and the handwritten std.zig.Ast.parse() is compared against it. This approach ensures a single source of truth and allows for easy iteration as the grammar changes.概括地说,我们的方法是编写一个工具,以 Zig 的 grammar.peg 为输入,输出一个简单的递归下降解析器。这个生成的解析器随后被用作模糊测试的预言机(oracle),并将手写的 std.zig.Ast.parse() 与其进行对比。这种方法确保了单一事实来源,并允许在语法变更时进行轻松迭代。

More details: #36094更多详情:#36094

C Translation Moving to External Package §C 语言转换功能迁移至外部包 §

@cImport was deprecated in Zig 0.16.0 and is now removed. Furthermore, in this release std.Build.Step.TranslateC is deprecated in favor of an explicit package dependency on official ZSF translate-c package, which is the same implementation the build step provides, but offers more configuration options for the translated code, and has an independent release cadence from the main Zig toolchain.@cImport 在 Zig 0.16.0 中已被弃用,现已移除。此外,在本次发布中,std.Build.Step.TranslateC 已被弃用,转而推荐显式依赖官方 ZSF translate-c 包。该包提供了与构建步骤相同的实现,但为转换后的代码提供了更多配置选项,并拥有独立于主 Zig 工具链的发布节奏。

Upgrade guide:升级指南:

zig fetch --save git+https://codeberg.org/ziglang/translate-c
--- a/build.zig
+++ b/build.zig
@@ -1,16 +1,19 @@
 const std = @import("std");
+const Translator = @import("translate_c").Translator;
 
 pub fn build(b: *std.Build) void {
     const target = b.standardTargetOptions(.{});
     const optimize = b.standardOptimizeOption(.{});
 
-    const translate_c = b.addTranslateC(.{
-        .root_source_file = b.path("src/c.h"),
+    const translate_c = b.dependency("translate_c", .{});
+
+    const translator: Translator = .init(translate_c, .{
+        .c_source_file = b.path("src/c.h"),
         .target = target,
         .optimize = optimize,
+ // additional options now available that go here:
+ // https://codeberg.org/ziglang/translate-c#options
     });
-    translate_c.linkSystemLibrary("glfw", .{});
-    translate_c.linkSystemLibrary("epoxy", .{});
+    translator.linkSystemLibrary("glfw3", .{});
+    translator.linkSystemLibrary("epoxy", .{});
 
     const exe = b.addExecutable(.{
         .name = "tetris",
@@ -21,7 +24,7 @@ pub fn build(b: *std.Build) void {
             .imports = &.{
                 .{
                     .name = "c",
-                    .module = translate_c.createModule(),
+                    .module = translator.mod,
                 },
             },
         }),

Added @backingInt and @fromBackingInt §新增 @backingInt 和 @fromBackingInt §

The @backingInt and @fromBackingInt builtins are new. These builtins replace the now-deprecated @intFromEnum and @enumFromInt builtins (#35966).新增了 @backingInt 和 @fromBackingInt 内置函数。这些内置函数取代了现已弃用的 @intFromEnum 和 @enumFromInt 内置函数 (#35966)。

@backingInt works with all enums and with bitpacks with explicit backing integer types only. It also works with tagged unions, returning the backing integer of the active tag value. An undefined enum or bitpack yields an undefined backing integer. @backingInt 适用于所有枚举,以及仅具有显式底层整数类型的位域(bitpack)。它也适用于带标签的联合体,返回活动标签值的底层整数。未定义的枚举或位域会产生未定义的底层整数。

@fromBackingInt infers its result type, which may be any enum or a bitpack with an explicit backing integer type. It takes a parameter of exactly that backing integer type. For enums, passing a backing integer that is either undefined or would yield an invalid tag value results in safety-checked Illegal Behavior. For bitpacks, passing an undefined backing integer yields an undefined bitpack.@fromBackingInt 推断其结果类型,该类型可以是任何枚举或具有显式底层整数类型的位域。它接受一个完全属于该底层整数类型的参数。对于枚举,传递未定义或会导致无效标签值的底层整数会导致安全检查的非法行为。对于位域,传递未定义的底层整数会产生未定义的位域。

@bitCast now also performs a safety check for invalid tag values if its destination type is an enum.如果目标类型是枚举,@bitCast 现在也会对无效的标签值执行安全检查。

Also adds a std.meta.BackingInt function to get the result type of @backingInt.同时添加了 std.meta.BackingInt 函数以获取 @backingInt 的结果类型。

Zig now requires empty enums to have noreturn as their backing integer because they are uninstantiable.Zig 现在要求空枚举必须使用 noreturn 作为其底层整数,因为它们无法实例化。

Upgrade example:升级示例:

--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -145,7 +145,7 @@ pub const Graph = struct {
 
     pub fn addGeneratedFile(graph: *Graph, owner: *Step) Configuration.GeneratedFileIndex {
         graph.generated_files.append(graph.arena, owner) catch @panic("OOM");
-        return @enumFromInt(graph.generated_files.items.len - 1);
+        return @fromBackingInt(@intCast(graph.generated_files.items.len - 1));
     }
 
     pub fn dupeString(graph: *const Graph, bytes: []const u8) []const u8 {
@@ -2607,7 +2607,7 @@ pub const LazyPath = union(enum) {
             .src_path, .cwd_relative, .relative, .dependency => {},
             .generated => |gen| {
                 const graph = other_step.owner.graph;
-                const generated_owner_step = graph.generated_files.items[@intFromEnum(gen.index)];
+                const generated_owner_step = graph.generated_files.items[@backingInt(gen.index)];
                 other_step.dependOn(generated_owner_step);
             },
         }

zig fmt automatically performs this upgrade.zig fmt 会自动执行此升级。

Added @SpirvType §新增 @SpirvType §

SPIR-V has a number of types, such as images and samplers, that have no equivalent in Zig's type system. Previously, the only way to refer to one of them was through inline assembly, which made it impossible to declare a texture or a storage buffer as an ordinary global variable. Zig 0.17.0 implements accepted proposal #35240, adding the @SpirvType builtin alongside the other type-creating builtins:SPIR-V 拥有许多类型(如图像和采样器),在 Zig 的类型系统中没有等价物。以前,引用它们的唯一方法是通过内联汇编,这使得无法将纹理或存储缓冲区声明为普通的全局变量。Zig 0.17.0 实现了已采纳的提案 #35240,添加了 @SpirvType 内置函数,与其他类型创建内置函数并列:

sample_code示例代码
@SpirvType(comptime options: std.lang.Type.Spirv) type

Using this builtin when not targeting SPIR-V is a compile error. The options are also validated against the target OS.在非 SPIR-V 目标上使用此内置函数会导致编译错误。这些选项也会针对目标操作系统进行验证。

spirv_type.zigspirv_type.zig
const std = @import("std");

const Image = @SpirvType(.{ .image = .{
    .usage = .{ .sampled = f32 },
    .format = .unknown,
    .dim = .@"2d",
    .depth = .not_depth,
    .arrayed = false,
    .multisampled = false,
    .access = .unknown,
} });
const SampledImage = @SpirvType(.{ .sampled_image = Image });

const texture = @extern(*addrspace(.constant) const SampledImage, .{
    .name = "texture",
    .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } },
});
const uv_in = @extern(*addrspace(.input) const @Vector(2, f32), .{
    .name = "uv",
    .decoration = .{ .location = 0 },
});
const color_out = @extern(*addrspace(.output) @Vector(4, f32), .{
    .name = "color",
    .decoration = .{ .location = 0 },
});

export fn main() callconv(.{ .spirv_fragment = .{} }) void {
    color_out.* = std.spirv.imageSampleImplicitLod(texture, uv_in.*);
}
Shell
$ zig build-obj spirv_type.zig -target spirv32-vulkan

Array Multiplication Syntax Removed §移除数组乘法语法 §

Array multiplication syntax (a ** b) has been removed in favor of @splat.数组乘法语法 (a ** b) 已被移除,转而使用 @splat。

Migration:迁移:

--- a/player/chromaprint.zig
+++ b/player/chromaprint.zig
@@ -35,7 +35,7 @@ pub const Chroma = struct {
     const max_index = @min(window_size / 2, freqToIndex(max_freq));
     const notes: [window_size]u8 = n: {
         @setEvalBranchQuota(window_size);
-        var result = [1]u8{0} ** window_size;
+        var result: [window_size]u8 = @splat(0);
         for (min_index..max_index) |i| {
             const freq = indexToFreq(i);
             const octave = freqToOctave(freq);
@@ -123,7 +123,7 @@ const RollingIntegralImage = struct {
     num_rows: u32,
 
     pub const init: RollingIntegralImage = .{
-        .data = [1]Float{0} ** data_size,
+        .data = @splat(0),
         .num_rows = 0,
     };

Added @divCeil §新增 @divCeil §

The new @divCeil builtin performs integer division rounded toward positive infinity, complementing the existing @divTrunc, @divFloor, and @divExact builtins.新的 @divCeil 内置函数执行向正无穷大取整的整数除法,补充了现有的 @divTrunc、@divFloor 和 @divExact 内置函数。

sample_code
@divCeil(5, 3) == 2
@divCeil(-5, 3) == -1

As with the other division builtins, caller guarantees that denominator != 0 and that result does not overflow.与其他除法内置函数一样,调用者需保证分母 != 0 且结果不会溢出。

No more std.math.divCeil(a, b) catch unreachable!不再需要 std.math.divCeil(a, b) catch unreachable!

@hasDecl Returns true Only for Public Declarations §@hasDecl 仅对公共声明返回 true §

Previously, @hasDecl returned true for public declarations and declarations in the same file. Now, the behavior is the same independently of which file @hasDecl is in.以前,@hasDecl 对公共声明和同一文件中的声明返回 true。现在,无论 @hasDecl 处于哪个文件,其行为都保持一致。

hasdecl.zighasdecl.zig
const std = @import("std");

const Foo = struct {
    bar: i32,

    const baz = 1;
    pub var quux = "xxx";
};

test "@hasDecl example" {
    try std.testing.expect(!@hasDecl(Foo, "bar"));
    try std.testing.expect(!@hasDecl(Foo, "baz")); // different in 0.17.0
    try std.testing.expect(@hasDecl(Foo, "quux"));
}
Shell
$ zig test hasdecl.zig
1/1 hasdecl.test.@hasDecl example...OK
All 1 tests passed.

Allow Dereference and Coercion to Array Pointer of comptime Length Slices §允许解引用并强制转换为编译期长度切片的数组指针 §

Now allowed:现在允许:

sample_code
const slice: []const u16 = &.{ 1, 2, 3 };
const array: [3]u16 = slice.*;
const array_ptr: *const [3]u16 = slice;

void{} Syntax Removed §移除 void{} 语法 §

void{} is no longer valid syntax. Use {} instead (#15213).void{} 不再是有效语法。请改用 {} (#15213)。

errdefer Capture Removed §移除 errdefer 捕获 §

sample_code
errdefer |err| {
    // `err` was the error being returned; you could do stuff with it!
    // Like a normal `defer/`errdefer`, you can't `return` or `try` in this block, so you can't change
    // which error is returned; but you can e.g. log it
}

The capture (|err|) is no longer allowed (#23734).不再允许捕获 (|err|) (#23734)。

To migrate, split the function into two:要进行迁移,请将函数拆分为两个:

fn processOneTarget(job: Job) void {
-    errdefer |err| std.debug.panic("panic: {s}", .{@errorName(err)});
+    processOneTargetInner(job) catch |err| std.debug.panic("panic: {s}", .{@errorName(err)});
+}
+fn processOneTargetInner(job: Job) !void {
     const target = job.target;

i0 Removed §移除 i0 §

i0 is no longer an allowed primitive integer type.i0 不再是允许的原始整数类型。

This type was nonsensical, so does not have a direct alternative. However, any uses of it can almost certainly be transparently replaced with u0.此类型本身毫无意义,因此没有直接替代品。不过,其任何用法几乎肯定都可以透明地替换为 u0。

The internal and link_once tags of std.lang.GlobalLinkage have been removed as they had unclear semantics and incomplete support in codegen and linking (#36956). Any use of link_once is likely served by weak, while the replacement for internal is to simply not @export the symbol in the first place.std.lang.GlobalLinkage 的 internal 和 link_once 标签已被移除,因为它们的语义不清,且在代码生成和链接中的支持不完整 (#36956)。link_once 的任何用途很可能由 weak 代替,而 internal 的替代方案则是从一开始就不 @export 该符号。

Standard Library §标准库 §

Deprecations §弃用项 §

StackFallbackAllocator Reworked §StackFallbackAllocator 重构 §

StackFallbackAllocator is an abstraction that is useful for the "small vec" optimization, in which common cases can fit on a pre-allocated stack buffer, but rare cases need dynamic heap allocation. The previous design had a few problems:StackFallbackAllocator 是一种抽象,对于“小型向量(small vec)”优化非常有用。在这种优化中,常见情况可以放入预分配的栈缓冲区,而罕见情况则需要动态堆分配。之前的设计存在几个问题:

Now, the buffer is provided as an argument, like most other std APIs that need a buffer.现在,缓冲区作为参数提供,就像大多数其他需要缓冲区的 std API 一样。

Migration guide:迁移指南:

sample_code
var stack align(@max(
    @alignOf(std.heap.StackFallbackAllocator(0)),
    @alignOf(Item)),
) = std.heap.stackFallback(@sizeOf(Item), self.gpa);
const allocator = stack.get();

⬇️

sample_code
var stack_buf: [1]Item = undefined;
var stack: std.heap.StackFallbackAllocator = .init(@ptrCast(&stack_buf), gpa);
const allocator = stack.allocator();

SafeAllocator Introduced §引入 SafeAllocator §

std.heap.DebugAllocator is replaced by a thread-safe allocator with the following guarantees:std.heap.DebugAllocator 被一个线程安全的分配器所取代,该分配器具有以下保证:

Given the backing allocator does not reuse memory, it does not reuse memory either and most writes after free will segmentation fault or are eventually detected and panic.鉴于后备分配器不会重用内存,它也不会重用内存,并且大多数释放后的写入操作最终都会导致段错误或被检测到并触发 panic。

std.heap.DebugAllocator and std.heap.Check are deprecated.std.heap.DebugAllocator 和 std.heap.Check 已弃用。

Every allocation is trailed by an AllocFooter which contains metadata for the allocation and stack traces. It is protected by a checksum to catch corruption from allocation overwrites and report canary mismatches. An allocation's memory has a minimum alignment of AllocFooter so that the footer is at a fixed offset determined from the allocation size. An allocation's memory is stored either:每个分配后面都有一个 AllocFooter,其中包含分配的元数据和栈跟踪。它受校验和保护,以捕获由于分配覆盖导致的损坏并报告 canary 不匹配。分配的内存具有 AllocFooter 的最小对齐方式,以便页脚位于根据分配大小确定的固定偏移量处。分配的内存存储在以下位置之一:

To track allocations, each thread maintains a table of backing allocations. The table may be modified by other threads in the case of a producer-consumer operation, so the table is a linked list only expanded by creating new segments. Each thread maintains a linked list of free entries, which may contain entries from other threads' tables.为了跟踪分配,每个线程维护一个后备分配表。在生产者-消费者操作的情况下,该表可能会被其他线程修改,因此该表是一个仅通过创建新段来扩展的链表。每个线程维护一个空闲条目的链表,其中可能包含来自其他线程表的条目。

In the case of producer-consumer operations, acquire/release ordering is assumed to be provided externally. This is also assumed by all other thread-safe allocators that reuse memory as otherwise there would be data races on reuse of allocated memory.在生产者-消费者操作的情况下,假定获取/释放顺序由外部提供。所有其他重用内存的线程安全分配器也假定如此,否则在重用已分配内存时会出现数据竞争。

Two fuzz tests have also been added for the allocator. They check that there is no memory reuse, that returned memory is writable, and that it is not overwritten. The multi-threaded fuzz test spawns a number of worker threads which are used for all the test runs. I have run these tests extensively under TSAN.还为该分配器添加了两个模糊测试。它们检查是否存在内存重用、返回的内存是否可写以及是否未被覆盖。多线程模糊测试会生成多个工作线程,这些线程用于所有测试运行。我已经在 TSAN 下对这些测试进行了广泛的运行。

Building the standard library tests with an -Osafe compiler build and -Ddebug-allocator:使用 -Osafe 编译器构建和 -Ddebug-allocator 构建标准库测试:

Benchmark 1 (3 runs): ./master-out/bin/zig test --zig-lib-dir lib lib/std/std.zig -femit-bin=test --test-no-exec
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          29.4s  ±  157ms    29.2s  … 29.5s           0 ( 0%)        0%
  peak_rss           2.24GB ± 3.49MB    2.23GB … 2.24GB          0 ( 0%)        0%
  cpu_cycles          143G  ±  999M      142G  …  144G           0 ( 0%)        0%
  instructions        268G  ± 5.22M      268G  …  268G           0 ( 0%)        0%
  cache_references   13.1G  ± 88.8M     13.0G  … 13.2G           0 ( 0%)        0%
  cache_misses       2.38G  ± 30.7M     2.35G  … 2.41G           0 ( 0%)        0%
  branch_misses       634M  ± 6.22M      629M  …  641M           0 ( 0%)        0%
Benchmark 2 (3 runs): ./branch-out/bin/zig test --zig-lib-dir lib lib/std/std.zig -femit-bin=test --test-no-exec
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          22.1s  ± 88.6ms    22.0s  … 22.2s           0 ( 0%)        ⚡- 24.7% ±  1.0%
  peak_rss           1.11GB ±  799KB    1.11GB … 1.11GB          0 ( 0%)        ⚡- 50.3% ±  0.3%
  cpu_cycles          136G  ±  480M      136G  …  137G           0 ( 0%)        ⚡-  4.4% ±  1.2%
  instructions        273G  ± 2.07M      273G  …  273G           0 ( 0%)        💩+  1.6% ±  0.0%
  cache_references   12.3G  ± 71.3M     12.2G  … 12.4G           0 ( 0%)        ⚡-  6.0% ±  1.4%
  cache_misses       2.02G  ± 11.5M     2.01G  … 2.03G           0 ( 0%)        ⚡- 14.9% ±  2.2%
  branch_misses       569M  ± 2.65M      567M  …  572M           0 ( 0%)        ⚡- 10.2% ±  1.7%

ArrayList §ArrayList §

Upgrade guide:

sample_code
if (list.getLastOrNull()) |foo| {
    // ...
}
const foo = list.getLast();

⬇️

sample_code
if (list.last()) |foo| {
    // ...
}
const foo = list.last().?;

ArrayList Pointer Stability §ArrayList 指针稳定性 §

This is an enhancement that can help track down ArrayList usage bugs faster (#36239).这是一项改进,可以帮助更快地追踪 ArrayList 使用错误 (#36239)。

Devlog Entry 开发日志条目

debug.SafetyLock Gains Support for Shared Locking §debug.SafetyLock 获得对共享锁的支持 §

The existing lock and unlock methods continue to act exclusively. They should be used when data may be mutated. New methods, lockShared and unlockShared, may be used for shared locking in situations where multiple independent users are reading but not mutating data.现有的 lock 和 unlock 方法继续以独占方式运行。当数据可能被修改时,应使用它们。新的方法 lockShared 和 unlockShared 可用于在多个独立用户读取而不修改数据的情况下进行共享锁定。

fmt.allocPrint moved to mem.Allocator §fmt.allocPrint 移至 mem.Allocator §

sample_code
try std.fmt.allocPrint(arena, "{s}={d}", .{ x, y });

⬇️

sample_code
try arena.print("{s}={d}", .{ x, y });

Formatted Printing Enhancements §格式化打印增强 §

The "{q}" specifier which escapes strings so that they can appear in double-quoted string literals has relaxed escaping rules such that UTF-8 encoded data can pass through unmangled.“{q}”说明符用于转义字符串,使其能够出现在双引号字符串字面量中。其转义规则已放宽,以便 UTF-8 编码的数据可以原样通过。

"{qf}" is introduced for double-quote escaping the output of a format().引入了“{qf}”用于对 format() 的输出进行双引号转义。

std.zon.parse Reworked §std.zon.parse 重构 §

std.zon.parse now takes struct args and allocates its result from an arena.std.zon.parse 现在接收结构体参数并从 arena 分配其结果。

Migration guide:

sample_code
var diag: Diagnostics = .{};
defer diag.deinit(gpa);
const result = std.zon.fromSlice(
    MyZonType,
    gpa,
    source,
    &diag,
    .{},
) catch |err| switch (err) {
    error.ParseZon => std.process.fatal("input.zon: {f}", .{diag}),
    error.OutOfMemory => |e| return e,
};
defer std.zon.parse.free(result);

⬇️

sample_code
var diag: Diagnostics = undefined;
const result = std.zon.fromSlice(MyZonType, .{
    .gpa = gpa,
    .arena = arena,
    .source = source,
    .diagnostics = &diag,
}) catch |err| switch (err) {
    error.ParseZon => diag.fatal("input.zon"),
    error.OutOfMemory => |e| return e,
}

Some methods were renamed:一些方法被重命名:

"updateFrom" variants such as updateFromSlice were added. These update an in memory value, overwriting the value's fields with fields specified in the ZON source. This can be useful when using ZON to load configuration files with varying precedence, for example a text editor that has a global config file and a per-project config file.添加了“updateFrom”变体,例如 updateFromSlice。这些变体用于更新内存中的值,用 ZON 源中指定的字段覆盖该值的字段。当使用 ZON 加载具有不同优先级的配置文件时,这非常有用,例如具有全局配置文件和每个项目配置文件的文本编辑器。

Rename bit_set Variants and Deprecate the Managed One §重命名 bit_set 变体并弃用托管版本 §

Renames the types for consistency, deprecating the previous names and the managed variant.为了一致性重命名类型,弃用了之前的名称和托管变体。

Struct-Of-Arrays Style for std.lang.Type §std.lang.Type 的结构体数组样式 §

When doing type reflection, structs and unions return their information in struct-of-arrays style (#35234).在进行类型反射时,结构体和联合体以结构体数组样式返回其信息 (#35234)。

--- a/lib/compiler/Maker/ScannedConfig.zig
+++ b/lib/compiler/Maker/ScannedConfig.zig
@@ -49,9 +49,10 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
 }
 
 fn printStruct(sc: *const ScannedConfig, s: *Serializer.Struct, comptime S: type, v: S) !void {
-    inline for (@typeInfo(S).@"struct".fields) |field| {
-        try s.fieldPrefix(field.name);
-        try printValue(sc, s.container.serializer, field.type, @field(v, field.name));
+    const info = @typeInfo(S).@"struct";
+    inline for (info.field_names, info.field_types) |field_name, field_type| {
+        try s.fieldPrefix(field_name);
+        try printValue(sc, s.container.serializer, field_type, @field(v, field_name));
     }
 }

Rename lang.OptimizeMode to lang.Optimize §将 lang.OptimizeMode 重命名为 lang.Optimize §

And remove "release" from the enum tag names.并从枚举标签名称中移除“release”。

No functional change, however, despite the addition of backwards-compatibile declarations in this patch, it is breaking because expressions that use == or != operators will not able to use the deprecated names.没有功能性变化,但是,尽管此补丁中添加了向后兼容的声明,但它是一个破坏性更改,因为使用 == 或 != 运算符的表达式将无法使用已弃用的名称。

lang.Optimize.runtimeSafety §lang.Optimize.runtimeSafety §

std.lang.Optimize.runtimeSafety is preferred as an alternative to std.debug.runtime_safety since it will offer callsites knowledge about their own module rather than standard library module.std.lang.Optimize.runtimeSafety 是 std.debug.runtime_safety 的首选替代方案,因为它将使调用点了解其自身模块,而不是标准库模块。

@import("builtin") Deprecations §@import("builtin") 弃用项 §

The redundant constants cpu, os, abi, and object_format in @import("builtin") have been deprecated and will be removed in 0.18.0. Please replace any usage with the corresponding fields on the target constant:@import("builtin") 中冗余的常量 cpu、os、abi 和 object_format 已弃用,并将于 0.18.0 中移除。请将任何用法替换为 target 常量上的相应字段:

Handle Floats Correctly in mem.eql and mem.findDiff §在 mem.eql 和 mem.findDiff 中正确处理浮点数 §

The functions std.mem.eql and std.mem.findDiff short-circuit when their two inputs are slices to the same memory. This short-circuiting is only correct when the == operator, for the given type, is reflexive. This isn't the case for floats, as for example std.math.nan(f64) != std.math.nan(f64). The change in this PR disables that optimisation when working on float slices.当 std.mem.eql 和 std.mem.findDiff 的两个输入是同一内存的切片时,它们会短路。这种短路仅在给定类型的 == 运算符是自反时才正确。对于浮点数而言并非如此,例如 std.math.nan(f64) != std.math.nan(f64)。此 PR 中的更改在处理浮点切片时禁用了该优化。

Previously-failing, now-succeeding tests:之前失败、现在通过的测试:

sample_code
const x: [3]f64 = .{ 42.0, std.math.nan(f64), 3.1415 };
try std.testing.expect(!std.mem.eql(f64, &x, &x));
try std.testing.expectEqual(1, std.mem.findDiff(f64, &x, &x));

Decouple Uri and net.HostName §解耦 Uri 和 net.HostName §

Uri was sometimes using HostName.validate for host (in resolveInPlace) and sometimes not (in parseAfterScheme). On its own, this was a problem, but the bigger problem is that RFC3986 (Uri) has a much different idea of what a valid host name is than RFC1123 (HostName), and so just making Uri consistently use HostName.validate would make Uri less useful overall.Uri 有时对主机使用 HostName.validate(在 resolveInPlace 中),有时则不使用(在 parseAfterScheme 中)。这本身就是一个问题,但更大的问题是 RFC3986 (Uri) 对有效主机名的定义与 RFC1123 (HostName) 有很大不同,因此仅使 Uri 始终使用 HostName.validate 会使 Uri 的整体实用性降低。

Instead, all HostName-related stuff has been removed from Uri. Uri.getHost has been moved to HostName.fromUri (without a graceful deprecation, since the semantics are different enough for users to need to evaluate usage sites), while Uri.getHostAlloc has been removed entirely.相反,所有与 HostName 相关的内容都已从 Uri 中移除。Uri.getHost 已移至 HostName.fromUri(没有平滑弃用,因为语义差异太大,用户需要评估使用位置),而 Uri.getHostAlloc 已完全移除。

Migration guide:

sample_code
var host_buf: [HostName.max_len]u8 = undefined;
const host = try uri.getHost(&host_buf);

⬇️

sample_code
var host_buf: [HostName.max_len]u8 = undefined;
// note: the error set is different than it was before since fromUri does validation
const host = try HostName.fromUri(uri, &host_buf);

#36036#36036

Build System §构建系统 §

Separate the Maker Process from the Configurer Process §将构建器进程与配置器进程分离 §

zig build now runs projects' build.zig code in a separate executable than the one that performs Package Management and executes the build graph, making zig build faster for several reasons (#35428):zig build 现在在与执行包管理和执行构建图的进程不同的可执行文件中运行项目的 build.zig 代码,这使得 zig build 在多个方面更快 (#35428):

Furthermore, configuration is now serialized into a compact binary format that can be consumed by third party tooling and is part of the new Build Server Protocol. The prior way of satisfying this use case by forking the build runner is no longer supported.此外,配置现在被序列化为一种紧凑的二进制格式,可供第三方工具使用,并且是新的构建服务器协议的一部分。之前通过 fork 构建运行程序来满足此用例的方式不再受支持。

To render configuration as .zon to stdout, pass --print-configuration.要将配置渲染为 .zon 并输出到标准输出,请传递 --print-configuration。

Cache System Reworked §缓存系统重构 §

New features:新功能:

All four combinations are possible (is_directory=true/false, metadata_mode=true/false). These features are exposed as new API in the Build System.所有四种组合都是可能的(is_directory=true/false, metadata_mode=true/false)。这些功能作为构建系统中的新 API 公开。

Since the Zig toolchain is heavily reliant on the caching system, this release also switches to a binary format, saving roughly 25% on file size, which eases a bit of pressure on the file system cache while also simplifying the work the computer needs to do - directly copy bytes from disk rather than parsing text files. The new zig cache-cat subcommand is available for troubleshooting or tinkering with files inside a zig-cache directory.由于 Zig 工具链严重依赖缓存系统,此版本还切换到了二进制格式,文件大小节省了约 25%,这减轻了文件系统缓存的压力,同时也简化了计算机的工作——直接从磁盘复制字节而不是解析文本文件。新的 zig cache-cat 子命令可用于故障排除或在 zig-cache 目录内查看文件。

The cache system also now has the capability to explain why a "miss" happened. The public-facing API of std.Build.Cache has many breaking changes, but outside of compiler tooling, this is an uncommon API to be used, and all the changes make it harder to misuse.缓存系统现在还有能力解释为什么发生“未命中”。std.Build.Cache 的面向公众的 API 有许多破坏性更改,但在编译器工具之外,这是一个不常用的 API,所有这些更改都使得它更难被误用。

This change has been observed to speed up cache hits by 5-10% (#36822).据观察,此更改使缓存命中速度提高了 5-10% (#36822)。

Introduce the Concept of Configure Cache Poisoning §引入配置缓存中毒的概念 §

If the cache is poisoned means that the configure logic had side effects, or otherwise did something that could not be tracked by the cache system.如果缓存被“中毒”,意味着配置逻辑产生了副作用,或者执行了缓存系统无法跟踪的操作。

This is not to be confused with whether individual steps may have side effects when being evaluated; it has to do with the logic inside build.zig itself. For example, a Run step that prints "hello world" has side effects at make time and therefore does not warrant setting this flag, while checking for the existence of scdoc at configure time in order to choose the default value for a configuration option does.这不要与各个步骤在评估时是否可能产生副作用相混淆;它与 build.zig 本身的逻辑有关。例如,打印“hello world”的 Run 步骤在 make 时有副作用,因此不值得设置此标志,而为了选择配置选项的默认值而在配置时检查 scdoc 的存在则需要。

Keeping the cache pure will make zig build faster, bypassing the configurer process when identical configuration would be generated.保持缓存纯净将使 zig build 更快,当生成相同的配置时,可以绕过配置器进程。

When the cache is poisoned, the maker process will delete the build configuration file upon ingesting it since it cannot be reused.当缓存中毒时,构建器进程在读取构建配置文件后会将其删除,因为它无法重复使用。

Ways to poison the cache include calling findProgram, or more directly std.Build.Graph.poisonCache. A better alternative than cache poisoning is to explicitly declare the configuration dependencies with these new functions:中毒缓存的方法包括调用 findProgram,或者更直接地调用 std.Build.Graph.poisonCache。比缓存中毒更好的替代方案是使用这些新函数显式声明配置依赖项:

Advanced users can override the cache poisoning behavior with a new CLI option:高级用户可以使用新的 CLI 选项覆盖缓存中毒行为:

  --cache-poison[=mode]        Override configuration caching behavior
      pure                     (default) Avoid false positive cache hits
      poisoned                 Don't cache the configuration
      disallowed               Panics when cache would be poisoned
      ignored                  A little poison never hurt anybody

findProgram §findProgram §

Immediately (in the configure phase), searches for an executable on the host that has more than one possible name.立即(在配置阶段)搜索主机上具有多个可能名称的可执行文件。

Names are searched in order, observing search prefixes first and then PATH environment variable.按顺序搜索名称,首先观察搜索前缀,然后是 PATH 环境变量。

Calling this function poisons the configuration cache, so it is only appropriate when the existence of the program or its output needs to be observed by configuration logic. That's why there is also findProgramLazy now.调用此函数会使配置缓存中毒,因此仅在配置逻辑需要观察程序的存在或其输出时才适用。这就是现在也有 findProgramLazy 的原因。

findProgramLazy §findProgramLazy §

Creates an anonymous Step that searches for an executable on the host that has more than one possible name.创建一个匿名步骤,搜索主机上具有多个可能名称的可执行文件。

Unlike findProgram, this function does not poison the configuration cache, however the result cannot be used in the configuration phase, hence the return type being LazyPath.与 findProgram 不同,此函数不会使配置缓存中毒,但是结果不能在配置阶段使用,因此返回类型为 LazyPath。

Returns the LazyPath of the found executable. The search only takes place if the LazyPath will be used by a depending Step.返回找到的可执行文件的 LazyPath。仅当 LazyPath 将被依赖步骤使用时,才会进行搜索。

This API is useful in the following cases:此 API 在以下情况下很有用:

Run Step: Passthru Args §Run 步骤:传递参数 §

In the Run step, passthru args are all together now, not observable in configure phase whether run args are provided.在 Run 步骤中,传递参数现在都在一起,在配置阶段无法观察到是否提供了运行参数。

--- build.zig
+++ build.zig
@
-if (b.args) |args| {
-    run_cmd.addArgs(args);
-}
+run_cmd.addPassthruArgs();

This removes a capability from build scripts since they can no longer observe those arguments. In exchange, it means that when changing those arguments, build scripts no longer must be rebuilt from source.这从构建脚本中移除了一项功能,因为它们无法再观察这些参数。作为交换,这意味着在更改这些参数时,构建脚本不再需要从源代码重新构建。

Fmt Step: Options §Fmt 步骤:选项 §

paths and exclude_paths are now LazyPath lists. There is a convenience method to create them: b.pathList.paths 和 exclude_paths 现在是 LazyPath 列表。有一个创建它们的便捷方法:b.pathList。

--- build.zig
+++ build.zig
@
-    const fmt_include_paths = &.{ "lib", "src", "test", "tools", "build.zig", "build.zig.zon" };
-    const fmt_exclude_paths = &.{ "test/cases", "test/behavior/zon" };
+    const fmt_include_paths = b.pathList(&.{ "lib", "src", "test", "tools", "build.zig", "build.zig.zon" });
+    const fmt_exclude_paths = b.pathList(&.{ "test/cases", "test/behavior/zon" });

Step.Options: add addOptionPathDirectory §Step.Options: 添加 addOptionPathDirectory §

Now, when adding an option that is a file path, one must explicitly choose between (#36876):现在,在添加文件路径选项时,必须在以下选项之间做出明确选择 (#36876):

Lazy Dependency Ergonomic Enhancements §延迟依赖项人体工学增强 §

Removed Ability to Override Build Runner §移除了覆盖构建运行程序的能力 §

There is no concept of a "build runner" any more; it has been split into: configurer and maker不再有“构建运行程序”的概念;它已被拆分为:配置器和构建器

This use case is now handled by the Build Server Protocol.此用例现在由构建服务器协议处理。

Package Management §包管理 §

All package management functionality has been moved out of the Compiler and into the Build System. This includes the following sub-commands:所有包管理功能已从编译器移出并移至构建系统。这包括以下子命令:

This means that large parts of what used to be included in the compiler executable are now shipped in source form instead, including:这意味着以前包含在编译器可执行文件中的大部分内容现在以源代码形式发布,包括:

All of this functionality is now compiled in -Osafe optimization mode rather than -Ofast due to being in the compiler. When hacking on the build system itself, the environment variable ZIG_DEBUG_CMD=1 may be used to compile the build system in debug mode instead.所有这些功能现在均以 -Osafe 优化模式编译,而不是 -Ofast,因为它们位于编译器中。在对构建系统本身进行修改时,可以使用环境变量 ZIG_DEBUG_CMD=1 以调试模式编译构建系统。

Miscellaneous changes:杂项更改:

Ability to Override Package Path §覆盖包路径的能力 §

--pkg-path CLI arg and ZIG_LOCAL_PKG_DIR env var are now observed for both fetch and build commands.--pkg-path CLI 参数和 ZIG_LOCAL_PKG_DIR 环境变量现在可用于 fetch 和 build 命令。

Global vs Local Fetching §全局与本地获取 §

Now zig fetch only fetches into the global cache, just like it used to. However, if --save (or any variant) is used, then it also fetches into the local package path. When fetching globally, does not require build.zig to be present. zig build always fetches locally (in addition to globally).现在 zig fetch 仅获取到全局缓存,就像以前一样。但是,如果使用了 --save(或其任何变体),它也会获取到本地包路径。全局获取时,不需要 build.zig 存在。zig build 总是进行本地获取(除了全局获取之外)。

Notably, this fixes the regressed use case zig fetch .值得注意的是,这修复了 zig fetch . 的回归用例。

When fetching by path, the hash is always computed, recompressed tarball is always created, always overwrites any existing global cache entry.通过路径获取时,总是计算哈希,总是创建重新压缩的 tarball,并且总是覆盖任何现有的全局缓存条目。

Slight Difference in PATH for DLL Arguments §DLL 参数的 PATH 略有不同 §

It used to be the case that, when targeting Windows or Wine, artifact args added to Run steps modified PATH based on the set of directories containing the recursive set of DLL dependencies. Now this is only done for argv[0]. The motivation for also doing this for the other command line arguments is unclear, since those DLLs don't need to be loaded in order to execute argv[0].过去,在针对 Windows 或 Wine 时,添加到 Run 步骤的工件参数会根据包含递归 DLL 依赖项集的目录集修改 PATH。现在这仅针对 argv[0] 执行。对其他命令行参数也这样做动机尚不清楚,因为这些 DLL 不需要为了执行 argv[0] 而加载。

Build Server Protocol §构建服务器协议 §

Now, when --listen=- is passed, the build system serves a protocol that allows connected clients to monitor and control the build graph as it executes. This is intended to be consumed by third-party tooling such as IDEs.现在,当传递 --listen=- 时,构建系统会提供一种协议,允许连接的客户端在构建图执行时对其进行监控和控制。这旨在供 IDE 等第三方工具使用。

Current things you can do:当前您可以执行的操作:

In particular, the separation of maker process and configurer process is a breaking change that prevents the ZLS project from working with 0.17.0. Although some progress was made to restore functionality in this release cycle, Zig team and ZLS team are still working together to enhance the build server protocol further to the point that ZLS can not only restore functionality, but surpass the power and capabilities compared to before.特别是,构建器进程和配置器进程的分离是一个破坏性更改,导致 ZLS 项目无法与 0.17.0 一起使用。尽管在此发布周期中在恢复功能方面取得了一些进展,但 Zig 团队和 ZLS 团队仍在共同努力进一步增强构建服务器协议,以使 ZLS 不仅能恢复功能,还能超越以前的能力和功能。

In the future it is expected for much of Zig's own first-party build system tooling to become a client of the build server protocol, dogfooding it to ensure that third-party tooling enjoys equivalent capabilities (#36497).未来,Zig 自己的第一方构建系统工具预计将成为构建服务器协议的客户端,通过“狗粮”测试确保第三方工具享有同等的功能 (#36497)。

It is also planned for the build server to multiplex compiler server protocol for the compilation steps, providing type-system information, refactoring, and other advanced editing capabilities (#615).还计划让构建服务器为编译步骤复用编译器服务器协议,提供类型系统信息、重构和其他高级编辑功能 (#615)。

Compiler §编译器 §

Incremental Compilation §增量编译 §

The Zig compiler's implementation of incremental compilation—a feature allowing near-instant rebuilds of projects after changing the code—has been significantly improved in Zig 0.17.0. Many bugs have been fixed, and the new ELF Linker introduced in the previous release has gained good support for the feature.Zig 编译器对增量编译的实现——一项允许在更改代码后近乎即时重建项目的功能——在 Zig 0.17.0 中得到了显著改进。许多错误已得到修复,上一版本中引入的新 ELF 链接器已获得了对该功能的良好支持。

Thanks to these enhancements, it is now possible for most projects targeting x86_64-linux to take advantage of incremental compilation. To do so, add the arguments -fincremental --watch to your zig build command (e.g. zig build -fincremental --watch)—this will cause the Zig build system to listen for changes to source files, and react to them by performing an incremental rebuild.得益于这些增强功能,大多数针对 x86_64-linux 的项目现在都可以利用增量编译。为此,请将参数 -fincremental --watch 添加到您的 zig build 命令中(例如 zig build -fincremental --watch)——这将使 Zig 构建系统监听源代码的更改,并通过执行增量重建来响应它们。

For more information on ways to use incremental compilation in your own projects, or to learn more about how this feature works under the hood, consider checking out this blog post by a Zig core team member.有关在您自己的项目中使用增量编译的方法的更多信息,或了解有关此功能在底层如何工作的更多信息,请考虑查看 Zig 核心团队成员的这篇博客文章。

Future releases will continue to focus on improving this feature, including introducing a new Mach-O linker and self-hosted aarch64 Backend with good support for incremental compilation; adding support for using incremental compilation without --watch; and fixing any remaining bugs.未来的版本将继续专注于改进此功能,包括引入新的 Mach-O 链接器和具有良好增量编译支持的自托管 aarch64 后端;添加在没有 --watch 的情况下使用增量编译的支持;以及修复任何剩余的错误。

SPIR-V Backend §SPIR-V 后端 §

The self-hosted SPIR-V backend is now multi-threaded like the other backends.自托管 SPIR-V 后端现在像其他后端一样是多线程的。

Execution modes such as LocalSize and OriginUpperLeft are now derived from the function's calling convention instead of being set through inline assembly, and the new spirv_task and spirv_mesh calling conventions add support for task and mesh shaders (#35676).LocalSize 和 OriginUpperLeft 等执行模式现在从函数的调用约定中派生,而不是通过内联汇编设置,新的 spirv_task 和 spirv_mesh 调用约定增加了对任务和网格着色器的支持 (#35676)。

Declaring capabilities and extensions in inline assembly with OpCapability and OpExtension is no longer allowed. They are enabled through target CPU features instead, i.e. the -mcpu option.不再允许在内联汇编中使用 OpCapability 和 OpExtension 声明功能和扩展。它们改为通过目标 CPU 功能(即 -mcpu 选项)启用。

22 bugs were fixed in the SPIR-V backend during this release cycle.在此发布周期中,SPIR-V 后端修复了 22 个错误。

aarch64 Backend §aarch64 后端 §

Progress towards this is blocked on Linker enhancements, many of which were completed during this release cycle.此方面的进展受限于链接器(Linker)的增强,其中许多增强功能已在本发布周期内完成。

loongarch Backend §loongarch 后端 §

Initial implementation of self-hosted backend for loongarch64 has been contributed (#36418). It is still experimental and not yet usable. There are two ways to contribute to this backend: working on it directly, and contributing to AIR Legalization Features, which helps all unfinished backends reach the finish line quicker.loongarch64 自托管后端的初步实现已获贡献(#36418)。它目前仍处于实验阶段,尚不可用。可以通过两种方式为该后端做出贡献:直接参与开发,或为 AIR 合法化功能(AIR Legalization Features)做出贡献,这将有助于所有未完成的后端更快地完成。

WebAssembly Backend §WebAssembly 后端 §

Zig's WebAssembly backend is now passing 2060/2054 (100%) behavior tests compared to the LLVM backend. However, it is not yet the default when compiling in debug optimization mode due to lack of debug info support (#37032).Zig 的 WebAssembly 后端在行为测试中已达到 2060/2054(100%)的通过率,与 LLVM 后端持平。然而,由于缺乏调试信息支持(#37032),它在调试优化模式下编译时仍不是默认选项。

Linker §链接器 §

ELF §ELF §

This release makes significant progress towards replacing Zig's legacy self-hosted ELF linker with its new implementation introduced in the previous release. Specific enhancements include:本版本在用上一版本引入的新实现替换 Zig 传统的自托管 ELF 链接器方面取得了重大进展。具体增强功能包括:

While this linker has not quite reached feature parity with our old self-hosted ELF linker yet—and so remains disabled by default—it is already capable in practice of building the vast majority of Zig projects targeting x86_64-linux. This unlocks the ability to use Incremental Compilation for these projects—like in Zig 0.16.0, the new linker is enabled by default in this case.虽然此链接器尚未完全达到我们旧版自托管 ELF 链接器的功能对等水平——因此默认仍处于禁用状态——但它在实践中已经能够构建绝大多数针对 x86_64-linux 的 Zig 项目。这解锁了为这些项目使用增量编译的能力——就像在 Zig 0.16.0 中一样,在这种情况下,新链接器是默认启用的。

In the next release of Zig, we hope to fully eliminate the legacy ELF linker in favour of this implementation.在 Zig 的下一个版本中,我们希望彻底淘汰旧版 ELF 链接器,全面转向此实现。

COFF §COFF §

COFF support in the linker is enhanced with the following features (#35674):链接器中的 COFF 支持通过以下功能得到了增强(#35674):

New Linker Testing Framework §新的链接器测试框架 §

Zig is moving towards snapshot-based testing for its linkers.Zig 正在转向基于快照的链接器测试。

Tests are a combination of comparing objdump snapshot output, actually running the artifacts, and checking for linker errors.测试方式结合了比较 objdump 快照输出、实际运行构建产物以及检查链接器错误。

zig build -Dlink-snapshot-update causes tests to run in a mode that outputs snapshots instead of checking against them.使用 zig build -Dlink-snapshot-update 可以使测试以输出快照而非校验快照的模式运行。

A typical workflow for adding a new test:添加新测试的典型工作流程:

  1. Add the test添加测试
  2. zig-debug build test-link -Dtest-filter=my-test -Dlink-snapshot-update
    • This will output a .dmp file for all the snapshot combinations defined in any verifyObjdump calls.这将为任何 verifyObjdump 调用中定义的快照组合输出一个 .dmp 文件。
    • A single snapshot intentionally aliases between many targets to reduce noise in the snapshot folder, so snapshot updates are made by whichever test runs first for that snapshot name. If differences between targets do exist, they will be revealed in step 4.单个快照会有意在多个目标之间建立别名,以减少快照文件夹中的冗余信息,因此快照更新由该快照名称对应的首个运行的测试完成。如果目标之间确实存在差异,这些差异将在第 4 步中显现出来。
  3. Inspect the snapshot output for correctness.检查快照输出的正确性。
  4. zig-debug build test-link -Dtest-filter=my-test
    • This will now run all targets against the newly added snapshots现在将针对新添加的快照运行所有目标。
  5. If there are now snapshot failures, that means different targets had different snapshot outputs. The output should be inspected to see if these results are indeed valid differences. If they are, then the scope parameter should be used to cause -Dlink-snapshot-update to output snapshot to different filenames, scoped on the diference.如果此时出现快照失败,则意味着不同的目标产生了不同的快照输出。应检查输出以确认这些结果是否确实是有效的差异。如果是,则应使用 scope 参数,使 -Dlink-snapshot-update 根据差异将快照输出到不同的文件名中。
  6. Re-run -Dlink-snapshot-update to update the new set of snapshots.重新运行 -Dlink-snapshot-update 以更新新的快照集合。

SPIR-V §SPIR-V §

The SPIR-V linker has been rewritten (#36828). It now supports incremental compilation and can link external .spv object files.SPIR-V 链接器已重写(#36828)。它现在支持增量编译,并可以链接外部 .spv 对象文件。

Fuzzer §模糊测试器(Fuzzer) §

Although this release's Build System changes are loosely related to Zig's integrated fuzzer and its interaction with the build system, no changes were made to the fuzzer itself.尽管本版本的构建系统变更与 Zig 的集成模糊测试器及其与构建系统的交互有松散联系,但模糊测试器本身并未进行任何更改。

We expect to focus on improving the fuzzer in a future release cycle.我们预计在未来的发布周期中重点改进模糊测试器。

Bug Fixes §Bug 修复 §

Full list of the 329 bug reports closed during this release cycle:本发布周期内关闭的 329 个 Bug 报告完整列表:

Many bugs were both introduced and resolved within this release cycle. Most bug fixes are omitted from these release notes for the sake of brevity.许多 Bug 在本发布周期内被引入并解决。为简洁起见,大多数 Bug 修复未列入这些发布说明中。

This Release Contains Bugs §此版本包含 Bug §

Zig has known bugs, miscompilations, and regressions. Zig 存在已知的 Bug、错误编译和回归问题。

Even with Zig 0.17.x, working on a non-trivial project using Zig may require participating in the development process.即使在 Zig 0.17.x 中,使用 Zig 进行非平凡项目开发也可能需要参与到开发流程中。

When Zig reaches 1.0.0, Tier 1 support will gain a bug policy as an additional requirement.当 Zig 达到 1.0.0 时,一级支持(Tier 1 support)将增加一项 Bug 策略作为额外要求。

Notable Regressions §显著回归 §

We are aware of these notable regressions in 0.17.0:我们已知 0.17.0 中存在以下显著回归问题:

Toolchain §工具链 §

LLVM 22 §LLVM 22 §

This release of Zig upgrades to LLVM 22.1.8. This covers Clang (zig cc), libc++, libc++abi, libunwind, and libtsan as well.此版本的 Zig 升级到了 LLVM 22.1.8。这也涵盖了 Clang (zig cc)、libc++、libc++abi、libunwind 和 libtsan。

Loop Vectorization Disabled to Work Around Regression §禁用循环向量化以规避回归问题 §

In the previous release of Zig, we were forced to disable a key LLVM optimization pass—loop vectorization—to work around a miscompilation which affected the Zig compiler.在 Zig 的上一个版本中,我们被迫禁用了关键的 LLVM 优化通道——循环向量化——以规避影响 Zig 编译器的错误编译问题。

Since we first introduced that workaround, a fix has been merged into LLVM's main branch. However, the fix is not available in LLVM 22, the LLVM version used by Zig 0.17.0. Therefore, this workaround remains enabled for now.自我们首次引入该规避措施以来,LLVM 主分支已合并了修复程序。然而,该修复在 Zig 0.17.0 使用的 LLVM 22 版本中不可用。因此,该规避措施目前仍然保留。

Zig 0.18.0 will upgrade to LLVM 23, so will allow us to re-enable this optimization pass.Zig 0.18.0 将升级到 LLVM 23,届时我们将能够重新启用此优化通道。

musl 1.2.5 §musl 1.2.5 §

Zig 0.17.0 distributes musl 1.2.5 plus backported security and portability fixes. Meanwhile, upstream has tagged 1.2.6. Zig 0.18.0 will update to musl 1.2.6.Zig 0.17.0 分发了 musl 1.2.5 以及向后移植的安全性和可移植性修复。同时,上游已标记 1.2.6。Zig 0.18.0 将更新至 musl 1.2.6。

When targeting musl statically, many functions are now provided by zig libc rather than source files copied from musl. Therefore, if you encounter bugs with musl libc provided by Zig, please respect upstream by reporting them to Zig's issue tracker rather than musl's.当目标为静态 musl 时,许多函数现在由 zig libc 而非从 musl 复制的源文件提供。因此,如果您在使用 Zig 提供的 musl libc 时遇到 Bug,请尊重上游,向 Zig 的问题追踪器而非 musl 的问题追踪器报告。

glibc 2.44 §glibc 2.44 §

glibc version 2.44 is now available when cross-compiling.交叉编译时现已支持 glibc 2.44 版本。

Linux 7.2 Headers §Linux 7.2 头文件 §

This release includes Linux kernel headers for version 7.2.此版本包含 7.2 版本的 Linux 内核头文件。

macOS 27.0 Headers §macOS 27.0 头文件 §

This release includes macOS system headers for version 27.0.此版本包含 27.0 版本的 macOS 系统头文件。

MinGW-w64 §MinGW-w64 §

Zig 0.17.distributes MinGW-w64 commit 31bd54ab7d5fe03c67ed2bb1a57e531b9c7f8cc4.Zig 0.17 分发了 MinGW-w64 提交 31bd54ab7d5fe03c67ed2bb1a57e531b9c7f8cc4。

However, many functions are now provided by zig libc rather than source files copied from MinGW-w64. Therefore, if you encounter bugs with MinGW-w64 libc provided by Zig, please respect upstream by reporting them to Zig's issue tracker rather than MinGW-w64's.然而,许多函数现在由 zig libc 而非从 MinGW-w64 复制的源文件提供。因此,如果您在使用 Zig 提供的 MinGW-w64 libc 时遇到 Bug,请尊重上游,向 Zig 的问题追踪器而非 MinGW-w64 的问题追踪器报告。

NetBSD 11.0 libc §NetBSD 11.0 libc §

NetBSD libc version 11.0 is now available when cross-compiling.交叉编译时现已支持 NetBSD libc 11.0 版本。

OpenBSD 7.9 libc §OpenBSD 7.9 libc §

OpenBSD libc version 7.9 is now available when cross-compiling.交叉编译时现已支持 OpenBSD libc 7.9 版本。

WASI libc §WASI libc §

Zig 0.17.0 continues to distribute WASI libc commit c89896107d7b57aef69dcadede47409ee4f702ee.Zig 0.17.0 继续分发 WASI libc 提交 c89896107d7b57aef69dcadede47409ee4f702ee。

However, many functions are now provided by zig libc rather than source files copied from WASI libc.然而,许多函数现在由 zig libc 而非从 WASI libc 复制的源文件提供。

Furthermore, starting with Zig 0.18.0, instead of distributing third party WASI libc code, Zig will provide libc for WASI targets via zig libc. For more information, see:此外,从 Zig 0.18.0 开始,Zig 将通过 zig libc 为 WASI 目标提供 libc,而不是分发第三方 WASI libc 代码。更多信息,请参阅:

zig libc §zig libc §

In libc.txt files, the gcc_dir field has been renamed to cc_dir to reflect the reality that it is not specific to GCC. The old name will still be accepted for now, but users are encouraged to migrate their libc.txt to the new name (#36951).在 libc.txt 文件中,gcc_dir 字段已重命名为 cc_dir,以反映它并非特定于 GCC 的事实。旧名称目前仍可接受,但建议用户将其 libc.txt 迁移至新名称(#36951)。

Additionally, cc_dir is now required on Linux targets. Note that, because Android and OpenHarmony store the relevant object files in an unusual location, users of these targets will likely want to set cc_dir to the same path as crt_dir.此外,Linux 目标现在必须使用 cc_dir。请注意,由于 Android 和 OpenHarmony 将相关对象文件存储在非常规位置,这些目标的用户可能需要将 cc_dir 设置为与 crt_dir 相同的路径。

zig cc §zig cc §

zig cc and zig c++ are now based on Clang 22.1.8.zig cc 和 zig c++ 现在基于 Clang 22.1.8。

zig objdump §zig objdump §

This was a requirement for snapshot testing, as well as aiding in developing the COFF Linker.这是快照测试的一项要求,也有助于 COFF 链接器的开发。

Supported features:支持的功能:

Usage: zig objdump [options] file

Options:
  -h, --help                         Print this help and exit
  --all-headers                      Alias for --file-headers --linker-member=2 --member-headers --section-headers --relocs --symbols
  --exports[=sort]                   Display exported symbols.
                                     In the case of COFF import libraries, displays the symbol list and import headers.
                                     Specify =sort to optionally sort the import headers by symbol name.
  --file-headers                     Display file-format specific headers
  --imports                          Display imported symbols
  --linker-member[=1|2|longnames]    (Coff) Display contents of the specified archive linker member (default 2)
  --member-headers                   Display archive member headers
  --elements=[e1],[e2],-[e3],...     Select which formatting elements are displayed. Intended for snapshot testing.
      file-type                      File type summary
      header-name                    Name that precedes a header block
      member-path                    Display full member paths. If removed, only basenames will be used.
      newlines                       Newlines between output sections
      table-header                   Table headers with column names
      all                            (default) All of the above
  --only-member=[name]               Only consider archive members names that contain [name]. Can be specified multiple times.
  --only-section=[name]              Only consider section names that contain [name]. Can be specified multiple times.
  --only-symbol=[name]               Only consider symbol names that contain [name]. Can be specified multiple times.
  --redact=[kind]                    Redact the specified field kind. Intended for snapshot testing.
      rva                            Relative virtual addresses
      va                             Virtual addresses and file offsets
      ord                            Symbol ordinals / hints
      size                           Sizes and lengths
      all                            All of the above
  --relocs                           Display relocations
  -s, --snapshot                     Alias for --redact=all --elements=-all
  --section-headers                  Display section headers
  --strings                          Display string tables
  --symbols                          Display symbol tables
  --tls                              Display TLS information

Some example output:一些示例输出:

❯ zig objdump mathtest-dync-exe-no-llvm.dll --all-headers
mathtest-dync-exe-no-llvm.dll: PE/COFF image


COFF Header:
            8664 machine (AMD64)
               7 number_of_sections
        6a08670a time_date_stamp
               0 pointer_to_symbol_table
               0 number_of_symbols
              f0 size_of_optional_header
            2022 flags
               | EXECUTABLE_IMAGE
               | LARGE_ADDRESS_AWARE
               | DLL

COFF Optional Header:
             20b magic (PE32+)
           14.00 linker_version
          14a400 size_of_code
           84e00 size_of_initialized_data
               0 size_of_uninitialized_data
            1000 address_of_entry_point (       180001000)
            1000 base_of_code (       180001000)
       180000000 image_base
            1000 section_alignment
             200 file_alignment
            6.00 operating_system_version
            1.00 image_version
            6.00 subsystem_version
               0 win32_version_value
          1d6000 size_of_image
             400 size_of_headers
               0 checksum
               2 subsystem (WINDOWS_GUI)
             160 dll_flags
               | HIGH_ENTROPY_VA
               | DYNAMIC_BASE
               | NX_COMPAT
          100000 size_of_stack_reserve
            1000 size_of_stack_commit
          100000 size_of_heap_reserve
            1000 size_of_heap_commit
               0 loader_flags
              10 number_of_rva_and_sizes

Data Directories:
          1b48d0       54 EXPORT
          1b4924       8c IMPORT
               0        0 RESOURCE
          1cc000     633c EXCEPTION
               0        0 SECURITY
          1d4000     1280 BASERELOC
          1bc000       1c DEBUG
               0        0 ARCHITECTURE
               0        0 GLOBALPTR
          1aebc8       28 TLS
               0        0 LOAD_CONFIG
               0        0 BOUND_IMPORT
          1b4c80      2d0 IAT
               0        0 DELAY_IMPORT
               0        0 COM_DESCRIPTOR
               0        0 RESERVED

Sections in 'mathtest-dync-exe-no-llvm.dll':
Num Name          RVA Virt Size Data Size   & Data & Relocs  & Lines # Relocs  # Lines    Flags
  1 .text        1000    14a346    14a400      400        0        0    0    0 60000020 | CNT_CODE MEM_EXECUTE MEM_READ
  2 .rdata     14c000     6fe3c     70000   14a800        0        0    0    0 40000040 | CNT_INITIALIZED_DATA MEM_READ
  3 .buildid   1bc000        52       200   1ba800        0        0    0    0 40000040 | CNT_INITIALIZED_DATA MEM_READ
  4 .data      1bd000      e2a0      d200   1baa00        0        0    0    0 c0000040 | CNT_INITIALIZED_DATA MEM_READ MEM_WRITE
  5 .pdata     1cc000      633c      6400   1c7c00        0        0    0    0 40000040 | CNT_INITIALIZED_DATA MEM_READ
  6 .tls       1d3000        20       200   1ce000        0        0    0    0 c0000040 | CNT_INITIALIZED_DATA MEM_READ MEM_WRITE
  7 .reloc     1d4000      1280      1400   1ce200        0        0    0    0 42000040 | CNT_INITIALIZED_DATA MEM_DISCARDABLE MEM_READ

No symbol table found

If this output was used for a snapshot test that wanted to test the presence of a particular export:如果此输出用于测试特定导出项是否存在快照测试:

❯ zig objdump mathtest-dync-exe-no-llvm.dll --exports --only-symbol=add --redact=rva --elements=-all
Export directory:
               0 flags
               0 time_date_stamp
            0.00 version
xxxxxxxxxxxxxxxx name_rva
               1 ordinal_base
               1 number_of_entries
               1 number_of_names
xxxxxxxxxxxxxxxx export_address_table_rva
xxxxxxxxxxxxxxxx name_pointer_table_rva
xxxxxxxxxxxxxxxx ordinal_table_rva
   1    0 xxxxxxxx | add

The redaction (--redact=) and element removal (--elements=) functionality is used to remove parts of the output that don't matter for the particular test, as to not cause spurious failures if say, an RVA for a symbol changes due to some unrelated change to the linker. -s is shorthand which enables all the redacts and removes all extra output elements, but particular tests may not use this if they do care about specific values.编辑(--redact=)和元素移除(--elements=)功能用于移除对特定测试不重要的输出部分,以避免因链接器无关更改导致符号 RVA 变化而引发虚假失败。-s 是一个缩写,它会启用所有编辑并移除所有额外的输出元素,但特定测试如果关心特定值,可能不会使用它。

resinator §resinator §

Windows Resource Compilation Moving to an External Package §Windows 资源编译移至外部包 §

Windows resource script compilation will be moved out of the compiler and into an official-but-external build system package in the next release. As such, the corresponding std.Build functions and fields (Build.Module.addWin32ResourceFile, etc) have been marked as deprecated in this release.Windows 资源脚本编译将在下一个版本中从编译器中移除,并移入一个官方但外部的构建系统包中。因此,相应的 std.Build 函数和字段(Build.Module.addWin32ResourceFile 等)在本版本中已被标记为弃用。

The zig rc subcommand will remain after this change in order to continue supporting the use case of using the Zig toolchain with other build systems.zig rc 子命令在此变更后将保留,以便继续支持将 Zig 工具链与其他构建系统结合使用的场景。

zig fmt §zig fmt §

Added --complexity Flag §新增 --complexity 标志 §

It's a simple tool for counting tokens and AST nodes, which can be used to share how an edit to a source file increases or reduces complexity with a heuristic that is more insightful than line count.这是一个用于统计标记(token)和 AST 节点的简单工具,可用于分享对源文件的编辑如何增加或减少复杂度,其启发式方法比单纯的行数统计更具洞察力。

For example, running it on old ELF linker directory:例如,在旧版 ELF 链接器目录上运行该工具:

info: src/link/Elf/gc.zig: tokens=1538 nodes=770
info: src/link/Elf/Atom.zig: tokens=15576 nodes=7768
info: src/link/Elf/Merge.zig: tokens=2288 nodes=1092
info: src/link/Elf/Thunk.zig: tokens=1128 nodes=519
info: src/link/Elf/SharedObject.zig: tokens=4566 nodes=2236
info: src/link/Elf/eh_frame.zig: tokens=4840 nodes=2335
info: src/link/Elf/Symbol.zig: tokens=3770 nodes=1872
info: src/link/Elf/synthetic_sections.zig: tokens=13287 nodes=6375
info: src/link/Elf/Object.zig: tokens=13903 nodes=6842
info: src/link/Elf/LinkerDefined.zig: tokens=4140 nodes=2091
info: src/link/Elf/relocatable.zig: tokens=3598 nodes=1848
info: src/link/Elf/Archive.zig: tokens=2176 nodes=1028
info: src/link/Elf/ZigObject.zig: tokens=20783 nodes=10274
info: src/link/Elf/AtomList.zig: tokens=1819 nodes=933
info: src/link/Elf/relocation.zig: tokens=1289 nodes=551
info: src/link/Elf/file.zig: tokens=2330 nodes=1087
info: total: tokens=97031 nodes=47621

Another example is after editing Lld.zig to use arena.print rather than std.fmt.allocPrint. The line count is roughly the same but --complexity tells a different story:另一个例子是在编辑 Lld.zig 以使用 arena.print 而非 std.fmt.allocPrint 之后。行数大致相同,但 --complexity 给出了不同的结果:

In the future this metric may be helpful for an automatic import organizer to determine whether to create an import alias or not. 未来,此指标可能有助于自动导入整理器确定是否创建导入别名。

Roadmap §路线图 §

  1. Work with ZLS team to enhance Build Server Protocol to the point where satisfies all their use cases.与 ZLS 团队合作,增强构建服务器协议(Build Server Protocol),直至满足其所有使用场景。
  2. Complete Windows support in the x86_64 backend so that it can be enabled by default.完成 x86_64 后端的 Windows 支持,以便将其设为默认。
  3. Complete and stabilize the language.完成并稳定语言特性。
  4. Complete the aarch64 Backend and make it the default backend for debug mode.完成 aarch64 后端,并将其设为调试模式的默认后端。
  5. Enhance the Linker implementations, eliminating dependency on LLD and support Incremental Compilation.增强链接器实现,消除对 LLD 的依赖并支持增量编译。
  6. Enhance the integrated Fuzzer to be competitive with AFL and other state-of-the-art fuzzers.增强集成模糊测试器,使其能够与 AFL 及其他先进的模糊测试器竞争。
  7. Transition from a library dependency on LLVM to a process dependency on Clang (#16270).从对 LLVM 的库依赖过渡到对 Clang 的进程依赖(#16270)。
  8. Complete the Build System, in particular Package Management features.完成构建系统,特别是包管理功能。
  9. Audit the Standard Library (#1629).审计标准库(#1629)。

Thank You Contributors! §感谢贡献者! §

Ziggy the Ziguana

Here are all the people who landed at least one contribution into this release:以下是为本版本做出至少一次贡献的所有人员:

Thank You Sponsors! §感谢赞助者! §

Ziggy the Ziguana

Special thanks to those who sponsor Zig. Because of diverse, recurring donations, Zig is driven by the open source community, rather than the goal of making profit. In particular, those below sponsored Zig for an average of $50/month or more during this release cycle using our preferred donation platform: 特别感谢那些赞助 Zig 的人们。 得益于多元且持续的捐赠,Zig 由开源社区驱动,而非以营利为目的。特别感谢以下在本次发布周期内,通过我们首选的捐赠平台平均每月赞助 50 美元或以上的赞助者:

Special thanks also to TigerBeetle, Synadia Communications, and ZML for substantial contributions.此外,还要特别感谢 TigerBeetle、Synadia Communications 和 ZML 所做出的重大贡献。