From 7e1eb1946a212054c353a4f10b21da5840e49b09 Mon Sep 17 00:00:00 2001 From: quartz55 Date: Sat, 11 Apr 2026 09:29:40 +0200 Subject: [PATCH] Update to Zig 0.16 - build.zig: moved link_libcpp to module creation and linkLibrary to module-level calls + std.Io related changes - std.Io: replaced std.io.FixedBufferStream with std.Io.Writer/Reader, updated Buffer.stream() to separate writer()/reader() methods --- .github/actions/setup-zig/action.yml | 2 +- .github/actions/setup-zig/install-zig.sh | 7 ++- .github/workflows/ci.yml | 2 +- .gitignore | 1 + build.zig | 48 ++++++++++++------- build.zig.zon | 2 +- examples/guided_tour.zig | 34 +++++++------- src/Lua.zig | 59 +++++++++++++++--------- src/tests.zig | 32 ++++++------- 9 files changed, 110 insertions(+), 77 deletions(-) diff --git a/.github/actions/setup-zig/action.yml b/.github/actions/setup-zig/action.yml index 23fb5af..1fa7918 100644 --- a/.github/actions/setup-zig/action.yml +++ b/.github/actions/setup-zig/action.yml @@ -4,7 +4,7 @@ inputs: version: description: 'Zig version to install' required: false - default: '0.15.1' + default: '0.16.0-dev.3153+d6f43caad' runs: using: 'composite' diff --git a/.github/actions/setup-zig/install-zig.sh b/.github/actions/setup-zig/install-zig.sh index 8cb68fc..609add9 100755 --- a/.github/actions/setup-zig/install-zig.sh +++ b/.github/actions/setup-zig/install-zig.sh @@ -54,7 +54,12 @@ else EXTRACT_CMD="tar -xf" fi -URL="https://ziglang.org/download/${VERSION}/${FILENAME}" +# Dev/nightly builds are served from /builds/, stable releases from /download// +if [[ "$VERSION" == *"-dev."* ]]; then + URL="https://ziglang.org/builds/${FILENAME}" +else + URL="https://ziglang.org/download/${VERSION}/${FILENAME}" +fi ARCHIVE_PATH="${INSTALL_DIR}/${FILENAME}" EXTRACTED_DIR="${INSTALL_DIR}/zig-${ARCH}-${OS}-${VERSION}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d63643c..e98ba6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] - zig-version: ['0.15.1'] + zig-version: ['0.16.0-dev.3153+d6f43caad'] defaults: run: diff --git a/.gitignore b/.gitignore index cb68ed9..16ba9a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .zig-cache/ zig-out/ +zig-pkg/ *.o .claude/settings.local.json diff --git a/build.zig b/build.zig index f699126..3c1875c 100644 --- a/build.zig +++ b/build.zig @@ -38,7 +38,11 @@ pub fn build(b: *std.Build) !void { // Luau VM lib const luau_vm = blk: { - const mod = b.createModule(.{ .target = target, .optimize = optimize }); + const mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libcpp = true, + }); try addSrcFiles(b, mod, luau_dep, "VM/src", flags); @@ -52,7 +56,6 @@ pub fn build(b: *std.Build) !void { const lib = b.addLibrary(.{ .name = "luau_vm", .root_module = mod, .linkage = .static }); lib.installHeadersDirectory(luau_dep.path("VM/include"), "", .{}); - lib.linkLibCpp(); b.installArtifact(lib); @@ -63,7 +66,11 @@ pub fn build(b: *std.Build) !void { // Luau CodeGen lib const luau_codegen = blk: { - const mod = b.createModule(.{ .target = target, .optimize = optimize }); + const mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libcpp = true, + }); try addSrcFiles(b, mod, luau_dep, "CodeGen/src", flags); @@ -72,13 +79,12 @@ pub fn build(b: *std.Build) !void { mod.addIncludePath(luau_dep.path("Common/include")); mod.addIncludePath(luau_dep.path("VM/src")); + mod.linkLibrary(luau_vm); + const lib = b.addLibrary(.{ .name = "luau_codegen", .root_module = mod, .linkage = .static }); lib.installHeader(luau_dep.path("CodeGen/include/luacodegen.h"), "luacodegen.h"); - lib.linkLibCpp(); - lib.linkLibrary(luau_vm); - b.installArtifact(lib); steps.luau_codegen.dependOn(&lib.step); @@ -88,7 +94,11 @@ pub fn build(b: *std.Build) !void { // Luau compiler lib const luau_compiler = blk: { - const mod = b.createModule(.{ .target = target, .optimize = optimize }); + const mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libcpp = true, + }); try addSrcFiles(b, mod, luau_dep, "Compiler/src", flags); try addSrcFiles(b, mod, luau_dep, "Ast/src", flags); @@ -104,7 +114,6 @@ pub fn build(b: *std.Build) !void { const lib = b.addLibrary(.{ .name = "luau_compiler", .root_module = mod, .linkage = .static }); lib.installHeader(luau_dep.path("Compiler/include/luacode.h"), "luacode.h"); - lib.linkLibCpp(); b.installArtifact(lib); @@ -113,7 +122,11 @@ pub fn build(b: *std.Build) !void { // Luau compiler binary { - const mod = b.createModule(.{ .target = target, .optimize = optimize }); + const mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libcpp = true, + }); mod.addCSourceFiles(.{ .root = luau_dep.path("."), @@ -143,7 +156,11 @@ pub fn build(b: *std.Build) !void { // Luau analyze binary { - const mod = b.createModule(.{ .target = target, .optimize = optimize }); + const mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libcpp = true, + }); try addSrcFiles(b, mod, luau_dep, "Analysis/src", flags); try addSrcFiles(b, mod, luau_dep, "Config/src", flags); @@ -172,8 +189,6 @@ pub fn build(b: *std.Build) !void { .root_module = mod, }); - exe.linkLibCpp(); - const run = b.addRunArtifact(exe); if (b.args) |args| { run.addArgs(args); @@ -269,6 +284,7 @@ pub fn build(b: *std.Build) !void { .root_source_file = b.path("src/tests.zig"), .target = target, .optimize = optimize, + .link_libcpp = true, }); test_mod.addImport("luaz", b.modules.get("luaz").?); @@ -287,8 +303,6 @@ pub fn build(b: *std.Build) !void { }); } - unit_tests.linkLibCpp(); - const run_tests = b.addRunArtifact(unit_tests); steps.@"test".dependOn(&run_tests.step); } @@ -332,15 +346,15 @@ fn addSrcFiles( const extensions = [_][]const u8{ ".cpp", ".c" }; const abs_path = dep.path(dir_path).getPath(b); - var dir = try std.fs.openDirAbsolute(abs_path, .{ .iterate = true }); - defer dir.close(); + var dir = try b.build_root.handle.openDir(b.graph.io, abs_path, .{ .iterate = true }); + defer dir.close(b.graph.io); var walker = try dir.walk(b.allocator); defer walker.deinit(); var files: std.ArrayList([]const u8) = .empty; - while (try walker.next()) |entry| { + while (try walker.next(b.graph.io)) |entry| { const ext = std.fs.path.extension(entry.basename); const include = for (extensions) |e| { if (std.mem.eql(u8, ext, e)) diff --git a/build.zig.zon b/build.zig.zon index cbd4014..e81c9ac 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -9,7 +9,7 @@ }, .fingerprint = 0xceb8ffd87c49e0c3, // Changing this has security and trust implications. - .minimum_zig_version = "0.14.1", + .minimum_zig_version = "0.16.0-dev.3153+d6f43caad", .paths = .{ "build.zig", diff --git a/examples/guided_tour.zig b/examples/guided_tour.zig index 2b0ae09..061a58b 100644 --- a/examples/guided_tour.zig +++ b/examples/guided_tour.zig @@ -152,7 +152,7 @@ const Counter = struct { pub fn main() !void { // Create an allocator (you can use any Zig allocator) - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + var gpa = std.heap.DebugAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); @@ -682,31 +682,29 @@ pub fn main() !void { print("Version: 0x{X:0>8}\n", .{std.mem.readInt(u32, buf.data[4..8], .little)}); // Use std.io patterns for structured reading/writing - var stream = buf.stream(); + var w = buf.writer(); + w.end = 16; // Seek past header - // Seek past header and write structured data - try stream.seekTo(16); - - // Write various data types using the stream writer - const writer = stream.writer(); - try writer.writeInt(u16, 0xABCD, .big); // 16-bit big-endian - try writer.writeInt(u32, 0x12345678, .little); // 32-bit little-endian - try writer.writeAll("Binary data chunk"); // Raw bytes + // Write various data types using the writer + try w.writeInt(u16, 0xABCD, .big); // 16-bit big-endian + try w.writeInt(u32, 0x12345678, .little); // 32-bit little-endian + try w.writeAll("Binary data chunk"); // Raw bytes // Write float as raw bytes (IEEE 754 double) const write_float_bytes = std.mem.toBytes(@as(f64, 3.14159)); - try writer.writeAll(&write_float_bytes); + try w.writeAll(&write_float_bytes); - // Read back the data using stream reader - try stream.seekTo(16); - const reader = stream.reader(); - const val16 = try reader.readInt(u16, .big); - const val32 = try reader.readInt(u32, .little); + // Read back the data using the reader + var r = buf.reader(); + r.seek = 16; + r.end = w.end; // Limit to bytes written + const val16 = try r.takeInt(u16, .big); + const val32 = try r.takeInt(u32, .little); var text_buf: [17]u8 = undefined; - _ = try reader.read(&text_buf); + try r.readSliceAll(&text_buf); // Read float as raw bytes and convert back var float_bytes: [8]u8 = undefined; - _ = try reader.read(&float_bytes); + try r.readSliceAll(&float_bytes); const float_val = std.mem.bytesToValue(f64, &float_bytes); print("Read back: u16=0x{X}, u32=0x{X}, text='{s}', float={d:.5}\n", .{ val16, val32, text_buf, float_val }); diff --git a/src/Lua.zig b/src/Lua.zig index 8271a73..4c99079 100644 --- a/src/Lua.zig +++ b/src/Lua.zig @@ -1499,8 +1499,8 @@ pub inline fn createTable(self: Self, opts: struct { arr: u32 = 0, rec: u32 = 0 /// @memcpy(buf.data[10..15], "hello"); /// /// // Use with I/O patterns -/// var stream = buf.stream(); -/// try stream.writer().writeInt(u32, 0x12345678, .little); +/// var w = buf.writer(); +/// try w.writeInt(u32, 0x12345678, .little); /// ``` /// /// Returns: `Buffer` - A wrapper around the newly created buffer @@ -1886,10 +1886,12 @@ pub const Function = struct { /// @memcpy(buf.data[10..20], "hello"); /// /// // Use with std.io patterns -/// var stream = buf.stream(); -/// try stream.writer().writeInt(u32, 0x12345678, .little); -/// try stream.seekTo(0); -/// const value = try stream.reader().readInt(u32, .little); +/// var w = buf.writer(); +/// try w.writeInt(u32, 0x12345678, .little); +/// +/// var r = buf.reader(); +/// r.end = w.end; // Limit to bytes written +/// const value = try r.takeVarInt(u32, .little, 4); /// ``` pub const Buffer = struct { ref: Ref, @@ -1910,23 +1912,38 @@ pub const Buffer = struct { return self.data.len; } - /// Returns a stream for reading/writing/seeking within the buffer. + /// Returns a Writer for sequential writing to the buffer. /// - /// The stream provides standard I/O operations on the buffer memory: - /// - `.writer()` - Get a writer for sequential writing - /// - `.reader()` - Get a reader for sequential reading - /// - `.seekTo(pos)` - Seek to a specific position - /// - `.getPos()` - Get current position + /// The writer uses the entire buffer capacity. It returns `error.WriteFailed` + /// when the buffer is full. Check `writer.end` for the current write position. /// /// Example: /// ```zig - /// var stream = buf.stream(); - /// try stream.writer().writeAll("Hello"); - /// try stream.seekTo(0); - /// const data = try stream.reader().readAllAlloc(allocator, 1024); + /// var w = buf.writer(); + /// try w.writeInt(u32, 0x12345678, .little); + /// const bytes_written = w.end; + /// ``` + pub fn writer(self: *Buffer) std.Io.Writer { + return std.Io.Writer.fixed(self.data); + } + + /// Returns a Reader for sequential reading from the buffer. + /// + /// By default, reads from position 0 to the end of the buffer. Adjust + /// `reader.seek` and `reader.end` fields to control the read range. + /// + /// Example: + /// ```zig + /// // Read only bytes that were written + /// var w = buf.writer(); + /// try w.writeAll("hello"); + /// + /// var r = buf.reader(); + /// r.end = w.end; // Limit to bytes written + /// const data = try r.peek(r.end); /// ``` - pub fn stream(self: *Buffer) std.io.FixedBufferStream([]u8) { - return std.io.fixedBufferStream(self.data); + pub fn reader(self: *Buffer) std.Io.Reader { + return std.Io.Reader.fixed(self.data); } /// Returns the registry reference ID if valid, otherwise null. @@ -2526,9 +2543,9 @@ pub fn registerUserData(self: Self, comptime T: type) !void { /// Returns: Allocated string containing the stack dump. Caller owns the memory. /// Errors: `std.mem.Allocator.Error` if memory allocation fails pub fn dumpStack(self: Self, allocator: std.mem.Allocator) ![]u8 { - var list: std.ArrayList(u8) = .empty; + var list = std.Io.Writer.Allocating.init(allocator); + const writer = &list.writer; - const writer = list.writer(allocator); const stack_size = self.state.getTop(); if (stack_size == 0) { @@ -2548,7 +2565,7 @@ pub fn dumpStack(self: Self, allocator: std.mem.Allocator) ![]u8 { n -= 1; } - return list.toOwnedSlice(allocator); + return list.toOwnedSlice(); } /// Apply sandbox restrictions to create a secure execution environment. diff --git a/src/tests.zig b/src/tests.zig index 0dfed29..e0923d0 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -1495,25 +1495,23 @@ test "buffer with std.io patterns" { var buf = try lua.createBuffer(256); defer buf.deinit(); - // Test writing with stream - var stream = buf.stream(); - - // Write various integer types - try stream.writer().writeInt(u32, 0x12345678, .little); - try stream.writer().writeInt(u16, 0xABCD, .little); - try stream.writer().writeInt(u8, 0xFF, .little); - - // Write string - try stream.writer().writeAll("Hello"); - - // Seek back and read - try stream.seekTo(0); - try expectEq(try stream.reader().readInt(u32, .little), 0x12345678); - try expectEq(try stream.reader().readInt(u16, .little), 0xABCD); - try expectEq(try stream.reader().readInt(u8, .little), 0xFF); + // Write with writer + var w = buf.writer(); + try w.writeInt(u32, 0x12345678, .little); + try w.writeInt(u16, 0xABCD, .little); + try w.writeByte(0xFF); + try w.writeAll("Hello"); + const bytes_written = w.end; + + // Read with reader - limit to bytes written + var r = buf.reader(); + r.end = bytes_written; + try expectEq(try r.takeVarInt(u32, .little, 4), 0x12345678); + try expectEq(try r.takeVarInt(u16, .little, 2), 0xABCD); + try expectEq(try r.takeByte(), 0xFF); var read_buf: [5]u8 = undefined; - _ = try stream.reader().read(&read_buf); + try r.readSliceAll(&read_buf); try expect(std.mem.eql(u8, &read_buf, "Hello")); }