spec generation complete

This commit is contained in:
Peter Li 2025-12-27 22:51:40 -08:00
parent b248573930
commit 75a9ae1b39
10 changed files with 138 additions and 32 deletions

View File

@ -14,10 +14,11 @@ backlogRoot: []const u8,
reflectShaderPathList: [][]u8 = undefined, reflectShaderPathList: [][]u8 = undefined,
nwdep: *std.Build.Dependency, nwdep: *std.Build.Dependency,
apigen: *std.Build.Step.Compile, // apigen: *std.Build.Step.Compile,
shaderEmbedGen: *std.Build.Step.Compile, shaderEmbedGen: *std.Build.Step.Compile,
loadDynamicsGen: *std.Build.Step.Compile, loadDynamicsGen: *std.Build.Step.Compile,
rcGen: *std.Build.Step.Compile, rcGen: *std.Build.Step.Compile,
specGen: *std.Build.Step.Compile,
generatedApis: std.StringHashMapUnmanaged(*std.Build.Module) = .{}, generatedApis: std.StringHashMapUnmanaged(*std.Build.Module) = .{},
pub const BuildSystem = @This(); pub const BuildSystem = @This();
@ -68,8 +69,9 @@ pub fn init(b: *std.Build, initOptions: InitOptions) BuildSystem {
.cookShaders = b.option(bool, "cookShaders", "generates shaders and updates .json files before running the build. (needs to be done whenever shaders are updated, this just runs tools/scripts/cook-shaders.py)") orelse false, .cookShaders = b.option(bool, "cookShaders", "generates shaders and updates .json files before running the build. (needs to be done whenever shaders are updated, this just runs tools/scripts/cook-shaders.py)") orelse false,
.nwdep = nwdep, .nwdep = nwdep,
.apigen = nwdep.artifact("backlog-apigen"), // .apigen = nwdep.artifact("backlog-apigen"),
.loadDynamicsGen = nwdep.artifact("backlog-generate-loadDynamics"), .loadDynamicsGen = nwdep.artifact("backlog-generate-loadDynamics"),
.specGen = nwdep.artifact("backlog-generate-spec"),
.rcGen = nwdep.artifact("backlog-generate-rc"), .rcGen = nwdep.artifact("backlog-generate-rc"),
.shaderEmbedGen = nwdep.artifact("backlog-shaderEmbedGen"), .shaderEmbedGen = nwdep.artifact("backlog-shaderEmbedGen"),
}; };

View File

@ -30,12 +30,12 @@ pub fn buildGenerators(b: *std.Build, opts: bh.Options) void {
}), }),
}); });
const generateExe = b.addExecutable(.{ const generateProgramSpecExe = b.addExecutable(.{
.name = "backlog-apigen", .name = "backlog-generate-spec",
.root_module = b.createModule(.{ .root_module = b.createModule(.{
.target = b.graph.host, .target = b.graph.host,
.optimize = .Debug, .optimize = .Debug,
.root_source_file = b.path("buildgen/generateApi.zig"), .root_source_file = b.path("buildgen/generateProgramSpec.zig"),
}), }),
}); });
@ -68,7 +68,7 @@ pub fn buildGenerators(b: *std.Build, opts: bh.Options) void {
b.installArtifact(fwdGeneratorExe); b.installArtifact(fwdGeneratorExe);
b.installArtifact(generateLoadDynamicsExe); b.installArtifact(generateLoadDynamicsExe);
b.installArtifact(generateExe); b.installArtifact(generateProgramSpecExe);
b.installArtifact(generateShaders); b.installArtifact(generateShaders);
b.installArtifact(generateRcExe); b.installArtifact(generateRcExe);

View File

@ -28,6 +28,28 @@ pub const Program = struct {
self.iconPath = self.buildSystem.generateRc(self.name, path) catch return; self.iconPath = self.buildSystem.generateRc(self.name, path) catch return;
} }
pub fn makeSpec(self: *@This()) *std.Build.Module {
const b = self.buildSystem.b;
const run = b.addRunArtifact(self.buildSystem.specGen);
const pfile = run.addOutputFileArg(b.fmt("{s}-spec.zig", .{self.name}));
run.addArg(self.name);
for (self.gameModules.items) |mod| {
if (mod.enabled)
run.addArg(mod.name);
}
const mod = b.createModule(.{
.target = self.opts.target,
.optimize = self.opts.optimize,
.root_source_file = pfile,
});
const core = self.buildSystem.nwdep.module("core");
mod.addImport("core", core);
return mod;
}
pub fn compileInstall(self: *@This()) *std.Build.Step.Compile { pub fn compileInstall(self: *@This()) *std.Build.Step.Compile {
const bEngine = self.buildSystem.bEngine; const bEngine = self.buildSystem.bEngine;
const b = self.buildSystem.b; const b = self.buildSystem.b;
@ -50,6 +72,9 @@ pub const Program = struct {
}), }),
}); });
// link core
const spec = self.makeSpec();
exe.root_module.addImport("gamespec", spec);
exe.root_module.addImport("core", core); exe.root_module.addImport("core", core);
exe.root_module.addImport("trampoline", trampoline); exe.root_module.addImport("trampoline", trampoline);
exe.root_module.addOptions("BacklogOptions", self.buildSystem.options); exe.root_module.addOptions("BacklogOptions", self.buildSystem.options);
@ -64,8 +89,6 @@ pub const Program = struct {
run_exe.dependOn(&runArtifact.step); run_exe.dependOn(&runArtifact.step);
} }
// link core
// 2. create the actual library that the loader will try to load // 2. create the actual library that the loader will try to load
// 3. set up linking, if static then we will link against the loader // 3. set up linking, if static then we will link against the loader

