Zig v0.17.0

Hacker News by 54 min read 28x views
Zig v0.17.0

Share Post

Carmen the Allocgator

Download & Documentation

Zig is a general-purpose programming tongue and toolchain for maintaining robust, optimal, and reusable software.

Zig betterment is funded via Zig Software Foundation, a 501(c)(3) non-profit organization. Please regard a recurring donation so that we can recommendation additional billable hours to our center squad members. This is the most straightforward way to accelerate the project alongside the Roadmap to 1.0. If you need donation receipts or are looking to migrate distant from GitHub Sponsors, we recommend donating via Every.org.

This publish features 5 months of work: changes from 206 different contributors, dispersed among 925 commits.

Originally predicted to be shorter, this publish sequence ended up substantial, with the Build System reworked, including the introduction of the Build Server Protocol, and the ELF Linker enhanced to the item anywhere we anticipate Incremental Compilation to activity for everyone on x86_64-linux.

Table of Contents §

Target Support §

Zero the Ziguana

Zig supports a broad range of architectures and functioning systems. The Support Table and Additional Platforms sections cover the targets that Zig can build programs for, during the zig-bootstrap README covers the targets that the Zig Compiler itself can be easily cross-compiled to run on.

Notable changes:

  • aarch64-openbsd is now tested natively in Zig's CI, ensuring high-quality assistance going forward.
  • aarch64-freebsd and aarch64-netbsd CI jobs now run on pull requests too, in supplement to expert pushes.
  • An LLVM bug that broke most aarch64-windows binaries, including the Zig Compiler, has been worked around.
  • The Zig Compiler now applies mandatory code hardening techniques whenever targeting aarch64-openbsd so that the resulting binaries really work.
  • Zig now provides stack traces on crashes and unsuccessful assertions on 32-bit ARM. Some work still remains for Thumb-only targets.
  • Zig now provides stack traces on crashes and unsuccessful assertions on SPARC.
  • Zig now handles pointer authentication opcodes whenever doing stack unwinding on AArch64.
  • Support for the loongarch32-linux-gnu[sf] targets has been added.
  • Zig now has mostly usable assistance for 64-bit SPARC, and especially sparc64-linux. This is mostly gratitude to Zig's new ELF linker which now has better assistance for this mark than LLD.
  • The Zig Standard Library has been ported to the x32 and N32 ABIs on x86-64 and 64-bit MIPS, respectively. These are niche ILP32 ABIs that authorize using the 64-bit education set during lone having 32-bit pointers - the idea being to commerce accessible location area for lower recollection use and improved cache utilization.
  • Target data has been added for several equivalent consoles: aarch64-switch, arm-gba, mipsel-psx, and powerpc-wiiu
  • Very first xtensa-linux assistance has been added to Zig. Note that, for now, this assistance can lone be exercised via the C backend or the experimental LLVM backend.
  • The Zig Standard Library now has assistance for arc[eb]-linux, csky-linux, and m88k-openbsd whenever using the C backend.
  • The Zig Standard Library now has assistance for no-libc microblaze[el]-linux, sh[eb]-linux, and sparc-linux.
  • Zig now enforces -mabi=ieeelongdouble for all PowerPC targets. This is fair a formalization of what was already reality; Zig has never supported the IBM "double-double" format for lengthy twice and apt never will. As a result, this publish drops assistance for powerpc-linux-gnueabi[hf] since glibc lone supports the "double-double" format on these targets. The powerpc-linux-musleabi[hf] targets remain supported as they use the IEEE format.
  • This publish drops assistance for powerpc64-linux-gnu. Zig has lone ever supported linking ELFv2 binaries for 64-bit PowerPC, and glibc does not officially support ELFv2 on big endian - nor IEEE lengthy double, as above.
  • Zig's capability to detect the native CPU example and features has been greatly enhanced across the board; this affects nearly all architecture on all supported OS.
  • The baseline CPU example has been changed for several targets:
    • aarch64-haiku: cortex_a55
    • m68k-*: M68030
    • mips64-openbsd: octeon
    • powerpc-netbsd: 750
    • powerpc64-freebsd: pwr8
    • powerpc64-linux: pwr8
    • powerpc64-openbsd: pwr9
    • s390x-*: arch11
    • sparc-*: generic
    • sparc-linux: v9
    • sparc64-*: ultrasparc
    • xtensa-*: esp32
  • In Zig's mark query syntax, native libc type finding now lone happens if the triple really uses native libc (i.e. the ABI component is omitted). We anticipate this new behavior to improved equivalent people's mental example for how mark queries work, particularly whenever considering how the OS component works.

Tier System §

Zig's flat of assistance for assorted targets is broadly categorized into four tiers alongside Tier 1 being the highest. The goal is for Tier 1 targets to have zero impaired tests - this volition rotate into a necessity for post-1.0.0 Zig releases.

Tier 1 §

  • All non-experimental language features are known to activity correctly.
  • The Compiler can create device code for this mark without relying on LLVM.
  • The unified fuzzer plant on this mark (if applicable).

Tier 2 §

  • The Standard Library cross-platform abstractions have implementations for this target.
  • Failed assertions and crashes create stack traces on this target.
  • libc is accessible for this mark equal whenever cross-compiling (if applicable).
  • Continuous integration machines build the component tests for this mark on all push.

Tier 3 §

  • The Compiler can create device code for this mark by relying on an external backend specified as LLVM.
  • The Linker can create entity files, libraries, and executables for this target.

Tier 4 §

  • The Compiler can create gathering or C origin code for this target.

Support Table §

In the following table, ✅ indicates complete support, ❌ indicates no support, and ⚠️ indicates that there is partial support, e.g. lone for some sub-targets, or alongside several notable known issues. ❔ indicates that the position is mostly unknown, typically since the mark is rarely exercised. Hover complete another icons for details.

Targets marked alongside 🪦 are obsolescent; the Zig compiler and standard archive keep best-effort assistance for them, but that assistance is expected to be removed eventually.

OS Version Requirements §

The Zig norm archive has minimum type requirements for some supported functioning systems, which in rotate power the Zig compiler itself:

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 additionally has varying levels of assistance for these targets, for which the tier scheme does not fairly apply:

  • aarch64-driverkit
  • aarch64[_be]-freestanding
  • aarch64-fuchsia
  • aarch64-hurd
  • aarch64-switch
  • aarch64-uefi
  • alpha-freestanding
  • amdgcn-amdhsa
  • amdgcn-amdpal
  • amdgcn-mesa3d
  • arc[eb]-freestanding
  • arm[eb]-freestanding
  • arm-3ds
  • arm-fuchsia
  • arm-gba
  • arm-uefi
  • arm-vita
  • avr-freestanding
  • bpf(eb,el)-freestanding
  • csky-freestanding
  • ez80-freestanding
  • ez80-tios
  • hexagon-freestanding
  • hppa[64]-freestanding
  • kalimba-freestanding
  • kvx-freestanding
  • lanai-freestanding
  • loongarch(32,64)-freestanding
  • loongarch(32,64)-uefi
  • m68k-freestanding
  • m88k-freestanding
  • microblaze[el]-freestanding
  • mips[64][el]-freestanding
  • mipsel-psx
  • mipsel-psp
  • msp430-freestanding
  • nvptx[64]-cuda
  • nvptx[64]-nvcl
  • or1k-freestanding
  • powerpc-wiiu
  • powerpc[64][le]-freestanding
  • powerpc64-ps3
  • propeller-freestanding
  • riscv(32,64)[be]-freestanding
  • riscv(32,64)-uefi
  • riscv64-fuchsia
  • riscv64-hurd
  • s390x-freestanding
  • sh[eb]-freestanding
  • sparc[64]-freestanding
  • spirv(32,64)-opencl
  • spirv(32,64)-opengl
  • spirv(32,64)-vulkan
  • spork8-freestanding
  • thumb[eb]-freestanding
  • thumb-fuchsia
  • thumb-gba
  • thumb-vita
  • ve-freestanding
  • wasm(32,64)-emscripten
  • wasm(32,64)-freestanding
  • x86[_16,_64]-freestanding
  • x86[_64]-hurd
  • x86[_64]-uefi
  • x86_64-driverkit
  • x86_64-fuchsia
  • x86_64-plan9
  • x86_64-ps4
  • x86_64-ps5
  • xcore-freestanding
  • xtensa[eb]-freestanding

