From 97c8de24b967bcd5b9d6bd51cdf682dde86537ad Mon Sep 17 00:00:00 2001 From: peterino2 Date: Tue, 30 Dec 2025 13:55:35 -0800 Subject: [PATCH] saving --- build.zig | 28 +------ build/engineDeps.zig | 10 +++ build/program.zig | 125 ++++++++++++++++++++++++++-- buildgen/generateModApi.zig | 49 +++++++++++ buildgen/generateProgramSpec.zig | 2 + buildgen/templates/moduleLaunch.zig | 14 ++++ engine/main2.zig | 1 + engine/modulelaunch.zig | 16 ++++ 8 files changed, 211 insertions(+), 34 deletions(-) create mode 100644 buildgen/generateModApi.zig create mode 100644 buildgen/templates/moduleLaunch.zig diff --git a/build.zig b/build.zig index c78d3c8..ec2579d 100644 --- a/build.zig +++ b/build.zig @@ -38,7 +38,7 @@ pub const InitOptions = struct { pub fn init(b: *std.Build, initOptions: InitOptions) BuildSystem { const buildOpts = declareBuildOptions(b); - var opts = bh.Options{ + const opts = bh.Options{ .target = initOptions.target, .optimize = initOptions.optimize, .static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false, @@ -48,8 +48,8 @@ pub fn init(b: *std.Build, initOptions: InitOptions) BuildSystem { if (opts.target.result.os.tag == .linux) { // using a static build for linux... object loading hell is not fun... // i have skill issues in that realm right now - std.debug.print("Important! only supporting static builds for linux", .{}); - opts.static_build = true; + // std.debug.print("Important! only supporting static builds for linux", .{}); + // opts.static_build = true; } const nwdep = b.dependency(initOptions.import_name, .{ @@ -162,28 +162,6 @@ const DynamicDepList: []const struct { dep: []const u8, artifact: []const u8 } = .{ .dep = "ozz", .artifact = "ozz_cpp" }, }; -// all other modules are disabled by default -pub const defaultEnabledModules: []const []const u8 = &.{ - "core", - "assets", - "platform", - "rend", -}; - -pub const moduleOrder: []const []const u8 = &.{ - "core", - "sys", - "assets", - "platform", - "net", - "physics", - "audio", - "rend", - "ui", - "imgui", - "papyrus", -}; - pub fn addProgram( self: *@This(), name: []const u8, diff --git a/build/engineDeps.zig b/build/engineDeps.zig index c506ddd..09e5161 100644 --- a/build/engineDeps.zig +++ b/build/engineDeps.zig @@ -30,6 +30,15 @@ pub fn buildGenerators(b: *std.Build, opts: bh.Options) void { }), }); + const generateModApiExe = b.addExecutable(.{ + .name = "backlog-generate-modapi", + .root_module = b.createModule(.{ + .target = b.graph.host, + .optimize = .Debug, + .root_source_file = b.path("buildgen/generateModApi.zig"), + }), + }); + const generateProgramSpecExe = b.addExecutable(.{ .name = "backlog-generate-spec", .root_module = b.createModule(.{ @@ -71,6 +80,7 @@ pub fn buildGenerators(b: *std.Build, opts: bh.Options) void { b.installArtifact(generateProgramSpecExe); b.installArtifact(generateShaders); b.installArtifact(generateRcExe); + b.installArtifact(generateModApiExe); { const loadDynamicsStub = b.addModule("loadDynamicsStub", .{ diff --git a/build/program.zig b/build/program.zig index 6a50f81..bf3fa88 100644 --- a/build/program.zig +++ b/build/program.zig @@ -4,6 +4,28 @@ pub const AddProgramOptions = struct { root_source_file: std.Build.LazyPath, }; +// all other modules are disabled by default +pub const defaultEnabledModules: []const []const u8 = &.{ + "core", + "assets", + "platform", + "rend", +}; + +pub const moduleOrder: []const []const u8 = &.{ + "core", + "sys", + "assets", + "platform", + "net", + "physics", + "audio", + "rend", + "ui", + "imgui", + "papyrus", +}; + pub const GameModule = struct { name: []const u8, enabled: bool = true, @@ -16,10 +38,37 @@ pub const Program = struct { // root_path: not used yet, we will create a second module that dynamically loads in to that root_path gameModules: std.ArrayListUnmanaged(GameModule) = .{}, + gameModulesMap: std.StringHashMapUnmanaged(bool) = .{}, buildSystem: *backlog.BuildSystem, iconPath: ?std.Build.LazyPath = null, allocator: std.mem.Allocator, // just set this to the build allocator + pub fn setModuleEnabled(self: *@This(), name: []const u8, enabled: bool) void { + const r = self.gameModulesMap.getOrPut(self.allocator, name); + r.value_ptr.* = enabled; + } + + fn finalizeModules(self: *@This()) void { + self.gameModules.clearRetainingCapacity(); + + for (moduleOrder) |mod| { + var enabled: bool = false; + for (defaultEnabledModules) |default| { + if (std.mem.eql(u8, default, mod)) { + enabled = true; + } + } + + if (self.gameModulesMap.get(mod)) |value| { + enabled = value; + } + + if (enabled) { + self.gameModules.append(self.allocator, .{ .name = mod, .enabled = enabled }) catch unreachable; + } + } + } + pub fn setIconPath(self: *@This(), path: []const u8) void { if (self.iconPath != null) { return; @@ -50,17 +99,72 @@ pub const Program = struct { return mod; } + pub fn makeGameApi(self: *@This()) *std.Build.Module { + const b = self.buildSystem.b; + const apigen = self.buildSystem.nwdep.artifact("backlog-generate-modapi"); + const run = b.addRunArtifact(apigen); + const pfile = run.addOutputFileArg(b.fmt("{s}-api.zig", .{self.name})); + + run.addArg(self.name); + + for (self.gameModules.items) |mod| { + if (mod.enabled) { + run.addArg(mod.name); + } + } + + const api = b.createModule(.{ + .target = self.opts.target, + .optimize = self.opts.optimize, + .root_source_file = pfile, + }); + + for (self.gameModules.items) |mod| { + if (mod.enabled) { + api.addImport(mod.name, self.buildSystem.nwdep.module(mod.name)); + } + } + + return api; + } + + pub fn makeGameModule(self: *@This()) *std.Build.Step.Compile { + const b = self.buildSystem.b; + const bEngine = self.buildSystem.bEngine; + + const opts = self.opts; + + // 1. generate the main launch codeset. + const lib = b.addLibrary(.{ + .name = self.name, + .linkage = if (opts.static_build) .static else .dynamic, + .root_module = b.createModule(.{ + .target = opts.target, + .optimize = opts.optimize, + .root_source_file = bEngine.path("engine/modulelaunch.zig"), + }), + }); + + lib.root_module.addImport("core", self.buildSystem.nwdep.module("core")); + + if (opts.static_build) { + // b.installArtifact(lib); + } else { + const installExtern = b.addInstallArtifact(lib, .{ + .dest_dir = .{ .override = .{ .custom = "modules" } }, + }); + b.getInstallStep().dependOn(&installExtern.step); + } + + return lib; + } + + // spec is linked in both the base trampoline pub fn compileInstall(self: *@This()) *std.Build.Step.Compile { const bEngine = self.buildSystem.bEngine; const b = self.buildSystem.b; const core = self.buildSystem.nwdep.module("core"); - - const trampoline = b.createModule(.{ - .target = self.opts.target, - .optimize = self.opts.optimize, - .root_source_file = b.path("test-trampoline.zig"), - }); - trampoline.addImport("core", core); + self.finalizeModules(); // 1. create the loader const exe = bEngine.addExecutable(.{ @@ -68,7 +172,7 @@ pub const Program = struct { .root_module = bEngine.createModule(.{ .target = self.opts.target, .optimize = self.opts.optimize, - .root_source_file = bEngine.path("engine/main2.zig"), // this path sould be generated by generateTrampoline.zig + .root_source_file = bEngine.path("engine/main2.zig"), }), }); @@ -76,9 +180,12 @@ pub const Program = struct { const spec = self.makeSpec(); exe.root_module.addImport("gamespec", spec); exe.root_module.addImport("core", core); - exe.root_module.addImport("trampoline", trampoline); exe.root_module.addOptions("BacklogOptions", self.buildSystem.options); + const gameModule = self.makeGameModule(); + const gameApi = self.makeGameApi(); + gameModule.root_module.addImport("backlog", gameApi); + { const runArtifact = b.addRunArtifact(exe); if (b.args) |args| { diff --git a/buildgen/generateModApi.zig b/buildgen/generateModApi.zig new file mode 100644 index 0000000..1d4093d --- /dev/null +++ b/buildgen/generateModApi.zig @@ -0,0 +1,49 @@ +const std = @import("std"); + +pub fn usage() void { + std.debug.print("generates a loader module which calls the start_modules for all the modules that the game module depends on.\ngenerate-mod-api \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 module_name = args[2]; + const module_list = args[3..]; + + var writer = std.ArrayList(u8){}; + + try writer.print(allocator, "pub const moduleName:[]const u8 = \"{s}\";\n", .{module_name}); + + try writer.print(allocator, "pub const moduleList:[]const []const u8 = &.{{\n", .{}); + for (module_list) |mod| { + try writer.print(allocator, "\"{s}\",\n", .{mod}); + } + try writer.print(allocator, "}};\n", .{}); + + for (module_list) |mod| { + try writer.print(allocator, "pub const {s} = @import(\"{s}\").module;\n", .{ mod, mod }); + } + + try writer.append(allocator, 0); + + 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}", .{writer.items[0 .. writer.items.len - 1]}); + defer ast.deinit(allocator); + const out = try ast.renderAlloc(allocator); + + // Write the content to the file + try file.writeAll(out); +} diff --git a/buildgen/generateProgramSpec.zig b/buildgen/generateProgramSpec.zig index 6db72f2..6b841d7 100644 --- a/buildgen/generateProgramSpec.zig +++ b/buildgen/generateProgramSpec.zig @@ -46,6 +46,8 @@ pub fn main() !void { \\ ); + _ = try writer.print(allocator, "pub const programName = \"{s}\";", .{programName}); + try writer.append(allocator, 0); // Write to specified output file diff --git a/buildgen/templates/moduleLaunch.zig b/buildgen/templates/moduleLaunch.zig new file mode 100644 index 0000000..8140f32 --- /dev/null +++ b/buildgen/templates/moduleLaunch.zig @@ -0,0 +1,14 @@ +pub export fn startup_module(p_allocator: *anyopaque, p_a: ?*anyopaque) bool { + const allocator = core.modulePreamble(p_allocator, p_a) catch return false; + _ = allocator; + core.engine_logs("module started"); + + return true; +} + +pub export fn shutdown_module() void {} + +// const backlog = @import("backlog"); +// const core = backlog.core; + +const core = @import("core").module; diff --git a/engine/main2.zig b/engine/main2.zig index 19da20f..7f10412 100644 --- a/engine/main2.zig +++ b/engine/main2.zig @@ -6,6 +6,7 @@ const panickers = core.panickers; pub const gamespec = @import("gamespec"); pub const options = @import("BacklogOptions"); + pub const std_options = std.Options{ .enable_segfault_handler = true, }; diff --git a/engine/modulelaunch.zig b/engine/modulelaunch.zig index e69de29..245c4cc 100644 --- a/engine/modulelaunch.zig +++ b/engine/modulelaunch.zig @@ -0,0 +1,16 @@ +pub export fn startup_module(p_allocator: *anyopaque, p_a: ?*anyopaque) bool { + const allocator = core.modulePreamble(p_allocator, p_a) catch return false; + _ = allocator; + core.engine_log("module started {s}", .{backlog.moduleName}); + + for (backlog.moduleList) |li| { + core.engine_log("mod: {s}", .{li}); + } + + return true; +} + +pub export fn shutdown_module() void {} + +const backlog = @import("backlog"); +const core = backlog.core;