diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8255a72..afcf267 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - name: setup zig uses: mlugg/setup-zig@v2 with: - version: 0.14.1 + version: 0.15.2 - name: zig build run: zig build --summary all diff --git a/CHANGELOG.md b/CHANGELOG.md index 48d7c48..ce1548b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,21 +4,25 @@ SPDX-FileCopyrightText: © 2025 Mark Delk SPDX-License-Identifier: MIT --> -## [Unreleased] +## Unreleased -## [0.3.0] - 2025-07-15 +## `0.4.0` - 2026-04-21 + +- update to zig 0.15.2 + +## `0.3.0` - 2025-07-15 - update to zig 0.14.1 - update mruby (still 3.4.0) -## [0.2.0] - 2025-06-01 +## `0.2.0` - 2025-06-01 - bump to latest mruby (3.4.0), use upstream instead of a fork -## [0.1.1] - 2025-02-20 +## `0.1.1` - 2025-02-20 - fix several small issues -## [0.1.0] - 2025-02-19 +## `0.1.0` - 2025-02-19 - initial open-source release diff --git a/README.md b/README.md index b5c707c..879fbb6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT # mruby.zig -Build [mruby](https://github.com/mruby/mruby) using [zig](https://ziglang.org) `0.14.1` (no rake!). +Build [mruby](https://github.com/mruby/mruby) using [zig](https://ziglang.org) `0.15.2` (no rake!). ## About @@ -18,8 +18,6 @@ This project builds MRuby from source, only using Zig. This means we emulate MRuby's non-trivial Rake-based build process entirely in Zig. -**NOTE**: We only support zig `0.14.1` at the moment. - ## Issues - Non-standard library gems that use any Ruby logic in their `mrbgem.rake` files aren't supported @@ -46,6 +44,8 @@ zig-out/bin/ ├── mrbtest ├── mruby └── mruby-strip + +1 directory, 8 files ``` See `zig build -h` for information about everything that's available: @@ -79,15 +79,14 @@ zig build mrbtest ``` mrbtest - Embeddable Ruby Test -............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... - Total: 1647 - OK: 1647 +........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... + Total: 1659 + OK: 1659 KO: 0 Crash: 0 Warning: 0 Skip: 0 - Time: 1.07 seconds - + Time: 1.4 seconds ``` To use `mirb`, `mruby`, etc: diff --git a/build.zig b/build.zig index ba44a29..53c320c 100644 --- a/build.zig +++ b/build.zig @@ -153,7 +153,7 @@ pub fn build(b: *std.Build) !void { index += 1; if (index == diagnostics.getLine()) { - var prefix = std.ArrayList(u8).init(b.allocator); + var prefix = std.array_list.Managed(u8).init(b.allocator); defer prefix.deinit(); var prefix_index: usize = 0; @@ -167,7 +167,7 @@ pub fn build(b: *std.Build) !void { @panic("failed to parse gems.json"); }; - var gems = std.ArrayList(Mgem).init(b.allocator); + var gems = std.array_list.Managed(Mgem).init(b.allocator); defer gems.deinit(); var builtin_gem_map = std.StringHashMap(Mgem).init(b.allocator); @@ -204,13 +204,17 @@ pub fn build(b: *std.Build) !void { const mrbc_exe = b.addExecutable(.{ .name = "mrbc", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); const host_mrbc_exe = b.addExecutable(.{ .name = "host-mrbc", - .target = b.graph.host, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = b.graph.host, + .optimize = optimize, + }), }); { for ([_]*std.Build.Step.Compile{ @@ -246,10 +250,13 @@ pub fn build(b: *std.Build) !void { // - const mruby_lib = b.addStaticLibrary(.{ + const mruby_lib = b.addLibrary(.{ .name = "libruby", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .root_source_file = null, + .target = target, + .optimize = optimize, + }), }); { const lib = mruby_lib; @@ -362,7 +369,7 @@ pub fn build(b: *std.Build) !void { }); } - var gem_init_content = std.ArrayList(u8).init(b.allocator); + var gem_init_content = std.array_list.Managed(u8).init(b.allocator); defer gem_init_content.deinit(); try gem_init_content.appendSlice( @@ -479,7 +486,7 @@ pub fn build(b: *std.Build) !void { // // generate mrbgems/gem_init.c { - var gem_init_content = std.ArrayList(u8).init(b.allocator); + var gem_init_content = std.array_list.Managed(u8).init(b.allocator); defer gem_init_content.deinit(); try gem_init_content.appendSlice( @@ -595,8 +602,10 @@ pub fn build(b: *std.Build) !void { const mruby_exe = b.addExecutable(.{ .name = "mruby", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); { const exe = mruby_exe; @@ -626,8 +635,10 @@ pub fn build(b: *std.Build) !void { const mirb_exe = b.addExecutable(.{ .name = "mirb", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); { const exe = mirb_exe; @@ -663,8 +674,10 @@ pub fn build(b: *std.Build) !void { // zig build mrdb -DMRB_USE_DEBUG_HOOK=true -- sample.rb const mrdb_exe = b.addExecutable(.{ .name = "mrdb", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); { const exe = mrdb_exe; @@ -698,8 +711,10 @@ pub fn build(b: *std.Build) !void { const mruby_strip_exe = b.addExecutable(.{ .name = "mruby-strip", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); { const exe = mruby_strip_exe; @@ -729,8 +744,10 @@ pub fn build(b: *std.Build) !void { const mrbtest = b.addExecutable(.{ .name = "mrbtest", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); { const exe = mrbtest; @@ -772,7 +789,7 @@ pub fn build(b: *std.Build) !void { } for (mruby_gems) |gem| { - var gem_test_content = std.ArrayList(u8).init(b.allocator); + var gem_test_content = std.array_list.Managed(u8).init(b.allocator); defer gem_test_content.deinit(); if (gem.test_rbfiles.len == 0) continue; @@ -837,7 +854,7 @@ pub fn build(b: *std.Build) !void { \\ , .{gem.name})[0..]); - var dependencies = std.ArrayList([]const u8).init(b.allocator); + var dependencies = std.array_list.Managed([]const u8).init(b.allocator); defer dependencies.deinit(); for (gem.dependencies) |dep| @@ -967,7 +984,7 @@ pub fn build(b: *std.Build) !void { // mrbgems/mruby-test/mrbtest.c { - var mrbtest_content = std.ArrayList(u8).init(b.allocator); + var mrbtest_content = std.array_list.Managed(u8).init(b.allocator); defer mrbtest_content.deinit(); try mrbtest_content.appendSlice( @@ -1070,6 +1087,23 @@ pub fn build(b: *std.Build) !void { // + const module = b.addModule("mruby", .{ + .root_source_file = b.addWriteFiles().add("src/lib.zig", + \\pub const c = @import("c"); + ), + // // after translate-c supports bitfields... + // .root_source_file = b.addWriteFiles().add("src/lib.zig", + // \\pub const c = @cImport({ + // \\ @cInclude("mruby.h"); + // \\ @cInclude("mruby/compile.h"); + // \\ @cInclude("mruby/data.h"); + // \\ @cInclude("mruby/string.h"); + // \\ @cInclude("mruby/variable.h"); + // \\ @cInclude("mruby/array.h"); + // \\}); + // ), + }); + const translate_c = b.addTranslateC(.{ // every header needed to use MRuby, add more as needed .root_source_file = b.addWriteFiles().add("input.c", @@ -1085,30 +1119,40 @@ pub fn build(b: *std.Build) !void { }); { translate_c.addIncludePath(mruby_dep.path("include")); - } - // TODO: this won't be needed after translate-c supports bitfields - const fix_translation_exe = b.addExecutable(.{ - .name = "fix-translation", - .target = b.graph.host, - .optimize = .ReleaseFast, - .root_source_file = b.path("src/fix_translation.zig"), - }); - const fix_translation = b.addRunArtifact(fix_translation_exe); - { - fix_translation.addFileArg(translate_c.getOutput()); + // const install = b.addInstallFile(translate_c.getOutput(), "input.h"); + // const step = b.step("fix-translation-header", "Generate translation input"); + // step.dependOn(&install.step); } - const fixed_translation = fix_translation.captureStdOut(); - const module = b.addModule("mruby", .{ - .root_source_file = b.addWriteFiles().add("src/lib.zig", - \\pub const c = @import("c"); - ), - }); { - module.addImport("c", b.createModule(.{ - .root_source_file = fixed_translation, - })); + // TODO: this won't be needed after translate-c supports bitfields + const fix_translation_exe = b.addExecutable(.{ + .name = "fix-translation", + .root_module = b.createModule(.{ + .target = b.graph.host, + .optimize = .ReleaseFast, + .root_source_file = b.path("src/fix_translation.zig"), + }), + }); + const fix_translation = b.addRunArtifact(fix_translation_exe); + { + fix_translation.addFileArg(translate_c.getOutput()); + } + const fixed_translation = fix_translation.captureStdOut(); + + // const install = b.addInstallFile(fixed_translation, "fixed-translation.zig"); + // const step = b.step("fix-translation", "Generate translation output"); + // step.dependOn(&install.step); + + module.addAnonymousImport("c", .{ + // .root_source_file = fixed_translation, + // TODO: why does this work, but not the above? + .root_source_file = b.addWriteFiles().addCopyFile(fixed_translation, "src/lib.zig"), + }); + + // TODO: when zig-translate-c has bitfield support + // module.addImport("c", translate_c.createModule()); module.linkLibrary(mruby_lib); } @@ -1117,8 +1161,10 @@ pub fn build(b: *std.Build) !void { const example_c = b.addExecutable(.{ .name = "example-c", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); { example_c.addCSourceFiles(.{ @@ -1164,13 +1210,21 @@ pub fn build(b: *std.Build) !void { const example_zig = b.addExecutable(.{ .name = "example-zig", - .target = target, - .optimize = optimize, - .root_source_file = b.path("src/example.zig"), + + // TODO: errors without this... :( + // undefined symbol: etext + // undefined symbol: edata + .use_llvm = true, + .root_module = b.createModule(.{ + .root_source_file = b.path("src/example.zig"), + .target = target, + .optimize = optimize, + .imports = &.{ + .{ .name = "mruby", .module = module }, + }, + }), }); { - example_zig.root_module.addImport("mruby", module); - b.installArtifact(example_zig); const run = b.addRunArtifact(example_zig); diff --git a/build.zig.zon b/build.zig.zon index 6c7310f..08cb71d 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -6,7 +6,7 @@ .name = .mruby, .fingerprint = 0x4a9e46f0ee99188a, .version = "0.0.0", - .minimum_zig_version = "0.14.1", + .minimum_zig_version = "0.15.2", .paths = .{ "src", "build.zig", diff --git a/build/linenoise/build.zig b/build/linenoise/build.zig index 4be438c..15e1192 100644 --- a/build/linenoise/build.zig +++ b/build/linenoise/build.zig @@ -10,11 +10,14 @@ pub fn build(b: *std.Build) !void { const src_dep = b.dependency("linenoise", .{}); - const lib = b.addStaticLibrary(.{ + const lib = b.addLibrary(.{ .name = "linenoise", - .target = target, - .optimize = .ReleaseFast, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); + { lib.addIncludePath(src_dep.path("")); lib.linkLibC(); @@ -34,8 +37,10 @@ pub fn build(b: *std.Build) !void { const example = b.addExecutable(.{ .name = "example", - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), }); { example.linkLibrary(lib); diff --git a/src/example.zig b/src/example.zig index 340e383..25e8ac4 100644 --- a/src/example.zig +++ b/src/example.zig @@ -99,18 +99,18 @@ pub fn main() !void { logger.info("Done", .{}); } -fn string_method(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mruby.mrb_value { +fn string_method(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.c) mruby.mrb_value { _ = self; return mruby.mrb_str_new_cstr(mrb, "example"); } -fn int_method(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mruby.mrb_value { +fn int_method(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.c) mruby.mrb_value { _ = self; _ = mrb; return mruby.mrb_fixnum_value(42); } -fn nil_method(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mruby.mrb_value { +fn nil_method(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.c) mruby.mrb_value { _ = self; _ = mrb; return mruby.mrb_nil_value(); @@ -151,13 +151,13 @@ const foo_data_type = mruby.mrb_data_type{ .dfree = fooFree, }; -fn fooFree(mrb: ?*mruby.mrb_state, ptr: ?*anyopaque) callconv(.C) void { +fn fooFree(mrb: ?*mruby.mrb_state, ptr: ?*anyopaque) callconv(.c) void { const foo: Foo = @as(*Foo, @ptrCast(@alignCast(ptr))).*; foo.close(); mruby.mrb_free(mrb, ptr); } -fn fooInitalize(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mruby.mrb_value { +fn fooInitalize(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.c) mruby.mrb_value { const new_memory = mruby.mrb_malloc_simple(mrb, @sizeOf(Foo)) orelse { @panic("mrb_malloc_simple returned NULL"); }; @@ -175,7 +175,7 @@ fn fooInitalize(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mr return self; } -fn oneArg(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mruby.mrb_value { +fn oneArg(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.c) mruby.mrb_value { const arg = mruby.mrb_get_arg1(mrb); const code = mruby.mrb_fixnum(arg); @@ -188,7 +188,7 @@ fn oneArg(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mruby.mr return mruby.mrb_fixnum_value(result); } -fn twoArgs(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.C) mruby.mrb_value { +fn twoArgs(mrb: [*c]mruby.mrb_state, self: mruby.mrb_value) callconv(.c) mruby.mrb_value { var a: i64 = undefined; var b: i64 = undefined; diff --git a/src/fix_translation.zig b/src/fix_translation.zig index 50b452f..cac8c1c 100644 --- a/src/fix_translation.zig +++ b/src/fix_translation.zig @@ -29,28 +29,26 @@ pub fn main() !void { const input_file = try std.fs.cwd().openFile(args[1], .{}); errdefer input_file.close(); - const reader = input_file.reader(); - const writer = std.io.getStdOut().writer(); + var read_buf: [4 * 1024]u8 = undefined; + var file_reader: std.fs.File.Reader = input_file.reader(&read_buf); - var line_buf = std.ArrayList(u8).init(allocator); - defer line_buf.deinit(); + var stdout_buffer: [1024]u8 = undefined; + var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); - while (reader.streamUntilDelimiter(line_buf.writer(), '\n', null)) { - if (line_buf.getLastOrNull() == '\r') _ = line_buf.pop(); - defer line_buf.clearRetainingCapacity(); + const reader = &file_reader.interface; + const writer = &stdout_writer.interface; - const line = line_buf.items; - // logger.debug("{s}", .{line}); + while (reader.takeDelimiterExclusive('\n')) |line| { + _ = reader.toss(1); if (std.mem.eql(u8, line, " gc: mrb_gc = @import(\"std\").mem.zeroes(mrb_gc),")) { - _ = try writer.write(" gc: u128 = @import(\"std\").mem.zeroes(u128),"); + _ = try writer.writeAll(" gc: u128 = @import(\"std\").mem.zeroes(u128),"); } else { - _ = try writer.write(line); + _ = try writer.writeAll(line); } - _ = try writer.write("\n"); - } else |err| switch (err) { - error.EndOfStream => {}, - else => |e| return e, + _ = try writer.flush(); + } else |err| { + if (err != error.EndOfStream) return err; } }