Language Changes §

Language Stability Progress §

Since the publish of Zig 0.16.0, a lot of advancement has been made towards stabilizing the language. This is a key stage in our roadmap, and a necessity before tagging Zig 1.0.

In particular, since the final release, we have discussed and made decisions on many language proposals—accepting about 25 and rejecting about 125. At the period of writing, 23 undecided tongue proposals remain open on the Codeberg matter tracker, and 61 undecided language proposals remain open on the bequest GitHub matter tracker. Therefore, this attempt represents a important stage towards finalizing the tongue scheme (although some major decisions remain).

@bitCast changes §

Zig 0.17.0 changes the definition of the @bitCast builtin.

In many cases, the new behavior is equal to the old: in particular, casting between an entire figure category and another entire figure category is unaffected, as is casting between an entire figure category and a packed struct or packed union.

However, the semantics of @bitCast calls involving gathering or vector types have changed. Unfortunately, this alter has the possible to interrupt existing code without triggering a compile error.. Therefore, it may be helpful whenever upgrading to audit any @bitCast uses which affect gathering or vector types.

The new definition of @bitCast is that it reinterprets the logical bit representation of a value as a distinct type. The following types are considered to have logical bit representations:

  • void
  • bool
  • integer types, apart from for comptime_int
  • floating-point types, apart from for comptime_float
  • integer-backed types enum(T), packed struct(T), and packed union(T)
  • arrays or vectors of any of these types

For entire figure and floating-point types, the logical bit depiction starts alongside the least-significant bit and ends alongside the most-significant bit. For gathering and vector types, all elements' logical bit representations are concatenated in command starting alongside the archetypal element.

In practice, this method that the new @bitCast definition mostly aligns alongside the old behavior on little-endian targets. Unlike the old behavior, the new behavior is completely endian-agnostic, ie the procedure behaves the identical despite of the mark endian.

The new @bitCast definition disallows casts between several types which were earlier allowed. In particular, casts involving extern struct or extern union types are no longer permitted. In most cases, code which was using specified casts is aiming to reinterpret the value's in-memory depiction (sometimes called "type punning")—to accomplish this, use @ptrCast or an extern union.

bitcast_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;
Shell
$ 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.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 ceremonial grammar.peg and the genuine tongue implementation did not concur in many places. Probably, the ceremonial grammar has never really 100% matched the genuine handwritten tokenizer and parser.

This issue is now fixed and unblocks forthcoming grammar changes and tongue specification work.

At a elevated level, the method was to compose a tool that accepts Zig's grammar.peg as input and outputs a uncomplicated recursive decline parser. This generated parser is afterward used as an oracle for fuzz evaluation and the handwritten std.zig.Ast.parse() is compared against it. This method ensures a sole origin of fact and allows for uncomplicated repeat as the grammar changes.

More details: #36094

C Translation Moving to External Package §

@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 definitive bundle dependency on official ZSF translate-c package, which is the same implementation the build stage provides, but offers additional configuration options for the translated code, and has an autonomous publish cadence from the chief Zig toolchain.

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 mark = 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, +  +  }); - 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 §

