diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.github/workflows/zig-checkers.yml b/.github/workflows/zig-checkers.yml new file mode 100644 index 0000000..0367ed3 --- /dev/null +++ b/.github/workflows/zig-checkers.yml @@ -0,0 +1,20 @@ +name: zig-checkers +on: + push: +permissions: {} + +jobs: + run-zig-build: + strategy: + matrix: + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Setup zig + uses: mlugg/setup-zig@v1.2.0 + with: + version: 0.13.0 + - name: zig-build + run: zig build diff --git a/.gitignore b/.gitignore index 541e1b4..ec9547b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,23 @@ -*.swp -zig-* +# This file is for zig-specific build artifacts. +# If you have OS-specific or editor-specific files to ignore, +# such as *.swp or .DS_Store, put those in your global +# ~/.gitignore and put this in your ~/.gitconfig: +# +# [core] +# excludesfile = ~/.gitignore +# +# Cheers! +# -andrewrk +.zig-cache/ +zig-out/ +/release/ +/debug/ +/build/ +/build-*/ +/docgen_tmp/ +# Although this was renamed to .zig-cache, let's leave it here for a few +# releases to make it less annoying to work with multiple branches. +zig-cache/ + +# header-gen directory headers/ diff --git a/README.md b/README.md index 4358683..91b383b 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,10 @@ Here are the following supported Zig language features: - [x] Extern Unions - [x] Extern Enums +## Zig version + +zig 0.13.0 + ## Getting started Given the following Zig code as the file `src/fancylib.zig` and using the C generator: diff --git a/build.zig b/build.zig index 6e0b60b..7969750 100644 --- a/build.zig +++ b/build.zig @@ -1,26 +1,31 @@ -const Builder = @import("std").build.Builder; - const std = @import("std"); -const warn = std.debug.print; // This build.zig is only used as an example of using header_gen -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); - - const mode = b.standardReleaseOptions(); + const optimize = b.standardOptimizeOption(.{}); // HEADER GEN BUILD STEP - const exe = b.addExecutable("example", "src/example/exports.zig"); - exe.main_pkg_path = "src/"; - exe.setTarget(target); - exe.setBuildMode(mode); - exe.addPackagePath("header_gen", "src/header_gen.zig"); - exe.install(); + const header_gen = b.addModule("header_gen", .{ + .root_source_file = b.path("src/header_gen.zig"), + }); + const exe = b.addExecutable(.{ + .name = "example", + .root_source_file = b.path("src/example/exports.zig"), + .target = target, + .optimize = optimize, + }); + exe.root_module.addImport("header_gen", header_gen); + b.installArtifact(exe); - const run_cmd = exe.run(); + const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + const run_step = b.step("headergen", "Run the app"); run_step.dependOn(&run_cmd.step); } diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..04e9861 --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,13 @@ +.{ + .name = "header_gen", + .version = "0.0.0", + .dependencies = .{}, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + "example", + "LICENSE", + "README.md", + }, +} diff --git a/src/deps_graph.zig b/src/deps_graph.zig index 03fd0f7..f4acb6f 100644 --- a/src/deps_graph.zig +++ b/src/deps_graph.zig @@ -76,7 +76,7 @@ pub fn DepsGraph(comptime T: type) type { pub const BeginSymbolError = error{ DuplicateSymbol, OutOfMemory }; pub fn beginSymbol(self: *Self, name: []const u8, payload: T) BeginSymbolError!void { - var result = try self.symbols.getOrPut(name); + const result = try self.symbols.getOrPut(name); if (result.found_existing) { return error.DuplicateSymbol; @@ -148,13 +148,13 @@ pub fn DepsGraph(comptime T: type) type { pub const EndSymbolError = error{OutOfMemory}; pub fn createNode(comptime V: type, data: V, allocator: Allocator) !*TailQueue(V).Node { - var node = try allocator.create(TailQueue(V).Node); + const node = try allocator.create(TailQueue(V).Node); node.* = .{ .data = data }; return node; } pub fn endSymbol(self: *Self) EndSymbolError!void { - var current_symbol = self.current_symbol orelse return; + const current_symbol = self.current_symbol orelse return; var unblock_queue = std.TailQueue(EmittedSymbol){}; @@ -199,9 +199,9 @@ pub fn DepsGraph(comptime T: type) type { } pub fn readEmitted(self: *Self) ?EmittedSymbol { - var symbol_node = self.emitted.popFirst() orelse return null; + const symbol_node = self.emitted.popFirst() orelse return null; - var symbol = symbol_node.data; + const symbol = symbol_node.data; self.allocator.destroy(symbol_node); @@ -277,7 +277,7 @@ pub fn DepsGraph(comptime T: type) type { _ = dependency_name; var maybe_dep_index: ?usize = null; - for (self.dependencies.items) |dependency, i| { + for (self.dependencies.items, 0..) |dependency, i| { if (dependency.eqlName(dependency)) { maybe_dep_index = i; break; @@ -430,7 +430,7 @@ test "Blocked symbols iterator" { try expect(deps.readEmitted() == null); var iter = deps.blockedIterator(); - var symbol = iter.next(); + const symbol = iter.next(); try expect(symbol != null); try expectEqualStrings(symbol.?.name, "TextPosition"); diff --git a/src/generators/c.zig b/src/generators/c.zig index bdeb428..63459f2 100644 --- a/src/generators/c.zig +++ b/src/generators/c.zig @@ -14,7 +14,7 @@ pub const C_Generator = struct { pub fn init(comptime src_file: []const u8, dst_dir: *Dir) Self { - var file = dst_dir.createFile(comptime filebase(src_file) ++ ".h", .{}) catch + const file = dst_dir.createFile(comptime filebase(src_file) ++ ".h", .{}) catch @panic("Failed to create header file for source: " ++ src_file); var res = Self{ .file = file }; @@ -48,7 +48,7 @@ pub const C_Generator = struct { self.writeType(meta.return_type.?); self.write(" " ++ name ++ "("); - inline for (meta.params) |arg, i| { + inline for (meta.params, 0..) |arg, i| { self.writeType(arg.type.?); //TODO: Figure out how to get arg names; for now just do arg0..argN _ = self.file.writer().print(" arg{}", .{i}) catch unreachable; @@ -93,7 +93,7 @@ pub const C_Generator = struct { self.write("enum " ++ name ++ " {\n"); comptime var last = 0; - inline for (meta.fields) |field, i| { + inline for (meta.fields, 0..) |field, i| { self.write(" " ++ field.name); // if field value is unexpected/custom, manually define it diff --git a/src/generators/ordered.zig b/src/generators/ordered.zig index c37f30a..8305c22 100644 --- a/src/generators/ordered.zig +++ b/src/generators/ordered.zig @@ -61,7 +61,7 @@ pub fn Ordered_Generator(comptime Generator: type) type { const Self = @This(); pub fn init(comptime src_file: []const u8, dst_dir: *Dir) Self { - var allocator = std.heap.page_allocator; + const allocator = std.heap.page_allocator; return Self{ .inner_gen = Generator.init(src_file, dst_dir), @@ -82,7 +82,7 @@ pub fn Ordered_Generator(comptime Generator: type) type { } fn getNextPhaseFor(self: *Self, symbol_name: []const u8, partial: bool) !?SymbolPhase { - var result = try self.emitted_phase.getOrPut(symbol_name); + const result = try self.emitted_phase.getOrPut(symbol_name); if (!result.found_existing) { result.value_ptr.* = if (partial) .Signature else .Full; @@ -106,7 +106,7 @@ pub fn Ordered_Generator(comptime Generator: type) type { const partial = if (emitted.symbol.payload == .Fn) false else emitted.partial; _ = partial; - var phase = self.getNextPhaseFor(emitted.symbol.name, emitted.partial) catch unreachable orelse continue; + const phase = self.getNextPhaseFor(emitted.symbol.name, emitted.partial) catch unreachable orelse continue; switch (emitted.symbol.payload) { .Struct => |meta| self.inner_gen.gen_struct(emitted.symbol.name, meta, phase), diff --git a/src/generators/python.zig b/src/generators/python.zig index 667f12a..bb301a6 100644 --- a/src/generators/python.zig +++ b/src/generators/python.zig @@ -17,7 +17,7 @@ pub const Python_Generator = struct { const Self = @This(); pub fn init(comptime src_file: []const u8, dst_dir: *Dir) Self { - var file = dst_dir.createFile(comptime filebase(src_file) ++ ".py", .{}) catch + const file = dst_dir.createFile(comptime filebase(src_file) ++ ".py", .{}) catch @panic("Failed to create header file for source: " ++ src_file); var res = Self{ .file = file }; @@ -45,7 +45,7 @@ pub const Python_Generator = struct { pub fn gen_func(self: *Self, name: []const u8, meta: FnMeta) void { self.print("lib.{s}.argtypes = [", .{name}); - for (meta.params) |arg, i| { + for (meta.params, 0..) |arg, i| { if (arg.type) |t| { self.writeType(t.*); } else { @@ -77,7 +77,7 @@ pub const Python_Generator = struct { self.write("\t_fields_ = ["); } - for (fields) |field, i| { + for (fields, 0..) |field, i| { if (i > 0) { self.write(prefix); } @@ -192,7 +192,7 @@ pub const Python_Generator = struct { var was_lower: bool = false; var is_upper: bool = undefined; - for (str) |char, i| { + for (str, 0..) |char, i| { is_upper = std.ascii.isUpper(char); if (char == '_' and i > 0) { diff --git a/src/header_gen.zig b/src/header_gen.zig index c3f9fb4..29c6e13 100644 --- a/src/header_gen.zig +++ b/src/header_gen.zig @@ -50,7 +50,7 @@ fn validateGenerator(comptime Generator: type) void { } pub fn HeaderGen(comptime S: type, comptime libname: []const u8) type { - comptime var all_decls: []const Declaration = @typeInfo(S).Struct.decls; + const all_decls: []const Declaration = @typeInfo(S).Struct.decls; return struct { decls: @TypeOf(all_decls) = all_decls, diff --git a/src/runtime.zig b/src/runtime.zig index 4be9056..324a700 100644 --- a/src/runtime.zig +++ b/src/runtime.zig @@ -43,7 +43,7 @@ pub const TypeInfo = union(enum) { pub fn init(comptime m: std.builtin.Type.Int) Int { return comptime .{ - .signedness = @intToEnum(Signedness, @enumToInt(m.signedness)), + .signedness = @enumFromInt(Signedness), .bits = m.bits, }; } @@ -93,7 +93,7 @@ pub const TypeInfo = union(enum) { pub fn init(comptime m: std.builtin.Type.Pointer) Pointer { return comptime .{ - .size = @intToEnum(TypeInfo.Pointer.Size, @enumToInt(m.size)), + .size = @enumFromInt(TypeInfo.Pointer.Size), .is_const = m.is_const, .is_volatile = m.is_volatile, .alignment = m.alignment, @@ -151,7 +151,9 @@ pub const TypeInfo = union(enum) { Packed, }; comptime { - validateSymbolInSync(ContainerLayout, std.builtin.Type.ContainerLayout, .{}); + validateSymbolInSync(ContainerLayout, std.builtin.Type.ContainerLayout, .{ + .ignore_fields = .{"auto", "extern", "packed"}, + }); } /// This data structure is used by the Zig language code generation and @@ -202,20 +204,20 @@ pub const TypeInfo = union(enum) { pub fn init(comptime m: std.builtin.Type.Struct, comptime name: []const u8) Struct { return comptime .{ .name = name, - .layout = @intToEnum(TypeInfo.ContainerLayout, @enumToInt(m.layout)), + .layout = @enumFromInt(TypeInfo.ContainerLayout), .fields = fields: { - comptime var arr: [m.fields.len]StructField = undefined; + const arr: [m.fields.len]StructField = undefined; - inline for (m.fields) |f, i| { + for (m.fields, 0..) |f, i| { arr[i] = StructField.init(f); } break :fields &arr; }, .decls = decls: { - comptime var arr: [m.decls.len]Declaration = undefined; + const arr: [m.decls.len]Declaration = undefined; - inline for (m.decls) |f, i| { + for (m.decls, 0..) |f, i| { arr[i] = Declaration.init(f); } @@ -336,21 +338,21 @@ pub const TypeInfo = union(enum) { pub fn init(comptime m: std.builtin.Type.Enum, comptime name: []const u8) Enum { return comptime .{ .name = name, - .layout = @intToEnum(TypeInfo.ContainerLayout, @enumToInt(m.layout)), + .layout = @enumFromInt(TypeInfo.ContainerLayout), .tag_type = &TypeInfo.init(m.tag_type), .fields = fields: { - comptime var arr: [m.fields.len]EnumField = undefined; + const arr: [m.fields.len]EnumField = undefined; - inline for (m.fields) |f, i| { + for (m.fields, 0..) |f, i| { arr[i] = EnumField.init(f); } break :fields &arr; }, .decls = decls: { - comptime var arr: [m.decls.len]Declaration = undefined; + const arr: [m.decls.len]Declaration = undefined; - inline for (m.decls) |f, i| { + for (m.decls, 0..) |f, i| { arr[i] = Declaration.init(f); } @@ -422,21 +424,21 @@ pub const TypeInfo = union(enum) { pub fn init(comptime m: std.builtin.Type.Union, comptime name: []const u8) Union { return comptime .{ .name = name, - .layout = @intToEnum(TypeInfo.ContainerLayout, @enumToInt(m.layout)), + .layout = @enumFromInt(TypeInfo.ContainerLayout), .tag_type = if (m.tag_type) |t| &TypeInfo.init(t) else null, .fields = fields: { - comptime var arr: [m.fields.len]UnionField = undefined; + const arr: [m.fields.len]UnionField = undefined; - inline for (m.fields) |f, i| { + for (m.fields, 0..) |f, i| { arr[i] = UnionField.init(f); } break :fields &arr; }, .decls = decls: { - comptime var arr: [m.decls.len]Declaration = undefined; + const arr: [m.decls.len]Declaration = undefined; - inline for (m.decls) |f, i| { + for (m.decls, 0..) |f, i| { arr[i] = Declaration.init(f); } @@ -487,7 +489,9 @@ pub const TypeInfo = union(enum) { } }; comptime { - validateSymbolInSync(Param, std.builtin.Type.Fn.Param, .{}); + validateSymbolInSync(Param, std.builtin.Type.Fn.Param, .{ + .ignore_fields = .{"arg_type"}, + }); } /// This data structure is used by the Zig language code generation and @@ -502,15 +506,15 @@ pub const TypeInfo = union(enum) { pub fn init(comptime m: std.builtin.Type.Fn) Fn { return comptime .{ - .calling_convention = @intToEnum(CallingConvention, @enumToInt(m.calling_convention)), + .calling_convention = @enumFromInt(CallingConvention), .alignment = m.alignment, .is_generic = m.is_generic, .is_var_args = m.is_var_args, .return_type = if (m.return_type) |t| &TypeInfo.init(t) else null, .args = args: { - comptime var arr: [m.args.len]Param = undefined; + const arr: [m.args.len]Param = undefined; - inline for (m.args) |f, i| { + for (m.args, 0..) |f, i| { arr[i] = Param.init(f); } @@ -532,7 +536,9 @@ pub const TypeInfo = union(enum) { } }; comptime { - validateSymbolInSync(Fn, std.builtin.Type.Fn, .{}); + validateSymbolInSync(Fn, std.builtin.Type.Fn, .{ + .ignore_fields = .{"args"}, + }); } pub const Opaque = struct { @@ -541,9 +547,9 @@ pub const TypeInfo = union(enum) { pub fn init(comptime m: std.builtin.Type.Opaque) Opaque { return comptime .{ .decls = decls: { - comptime var arr: [m.decls.len]Declaration = undefined; + const arr: [m.decls.len]Declaration = undefined; - inline for (m.decls) |f, i| { + for (m.decls, 0..) |f, i| { arr[i] = Declaration.init(f); } @@ -645,13 +651,13 @@ pub const TypeInfo = union(enum) { } usingnamespace blk: { - var uniqueIdCounter: usize = 0; + const uniqueIdCounter: usize = 0; break :blk struct { pub fn uniqueId(comptime T: type) usize { _ = T; comptime { - var id = uniqueIdCounter; + const id = uniqueIdCounter; uniqueIdCounter += 1; @@ -703,9 +709,9 @@ pub const TypeInfo = union(enum) { .ErrorSet = errorset: { if (m == null) return null; - comptime var arr: [m.?.len]Error = undefined; + const arr: [m.?.len]Error = undefined; - inline for (m.?) |f, i| { + for (m.?, 0..) |f, i| { arr[i] = .{ .name = f.name, }; @@ -845,32 +851,32 @@ const talloc = std.testing.allocator; // TODO .Type test "Runtime TypeInfo.Void" { - var info_void = TypeInfo.init(void); + const info_void = TypeInfo.init(void); try expect(info_void == .Void); } test "Runtime TypeInfo.Bool" { - var info_bool = TypeInfo.init(bool); + const info_bool = TypeInfo.init(bool); try expect(info_bool == .Bool); } // TODO .NoReturn test "Runtime TypeInfo.Int" { - var info_i32 = TypeInfo.init(i32); + const info_i32 = TypeInfo.init(i32); try expect(info_i32 == .Int); try expectEqual(@as(i32, 32), info_i32.Int.bits); try expectEqual(true, info_i32.Int.signedness == .signed); } test "Runtime TypeInfo.Float" { - var info_f64 = TypeInfo.init(f64); + const info_f64 = TypeInfo.init(f64); try expect(info_f64 == .Float); try expectEqual(@as(i32, 64), info_f64.Float.bits); } test "Runtime TypeInfo.Pointer" { - var info_pointer_f64 = TypeInfo.init(*f64); + const info_pointer_f64 = TypeInfo.init(*f64); try expect(info_pointer_f64 == .Pointer); try expectEqual(TypeInfo.Pointer.Size.One, info_pointer_f64.Pointer.size); try expectEqual(false, info_pointer_f64.Pointer.is_const); @@ -879,7 +885,7 @@ test "Runtime TypeInfo.Pointer" { try expect(info_pointer_f64.Pointer.child.* == .Float); try expectEqual(false, info_pointer_f64.Pointer.is_allowzero); - var info_pointer_many = TypeInfo.init([*]f64); + const info_pointer_many = TypeInfo.init([*]f64); try expect(info_pointer_many == .Pointer); try expectEqual(TypeInfo.Pointer.Size.Many, info_pointer_many.Pointer.size); try expectEqual(false, info_pointer_many.Pointer.is_const); @@ -890,7 +896,7 @@ test "Runtime TypeInfo.Pointer" { } test "Runtime TypeInfo.Array" { - var info_array = TypeInfo.init([2]i32); + const info_array = TypeInfo.init([2]i32); try expect(info_array == .Array); try expectEqual(@as(i32, 2), info_array.Array.len); try expect(info_array.Array.child.* == .Int); @@ -903,7 +909,7 @@ test "Runtime TypeInfo.Struct" { pub fn bar() void {} }; - var info_struct = TypeInfo.init(FooStruct); + const info_struct = TypeInfo.init(FooStruct); try expect(info_struct == .Struct); try expect(info_struct.Struct.layout == .Auto); try expectEqual(@as(usize, 1), info_struct.Struct.fields.len); @@ -912,12 +918,12 @@ test "Runtime TypeInfo.Struct" { } test "Runtime TypeInfo.ComptimeFloat" { - var info_comptime_float = TypeInfo.init(comptime_float); + const info_comptime_float = TypeInfo.init(comptime_float); try expect(info_comptime_float == .ComptimeFloat); } test "Runtime TypeInfo.ComptimeInt" { - var info_comptime_int = TypeInfo.init(comptime_int); + const info_comptime_int = TypeInfo.init(comptime_int); try expect(info_comptime_int == .ComptimeInt); } @@ -925,7 +931,7 @@ test "Runtime TypeInfo.ComptimeInt" { // // TODO .Null test "Runtime TypeInfo.Optional" { - var info_optional = TypeInfo.init(?i32); + const info_optional = TypeInfo.init(?i32); try expect(info_optional == .Optional); try expect(info_optional.Optional.child.* == .Int); } @@ -936,26 +942,26 @@ test "Runtime TypeInfo.Optional" { test "Runtime TypeInfo.Enum" { const FooEnum = enum { Foo, Bar }; - var info_enum = TypeInfo.init(FooEnum); + const info_enum = TypeInfo.init(FooEnum); try expect(info_enum == .Enum); } test "Runtime TypeInfo.Union" { const FooUnion = union { Foo: void, Bar: i32 }; - var info_union = TypeInfo.init(FooUnion); + const info_union = TypeInfo.init(FooUnion); try expect(info_union == .Union); } test "Runtime TypeInfo.Fn" { // .Fn - var info_fn = TypeInfo.init(fn () void); + const info_fn = TypeInfo.init(fn () void); try expect(info_fn == .Fn); } test "Runtime TypeInfo.Struct declarations" { // .Fn - var info_fn = TypeInfo.init(struct { + const info_fn = TypeInfo.init(struct { const WackType = packed struct { mr_field: *LameType, ola: u8 }; const LameType = struct {