Updates Zig

This commit is contained in:
Mason Remaley 2026-04-13 23:40:46 -07:00
parent 1673ed636a
commit a6bdcb3836
3 changed files with 63 additions and 61 deletions

5
.gitignore vendored
View file

@ -1,2 +1,3 @@
.zig-cache
zig-out
/.zig-cache/
/zig-out/
/zig-pkg/

View file

@ -2,7 +2,7 @@
.name = .dear_imgui,
.fingerprint = 0xc1cc609af54040bd,
.version = "1.0.0",
.minimum_zig_version = "0.16.0-dev.2193+fc517bd01",
.minimum_zig_version = "0.16.0-dev.3153+d6f43caad",
.dependencies = .{
.@"dear-imgui" = .{
// Using a patched version of v1.92.5-docking that has a UBSAN fix. The equivalent to

View file

@ -9,29 +9,27 @@ const DeclarationKind = enum {
import, // Assumed to be normal, but external
};
const Declarations = std.StringArrayHashMap(DeclarationKind);
const Declarations = std.array_hash_map.String(DeclarationKind);
const Symbols = struct {
public: std.StringArrayHashMap(void),
front_buf: std.StringArrayHashMap(void),
public: std.array_hash_map.String(void),
front_buf: std.array_hash_map.String(void),
pub fn init(allocator: Allocator) @This() {
return .{
.public = .init(allocator),
.front_buf = .init(allocator),
pub const empty: @This() = .{
.public = .empty,
.front_buf = .empty,
};
}
pub fn deinit(self: *@This()) void {
self.public.deinit();
self.front_buf.deinit();
pub fn deinit(self: *@This(), gpa: Allocator) void {
self.public.deinit(gpa);
self.front_buf.deinit(gpa);
}
/// Returns true if there's already a public symbol with this name.
pub fn put(self: *@This(), name: []const u8) !bool {
pub fn put(self: *@This(), gpa: Allocator, name: []const u8) !bool {
const trimmed = std.mem.trimEnd(u8, name, "_");
if (self.public.contains(trimmed)) return false;
try self.front_buf.put(trimmed, {});
try self.front_buf.put(gpa, trimmed, {});
return true;
}
@ -207,8 +205,8 @@ pub fn main(init: std.process.Init) !void {
}
// Build a list of symbols so we can skip duplicates of public symbols in the internal headers
var symbols: Symbols = .init(allocator);
defer symbols.deinit();
var symbols: Symbols = .empty;
defer symbols.deinit(allocator);
// Write the source
const main_source = try Dir.cwd().readFileAlloc(io, in_path, allocator, .limited(max_size));
@ -254,43 +252,43 @@ pub fn main(init: std.process.Init) !void {
}
fn writeSource(
allocator: Allocator,
gpa: Allocator,
source: []const u8,
writer: *Io.Writer,
symbols: *Symbols,
internal: bool,
) !void {
const header = try std.json.parseFromSlice(Header, allocator, source, .{
const header = try std.json.parseFromSlice(Header, gpa, source, .{
.ignore_unknown_fields = true,
});
defer header.deinit();
// We need the list of declarations up front.
var declarations = try getDeclarations(allocator, &header.value);
defer declarations.deinit();
var declarations = try getDeclarations(gpa, &header.value);
defer declarations.deinit(gpa);
// Write all defines as private constants.
try writeDefines(writer, internal, symbols, &header.value);
try writeDefines(gpa, writer, internal, symbols, &header.value);
// Write all typedefs as private constants.
try writeTypedefs(writer, &header.value, symbols, &declarations);
try writeTypedefs(gpa, writer, &header.value, symbols, &declarations);
// Write all cimgui functions as private extern functions.
try writeExternFunctions(writer, &header.value, symbols, &declarations);
try writeExternFunctions(gpa, writer, &header.value, symbols, &declarations);
// Alias cimgui free functions under Zig friendly names.
try writeFreeFunctions(writer, &header.value, symbols);
try writeFreeFunctions(gpa, writer, &header.value, symbols);
// Get a list of cimgui methods. These were already written as externs, and can be aliased
// when we write their respective types.
var methods = try Methods.get(allocator, &header.value);
defer methods.deinit(allocator);
var methods = try Methods.get(gpa, &header.value);
defer methods.deinit(gpa);
// Write cimgui enums as Zig enums.
try writeEnums(allocator, writer, internal, &header.value, symbols);
try writeEnums(gpa, writer, internal, &header.value, symbols);
// Write cimgui structs as Zig structs and unions.
try writeStructs(writer, &header.value, &declarations, &methods, symbols);
try writeStructs(gpa, writer, &header.value, &declarations, &methods, symbols);
// Write helpers used by the other generated code. We skip this for the internal header
// since we're going to concatenate it with the main header, so this stuff will already be
@ -300,9 +298,9 @@ fn writeSource(
}
}
fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations {
var declarations = Declarations.init(allocator);
errdefer declarations.deinit();
fn getDeclarations(gpa: Allocator, header: *const Header) !Declarations {
var declarations: Declarations = .empty;
errdefer declarations.deinit(gpa);
for (header.structs) |ty| {
if (skip(ty.conditionals)) continue;
@ -337,20 +335,20 @@ fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations {
};
}
try declarations.put(trimmed, kind);
try declarations.put(gpa, trimmed, kind);
}
for (header.enums) |e| {
if (skip(e.conditionals)) continue;
const trimmed = std.mem.trimEnd(u8, e.name, "_");
try declarations.put(trimmed, .normal);
try declarations.put(gpa, trimmed, .normal);
}
return declarations;
}
fn writeDefines(writer: anytype, internal: bool, symbols: *Symbols, header: *const Header) !void {
fn writeDefines(gpa: Allocator, writer: anytype, internal: bool, symbols: *Symbols, header: *const Header) !void {
// We skip defines from the internal namespace for now
if (internal) return;
@ -358,7 +356,7 @@ fn writeDefines(writer: anytype, internal: bool, symbols: *Symbols, header: *con
if (define.is_internal != internal) continue;
if (skip(define.conditionals)) continue;
if (define.content) |content| {
if (try symbols.put(define.name)) {
if (try symbols.put(gpa, define.name)) {
if (std.mem.startsWith(u8, content, "(")) {
const end = std.mem.indexOfScalar(u8, content, ')').?;
const ty = content[1..end];
@ -375,6 +373,7 @@ fn writeDefines(writer: anytype, internal: bool, symbols: *Symbols, header: *con
}
fn writeTypedefs(
gpa: Allocator,
writer: anytype,
header: *const Header,
symbols: *Symbols,
@ -392,7 +391,7 @@ fn writeTypedefs(
std.mem.eql(u8, typedef.name, typedef.type.declaration.?)) continue;
// Write the typedef prefix
if (try symbols.put(typedef.name)) {
if (try symbols.put(gpa, typedef.name)) {
try writer.writeAll("pub const ");
try writeTypeName(writer, typedef.name);
try writer.writeAll(" = ");
@ -403,6 +402,7 @@ fn writeTypedefs(
}
fn writeExternFunctions(
gpa: Allocator,
writer: anytype,
header: *const Header,
symbols: *Symbols,
@ -412,7 +412,7 @@ fn writeExternFunctions(
if (skip(function.conditionals)) continue;
if (argsContainsVaList(function.arguments)) continue;
if (try symbols.put(function.name)) {
if (try symbols.put(gpa, function.name)) {
try writer.print("extern fn {s}(", .{function.name});
for (function.arguments) |argument| {
if (argument.type) |ty| {
@ -446,13 +446,13 @@ fn argsContainsVaList(arguments: []const Header.Function.Argument) bool {
return false;
}
fn writeFreeFunctions(writer: anytype, header: *const Header, symbols: *Symbols) !void {
fn writeFreeFunctions(gpa: Allocator, writer: anytype, header: *const Header, symbols: *Symbols) !void {
for (header.functions) |function| {
if (skip(function.conditionals)) continue;
if (function.original_class != null) continue;
if (argsContainsVaList(function.arguments)) continue;
if (try symbols.put(function.name)) {
if (try symbols.put(gpa, function.name)) {
try writer.writeAll("pub const ");
try writeFunctionName(writer, function.name);
try writer.print(" = {s};\n", .{function.name});
@ -461,19 +461,19 @@ fn writeFreeFunctions(writer: anytype, header: *const Header, symbols: *Symbols)
}
const Methods = struct {
types: std.StringArrayHashMap(std.ArrayList([]const u8)),
types: std.array_hash_map.String(std.ArrayList([]const u8)),
fn get(allocator: Allocator, header: *const Header) !Methods {
fn get(gpa: Allocator, header: *const Header) !Methods {
// Initialize an empty method list for each type
var types = std.StringArrayHashMap(std.ArrayList([]const u8)).init(allocator);
errdefer types.deinit();
var types: std.array_hash_map.String(std.ArrayList([]const u8)) = .empty;
errdefer types.deinit(gpa);
errdefer for (types.values()) |*methods| {
methods.deinit(allocator);
methods.deinit(gpa);
};
for (header.structs) |ty| {
var methods: std.ArrayList([]const u8) = .empty;
errdefer methods.deinit(allocator);
try types.put(ty.name, methods);
errdefer methods.deinit(gpa);
try types.put(gpa, ty.name, methods);
}
// Fill in the method lists
@ -483,24 +483,24 @@ const Methods = struct {
if (function.original_class) |class| {
const methods = types.getPtr(class).?;
try methods.append(allocator, function.name);
try methods.append(gpa, function.name);
}
}
return .{ .types = types };
}
fn deinit(self: *Methods, allocator: Allocator) void {
fn deinit(self: *Methods, gpa: Allocator) void {
for (self.types.values()) |*methods| {
methods.deinit(allocator);
methods.deinit(gpa);
}
self.types.deinit();
self.types.deinit(gpa);
self.* = undefined;
}
};
fn writeEnums(
allocator: Allocator,
gpa: Allocator,
writer: anytype,
internal: bool,
header: *const Header,
@ -509,7 +509,7 @@ fn writeEnums(
for (header.enums) |e| {
if (skip(e.conditionals)) continue;
if (try symbols.put(e.name)) {
if (try symbols.put(gpa, e.name)) {
try writer.writeAll("pub const ");
try writeTypeName(writer, e.name);
try writer.writeAll(" = ");
@ -517,7 +517,7 @@ fn writeEnums(
if (e.is_flags_enum) {
try writeFlagsEnum(writer, internal, e);
} else {
try writeNormalEnum(allocator, writer, internal, e);
try writeNormalEnum(gpa, writer, internal, e);
}
}
}
@ -572,13 +572,13 @@ fn writeFlagsEnum(writer: anytype, internal: bool, e: Header.Enum) !void {
}
fn writeNormalEnum(
allocator: Allocator,
gpa: Allocator,
writer: anytype,
internal: bool,
e: Header.Enum,
) !void {
var values = std.AutoArrayHashMap(i64, void).init(allocator);
defer values.deinit();
var values: std.array_hash_map.Auto(i64, void) = .empty;
defer values.deinit(gpa);
try writer.writeAll("enum(");
switch (e.storage_type.declaration) {
@ -602,7 +602,7 @@ fn writeNormalEnum(
// We skip duplicate values, these are sometimes present e.g. in the keys enum which
// contains the mods enum and therefore two "none" options that are identical.
if (values.contains(element.value)) continue;
try values.put(element.value, {});
try values.put(gpa, element.value, {});
// Write the element
try writer.writeAll(" ");
@ -632,6 +632,7 @@ fn writeNormalEnum(
}
fn writeStructs(
gpa: Allocator,
writer: anytype,
header: *const Header,
declarations: *const Declarations,
@ -648,7 +649,7 @@ fn writeStructs(
const decl_kind = declarations.get(ty.name).?;
if (decl_kind == .import) continue;
if (try symbols.put(ty.name)) {
if (try symbols.put(gpa, ty.name)) {
// Write the struct
try writer.writeAll("pub const ");
try writeTypeName(writer, ty.name);