The @backingInt and @fromBackingInt builtins are new. These builtins substitute the now-deprecated @intFromEnum and @enumFromInt builtins (#35966).

@backingInt plant alongside all enums and alongside bitpacks alongside explicit backing entire figure types only. It additionally plant alongside tagged unions, returning the backing entire figure of the energetic tag value. An undefined enum or bitpack yields an undefined assistance integer.

@fromBackingInt infers its outcome type, which may be any enum or a bitpack alongside an explicit assistance entire figure type. It takes a indicator of exactly that assistance entire figure type. For enums, passing a assistance entire figure that is either undefined or would output an invalid tag value results in safety-checked Illegal Behavior. For bitpacks, passing an undefined assistance entire figure yields an undefined bitpack.

@bitCast now additionally performs a safety inspect for invalid tag values if its destination category is an enum.

Also adds a std.meta.BackingInt function to get the result category of @backingInt.

Zig now requires bare enums to have noreturn as their assistance entire figure because they are uninstantiable.

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 chart = 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.

Added @SpirvType §

SPIR-V has a figure of types, specified as images and samplers, that have no equal in Zig's type system. Previously, the lone way to mention to one of them was through inline assembly, which made it unattainable to province a texture or a retention buffer as an average earth variable. Zig 0.17.0 implements accepted recommendation #35240, adding the @SpirvType builtin alongside the another type-creating builtins:

sample_code
@SpirvType(comptime options: std.lang.Type.Spirv) type
  • .sampler creates an OpTypeSampler.
  • .image creates an OpTypeImage.
  • .sampled_image creates an OpTypeSampledImage from an image category whose use is .sampled.
  • .runtime_array creates an OpTypeRuntimeArray. It supports indexing and exposes a len site fair akin the gathering type.

Using this builtin whenever not targeting SPIR-V is a compile error. The options are additionally validated against the mark OS.

spirv_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.

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 outcome = [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 §

The new @divCeil builtin performs entire figure division rounded toward positive infinity, complementing the existing @divTrunc, @divFloor, and @divExact builtins.

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

As alongside the another division builtins, visitant guarantees that denominator != 0 and that outcome does not overflow.

No additional std.math.divCeil(a, b) catch unreachable!

@hasDecl Returns true Only for Public Declarations §

Previously, @hasDecl returned true for community declarations and declarations in the identical file. Now, the behavior is the identical independently of which file @hasDecl is in.

hasdecl.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")); 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{} is no longer valid syntax. Use {} alternatively (#15213).

errdefer Capture Removed §

sample_code
errdefer |err| { }

The grasp (|err|) is no longer allowed (#23734).

To migrate, divided 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 mark = job.target; 

i0 Removed §

i0 is no longer an allowed primitive entire figure type.

This category was nonsensical, so does not have a straightforward alternative. However, any uses of it can nearly certainly be transparently replaced alongside u0.

internal and link_once Global Linkage Removed §

The inner and link_once tags of std.lang.GlobalLinkage have been removed as they had unclear semantics and incomplete assistance in codegen and linking (#36956). Any use of link_once is apt served by weak, during the replacement for inner is to merely not @export the sign in the archetypal place.

Standard Library §

  • Added f128 assistance for @exp and @exp2 according to "Table-Driven Implementation of the Exponential Function in IEEE Floating-Point Arithmetic" by Ping Tak Peter Tang, adapted to activity alongside 128-bit numbers (#31846).
  • Added std.Io.Semaphore.waitTimeout (#31924).
  • Added std.spirv helpers for sampling, querying, and penning images (#36187).
  • ArrayHashMap.setKey no longer recomputes the complete indicator (#32136).
  • std.Target.parseCpuModel now returns optional fairly than error.
  • std.debug.Pdb: deduplicate inline origin locations (#35438).
  • hash.crc complete namespace audit (#35952).
  • std.fs.path add appending variants for related and determine (#36784).

Deprecations §

  • std.heap.memory_pool.AlignedManaged removed in favor of std.heap.memory_pool.Aligned.
  • std.heap.memory_pool.ExtraManaged removed in favor of std.heap.memory_pool.Extra.
  • Deprecated std.builtin in favor of std.lang.
  • Deprecated std.meta.fieldInfo in favor of @typeInfo.
  • Deprecated std.meta.fieldNames in favor of @typeInfo.
  • Deprecated std.meta.fieldTypes in favor of @typeInfo.
  • Deprecated std.DoublyLinkedList.pop in favor of std.DoublyLinkedList.popLast.
  • Renamed std.gpu to std.spirv.
  • Removed std.ascii.indexOfIgnoreCase in favor of std.ascii.findIgnoreCase.
  • Removed std.ascii.indexOfIgnoreCasePos in favor of std.ascii.findIgnoreCasePos.
  • Removed std.ascii.indexOfIgnoreCasePosLinear in favor of std.ascii.findIgnoreCasePosLinear.
  • Removed std.bit_set.Integer.initEmpty in favor of std.bit_set.Integer.empty.
  • Removed std.bit_set.Integer.initFull in favor of std.bit_set.Integer.full.
  • Removed std.bit_set.Array.initEmpty in favor of std.bit_set.Array.empty.
  • Removed std.bit_set.Array.initFull in favor of std.bit_set.Array.full.
  • Removed std.enums.EnumSet.initEmpty in favor of std.enums.EnumSet.empty.
  • Removed std.enums.EnumSet.initFull in favor of std.enums.EnumSet.full.
  • Removed std.mem.containsAtLeastScalar2 in favor of std.mem.containsAtLeastScalar.
  • Removed std.mem.readPackedIntNative in favor of std.mem.readPackedInt.
  • Removed std.mem.readPackedIntForeign in favor of std.mem.readPackedInt.
  • Removed std.mem.writePackedIntNative in favor of std.mem.writePackedInt.
  • Removed std.mem.writePackedIntForeign in favor of std.mem.writePackedInt.

StackFallbackAllocator Reworked §

StackFallbackAllocator is an idea that is helpful for the "small vec" optimization, in which average cases can fit on a pre-allocated stack buffer, but rare cases need energetic heap allocation. The former scheme had a few problems:

  • There was no way to define the alignment of the buffer.
  • It was generic complete the size of the buffer.
  • Calling .allocator().get() mutated the type, dissimilar all another allocators, requiring a runtime safety check.

Now, the buffer is provided as an argument, akin most another std APIs that need a buffer.

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 §

std.heap.DebugAllocator is replaced by a thread-safe allocator alongside the following guarantees:

  • deinit reports all leaks and frees all assistance memory.
  • All allocation mismatches outcome in either a panic or segmentation fault.
  • Allocations from another SafeAllocator instances logic a panic (if Options.canary differ).
  • Double frees and procedure (resize, remap, and free) races panic or segmentation fault.

Given the assistance allocator does not reuse memory, it does not reuse recollection either and most writes following liberated volition segmentation error or are eventually detected and panic.

std.heap.DebugAllocator and std.heap.Check are deprecated.

Every allocation is trailed by an AllocFooter which contains metadata for the allocation and stack traces. It is protected by a checksum to capture misconduct from allocation overwrites and study canary mismatches. An allocation's recollection has a minimum alignment of AllocFooter so that the footer is at a fixed offset resolute from the allocation size. An allocation's recollection is stored either:

  • Inside linearly-filled buckets for small allocations.
  • Inside an allocation immediately from the assistance allocator.

To track allocations, all thread maintains a array of assistance allocations. The array may be modified by another threads in the case of a producer-consumer operation, so the array is a connected catalog lone expanded by creating new segments. Each thread maintains a connected catalog of liberated entries, which may merge entries from another threads' tables.

In the case of producer-consumer operations, acquire/release ordering is assumed to be provided externally. This is additionally assumed by all another thread-safe allocators that reuse recollection as alternatively there would be data races on reuse of allocated memory.

Two fuzz tests have additionally been added for the allocator. They inspect that there is no recollection reuse, that returned recollection is writable, and that it is not overwritten. The multi-threaded fuzz test spawns a number of employee threads which are used for all the test runs. I have run these tests extensively under TSAN.

Building the norm archive tests alongside an -Osafe compiler build and -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 measure average ± σ 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 measure average ± σ 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 §

  • getLastOrNull has been deprecated and renamed to last
  • getLast has been deprecated in favor of final combined alongside .?
  • lastPtr has been added which returns ?*T

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 §

This is an enhancement that can assistance track downward ArrayList use bugs faster (#36239).

Devlog Entry

The existing fastener and unlock methods continue to act exclusively. They have to be used whenever data may be mutated. New methods, lockShared and unlockShared, may be used for shared locking in situations anywhere multiple autonomous users are study but not mutating data.

fmt.allocPrint moved to 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 cord literals has relaxed escaping rules specified that UTF-8 encoded data can continue through unmangled.

"{qf}" is introduced for double-quote escaping the output of a format().

std.zon.parse Reworked §

std.zon.parse now takes struct args and allocates its outcome from an arena.

Migration guide:

sample_code
var diag: Diagnostics = .{}; defer diag.deinit(gpa); const outcome = 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 outcome = 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:

  • fromSliceAlloc ➡️ fromSlice
  • fromSlice ➡️ fromSliceNoAlloc
  • The another "from" methods were renamed following this identical scheme.

"updateFrom" variants specified as updateFromSlice were added. These update an in recollection value, overwriting the value's sectors alongside sectors stated in the ZON source. This can be useful whenever using ZON to burden configuration records alongside varying precedence, for example a content publishing company that has a earth config document and a per-project config file.

Rename bit_set Variants and Deprecate the Managed One §

Renames the types for consistency, deprecating the former names and the managed variant.

  • std.bit_set.IntegerBitSet ➡️ std.bit_set.Integer
  • std.bit_set.ArrayBitSet ➡️ std.bit_set.Array
  • std.StaticBitset, std.bit_set.StaticBitSet ➡️ std.bit_set.Static
  • std.DynamicBitSetUnmanaged, std.bit_set.DynamicBitSetUnmanaged ➡️ std.bit_set.Dynamic
  • std.DynamicBitSet, std.bit_set.DynamicBitSet ➡️ std.bit_set.DynamicManaged (deprecated)

Struct-Of-Arrays Style for std.lang.Type §

When doing category reflection, structs and unions come back their data in struct-of-arrays style (#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 §

And eliminate "release" from the enum tag names.

No functional change, however, notwithstanding the supplement of backwards-compatibile declarations in this patch, it is breaking since expressions that use == or != operators volition not capable to use the deprecated names.

  • std.lang: OptimizeMode ➡️ Optimize
    • Debug ➡️- debug
    • ReleaseSafe ➡️- safe
    • ReleaseFast ➡️- fast
    • ReleaseSmall ➡️- small

lang.Optimize.runtimeSafety §

std.lang.Optimize.runtimeSafety is preferred as an substitute to std.debug.runtime_safety since it volition recommendation callsites cognition concerning their own component fairly than norm archive module.

@import("builtin") Deprecations §

The redundant constants cpu, os, abi, and object_format in @import("builtin") have been deprecated and volition be removed in 0.18.0. Please substitute any use alongside the corresponding sectors on the mark constant:

  • @import("builtin").cpu ➡️ @import("builtin").target.cpu
  • @import("builtin").os ➡️ @import("builtin").target.os
  • @import("builtin").abi ➡️ @import("builtin").target.abi
  • @import("builtin").object_format ➡️ @import("builtin").target.ofmt

Handle Floats Correctly in mem.eql and mem.findDiff §

The functions std.mem.eql and std.mem.findDiff short-circuit whenever their two inputs are slices to the identical memory. This short-circuiting is lone correct whenever the == operator, for the stated type, is reflexive. This isn't the case for floats, as for example std.math.nan(f64) != std.math.nan(f64). The alter in this PR disables that optimisation whenever operating on drift slices.

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 was sometimes using HostName.validate for presenter (in resolveInPlace) and sometimes not (in parseAfterScheme). On its own, this was a problem, but the bigger issue is that RFC3986 (Uri) has a much distinct idea of what a valid presenter name is than RFC1123 (HostName), and so fair making Uri consistently use HostName.validate would create Uri small helpful overall.

Instead, all HostName-related material has been removed from Uri. Uri.getHost has been moved to HostName.fromUri (without a graceful deprecation, since the semantics are distinct adequate for users to need to measure use sites), during Uri.getHostAlloc has been removed entirely.

Migration guide:

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

⬇️

sample_code
var host_buf: [HostName.max_len]u8 = undefined; const presenter = try HostName.fromUri(uri, &host_buf);

#36036

Build System §

  • b.build_root (Directory) ➡️ b.root (Path)
  • ConfigHeader.Options: include_guard_override ➡️ include_guard
  • LazyPath: getDisplayName ➡️ format ("{f}")
  • LazyPath.basename: removed since the value is not known until create phase
  • b.findProgram divided into findProgram and findProgramLazy and API future-proofed.
  • ConfigHeader fixed; now reports unused values for all styles
  • addArtifactArg, addPrefixedArtifactArg ➡️ addArtifactArg2
  • addOutputFileArg, addPrefixedOutputFileArg ➡️ addOutputFileArg2
  • addFileContentArg, addPrefixedFileContentArg ➡️ addFileContentArg2
  • addOutputDirectoryArg, addPrefixedOutputDirectoryArg ➡️ addOutputDirectoryArg2
  • addDirectoryArg, addPrefixedDirectoryArg, addDecoratedDirectoryArg ➡️ addDirectoryArg2
  • addDepFileOutputArg, addPrefixedDepFileOutputArg ➡️ addDepFileOutputArg2
  • addFileArg, addPrefixedFileArg ➡️ addFileArg2

Separate the Maker Process from the Configurer Process §

zig build now runs projects' build.zig code in a distinct executable than the one that performs Package Management and executes the build graph, making zig build faster for multiple reasons (#35428):

  • The creator executable remains unmodified whenever build.zig manuscript is edited, and hence lone needs to be built exactly formerly ("first period setup") following installing Zig.
  • The creator executable is built alongside optimizations enabled, which is starting to become additional precious now that we have introduced --watch and --fuzz.
  • build.zig logic can be skipped sometimes depending on what CLI flags are used with zig build.

Furthermore, configuration is now serialized into a compact binary format that can be consumed by third gathering 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.

To render configuration as .zon to stdout, continue --print-configuration.

Cache System Reworked §

New features:

  • Directory support. Ability for entries added, removed, or renamed in directories to logic a cache miss.
  • Metadata mode. Normally, lone changed contents causes a cache miss. In metadata mode, whenever size, inode, or mtime changes, it continually causes a cache young female autonomous of contents.

All four combinations are imaginable (is_directory=true/false, metadata_mode=true/false). These features are exposed as new API in the Build System.

Since the Zig toolchain is heavily reliant on the caching system, this publish additionally switches to a binary format, preservation approximately 25% on document size, which eases a bit of force on the document scheme cache during additionally simplifying the activity the device needs to do - immediately copy bytes from disk fairly than parsing content files. The new zig cache-cat subcommand is accessible for troubleshooting or tinkering alongside records inner a zig-cache directory.

The cache scheme additionally now has the capability to explain why a "miss" happened. The public-facing API of std.Build.Cache has many breaking changes, but exterior of compiler tooling, this is an rare API to be used, and all the changes create it harder to misuse.

This alter has been observed to speed up cache hits by 5-10% (#36822).

Introduce the Concept of Configure Cache Poisoning §

If the cache is poisoned method that the configure logic had flank effects, or otherwise did item that could not be tracked by the cache system.

This is not to be confused alongside whether idiosyncratic steps may have flank effects whenever being evaluated; it has to do alongside the logic inner build.zig itself. For example, a Run stage that prints "hello world" has flank effects at create time and hence does not justify environment this flag, during checking for the beingness of scdoc at configure time in command to choose the default value for a configuration choice does.

Keeping the cache clean volition create zig build faster, bypassing the configurer procedure when identical configuration would be generated.

When the cache is poisoned, the creator procedure volition delete the build configuration document upon ingesting it since it cannot be reused.

Ways to poison the cache contain calling findProgram, or additional directly std.Build.Graph.poisonCache. A improved substitute than cache poisoning is to explicitly province the configuration requirements alongside these new functions:

  • std.Build.dependOnFileContents - indicates that the build.zig logic depends on a particular file's contents.
  • std.Build.dependOnFileMetadata - indicates that the build.zig logic depends on a particular file's size, inode, mtime, and contents.
  • std.Build.dependOnDirectoryContents - indicates that the build.zig logic depends on a particular directory's entries.
  • std.Build.dependOnDirectoryMetadata - indicates that the build.zig logic depends on a particular directory's final modification date.

Advanced users can override the cache poisoning behavior alongside a new CLI option:

 --cache-poison[=mode] Override configuration caching behavior clean (default) Avoid false affirmative cache hits poisoned Don't cache the configuration disallowed Panics whenever cache would be poisoned ignored A small poison never hurt anybody

findProgram §

Immediately (in the configure phase), searches for an executable on the presenter that has additional than one imaginable name.

Names are searched in order, observing hunt prefixes archetypal and afterward PATH surroundings variable.

Calling this function poisons the configuration cache, so it is lone suitable whenever the beingness of the program or its output needs to be observed by configuration logic. That's why there is also findProgramLazy now.

findProgramLazy §

Creates an anonymous Step that searches for an executable on the presenter that has additional than one imaginable name.

Unlike findProgram, this function does not poison the configuration cache, however the outcome cannot be used in the configuration phase, hence the come back category being LazyPath.

Returns the LazyPath of the established executable. The hunt lone takes place if the LazyPath volition be used by a depending Step.

This API is helpful in the following cases:

  • The binary is not named the identical throughout all systems (for example "python" vs "python3").
  • The binary may be produced by construction from origin fairly than being globally installed and volition hence be perchance established in one of the hunt prefix paths.

Run Step: Passthru Args §

In the Run step, passthru args are all together now, not observable in configure phase whether run args are provided.

--- 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 detect those arguments. In exchange, it method that whenever changing those arguments, build scripts no longer must be rebuilt from source.

Fmt Step: Options §

paths and exclude_paths are now LazyPath lists. There is a convenience method to create them: 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 §

Now, whenever adding an choice that is a document path, one must explicitly choose between (#36876):

  • addOptionPath (must be a file)
  • addOptionPathDirectory (must be a directory)
  • addOptionPathUntracked (opt out of dependency tracking)

Lazy Dependency Ergonomic Enhancements §

  • Log whenever lazy requirements are fetched.
  • std.Build.dependency: assistance lazy dependencies
  • Introduce std.Build.dependencyLazy which perchance returns error.LazyDependencyNeeded alternatively of null, so that you can use try
  • When person build functions return error.LazyDependencyNeeded, build scheme proceeds to fetch them fairly than failing configuration.

Removed Ability to Override Build Runner §

There is no idea 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 bundle administration functionality has been moved out of the Compiler and into the Build System. This includes the following sub-commands:

  • zig build
  • zig fetch
  • zig init
  • zig libc
  • zig cache-cat

This method that ample parts of what used to be included in the compiler executable are now shipped in origin form instead, including:

  • package fetching logic
  • http client and networking
  • TLS (Transport Layer Security) and connected crypto
  • git protocol
  • xz, gzip, zstd, flate, zip
  • parsing, validation, and alternatively dealing alongside build.zig.zon files

All of this functionality is now compiled in -Osafe optimization manner fairly than -Ofast because of being in the compiler. When hacking on the build scheme itself, the surroundings changeable ZIG_DEBUG_CMD=1 may be used to compile the build scheme in debug manner instead.

Miscellaneous changes:

  • Bug fix: refuse way deps that escape the genitor bundle root.

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.

Global vs Local Fetching §

Now zig fetch lone fetches into the earth cache, fair akin it used to. However, if --save (or any variant) is used, afterward it additionally fetches into the local bundle path. When fetching globally, does not necessitate build.zig to be present. zig build always fetches locally (in supplement to globally).

Notably, this fixes the regressed use case zig fetch .

When fetching by path, the hash is continually computed, recompressed tarball is continually created, always overwrites any existing earth cache entry.

Slight Difference in PATH for DLL Arguments §

It used to be the case that, whenever targeting Windows or Wine, relic args added to Run steps modified PATH according to the set of directories containing the recursive set of DLL dependencies. Now this is only done for argv[0]. The motivation for additionally doing this for the another command row arguments is unclear, since those DLLs don't need to be loaded in command to execute argv[0].

Build Server Protocol §

Now, whenever --listen=- is passed, the build scheme serves a protocol that allows connected clients to detect and authority the build chart as it executes. This is intended to be consumed by third-party tooling specified as IDEs.

Current things you can do:

  • Get complete admission to the complete build graph's static, post-configuration information, specified as which build steps are available, which options are set, dependencies, etc. There are a couple things yet to be included, specified as the exposed set of component names.
  • Get notified whenever a build stage starts and completes, including data concerning errors and which records were generated.
  • Request particular steps to build.

In particular, the separation of creator procedure and configurer process is a breaking alter that prevents the ZLS project from working alongside 0.17.0. Although several advancement was made to reconstruct functionality in this publish cycle, Zig squad and ZLS squad are motionless operating together to enhance the build server protocol additional to the item that ZLS can not lone reconstruct functionality, but surpass the power and capabilities compared to before.

In the forthcoming it is expected for much of Zig's own first-party build scheme tooling to rotate into a client of the build server protocol, dogfooding it to justify that third-party tooling enjoys equivalent capabilities (#36497).

It is additionally planned for the build server to multiplex compiler server protocol for the compilation steps, providing type-system information, refactoring, and another advanced editing capabilities (#615).

Compiler §

Incremental Compilation §

The Zig compiler's implementation of incremental compilation—a characteristic allowing near-instant rebuilds of projects following changing the code—has been considerably improved in Zig 0.17.0. Many bugs have been fixed, and the new ELF Linker introduced in the former publish has gained fine assistance for the feature.

Thanks to these enhancements, it is now imaginable for most projects targeting x86_64-linux to obtain advantage of incremental compilation. To do so, add the arguments -fincremental --watch to your zig build command (e.g. zig build -fincremental --watch)—this volition logic the Zig build scheme to hear for changes to origin files, and react to them by performing an incremental rebuild.

For additional data on ways to use incremental compilation in your own projects, or to learn additional concerning how this characteristic plant under the hood, regard checking out this blog post by a Zig center squad member.

Future releases volition continue to concentration on improving this feature, including introducing a new Mach-O linker and self-hosted aarch64 Backend alongside fine assistance for incremental compilation; adding assistance for using incremental compilation without --watch; and fixing any remaining bugs.

SPIR-V Backend §

The self-hosted SPIR-V backend is now multi-threaded akin the another backends.

Execution modes specified as LocalSize and OriginUpperLeft are now derived from the function's calling gathering alternatively of being set through inline assembly, and the new spirv_task and spirv_mesh calling conventions add assistance for project and mesh shaders (#35676).

Declaring capabilities and extensions in inline gathering alongside OpCapability and OpExtension is no longer allowed. They are enabled through mark CPU features instead, ie the -mcpu option.

22 bugs were fixed in the SPIR-V backend during this publish cycle.

aarch64 Backend §

Progress towards this is blocked on Linker enhancements, many of which were completed during this publish cycle.

loongarch Backend §

Initial implementation of self-hosted backend for loongarch64 has been contributed (#36418). It is motionless experimental and not yet usable. There are two ways to contribute to this backend: operating on it directly, and contributing to AIR Legalization Features, which helps all unfinished backends attain the complete row quicker.

WebAssembly Backend §

Zig's WebAssembly backend is now passing 2060/2054 (100%) behavior tests compared to the LLVM backend. However, it is not yet the default whenever compiling in debug optimization manner due to deficiency of debug info assistance (#37032).

Linker §

ELF §

This publish makes important advancement towards replacing Zig's bequest self-hosted ELF linker alongside its new implementation introduced in the former release. Specific enhancements include:

  • Full x86_64 support
  • Full SPARC64 support
  • Partial Loongarch support
  • Static archive generation
  • Shared archive generation
  • Errors for undefined symbols in executables
  • GOT generation
  • Copy relocations
  • GNU sign versioning
  • DWARF debug information
  • Symbol hash array generation
  • Mostly-reproducible binaries
  • Arbitrary division alignment
  • Support for small presenter document scheme obstacle sizes

While this linker has not fairly reached characteristic parity alongside our old self-hosted ELF linker yet—and so remains impaired by default—it is already capable in custom of building the huge bulk 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.

In the next publish of Zig, we anticipation to completely eliminate the bequest ELF linker in favor of this implementation.

COFF §

COFF assistance in the linker is enhanced alongside the following features (#35674):

  • Outputing objects (.obj) and archives (.lib)
  • Outputing implibs alongside images
  • Outputing the TLS and Exports data directories for images
  • Consuming objects, archives, and import libraries as inputs
  • Only links in objects from archives as required, ie. if they merge a sign needed to fulfill a reference
  • COMDAT rules (enough assistance for linking compiler_rt and libc, several COMDAT types are not supported yet)
  • Supports linking against the two -gnu and -msvc libc
  • TLS support
  • __dllimport support: Indirect calls / loads from the IAT directly
  • Detects which entrypoint to choose according to exported symbols
  • -gnu: Constructor / destructor assistance (ie. merge .ctor and .dtor, and set up the __CTOR_LIST__, __DTOR_LIST__ symbols)
  • Support for multiple .drectve arguments (these are required to correctly link msvc libc):
    • /INCLUDE: Forcing a sign to be referenced
    • /ALTERNATENAME: Adding sign aliases
    • /MERGE: Section merging. This functionality is additionally used to straightforward certain sections into the right location (like .ctor / .dtor into .rdata)
    • /DEFAULTLIB: Adding new inputs

New Linker Testing Framework §

Zig is moving towards snapshot-based evaluation for its linkers.

Tests are a blend of comparing objdump snapshot output, really operating the artifacts, and checking for linker errors.

zig build -Dlink-snapshot-update causes tests to run in a manner that outputs snapshots alternatively of checking against them.

A representative workflow for adding a new test:

  1. Add the test
  2. zig-debug build test-link -Dtest-filter=my-test -Dlink-snapshot-update
    • This volition output a .dmp document for all the snapshot combinations defined in any verifyObjdump calls.
    • A sole snapshot intentionally pseudonyms between many targets to decrease noise in the snapshot folder, so snapshot updates are made by whichever test runs archetypal for that snapshot name. If differences between targets do exist, they volition be revealed in stage 4.
  3. Inspect the snapshot output for correctness.
  4. zig-debug build test-link -Dtest-filter=my-test
    • This volition now run all targets against the newly added snapshots
  5. If there are now snapshot failures, that method distinct targets had distinct snapshot outputs. The output have to be inspected to see if these results are certainly valid differences. If they are, afterward the range indicator have to be used to logic -Dlink-snapshot-update to output snapshot to distinct filenames, scoped on the diference.
  6. Re-run -Dlink-snapshot-update to update the new set of snapshots.

SPIR-V §

The SPIR-V linker has been rewritten (#36828). It now supports incremental compilation and can nexus external .spv entity files.

Fuzzer §

Although this release's Build System changes are loosely connected to Zig's integrated fuzzer and its communication alongside the build system, no changes were made to the fuzzer itself.

We anticipate to concentration on improving the fuzzer in a forthcoming publish cycle.

Bug Fixes §

Full catalog of the 329 bug reports closed during this publish cycle:

Many bugs were the two introduced and resolved inside this publish cycle. Most bug fixes are omitted from these publish notes for the purpose of brevity.

This Release Contains Bugs §

Zig has known bugs, miscompilations, and regressions.

Even alongside Zig 0.17.x, operating on a non-trivial project using Zig may necessitate participating in the betterment process.

When Zig reaches 1.0.0, Tier 1 assistance volition acquire a bug guideline as an additional requirement.

Notable Regressions §

We are conscious of these notable regressions in 0.17.0:

LLVM 22 §

This publish of Zig upgrades to LLVM 22.1.8. This covers Clang (zig cc), libc++, libc++abi, libunwind, and libtsan as well.

Loop Vectorization Disabled to Work Around Regression §

In the former publish of Zig, we were forced to disable a key LLVM optimization pass—loop vectorization—to activity about a miscompilation which affected the Zig compiler.

Since we archetypal introduced that workaround, a fix has been merged into LLVM's chief branch. However, the fix is not accessible in LLVM 22, the LLVM type used by Zig 0.17.0. Therefore, this workaround remains enabled for now.

Zig 0.18.0 volition upgrade to LLVM 23, so volition authorize us to re-enable this optimization pass.

musl 1.2.5 §

Zig 0.17.0 distributes musl 1.2.5 affirmative backported safety and portability fixes. Meanwhile, upstream has tagged 1.2.6. Zig 0.18.0 volition update to musl 1.2.6.

When targeting musl statically, many functions are now provided by zig libc rather than origin records copied from musl. Therefore, if you encounter bugs alongside musl libc provided by Zig, please regard upstream by reporting them to Zig's matter tracker fairly than musl's.

glibc 2.44 §

glibc type 2.44 is now accessible whenever cross-compiling.

This publish includes Linux kernel headers for type 7.2.

This publish includes macOS scheme headers for type 27.0.

MinGW-w64 §

Zig 0.17.distributes MinGW-w64 commit 31bd54ab7d5fe03c67ed2bb1a57e531b9c7f8cc4.

However, many functions are now provided by zig libc rather than origin records copied from MinGW-w64. Therefore, if you encounter bugs alongside MinGW-w64 libc provided by Zig, delight regard upstream by reporting them to Zig's matter tracker fairly than MinGW-w64's.

NetBSD 11.0 libc §

NetBSD libc type 11.0 is now accessible whenever cross-compiling.

OpenBSD 7.9 libc §

OpenBSD libc type 7.9 is now accessible whenever cross-compiling.

WASI libc §

Zig 0.17.0 continues to allocate WASI libc commit c89896107d7b57aef69dcadede47409ee4f702ee.

However, many functions are now provided by zig libc fairly than origin records copied from WASI libc.

Furthermore, starting alongside Zig 0.18.0, alternatively of distributing third gathering WASI libc code, Zig will provision libc for WASI targets via zig libc. For additional information, see:

zig libc §

In libc.txt files, the gcc_dir site has been renamed to cc_dir to indicate the actuality that it is not particular to GCC. The old name volition motionless be accepted for now, but users are encouraged to migrate their libc.txt to the new name (#36951).

Additionally, cc_dir is now required on Linux targets. Note that, since Android and OpenHarmony shop the applicable entity records in an different location, users of these targets volition apt desire to set cc_dir to the identical way as crt_dir.

zig cc §

zig cc and zig c++ are now according to Clang 22.1.8.

zig objdump §

This was a necessity for snapshot testing, as fine as aiding in evolving the COFF Linker.

Supported features:

Usage: zig objdump [options] file Options: -h, --help Print this assistance 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 sign catalog and import headers. Specify =sort to optionally kind the import headers by sign name. --file-headers Display file-format particular headers --imports Display imported symbols --linker-member[=1|2|longnames] (Coff) Display contents of the stated archive linker associate (default 2) --member-headers Display archive associate headers --elements=[e1],[e2],-[e3],... Select which formatting elements are displayed. Intended for snapshot testing. file-type File category summary header-name Name that precedes a header block member-path Display complete associate paths. If removed, lone basenames volition be used. newlines Newlines between output sections table-header Table headers alongside pillar names all (default) All of the above --only-member=[name] Only regard archive members names that merge [name]. Can be stated multiple times. --only-section=[name] Only regard division names that merge [name]. Can be stated multiple times. --only-symbol=[name] Only regard sign names that merge [name]. Can be stated multiple times. --redact=[kind] Redact the stated site kind. Intended for snapshot testing. rva Relative virtual addresses va Virtual addresses and document 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 division headers --strings Display cord tables --symbols Display sign 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 device (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 sign array found

If this output was used for a snapshot test that wanted to test the existence 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 component elimination (--elements=) functionality is used to eliminate parts of the output that don't matter for the particular test, as to not logic spurious failures if say, an RVA for a sign changes because of several unrelated alter to the linker. -s is shorthand which enables all the redacts and removes all additional output elements, but particular tests may not use this if they do attention about particular values.

resinator §

Windows Resource Compilation Moving to an External Package §

Windows asset script compilation volition 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.

The zig rc subcommand volition remain following this alter in command to continue supporting the use case of using the Zig toolchain alongside another build systems.

zig fmt §

Added --complexity Flag §

It's a uncomplicated tool for counting tokens and AST nodes, which can be used to portion how an edit to a source document increases or reduces complexity alongside a heuristic that is additional insightful than row count.

For example, operating it on old ELF linker directory:

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 following editing Lld.zig to use arena.print fairly than std.fmt.allocPrint. The row figure is approximately the identical but --complexity tells a distinct story:

  • before: tokens=11929 nodes=5900
  • after: tokens=11832 nodes=5852 (1% decrease in origin complexity)

In the forthcoming this metric may be helpful for an automatic import coordinator to decide whether to create an import pseudonym or not.

Roadmap §

  1. Work alongside ZLS squad to enhance Build Server Protocol to the item where satisfies all their use cases.
  2. Complete Windows assistance in the x86_64 backend so that it can be enabled by default.
  3. Complete and stabilize the language.
  4. Complete the aarch64 Backend and create it the default backend for debug mode.
  5. Enhance the Linker implementations, eliminating dependency on LLD and assistance Incremental Compilation.
  6. Enhance the unified Fuzzer to be rivalrous alongside AFL and another state-of-the-art fuzzers.
  7. Transition from a archive dependency on LLVM to a procedure dependency on Clang (#16270).
  8. Complete the Build System, in particular Package Management features.
  9. Audit the Standard Library (#1629).

Thank You Contributors! §

Ziggy the Ziguana

Here are all the group who landed at smallest one contribution into this release:

  • Alex Rønne Petersen
  • Andrew Kelley
  • Matthew Lugg
  • Casey Banner
  • Jacob Young
  • Frank Denis
  • Ali Chraghi
  • Isaac Freund
  • Pavel Verigo
  • Ryan Liptak
  • Techatrix
  • Justus Klausecker
  • Linus Groh
  • xtex
  • rpkak
  • David Rubin
  • Elaine Gibson
  • David Senoner
  • K4
  • fardragon
  • pentuppup
  • Krzysztof Wolicki
  • Mason Remaley
  • Meghan Denny
  • Christophe Delage
  • Robbie Lyman
  • Lukáš Lalinský
  • Brandon Black
  • Kendall Condon
  • hemisputnik
  • whatisaphone
  • Ben Anderman
  • GasInfinity
  • Huang Zhichao
  • Jakub Konka
  • Jari Vetoniemi
  • Kleshzz
  • Mick Sayson
  • Mikołaj Rosowski
  • Ryan Mehri
  • Sertonix
  • jeffkdev
  • lg
  • Carl Åstholm
  • EJ
  • Hila Friedman
  • Quint Daenen
  • Saurabh Mishra
  • Stephen Gregoratto
  • Subo2002
  • Ten Eugene
  • zacoons
  • Arthur Teixeira
  • Ben Burkert
  • Bernard Assan
  • CursedByTheVoid
  • Daniel Kareh
  • Ennui Langeweile
  • Igor Anić
  • Janne Hellsten
  • Jay Petacat
  • Nguyễn Gia Phong
  • Ragul R
  • Rue04
  • Ryan Mehri
  • Sam Connelly
  • Scott Redig
  • Theo Fabi
  • Vitor Fernandes
  • c-kappel
  • gero3
  • glowsquid
  • taoqy
  • teflate
  • xeondev
  • AI Xin
  • ARandomOSDever
  • Acid Bong
  • Adrià Arrufat
  • Akshay Trivedi
  • Alan Cocanour
  • Alex Kladov
  • Amilia MacIntyre
  • Anders Stenberg
  • Andrew Kraevskiii
  • Anshul Gupta
  • Anthon van der Neut
  • Ari Becker
  • Ashley (holtowd)
  • C19
  • Carter Snook
  • Chadwain Holness
  • Chloé Vulquin
  • Chris Boesch
  • Christoffer Lerno
  • Corentin Kerisit
  • David
  • Devin J. Pohly
  • Diego Peña y Lillo
  • Dmitry Mostovenko
  • Eric Joldasov
  • Erik Schlyter
  • FalsePattern
  • Fitti
  • Gabriel Sa
  • Gereon V
  • Giuseppe Cesarano
  • Gota7
  • GrimTyr
  • Guillaume Wenzek
  • Guy Fischman
  • Henry Kupty
  • Ignacio Ibarra
  • Jan Procházka
  • Jan200101
  • Jeff Fowler
  • Jeremy Linton
  • John Benediktsson
  • Jonathan Marler
  • Joseph Lyncheski
  • Josh Megnauth
  • Kirk Scheibelhut
  • Leon Lombar
  • Leonid Emar-Kar
  • Mai-Lapyst
  • Manlio Perillo
  • Marcel W. Wysocki
  • Mark Rushakoff
  • Mathieu Suen
  • Matthew Knight
  • Matthias Portzel
  • Michael Farber Brodsky
  • Miloš Kozák
  • Nguyen Gia Huy
  • Nico Elbers
  • Noam Rothschild
  • Nurul Huda (Apon)
  • Paul Anderson
  • Paulo Duarte
  • Perry Fraser
  • Pivok
  • Preeternal
  • Prokop Randáček
  • RadsammyT
  • Rayan Halder
  • Richalsu
  • Richard Levitte
  • Rue04
  • Ryan Davis
  • Ryan King
  • Sage Hane
  • Samuel Hunter
  • Sawyer X
  • Siddharth Sinha
  • Steve
  • Tapir
  • Thibault Leclercq
  • Yasin Gorgij
  • Zhalkhas
  • abdessalem
  • agave
  • ahwayakchih
  • akbarhusain
  • arshidkv12
  • avalyn0x45
  • badayvedat
  • binarycraft007
  • brianferri
  • brkzlr
  • carmooo
  • cheesecakecatttt
  • conmaster2112
  • drex_vk
  • gDator
  • gemmaro
  • gubbu
  • ilovapples
  • jmcaine
  • johan0A
  • jpk68
  • krystiann
  • kubashi
  • l1yefeng
  • levinqua
  • llogick
  • marximimus
  • mihael
  • mlugg
  • nash1111
  • ndjenks
  • nekogirl
  • nyx-xyn
  • pancelor
  • skdishansachin
  • sphaerophoria
  • squidy239
  • sstochi
  • vlkrs
  • zirunis
  • Ömer Faruk IRMAK
  • Έλλεν Εμίλια Άννα Zscheile
  • 林晨 (Leo Cheng)

Ziggy the Ziguana

Special gratitude to those who sponsor Zig. Because of diverse, recurring donations, Zig is driven by the open origin community, rather than the goal of making profit. In particular, those below sponsored Zig for an average of $50/month or additional during this publish cycle using our preferred contribution platform:

  • Sergey M
  • Mitchell Kember
  • David Vanderson
  • Thomas Manner
  • Kirk Scheibelhut
  • Kazuhiro Kondo
  • Merlyn Morgan-Graham
  • Freddi Linse
  • Numan Sachwani
  • Aurélien Cibrario
  • Erik Dunteman
  • Ondra Voves
  • Mitchell Gayner
  • Dylan Conway
  • Trevor John
  • Jason Watson
  • Greg Clark
  • Benjamin Crist
  • Alexander Weavers
  • Natalie Vais
  • Stevie Hryciw
  • Kyle Hill
  • Felix Queißner
  • Srinivasan Balram
  • Peter Ronnquist
  • Lajos Nagy
  • Gauthier Voron
  • Andrew Mangogna
  • Alex Kladov
  • Jacob Sandlund
  • Jordan Lucier
  • Wolfgang Sanyer
  • Matthew Knight
  • Nick Macholl
  • Ceri Elenbaas
  • Michael Keathley
  • Daniele Cocca
  • Bartosz Bogacz
  • James Cox-Morton
  • William Canan
  • Fabio Arnold
  • Johannes Meyer
  • Silver van Koten
  • Flavius Gruian
  • Daniel MacDougall
  • Karrick McDermott
  • Dan Mack
  • Caleb Hearon
  • Richard Levitte
  • Ingimar Jóhannesson
  • David Fendley
  • Aaron Cross
  • Jeremiah Oard
  • Simon Ekström
  • Jorge De León
  • Saurabh Mishra
  • Rob Green
  • Kytezign q
  • Mykhailo Tsiuptsiun
  • Paul Sargent
  • Erik Mållberg
  • Igor Anic
  • Fawzi Mohamed
  • David Jones
  • Magnus Holm
  • Nicholas Woolmer
  • Samarth Kishor
  • Charles Haws
  • Shlomi Atar
  • Robbie Lyman
  • Andrius Bentkus
  • Jean-Luc Geering
  • Aaron Mady
  • coleman broaddus
  • Trace Andreason
  • Jim Calabro
  • Chris Baldwin
  • Ian Johnson
  • Brandon Black
  • Michael Lynch
  • O Y
  • Francesco Gualazzi
  • David Sugar
  • Malcolm Still
  • Jeff Fowler
  • Yaroslav Zhavoronkov
  • Miles McGruder
  • Álvaro Justen
  • FELIPE SOARES GONCALVES SA ROSA
  • Noah Betzen
  • Manuel Barkhau
  • Rikard Karlsen
  • Frank Ittermann
  • Eli Janssen
  • Peter Snelgrove
  • Will Pragnell
  • Pete Dietl
  • Vaughn Spielman
  • Michael Kato
  • Daniel Dubecky Hodan
  • Dan Boykis
  • Richard Feldman
  • Markus Ort
  • Peyman Mortazavi
  • Wilson Bilkovich
  • Kev Burns
  • Francisco Nevitt Gonçalves
  • Mark Banhidi
  • Kristoffer Ström
  • Carl Distefano
  • Alexander Reustle
  • Martin Hovda Haugsand
  • Lexa Tang
  • Lennart Tuijnder
  • Enver Bisevac
  • Jameson York
  • Hong Shick Pak
  • Travis Staloch
  • Clover Caruso
  • Matthew Chavez
  • Daniel Gregoire
  • Jose M Rico
  • Xavier Cochran
  • Nas Denkov
  • Pavel Rychlý
  • papa leromi
  • Ronald Zielaznicki
  • Tommi Komulainen
  • Matthew Jee
  • Johan Forsberg
  • Łukasz Mróz
  • Fabio Leimgruber
  • Maurice van Veen
  • Dean Simmons
  • Pierre Marc Levasseur
  • Sebastian Appler
  • Sam Windell
  • Aksel Hjerpbakk
  • Jonathan Helland
  • Karl Fleischmann
  • Erik Hansen
  • Chris Boesch
  • Pablo Álvarez
  • Jacob Hooper
  • Avinash Lakshman
  • Joshua Park
  • Nicholas Clark
  • Ryan Higgins
  • Jeffrey Ollie
  • Adam Goertz
  • David Nowotny
  • Gus Louw
  • David Francoeur
  • David Sparby
  • Tyler Bender
  • Mark Halonen
  • Reinis Taukulis
  • Nancy Remaley
  • Isaac F
  • Kjell Hoffhenke
  • Vlad Panazan
  • Jordan Rowland
  • Jay Van Der Wall
  • Jean-Philippe Quenord
  • Jakob Külzer
  • Varun Pramanik
  • Benjamin Edwards
  • Andreas Herrmann
  • Adam Nilsson
  • Joseph Ruiz
  • Anthony Nguyen
  • Marcin Wolcendorf
  • Tobias Lahrmann Hansen
  • Pat Smuk
  • Martin Weber
  • Jordan Kardon
  • Benjamin LE BERRE
  • John Goen
  • Sebastian Ahlman
  • Anthony Hernandez
  • Shail Patel
  • Alexander Genaud
  • Morten Dalfoss
  • Jason Dubaniewicz
  • Mark Hayes
  • Eivind Rovik
  • Renan Silva
  • Isak Källman
  • Ladislav Böhm
  • LeRoyce Pearson
  • Rowan Saunders
  • Joshua Masci
  • Raymond Imber
  • Daniel Worley
  • Owen Cabalceta
  • Erez Shomron
  • Max Grosse
  • Ehden Sinai
  • Christopher Redden
  • Antoine Balaine
  • Chris Durkin
  • Dave Wallace
  • Aura Birb
  • Andy Armstrong
  • Spencer Brower
  • Simon Clavet
  • Guido Schmidt
  • Peter McGaughey
  • Callum McArthur
  • David Lei
  • David Brotz
  • Matti Hänninen
  • Joseph Chan
  • Vincent Weber
  • Jeremy McAdams
  • Morgan Gallant
  • Brett Pechiney
  • Thilina Jayanath Nenathunga Liyanage
  • Kevin Bockelandt
  • Gunnar Zötl

Special gratitude additionally to TigerBeetle, Synadia Communications, and ZML for significant contributions.

Other Article Hacker News
↑
Close Right Ads
Close Left Ads