It worked ! Here is a sketch of my solution:
// VmConfig.zig
/// Log the stack from the current callFrame.
logStack: bool,
/// Log the callStack.
logCallStack: bool,
/// Log each instructions.
logInstructions: bool,
/// Log each garbage collection cycle.
logGCCycles: bool,
/// Log all allocations made by the Vm.
logAllocations: bool,
/// Each call to the alloc functions triggers a GC Cycle.
stressGC: bool,
/// Jump offsets are encoded using 1 byte instead of 2.
smallJumps: bool,
/// Embed arrays of known length within allocations of types.
vlaTypes: bool,
/// Embed hash inside string struct.
storeHash: bool,
/// Cache strings to prevent duplicates.
internString: bool,
// build.zig
fn optionFrom(b: *std.Build, comptime T: type, values: *const T) anyerror!*std.Build.Step.Options {
const options = b.addOptions();
inline for (@typeInfo(T).@"struct".fields) |field| {
options.addOption(@FieldType(T, field.name), field.name, @field(values, field.name));
}
var writer = std.Io.Writer.Allocating.init(b.allocator);
defer writer.deinit();
try std.zon.stringify.serialize(values, .{ .whitespace = false }, &writer.writer);
try writer.writer.writeByte(0);
const formatted: []const u8 = writer.written();
const res = formatted[0 .. formatted.len - 1 :0];
options.addOption([:0]const u8, "formatted", res);
return options;
}
// main.zig
const RunData = struct {
numCycles: usize,
maxAllocated: usize,
maxCollected: usize,
maxGrayStackSize: usize,
file: []const u8,
config: VmConfig,
};
const config = try std.zon.parse.fromSlice(VmConfig, allocator, Vm.config.formatted, null, .{
.free_on_error = true,
.ignore_unknown_fields = false,
});
const data = RunData{
.numCycles = vm.gc.numCycles,
.maxAllocated = vm.gc.maxAllocated,
.maxCollected = vm.gc.maxCollected,
.maxGrayStackSize = vm.gc.maxGrayStackSize,
.file = path,
.config = config,
};
try std.zon.stringify.serialize(data, .{}, results.writer().?);