pub const AddProgramOptions = struct { name: []const u8, desc: []const u8, root_source_file: LazyPath, imports: []const Build.Module.Import = &.{}, }; pub const Program = struct { allocator: std.mem.Allocator, opts: AddProgramOptions, gameModules: std.ArrayListUnmanaged(GameModule) = .{}, extras: std.ArrayListUnmanaged(GameModule) = .{}, dynamicModules: std.ArrayListUnmanaged(*DynamicModule) = .{}, buildSystem: *BuildSystem, iconPath: ?std.Build.LazyPath = null, pub fn setIconPath(self: *@This(), path: []const u8) void { if (self.iconPath != null) { return; } self.iconPath = self.buildSystem.generateRc(self.opts.name, path) catch return; } pub fn setModuleEnabled(self: *@This(), module: []const u8, enable: bool) void { for (self.gameModules.items) |*m| { if (std.mem.eql(u8, m.name, module)) { m.enabled = enable; return; } } // module not found, add it here. self.gameModules.append(self.allocator, .{ .name = module, .enabled = enable }) catch @panic("out of memory"); } 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 addDynamicModule(self: *@This(), module: []const u8, root_source_file: std.Build.LazyPath) *DynamicModule { const dynamicModule = DynamicModule.init(module, self); dynamicModule.opts.root_source_file = root_source_file; self.dynamicModules.append(self.allocator, dynamicModule) catch @panic("out of memory"); return dynamicModule; } pub fn compileInstall(self: *@This()) *std.Build.Module { const exe = self.buildSystem.addProgram(self.opts); 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(exe, extra.name); } exe.addImport("backlog", self.buildSystem.generateApi(self.opts.name, modlist.items, self.dynamicModules.items)); if (self.buildSystem.target.result.os.tag == .windows) { if (self.iconPath) |ip| { exe.addWin32ResourceFile(.{ .file = ip, .flags = &.{}, }); } } return exe; } }; const std = @import("std"); const Build = std.Build; const LazyPath = Build.LazyPath;