View File

@ -0,0 +1,64 @@
const std = @import("std");
pub fn usage() void {
std.debug.print("generate-program-spec <output file name> <spec_name> <module list>\n", .{});
}
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
// Get output filename from build system
const args = try std.process.argsAlloc(allocator);
if (args.len < 3) {
usage();
@panic("Missing output filename\n");
}
const out_path = args[1];
const programName = args[2];
const modules = args[3..];
// Generate Zig code content
var writer = std.ArrayList(u8){};
_ = try writer.appendSlice(allocator,
\\const core = @import("core").module;
\\
\\ const std = @import("std");
\\ pub fn getSpec() !*core.SpecVariantMap {
\\ const spec = try std.heap.smp_allocator.create(core.SpecVariantMap);
\\ spec.* = try core.createSpecVariant(.{
\\ .useGPA = true,
);
try writer.print(allocator, ".name = \"{s}\",\n", .{programName});
for (modules) |mod| {
try writer.print(allocator, ".{s} = true,\n", .{mod});
}
_ = try writer.appendSlice(allocator,
\\ }, std.heap.smp_allocator);
\\
\\ return spec;
\\ }
\\
);
try writer.append(allocator, 0);
// Write to specified output file
// Open or create the file for writing (overwrites if it exists)
const file = try std.fs.cwd().createFile(out_path, .{});
defer file.close();
var ast = try std.zig.Ast.parse(allocator, @as([:0]const u8, @ptrCast(writer.items[0 .. writer.items.len - 1])), .zig);
// std.debug.print("output=\n{s}", .{content.items[0 .. content.items.len - 1]});
defer ast.deinit(allocator);
const out = try ast.renderAlloc(allocator);
// Write the content to the file
try file.writeAll(out);
}

View File

@ -0,0 +1,11 @@
// templated file
//
// should still be a formattable zig file
// even if it is not compile-able
//
// definitions marked with // TEMPLATE_DEFINITION
// are removed during the templating step
const programName = "__program_name"; // TEMPLATE_DEFINITION
export fn loadModule() void {}

View File

@ -0,0 +1,26 @@
// templated file
//
// should still be a formattable zig file
// even if it is not compile-able
//
// definitions marked with // TEMPLATE_DEFINITION
// are removed during the templating step
const core = @import("core");
const programName = "__program_name"; // TEMPLATE_DEFINITION
pub export fn startup_module(p_allocator: *anyopaque, p_a: ?*anyopaque) bool {
const allocator = core.modulePreamble(p_allocator, p_a) catch return false;
_ = allocator;
// imgui.setupFromModule();
// platform.setupFromModule();
// sys.setupFromModule();
// rend.setupFromModule();
// backlog.physics.setupFromModule();
core.engine_logs("creating externgame");
// start_module(core.startup_getArgs(p_a.?)) catch return false;
return true;
}

View File

View File

@ -4,9 +4,7 @@ const panickers = core.panickers;
// const realMain = @import("main"); // const realMain = @import("main");
// pub const gametree = @import("gametree"); pub const gamespec = @import("gamespec");
pub const trampoline = @import("trampoline");
pub const options = @import("BacklogOptions"); pub const options = @import("BacklogOptions");
pub const std_options = std.Options{ pub const std_options = std.Options{
.enable_segfault_handler = true, .enable_segfault_handler = true,
@ -40,21 +38,6 @@ fn fileExists(path: []const u8) bool {
return true; return true;
} }
// this should be provided by gametree,
pub fn getSpec(comptime name: []const u8) !*core.SpecVariantMap {
const spec = try std.heap.smp_allocator.create(core.SpecVariantMap);
spec.* = try core.createSpecVariant(.{
.useGPA = true,
.name = name,
// placeholder module list.
.core = true,
.platform = true,
.assets = true,
}, std.heap.smp_allocator);
return spec;
}
pub fn run() !void { pub fn run() !void {
core.engine_logs("calling gEngine.run"); core.engine_logs("calling gEngine.run");
@ -144,7 +127,7 @@ pub fn main() !void {
core.engine_log("Working Dir set: {s}", .{try std.fs.cwd().realpath(".", &BUFFER)}); core.engine_log("Working Dir set: {s}", .{try std.fs.cwd().realpath(".", &BUFFER)});
} }
const spec = try getSpec("sampleGame"); const spec = try gamespec.getSpec();
_ = startEngine(spec); _ = startEngine(spec);
// panickers.attachSegfaultHandler(); // panickers.attachSegfaultHandler();

View File

@ -1,7 +1,4 @@
What is thisthis 1. create generate-launcher.zig
this is going to be an exercise in craftsmanship 2. create generate-landing.zig
1. start with a simple main program that starts the core's loop.