https://ziglang.org/download/0.9.0/release-notes.html 0.9.0 Release Notes Zero the Ziguana Download & Documentation Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software. Backed by the Zig Software Foundation, the project is financially sustainable. These core team members work on Zig full-time: * Andrew Kelley * Loris Cro * Jakub Konka Please consider a recurring donating to the ZSF to help us pay more contributors! This release features 6 months of work: changes from 177 different contributors, spread among 2023 commits. One sentence summary: The Toolchain "just works" in more cases, many bugs were fixed, the Self-Hosted Compiler is 44% complete, the Support Table is expanded, there were a handful of Language Changes, the project started Performance Tracking, and the Standard Library, although unstable, became more useful. Table of Contents SS * Table of Contents * Isaac Freund Joins the Core Zig Team * Support Table + Tier System o Tier 1 Support o Tier 2 Support o Tier 3 Support o Tier 4 Support + WebAssembly o WASI + 32-bit x86 + RISC-V + NetBSD + Windows o ARM64 Windows + UEFI + iOS + Solaris/Illumos + Haiku + macOS o Versioned C Headers + Linux o io_uring + OpenBSD + SPARC + Plan 9 + Custom Operating Systems * Documentation * Language Changes + More Builtins Return String Literals + @minimum and @maximum + @select + SIMD + @intToEnum Implicitly Performs @intCast + Shadowing Declarations + Keywords Deleted: true, false, undefined, null + usingnamespace No Longer Affects Identifier Lookup + c_void renamed to anyopaque + Saturating Arithmetic + Compile Errors for Unused Locals + @export with Field Access + Inline Assembly Requires String Literals + @prefetch * Bootstrap Compiler + Better Awareness of Unwind Tables + Moved Unreachable Code Errors to Self-Hosted * Self-Hosted Compiler + Parser + LLVM Backend + C Backend + x86 Backend + aarch64 Backend + Self-Hosted Linker + C Translation + Cache System o Shared Cache Locking o Improved Handling of Generated File builtin.zig o Detection of Problematic Timestamps o Improved Hashing Logic + Debug Crash Handler + Stop Guessing Whether the System Can Execute Binaries + Link Dynamic Libraries As-Needed by Default * Standard Library + Deprecations + Additional API + Crypto + Math + JSON + Formatted Printing + Threading o Mutex Lock/Unlock + Allocgate + Random Interface + Hash Maps + Logging o Only 4 Log Levels + Namespacing of OS Bits * Bug Fixes + This Release Contains Bugs * Zig Build System + Generated Files as Inputs + Build Options + Executors * Toolchain + LLVM 13 + musl 1.2.2 + glibc 2.34 o Native Version Detection + mingw-w64 9.0.0 + libunwind + libcxx + zig cc + zig c++ + zig fmt + zig ar + Objective-C and Objective-C++ + compiler-rt * Performance Tracking * Continuous Integration * Roadmap + Package Manager Status + Accepted Proposals * Thank You Sponsors! Isaac Freund Joins the Core Zig Team SS Ziggy the Ziguana To many, the reaction to this announcement will be something like, "Oh? I thought he was already on the core zig team." This goes to show how obvious this decision was. Isaac is a level-headed, talented, careful, patient, and diligent programmer. You might be viewing these release notes through his dynamic tiling Wayland compositor, River. He also works on TigerBeetle - the world's fastest financial accounting database. In addition to lending his technical expertise to the Zig project, Isaac has proven to be a steadfast community leader, setting an example for how to treat others with kindness and respect. Please give him a warm welcome to the core Zig team. Support Table SS Tier System SS A green check mark () indicates the target meets all the requirements for the support tier. The other icons indicate what is preventing the target from reaching the support tier. In other words, the icons are to-do items. If you find any wrong data here please submit a pull request! Tier 1 Support SS * Not only can Zig generate machine code for these targets, but the standard library cross-platform abstractions have implementations for these targets. * The CI server automatically tests these targets on every commit to master branch. * The CI server automatically produces pre-built binaries for these targets, on every commit to master, and updates the download page with links. * These targets have debug info capabilities and therefore produce stack traces on failed assertions. * libc is available for this target even when cross compiling. * All the behavior tests and applicable standard library tests pass for this target. All language features are known to work correctly. Experimental features do not count towards disqualifying an operating system or architecture from Tier 1. * zig cc, zig c++ and related toolchain commands support this target. * If the Operating System is proprietary then the target is not marked deprecated by the vendor, such as macos/x86. freestanding Linux 3.16+ macOS 10.13+ Windows 8.1+ WASI x86_64 N/A x86 #1929 #537 N/A aarch64 #2443 N/A arm #3174 N/A mips #3345 N/A N/A N/A riscv64 #4456 N/A N/A N/A sparcv9 #4931 N/A N/A N/A wasm32 N/A N/A N/A Tier 2 Support SS * The standard library supports this target, but it's possible that some APIs will give an "Unsupported OS" compile error. One can link with libc or other libraries to fill in the gaps in the standard library. * These targets are known to work, but may not be automatically tested, so there are occasional regressions. * Some tests may be disabled for these targets as we work toward Tier 1 Support. free Linux macOS Windows FreeBSD NetBSD DragonFlyBSD UEFI standing 3.16+ 10.13+ 8.1+ 12.0+ 8.0+ 5.8+ x86_64 Tier 1 Tier Tier 1 Tier 1 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 N/A N/A N/A powerpc N/A N/A N/A riscv64 Tier 1 N/A N/A N/A sparcv9 Tier 1 N/A N/A N/A N/A Tier 3 Support SS * The standard library has little to no knowledge of the existence of this target. * If this target is provided by LLVM, LLVM has the target enabled by default. * These targets are not frequently tested; one will likely need to contribute to Zig in order to build for these targets. * The Zig compiler might need to be updated with a few things such as + what sizes are the C integer types + C ABI calling convention for this target + start code and default panic handler * zig targets is guaranteed to include this target. freestanding Linux Windows FreeBSD NetBSD UEFI 3.16+ 8.1+ 12.0+ 8.0+ 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 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 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 Support SS * Support for these targets is entirely experimental. * If this target is provided by LLVM, LLVM may have the target as an experimental target, which means that you need to use Zig-provided binaries for the target to be available, or build LLVM from source with special configure flags. zig targets will display the target if it is available. * This target may be considered deprecated by an official party, such as macosx/i386 in which case this target will remain forever stuck in Tier 4. * This target may only support -femit-asm and cannot emit object files (-fno-emit-bin enabled by default and cannot 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, because Apple has officially dropped support for them. WebAssembly SS Luuk de Gram writes: During this release we hit some major milestones. The Self-Hosted Linker for wasm was rewritten, with knowledge gained from building a stand-alone wasm linker. The linker is now capable of building a memory layout with a virtual stack, as well as perform relocations. Those are some of the neccesary features required to be able to implement zig test. As of today, the self-hosted wasm backend is now capable of passing 13% of all the behavioral tests. With all of those changes, contributing to the wasm backend is made a lot easier. The linker is now capable enough where only knowledge about wasm is required to contribute to the backend. Those features were implemented in the following Pull Requests: * Implement the MIR pass (#10153) * Upstream zwld (partly) into wasm backend (#10229) * Implement zig test (#10240) * Initial behavior tests succeeding (#10275) The following 4 new linker flags were added for WebAssembly (#8633): * --import-memory - import memory from the environment * --initial-memory=[bytes] - initial size of the linear memory * --max-memory=[bytes] - maximum size of the linear memory * --global-base=[addr] - where to start to place global data With these items addressed, Zig is one of the supported languages for the WASM-4 Fantasy Console. Tom, the creator of Context Free, is hosting a game jam on January 14 - 23. Additionally, the linker frontend for wasm targets now supports the following flags: * --export: Forces a symbol to be exported to the host environment. * -rdynamic: Adds all symbols to the dynamic symbol table (known as --dynamic-export in wasm-ld). Contributors: Luuk de Gram, Takeshi Yoneda, Jakub Konka, Andrew Kelley WASI SS WebAssembly System Interface is a pseudo-operating system that provides sandboxed I/O and other system capabilities to WebAssembly. * wasi libc: fix wasm-ld failure in matching libc symbols, and enable tests (#9227). * link: don't link system libraries by the wasm-ld linker. The only allowed system libraries that we can link are libraries that are part of the sysroot such as libc or WASI emulated subcomponents. This is required as Wasm allows to defer symbol resolution until load time. For example, specifying that an import is coming from wasi_snapshot_preview1 should not generate a link flag -lwasi_snapshot_preview1 on the linker line as this is not a system library that needs to be imported at link-time, but a system library that is provided by the runtime at load-time. * include emulated libs in WASI libc (#8992). * added support for WASI reactor in pure Zig executables (#9178) (# 9605). * improved integration with wasi-libc. * always grant fd_readdir right. 32-bit x86 SS Zig now has Continuous Integration testing enabled for Linux builds against glibc. RISC-V SS * Fix RISC-V assembly CPU features. Previously, Zig did not properly communicate the target CPU features for RISC-V to clang assembler, because Clang has a different way to pass CPU features for C code and for assembly code. This commit makes Zig pass a RISC-V -march flag in order to communicate CPU features to Clang when compiling assembly files. * Default target-abi based on RISC-V extensions and user selectable -mabi/target-abi (#10006). Contributors: Andrew Kelley, Michael Dusan, vole-dev NetBSD SS * Added args to limit number of PT_LOAD segs (#9109). * Added more std.os bits. Windows SS * Zig now looks for more DLL import lib path names. When linking with -lfoo syntax, this indicates to Zig that the dependency should either be provided by Zig, or it should be dynamically provided by the system. For windows-gnu targets, the search path was "foo.lib". Now it additionally looks for "libfoo.dll.a" (# 7799). * Removed the TCHAR idiom entirely. * std.Progress: use *W functions instead of *A functions (#534). This eliminates the last and final call to any A functions so now we are properly using only W functions in the Standard Library. * Added definitions for winmm.dll (#8801). * Fixed OVERLAPPED, add OVERLAPPED_ENTRY. * Support emitting DWARF on Windows (#8717). * Improved error for unsupported async sockets. * Fixed deadlock in ChildProcess (#9148). * Fixed compile error: "'bMenu' needs to casted" (#9426). * Removed WIN16 version of WSAOVERLAPPED. Use LPWSAOVERLAPPED_COMPLETION_ROUTINE. * Fixed Standard Library path resolution. GetCurrentDirectory returns a path with a trailing slash if and only if the cwd is a root directory, making the code in resolveWindows return an invalid path with two consecutive slashes (#10093). * Disable LTO by default on Windows when linking libc++ due to LLVM bugs (#8531). Contributors: Andrew Kelley, viri, mchudleigh, Jonathan Marler, Travis Martin, LemonBoy ARM64 Windows SS 0.9.0 is the first release which publishes a build of Zig for ARM64 Windows (#9102): zig-windows-aarch64-0.9.0.zip Be warned that it has not been properly tested yet; Zig developers are still in the process of acquiring the hardware needed to run ARM64 Windows. Thanks to Martin Storsjo for the tip about the ECS LIVA Mini Box QC710. UEFI SS * boot_services: allow custom MemoryTypes. * Fixed packed struct bitfields. * FileProtocol: add Reader, Writer, SeekableStream. * MemoryDescriptor: fixed padding after memory type. * Added virtual addressing helpers (#10195). Contributors: Stephen von Takach, Nameless, Sreehari Sreedev iOS SS Thanks to major improvements in the Self-Hosted Linker combined with support for compiling Objective-C, along with miscellaneous improvements in the Self-Hosted Compiler, Zig now targets iOS and iPhone Simulator platforms. See kubkon/zig-ios-example for a complete example. (#9532) Solaris/Illumos SS Initial bringup of the Solaris/Illumos port by Stephen Gregoratto. Haiku SS Improved Haiku support in the Standard Library by Al Hoang (#10073). Thanks to waddlesplash for stopping by and reviewing the patch. macOS SS Generally, Zig 0.9.0 works much better than 0.8.x on macOS, due to major improvements in the Self-Hosted Linker, Versioned C Headers, and miscellaneous improvements, such as: * Improved SDK detection and linker integration with _mh_execute_header (#10217). * Fixed stack traces in aarch64-macos and when linking with ld64 (# 10225). * Fixed ulock usage (#9545). Versioned C Headers SS The fetch-them-macos-headers project has been improved to account for headers from multiple versions of macOS. Currently, these versions are 10 (Catalina), 11 (Big Sur), and 12 (Monterey). As Apple releases new major versions of macOS, this project will track the latest three, which matches the security update policy of Apple. The tool has been improved to detect which files are different across both versions and architectures, dividing the files up into eight categories: * aarch64-macos.11 * aarch64-macos.12 * x86_64-macos.10 * x86_64-macos.11 * x86_64-macos.12 * any-macos * any-macos.11 * any-macos.12 Files that are common between multiple categories are put into the "any" ones, as least specific as possible, to save on installation size. Long story short, this fixes bugs having to do with incompatible header files, and comes at a minimal cost of additional installation size: Before these changes: * macOS C headers and .tbd files total installation size: 6.1 MiB (534 KB tarball size) * supported triples: + x86_64-macos.11 (Big Sur) + aarch64-macos.11 (Big Sur) After these changes: * macOS C headers and .tbd files total installation size: 13.1 MiB (581 KB tarball size) * supported triples: + x86_64-macos.10 (Catalina) + x86_64-macos.11 (Big Sur) + x86_64-macos.12 (Monterey) + aarch64-macos.11 (Big Sur) + aarch64-macos.12 (Monterey) Linux SS * Updated libc Linux headers to v5.16-rc3 (#9837). Additionally, the headers have been compacted to reduce installation size by sharing x86 and x86_64 headers in the same directory. There is a new tool for Zig maintainers to use to upgrade libc Linux headers in the future. * Fixed some BPF fn definitions. Cross-checked with bpf.h of kernel 5.12.9. * Added Linux XDP bits (#9019). * Added fadvise support. * Added waitid syscall (#9335). * Added mknod and mknodat syscalls. * Added inotify_rm_watch definition and made inotify_add_watch's pathname marked as null-terminated. * Fixed definition of RW flags (#9428). * Added missing FUTEX definitions. * Added recent clone/clone3 and missing signalfd flags. * Fixed rlimit_resource for MIPS and SPARC (#9227). * Added Linux ioctl creation utilities (#9748). * Updated syscall numbers for 5.14. * Fixed edge case in TLS tp calculation. * Added missing termios definitions (#9707). * Added perf syscall bits (#10088). * Fixed invalid errno definition for Android. * EBADLIB in execve now maps to error.InvalidExe rather than error.Unexpected. Contributors: Andrew Kelley, LemonBoy, Jens Goldberg, Vincent Rischmann, Aydin Mercan, Kenta Iwasaki, Hiroaki Nakamura, Felix "xq" Queissner io_uring SS * Addd sqe prep methods for epoll_ctl, poll_add, and poll_remove. * Exposed register_eventfd, register_eventfd_async, unregister_eventfd (#9449). * Implement read_fixed/write_fixed. * Implement statx. * Added poll_update. Additionally added a method from liburing to queue (but not submit) a SQE to update the user data of an existing poll operation. * Added cancel and io_uring_prep_cancel (#10081). * Implemented register_files_update. * Added link_timeout (#10151). * Added more opcodes (#10322). OpenBSD SS * Fix dynamic linker path (#9010). * Event loop: use EVFILT_TIMER instead of EVFILT_USER. OpenBSD doesn't implement EVFILT_USER filter for kqueue(2), so we couldn't use that for event loop. Instead, use a EVFILT_TIMER filter with EV_ONESHOT (trigger only once) and delay 0sec (which trigger immediatly). It fits the usage of EVFILT_USER which is only used to "wakeup" the kevent(2) call from userland. * Added termios constants to std.c.openbsd (#10178). Contributors: Sebastien Marie, Dante Catalfamo SPARC SS * SPARCv9: use C calling convention for restore_rt. Prevents infinite loop when calling rt_sigreturn. * Add missing C type definitions. * Miscellaneous improvements resulting in more behavior tests passing (#9853). * Threading: added a freeAndExit() implementation. Contributors: Koakuma Plan 9 SS A new linker backend for the Plan9 a.out executable format has been written for the Self-Hosted Compiler by Jacob G-W. The linker only works with the x86_64 and aarch64 backends because LLVM cannot emit Plan9 object files. Experimental source location debug info is emitted from this linker. It can be used with -target x86_64-plan9. Hopefully Zig can soon join Go as the second modern language that is a first class citizen on Plan9! Custom Operating Systems SS People have started to use Zig to build their own operating systems due to the standard library being available and unopinionated. Some improvements to this use case in 0.9.0: * Made Linux syscalls accessible even when targeting non-Linux. * Ability to override MAX_PATH_BYTES for custom operating systems. * Moved Standard Library iovec and log levels to a common area, allowing only the OSes that uses them to import them, and removing dependencies on bits.zig for the os//.zig files. * Fixed issue where root.os.panic could return. Contributors: N00byEdge, mason1920, rgreenblatt Documentation SS Ziggy the Ziguana * New section: C Translation CLI * New section: C Translation Caching * New section: Translation Failures * New section: C Macros * Miscellaneous minor improvements and corrections. Contributors: Andrew Kelley, pfg, Mr. Paul, Daniele Cocca, Lee Cannon, Travis Staloch, Jacob G-W, Robin Voetter, Auguste Rame, Meghan, Michael Byrne, David May, Dmitry Matveyev, Evan Haas, Exonorid, Isaac Freund, Jarred Sumner, Jonathan Marler, Josh Soref, Nathan Michaels, Norberto Martinez, Nulo, Paul, Philipp Luhmann, Roman Frolow, Rory O'Kane, Veikka Tuominen, bnprks, kprotty, travisstaloch, yetanothercheer Language Changes SS @byteOffsetOf is renamed to @offsetOf. zig fmt automatically performs this upgrade for you. More Builtins Return String Literals SS @tagName, @errorName, @typeName, and @embedFile now have a return type of *[N:0]const u8 instead of []const u8. This means that these builtins can be used anywhere a string literal would be used. In other words, they can be coerced into any of these types: * []const u8 (slice which has pointer and length) * [*:0]const u8 (null-terminated pointer) * [:0]const u8 (slice which has pointer and length and is also guaranteed by the type system to have a null byte at the end, which is not counted in the length) Similarly, the file and fn_name fields of std.builtin.SourceLocation returned by @src now are [:0]const u8, making it possible to pass them as null-terminated strings without copying them. @minimum and @maximum SS New builtins: @minimum and @maximum These builtins accept integers, floats, and vectors of either. In the latter case, the operation is performed element wise. NaNs are handled as follows: if one of the operands of a (pairwise) operation is NaN, the other operand is returned. If both operands are NaN, NaN is returned. See also: SIMD @select SS New builtin: @select @select(comptime T: type, pred: @Vector(len, bool), a: @Vector(len, T), b: @Vector(len, T)) @Vector(len, T) Selects values element-wise from a or b based on pred. If pred[i] is true, the corresponding element in the result will be a[i] and otherwise b[i]. See also: SIMD SIMD SS In this release, the following builtins have been improved to support SIMD vectors: * @popCount * @ctz * @clz These SIMD-enabled builtins are new in 0.9.0: * @select * @minimum and @maximum SIMD support in Zig pretty far along, with more improvements still planned. If you try to use SIMD in your Zig codebase and you find that it does not satisfy your use case, we want to hear from you! Please open an issue and describe the situation. SIMD Vector Syntax is planned so that one is not required to use @Vector. Documentation in the language reference is bare bones and needs to be fleshed out. There is still some missing functionality which you can see listed in #903. The focus now has shifted to implementing SIMD in the Self-Hosted Compiler since that is ultimately what everyone will be using. @intToEnum Implicitly Performs @intCast SS This is a backwards-compatible language change. Previously, @intToEnum coerced its integer operand to the integer tag type of the destination enum type, often requiring the callsite to additionally wrap the operand in an @intCast. Now, the @intCast is implicit, and any integer operand can be passed to @intToEnum. The same as before, it is illegal behavior to pass any integer which does not have a corresponding enum tag. In summary, you can change this: return @intToEnum(Tag, @intCast(@typeInfo(Tag).Enum.tag_type, number)); ...into this: return @intToEnum(Tag, number); Shadowing Declarations SS Locals are never allowed to shadow declarations, but declarations will sometimes need to have the same name as each other. Consider this case: pub const List = struct { head: *Node, pub const Node = struct { bar: i32, next: *Node, pub fn init() Node { // ... } }; pub fn init() List { // ... } }; Consider the full namespace paths of the functions: * List.init * List.Node.init This is completely reasonable and expected, but it causes, within the scope of Node, for the init identifier to be ambiguous. For example, if we reference the init function from the inner scope, we get an error: test.zig pub const List = struct { head: *Node, pub const Node = struct { bar: i32, next: *Node, pub fn init() Node { // ... } test "example" { _ = init; } }; pub fn init() List { // ... } }; Shell $ zig test test.zig docgen_tmp/test.zig:13:17: error: ambiguous reference _ = init; ^ docgen_tmp/test.zig:8:13: note: declared here pub fn init() Node { ^ docgen_tmp/test.zig:17:9: note: also declared here pub fn init() List { ^ This is resolved by eliminating the ambiguity by accessing the function via its namespace: pub const List = struct { head: *Node, pub const Node = struct { bar: i32, next: *Node, pub fn init() Node { // ... } test "example" { _ = Node.init; _ = List.init; } }; pub fn init() List { // ... } }; No error this time. Similarly, variables are now allowed to have the same names as primitives such as i32 and null, however they must use the @"" sytax in order to disambiguate (#6062). The motivation for these language decisions is to reduce the amount of non-local awareness a person reading Zig code must have in order to confidently make changes. Keywords Deleted: true, false, undefined, null SS Now these are primitives provided by the language, same as void, u32, etc. Consequently one can now use these tokens as, for example, struct field names: const Foo = struct { true: i32, false: i32, undefined: i32, null: i32, }; However it is still required to use @"" syntax to disambiguate between references to primitives or same-named identifiers. Example: test.zig test "example" { var i32: bool = true; } Shell $ zig test test.zig docgen_tmp/test.zig:2:9: error: name shadows primitive 'i32' var i32: bool = true; ^ docgen_tmp/test.zig:2:9: note: consider using @"i32" to disambiguate var i32: bool = true; ^ usingnamespace No Longer Affects Identifier Lookup SS This is a breaking change that is likely to affect most codebases. usingnamespace no longer imports identifiers into the current namespace: undeclared.zig const std = @import("std"); usingnamespace std.debug; pub fn main() !void { try print("hello", .{}); } Shell $ zig build-exe undeclared.zig docgen_tmp/undeclared.zig:6:9: error: use of undeclared identifier 'print' try print("hello", .{}); ^ It can still be used, however, to add declarations to a namespace. For example, a file called c.zig which contains the following: pub usingnamespace @cImport({ @cInclude("stdio.h"); @cInclude("math.h"); @cInclude("time.h"); @cInclude("epoxy/gl.h"); @cInclude("GLFW/glfw3.h"); @cDefine("STBI_ONLY_PNG", ""); @cDefine("STBI_NO_STDIO", ""); @cInclude("stb_image.h"); }); This was the intended use case for usingnamespace all along, and it still works the same. The motivations for this change are: * It limits the programmer's ability to abuse the feature, decreasing the potential amount of non-local awareness a person reading Zig code must have in order to confidently make changes. * It makes it possible for the compiler to look up identifiers prior to type-checking. This has two benefits: + Enables the compiler to report Compile Errors for Unused Locals. + Improves compilation speed. Compilation speed is a serious goal of the project. Zig the language is willing to take on restrictions and design limitations in order to facilitate potential compilation speed enhancements. There is an open proposal to rename the keyword. c_void renamed to anyopaque SS c_void actually has nothing to do with C; it is just an opaque type that has some relaxed coercion rules surrounding type erasure. In Zig 0.9.0 it is renamed to anyopaque but it has the exact same semantics. zig fmt automatically performs the rename. Saturating Arithmetic SS Zig now has syntax to perform arithmetic that does not wrap, overflow, or invoke illegal behavior. Instead, if the result does not fit into the destination type, the value is clamped to the minimum or maximum: saturating_arithmetic.zig const std = @import("std"); const expect = std.testing.expect; test "example" { var x: u8 = 200; var y: u8 = 100; try expect(x +| y == 255); try expect(y -| x == 0); try expect(y *| x == 255); try expect(y <<| x == 255); } Shell $ zig test saturating_arithmetic.zig 1/1 test "example"... OK All 1 tests passed. Relevant issues: #9949 #9679 #9619 Compile Errors for Unused Locals SS It is no longer possible to have a local variable or parameter that is not referenced: test.zig test "example" { var x: i32 = 1234; } Shell $ zig test test.zig docgen_tmp/test.zig:2:9: error: unused local variable var x: i32 = 1234; ^ This has been planned since before 0.1.0 was released, and it is planned to introduce more compile errors for unused things, despite this having been a controversial change. Zig will never have a "sloppy mode" flag. The motivation for this change is helping with refactoring and reworking code, and preventing bugs, ultimately saving developer time. If a local is intentionally unused, it can be discarded, like this: unused.zig test "example" { var x: i32 = 1234; _ = x; } Shell $ zig test unused.zig 1/1 test "example"... OK All 1 tests passed. Zero the Ziguana The eventual goal for the developer experience related to errors for unused things is that it will work similar to the "Organize Imports" button in Eclipse that Java developers are familiar with. Idea being that IDEs would have a simple keyboard shortcut that would automatically add discards for all unused things, eliminating this compile error as a stumbling block when a developer is experimenting, and yet ensuring that the source code on disk documents the code smell with explicit discarding of unused things. Another possibility is that zig fmt could grow a --fix-unused flag, performing this hypothetical operation outlined above. @export with Field Access SS @export creates a symbol in the output object file. Previously, declaration must be an identifier. Now, it could be field access expression: * An identifier (x) identifying a function or a variable. * Field access (x.y) looking up a function or a variable. Inline Assembly Requires String Literals SS The end-game for inline assembly is that the syntax is more integrated with Zig, and it will not allow string concatenation for the assembler code, for the same reasons that Zig does not have a preprocessor. However, inline assembly in zig right now is lacking for a variety of use cases (take a look at the open issues having to do with inline assembly for example), and being able to use comptime expressions to concatenate text is a workaround that real-world users are exploiting to get by in the short term. This release introduces "assembly code must use string literal syntax" as a compile error when using the Self-Hosted Compiler, but allows it through when using the Bootstrap Compiler. @prefetch SS New builtin: @prefetch @prefetch(ptr: anytype, comptime options: std.builtin.PrefetchOptions) This builtin tells the compiler to emit a prefetch instruction if supported by the target CPU. If the target CPU does not support the requested prefetch instruction, this builtin is a noop. This function has no effect on the behavior of the program, only on the performance characteristics. The ptr argument may be any pointer type and determines the memory address to prefetch. This function does not dereference the pointer; it is perfectly legal to pass a pointer to invalid memory to this function and no illegal behavior will result. The options argument is the following struct: builtin.zig /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const PrefetchOptions = struct { /// Whether the prefetch should prepare for a read or a write. rw: Rw = .read, /// 0 means no temporal locality. That is, the data can be immediately /// dropped from the cache after it is accessed. /// /// 3 means high temporal locality. That is, the data should be kept in /// the cache as it is likely to be accessed again soon. locality: u2 = 3, /// The cache that the prefetch should be preformed on. cache: Cache = .data, pub const Rw = enum { read, write, }; pub const Cache = enum { instruction, data, }; }; Bootstrap Compiler SS In the previous release, as well as this release, the main Zig compiler everybody uses is the bootstrap compiler, written in C++, also known as "stage1". Despite the main focus of this release cycle being the Self-Hosted Compiler, there were some improvements to stage1 as well. * Fix SIMD instructions not respecting target CPU features when LTO is enabled (#8965). * Store the specified code model in the LLVM module, ensuring that LTO builds pick up the correct model (#9132). * Fix initialization of tuples with array literals (now it works). * Fix render_const_value for printing const optional pointers. * Make @truncate to an integer type of different sign an error at comptime too. * CLI: remove --verbose-ast and --verbose-tokenize (#9034). * Fix handling of C ABI parameters split in multiple regs by taking into account the increased number of parameters when flattening a structure into one or more SSE registers (#9061). * Fix zig0 help message (#9140). * Fix @shuffle type and mask parameters to imply a comptime scope for the expression. * Fix unexpected truncation behavior with comptime_int larger than u64 range (#9303) (#9299). * Compilation speed is enhanced by 19% by improving hash functions. * Compilation RAM usage is reduced by 5% by avoiding wasting padding with IR instruction tags and by removing an unneeded field. * Fix bigint_shl (#9305). * Add c_longdouble mapping for the s390x architecture. * Expand SysV C ABI compatibility for small structs. * Fix anonymous struct naming in some cases (#4330) (#9339). * Add mask before truncating dereferenced bit pointers (#9584). Resulted in an LLVM bug fix. * Work around LLVM's buggy fma lowering by lowering @mulAdd directly to a call to fmaq instead of to the LLVM intristic because LLVM will lower it to fmal even when the target's long double is not equivalent to f128. * Fix zig test --verbose-air crashing on an empty file (#10031). * Fix path normalization on Windows by backporting a missing change from the Self-Hosted Compiler (#9465). * Fix type mapping for integers and c_longdouble for the nvptx architecture. * Fix linking errors with floorl on MSVC by including math.h in a .cpp file. floorl is a force inline function defined in a header thus not visible for the linker. * Fix caching of LLVM builtin fns. The cache entry must take into account the fact some functions operate on scalar types and some other on vectors of scalar types (#10147). * Improve packed struct array padding error message. * Fix exporting enums (#9498). * Make cmpxchg respect -fsingle-threaded. * Add support for the NO_COLOR environment variable. * Disable valgrind integration on macOS. Unfortunately, Valgrind for macOS has been broken for years, and the Homebrew formula is only for Linux (#9612). * Fix @divTrunc behavior dependent on the order of operands (#10001 ). * Make omiting frame pointer independent of build mode (#9874). Contributors: Andrew Kelley, LemonBoy, Martin Wickham, Robin Voetter, Daniele Cocca, Takeshi Yoneda, Auguste Rame, Daniele Cocca, Jacob G-W, Lee Cannon, LemonBoy, Matthew Borkowski, Travis Staloch, leesongun, travisstaloch, Belhorma Bendebiche, Evan Haas, Exonorid, Frank Denis, Jakub Konka, Jay Petacat, Josh Soref, Kirk Scheibelhut, Meghan Denny, Michael Dusan, Richard Eklycke, Stephen Gregoratto, Veikka Tuominen, mlarouche, vole-dev, Ziga Zeljko Better Awareness of Unwind Tables SS Main issue: #9046 * Zig now allows configuring the uwtables function attr via a flag rather than its own logic. * The Self-Hosted Compiler defaults to enabling uwtable attr when linking libunwind, or always on Windows. It also makes link_eh_frame_hdr true automatically if uwtable attr is set to be on for zig functions. * The CLI adds -funwind-tables and -fno-unwind-tables to allow the user to override the defaults. * It is now hooked up to zig cc. Moved Unreachable Code Errors to Self-Hosted SS The Self-Hosted Compiler is so fast that Zig 0.9.0 additionally runs the first three phases of the self-hosted pipeline (tokenizing, Parser, and AST lowering), before invoking the bootstrap compiler, to enable Compile Errors for Unused Locals among other kinds of compile errors. At first it seemed this would be a small perf hit to additionally run part of the self-hosted compiler in front of the bootstrap compiler, but it would be worth it to gain access to the compile errors that are only implemented in the self-hosted compiler. But something delightful happened. This change allowed us to move the "unreachable code" compile error from the bootstrap compiler to the self-hosted compiler. This made it possible to delete a couple of fields from some structs within the bootstrap compiler, resulting in a small performance improvement. But because the self-hosted compiler is so fast, the performance gain outweighed the performance cost! So we actually improved performance by additionally running the self-hosted compiler in front of the bootstrap compiler. Self-Hosted Compiler SS The main focus of this release cycle was the self-hosted compiler (also known as "stage2"). Here is an infographic to communicate a sense of progress: Progress Report Progress Report Currently we have 467 out of 1072 behavior tests passing with the LLVM Backend. Once this reaches 100% we can start shipping the self-hosted compiler instead of the Bootstrap Compiler. In this release cycle, we took a detour from making progress on passing more tests, to invest in applying Data-Oriented Design principles to the codebase. This resulted in significant performance improvements. Despite the fact that .zig source code by default is still compiled in this release using the Bootstrap Compiler, the main driver code is already self-hosted, as well as many features, such as zig cc, C Translation, CPU feature detection, and the Cache System. Improvements made to "stage2" in these areas do in fact affect the main Zig user experience. The bullet points listed here are part of the shared code between both compiler implementations. Miscellaneous improvements: * native libc detection: respect spaces in CC env var. Zig has detection for when it is accidentally being called recursively when trying to find the native libc installation. However it was not working, resulting in a cryptic failure, because zig tried to execute a command which had spaces in it rather than tokenizing it. This improves the user experience of zig cc for systems that Zig does not support cross-compiling for (#8960). * Print path on libc/libc-path fatal error. * CLI: rename --override-lib-dir to --zig-lib-dir. This breaking change disambiguates between overriding the lib dir when performing an installation with the Zig Build System, and overriding the lib dir that the Zig installation itself uses. * The equivalent of zig ast-check is now run unconditionally for all files, even when using the Bootstrap Compiler. This means instant feedback for many compile errors such as Compile Errors for Unused Locals (#9191). * Added --sysroot link option (#9202). * AstGen: fixed O(N^2) perf for many decls with same parent (#9234 ). * AstGen: error for return outside of function scope (#9346). * Improved error messages that tell the paths of files when errors occur. * Added support for the NO_COLOR environment variable. * More compile errors for invalid inline assembly. * Fixed libc include directories for the MSVC target. * -rdynamic now implies -fdll-export-fns unless the latter is explicitly set (#9340). * Added -femit-llvm-bc CLI option, and improved -fcompiler-rt support (#9440). * The CLI now recognizes -z origin, -z noexecstack, -z now, -z relro, -z notext, and -z nodelete. These are additionally available in the Zig Build System. * Fixed libc file to check against compilation target instead of native (#9670). * zig init-lib and zig init-exe will no longer overwrite src/ main.zig if it already exists. * The example generated by zig init-exe now demonstrates simple testing (#9919). * Made pointer variables in zig init-lib and zig init-exe build.zig const (#10057). * zig test gains a --test-no-exec flag. * Fixed zig test --test-evented-io (#9779). * New CLI parameter: -femit-implib. * Fixed incorrectly invoking LLD when building an object file. * CLI: introduce -fsingle-threaded/-fno-single-threaded (#10143). Previously there was only --single-threaded. This flag now matches other boolean flags: instead of only being able to opt in to single-threaded builds, you can now force multi-threaded builds. Currently this only has the possibility to emit an error message, but it is a better user experience to understand why one cannot choose to enable threads in some cases. This is breaking change to the CLI. * Fix lakemont CpuModel (#9099). Contributors: Andrew Kelley, Jakub Konka, Jacob G-W, Robin Voetter, Joachim Schmidt, Luuk de Gram, Evan Haas, Martin Wickham, Matthew Borkowski, Lee Cannon, Veikka Tuominen, Takeshi Yoneda, Travis Staloch, drew, Ryan Liptak, xackus, Emily Bellows, Jonathan Marler, g-w1, Alex Ronne Petersen, Dmitry Matveyev, J.C. Moyer, Meghan Denny, Michael Dusan, kprotty, Andrew Gutekanst, Daniele Cocca, FnControlOption, Isaac Freund, Kurt Kartaltepe, LemonBoy, Lewis Gaul, Matt Knight, Tom Maenan Read Cutting, Zen1th, jacob gw, vole-dev, Ziga Zeljko, AODQ, Al Hoang, Christopher Smyth, Dimenus, Exonorid, Frank Denis, Hadrien Dorio, Isaac Freund, Josh Soref, Kenta Iwasaki, Loris Cro, Michal Ziulek, Scibuild, Sebastian Ullrich, Sizhe Zhao, Stephen Gregoratto, Stephen Gutekanst, Stephan Kochen, Tamas Kenez, Thomas Ives, Vincent Rischmann, daurnimator, pithlessly, travisstaloch, xavier Parser SS * It now uses a scratch buffer to avoid heap allocations in many cases. * suspend expressions now require blocks. * tokenizer: fixed index-out-of-bounds on string_literal_backslash right before EOF. * tokenizer: fixed index-out-of-bounds on unfinished unicode escapes before EOF. * Improved C pointer prefix parsing; no longer indexes out of bounds on EOF. * Fixed parsing of extern function declarations (#10040). * Made chained comparison operators a parse error. LLVM Backend SS The LLVM backend is now passing 44% of the behavior tests. This is currently the main focus of the self-hosted compiler effort, because when it gets to 100%, we can start shipping the self-hosted compiler instead of the Bootstrap Compiler. The new LLVM backend has reached a milestone: it can now produce a viable binary for this Tetris clone. This gives us some early performance measurements. On Andrew's laptop: zig build-exe src/main.zig -fLLVM -lc -Istb_image-2.22 -lglfw -lepoxy --main-pkg-path . stb_image-2.22/stb_image_impl.c -fno-stage1 * cold zig-cache * 28,429 lines of Zig (26,324 of that is translated C .h files) * 7,551 lines of C Using the Bootstrap Compiler: * wall clock: 4.17 seconds * peak RSS: 439 MiB Using the Self-Hosted Compiler: * wall clock: 2.76 seconds * peak RSS: 236 MiB This time includes: * the llvm backend which remember is the slow one compared to the x86 Backend. * LLD instead of our Self-Hosted Linker. * building compiler-rt with LLVM optimizations on. * waiting for C Translation. * waiting for clang to build the .c files. So this is not a fair benchmark to measure how many lines/second Zig can compile. Even so, it's 1.5x faster and 0.53x as much memory as the Bootstrap Compiler. C Backend SS The C backend is now passing 22% of the behavior tests. When it gets to 100%, we can delete the Bootstrap Compiler and replace it with the self-hosted compiler converted into C code. x86 Backend SS The x86 backend is not yet capable of executing the zig test runner, so technically it is passing 0% of the behavior tests. However basic codegen is already in place, we have an MIR representation, and both rendering to machine code and assembly code is implemented. We are just a few bug fixes and enhancements away from x86 joining the "behavior tests passing" progress bar. Jakub Konka has started working on this in earnest. aarch64 Backend SS The aarch64 backend is in a very similar state as the x86 Backend. Joachim Schmidt has been making steady progress. Self-Hosted Linker SS The main improvements to the self-hosted linker have been to the MachO linker backend by Jakub Konka and to the WebAssembly linker backend by Luuk de Gram. The most significant milestone for the self-hosted MachO linker is that it is getting battle tested by the community every day, and it can now successfully be used as a drop-in linker for other languages and environments such as C, C++, Objective-C, Objective-C++, Go and Rust. It can also be used to cross-compile code dependent on frameworks from a non-Apple host such as Linux to Apple platforms such as macOS, iOS, etc., with the sysroot provided by the user. Additionally, the linker was featured at the 2021 Handmade Seattle Conference where Jakub in a short 5 minute video demonstrated the linker's current capabilities when used with the bootstrap compiler (stage1), and showcased a prototype for incremental linking and what developer experience it will unlock when used with the self-hosted compiler (stage2). The demo is available at the Handmade Seattle Conference media website here: The ZLD Linker demo. Major improvements to the MachO linker backend: * Ability to correctly link common symbols (aka tentative definitions). * Ability to generate basic __eh_frame debug section. * Ability to link system libraries and frameworks including in cross-compilation contexts. Achieving this required creating a TAPI (yaml) parser for parsing Apple's text-based definition stub files such as libSystem.B.tbd. * Ability to defer imports (undefined symbols) resolution in dynamic libraries until load time. This effectively implies Zig's MachO linker respects -fallow-shlib-undefined or equivalently in macOS parlance -Wl, "-undefined dynamic_lookup" flags. This in turn implies that Zig can be used to successfully build NodeJS or Python native addons/modules which require deferred until load-time undefined symbol resolution. See for instance issue # 3000. * Ability to target iOS and iOS simulator targets. How to do that is documented in Jakub's standalone repo zig-ios-example on GitHub. * The linker can successfully be used as a drop-in linker for C, C++, Objective-C, Objective-C++, Go and Rust * Ability to perform incremental linking updates to Zig mixed with C objects. Current linker implementation allows the user to use the self-hosted Zig compiler's watch mode to perform incremental updates to both Zig and C sources at the same time. While Zig will perform the updates at the finest granularity, i.e., on a per decl/symbol basis, the linker can also relink the C object files if they are changed without affecting the Zig generated decls. This is a prototype of the desired developer experience we are aiming for, and it was demonstrated as part of the linker's demo at the 2021 Handmade Seattle Conference (link above). * Creation of a standalone visualisation tool for exploring differences between subsequent incremental linker updates when the self-hosted compiler is run in the watch mode. The tool is called zig-snapshots and aims to become the debugging tool for Zig linker developers and contributors. In order to use the tool, the self-hosted Zig compiler needs to be built with -Dlink-snapshot, and then the compiler needs to be passed --debug-link-snapshot. Miscellaneous linker improvements: * Correctly delimit rpath in LC_RPATH load command payload. * Handle Windows paths when cross-compiling from Windows to macOS. * Skip temporary and unnamed symbols from inclusion in the MachO's symbol table. * Ignore undefined symbols marked from discarding - if a symbol is undefined after we tried resolving it and it is annotated with N_DESC_DISCARDED description flag, simply ignore it rather than throw an error.UndefinedSymbolReference. * Add missing TbdV3 fields, allow for []TbdV3, and synthesise Objective-C ivars and eh_types symbol names. * Resolve frameworks in BFS order. * Add a GOT entry for ARM64_RELOC_POINTER_TO_GOT target. * COFF: honor the link_libunwind flag. * wasm: respect stack_size_override for build-obj and build-lib (# 8633). * MachO: Ability to create dylibs (#9266) * Add fat/universal dylib support. With this change, zig can link with dynamic libraries contained within a fat/universal file that had multiple separate binaries embedded within it for multi-arch support (in macOS). * MachO: Fix section mapping for Go specific sections. * MachO: Link against system libSystem when building natively (# 9242). * COFF: Add IMPLIB support (#9347). * macho: fixed writing null symbols into undef symbols section. * macho: handle non-extern UNSIGNED relocs on arm64. * macho: write out LC_FUNCTION_START data. * macho: moved load command wrappers and parsing utils to the Standard Library (#10310). * macho: allow undefined symbols in dylibs. We now respect both -fallow-shlib-undefined and -Wl,"-undefined=dynamic_lookup" flags. As a result of this change, it is now possible to generate a valid native Node.js addon with Zig for macOS (#8180) (#3000). * macho: refactor consts in std.macho, and fix two bugs (#10338). * macho: error instead of warning when a requested -framework is not found. C Translation SS * Properly handle enums used as boolean expressions. * Implement flexible arrays (#8759). * Fix enums that require c_uint type. * Better support for static local variables. * Don't bother with unwrapping pointers. Dereferencing a c pointer implicitly includes an unwrap, manually adding it just causes bugs. * Improve type parsing (#9092). * Remove usage of extern enum. Instead, translate enum types as the underlying integer type. Translate enum constants as top-level integer constants of the correct type (which does not necessarily match the enum integer type). If an enum constant's type cannot be translated for some reason, omit it. discussion (#9153). * Avoid discarding variables unless necessary (#9205). * Handle underscore when used as an identifier by using @ syntax to escape _ when used as an identifier. * Handle NAN and INFINITY macros (#9468). * Handle signed array subscripts. This is a rather complicated workaround for handling signed array subscripts. Once [*]T + isize is allowed, this can be removed (#8556). * Handle macros that cast to cv void (#9507). * Allow string literals to be used as char *. In C the type of string literals is char *, so when using them in a non-const context we have to cast the const away (#9126). * Avoid repeating string in type when making it mutable. * Remove now unnecessary mangling of primitive type shadowing (# 6382). * Fix logic for checking primitive names (#9928). * Create inline fn for always_inline. * Allow negative denominator in remainder (%) operator (#10176). * Coerce boolean results to c_int when negated (#10175). * Prevent a while under an if from stealing the else. * Fix args when calling clang::ASTUnit::LoadFromCommandLine. In addition to these improvements to zig translate-c, Veikka Tuominen, Evan Haas, and iddev5 have been working on arocc, a C compiler written in Zig. One of the goals of the project is to replace Clang as Zig's C frontend for C translation. Contributors: Evan Haas, Veikka Tuominen, xackus, Matthew Borkowski, Stephan Kochen, Andrew Kelley, Tamas Kenez Cache System SS Zig's cache system is central to its strategy to support many targets, by shipping with only source files and lazily building artifacts as needed. Shared Cache Locking SS The cache system now drops from exclusive locks to shared locks after an artifact is built. Additionally, when checking the cache, if an exclusive lock cannot be obtained, a shared lock will be obtained instead. Together, this solves a design flaw in the caching system that was causing deadlocks, and allows multiple processes to share the same read-only build artifacts, while still allowing a cache garbage collection utility to operate concurrently with the Zig compiler even as build artifacts are being actively used. This required new Standard Library functionality: std.fs.File.setLock. The Windows implementation based on using NtLockFile and NtUnlockFile rather than relying on ShareAccess flags and manual polling. This resolved the deadlock problems reported in #9139 and #9187. It also allowed us to remove another workaround to a deadlock when supplying the same source file multiple times. Main issue: #7596 Improved Handling of Generated File builtin.zig SS All Zig code is eligible to @import("builtin") which is mapped to a generated file, builtin.zig, based on the target and other settings. Zig invocations which share the same target settings will generate the same builtin.zig file and thus the path to builtin.zig is in a shared cache folder, and different projects can sometimes use the same file. In previous versions of Zig, this led to conditions where multiple invocations of zig would race to write this file. If one process wanted to read the file while another process wrote the file, the reading process could observe a truncated or partially written builtin.zig file. Zig 0.9.0 has the following improvements: * In the cold path, atomically renames the builtin.zig file into place, preventing any race conditions from occurring. * Avoids clobbering the inode and mtime in the hot path. * Avoids creating a partially written file. * Keeps builtin.zig on disk for debug info and stack trace purposes. * Does not mark the task as complete until the file is finished being populated (possibly by an external process). * The hot path does one stat() syscall that happens in a worker thread. In summary, performance is improved and a race condition crash was fixed (#9439). Detection of Problematic Timestamps SS One problem with caching systems is that if a file is written, read, and then written again all within a very short period of time, the file system mtime granularity may not tell a difference between those two writes, and so a subsequent read might register an unchanged file, when in fact the file was changed. To avoid this problem, Zig recognizes the concept of problematic timestamps, which notices at read() time that the current time is so recent that the file system's mtime granularity would not actually tell the difference from the previous write. In such case it marks the mtime as untrustworthy, so that next time the cache system does not rely on the mtime, and is forced to fall back to a file contents hash. In previous releases of Zig, this problematic timestamp was calculated based on a syscall to get the current time. This was not an accurate measurement of problematic timestamps, because asking the system for the current time did not necessarily correspond to the time that the file system would return, and it had no way of conveying the mtime granularity of the filesystem. In Zig 0.9.0, the problematic timestamp is learned by writing a temporary file to the cache directory, and reading the mtime from that temporary file. This mtime will have the appropriate granularity to use to check if a timestamp is problematic (i.e. too recent) and should not be trusted. Thank you to Travis Martin for submitting this improvement (#9930). Improved Hashing Logic SS Stephen Gutekanst writes: While investigating slow build times with a large project, I found that the compiler was reading from disk nearly every C source file in my project when rebuilding despite no changes having been made. This accounted for several seconds of time (approx. 20-30% of running zig build without any changes to the sources.) The cause of this was that comparisons of file mtimes would always fail (the mtime of the file on disk was always newer than that stored in the cache manifest), and so the cache logic would always fall back to byte-for-byte file content comparisons with what is on disk versus in the cache - reading every C source file in my project from disk during each rebuild. Because file contents were the same, a cache hit occurred, and despite the mtime being different the cache manifest would not be updated. One could reproduce this by building a Zig project so the cache is populated, and then changing mtimes of their C source files to be newer than what is in the cache (without altering file contents.) The fix was rather simple: always write the updated cache manifest regardless of whether or not a cache hit occurred, because a cache hit doesn't indicate if a manifest is dirty. Luckily, writeManifest already contained logic to determine if a manifest is dirty and becomes no-op if no change to the manifest file is necessary, so the fix was to call writeManifest in the Self-Hosted Compiler even in the case of a cache hit. Debug Crash Handler SS Martin Wickham added this crash report to the panic function, which has been really nice for internal compiler development. Crashes now look something like this: $ ./zig-out/bin/zig test -fLLVM ../test/behavior/eval_stage1.zig thread 831982 panic: access of inactive union field Analyzing ../test/behavior/eval_stage1.zig: eval_stage1.zig:test.inlined loop has array literal with elided runtime scope on first iteration but not second iteration %115 = load(%111) node_offset:22:19 %116 = int(2) %117 = cmp_lt(%115, %116) node_offset:22:21 %118 = as_node(@Ref.bool_type, %117) node_offset:22:21 > %119 = condbr_inline(%118, { %127 = dbg_stmt(23, 9) %128 = alloc_inferred() node_offset:23:9 %133 = block({ %129 = load(%111) node_offset:23:28 %130 = cmp_eq(%129, @Ref.zero) node_offset:23:30 %131 = as_node(@Ref.bool_type, %130) node_offset:23:30 %132 = condbr(%131, { %134 = array_type(@Ref.one, @Ref.i32_type) %135 = elem_type(%134) node_offset:23:36 %136 = coerce_result_ptr(%134, %128) %137 = elem_ptr_imm(%136, 0) node_offset:23:43 %138 = int(2) %139 = store_node(%137, %138) node_offset:23:43 %140 = validate_array_init({ %137 = elem_ptr_imm(%136, 0) node_offset:23:43 }) node_offset:23:42 %143 = break(%133, @Ref.void_value) }, { %141 = load(%101) node_offset:23:51 %142 = store_to_block_ptr(%128, %141) %144 = break(%133, @Ref.void_value) }) node_offset:23:24 }) node_offset:23:24 %145 = resolve_inferred_alloc(%128) node_offset:23:9 %146 = dbg_stmt(24, 9) %147 = load(%128) node_offset:24:13 %148 = ensure_result_non_error(%147) node_offset:24:13 %149 = break_inline(%120, @Ref.void_value) }, { %150 = break_inline(%114, @Ref.void_value) }) node_offset:22:12 For full context, use the command zig ast-check -t ../test/behavior/eval_stage1.zig in ../test/behavior/eval_stage1.zig: eval_stage1.zig:test.inlined loop has array literal with elided runtime scope on first iteration but not second iteration > %120 = block_inline({%115..%119}) node_offset:22:12 in ../test/behavior/eval_stage1.zig: eval_stage1.zig:test.inlined loop has array literal with elided runtime scope on first iteration but not second iteration > %114 = block_inline({%120..%126}) node_offset:22:12 /home/andy/Downloads/zig/src/Sema.zig:991:53: 0x3049c86 in Sema.analyzeBody (zig) const break_data = datas[break_inst].@"break"; ^ /home/andy/Downloads/zig/src/Sema.zig:956:56: 0x3049525 in Sema.analyzeBody (zig) const break_inst = try sema.analyzeBody(block, inline_body); ^ /home/andy/Downloads/zig/src/Sema.zig:956:56: 0x3049525 in Sema.analyzeBody (zig) const break_inst = try sema.analyzeBody(block, inline_body); ^ /home/andy/Downloads/zig/src/Module.zig:4306:25: 0x301b2c5 in Module.analyzeFnBody (zig) _ = sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) { ^ /home/andy/Downloads/zig/src/Compilation.zig:2343:47: 0x2dff765 in Compilation.processOneJob (zig) var air = module.analyzeFnBody(decl, func, sema_arena) catch |err| switch (err) { ^ /home/andy/Downloads/zig/src/Compilation.zig:2261:30: 0x2df229d in Compilation.performAllTheWork (zig) try processOneJob(self, work_item, main_progress_node); ^ /home/andy/Downloads/zig/src/Compilation.zig:1872:31: 0x2deddd7 in Compilation.update (zig) try self.performAllTheWork(); ^ /home/andy/Downloads/zig/src/main.zig:2875:20: 0x2d5812f in updateModule (zig) try comp.update(); ^ /home/andy/Downloads/zig/src/main.zig:2558:17: 0x2ce4d2e in buildOutputType (zig) updateModule(gpa, comp, hook) catch |err| switch (err) { ^ /home/andy/Downloads/zig/src/main.zig:216:31: 0x2cca5f6 in mainArgs (zig) return buildOutputType(gpa, arena, args, .zig_test); ^ /home/andy/Downloads/zig/src/main.zig:165:20: 0x2cc9350 in main (zig) return mainArgs(gpa, arena, args); ^ /home/andy/Downloads/zig/lib/std/start.zig:553:37: 0x3179297 in std.start.callMain (zig) const result = root.main() catch |err| { ^ /home/andy/Downloads/zig/lib/std/start.zig:495:12: 0x2ccc037 in std.start.callMainWithArgs (zig) return @call(.{ .modifier = .always_inline }, callMain, .{}); ^ /home/andy/Downloads/zig/lib/std/start.zig:460:12: 0x2ccbde2 in std.start.main (zig) return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp }); ^ Aborted (core dumped) Here we can see that there is a bug in the compiler where it tried to access the wrong union field. Not only do we get a stack trace pointing at the union field access, but it tells us the source file, line number, and function that the compiler was analyzing when it crashed, it dumps out the ZIR in text form, pointing to the exact instruction that was being analyzed, and dumps out the analysis stack including the ZIR instructions. In many cases, seeing this information is enough to completely diagnose the problem, without having to resort to a debugger. It additionally makes it easier for contributors to help out, and it increases the chances of error reports to include enough information to reproduce or diagnose the issue. Stop Guessing Whether the System Can Execute Binaries SS Previously when using zig run or zig test, Zig would try to guess whether the host system was capable of running the target binaries. Now, it will always try. If it fails, then Zig emits a helpful warning to explain the probable cause: $ uname -a Linux ark 5.10.81 #1-NixOS SMP Sun Nov 21 12:46:37 UTC 2021 x86_64 GNU/Linux $ zig run hello.zig -target aarch64-linux warning: the host system (x86_64-linux.5.10.81...5.10.81-gnu.2.33) does not appear to be capable of executing binaries from the target (aarch64-linux.3.16...5.5.5-musl) error: the following command failed to execve with 'InvalidExe': /home/andy/.cache/zig/o/b61b3c9b78433477f6b5c343ce95631f/hello $ zig run hello.zig -target x86_64-linux-gnu -lc warning: the host system does not appear to be capable of executing binaries from the target because the host dynamic linker is located at '/nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/ld-linux-x86-64.so.2', while the target dynamic linker path is '/lib64/ld-linux-x86-64.so.2'. Consider using --dynamic-linker error: the following command failed to execve with 'FileNotFound': /home/andy/.cache/zig/o/f0f8bdc473cbcf7f00bd72f0450102ad/hello $ zig test behavior.zig -target aarch64-linux warning: the host system (x86_64-linux.5.10.81...5.10.81-gnu.2.33) does not appear to be capable of executing binaries from the target (aarch64-linux.3.16...5.5.5-musl). Consider using --test-no-exec or --test-cmd error: the following command failed with 'InvalidExe': ../test/zig-cache/o/b70989a95e10772fc12652c7f94a5cf5/test zig $ zig test behavior.zig -target x86_64-linux-gnu -lc warning: the host system does not appear to be capable of executing binaries from the target because the host dynamic linker is located at '/nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/ld-linux-x86-64.so.2', while the target dynamic linker path is '/lib64/ld-linux-x86-64.so.2'. Consider using --dynamic-linker, --test-no-exec, or --test-cmd error: the following command failed with 'FileNotFound': ../test/zig-cache/o/795162652b84a90baa06fbb62db5eb68/test zig This integrates better when something such as binfmt_misc is installed. See also the new Executors feature of the Zig Build System. Link Dynamic Libraries As-Needed by Default SS Now, the default for dynamic libraries (-l or --library) is to only link them if they end up being actually used. With the Zig CLI, the new options -needed-l or --needed-library can be used to force link against a dynamic library. With zig cc, this behavior can be overridden with -Wl,--no-as-needed (and restored with -Wl,--as-needed). We might need to revert this change in order to satisfy the design requirement of having the default be the same on all platforms due to some macOS considerations. Related issue: #10164 Standard Library SS The Zig standard library is still unstable and mainly serves as a testbed for the language. After the Self-Hosted Compiler is completed, the language stabilized, and Package Manager completed, then it will be time to start working on stabilizing the standard library. Until then, experimentation and breakage without warning is allowed. Miscellaneous improvements: * Fix path resolution on Windows (#10093). * Fix stack traces for Zig on macOS when linked with any linker including Apple's ld64. * Better handing of POLLHUP in ChildProcess (#8988). * Changed return values of SectionHeaderIterator().next() to bswapAllFields() (#9014). * Fix bug in io.FixedBufferStream seekTo (#9023). * ascii: add allocation free versions of lower/upper string. * GeneralPurposeAllocator: add retain_metadata option to report more double frees. * c: add sigfillset, alarm, sigwait. * c: fix waitpid() definition. * Made ChildProcess exit code u8 to match process.exit. * Added os.dup(). * Made copy_file_range checks run at compile-time (#9146). * Fixed PIE startup sequence (#9168). * Added xoshiro256++ (#9298). * Added missing error codes to os functions. * fs.path.join: skip empty strings. * ArrayList(u0) works now. This type still tracks length, but does not allocate additional memory. * DynamicBitSet.iterator takes self as const. * mem.split and mem.tokenize generic instead of assuming u8 (#9531 ). * Ip4Address parser: reject 0-prefixed components (#9538). * rand.Random: add enumValue() (#9583). * debug.LineInfo.deinit and debug.SymbolInfo.deinit are now public. * (p)writev now performs partial writes if iov.len > IOV_MAX. * Fixed bad integer cast in WIFSTOPPED for Linux, FreeBSD, and DragonFlyBSD. The intermediate value can be larger than an u16, so @truncate is needed to match the behavior of musl. * ArrayListUnmanaged: implement writer(). * Publicized ArrayListUnmanaged.allocatedSlice to match ArrayList. * Added functions to decode an epoch timestamp (#9040). * net.Address: Fix writing 0-bytes when formatting Unix addresses. * unicode: cleanup allocations on error in allocating functions. Fixes leaks when utf16leToUtf8Alloc/utf16leToUtf8AllocZ/ utf8ToUtf16LeWithNull return an error and adds relevant test cases. * Set the Storage socket sizes to be system defined (#9759). * elf: added a couple missing special section indexes. * elf: add amd64 relocation types. * Fixed mem.Allocator.resize() for non u8 element types (#9806). * Change to resolving scope IDs using IPv6 sockets. * os.flock: FreeBSD can return EOPNOTSUPP. * Improved @panic hierarchy by always using builtin.panic. * deflate: fixed bits_left overflow at EndOfStream and @intCast truncation with empty Huffman table. * deflate: check for distances past beginning of output stream. * deflate: better Huffman.construct errors and error handling (# 9880). * os: handle ETXTBSY from open(). * PriorityQueue: moved compareFn from init to type constructor in PriorityQueue and PriorityDequeue. This change significantly improves performance for simple compare functions and modifies the API to be more consistent with e.g. HashMap. * Distinguish between unexpected child process exit code and unclean exit. * MultiArrayList: get function take self by value. * Made meta.trait.isContainer true for opaques. * GeneralPurposeAllocator: fixed memory limit accounting for large allocations. * ArrayList: add ensureTotalCapacityPrecise (#10077). * ppoll: cast number of fds to nfds_t. * Publicize Allocator.reallocBytes. This is useful when dealing with runtime-known alignments, eg. interfacing with C code that accepts custom allocation callbacks (#9394). * Added chmod and chown. * builtin.StackTraceformat: fix compile error when building for a target that does not have stderr or detectTTYConfig (such as freestanding). * Added NotLink error (#9877) (#9872). * Fixed type error for u8 in writeIntSlice. * mem.indexOfPos now returns start_index when needle length is zero (#10220) (#10216). * Fixed slice bounds in system.preadMin. * Handle rmdirZ EINVAL error (#10145). * Fixed test label off-by-one error (#10277). * PriorityQueue: comparator now takes a context parameter (#10342). Contributors: Andrew Kelley, Robin Voetter, Jakub Konka, kprotty, Ryan Liptak, Lee Cannon, Vincent Rischmann, LemonBoy, Veikka Tuominen, Jacob G-W, Jonathan Marler, Matthew Borkowski, Evan Haas, Felix (xq) Queissner, Takeshi Yoneda, Koakuma, Luuk de Gram, Martin Wickham, Aaron Sikes, Al Hoang, Frank Denis, Isaac Freund, Marc Tiehuis, lucky, Kenta Iwasaki, Matt Chudleigh, Stephen Gregoratto, Travis Staloch, Ali Chraghi, Asherah Connor, Hiroaki Nakamura, Jens Goldberg, Lewis Gaul, Meghan, Michael Dusan, N00byEdge, Ominitay, Tom Maenan Read Cutting, jacob gw, viri, Dmitry Matveyev, Gregory Anders, InKryption, Isaac Freund, Jarred Sumner, Jeremy Fillingim, Malcolm Still, Samadi van Koten, Silver, Sizhe Zhao, Sreehari Sreedev, Stephen von Takach, Sebastien Marie, Travis Martin, codic12, daurnimator, rgreenblatt, xackus, Adam C, Andrew Gutekanst, Arnav Singh, ArtixFox, Asa Zeren, Austin Clements, Aydin Mercan, Ayende Rahien, Biolunar, Bjorn Linse, Boo, Carlos Zuniga, Chris Gregory, Chris Heyes, Coleman Broaddus, Daniele Cocca, Dante Catalfamo, Dante Catalfamo, Dustin Taylor, Edward Dean, Ellis Trisk-Grove, Emil Lerch, Exonorid, Fabio Arnold, Felix "xq" Queissner, Filippo Casarin, FnControlOption, Frank Denis, Garrett Squire, Hiroaki Nakamura, HugoFlorentino, Isaac Freund, Isaac Yonemoto, Jakub Dupak, Jan200101, Justin Whear, Kirjastonhoitaja, Klecko, LemonBoy, Luna, Mahdi Khanalizadeh, Matt Knight, Max Hollmann, Michal Ziulek, Miles Alan, Nameless, Nathan Michaels, Nguyen Gia Phong, Philip Akesson, Philipp Luhmann, Rohlem, Sebastien Marie, Tau, Thom Chiovoloni, Tizoner, Trioct, William Stein, Zach Banks, Zapolsky Anton, alichraghi, charlieman, chwayne, d18g, fn ^ [?], g-w1, hadroncfy, jdmichaud, joachimschmidt557, leesongun, mason1920, pfg, protty, purringChaos, tgschultz, tjohnes, viri Deprecations SS * ensureCapacity is removed in favor of ensureTotalCapacity and ensureUnusedCapacity. * fs.Walker is moved to fs.Dir.Walker. Paths of entries are relative to the Dir. * std.Target.current is moved to @import("builtin").target (#9388) (#9321). * DynamicBitSet functions have allocator parameters moved to be the first one (after self) to match common convention (#9944). * debug.warn is removed in favor of debug.print. * mem.dupe is removed in favor of mem.Allocator.dupe. * mem.spanZ is removed in favor of mem.sliceTo. * ensureCapacity is removed in favor of ensureUnusedCapacity or ensureTotalCapacity. * ArrayList.toUnmanaged is removed in favor of ArrayList.moveToUnmanaged which has different semantics. * base64.standard_pad_char is removed in favor of base64.standard.pad_char. * base64.standard_encoder is removed in favor of base64.standard.Encoder. * base64.standard_decoder is removed in favor of base64.standard.Decoder. * build.Version is removed; use std.builtin.Version instead. * build.Target is removed; use std.zig.CrossTarget instead. * hash_map.DefaultMaxLoadPercentage is removed in favor of hash_map.default_max_load_percentage. * io.FindByteOutStream is removed in favor of io.FindByteWriter. * io.findByteOutStream is removed in favor of io.findByteWriter. Additional API SS * mem.alignPointerOffset * mem.alignPointer * Thread.Futex (#9070). * unicode.fmtUtf16le * io.Reader.readUntilDelimiter * BoundedArray: a simple way to represent small data whose max size is known (#9134). * meta.Float Crypto SS * timing-safe functions to add and subtract serialized integers (# 8977). * aes 128-bit key expansion test - properly test the inverse round keys (#9065). * Switched rand.DefaultPrng to Xoshiro256++ (#9301). * Handle the top bit in 25519.field.fromBytes64() (#9435). * added scrypt kdf (#9577). * reexport crypto/phc_encoding (#9712). * added writer methods on all crypto.hash types (#10168). * updated docs (#10150). * add argon2 kdf (#9756). * edwards25519: correctly flip the Y sign in the H2C operation. Math SS * sqrt_int: fixed odd size integers types. * Fixed tanh for negative inputs (#9047). * Fixed bigint add failures with aliasing (#8330). * Fixed complex ldexp implementation (#9047). * big ints: 2s complement signed xor/and/or (#9825). * Big int wrapping/saturating (#9885). * Big int saturating left shift (#9954). * Fixed a case where big int truncate would assume that the input fits in the output limbs buffer. * Big ints: division fixes (#10017). * Implemented bigint popcount. * Added f128 implementations of fma, frexp, and ilogb. * Fixed bug where asinh64 doesn't respect signedness for negative values (#9940). * Fixed bug in exp2 (#9999). * Fixed copy-paste error that results in incorrect results from exp64. * Added ldexp and make scalbn an alias. We assume we are compiled on a base-2 radix floating point system. This is a reasonable assumption. musl libc as an example also assumes this. We implement scalbn as an alias for ldexp, since ldexp is defined as 2 regardless of the float radix. This is opposite to musl which defines scalbn in terms of ldexp (#9799). * Reimplement sin/cos/tan based on musl (#10276). * Added phi constant. JSON SS * Now allows scientific notation to coerce to integers as long as they actually resolve to int type. * Now catches and handles overflow when parsing floating-point values with no fractional parts. * parse: added support for recursive objects (#9307). * stringify: added an option to not write out null optional fields (#8979). * Now uses a bit-stack for nesting instead of a large integer type (#5959). Formatted Printing SS * std.fmt: Better formatting of tuple types by skipping the useless type name and the numeric field names. * Added name of type in unsupport format string compile error. * Added support for printing slices strings (#9562). * Fixed float formatting for 0.0 when precision is 0 (#9642). * Format functions take case as an enum. * Improved error message when there are missing arguments. * Added fmt.fmtDurationSigned. * Fixed endless loop, working around a Bootstrap Compiler bug that may sometimes lead to an endless loop being generated when unrolling the fmt impl (#9961). Please note that the formatted printing API is unstable and will very likely break everyone's formatting code before we reach 1.0. Threading SS * Thread spawning API is now similar to the @call(.{}, function, args_tuple) builtin. * Spawn options (first arg) with customizable thread stack size. * Renamed wait() to join(). * Renamed handle() to getHandle() for consistency. * Added ability to detach() thread, allowing it to clean up resources when it exits instead of calling join(). * Moved getCurrentThreadId() into getCurrentId(). * Added Thread.setName and Thread.getName (#8570) including for DragonFlyBSD (#9910). Mutex Lock/Unlock SS Thread.Mutex: change API to lock() and unlock(). This is a breaking change. Before, usage looked like this: const held = mutex.acquire(); defer held.release(); Now it looks like this: mutex.lock(); defer mutex.unlock(); The Held type was an idea to make mutexes slightly safer by making it more difficult to forget to release an aquired lock. However, this ultimately caused more problems than it solved, when any data structures needed to store a held mutex. Simplify everything by reducing the API down to the primitives: lock() and unlock(). Related issues: #8051 #8246 #10105 Allocgate SS The mem.Allocator interface has changed in a breaking way. In short summary, here is how to change your code: * Change *Allocator to Allocator in function parameter types and struct field types. * Instead of taking the pointer to an allocator field, such as & gpa.allocator, use a function call like this: gpa.allocator(). The motivation for this change was performance. This blog post is an excellent piece of technical writing; I couldn't have done a better job myself in these release notes: Allocgate is coming in Zig 0.9, and you will have to change your code Random Interface SS The rand.Random interface was changed in an equivalent manner to the Allocator interface changes, for the same reason (perf). Hash Maps SS * Fixed auto hash of tagged union with void field. * HashMap.getOrPutAssumeCapacityAdapted now sets key to undefined ( #9138). * Fixed ensureUnusedCapacity() over-allocating (#9365). * Corrected hasUniqueRepresentation for vectors (#9333). * Added ArrayHashMap.popOrNull, corresponding to ArrayList.popOrNull. * Added getKey methods (#9607). * Interleaving calls to HashMap.removeAssertDiscard() / HashMap.putAssumeCapacity() no longer cause hash maps to run out of memory (#7468). Logging SS * Introduced arbitrary code execution via ${jndi:ldap://... inside any logged string. + just kidding * Provide method to set logging level per scope (#8584). * Added a logging allocator that uses log (#8511). * Introduced compile error when root.log is not a function. * Default log logic is extracted into public function std.log.defaultLog (#9224). * Added std.log.Level.asText for getting a printable string from the log level. Only 4 Log Levels SS Over the last year of using std.log in practice, it has become clear that having the previous 8 distinct log levels (to match syslog) does more harm than good. It is too subjective which level a given message should have which makes filtering based on log level weaker as not all messages will have been assigned the log level one might expect. Instead, more granular filtering should be achieved by leveraging the logging scope feature. Filtering based on a combination of scope and log level should be sufficiently powerful for all use-cases. Note that the Self-Hosted Compiler has already limited itself to 4 distinct log levels for many months and implemented granular filtering based on both log scope and level. This has worked very well in practice. The four log levels are: * err - Error: something has gone wrong. This might be recoverable or might be followed by the program exiting. * warn - Warning: it is uncertain if something has gone wrong or not, but the circumstances would be worth investigating. * info - Info: general messages about the state of the program. * debug - Debug: messages only useful for debugging. Namespacing of OS Bits SS Since usingnamespace No Longer Affects Identifier Lookup, it helped to introduce proper namespacing to the many OS-specific constants that were essentially ported over from C headers (#9618). * errno is now a nonexhaustive enum, with the 'E' prefix chopped off. * Other stuff also is renamed so that the common prefix extracted out into a struct. Bug Fixes SS Full list of the 147 bug reports closed during this release cycle. Note: many bugs were both introduced and resolved within this release cycle. This Release Contains Bugs SS Zero the Ziguana Zig has known bugs and even some miscompilations. Zig is immature. Even with Zig 0.9.0, working on a non-trivial project using Zig will likely require participating in the development process. When Zig reaches 1.0.0, a new requirement for Tier 1 Support will be 0 known bugs for that target. A 0.9.1 release is planned. Zig Build System SS The Zig Build System is invoked via the zig build command, which executes a declarative build.zig script to collect options and describe the graph of steps, and then provides options to execute those steps. Although it is already essential to nearly every Zig project, the Zig Build System is still experimental and unstable. As a build system, stability is especially important, but cannot occur until the language stabilizes. Language stability is the next area of focus on the Roadmap. Miscellaneous improvements: * There is a new zig build flag, --prominent-compile-errors, which, in the case when there are compile errors, hides all the other standard error output besides the compile errors (#8513). * Improved API to use optionals instead of setting things to undefined, preventing some common bugs (#9013) (#8928) (#7991). * Added linkLibCpp helper to std.build.LibExeObjStep. * Changeed defineCMacro to take separate name and value arugments. * std.build.InstallDir: made dupe() a public function. * Added CPU feature check to standardTargetOptions (#8060). * std.build.LibExeObjStep: linkage is now an optional that defaults to null. Rather than duplicating the compiler's logic to determine whether to link statically or dynamically by default, the build system simply omits the flag unless overrridden. * zig build gains new flags: + --prefix-lib-dir [path]: Override default library directory path + --prefix-exe-dir [path]: Override default executable directory path + --prefix-include-dir [path]: Override default include directory path + --libc [file]: Provide a file which specifies libc paths. This new option sets a default libc paths file to be used for all LibExeObjSteps. Setting LibExeObjStep.libc_file overrides this default. This is required to allow users to cross compile projects linking system libraries without needing to patch the build.zig. + --debug-log [scope]: Enable debugging the compiler. * --override-lib-dir is renamed to --zig-lib-dir to disambiguate with --prefix-lib-dir. * Fixed transitive dependendencies on libraries incorrectly depending on the order that the dependencies were declared. * Print enum values for build options in help output (#9650). * Fixed handling of -Dcpu. Previously, -Dcpu was completely ignored if -Dtarget was not passed as well. Further, -Dcpu=baseline was ignored even if -Dtarget=native was passed. These two issues are now fixed; zig build always respects the -Dcpu option if present. * RunStep now distinguishes between unexpected child process exit code and unclean exit. * RunStep gains a print field, which controls whether it prints the command before running it. By default it is set to builder.verbose. * Added missing field: each_lib_rpath, which corresponds to -feach-lib-rpath and -fno-each-lib-rpath (#8800). * InstallRawStep: now properly handles empty segments. * InstallRawStep: added Intel HEX support (#9636). * InstallRawStep: allow custom dest_dir. * InstallRawStep: added single section dumping and padding. * Added emit path options to emit args in build.zig (#10278). * Added test executable builds to build.zig (#10288). * Fixed implibs for DLLs not being installed. Contributors: Andrew Kelley, Felix (xq) Queissner, Lee Cannon, Aaron Sikes, Jonathan Marler, Isaac Freund, Jakub Konka, Martin Wickham, Evan Haas, Ryan Liptak, Tom Maenan Read Cutting, Veikka Tuominen, Andrew Gutekanst, Asa Zeren, Edward Dean, Ellis Trisk-Grove, Jacob G-W, Jan200101, Jarred Sumner, Kenta Iwasaki, LemonBoy, Luuk de Gram, Matt Knight, N00byEdge, Ominitay, Takeshi Yoneda Generated Files as Inputs SS There has been a breaking change which breaks all projects using std.build.Pkg. The build system now uses std.build.FileSource in more places instead of paths. This supports the use case of using generated files anywhere the build system expects a file, such as when creating an executable or a library. Usage example: const std = @import("std"); const TemplateStep = @import("src/TemplateStep.zig"); pub fn build(b: *std.build.Builder) void { const target = b.standardTargetOptions(.{}); const mode = b.standardReleaseOptions(); // An arbitrary step that generates a output file const template_step = TemplateStep.create(b, std.build.FileSource{ .path = "example/layout.ztt", }); const exe = b.addExecutable("demo", "example/main.zig"); exe.addPackage(std.build.Pkg{ .name = "template", .path = template_step.getFileSource(), // we can now add the generated file also as a package source }); exe.setTarget(target); exe.setBuildMode(mode); exe.install(); } Build Options SS Previously, there was a function addBuildOption which could be used to create a basic build_options.zig file which could then be imported into zig code and used for conditional compilation. This API had several problems: * It was global; there could be only one set of options. * It was hard-coded to write to zig-cache/build_options.zig. Now this API is reworked (this is a breaking change) with the following improvements (#9623): * It integrates with the FileSource abstraction * It supports mapping as an arbitrarily named package. * It supports mapping to multiple different artifacts. * It uses a hash of contents for the filename, avoiding clobbering, and playing nicely with the Cache System. Example usage: const client = b.addSharedLibrary("client", "src/client/zig/client_main.zig", .unversioned); client.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding, }); client.addPackagePath("shared", "src/shared/index.zig"); const server_options = b.addOptions(); server_options.addOptionArtifact("client_wasm_path", client); server_options.addOption(u32, "mem_leak_frames", mem_leak_frames); server_options.addOption(bool, "support_mp3", support_mp3); const server = b.addExecutable("groovebasin", "src/server/server_main.zig"); server.setTarget(target); server.setBuildMode(mode); server.addPackagePath("shared", "src/shared/index.zig"); server.addOptions("build_options", server_options); server.install(); In this example, we see that the server_main.zig file will be able to @import("build_options").client_wasm_path and have a comptime string that contains the file path of the client WebAssembly file produced by Zig. Additionally, there were various bug fixes for addOption (#10016). Executors SS zig build now has the following additional flags: -fdarling, -fno-darling Integration with system-installed Darling to execute macOS programs on Linux hosts (default: no) -fqemu, -fno-qemu Integration with system-installed QEMU to execute foreign-architecture programs on Linux hosts (default: no) --glibc-runtimes [path] Enhances QEMU integration by providing glibc built for multiple foreign architectures, allowing execution of non-native programs that link with glibc. -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on ARM64 macOS hosts. (default: no) -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to execute WASI binaries. (default: no) -fwine, -fno-wine Integration with system-installed Wine to execute Windows programs on Linux hosts. (default: no) These enable integration with system-installed programs which can provide the ability to test cross-compiled build artifacts. For example: $ uname Linux $ uname -m x86_64 $ zig init-exe info: Created build.zig info: Created src/main.zig info: Next, try `zig build --help` or `zig build run` $ zig build test # run the tests natively All 1 tests passed. $ zig build test -Dtarget=aarch64-linux # compiles but does not run the tests $ zig build test -Dtarget=aarch64-linux -fqemu # now it runs the tests! All 1 tests passed. $ zig build test -Dtarget=x86_64-windows -fwine # we can even test our windows code on linux All 1 tests passed. Toolchain SS LLVM 13 SS This release of Zig upgrades to LLVM 13. Good news: we noticed something like a 12% improvement in compilation speed when we upgraded Zig from LLVM 12 to 13. musl 1.2.2 SS Zero the Ziguana Zig ships with the source code to musl. When the musl C ABI is selected, Zig builds static musl from source for the selected target. Zig also supports targeting dynamically linked musl which is useful for Linux distributions that use it as their system libc, such as Alpine Linux. Musl has not tagged a new release since Zig 0.8.0, so the version shipped with Zig remains at 1.2.2. However, there has been a major improvement when targeting dynamically linked musl libc. Zig now generates a more accurate libc.so for cross compiling purposes. Previously, the way it worked is that we used a script to process the output of objdump --dynamic-syms /path/to/musl/libc.so and generate a libc.s file, which could then be lazily compiled by Zig into libc.so for the requested target when cross compiling. The problem is that the input libc.so file we used was musl built dynamically for x86_64. While this is almost correct for other architectures besides x86_64, it is not completely correct, leading to bugs such as #8896. The updated script now inputs musl built for 7 different architectures: * libc.so built for riscv64 * libc.so built for mips * libc.so built for i386 * libc.so built for x86_64 * libc.so built for powerpc * libc.so built for powerpc64 * libc.so built for aarch64 These are produced by passing zig cc in as the CC environment variable when building musl (instructions). Next, the script identifies: * which symbols are common, and which are specific to some architectures * which symbols are functions, and which symbols are objects * what size (in bytes) the objects are Using this information, the script creates a libc.S file, which is shipped along with the Zig compiler. The file is only 104 KB because it uses the preprocessor in order to support the few differences between architectures. For example, if you execute Zig like this: zig build-exe hello.c -target aarch64-linux-musl -dynamic Zig will, under the hood, assemble libc.S with -DPTR64 -DARCH_aarch64, producing a libc.so file that can be passed to the linker, accurately modeling the libc.so that will be found on the target. The preprocessor directives in libc.S are based on excluding symbols, so even when targeting an architecture that is missing from that list of 7, will work fine; it's just that there may be extra symbols that shouldn't be there, and if there happened to be any special symbols that only existed for that one architecture, those will be missing. It will still be a small improvement to expand that list of 7 to more targets. Regardless, the changes made in this release are strictly an improvement when compared with prior status quo. glibc 2.34 SS Zig gains the ability to target glibc 2.34 in addition to the other 46 glibc versions. There was a major improvement to targeting glibc when cross compiling. Zig supports targeting every version of glibc for any target architecture. Previously, in order to accomplish this, Zig had only the information from the .abilist files from the latest verison of glibc: $ cat ../lib/libc/glibc/*.txt | wc -c 205219 $ cat ../lib/libc/glibc/*.txt | xz | wc -c 22976 The information required to do this took up 200 KB installation size / 22 KB tarball size, and it had the following problems (which caused several bugs): * It failed to represent symbols that migrate from one library to another between glibc versions (#7667). * It failed to represent a distinction between functions and objects (#8896). * It failed to represent object sizes. Now there is a new ziglang/glibc-abi-tool that produces an improved dataset. The project is quite interesting; if you are curious to learn more, check out the README of that repository which explains in detail the strategy and encoding. With the new dataset: $ cat abilists | wc -c 169421 $ cat abilists | xz | wc -c 24880 The new data that Zig ships with is 165 KB installation size / 24 KB tarball size, and all the above issues are solved. When a Zig user requests to cross compile for glibc, Zig uses this abilists file to create, for the requested glibc version and CPU architecture: * m.s * pthread.s * c.s * dl.s * rt.s * ld.s * util.s ...which are then assembled into: * libm.so * libpthread.so * libc.so * libdl.so * librt.so * ld.so * libutil.so These files are cached and placed on the linker line when cross compiling. Thanks to this improved dataset, they now accurately model the requested version of glibc. If we naively shipped every version of the .abilist files: $ cat (find glibc/ -name "*.abilist") | wc -c 37041906 $ cat (find glibc/ -name "*.abilist") | xz | wc -c 205036 ...it would have been 35 MiB installation size, 200 KB tarball size. So we have effectively achieved a compression ratio of 219:1 by implementing a bespoke encoding of this information. Native Version Detection SS When Zig is instructed to build for the native OS (which is the default, unless a -target argument is provided) on a glibc system, Zig first checks its own executable ELF file to determine if it is dynamically linked. If it is, it introspects its own dynamically loaded libraries to find libc, and find out if it is glibc, and if so, what version it is. When the Zig compiler is statically linked, it falls back to inspecting the /usr/bin/env ELF file to determine the native glibc version, by checking the DT_RUNPATH, and then calling readlink() on the libc.so file, because typically the symlink will have e.g. libc-2.33.so in the name, revealing the glibc version. Until now, if the file did not have a DT_RUNPATH, Zig would give up and fall back to the default version of glibc, which was 2.17. Fortunately, this information is also in readlink() of ld.so, which is available as the "INTERP" file path in the ELF file. Zig now looks for e.g. ld-2.33.so on the symlink data for the dynamic linker, which makes Zig correctly detect the native glibc version in more cases. In theory a more complete solution would also look at /etc/ ld.so.cache if necessary, and finally fall back to some hard coded paths, in order to resolve the location of libc.so, in order to do this readlink() trick on the resulting path. You can find that flow chart with man ld.so. But it looks like this logic will be enough to get a correct answer in all real world cases. Of course if we find out that is not the case, we can expand the detection logic. This has been tested on Debian Buster and glibc-based Void Linux. See #6469 for more details. mingw-w64 9.0.0 SS Zig ships with the source code to mingw-w64. When targeting *-windows-gnu and linking against libc, Zig builds mingw-w64 from source for the selected target. The mingw-w64 project has not tagged a new release since Zig 0.8.0, so the version shipped with Zig remains at 9.0.0. However, there have been improvements related to mingw-w64 integration: * Fixed logic to add crt sources for ARM. * Added implementation for _fseeki64 and _ftelli64 (#9402) (#9766). * Added missing file frexp.c to mingwex.lib. Fixes a frexp() segfault on Windows. * Fixed link error with LTO and mingw (#8674). libunwind SS Fixed unwinding through libunwind stack frames (#9591). libcxx SS Disabled redundant new/delete definitions which are already provided by libcxxabi. zig cc SS * Fixed not recognizing all the different pie flags that Clang supports. * Improved linker args parsing. Handle linker args joined with = such as -Wl,-rpath=foo. Update existing args --major-os-version, --minor-os-version, --major-subsystem-version and --minor-subsytem-version to work with the new parsing. Also handle -Wl,--script in addition to -Wl,-T. * Support -S and -emit-llvm CLI parameters (#6425). * Added -ffunction-sections, -fcolor-diagnostics, and -fcaret-diagnostics integration (#6290). * Added -Bdynamic and -Bstatic integration (#10050). * Honor all -m and -mno- CPU feature flags (#9196). Please be aware that there are still open zig cc issues. However, these are use cases that never worked in the first place, making them bugs and enhancements, not regressions. Contributors: Andrew Kelley, Vincent Rischmann zig c++ SS zig c++ is equivalent to zig cc with an added -lc++ parameter, but I made a separate heading here because I realized that some people are not aware that Zig supports compiling C++ code and providing libc++ too! #include int main() { std::cout << "Hello World!" << std::endl; return 0; } $ zig c++ -o hello hello.cpp $ ./hello Hello World! Cross-compiling too, of course: $ zig c++ -o hello hello.cpp -target riscv64-linux $ qemu-riscv64 ./hello Hello World! One thing that trips people up when they use this feature is that the C++ ABI is not stable across compilers, so always remember the rule: You must use the same C++ compiler to compile all your objects and static libraries. This is an unfortunate limitation of C++ which Zig can never fix. zig fmt SS * --ast-check now works in combination with --stdin. * Now respects trailing commas in inline assembly. * Fixed formatting for single-line containers with comments (#8810 ). * Fixed performance issue with nested arrays (#10224) (#10194). Contributors: Jacob G-W, jdmichaud, tjohnes, chwayne zig ar SS Fixed argument forwarding to LLVM on Windows, fixing zig ar on Windows. Objective-C and Objective-C++ SS Zig now supports compiling Objective-C files: Foo.h #import @interface Foo : NSObject - (NSString *)name; @end Foo.m #import "Foo.h" @implementation Foo - (NSString *)name { NSString *str = [[NSString alloc] initWithFormat:@"Zig"]; return str; } @end test.m #import "Foo.h" #import int main(int argc, char *argv[]) { @autoreleasepool { Foo *foo = [[Foo alloc] init]; NSString *result = [foo name]; assert([result isEqualToString:@"Zig"]); return 0; } } $ zig run test.m Foo.m -I. -framework Foundation Of course the zig cc CLI works as well: $ zig cc -o test test.m Foo.m -I. -framework Foundation Likewise, Zig now supports compiling Objective-C++ files. In our example, if we rename test.m to test.mm, Foo.m to Foo.mm, and update test.mm like so: test.mm #import "Foo.h" #import int main(int argc, char *argv[]) { @autoreleasepool { Foo *foo = [[Foo alloc] init]; NSString *result = [foo name]; std::cout << "Hello from C++ and " << [result UTF8String]; assert([result isEqualToString:@"Zig"]); return 0; } } $ zig run test.mm Foo.mm -I. -framework Foundation Hello from C++ and Zig Of course the zig c++ CLI works as well: $ zig c++ -o test test.mm Foo.mm -I. -framework Foundation Contributors: Stephen Gutekanst, Jakub Konka, Andrew Kelley compiler-rt SS compiler-rt is the library that provides, for example, 64-bit integer multiplication for 32-bit architectures which do not have a machine code instruction for it. In the GNU world, it's called libgcc. Unlike most compilers, which depend on a binary build of compiler-rt being installed alongside the compiler, Zig builds compiler-rt on-the-fly, from source, as needed for the target platform. This release saw some improvements to Zig's compiler-rt implementation (# 1290). * Added __clzdi2 and __clzti2. * Added __clzdi2 and __clzti2. * Added __ffssi2, __ffsdi2 and __ffsti2 (#10268). * Added __paritysi2, __paritydi2, __parityti2. * Added __ctzsi2, __ctzdi2 and __ctzti2. * Added __bswapsi2, __bswapdi2 and __bswapti2. * Added __cmpsi2, __cmpdi2, __cmpti2. * Added __ucmpsi2, __ucmpdi2, __ucmpti2. * Added __popcountsi2, __popcountdi2, and __popcountti2. * Added __mulosi2. * Added __negsi2, __negdi2, __negti2. * Added for 64-bit ARM: __chkstk, __divti3, __modti3, __udivti3, __umodti3 * Disable spinlocks for atomic instrinsics for BPF. The BPF target does not support mutable global variables. Mark the BPF target as not supporting atomic variables in order to avoid including the global spinlock table. * Added __isPlatformVersionAtLeast which are used for Objective-C and Objective-C++ @available expressions) on macOS (#10232). With all these additions, we nearly have a fully complete compiler-rt implementation! Contributors: Andrew Kelley, Jan Philipp Hafer, Jacob G-W, Jonathan Marler, LemonBoy, J.C. Moyer, Kenta Iwasaki, Stephen Gutekanst, Veikka Tuominen, jdmichaud Performance Tracking SS The gotta-go-fast repository contains a set of benchmarks that are now run for each commit on our Continuous Integration server, providing a set of graphs for various metrics that we track over time . Performance Dashboard Zero the Ziguana These have already helped diagnose performance regressions. As an example, the pull request that implemented Allocgate accidentally deleted a call to free() in the GeneralPurposeAllocator. This did not actually cause any tests to fail, but on the performance dashboard, it was clear that a bunch more memory was getting used. As Zig matures, we will add more benchmarks to this system, particularly for measuring compilation speed of various users' projects, so that we can pay attention to how changes to the codebase over time are affecting performance characteristics. Thank you to Austin Rude for improving the user interface and display of the graphs. Continuous Integration SS Zig Software Foundation is now paying Hetzner for a 100 euros/month bare metal x86_64 machine which operates ci.ziglang.org. We switched away from Azure for x86_64 Linux CI runs, gaining the following benefits: * The average CI run for x86_64-linux went from 4 hours to 1.5 hours. * We stopped experiencing false positive test failures due to the OOM killer. * We use the server's hard drive for a cache instead of downloading multiple hundreds of mebibytes from the Internet every run, saving on bandwidth costs. * Since it is a bare metal machine with deterministic hardware resources every run, it is used for running benchmarks for our new Performance Tracking system. Big, big thank you to Michael Dusan who volunteered his time to set up and maintain this. Please consider donating to the ZSF so that we can pay more people like him for their valuable time. Still on the to-do list is migrating these over to the new system via QEMU or some other OS virtualization software: * x86_64 Windows, currently running on Azure. * x86_64 FreeBSD, currently running on a LavaTech-hosted instance of SourceHut. And finally we still have these remaining: * aarch64-linux, currently running on Drone CI. For ARM 64-bit, we probably need to rent another bare metal machine that has an aarch64 CPU. On Drone CI it frequently fails CI runs with OOM, depending on the luck of the draw of which virtual machine it decides to run our builds on. * x86_64-macos, currently running on Azure. For some reason that is beyond my comprehension it is tricky to virtualize macOS (possibly for legal reasons?) so it seems this is not eligible to move over to be virtualized in our x86_64-linux box. I would love to be told that I am wrong about this. We are also seeing some CI runs fail with OOM on this one. * aarch64-macos, we don't have any CI coverage for this target yet. This has both the ARM 64-bit problem and the macOS problem. I don't know, maybe the play here would be getting a powerful aarch64-macos server and virtualizing Linux on it for the aarch64-linux case. Such machines don't really seem to be available yet. Unfortunately until we solve these last three, we will continue to experience flaky CI failures due to OOM. That is, until we ship the Self-Hosted Compiler, which uses significantly less memory, side-stepping this problem. Other miscellaneous news: * The CI pipeline now uses zig fmt and rejects contributions which do not conform (#9106). Roadmap SS Ziggy the Ziguana The primary goal of the 0.9.0 release cycle was self-hosting the compiler. At this time, 44% of the behavior tests are passing, with the percent rising quickly. The major theme of the 0.10.0 release cycle will be stabilizing the language, creating a first draft of the language specification, and self-hosting the compiler. Some upcoming milestones in the next release cycle: * Self-Hosted Compiler can build itself with the LLVM Backend. Unlocks faster development iteration times when working on the Self-Hosted Compiler. * All behavior tests and other tests passing with the LLVM Backend. At this point we can ship the Self-Hosted Compiler instead of the Bootstrap Compiler. * Self-Hosted Compiler can build itself with the C Backend. Unlocks ability to replace the Bootstrap Compiler with Self-Hosted Compiler generated C code (#6378). * Self-Hosted Linker support for ELF. At this point it will be time to do a proof of concept of hot code swapping for Linux. * Self-Hosted Linker support for PE/COFF. At this point it will be time to do a proof of concept of hot code swapping for Windows. * Behavior tests passing for the x86 Backend or aarch64 Backend. Unleashes our full compilation speed when targeting the respective architecture. Package Manager Status SS Having a package manager built into the Zig compiler is a long-anticipated feature. Zig 0.9.0 does not have this feature. If the package manager works well, people will use it, which means building Zig projects will involve compiling more lines of Zig code, which means the Zig compiler must get faster, better at incremental compilation, and better at resource management. Therefore, the package manager depends on finishing the Self-Hosted Compiler, since it is planned to have these improved performance characteristics, while the Bootstrap Compiler is not planned to have them. Accepted Proposals SS If you want more of a sense of the direction Zig is heading, you can look at the set of accepted proposals. Thank You Sponsors! SS Ziggy the Ziguana Special thanks to those who sponsor Zig. Because of you, Zig is driven by the open source community, rather than the goal of making profit. In particular, these fine folks sponsor Zig for $50/month or more: * Pex * Kirk Scheibelhut * drfuchs * tarasbob * Lager Data * Stephen Gutekanst * Stevie Hryciw * Derek Collison * Karrick McDermott * Joran Dirk Greef * The Lycus Foundation * Bjorn Linse * Dustin Taylor * Jose M Rico * Simon A. Nielsen Knights * Josh Wolfe * Ryan Saunderson * ryanworl * Rui Ueyama * Alun Bestor * Evan Ovadia * Terin Stock * Aras Pranckevicius * Jethro Nederhof * Christopher David Shirk * David Vanderson * SkunkWerks GmbH * Matthew Knight * Loic Tosser * tawawhite * Martin Schwaighofer * Santiago Andaluz * Luke Champine * Rand Fitzpatrick * Jesus Alvarez * Vincent Foley * Alexis Sellier * Charlie Cheever * Brett Slatkin * Wojtek Mach * Max De Marzi * Matyas Tamas * Christopher Dolan * Robert Hencke * Rain * Alex Bubnov * Anton Kochkov * Jamie Brandon * Jordan Orelli * Max Bernstein * Timothy Ham * mbarkhau * Andrew Gallant * Jay Petacat * Christian Wesselhoeft * Tyler Gibbons * Keith Devens * Agam Dua * Ian * Daniel Hensley * Charles * Erik Lundin * Sean * Andrey Nekrasov * Vincent Rischmann * Emily A. Bellows * Martin Wickham * Lee Cannon * Neil Wang * Ross Rheingans-Yoo * Per Lonn Wege * Felix Queissner * Mario Arias * Luuk de Gram * Mateusz Czarnecki * jamesmcgill * Yaroslav Zhavoronkov * Clay Kuppinger * Tom Maenan Read Cutting * Mykhailo Tsiuptsiun * meraymond2 * Auguste Rame * Mamadou S Diallo * cryptocode * Dirk de Visser * topolarity