Download & Documentation
Zig is a frequent-aim programming language and toolchain for asserting
robust, optimum, and reusable utility.
Zig model is funded by Zig Tool Foundation,
a 501(c)(3) non-profit organization. Please set in thoughts a ordinary donation
in reveal that we are in a position to offer extra billable hours to our core team participants. Right here’s
the most easy methodology to hasten the mission alongside the
Roadmap to 1.0.
This free up aspects 8 months of work:
adjustments from 268 varied contributors, spread amongst
3688 commits.
Within the past, these free up notes gather been extremely prolonged, trying to
gather in thoughts all enhancements that befell at some level of the free up cycle. In
the hobby of no longer overwhelming the reader to boot to the maintainers
creating these notes, this doc is abridged. Many adjustments, at the side of
API breaking adjustments, are no longer mentioned right here.
Table of Contents §
- Table of Contents
- Make stronger Table
- Tier Machine
- Tier 1 Make stronger
- Tier 2 Make stronger
- Tier 3 Make stronger
- Tier 4 Make stronger
- Tier Machine
- Redesign How Autodoc Works
- Installed Standard Library Documentation
- Time to Generate Documentation
- Original Autodoc Facets
- Reliable Linkification
- Interactive Source Listings
- Embedded Source Listings
- Search Contains Doc Feedback
- Error Build Take into memoir
- Honest appropriate Form Detection
- Honest appropriate Implementation of Scroll Ancient past
- Language Modifications
- Unnecessary Employ of var
- Consequence Space Semantics
- Combination Destructuring
- Namespace Form Equivalence
- Comptime Reminiscence Modifications
- @fieldParentPtr
- Disallow alignment on feature form
- @errorCast
- @abs
- Standard Library
- Windows Expose Line Argument Parsing
- Bring-Your-Maintain-OS API Layer Regressed
- std.os renamed to std.posix
- Ryu Floating-Point Formatting
- Transformed HTTP
- Elimination of std.http.Headers
- Remodel Server Fully
- deflate reimplemented from first principles
- std.posix APIs Invent Form Safety
- std.builtin Enum Fields Lowercased
- World Configuration
- Pointer Stability Locks
- Variety Machine
- Machine Package Mode
- Potential to Present Non-mandatory Machine Library Integration
- Machine Integration Support Share
- The usage of the Machine Integration Alternate choices
- Original Delivery Option
- Steer sure of Fetching in Machine Mode
- Sluggish Dependencies
- introduce b.route; deprecate LazyPath.relative
- Header Installation
- dependencyFromBuildZig
- Machine Package Mode
- Compiler
- x86 Backend
- Windows Belongings
- Linker
- Cache Machine
- Bug Fixes
- Comptime Pointer Catch admission to
- This Delivery Incorporates Bugs
- Toolchain
- LLVM 17
- musl 1.2.4
- glibc 2.38
- mingw-w64
- Roadmap
- Async/Await Characteristic Standing
- Thank You Contributors!
- Thank You Sponsors!
Make stronger Table §
Tier Machine §
A inexperienced check trace (✅) indicates the aim meets the final necessities for the
make stronger tier. The plenty of icons show camouflage what is stopping the aim from
reaching the make stronger tier. In varied phrases, the icons are
to-attain items. When you see any disagreeable knowledge right here please
submit a pull query!
Tier 1 Make stronger §
- Now not easiest can Zig generate machine code for these targets, however the
Standard Library execrable-platform abstractions gather implementations
for these targets. - The CI server automatically assessments these targets on every decide to master
division. The 🧪 icon manner this aim doesn’t yet gather CI take a look at protection. - The CI server automatically produces pre-constructed binaries for these targets,
on every decide to master, and updates
the download page with hyperlinks.
The 📦 icon manner the download page is missing this aim. - These targets gather debug info capabilities and therefore
make stack traces on failed assertions. - libc is equipped for this aim even when execrable compiling.
- The overall behavior assessments and acceptable typical library assessments pass for this aim.
All language aspects are known to work appropriately. Experimental aspects attain no longer
depend towards disqualifying an operating intention or structure from Tier 1.
The 🐛 icon manner there are known bugs stopping
this aim from reaching Tier 1. - zig cc, zig c++, and linked toolchain instructions make stronger
this aim. - If the Working Machine is proprietary then the aim is now not any longer marked deprecated
by the dealer. The 💀 icon manner the OS is formally deprecated,
similar to macos/x86.
freestanding | Linux 3.16+ | macOS 11+ | Windows 10+ | WASI | |
---|---|---|---|---|---|
x86_64 | ✅ | ✅ | ✅ | ✅ | N/A |
x86 | ✅ | #1929 🐛 | 💀 | #537 🐛 | N/A |
aarch64 | ✅ | #2443 🐛 | ✅ | #16665 🐛 | N/A |
arm | ✅ | #3174 🐛 | 💀 | 🐛📦🧪 | N/A |
mips | ✅ | #3345 🐛📦 | N/A | N/A | N/A |
riscv64 | ✅ | #4456 🐛 | N/A | N/A | N/A |
sparc64 | ✅ | #4931 🐛📦🧪 | N/A | N/A | N/A |
powerpc64 | ✅ | 🐛 | N/A | N/A | N/A |
powerpc | ✅ | 🐛 | N/A | N/A | N/A |
wasm32 | ✅ | N/A | N/A | N/A | ✅ |
Tier 2 Make stronger §
- The Standard Library helps this aim, however it completely is feasible that some
APIs will give an “Unsupported OS” compile error. One can hyperlink with libc or varied
libraries to comprise in the gaps in the long-established library. The 📖 icon manner the
typical library is simply too incomplete to be regarded as Tier 2 famous. - These targets are known to work, however would possibly maybe perchance perchance perchance no longer be automatically tested, so there
are occasional regressions. 🔍 manner that no one has in actuality looked into this aim
so whether or no longer or no longer it works is unknown. - Some assessments also can very smartly be disabled for these targets as we work towards
Tier 1 Make stronger.
free standing | Linux 3.16+ | macOS 11+ | Windows 10+ | FreeBSD 12.0+ | NetBSD 8.0+ | Dragon FlyBSD 5.8+ | OpenBSD 7.3+ | UEFI | |
---|---|---|---|---|---|---|---|---|---|
x86_64 | Tier 1 | Tier 1 | Tier 1 | Tier 1 | ✅ | ✅ | ✅ | ✅ | ✅ |
x86 | Tier 1 | ✅ | 💀 | ✅ | 🔍 | 🔍 | N/A | 🔍 | ✅ |
aarch64 | Tier 1 | ✅ | Tier 1 | ✅ | 🔍 | 🔍 | N/A | 🔍 | 🔍 |
arm | Tier 1 | ✅ | 💀 | 🔍 | 🔍 | 🔍 | N/A | 🔍 | 🔍 |
mips64 | ✅ | ✅ | N/A | N/A | 🔍 | 🔍 | N/A | 🔍 | N/A |
mips | Tier 1 | ✅ | N/A | N/A | 🔍 | 🔍 | N/A | 🔍 | N/A |
powerpc64 | Tier 1 | ✅ | 💀 | N/A | 🔍 | 🔍 | N/A | 🔍 | N/A |
powerpc | Tier 1 | ✅ | 💀 | N/A | 🔍 | 🔍 | N/A | 🔍 | N/A |
riscv64 | Tier 1 | ✅ | N/A | N/A | 🔍 | 🔍 | N/A | 🔍 | 🔍 |
sparc64 | Tier 1 | ✅ | N/A | N/A | 🔍 | 🔍 | N/A | 🔍 | N/A |
Tier 3 Make stronger §
- The long-established library has minute to no knowledge of the existence of this
aim. - If this aim is equipped by LLVM, LLVM has the aim enabled by default.
- These targets are no longer usually tested; one will likely must contribute
to Zig with a opinion to operate for these targets. - The Zig compiler would possibly maybe perchance perchance perchance must be updated with a couple of issues similar to
- what sizes are the C integer kinds
- C ABI calling conference for this aim
- originate code and default fear handler
zig targets
is guaranteed to incorporate this aim.
freestanding | Linux 3.16+ | Windows 10+ | FreeBSD 12.0+ | NetBSD 8.0+ | UEFI | |
---|---|---|---|---|---|---|
x86_64 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 2 |
x86 | Tier 1 | Tier 2 | Tier 2 | ✅ | ✅ | Tier 2 |
aarch64 | Tier 1 | Tier 2 | Tier 2 | ✅ | ✅ | ✅ |
arm | Tier 1 | Tier 2 | ✅ | ✅ | ✅ | ✅ |
mips64 | Tier 2 | Tier 2 | N/A | ✅ | ✅ | N/A |
mips | Tier 1 | Tier 2 | N/A | ✅ | ✅ | N/A |
riscv64 | Tier 1 | Tier 2 | N/A | ✅ | ✅ | ✅ |
powerpc32 | Tier 2 | Tier 2 | N/A | ✅ | ✅ | N/A |
powerpc64 | Tier 2 | Tier 2 | N/A | ✅ | ✅ | N/A |
bpf | ✅ | ✅ | N/A | ✅ | ✅ | N/A |
hexagon | ✅ | ✅ | N/A | ✅ | ✅ | N/A |
amdgcn | ✅ | ✅ | N/A | ✅ | ✅ | N/A |
sparc | ✅ | ✅ | N/A | ✅ | ✅ | N/A |
s390x | ✅ | ✅ | N/A | ✅ | ✅ | N/A |
lanai | ✅ | ✅ | N/A | ✅ | ✅ | N/A |
csky | ✅ | ✅ | N/A | ✅ | ✅ | N/A |
freestanding | emscripten | |
---|---|---|
wasm32 | Tier 1 | ✅ |
Tier 4 Make stronger §
- Make stronger for these targets is exclusively experimental.
- If this aim is equipped by LLVM, LLVM would possibly maybe perchance perchance perchance gather the aim as an
experimental aim, which manner that you just gather to make spend of Zig-equipped binaries
for the aim to be accessible, or operate LLVM from provide with particular configure flags.
zig targets
will show camouflage the aim if it’s accessible. - This aim also can very smartly be regarded as deprecated by an authentic birthday celebration, in
which case this aim will remain with no waste in sight stuck in Tier 4. - This aim would possibly maybe perchance perchance perchance easiest make stronger
-femit-asm
and can’t emit
object recordsdata, whereby case-fno-emit-bin
is enabled by
default and can’t be overridden.
Tier 4 targets:
- avr
- riscv32
- xcore
- nvptx
- msp430
- r600
- arc
- tce
- le
- amdil
- hsail
- spir
- kalimba
- shave
- renderscript
- 32-bit x86 macOS, 32-bit ARM macOS, powerpc32 and powerpc64 macOS, on memoir of
Apple has formally dropped make stronger for them.
Redesign How Autodoc Works §
This free up deletes the earlier (experimental) Autodoc implementation and replaces it with a peculiar (no longer experimental!) one.
The outmoded implementation looked like this:
5987 src/Autodoc.zig 435 src/autodoc/render_source.zig 10270 lib/docs/commonmark.js 1245 lib/docs/index.html 5242 lib/docs/main.js 2146 lib/docs/ziglexer.js 25325 total
After compilation (sizes are for typical library documentation):
272K commonmark.js 3.8M data-astNodes.js 360K data-calls.js 767K data-comptimeExprs.js 2.2M data-decls.js 896K data-exprs.js 13K data-files.js 45 data-guideSections.js 129 data-modules.js 15 data-rootMod.js 294 data-typeKinds.js 3.2M data-types.js 38K index.html 158K main.js 36M src/ (470 .zig.html files) 78K ziglexer.js
Total output size: 47M (5.7M gzipped)
src/Autodoc.zig
processed ZIR code, outputting JSON knowledge for a web utility to savor. This resulted in rather a couple of code ineffectively trying to reconstruct the AST from no-longer-accessible knowledge.
lib/docs/commonmark.js
used to be a Third-birthday celebration markdown implementation that supported too many aspects; as an instance I attain no longer need it to be that it’s doubtless you’ll perchance perchance perchance maybe factor in to assemble HTML tags in doc feedback, on memoir of that will fetch provide code uglier. Easiest markdown that seems appropriate both as provide and rendered must be allowed.
lib/docs/ziglexer.js
used to be an implementation of Zig language tokenization in JavaScript, despite Zig already exposing its own tokenizer in the long-established library. After I saw this added to the zig mission, a minute bit portion of me died inner.
src/autodoc/render_source.zig
used to be a instrument that transformed .zig recordsdata to a syntax-highlighted however non-interactive .zig.html recordsdata.
The unusual implementation appears like this:
942 lib/docs/main.js 403 lib/docs/index.html 933 lib/docs/wasm/markdown.zig 226 lib/docs/wasm/Decl.zig 1500 lib/docs/wasm/markdown/Parser.zig 254 lib/docs/wasm/markdown/renderer.zig 192 lib/docs/wasm/markdown/Document.zig 941 lib/docs/wasm/main.zig 1038 lib/docs/wasm/Walk.zig 6630 total
After compilation (sizes are for typical library documentation):
12K index.html 32K main.js 192K main.wasm 12M sources.tar
Total output size: 12M (2.3M gzipped)
As it’s doubtless you’ll perchance perchance perchance maybe look, it’s both dramatically extra life like in the case of implementation to boot to operate artifacts. Now there are exactly 4 recordsdata as an different of many, with a 4x good buy in entire file size of the generated web app.
Nevertheless, no longer easiest is it extra life like, it’s in actuality extra powerful than the outmoded intention, on memoir of as an different of processing ZIR, this methodology processes the availability recordsdata without lengthen, which manner it has 100% of the knowledge and never desires to portion the rest collectively backwards.
This approach uses a WebAssembly module written in Zig. This enables it to reuse ingredients from the compiler, similar to the tokenizer, parser, and varied utilities for operating on Zig code.
The sources.tar file, after being decompressed by the HTTP layer, is fed without lengthen into the wasm module’s memory. The tar file is parsed the spend of std.tar and provide recordsdata are parsed in space, with some extra computations added to hash tables on the side.
There would possibly maybe be room for introducing employee threads to velocity up the parsing, even supposing single-threaded it’s already so quick that it doesn’t seem necessary.
Installed Standard Library Documentation §
In Zig 0.11.0, a Zig installation comes with a docs/std/
directory that includes these 47M of output artifacts mentioned above.
This rewrite eliminated these artifacts from Zig installations, as an different
offering the zig std
exclaim, which hosts std lib autodocs and
spawns a browser window to peep them. When this exclaim is activated,
lib/compiler/std-docs.zig
is compiled from provide to fetch
this operation.
The HTTP server creates the requested recordsdata on the flit, at the side of
rebuilding main.wasm
if any of its provide recordsdata changed, and developing
sources.tar
, which manner that any provide adjustments to the documented recordsdata,
or to the autodoc intention itself are without lengthen reflected when
viewing doctors. Prefixing the URL with /debug
ends in a debug
operate of the WebAssembly module.
This vogue contributors can take a look at adjustments to Zig typical library documentation, to boot to autodocs performance, by urgent refresh in their browser window, the spend of a easiest binary distribution of Zig.
In entire, this reduced the Zig installation size from 317M to 268M (-15%).
A ReleaseSmall operate of the compiler shrinks from 10M to 9.8M (-1%).
Time to Generate Documentation §
Autodocs period is now carried out smartly as portion of the pipeline of the compiler in wish to tacked on on the pause. It also now no longer has any dependencies on varied ingredients of the pipeline.
Right here’s how prolonged it now takes to generate typical library documentation:
Benchmark 1 (3 runs): old/zig test /home/andy/dev/zig/lib/std/std.zig -fno-emit-bin -femit-docs=docs measurement mean ± σ min … max outliers delta wall_time 13.3s ± 405ms 12.8s … 13.6s 0 ( 0%) 0% peak_rss 1.08GB ± 463KB 1.08GB … 1.08GB 0 ( 0%) 0% cpu_cycles 54.8G ± 878M 54.3G … 55.8G 0 ( 0%) 0% instructions 106G ± 313K 106G … 106G 0 ( 0%) 0% cache_references 2.11G ± 35.4M 2.07G … 2.14G 0 ( 0%) 0% cache_misses 41.3M ± 455K 40.8M … 41.7M 0 ( 0%) 0% branch_misses 116M ± 67.8K 116M … 116M 0 ( 0%) 0% Benchmark 2 (197 runs): new/zig build-obj -fno-emit-bin -femit-docs=docs ../lib/std/std.zig measurement mean ± σ min … max outliers delta wall_time 24.6ms ± 1.03ms 22.8ms … 28.3ms 4 ( 2%) ⚡- 99.8% ± 0.3% peak_rss 87.3MB ± 60.6KB 87.2MB … 87.4MB 0 ( 0%) ⚡- 91.9% ± 0.0% cpu_cycles 38.4M ± 903K 37.4M … 46.1M 13 ( 7%) ⚡- 99.9% ± 0.2% instructions 39.7M ± 12.4K 39.7M … 39.8M 0 ( 0%) ⚡-100.0% ± 0.0% cache_references 2.65M ± 89.1K 2.54M … 3.43M 3 ( 2%) ⚡- 99.9% ± 0.2% cache_misses 197K ± 5.71K 186K … 209K 0 ( 0%) ⚡- 99.5% ± 0.1% branch_misses 184K ± 1.97K 178K … 190K 6 ( 3%) ⚡- 99.8% ± 0.0%
It dilapidated to plot end upwards of 13 seconds. Now it takes 25ms.
Original Autodoc Facets §
Reliable Linkification §
This stems from the actual fact that with stout provide recordsdata we now gather the final knowledge, and would possibly maybe perchance perchance write extra robust code to assemble a study up identifiers from the context they occur in.
Interactive Source Listings §
Press u
to head to provide code for any declaration:
The hyperlinks plot end you to the API page for that categorical hyperlink by changing the placement hash.
Embedded Source Listings §
Error Build Take into memoir §
Merged error units are detected:
Errors that advance from varied declarations are linked:
Errors are also confirmed on feature peep:
Honest appropriate Form Detection §
Old implementation guesses disagreeable on the vogue of options
to boot to DynLib
.
Honest appropriate Implementation of Scroll Ancient past §
The earlier implementation implemented scroll historical past in JavaScript, which is inconceivable to realize
appropriately. The unusual intention makes cautious spend of the ‘popstate’ event combined with the historical past API
to scroll to the high of the window easiest when the user navigates to a peculiar hyperlink – respecting the browser’s
saved scroll historical past in all varied cases.
For extra little print look
the commit diff.
Language Modifications §
Unnecessary Employ of var §
Zig 0.12.0 introduces a peculiar compile error which is emitted when a native variable is declared as
a var
, however the compiler can infer that const
would suffice.
const expectEqual = @import("std").testing.expectEqual;
test "unnecessary use of var" {
var x: u32 = 123;
try expectEqual(123, x);
}
$ zig test unnecessary_var.zig docgen_tmp/unnecessary_var.zig:3:9: error: local variable is never mutated var x: u32 = 123; ^ docgen_tmp/unnecessary_var.zig:3:9: note: consider using 'const'
As indicated by the error message, the answer is straightforward: spend const
as an different
the place acceptable.
Consequence Space Semantics §
Zig 0.12.0 features quite so much of enhancements to Consequence Space Semantics (RLS).
This free up implements forwarding of result kinds by the address-of operator (&
). This enables
syntactic constructs which rely on result kinds, similar to nameless initializations .{ ... }
and casting builtins like @intCast
, to feature appropriately in the presence of the
address-of operator:
const S = struct { x: u32 };
const int: u64 = 123;
const val: *const S = &.{ .x = @intCast(int) };
comptime {
_ = val;
}
$ zig test address_of_rls.zig All 0 tests passed.
To boot, Zig 0.12.0 removes the flexibility for result areas to propagate by @as
and explicitly-typed mixture initializations T{ ... }
. This restriction is in space to
simplify the language originate: earlier releases contained quite so much of bugs touching on to incorrect casting of result pointers.
Combination Destructuring §
Zig 0.12.0 introduces a peculiar syntax to permit destructuring indexable aggregates: that is, tuples, vectors, and arrays.
Writing a sequence of lvalues or native variable declarations on the left-hand side of the assignment will strive to
destructure the stamp specified on the staunch-hand side:
const std = @import("std");
const assert = std.debug.assert;
const expectEqual = std.testing.expectEqual;
test "destructure array" {
var z: u32 = undefined;
const x, var y, z = [3]u32{ 1, 2, 3 };
y += 10;
try expectEqual(1, x);
try expectEqual(12, y);
try expectEqual(3, z);
}
test "destructure vector" {
// Comptime-known values are propagated as you would expect.
const x, const y = @Vector(2, u32){ 1, 2 };
comptime assert(x == 1);
comptime assert(y == 2);
}
test "destructure tuple" {
var runtime: u32 = undefined;
runtime = 123;
const x, const y = .{ 42, runtime };
// The first tuple field is a `comptime` field, so `x` is comptime-known even
// though `y` is runtime-known.
comptime assert(x == 42);
try expectEqual(123, y);
}
$ zig test destructure.zig 1/3 destructure.test.destructure array... OK 2/3 destructure.test.destructure vector... OK 3/3 destructure.test.destructure tuple... OK All 3 tests passed.
Slices can’t be without lengthen destructured. To destructure values from a nick, convert it to an array by lowering
with comptime-known bounds, similar to slice[0..3].*
.
Namespace Form Equivalence §
In Zig, struct
, enum
, union
, and opaque
kinds are particular. They
attain no longer spend structural equivalence, like tuples and arrays attain; as an different, they operate determined kinds. These kinds gather
namespaces, and thus would possibly maybe perchance perchance perchance have declarations. For this motive, they would possibly maybe perchance perchance perchance even be referred to collectively as “namespace
kinds”.
In 0.11.0, at any time when a declaration of this sort of form used to be semantically analyzed, a peculiar form used to be created. Equivalence of
generic kinds used to be handled by memoization of comptime feature calls; i.e.
std.ArrayList(u8) == std.ArrayList(u8)
held since the ArrayList
feature used to be easiest called
once, and its results memoized.
In 0.12.0, this has changed. Namespace kinds for the time being are deduplicated primarily based on two factors: their provide plot, and
their captures.
The “captures” of a form refers back to the dwelling of comptime-known kinds and values which it closes over. In varied phrases,
it is the dwelling of values referenced within the form however declared outdoor of it. For example, the
comptime T: type
parameter of std.ArrayList
is captured by the form it returns. If two
namespace kinds are declared by the identical portion of code and gather the identical captures, they for the time being are regarded as to be
exactly the identical form.
Camouflage that the compiler will mute memoize comptime calls: that hasn’t changed. Nevertheless, this memoization now no longer
has a necessary affect on language semantics.
It’s unlikely that this trade will reason breakage in unusual code. The maybe scenario the place it would possibly perchance perchance perchance is
something just like the following:
fn MakeOpaque(comptime n: comptime_int) type {
_ = n;
return opaque {};
}
const A = MakeOpaque(0);
const B = MakeOpaque(1);
In Zig 0.11.0, this code would operate two determined kinds, since the calls to MakeOpaque
are determined
and thus the opaque
declaration used to be analyzed individually for every call. In Zig 0.12.0, these kinds are
identical (A == B
), on memoir of whereas the feature is called twice, the declaration doesn’t hold any
stamp.
This code would possibly maybe perchance perchance perchance even be mounted by forcing the form declaration to hold n
:
fn MakeOpaque(comptime n: comptime_int) type {
return opaque {
comptime {
_ = n;
}
};
}
const A = MakeOpaque(0);
const B = MakeOpaque(1);
Since n
is referenced within the opaque
declaration, this code creates two determined kinds.
Comptime Reminiscence Modifications §
Zig 0.12.0 overhauls the compiler’s interior illustration of comptime memory, and extra specifically
comptime-mutable memory (i.e. comptime var
). This overhaul comes with some user-going by
adjustments in the develop of fresh restrictions on what it’s doubtless you’ll perchance perchance perchance maybe attain with a comptime var
.
The first, and most necessary, unusual rule is that a pointer to a comptime var
is now not any longer in actuality
allowed to turn out to be runtime-known. For example, set in thoughts the following snippet:
test "runtime-known comptime var pointer" {
comptime var x: u32 = 123;
// `var` makes `ptr` runtime-known
var ptr: *const u32 = undefined;
ptr = &x;
if (ptr.* != 123) return error.TestFailed;
}
$ zig test comptime_var_ptr_runtime.zig docgen_tmp/comptime_var_ptr_runtime.zig:5:11: error: runtime value contains reference to comptime var ptr = &x; ^~ docgen_tmp/comptime_var_ptr_runtime.zig:5:11: note: comptime var pointers are not available at runtime
In earlier variations of Zig, this take a look at passed as it’s doubtless you’ll perchance perchance perchance maybe query. In Zig 0.12.0, it emits a compile error,
since the assignment to ptr
makes the stamp &x
– which is a pointer to a
comptime var
– runtime-known.
Such pointers also can moreover turn out to be runtime-known by, as an instance, being passed to a feature called at runtime:
test "comptime var pointer as runtime argument" {
comptime var x: u32 = 123;
if (load(&x) != 123) return error.TestFailed;
}
fn load(ptr: *const u32) u32 {
return ptr.*;
}
$ zig test comptime_var_ptr_runtime_arg.zig docgen_tmp/comptime_var_ptr_runtime_arg.zig:3:14: error: runtime value contains reference to comptime var if (load(&x) != 123) return error.TestFailed; ^~ docgen_tmp/comptime_var_ptr_runtime_arg.zig:3:14: note: comptime var pointers are not available at runtime
This take a look at also emits a compile error in Zig 0.12.0. The choice to load
occurs at runtime, and its
ptr
parameter is now not any longer marked comptime
, so ptr
is runtime-known
within the body of load
. This vogue the call to load
makes the pointer &x
runtime-known, hence the compile error.
This restriction used to be set in space to fix some soundness bugs. When a pointer to a comptime var
turns into runtime-known, mutations to it turn out to be invalid since the pointed-to knowledge turns into constant, however the form intention
fails to replicate this, resulting in the probability of runtime segmentation faults in what looks to be real code. In
addition, the stamp you read from this sort of pointer at runtime would possibly maybe perchance perchance perchance be its “closing” comptime stamp, which used to be an
unintuitive behavior. Thus, these pointers can now no longer be runtime-known.
The second unusual restriction is that a pointer to a comptime var
is now not any longer in actuality allowed to be contained
within the resolved stamp of a world declaration. For example, set in thoughts the following snippet:
const ptr: *const u32 = ptr: {
var x: u32 = 123;
break :ptr &x;
};
comptime {
_ = ptr;
}
$ zig test comptime_var_ptr_global.zig docgen_tmp/comptime_var_ptr_global.zig:1:30: error: global variable contains reference to comptime var const ptr: *const u32 = ptr: { ~~~~~^ referenced by: comptime_0: docgen_tmp/comptime_var_ptr_global.zig:6:9 remaining reference traces hidden; use '-freference-trace' to see all reference traces
Right here, ptr
is a world declaration whose stamp is a pointer to a comptime var
.
This declaration used to be authorized in Zig 0.11.0, however raises a compile error in Zig 0.12.0. The identical rule applies in
extra advanced cases, similar to when the pointer is contained within a struct self-discipline:
const S = struct { ptr: *const u32 };
const val: S = blk: {
var x: u32 = 123;
break :blk .{ .ptr = &x };
};
comptime {
_ = val;
}
$ zig test comptime_var_ptr_global_struct.zig docgen_tmp/comptime_var_ptr_global_struct.zig:2:21: error: global variable contains reference to comptime var const val: S = blk: { ~~~~~^ referenced by: comptime_0: docgen_tmp/comptime_var_ptr_global_struct.zig:7:9 remaining reference traces hidden; use '-freference-trace' to see all reference traces
This code raises the identical compile error as the earlier instance. This restriction has been set in space primarily to
succor the implementation of incremental compilation in the Zig compiler, which depends on the actual fact that diagnosis of
global declarations is reveal-autonomous, and the dependencies between declarations would possibly maybe perchance perchance perchance even be with out train modeled.
Essentially the most frequent methodology for this to manifest as a compile error in unusual code is if a feature constructs a nick
at comptime which is then dilapidated at runtime. For example, set in thoughts the following snippet:
fn getName() []const u8 {
comptime var buf: [9]u8 = undefined;
// In practice there would likely be more complex logic here to populate `buf`.
@memcpy(&buf, "some name");
return &buf;
}
test getName {
try @import("std").testing.expectEqualStrings("some name", getName());
}
$ zig test construct_slice_comptime.zig docgen_tmp/construct_slice_comptime.zig:5:12: error: runtime value contains reference to comptime var return &buf; ^~~~ docgen_tmp/construct_slice_comptime.zig:5:12: note: comptime var pointers are not available at runtime referenced by: decltest.getName: docgen_tmp/construct_slice_comptime.zig:8:64 remaining reference traces hidden; use '-freference-trace' to see all reference traces
A call to getName
returns a nick whose ptr
self-discipline is a pointer to a
comptime var
. This vogue the stamp can’t be dilapidated at runtime, nor can it seem in the stamp
of a world declaration. This code would possibly maybe perchance perchance perchance even be mounted by selling the computed knowledge to a const
after filling the buffer:
fn getName() []const u8 {
comptime var buf: [9]u8 = undefined;
// In practice there would likely be more complex logic here to populate `buf`.
@memcpy(&buf, "some name");
const final_name = buf;
return &final_name;
}
test getName {
try @import("std").testing.expectEqualStrings("some name", getName());
}
$ zig test construct_slice_comptime.zig 1/1 construct_slice_comptime.decltest.getName... OK All 1 tests passed.
Love in earlier variations of Zig, comptime-known const
s gather limitless lifetime, and the
restrictions mentioned right here attain no longer apply to them. Therefore, this code functions as expected.
One other that it’s doubtless you’ll perchance perchance perchance maybe factor in failure mode is in code which dilapidated the outmoded semantics to operate global mutable comptime instruct. For
instance, the following snippet attempts to operate a world comptime counter:
const counter: *u32 = counter: {
var n: u32 = 0;
break :counter &n;
};
comptime {
counter.* += 1;
}
$ zig test global_comptime_counter.zig docgen_tmp/global_comptime_counter.zig:1:32: error: global variable contains reference to comptime var const counter: *u32 = counter: { ~~~~~~~~~^ referenced by: comptime_0: docgen_tmp/global_comptime_counter.zig:6:5 remaining reference traces hidden; use '-freference-trace' to see all reference traces
This code emits a compile error in Zig 0.12.0. This spend case is now not any longer and ought to now not ever be supported by Zig: any mutable
comptime instruct ought to be represented in the community.
@fieldParentPtr §
The first argument is eliminated in choose of the spend of the pause result form.
Migration recordsdata:
const parent_ptr = @fieldParentPtr(Parent, "field_name", field_ptr);
↓
const parent_ptr: *Parent = @fieldParentPtr("field_name", field_ptr);
or
const parent_ptr: *Parent = @alignCast(@fieldParentPtr("field_name", field_ptr));
looking out on what parent pointer alignment the compiler is able to show camouflage.
The second develop is extra portable, because it’s that it’s doubtless you’ll perchance perchance perchance maybe factor in for the
@alignCast
to be necessary for some targets however no longer others.
Disallow alignment on feature form §
Zig 0.11.0 allowed feature kinds to specify an alignment. Right here’s disallowed in Zig 0.12.0,
on memoir of is it a property of feature declarations and pointers, no longer of feature kinds.
comptime {
_ = fn () align(4) void;
}
$ zig test func_type_align.zig docgen_tmp/func_type_align.zig:2:21: error: function type cannot have an alignment _ = fn () align(4) void; ^
@errorCast §
Old releases of Zig incorporated an @errSetCast
builtin which performed a security-checked
cast from one error dwelling to another, doubtlessly smaller, one. In Zig 0.12.0, this builtin is changed with
@errorCast
. Old uses will continue to work, however to boot to, this unusual builtin can cast
the error dwelling of an error union:
const testing = @import("std").testing;
test "@errorCast error set" {
const err: error{Foo, Bar} = error.Foo;
const casted: error{Foo} = @errorCast(err);
try testing.expectEqual(error.Foo, casted);
}
test "@errorCast error union" {
const err: error{Foo, Bar}!u32 = error.Foo;
const casted: error{Foo}!u32 = @errorCast(err);
try testing.expectError(error.Foo, casted);
}
test "@errorCast error union payload" {
const err: error{Foo, Bar}!u32 = 123;
const casted: error{Foo}!u32 = @errorCast(err);
try testing.expectEqual(123, casted);
}
$ zig test error_cast.zig 1/3 error_cast.test.@errorCast error set... OK 2/3 error_cast.test.@errorCast error union... OK 3/3 error_cast.test.@errorCast error union payload... OK All 3 tests passed.
@abs §
Old releases of Zig incorporated the @fabs
builtin. This has been changed with a peculiar
@abs
builtin, which is able to feature on integers to boot to floats:
const expectEqual = @import("std").testing.expectEqual;
test "@abs on float" {
const x: f32 = -123.5;
const y = @abs(x);
try expectEqual(123.5, y);
}
test "@abs on int" {
const x: i32 = -12345;
const y = @abs(x);
try expectEqual(12345, y);
}
$ zig test abs.zig 1/2 abs.test.@abs on float... OK 2/2 abs.test.@abs on int... OK All 2 tests passed.
Standard Library §
Windows Expose Line Argument Parsing §
On Windows, the exclaim line arguments of a program are a single WTF-16
encoded string and it’s as much as this system to chop up it into an array of
strings. In C/C++, the entry level of the C runtime takes care of splitting
the exclaim line and passing argc/argv to the main feature.
Previously, ArgIteratorWindows matched the behavior of
CommandLineToArgvW, however it completely looks that CommandLineToArgvW’s behavior
doesn’t match the behavior of the C runtime submit-2008. In 2008, the C
runtime argv splitting
changed how it handles consecutive double quotes
within a quoted argument (it’s now regarded as an escaped quote, e.g.
"foo""bar"
submit-2008 would get parsed into foo"bar
), and the foundations round
argv[0] had been also changed.
This free up makes ArgIteratorWindows match the behavior of the
submit-2008 C runtime. The motivation right here is roughly the identical as when the
same trade used to be made in Rust,
that is (paraphrased):
- Fixed behavior between Zig and unusual C/C++ functions
- Permits users to flee double quotes in a methodology that can perchance even be extra easy
Furthermore, the suggested mitigation for
BatBadBut
depends on the submit-2008 argv splitting behavior for roundtripping of the
arguments given to cmd.exe.
The BadBatBut
mitigation did no longer fetch the 0.12.0 free up cutoff.
Bring-Your-Maintain-OS API Layer Regressed §
Old variations of Zig allowed functions to override the POSIX API layer of the long-established library.
This free up deliberately removes this capacity, with no migration route equipped.
This used to be a mistake from day one. Right here’s the disagreeable abstraction layer to realize this in.
The alternate opinion for right here is to fetch all I/O operations require an IO
interface parameter, similar to how allocations require an Allocator
interface parameter nowadays.
The sort of opinion is now not any longer yet implemented, so functions which require this performance must withhold a
fork of the long-established library until then.
std.os renamed to std.posix §
Migration recordsdata:
std.os.abort();
↓
std.posix.abort();
In most cases, one must desire to make spend of the increased-stage execrable-platform abstractions in wish to reaching
into the POSIX API layer. For example, std.process.exit
is extra portable than
std.posix.exit
. You have to most incessantly query the API inner std.posix
to be accessible on a given OS when the OS implements that corresponding POSIX performance.
Ryu Floating-Point Formatting §
Zig 0.12.0 replaces the earlier errol floating level formatting algorithm with one primarily based on
Ryu, a recent algorithm for
changing IEEE-754 floating-level numbers to decimal strings.
The improvements this brings are:
- Potential to format f80 and f128 kinds
- More beautiful f16 and f32 formatting
- Full round-time out make stronger for every drift form
- Generic backend that can perchance even be dilapidated to print any drift of a frequent choice of bits (much less than or equal to 128 bits)
Behavior Differences:
- Exponents don’t seem to be any longer padded with a number one 0 to 2-digits and if sure, the trace is now no longer printed:
errol: 1e+02 ryu: 1e2
- Fractional values of 0 are omitted in stout precision mode:
errol: 2.0e+00 ryu: 2e0
- Stout precision output is extra beautiful in all cases varied than f64,
since we now no longer attain a cast internally to f64:# Ryu 3.1234567891011121314151617181920212E0 :f128 3.1234567891011121314E0 :f80 3.1234567891011121314E0 :c_longdouble 3.123456789101112E0 :f64 3.1234567E0 :f32 3.123E0 :f16 ## Errol 3.123456789101112e+00 :f128 3.123456789101112e+00 :f80 3.123456789101112e+00 :c_longdouble 3.123456789101112e+00 :f64 3.12345671e+00 :f32 3.123046875e+00 :f16
- Furthermore, rounding behaviour in these cases can fluctuate in the mounted
precision case as the shortest illustration will most incessantly fluctuate:# bits: 141333 # precision: 3 # std_shortest: 1.98049715e-40 # ryu_shortest: 1.9805e-40 # type: f32 | | std_dec: 0.000 | ryu_dec: 0.000 | | std_exp: 1.980e-40 | ryu_exp: 1.981e-40
Performance: ~2.3x performance improvement
Code Dimension: roughly +5KB (2x)
Source for these stats
Transformed HTTP §
First, some truthful easy adjustments:
- don’t emit Server HTTP header. Let the user add that if they wish to. It be no longer strictly necessary, and arguably a detrimental default.
- appropriate the error dwelling of
finish
to no longer gather NotWriteable and MessageTooLong in it - offer protection to in opposition to zero-length chunks in Server
- add missing redirect behavior approach to FetchOptions and fetch it an enum as an different of two fields
error.CompressionNotSupported
is renamed toerror.CompressionUnsupported
, matching the naming conference from the final varied errors in the identical dwelling.- Removed documentation feedback that had been redundant with self-discipline and form names.
- Disabling zstd decompression in the server for now; look #18937.
- Robotically contend with query: 100-continue requests
Subsequent, eliminated the flexibility to heap-allocate the buffer for headers. The buffer for HTTP headers is now frequently equipped by a static buffer. As a , OutOfMemory
is now no longer a member of the read()
error dwelling, and the API and implementation of Client and Server are simplified. error.HttpHeadersExceededSizeLimit
is renamed to error.HttpHeadersOversize
.
Lastly, the astronomical adjustments:
As an different, some headers are equipped by narrate self-discipline names populated
whereas parsing the HTTP query/response, and some are equipped by unusual
fields that make stronger passing extra, arbitrary headers. This resulted in
simplification of common sense in a entire lot of locations, to boot to elimination of the
probability of failure in a entire lot of locations. There would possibly maybe be much less deinitialization
code occurring now. Furthermore, it made it now no longer necessary to clone
the headers knowledge building with a opinion to contend with redirects.
http_proxy and https_proxy fields for the time being are pointers because it’s no longer uncommon for them to be unpopulated.
loadDefaultProxies
is became initDefaultProxies
to keep up a correspondence that it doesn’t in actuality load the rest from disk or from the community. The feature now is leaky; the API user must pass an already instantiated area allocator. Eliminates the must deinitialize proxies.
Earlier than, proxies kept arbitrary units of headers. Now they easiest retailer the authorization stamp.
Removed the duplicated code between https_proxy and http_proxy. Lastly, parsing failures of the atmosphere variables result in errors being emitted in wish to silently ignoring the proxy.
Remodel Server Fully §
Essentially, this removes the poorly named wait
, send
, finish
functions, which all operated on the identical “Response” object, which used to be in actuality being dilapidated as the query.
Now, it appears like this:
std.net.Server.accept()
provides you astd.net.Server.Connection
std.http.Server.init()
with the connectionServer.receiveHead()
provides you a Seek recordsdata fromRequest.reader()
provides you a body readerRequest.respond()
is a one-shot, orRequest.respondStreaming()
creates
aResponse
Response.writer()
provides you a body authorResponse.end()
finishes the response;Response.endChunked()
permits
passing response trailers.
In varied phrases, the form intention now guides the API user down the staunch route.
receiveHead
permits extra bytes to be read into the read buffer, and then will reuse these bytes for the body or the following query upon connection reuse.
respond()
, the one-shot feature, will send your entire response in a single syscall.
Streaming response bodies now no longer wastefully wraps every call to jot down with a chunk header and trailer; as an different it easiest sends the HTTP chunk wrapper when flushing. This vogue the user can mute regulate when it happens however it completely also doesn’t add pointless chunks.
Empirically, the usage code is very much much less noisy, it has much less
error facing whereas facing errors extra appropriately, it’s extra evident what
is going on, and it’s syscall-optimum.
var read_buffer: [8000]u8 = undefined;
accept: while (true) {
const connection = try http_server.accept();
defer connection.stream.close();
var server = std.http.Server.init(connection, &read_buffer);
while (server.state == .ready) {
var request = server.receiveHead() catch |err| {
std.debug.print("error: {s}n", .{@errorName(err)});
continue :accept;
};
try static_http_file_server.serve(&request);
}
}
pub fn serve(context: *Context, request: *std.http.Server.Request) ServeError!void {
// ...
return request.respond(content, .{
.status = status,
.extra_headers = &.{
.{ .name = "content-type", .value = @tagName(file.mime_type) },
},
});
Furthermore:
- Uncouple
std.http.HeadParser
from protocol.zig - Delete
std.Server.Connection
; spendstd.net.Server.Connection
as an different.- The API user provides the read buffer when initializing the
http.Server, and it’s dilapidated for the HTTP head to boot to a buffer
for reading the body into.
- The API user provides the read buffer when initializing the
- Replace and doc the Dispute enum. No longer is there both “originate”
and “first”.
std.http.Client
has no longer yet been reworked in a identical manner as std.http.Server
.
deflate reimplemented from first principles §
In Zig 0.11.0, the deflate implementation used to be ported from the Crawl
typical library, which had a bunch of undesirable properties, similar to
incorrect spend of global variables, feedback about Crawl’s optimizer in Zig’s
codebase, and the requirement of dynamic memory allocation.
Zig 0.12.0 has a peculiar implementation that is now not any longer a port of an unusual codebase.
The unusual implementation is roughly 1.2-1.4x sooner in decompression and
1.1-1.2x sooner in compression. Compressed sizes are truthful powerful the identical
in both cases (provide).
The unusual code uses static allocations for all constructions, doesn’t require
allocator. That is nice especially for deflate the place all constructions,
interior buffers are allocated to the stout size. Runt much less for inflate
the place the earlier verision dilapidated much less memory by no longer preallocating to theoretical
max size array that are on the entire no longer fully dilapidated.
For deflate the unusual implementaiton allocates 395K whereas earlier
implementation dilapidated 779K. For inflate the unusual implementation allocates
74.5K whereas the outmoded one round 36K.
Inflate difference is on memoir of we right here spend 64K historical past as an different of 32K previously.
Migration recordsdata:
const std = @import("std");
// To get this file:
// wget -nc -O war_and_peace.txt https://www.gutenberg.org/ebooks/2600.txt.utf-8
const data = @embedFile("war_and_peace.txt");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
try oldDeflate(allocator);
try new(std.compress.flate, allocator);
try oldZlib(allocator);
try new(std.compress.zlib, allocator);
try oldGzip(allocator);
try new(std.compress.gzip, allocator);
}
pub fn new(comptime pkg: type, allocator: std.mem.Allocator) !void {
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();
// Compressor
var cmp = try pkg.compressor(buf.writer(), .{});
_ = try cmp.write(data);
try cmp.finish();
var fbs = std.io.fixedBufferStream(buf.items);
// Decompressor
var dcp = pkg.decompressor(fbs.reader());
const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
defer allocator.free(plain);
try std.testing.expectEqualSlices(u8, data, plain);
}
pub fn oldDeflate(allocator: std.mem.Allocator) !void {
const deflate = std.compress.v1.deflate;
// Compressor
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();
// Remove allocator
// Rename deflate -> flate
var cmp = try deflate.compressor(allocator, buf.writer(), .{});
_ = try cmp.write(data);
try cmp.close(); // Rename to finish
cmp.deinit(); // Remove
// Decompressor
var fbs = std.io.fixedBufferStream(buf.items);
// Remove allocator and last param
// Rename deflate -> flate
// Remove try
var dcp = try deflate.decompressor(allocator, fbs.reader(), null);
defer dcp.deinit(); // Remove
const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
defer allocator.free(plain);
try std.testing.expectEqualSlices(u8, data, plain);
}
pub fn oldZlib(allocator: std.mem.Allocator) !void {
const zlib = std.compress.v1.zlib;
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();
// Compressor
// Rename compressStream => compressor
// Remove allocator
var cmp = try zlib.compressStream(allocator, buf.writer(), .{});
_ = try cmp.write(data);
try cmp.finish();
cmp.deinit(); // Remove
var fbs = std.io.fixedBufferStream(buf.items);
// Decompressor
// decompressStream => decompressor
// Remove allocator
// Remove try
var dcp = try zlib.decompressStream(allocator, fbs.reader());
defer dcp.deinit(); // Remove
const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
defer allocator.free(plain);
try std.testing.expectEqualSlices(u8, data, plain);
}
pub fn oldGzip(allocator: std.mem.Allocator) !void {
const gzip = std.compress.v1.gzip;
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();
// Compressor
// Rename compress => compressor
// Remove allocator
var cmp = try gzip.compress(allocator, buf.writer(), .{});
_ = try cmp.write(data);
try cmp.close(); // Rename to finisho
cmp.deinit(); // Remove
var fbs = std.io.fixedBufferStream(buf.items);
// Decompressor
// Rename decompress => decompressor
// Remove allocator
// Remove try
var dcp = try gzip.decompress(allocator, fbs.reader());
defer dcp.deinit(); // Remove
const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
defer allocator.free(plain);
try std.testing.expectEqualSlices(u8, data, plain);
}
std.posix APIs Invent Form Safety §
For example, let’s watch at std.posix.termios
:
- Add missing API bits to termios and the forms of its fields for all 12 operating systems
- Honest appropriate API bits on Linux (they had been disagreeable for some CPU architectures)
- Consolidate std.c definitions
- Add form safety to all integers
For example previously right here is the methodology it’s doubtless you’ll perchance perchance perchance maybe dwelling fast mode on a tty:
const in = std.io.getStdIn();
// copy original settings and restore them once done
const original_termios = try std.posix.tcgetattr(in.handle);
defer std.posix.tcsetattr(in.handle, .FLUSH, original_termios) catch {};
// set immediate input mode
var termios = original_termios;
termios.lflag &= ~@as(std.posix.system.tcflag_t, std.posix.system.ICANON);
// flush changes
try std.posix.tcsetattr(in.handle, .FLUSH, termios);
Now the center portion appears like this:
// set immediate input mode
var termios = original_termios;
termios.lflag.ICANON = false;
Right here’s due to the unusual definitions primarily based on packed struct
.
Right here’s as an instance the definition of lflag
for Linux:
pub const tc_lflag_t = switch (native_arch) {
.powerpc, .powerpcle, .powerpc64, .powerpc64le => packed struct(u32) {
_0: u1 = 0,
ECHOE: bool = false,
ECHOK: bool = false,
ECHO: bool = false,
ECHONL: bool = false,
_5: u2 = 0,
ISIG: bool = false,
ICANON: bool = false,
_9: u1 = 0,
IEXTEN: bool = false,
_11: u11 = 0,
TOSTOP: bool = false,
_23: u8 = 0,
NOFLSH: bool = false,
},
.mips, .mipsel, .mips64, .mips64el => packed struct(u32) {
ISIG: bool = false,
ICANON: bool = false,
_2: u1 = 0,
ECHO: bool = false,
ECHOE: bool = false,
ECHOK: bool = false,
ECHONL: bool = false,
NOFLSH: bool = false,
IEXTEN: bool = false,
_9: u6 = 0,
TOSTOP: bool = false,
_: u16 = 0,
},
else => packed struct(u32) {
ISIG: bool = false,
ICANON: bool = false,
_2: u1 = 0,
ECHO: bool = false,
ECHOE: bool = false,
ECHOK: bool = false,
ECHONL: bool = false,
NOFLSH: bool = false,
TOSTOP: bool = false,
_9: u6 = 0,
IEXTEN: bool = false,
_: u16 = 0,
},
};
Many extra std.posix
APIs had been adjusted in a
identical methodology.
std.builtin Enum Fields Lowercased §
Zig 0.12.0 takes the opportunity to regulate the self-discipline names of some enums in std.builtin
to align
with our latest naming conventions, which dictate that enum fields must be snake_case
. The next enums gather been updated:
std.builtin.AtomicOrder
std.builtin.ContainerLayout
std.builtin.Endian
std.builtin.FloatMode
std.builtin.GlobalLinkage
std.builtin.LinkMode
World Configuration §
Previously, when one necessary to override defaults, similar to the logging feature dilapidated by std.log
, they would must clarify std_options
in their root file, like so:
pub const std_options = struct {
pub const logFn = myLogFn;
};
Camouflage how std_options
above is a struct form definiton. In this free up std_options
is now an instance of std.Options
, making the arrangement of defining overrides much less error-inclined.
The code above would watch like this now:
pub const std_options: std.Options = .{
.logFn = myLogFn,
};
And right here is the definition of std.Options
to assemble a study what else it’s doubtless you’ll perchance perchance perchance maybe override.
pub const Options = struct {
enable_segfault_handler: bool = debug.default_enable_segfault_handler,
/// Function used to implement `std.fs.cwd` for WASI.
wasiCwd: fn () os.wasi.fd_t = fs.defaultWasiCwd,
/// The current log level.
log_level: log.Level = log.default_level,
log_scope_levels: []const log.ScopeLevel = &.{},
logFn: fn (
comptime message_level: log.Level,
comptime scope: @TypeOf(.enum_literal),
comptime format: []const u8,
args: anytype,
) void = log.defaultLog,
fmt_max_depth: usize = fmt.default_max_depth,
cryptoRandomSeed: fn (buffer: []u8) void = @import("crypto/tlcsprng.zig").defaultRandomSeed,
crypto_always_getrandom: bool = false,
crypto_fork_safety: bool = true,
/// By default Zig disables SIGPIPE by setting a "no-op" handler for it. Set this option
/// to `true` to prevent that.
///
/// Note that we use a "no-op" handler instead of SIG_IGN because it will not be inherited by
/// any child process.
///
/// SIGPIPE is triggered when a process attempts to write to a broken pipe. By default, SIGPIPE
/// will terminate the process instead of exiting. It doesn't trigger the panic handler so in many
/// cases it's unclear why the process was terminated. By capturing SIGPIPE instead, functions that
/// write to broken pipes will return the EPIPE error (error.BrokenPipe) and the program can handle
/// it like any other error.
keep_sigpipe: bool = false,
/// By default, std.http.Client will support HTTPS connections. Set this option to `true` to
/// disable TLS support.
///
/// This will likely reduce the size of the binary, but it will also make it impossible to
/// make a HTTPS connection.
http_disable_tls: bool = false,
side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations,
};
Pointer Stability Locks §
This provides std.debug.SafetyLock
and uses it in typical library hash maps by adding lockPointers()
and unlockPointers()
.
This provides a methodology to detect when an unlawful modification has took space and fear in wish to invoke undefined behavior:
const std = @import("std");
pub fn main() !void {
const gpa = std.heap.page_allocator;
var map: std.AutoHashMapUnmanaged(i32, i32) = .{};
const gop = try map.getOrPut(gpa, 1234);
map.lockPointers();
defer map.unlockPointers();
gop.value_ptr.* = try calculate(gpa, &map);
}
fn calculate(gpa: std.mem.Allocator, m: anytype) !i32 {
try m.put(gpa, 42, 420);
return 999;
}
$ zig build-exe safety_locks.zig $ ./safety_locks thread 188810 panic: reached unreachable code /home/andy/local/lib/zig/std/debug.zig:403:14: 0x1036b4d in assert (safety_locks) if (!ok) unreachable; // assertion failure ^ /home/andy/local/lib/zig/std/debug.zig:2845:15: 0x10375fb in lock (safety_locks) assert(l.state == .unlocked); ^ /home/andy/local/lib/zig/std/hash_map.zig:1331:44: 0x1066683 in getOrPutContextAdapted__anon_6584 (safety_locks) self.pointer_stability.lock(); ^ /home/andy/local/lib/zig/std/hash_map.zig:1318:56: 0x1037505 in getOrPutContext (safety_locks) const gop = try self.getOrPutContextAdapted(allocator, key, ctx, ctx); ^ /home/andy/local/lib/zig/std/hash_map.zig:1244:52: 0x103765a in putContext (safety_locks) const result = try self.getOrPutContext(allocator, key, ctx); ^ /home/andy/local/lib/zig/std/hash_map.zig:1241:35: 0x1034023 in put (safety_locks) return self.putContext(allocator, key, value, undefined); ^ /home/andy/docgen_tmp/safety_locks.zig:15:14: 0x1033fb6 in calculate__anon_3194 (safety_locks) try m.put(gpa, 42, 420); ^ /home/andy/docgen_tmp/safety_locks.zig:11:36: 0x10341eb in main (safety_locks) gop.value_ptr.* = try calculate(gpa, &map); ^ /home/andy/local/lib/zig/std/start.zig:511:37: 0x1033ec5 in posixCallMainAndExit (safety_locks) const result = root.main() catch |err| { ^ /home/andy/local/lib/zig/std/start.zig:253:5: 0x10339e1 in _start (safety_locks) asm volatile (switch (native_arch) { ^ ???:?:?: 0x0 in ??? (???) (process terminated by signal)
One thing nice about right here is that whenever you occur to spend the “think capability” variants then such mutations are in actuality smartly-outlined, and don’t dwelling off the train:
const std = @import("std");
pub fn main() !void {
const gpa = std.heap.page_allocator;
var map: std.AutoHashMapUnmanaged(i32, i32) = .{};
try map.ensureUnusedCapacity(gpa, 2);
const gop = map.getOrPutAssumeCapacity(1234);
map.lockPointers();
defer map.unlockPointers();
gop.value_ptr.* = calculate(&map);
}
fn calculate(m: anytype) i32 {
m.putAssumeCapacity(42, 420);
return 999;
}
$ zig build-exe assume_capacity.zig $ ./assume_capacity
Observe-up initiatives that did no longer fetch the free up cutoff:
- introduce pointer stability safety locks to array lists
- introduce pointer stability safety locks to MultiArrayList
- add stack traces to pointer stability safety locks
Variety Machine §
Machine Package Mode §
Makes the zig operate intention very much extra friendly to intention equipment maintainers by introducing Machine Integration Alternate choices.
Let’s discover about this characteristic the spend of
groovebasin
as an instance mission:
Potential to Present Non-mandatory Machine Library Integration §
--- a/build.zig
+++ b/build.zig
@@ -5,18 +5,8 @@ pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{
.preferred_optimize_mode = .ReleaseSafe,
});
- const libgroove_optimize_mode = b.option(
- std.builtin.OptimizeMode,
- "libgroove-optimize",
- "override optimization mode of libgroove and its dependencies",
- );
const use_llvm = b.option(bool, "use-llvm", "LLVM backend");
- const groove_dep = b.dependency("groove", .{
- .optimize = libgroove_optimize_mode orelse .ReleaseFast,
- .target = target,
- });
-
b.installDirectory(.{
.source_dir = .{ .path = "public" },
.install_dir = .lib,
@@ -31,7 +21,22 @@ pub fn build(b: *std.Build) void {
.use_llvm = use_llvm,
.use_lld = use_llvm,
});
- server.linkLibrary(groove_dep.artifact("groove"));
+
+ if (b.systemIntegrationOption("groove", .{})) {
+ server.linkSystemLibrary("groove");
+ } else {
+ const libgroove_optimize_mode = b.option(
+ std.builtin.OptimizeMode,
+ "libgroove-optimize",
+ "override optimization mode of libgroove and its dependencies",
+ );
+ const groove_dep = b.dependency("groove", .{
+ .optimize = libgroove_optimize_mode orelse .ReleaseFast,
+ .target = target,
+ });
+ server.linkLibrary(groove_dep.artifact("groove"));
+ }
+
b.installArtifact(server);
const run_cmd = b.addRunArtifact(server);
With this diff plus some identical adjustments in the mission’s dependency tree…
Machine Integration Support Share §
There is a peculiar --help
portion:
System Integration Options: --system [dir] System Package Mode. Disable fetching; prefer system libs -fsys=[name] Enable a system integration -fno-sys=[name] Disable a system integration --host-target [triple] Use the provided target as the host --host-cpu [cpu] Use the provided CPU as the host --host-dynamic-linker [path] Use the provided dynamic linker as the host Available System Integrations: Enabled: groove no z no mp3lame no vorbis no ogg no
The usage of the Machine Integration Alternate choices §
[nix-shell:~/dev/groovebasin]$ zig build -fsys=z [nix-shell:~/dev/groovebasin]$ ldd zig-out/bin/groovebasin linux-vdso.so.1 (0x00007fff054c7000) libz.so.1 => /nix/store/8mw6ssjspf8k1ija88cfldmxlbarl1bb-zlib-1.2.13/lib/libz.so.1 (0x00007fe164675000) libm.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libm.so.6 (0x00007fe164595000) libc.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libc.so.6 (0x00007fe1643ae000) /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib64/ld-linux-x86-64.so.2 (0x00007fe164696000)
Now, re-slump the exclaim however eliminating -fsys=z
:
[nix-shell:~/dev/groovebasin]$ ~/Downloads/zig/build-release/stage4/bin/zig build [nix-shell:~/dev/groovebasin]$ ldd zig-out/bin/groovebasin linux-vdso.so.1 (0x00007ffcc23f6000) libm.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libm.so.6 (0x00007f525feea000) libc.so.6 => /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/libc.so.6 (0x00007f525fd03000) /nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib64/ld-linux-x86-64.so.2 (0x00007f525ffcc000)
Original Delivery Option §
Machine equipment maintainers can provide the unusual --release
option with a opinion to
dwelling a tool-extensive need for optimization mode, whereas respecting the utility developer’s different.
--release[=mode] Request release mode, optionally specifying a preferred optimization mode: fast, safe, small
andy@ark ~/d/a/zlib (main)> zig build --release the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small error: the following build command failed with exit code 1: /home/andy/dev/ayb/zlib/zig-cache/o/6f46a03cb0f5f70d2c891f31086fecc9/build /home/andy/Downloads/zig/build-release/stage3/bin/zig /home/andy/dev/ayb/zlib /home/andy/dev/ayb/zlib/zig-cache /home/andy/.cache/zig --seed 0x3e999c60 --release andy@ark ~/d/a/zlib (main) [1]> zig build --release=safe andy@ark ~/d/a/zlib (main)> vim build.zig andy@ark ~/d/a/zlib (main)> git diff diff --git a/build.zig b/build.zig index 76bbb01..1bc13e6 100644 --- a/build.zig +++ b/build.zig @@ -5,7 +5,9 @@ pub fn build(b: *std.Build) void { const lib = b.addStaticLibrary(.{ .name = "z", .target = b.standardTargetOptions(.{}), - .optimize = b.standardOptimizeOption(.{}), + .optimize = b.standardOptimizeOption(.{ + .preferred_optimize_mode = .ReleaseFast, + }), }); lib.linkLibC(); lib.addCSourceFiles(.{ andy@ark ~/d/a/zlib (main)> zig build --release andy@ark ~/d/a/zlib (main)> zig build --release=small andy@ark ~/d/a/zlib (main)>
This selection also can very smartly be dwelling even supposing the mission’s operate script doesn’t explicitly reveal an optimization
configuration option.
Steer sure of Fetching in Machine Mode §
--system
prevents Zig from fetching functions. As an different, a directory of functions
is equipped, populated presumably by the intention equipment supervisor.
[nix-shell:~/dev/2Pew]$ zig build --system ~/tmp/p -fno-sys=SDL2 error: lazy dependency package not found: /home/andy/tmp/p/1220c5360c9c71c215baa41b46ec18d0711059b48416a2b1cf96c7c2d87b2e8e4cf6 info: remote package fetching disabled due to --system mode info: dependencies might be avoidable depending on build configuration [nix-shell:~/dev/2Pew]$ zig build --system ~/tmp/p [nix-shell:~/dev/2Pew]$ mv ~/.cache/zig/p/1220c5360c9c71c215baa41b46ec18d0711059b48416a2b1cf96c7c2d87b2e8e4cf6 ~/tmp/p [nix-shell:~/dev/2Pew]$ zig build --system ~/tmp/p -fno-sys=SDL2 steps [5/8] zig build-lib SDL2 ReleaseFast native... Compile C Objects [75/128] e_atan2... ^C [nix-shell:~/dev/2Pew]$
Sluggish Dependencies §
--- a/build.zig
+++ b/build.zig
- const groove_dep = b.dependency("groove", .{
- .optimize = libgroove_optimize_mode orelse .ReleaseFast,
- .target = target,
- });
+ if (b.lazyDependency("groove", .{
+ .optimize = libgroove_optimize_mode orelse .ReleaseFast,
+ .target = target,
+ })) |groove_dep| {
+ server.linkLibrary(groove_dep.artifact("groove"));
+ }
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -5,6 +5,7 @@
.groove = .{
.url = "https://github.com/andrewrk/libgroove/archive/66745eae734e986cd478e7220664f2de902d10a1.tar.gz",
.hash = "1220285f0f6b2be336519a0e612a11617c655f78b0efe1cac12fc73fc1e50c7b3e14",
+ .lazy = true,
},
},
.paths = .{
This makes the dependency easiest get fetched if it’s in actuality dilapidated. The
operate runner will be rebuilt if any missing slothful dependencies are
encountered.
There would possibly maybe be an error for the spend of dependency()
as an different of lazyDependency()
:
$ zig build -h thread 2904684 panic: dependency 'groove' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead /home/andy/Downloads/zig/lib/std/debug.zig:434:22: 0x11901a9 in panicExtra__anon_18741 (build) std.builtin.panic(msg, trace, ret_addr); ^ /home/andy/Downloads/zig/lib/std/debug.zig:409:15: 0x1167399 in panic__anon_18199 (build) panicExtra(null, null, format, args); ^ /home/andy/Downloads/zig/lib/std/Build.zig:1861:32: 0x1136dca in dependency__anon_16705 (build) std.debug.panic("dependency '{s}{s}' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead", .{ b.dep_prefix, name }); ^ /home/andy/dev/groovebasin/build.zig:33:40: 0x10e8865 in build (build) const groove_dep = b.dependency("groove", .{ ^ /home/andy/Downloads/zig/lib/std/Build.zig:1982:33: 0x10ca783 in runBuild__anon_8952 (build) .Void => build_zig.build(b), ^ /home/andy/Downloads/zig/lib/build_runner.zig:310:29: 0x10c6708 in main (build) try builder.runBuild(root); ^ /home/andy/Downloads/zig/lib/std/start.zig:585:37: 0x10af845 in posixCallMainAndExit (build) const result = root.main() catch |err| { ^ /home/andy/Downloads/zig/lib/std/start.zig:253:5: 0x10af331 in _start (build) asm volatile (switch (native_arch) { ^ ???:?:?: 0x8 in ??? (???) Unwind information for `???:0x8` was not available, trace may be incomplete error: the following build command crashed: /home/andy/dev/groovebasin/zig-cache/o/20af710f8e0e96a0ccc68c47688b2d0d/build /home/andy/Downloads/zig/build-release/stage3/bin/zig /home/andy/dev/groovebasin /home/andy/dev/groovebasin/zig-cache /home/andy/.cache/zig --seed 0x513e8ce9 -Z4472a09906216280 -h
It be allowed to realize the reverse – lazyDependency()
when the manifest file doesn’t trace it as slothful.
It be doubtlessly most attention-grabbing tell to frequently spend lazyDependency()
in operate.zig.
introduce b.route; deprecate LazyPath.relative §
This provides the *std.Build
proprietor to LazyPath so
that slothful paths returned from a dependency would possibly maybe perchance perchance perchance even be dilapidated in the utility’s
operate script with out friction or footguns.
Migration recordsdata:
Source-Relative LazyPath:
.root_source_file = .{ .path = "src/main.zig" },
↓
.root_source_file = b.path("src/main.zig"),
LazyPath.relative
.root_source_file = LazyPath.relative("src/main.zig"),
↓
.root_source_file = b.path("src/main.zig"),
Test Runner
.test_runner = "path/to/test_runner.zig",
↓
.test_runner = b.path("path/to/test_runner.zig"),
The intent for Compile.installHeader
and company has frequently been to
bundle the headers alongside an artifact, gather them be set in collectively
with the artifact and get automatically added to the encompass search paths
of modules that hyperlink with the artifact.
In Zig 0.11.0, however, these functions modified the default
install
high-stage step of the builder, result in a decision of
sudden results similar to placing in or no longer placing in the headers
looking out on which high-stage operate steps are invoked.
Zig 0.12.0 adjustments it in reveal that set in headers are added to the compile
step itself as an different of editing the high-stage set up step. To contend with the
building of the encompass search route for dependent linking modules, an
middleman WriteFile
step responsible for developing the staunch
encompass tree is created and dwelling up the first time a module hyperlinks to an
artifact.
Migration recordsdata:
installHeader now takes a LazyPath
:
for (headers) |h| lib.installHeader(h, h);
↓
for (headers) |h| lib.installHeader(b.path(h), h);
Compile.installConfigHeader
has had its second argument eliminated and now
uses the stamp of include_path
as its sub route, for parity with
Module.addConfigHeader
. Employ
artifact.installHeader(config_h.getOutput(), "foo.h")
in reveal so that you just can dwelling the sub route to something varied.
lib.installConfigHeader(avconfig_h, .{});
↓
lib.installConfigHeader(avconfig_h);
Compile.installHeadersDirectory
/installHeadersDirectoryOptions
gather been consolidated into Compile.installHeadersDirectory
, which takes a
LazyPath
and permits exclude/encompass filters staunch like InstallDir
.
lib.installHeadersDirectoryOptions(.{
.source_dir = upstream.path(""),
.install_dir = .header,
.install_subdir = "",
.include_extensions = &.{
"zconf.h",
"zlib.h",
},
});
↓
lib.installHeadersDirectory(upstream.path(""), "", .{
.include_extensions = &.{
"zconf.h",
"zlib.h",
},
});
- [Breaking]
b.addInstallHeaderFile
now takes aLazyPath
. - [Breaking] As a workaround for
resurrect emit-h, the generated
-femit-h
header is now never emitted even when the user specifies an
override for h_dir. When you fully need the emitted header, you now
must attaininstall_artifact.emitted_h = artifact.getEmittedH()
until
-femit-h
is mounted. - Added
WriteFile.addCopyDirectory
, which functions very similar to InstallDir. InstallArtifact
has been updated to set up the bundled headers alongide the artifact. The bundled headers are set in to the directory specified by h_dir (which iszig-out/include
by default).
dependencyFromBuildZig §
Given a struct that corresponds to the operate.zig of a dependency, b.dependencyFromBuildZig
returns that very same dependency. In varied phrases, whenever you occur to’ve already a @import
ed a depdency’s operate.zig, it’s doubtless you’ll perchance perchance perchance maybe spend this selection to get the corresponding Dependency
:
// in consumer build.zig
const foo_dep = b.dependencyFromBuildZig(@import("foo"), .{});
This feature will likely be significant for functions that reveal functions from their operate.zig recordsdata that must make spend of their corresponding Dependency
(as an instance, for equipment-relative paths, or for working intention instructions and returning the output as slothful paths). This would possibly maybe well perchance perchance perchance be finished by:
// in dependency build.zig
pub fn getImportantFile(b: *std.Build) std.Build.LazyPath {
const this_dep = b.dependencyFromBuildZig(@This(), .{});
return this_dep.path("file.txt");
}
// in consumer build.zig
const file = @import("foo").getImportantFile(b);
Compiler §
x86 Backend §
The x86 backend is now passing 1765/1828 (97%) of the behavior take a look at suite, compared with the LLVM backend.
It’s far satisfactory alongside that it’s every so usually life like whereas developing, mainly due to the actual fact that it
provides dramatically sooner compilation velocity:
Benchmark 1 (8 runs): zig-0.12.0 build-exe hello.zig measurement mean ± σ min … max outliers delta wall_time 667ms ± 26.7ms 643ms … 729ms 1 (13%) 0% peak_rss 175MB ± 19.3MB 168MB … 223MB 1 (13%) 0% cpu_cycles 3.42G ± 532M 3.21G … 4.74G 1 (13%) 0% instructions 6.20G ± 1.05G 5.83G … 8.79G 1 (13%) 0% cache_references 241M ± 19.9M 234M … 291M 1 (13%) 0% cache_misses 48.3M ± 1.26M 47.7M … 51.4M 1 (13%) 0% branch_misses 35.3M ± 4.07M 33.7M … 45.4M 1 (13%) 0% Benchmark 2 (26 runs): zig-0.12.0 build-exe hello.zig -fno-llvm -fno-lld measurement mean ± σ min … max outliers delta wall_time 196ms ± 5.77ms 187ms … 208ms 0 ( 0%) ⚡- 70.6% ± 1.7% peak_rss 88.7MB ± 721KB 87.8MB … 90.4MB 2 ( 8%) ⚡- 49.3% ± 4.3% cpu_cycles 842M ± 6.01M 836M … 866M 1 ( 4%) ⚡- 75.4% ± 6.0% instructions 1.60G ± 9.62K 1.60G … 1.60G 0 ( 0%) ⚡- 74.1% ± 6.5% cache_references 56.6M ± 378K 56.0M … 57.3M 0 ( 0%) ⚡- 76.6% ± 3.2% cache_misses 8.43M ± 104K 8.30M … 8.79M 2 ( 8%) ⚡- 82.5% ± 1.0% branch_misses 7.20M ± 30.2K 7.15M … 7.28M 2 ( 8%) ⚡- 79.6% ± 4.4%
This backend would possibly maybe perchance perchance perchance even be accessed when compiling for an x86_64 aim by passing the CLI choices
-fno-llvm -fno-lld
, or by environment the operate intention
flags use_llvm
and use_lld
on
std.Build.Step.Compile
to false
. This backend is
now ready to compile many Zig projects, at the side of the compiler itself.
Excellent initiatives until it would possibly perchance perchance perchance even be selected by default as an different of LLVM for debug builds:
- 100% behavior assessments passing
- Improved debug info
- Improved runtime performance
Windows Belongings §
Zig now helps compiling (and execrable-compiling) Windows resource scripts (.rc
recordsdata) and .manifest
recordsdata, and linking the resulting .res
recordsdata into the resource desk of PE/COFF binaries.
- Add a .rc -> .res compiler to the Zig compiler
- Add zig rc subcommand, a (execrable-platform) topple-in substitute for rc.exe
- Add preliminary make stronger for Windows .manifest recordsdata
Look Zig is now also a Windows resource compiler for some spend-cases of this characteristic and little print of how to make spend of it.
Linker §
Zig now helps ELF linking for x86_64, aarch64, and partial make stronger for riscv64.
Dependency on LLD is anticipated to be dropped at some level of the following free up cycle.
The -fno-lld
flag would possibly maybe perchance perchance perchance even be dilapidated to make spend of Zig’s linker the place it’s no longer for the time being the default.
Cache Machine §
This moderately anxious bug is mounted now: error: StreamTooLong when recompiling; reproduction provide recordsdata in cache manifest
The fix, which deduplicates recordsdata listed in the cache manifest, makes cache hits very much sooner.
Information level: cache hit building hello world with static musl libc
Benchmark 1 (61 runs): master/zig build-exe hello.c -target native-native-musl -lc measurement mean ± σ min … max outliers delta wall_time 81.4ms ± 1.76ms 77.7ms … 87.1ms 1 ( 2%) 0% peak_rss 64.6MB ± 77.7KB 64.4MB … 64.7MB 0 ( 0%) 0% cpu_cycles 97.2M ± 1.04M 95.1M … 101M 1 ( 2%) 0% instructions 153M ± 11.1K 152M … 153M 0 ( 0%) 0% cache_references 2.21M ± 97.1K 2.05M … 2.54M 2 ( 3%) 0% cache_misses 529K ± 24.4K 486K … 600K 4 ( 7%) 0% branch_misses 409K ± 6.45K 397K … 437K 1 ( 2%) 0% Benchmark 2 (189 runs): cache-dedup/zig build-exe hello.c -target native-native-musl -lc measurement mean ± σ min … max outliers delta wall_time 25.8ms ± 1.26ms 23.9ms … 30.7ms 11 ( 6%) ⚡- 68.4% ± 0.5% peak_rss 65.2MB ± 61.8KB 65.1MB … 65.4MB 2 ( 1%) 💩+ 1.0% ± 0.0% cpu_cycles 41.2M ± 608K 40.1M … 46.3M 4 ( 2%) ⚡- 57.6% ± 0.2% instructions 64.3M ± 12.6K 64.3M … 64.4M 2 ( 1%) ⚡- 57.8% ± 0.0% cache_references 1.28M ± 34.5K 1.21M … 1.35M 0 ( 0%) ⚡- 41.9% ± 0.7% cache_misses 348K ± 18.6K 297K … 396K 0 ( 0%) ⚡- 34.2% ± 1.1% branch_misses 199K ± 1.34K 197K … 206K 6 ( 3%) ⚡- 51.2% ± 0.2%
Bug Fixes §
Stout list of the 502 bug experiences closed at some level of this free up cycle.
Many bugs had been both launched and resolved within this free up cycle.
Most bug fixes are omitted from these free up notes for the sake of brevity.
Comptime Pointer Catch admission to §
Zig has had quite so much of prolonged-standing bugs touching on to accessing pointers at compile time. When trying to access
pointers in a non-trivial methodology, similar to loading a nick of an array or reinterpreting memory, it’s doubtless you’ll perchance perchance perchance maybe at cases
be greeted with a faux sure compile error stating that the comptime dereference required a favorable form to
gather a smartly-outlined layout.
The merge of #19630 resolves this concern. In Zig 0.12.0,
the compiler must now no longer emit incorrect compile errors when doing advanced issues with comptime memory.
This trade also entails some fixes to the common sense for comptime @bitCast
; in particular,
bitcasting aggregates containing pointers now no longer incorrectly forces the operation to occur at runtime.
This Delivery Incorporates Bugs §
Zig has
known bugs
and even some
miscompilations.
Zig is immature. Even with Zig 0.12.0, working on a non-trivial mission the spend of Zig will
likely require taking fragment in the improvement route of.
When Zig reaches 1.0.0, Tier 1 Make stronger will operate a bug protection as an additional
requirement.
LLVM 17 §
This free up of Zig upgrades to
LLVM 17.0.6.
Zig now generates LLVM bitcode module recordsdata without lengthen and then passes these to LLVM. This
manner that a Zig compiler constructed with out LLVM libraries can mute make .bc
recordsdata,
that will then be passed to clang for compilation.
musl 1.2.4 §
Though musl v1.2.5 is now accessible upstream, this version of Zig
continues to give v1.2.4. The next free up of Zig is anticipated to assemble
the updated musl.
glibc 2.38 §
glibc variations 2.35, 2.36, 2.37, and 2.38 for the time being will likely be found when execrable-compiling.
mingw-w64 §
Essentially primarily based totally on a proposal from Martin Storsjö, Zig now
tracks the latest master division commit of mingw-w64.
Roadmap §
The main theme of the 0.13.0 free up cycle will be compilation velocity.
Some upcoming milestones we are in a position to be practising in the 0.13.0 free up cycle:
- Making the x86 Backend the default backend for debug mode.
- Linker make stronger for COFF. Catch rid of dependency on LLD.
- Enabling incremental compilation for fast rebuilds.
- Introduce Concurrency to semantic diagnosis to further lengthen compilation velocity.
The postulate right here is that prioritizing sooner compilation will lengthen
model velocity on the Compiler itself, resulting in extra bugs
mounted and aspects finished in the following free up cycles.
It also would possibly maybe perchance perchance perchance doubtlessly result in language adjustments that unblock quick compilation.
Async/Await Characteristic Standing §
Async functions regressed with the free up of 0.11.0 (the earlier
free as much as this one). Their future in the Zig language is unclear due to
extra than one unsolved concerns:
- LLVM’s inability to optimize them.
- Third-birthday celebration debuggers’ inability to debug them.
- The cancellation train.
- Async feature pointers stopping the stack size from being known.
These concerns are surmountable, however it completely will plot end time. The Zig team is
for the time being bearing in mind varied priorities.
Thank You Contributors! §
Listed right here are the final these that landed no longer much less than one contribution into this free up:
- Andrew Kelley
- Jakub Konka
- Jacob Younger
- Matthew Lugg
- Robin Voetter
- Igor Anić
- Ryan Liptak
- Veikka Tuominen
- antlilja
- Carl Åstholm
- Luuk de Gram
- Michael Dusan
- Dominic
- Krzysztof Wolicki
- Casey Banner
- Ali Chraghi
- Nameless
- Ian Johnson
- David Rubin
- Meghan Denny
- Marc Tiehuis
- Techatrix
- Xavier Bouchoux
- Bogdan Romanyuk
- Pat Tullmann
- Frank Denis
- Tristan Ross
- Loris Cro
- Stephen Gregoratto
- xdBronch
- Evan Haas
- John Schmidt
- Ryan Zezeski
- expikr
- Elaine Gibson
- MrDmitry
- e4m2
- Adam Goertz
- Jan Philipp Hafer
- Jay Petacat
- Jonathan Marler
- Travis Staloch
- Wooster
- XXIV
- joadnacer
- Jae B
- Kai Jellinghaus
- Linus Groh
- frmdstryr
- Garrett Beck
- Josh Wolfe
- Karl Seguin
- Sahnvour
- february cozzocrea
- fn ⌃ ⌥
- Carter Snook
- Eric Joldasov
- Erik Arvstedt
- Gordon Cassie
- HydroH
- JustinWayland
- Lucas Santos
- Luis Cáceres
- Motiejus Jakštys
- Nguyễn Gia Phong
- Paul Berg
- Pavel Verigo
- Piotr Szlachciak
- Prokop Randáček
- Ratakor
- Stevie Hryciw
- SuperAuguste
- Zachary Raineri
- amp-59
- garrisonhh
- Alex Kladov
- Ben Crist
- Eric Eastwood
- Jan200101
- Jari Vetoniemi
- Jeremy Volkman
- Kang Seonghoon
- Manlio Perillo
- Markus F.X.J. Oberhumer
- Michael Ortmann
- Pascal S. de Kloe
- Philipp Lühmann
- Ruben Dimas
- Sean
- Tobias Simetsreiter
- Tom Read Lowering
- Tw
- Vlad Pănăzan
- cipharius
- jimying
- nikneym
- none
- ocrap7
- riverbl
- snoire
- tjog
- xEgoist
- Abhinav Gupta
- Adrià Arrufat
- Ahmed
- Alex
- Alexander Heinrich
- AlliedEnvy
- Ambareesh “Amby” Balaji
- Amir Alawi
- Andre Herbst
- Andre Weissflog
- Andreas Herrmann
- Anubhab Ghosh
- Arnau
- Artem Kolichenkov
- Aven Bross
- Banacial
- Becker A
- Ben Sinclair
- Brandon Gloomy
- Brandon Botsch
- CPestka
- Chadwain Holness
- Chris Boesch
- Chris Burgess
- Christian Flicker
- Christiano Haesbaert
- Christofer Nolander
- Constantin Bilz
- Constantin Pestka
- Craig O’Connor
- Curtis Tate Wilkinson
- Daniel A.C. Martin
- Daniel Guzman
- David Gonzalez Martin
- DilithiumNitrate
- Dillen Meijboom
- DraagrenKirneh
- Emil Lerch
- Emil Tywoniak
- F3real
- Federico Stra
- Felix Kollmann
- Gregory Anders
- Gregory Mullen
- Guillaume Wenzek
- Gustavo C. Viegas
- Hashi364
- Hong Shick Pak
- Ian Kerins
- Igor Sadikov
- IntegratedQuantum
- Jacob G-W
- James Chen-Smith
- Jan Weidner
- Jeremia Dominguez
- Jiacai Liu
- Jim Calabro
- Joachim Schmidt
- Joel Gustafson
- Johan Jansson
- John Benediktsson
- Jordyfel
- Justus Klausecker
- Kamil T
- Karl Böhlmark
- Khang Nguyen Duy
- Kirk Scheibelhut
- Koakuma
- Lateef Jackson
- Lauri Tirkkonen
- Lee Cannon
- Leo Emar-Kar
- Leonardo Gatti
- Lewis Gaul
- LinuxUserGD
- Littleote
- Liviu Dudau
- LordMZTE
- Luca Ivaldi
- Lucas Culverhouse
- Maciej ‘vesim’ Kuliński
- Marcius
- Mason Remaley
- Matt Knight
- Matthew Wozniak
- Maximilian
- Michael Bradshaw
- Michael Lynch
- Michael Pfaff
- Michael Scott
- Michal Ziulek
- Mikko Kaihlavirta
- Minsoo Choo
- Mustafa Uzun
- Naboris
- Nan Zhong
- Niles Salter
- Nitin Prakash
- OK Ryoko
- PanSashko
- Paul Jimenez
- PauloCampana
- Peng He
- Phil Richards
- Prcuvu
- Purrie
- Pyry Kovanen
- Qusai Hroub
- Rafael Fernández López
- Rahul Prabhu
- Reokodoku
- Robinson Collado
- Roman Frołow
- Ryan Barth
- Samuel Fiedler
- Samuel Nevarez
- Scott Schwarz
- Sebastien Marie
- Simon Brown
- Stefan Su
- Stephen Gutekanst
- Tim Culverhouse
- Tobias Simetsreiter
- Tomasz Lisowski
- Vitalijus Valantiejus
- Frosty weather
- andrewkraevskii
- arbrk1
- bfredl
- binarycraft007
- castholm
- cdrmack
- cfillion
- crayon
- cryptocode
- danielsan901998
- davideger
- dbandstra
- dhash
- dundargoc
- emberfade
- hdert
- iwVerve
- jacwil
- jaina heartles
- jd
- leap123
- lockbox
- loris
- mataha
- melonedo
- mllken
- ndbn
- notcancername
- pancelor
- paoda
- radar roark
- regeliv
- salo-dea
- sammy j
- tinusgraglin
- tison
- vinnichase
- yunsh1
- zhylmzr
- Андрей Краевский
Special due to of us that sponsor Zig.
Because of of ordinary donations, Zig is pushed by the originate provide neighborhood, moderately
than the neutral of developing profit. Severely, these just appropriate-wanting of us sponsor Zig
for $50/month or extra:
- Josh
Wolfe - Matt Knight
- Stevie
Hryciw - Jethro
Nederhof - Karrick
McDermott - José M
Rico - drfuchs
- Joran Dirk Greef
- Rui
Ueyama - bfredl
- Simon A.
Nielsen Knights - Stephen
Gutekanst - Derek
Collison - Daniele
Cocca - Rafael
Batiati - Aras
Pranckevičius - Terin Inventory
- Loïc Tosser
- Kirk
Scheibelhut - Mitchell
Hashimoto - Brian
Gold - Paul
Harrington - Clark
Gaebel - Bun
- Marcus
Eagan - Ken
Chilton - Sebastian
- Will
Manning - Fulcrum Labs
- Alex Mackenzie at
Tapestry VC - Alok
Parlikar - Viktor
Tratsevskyy - johnpyp
- Huly® Platform™
- Reuben Dunnington
- Isaac Yonemoto
- Luuk de Gram
- Auguste Rame
- Jay Petacat
- Dirk de Visser
- Santiago Andaluz
- Andrew Mangogna
- Yaroslav Zhavoronkov
- Christian Wesselhoeft
- Anton Kochkov
- Max Bernstein
- James McGill
- Luke Champine
- AG.王爱国
- Wojtek Mach
- Nicola Larosa
- Daniel Hensley
- cryptocode
- Erik Mållberg
- Collin Kemper
- Fabio Arnold
- Tom Read Lowering
- Ross Rheingans-Yoo
- Emily A. Bellows
- Justin “J.R.” Hill
- Mykhailo Tsiuptsiun
- Kiril Mihaylov
- Brett Slatkin
- Sean Carey
- Yurii Rashkovskii
- Benjamin Ebby
- Ralph Brorsen
- OM PropTech GmbH
- Alex Sergeev
- Pierre Curto
- Kemal Akkoyun
- Marco Munizaga
- Josh Ashby
- Chris 1st Earl Baldwin of Bewdley
- Malcolm Soundless
- Viktor Hellström
- Francis Bouvier
- Fawzi Mohamed
- Alve Larsson
- Nicolas Goy
- Ian Johnson
- Carlos Pizano Uribe
- Rene Schallner
- Linus Groh
- Jinkyu Yi
- jake hemmerle
- Will Pragnell
- Nathan Youngman
- Peter Snelgrove
- Jeff Fowler
- Nate
- Samu
- foxnne
- Christian Gibson
- 11sync.web
- impactaky
- Dylan Conway
- Hlib Kanunnikov
- merkleplant
- Omar AlSuwaidi