From 512eab0db082f1679af4de77b1f1713409766fcf Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Tue, 14 Apr 2026 14:29:49 -0700 Subject: [PATCH] upgrade to zig 0.16.0 --- .mise.toml | 2 +- build.zig | 41 ++++++++++++++++++++++++----------------- build.zig.zon | 2 +- src/main.zig | 21 +++++++++------------ src/srf.zig | 6 +++--- 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/.mise.toml b/.mise.toml index 9927c37..c338b44 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,5 +1,5 @@ [tools] prek = "0.3.1" "ubi:DonIsaac/zlint" = "0.7.9" -zig = "0.15.2" +zig = "0.16.0" zls = "0.15.1" diff --git a/build.zig b/build.zig index c390dbc..dd7d730 100644 --- a/build.zig +++ b/build.zig @@ -250,6 +250,7 @@ const BenchmarkStep = struct { const b = step.owner; const self: *BenchmarkStep = @fieldParentPtr("step", step); + const io = b.graph.io; const gen_path = b.getInstallPath(.bin, self.gen_exe.name); const exe_path = b.getInstallPath(.bin, self.srf_exe.name); const count_str = b.fmt("{d}", .{self.record_count}); @@ -271,29 +272,32 @@ const BenchmarkStep = struct { const hash_str = b.fmt("{x}", .{hash}); const cache_dir = b.cache_root.join(b.allocator, &.{ "o", hash_str }) catch @panic("OOM"); - std.fs.cwd().makePath(cache_dir) catch {}; + b.cache_root.handle.createDirPath(io, cache_dir) catch @panic("Could not create cache path"); const filename = b.fmt("test-{s}.{s}", .{ fmt.name, fmt.ext }); const filepath = b.pathJoin(&.{ cache_dir, filename }); test_files[i] = filepath; // Check if file exists - if (std.fs.cwd().access(filepath, .{})) { + if (b.cache_root.handle.access(io, filepath, .{})) { continue; // File exists, skip generation } else |_| {} // Generate file - var child = std.process.Child.init(&.{ gen_path, fmt.name, count_str }, b.allocator); - child.stdout_behavior = .Pipe; - try child.spawn(); + var child = try std.process.spawn(io, .{ + .argv = &.{ gen_path, fmt.name, count_str }, + .stdout = .pipe, + }); - const output = try child.stdout.?.readToEndAlloc(b.allocator, 100 * 1024 * 1024); + var buf: [4096]u8 = undefined; + var file_reader = child.stdout.?.reader(io, &buf); + var reader = &file_reader.interface; + const output = try reader.allocRemaining(b.allocator, .unlimited); defer b.allocator.free(output); + const term = try child.wait(io); + if (term != .exited or term.exited != 0) return error.GenerationFailed; - const term = try child.wait(); - if (term != .Exited or term.Exited != 0) return error.GenerationFailed; - - try std.fs.cwd().writeFile(.{ .sub_path = filepath, .data = output }); + try b.cache_root.handle.writeFile(io, .{ .sub_path = filepath, .data = output }); } // Run hyperfine @@ -308,16 +312,19 @@ const BenchmarkStep = struct { try argv.append(b.allocator, b.fmt("{s} jsonl <{s}", .{ exe_path, test_files[2] })); } - var child = std.process.Child.init(argv.items, b.allocator); - // We need to lock stderror so hyperfine can output progress in place - std.debug.lockStdErr(); - defer std.debug.unlockStdErr(); + // SAFETY: buffer for locking + var buf: [1024]u8 = undefined; // I have no idea what the right size buffer should be + _ = try io.lockStderr(&buf, null); + defer io.unlockStderr(); - try child.spawn(); - const term = try child.wait(); + var child = try std.process.spawn(io, .{ + .argv = argv.items, + }); - if (term != .Exited or term.Exited != 0) + const term = try child.wait(io); + + if (term != .exited or term.exited != 0) return error.BenchmarkFailed; } }; diff --git a/build.zig.zon b/build.zig.zon index 5b5a298..6fab4ff 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -25,7 +25,7 @@ .fingerprint = 0x102ed002eff998a9, // Changing this has security and trust implications. // Tracks the earliest Zig version that the package considers to be a // supported use case. - .minimum_zig_version = "0.15.2", + .minimum_zig_version = "0.16.0", // This field is optional. // Each dependency must either provide a `url` and `hash`, or a `path`. // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. diff --git a/src/main.zig b/src/main.zig index ad7deee..f69bc9a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -46,13 +46,10 @@ const CountingAllocator = struct { } }; -pub fn main() !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - const base_allocator = gpa.allocator(); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; - const args = try std.process.argsAlloc(base_allocator); - defer std.process.argsFree(base_allocator, args); + const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len < 2) { std.debug.print("Usage: {s} \n", .{args[0]}); @@ -61,19 +58,19 @@ pub fn main() !void { const format = args[1]; - const debug_allocs = std.process.hasEnvVarConstant("DEBUG_ALLOCATIONS"); + const debug_allocs = init.environ_map.contains("DEBUG_ALLOCATIONS"); - var counting = CountingAllocator{ .child_allocator = base_allocator }; - const allocator = if (debug_allocs) counting.allocator() else base_allocator; + var counting = CountingAllocator{ .child_allocator = gpa }; + const allocator = if (debug_allocs) counting.allocator() else gpa; var stdin_buffer: [1024]u8 = undefined; - var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer); + var stdin_reader = std.Io.File.stdin().reader(init.io, &stdin_buffer); const stdin = &stdin_reader.interface; // Load all data into memory first for fair comparison var data: std.ArrayList(u8) = .empty; - defer data.deinit(base_allocator); - try stdin.appendRemaining(base_allocator, &data, @enumFromInt(100 * 1024 * 1024)); + defer data.deinit(gpa); + try stdin.appendRemaining(gpa, &data, @enumFromInt(100 * 1024 * 1024)); if (std.mem.eql(u8, format, "srf")) { var reader = std.Io.Reader.fixed(data.items); diff --git a/src/srf.zig b/src/srf.zig index 0273ea9..a4582e2 100644 --- a/src/srf.zig +++ b/src/srf.zig @@ -1018,9 +1018,9 @@ pub const RecordIterator = struct { /// use or refresh cached data. Note that data will be returned by parse/ /// iterator regardless of freshness. This enables callers to use cached /// data temporarily while refreshing it - pub fn isFresh(self: RecordIterator) bool { + pub fn isFresh(self: RecordIterator, io: std.Io) bool { if (self.expires) |exp| - return std.time.timestamp() < exp; + return std.Io.Timestamp.now(io, .real).toSeconds() < exp; // no expiry: always fresh, never frozen return true; @@ -1038,7 +1038,7 @@ pub const RecordIterator = struct { defer ri.deinit(); // No expiry set, so always fresh - try std.testing.expect(ri.isFresh()); + try std.testing.expect(ri.isFresh(std.testing.io)); } };