// legacy code, kept here as reference pub const GameModule = struct { name: []const u8, enabled: bool = true, }; pub fn program(self: *BuildSystem, opts: AddProgramOptions) *Program { const prog = self.b.allocator.create(Program) catch unreachable; prog.* = .{ .allocator = self.b.allocator, .opts = opts, .buildSystem = self, }; for (moduleOrder) |module| { prog.setModuleEnabled(module, false); } for (defaultEnabledModules) |module| { prog.setModuleEnabled(module, true); } return prog; } pub const DynamicModule = struct { name: []const u8, allocator: std.mem.Allocator, buildSystem: *BuildSystem, programName: []const u8, opts: Program.AddProgramOptions, extras: std.ArrayListUnmanaged(Program.GameModule) = .{}, gameModules: std.ArrayListUnmanaged(Program.GameModule) = .{}, library: ?*std.Build.Step.Compile = null, pub fn addExtraModule(self: *@This(), module: []const u8) void { self.extras.append(self.allocator, .{ .name = module, .enabled = true }) catch @panic("out of memory"); } pub fn init(name: []const u8, p: *Program) *@This() { var self: *@This() = p.allocator.create(@This()) catch @panic("out of memory"); self.* = .{ .opts = p.opts, .programName = p.opts.name, .buildSystem = p.buildSystem, .allocator = p.allocator, .name = name, }; for (p.gameModules.items) |module| { self.gameModules.append(self.allocator, module) catch @panic("out of memory"); } for (p.extras.items) |module| { self.extras.append(self.allocator, module) catch @panic("out of memory"); } return self; } pub fn compileInstall(self: *@This()) *std.Build.Step.Compile { if (self.library) |lib| { return lib; } const b = self.buildSystem.b; const static = self.buildSystem.staticBuild; const lib = b.addLibrary(.{ .name = self.name, .linkage = if (static) .static else .dynamic, .root_module = b.createModule(.{ .root_source_file = self.opts.root_source_file, .link_libc = true, .optimize = self.buildSystem.optimize, .target = self.buildSystem.target, }), }); const allocator = self.buildSystem.b.allocator; var modlist = std.ArrayList([]const u8){}; for (self.gameModules.items) |mod| { if (mod.enabled) { modlist.append(allocator, mod.name) catch @panic("out of memory"); } } for (self.extras.items) |extra| { self.buildSystem.addExtraModule(lib.root_module, extra.name); } lib.root_module.addImport("backlog", self.buildSystem.generateApi(self.name, modlist.items, null)); lib.root_module.addOptions("BacklogOptions", self.buildSystem.options); if (!static) { const installExtern = b.addInstallArtifact(lib, .{ .dest_dir = .{ .override = .{ .custom = "modules" } }, }); b.getInstallStep().dependOn(&installExtern.step); } return lib; } }; pub fn generateApi(self: *@This(), programName: []const u8, moduleList: []const []const u8, dynamicModules: ?[]const *DynamicModule,) *std.Build.Module { // std.debug.print("GENERATE API:: {s}\n", .{programName}); for (moduleList) |mod| { _ = mod; // std.debug.print("{s}\n", .{mod}); } // if (self.generatedApis.get(programName)) |m| { return m; } const run = self.b.addRunArtifact(self.apigen); const pfile = self.b.fmt("{s}Api.zig", .{programName}); const output = run.addOutputFileArg(pfile); for (moduleList) |modName| { run.addArg(modName); } const mod = self.b.addModule(pfile, .{ .target = self.target, .optimize = self.optimize, .root_source_file = output, }); for (moduleList) |modName| { mod.addImport(modName, self.nwdep.module(modName)); } const loadStatics = self.generateInstallStaticResources(programName, "content/_shaders") catch unreachable; mod.addImport("staticShaderLoader", loadStatics); // deal with dynamics if (dynamicModules) |dynamics| { const loadDynamics = self.generateLoadDynamics(programName, dynamics) catch @panic("unknown"); mod.addImport("loadDynamics", loadDynamics); } else { mod.addImport("loadDynamics", self.nwdep.module("loadDynamicsStub")); } self.generatedApis.put(self.b.allocator, programName, mod) catch @panic("out of memory"); return mod; } pub fn generateLoadDynamics(self: *@This(), programName: []const u8, dynamics: []const *DynamicModule) !*std.Build.Module { const run = self.b.addRunArtifact(self.loadDynamicsGen); const pfile = self.b.fmt("{s}LoadDynamics.zig", .{programName}); const output = run.addOutputFileArg(pfile); if (self.staticBuild) { run.addArg("static"); } else { run.addArg("dynamic"); } for (dynamics) |dyn| { run.addArg(dyn.name); } const mod = self.b.addModule(pfile, .{ .target = self.target, .optimize = self.optimize, .root_source_file = output, }); mod.addImport("core", self.nwdep.module("core")); for (dynamics) |dyn| { const dynmod = dyn.compileInstall(); mod.addImport(dyn.name, dynmod.root_module); } return mod; }