Backlog/build/program.zig

258 lines
7.8 KiB
Zig

pub const AddProgramOptions = struct {
name: []const u8,
opt: bh.Options,
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,
};
pub const Program = struct {
name: []const u8,
opts: bh.Options,
// 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;
}
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 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");
self.finalizeModules();
// 1. create the loader
const exe = bEngine.addExecutable(.{
.name = self.name,
.root_module = bEngine.createModule(.{
.target = self.opts.target,
.optimize = self.opts.optimize,
.root_source_file = bEngine.path("engine/main2.zig"),
}),
});
// link core
const spec = self.makeSpec();
exe.root_module.addImport("gamespec", spec);
exe.root_module.addImport("core", core);
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| {
runArtifact.addArgs(args);
}
const run_exe = b.step(b.fmt("run-{s}", .{self.name}), "runs the program");
run_exe.dependOn(&runArtifact.step);
}
// 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
self.buildSystem.b.installArtifact(exe);
// return the actual library not the loader
return exe;
}
// const b = self.b;
// const exe = self.nw_builder.addExecutable(.{
// .name = opts.name,
// .target = self.target,
// .optimize = self.optimize,
// .root_source_file = self.nw_builder.path("engine/main.zig"),
// });
// b.installArtifact(exe);
// const runArtifact = b.addRunArtifact(exe);
// if (b.args) |args| {
// runArtifact.addArgs(args);
// }
// const run_exe = b.step(self.b.fmt("run-{s}", .{opts.name}), opts.desc);
// run_exe.dependOn(&runArtifact.step);
// // main path = name/main.zig
// const mod = b.addModule(opts.name, .{
// .target = self.target,
// .optimize = self.optimize,
// .root_source_file = opts.root_source_file,
// .imports = opts.imports,
// });
// exe.root_module.addImport("main", mod);
// // todo.. remove this one and see what happens
// exe.root_module.addImport("core", self.nwdep.module("core"));
// // mod.addImport("Backlog", self.nw_mod);
// exe.root_module.addOptions("BacklogOptions", self.options);
// if (self.cookShaders) {
// const cookShadersScript = b.fmt("{s}/tools/scripts/cookShaders.py", .{self.backlogRoot});
// const cookShadersCommand = b.addSystemCommand(&[_][]const u8{"python"});
// cookShadersCommand.addArg(cookShadersScript);
// run_exe.dependOn(&cookShadersCommand.step);
// }
// b.getInstallStep().dependOn(self.nw_builder.getInstallStep());
// // run_exe.dependOn(b.getInstallStep());
// return mod;
};
const std = @import("std");
const bh = @import("bh");
const backlog = @import("../build.zig");