new build system who dis
This commit is contained in:
parent
8a30c78260
commit
3648615829
|
|
@ -0,0 +1,696 @@
|
||||||
|
// MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=1 -- use this if you're getting that odd crash on mac
|
||||||
|
b: *std.Build,
|
||||||
|
nw_builder: *std.Build,
|
||||||
|
target: std.Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.Mode,
|
||||||
|
nw_mod: *std.Build.Module,
|
||||||
|
spirvReflect: SpirvReflect.SpirvGenerator2,
|
||||||
|
gltf2ozz: ozz.GltfToOzz,
|
||||||
|
options: *std.Build.Step.Options,
|
||||||
|
cookShaders: bool,
|
||||||
|
|
||||||
|
backlogRoot: []const u8,
|
||||||
|
// list of all shaders discovered under
|
||||||
|
// content/_shaders/def
|
||||||
|
reflectShaderPathList: [][]u8 = undefined,
|
||||||
|
|
||||||
|
staticBuild: bool = false,
|
||||||
|
|
||||||
|
nwdep: *std.Build.Dependency,
|
||||||
|
apigen: *std.Build.Step.Compile,
|
||||||
|
shaderEmbedGen: *std.Build.Step.Compile,
|
||||||
|
loadDynamicsGen: *std.Build.Step.Compile,
|
||||||
|
rcGen: *std.Build.Step.Compile,
|
||||||
|
generatedApis: std.StringHashMapUnmanaged(*std.Build.Module) = .{},
|
||||||
|
|
||||||
|
const engineDepList = [_][]const u8{
|
||||||
|
"assets",
|
||||||
|
"audio",
|
||||||
|
"core",
|
||||||
|
"net",
|
||||||
|
"papyrus",
|
||||||
|
"platform",
|
||||||
|
"rend",
|
||||||
|
"ui",
|
||||||
|
"imgui",
|
||||||
|
"physics",
|
||||||
|
"sys",
|
||||||
|
};
|
||||||
|
|
||||||
|
const BuildSystem = @This();
|
||||||
|
const std = @import("std");
|
||||||
|
const Build = std.Build;
|
||||||
|
const LazyPath = Build.LazyPath;
|
||||||
|
|
||||||
|
const SpirvReflect = @import("SpirvReflect");
|
||||||
|
const ozz = @import("ozz");
|
||||||
|
|
||||||
|
pub const InitOptions = struct {
|
||||||
|
import_name: []const u8 = "Backlog",
|
||||||
|
backlogRoot: []const u8 = "./BacklogEngine",
|
||||||
|
staticBuild: bool = false,
|
||||||
|
target: Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn init(b: *std.Build, opts: InitOptions) BuildSystem {
|
||||||
|
var buildOpts = declareBuildOptions(b);
|
||||||
|
|
||||||
|
if (opts.target.result.os.tag == .linux) {
|
||||||
|
// using a static build for linux... object loading hell is not fun
|
||||||
|
std.debug.print("Important! only supporting static builds for linux", .{});
|
||||||
|
buildOpts.static_build = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nwdep = b.dependency(opts.import_name, .{
|
||||||
|
.target = opts.target,
|
||||||
|
.optimize = opts.optimize,
|
||||||
|
.static_build = buildOpts.static_build,
|
||||||
|
});
|
||||||
|
|
||||||
|
var self = BuildSystem{
|
||||||
|
.b = b,
|
||||||
|
.nw_builder = nwdep.builder,
|
||||||
|
.target = opts.target,
|
||||||
|
.optimize = opts.optimize,
|
||||||
|
.nw_mod = nwdep.module("Backlog"),
|
||||||
|
.backlogRoot = opts.backlogRoot,
|
||||||
|
.spirvReflect = SpirvReflect.SpirvGenerator2.init(nwdep.builder, .{}),
|
||||||
|
.options = createGameOptions(b, buildOpts),
|
||||||
|
.gltf2ozz = ozz.GltfToOzz.init(nwdep.builder, .{}),
|
||||||
|
.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,
|
||||||
|
|
||||||
|
.staticBuild = buildOpts.static_build,
|
||||||
|
.nwdep = nwdep,
|
||||||
|
.apigen = nwdep.artifact("backlog-apigen"),
|
||||||
|
.loadDynamicsGen = nwdep.artifact("backlog-generate-loadDynamics"),
|
||||||
|
.rcGen = nwdep.artifact("backlog-generate-rc"),
|
||||||
|
.shaderEmbedGen = nwdep.artifact("backlog-shaderEmbedGen"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const exeList = [2]*std.Build.Step.Compile{ self.gltf2ozz.exe, self.spirvReflect.reflect };
|
||||||
|
const install_tools = b.step("tools", "installs tools needed to generate outputs for the engine");
|
||||||
|
for (exeList) |exe| {
|
||||||
|
const toolsInstall = b.addInstallArtifact(exe, .{
|
||||||
|
.dest_dir = .{ .override = .{ .custom = "tools" } },
|
||||||
|
});
|
||||||
|
|
||||||
|
install_tools.dependOn(&toolsInstall.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const runArtifact = b.addRunArtifact(self.gltf2ozz.exe);
|
||||||
|
if (b.args) |args| {
|
||||||
|
runArtifact.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run_exe = b.step("gltf2ozz", "runs the gltf animation converter.");
|
||||||
|
run_exe.dependOn(&runArtifact.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const runArtifact = b.addRunArtifact(self.spirvReflect.reflect);
|
||||||
|
if (b.args) |args| {
|
||||||
|
runArtifact.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run_exe = b.step("spv-reflect", "runs the gltf animation converter.");
|
||||||
|
run_exe.dependOn(&runArtifact.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addDependencyInstalls(self.b, .ReleaseFast);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const AddProgramOptions = struct {
|
||||||
|
name: []const u8,
|
||||||
|
desc: []const u8,
|
||||||
|
root_source_file: LazyPath,
|
||||||
|
imports: []const Build.Module.Import = &.{},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn addProgram(self: *BuildSystem, opts: AddProgramOptions) *std.Build.Module {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const BuildOptions = struct {
|
||||||
|
mutex_job_queue: bool,
|
||||||
|
static_build: bool,
|
||||||
|
zero_logging: bool,
|
||||||
|
slow_logging: bool,
|
||||||
|
force_mailbox: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn declareBuildOptions(b: *std.Build) BuildOptions {
|
||||||
|
return .{
|
||||||
|
.mutex_job_queue = b.option(bool, "mutex_job_queue", "temporary test, reverts to old mutex based queue behaviour in jobs.zig:JobManager") orelse false,
|
||||||
|
.static_build = b.option(bool, "static_build", "builds the entire game as a single executable") orelse false,
|
||||||
|
.zero_logging = b.option(bool, "zero_logging", "disables all logging, only intended for use on job dispatch testing") orelse false,
|
||||||
|
.slow_logging = b.option(bool, "slow_logging", "Disables buffered logging, takes a hit to performance but gain timing information on logging") orelse false,
|
||||||
|
.force_mailbox = b.option(bool, "force_mailbox", "forces mailbox mode for present mode. unlocks framerate to irresponsible levels") orelse false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn createGameOptions(b: *std.Build, options: BuildOptions) *std.Build.Step.Options {
|
||||||
|
const opts = b.addOptions();
|
||||||
|
|
||||||
|
inline for (@typeInfo(BuildOptions).@"struct".fields) |field| {
|
||||||
|
opts.addOption(bool, field.name, @field(options, field.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// build options for core.zig
|
||||||
|
// opts.addOption(
|
||||||
|
// bool,
|
||||||
|
// "mutex_job_queue",
|
||||||
|
// );
|
||||||
|
|
||||||
|
// opts.addOption(
|
||||||
|
// bool,
|
||||||
|
// "static_build",
|
||||||
|
// );
|
||||||
|
|
||||||
|
// opts.addOption(
|
||||||
|
// bool,
|
||||||
|
// "zero_logging",
|
||||||
|
// );
|
||||||
|
// opts.addOption(
|
||||||
|
// bool,
|
||||||
|
// "slow_logging",
|
||||||
|
// );
|
||||||
|
// opts.addOption(
|
||||||
|
// bool,
|
||||||
|
// "force_mailbox",
|
||||||
|
// );
|
||||||
|
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addExtraModule(self: *BuildSystem, mod: *std.Build.Module, moduleName: []const u8) void {
|
||||||
|
const dep = self.b.dependency(moduleName, .{ .target = self.target, .optimize = self.optimize, .static_build = self.staticBuild });
|
||||||
|
mod.addImport(moduleName, dep.module(moduleName));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addDependencyInstalls(self: *BuildSystem, b: *std.Build, optimize: std.builtin.OptimizeMode) void {
|
||||||
|
//if (self.staticBuild) {
|
||||||
|
//return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
inline for (DynamicDepList) |d| {
|
||||||
|
b.installArtifact(b.dependency(
|
||||||
|
d.dep,
|
||||||
|
.{ .target = self.target, .optimize = optimize, .static_build = self.staticBuild },
|
||||||
|
).artifact(d.artifact));
|
||||||
|
}
|
||||||
|
|
||||||
|
// b.installArtifact(b.dependency(
|
||||||
|
// "sdl3",
|
||||||
|
// .{ .target = self.target, .optimize = optimize, .static_build = self.staticBuild },
|
||||||
|
// ).artifact("SDL3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const DynamicDepList: []const struct { dep: []const u8, artifact: []const u8 } = &.{
|
||||||
|
.{ .dep = "sdl3", .artifact = "SDL3" },
|
||||||
|
.{ .dep = "spng", .artifact = "spng_c" },
|
||||||
|
.{ .dep = "lua", .artifact = "luac" },
|
||||||
|
// .{ .dep = "miniaudio", .artifact = "miniaudio_c" },
|
||||||
|
.{ .dep = "zphysics", .artifact = "joltc" },
|
||||||
|
// .{ .dep = "enet", .artifact = "enet_c" },
|
||||||
|
.{ .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 const DynamicModule = struct {
|
||||||
|
name: []const u8,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
buildSystem: *BuildSystem,
|
||||||
|
programName: []const u8,
|
||||||
|
opts: AddProgramOptions,
|
||||||
|
|
||||||
|
extras: std.ArrayListUnmanaged(GameModule) = .{},
|
||||||
|
gameModules: std.ArrayListUnmanaged(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 = if (static)
|
||||||
|
b.addStaticLibrary(.{
|
||||||
|
.root_source_file = self.opts.root_source_file,
|
||||||
|
.link_libc = true,
|
||||||
|
.optimize = self.buildSystem.optimize,
|
||||||
|
.target = self.buildSystem.target,
|
||||||
|
.name = self.name,
|
||||||
|
})
|
||||||
|
else
|
||||||
|
b.addSharedLibrary(.{
|
||||||
|
.root_source_file = self.opts.root_source_file,
|
||||||
|
.link_libc = true,
|
||||||
|
.optimize = self.buildSystem.optimize,
|
||||||
|
.target = self.buildSystem.target,
|
||||||
|
.name = self.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
var modlist = std.ArrayList([]const u8).init(self.buildSystem.b.allocator);
|
||||||
|
|
||||||
|
for (self.gameModules.items) |mod| {
|
||||||
|
if (mod.enabled) {
|
||||||
|
modlist.append(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) {
|
||||||
|
// generateApi should create static callers for the main program
|
||||||
|
} else {
|
||||||
|
const installExtern = b.addInstallArtifact(lib, .{
|
||||||
|
.dest_dir = .{ .override = .{ .custom = "modules" } },
|
||||||
|
});
|
||||||
|
b.getInstallStep().dependOn(&installExtern.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const GameModule = struct {
|
||||||
|
name: []const u8,
|
||||||
|
enabled: bool = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
var modlist = std.ArrayList([]const u8).init(self.buildSystem.b.allocator);
|
||||||
|
|
||||||
|
for (self.gameModules.items) |mod| {
|
||||||
|
if (mod.enabled) {
|
||||||
|
modlist.append(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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========= standalone build instance =======
|
||||||
|
// maybe the default should be like an engine launcher/project launcher or something
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false;
|
||||||
|
|
||||||
|
const spirvDep = b.dependency("SpirvReflect", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.static_build = static_build,
|
||||||
|
});
|
||||||
|
_ = spirvDep;
|
||||||
|
|
||||||
|
const fwdGeneratorExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-fwd",
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("build/generateFwd.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-apigen",
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("build/generateApi.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateShaders = b.addExecutable(.{
|
||||||
|
.name = "backlog-shaderEmbedGen",
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("build/generateEmbeddedShaders.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateRcExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-rc",
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("build/generateRc.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateLoadDynamicsExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-loadDynamics",
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("build/generateLoadDynamics.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
b.installArtifact(generateLoadDynamicsExe);
|
||||||
|
b.installArtifact(generateExe);
|
||||||
|
b.installArtifact(generateShaders);
|
||||||
|
b.installArtifact(generateRcExe);
|
||||||
|
|
||||||
|
{
|
||||||
|
const loadDynamicsStub = b.addModule("loadDynamicsStub", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = b.path("engine/loadDynamicsStub.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = loadDynamicsStub;
|
||||||
|
|
||||||
|
const mod = b.addModule("Backlog", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = b.path("engine/backlog.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
for (engineDepList) |depName| {
|
||||||
|
const dep = b.dependency(
|
||||||
|
depName,
|
||||||
|
.{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.static_build = static_build,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const run = b.addRunArtifact(fwdGeneratorExe);
|
||||||
|
const output = run.addOutputFileArg(b.fmt("{s}_fwd.zig", .{depName}));
|
||||||
|
|
||||||
|
const modFwd = b.addModule(depName, .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = output,
|
||||||
|
});
|
||||||
|
|
||||||
|
mod.addImport(b.fmt("{s}", .{depName}), modFwd);
|
||||||
|
modFwd.addImport("module", dep.module(depName));
|
||||||
|
|
||||||
|
// mod.addImport(depName, dep.module(depName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// link in large platform support functions... special case.
|
||||||
|
{
|
||||||
|
const dep = b.dependency("sdl3", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.static_build = static_build,
|
||||||
|
});
|
||||||
|
const lib = dep.module("SDL3");
|
||||||
|
|
||||||
|
mod.addImport("sdl3_fwd", 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 generateRc(self: *@This(), programName: []const u8, iconPath: []const u8) !std.Build.LazyPath {
|
||||||
|
const run = self.b.addRunArtifact(self.rcGen);
|
||||||
|
const pfile = self.b.fmt("{s}.rc", .{programName});
|
||||||
|
const output = run.addOutputFileArg(pfile);
|
||||||
|
run.addArg(iconPath);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generateInstallStaticResources(self: *@This(), programName: []const u8, shadersPath: []const u8) !*std.Build.Module {
|
||||||
|
const run = self.b.addRunArtifact(self.shaderEmbedGen);
|
||||||
|
const pfile = self.b.fmt("{s}ShaderGen.zig", .{programName});
|
||||||
|
const output = run.addOutputFileArg(pfile);
|
||||||
|
run.addArg(shadersPath);
|
||||||
|
|
||||||
|
const b = self.b;
|
||||||
|
const mod = self.b.addModule(pfile, .{
|
||||||
|
.target = self.target,
|
||||||
|
.optimize = self.optimize,
|
||||||
|
.root_source_file = output,
|
||||||
|
});
|
||||||
|
mod.addImport("core", self.nwdep.module("core"));
|
||||||
|
|
||||||
|
var dir = try std.fs.cwd().openDir("content/_shaders", .{ .iterate = true });
|
||||||
|
defer dir.close();
|
||||||
|
|
||||||
|
var walker = dir.iterate();
|
||||||
|
while (try walker.next()) |shaderType| {
|
||||||
|
if (shaderType.kind == .directory) {
|
||||||
|
var d2 = try dir.openDir(shaderType.name, .{ .iterate = true });
|
||||||
|
defer d2.close();
|
||||||
|
var w2 = d2.iterate();
|
||||||
|
while (try w2.next()) |shaderName| {
|
||||||
|
const shaderPath = b.fmt("content/_shaders/{s}/{s}", .{ shaderType.name, shaderName.name });
|
||||||
|
mod.addAnonymousImport(shaderName.name, .{
|
||||||
|
.root_source_file = b.path(shaderPath),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
254
build.zig
254
build.zig
|
|
@ -0,0 +1,254 @@
|
||||||
|
// MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=1 -- use this if you're getting that odd crash on mac
|
||||||
|
b: *std.Build,
|
||||||
|
bEngine: *std.Build, // used to resolve executable paths from within the engine's root directory
|
||||||
|
opts: bh.Options,
|
||||||
|
nw_mod: *std.Build.Module,
|
||||||
|
gltf2ozz: ozz.GltfToOzz,
|
||||||
|
options: *std.Build.Step.Options,
|
||||||
|
cookShaders: bool,
|
||||||
|
|
||||||
|
backlogRoot: []const u8,
|
||||||
|
|
||||||
|
// list of all shaders discovered under
|
||||||
|
// content/_shaders/def
|
||||||
|
reflectShaderPathList: [][]u8 = undefined,
|
||||||
|
|
||||||
|
nwdep: *std.Build.Dependency,
|
||||||
|
apigen: *std.Build.Step.Compile,
|
||||||
|
shaderEmbedGen: *std.Build.Step.Compile,
|
||||||
|
loadDynamicsGen: *std.Build.Step.Compile,
|
||||||
|
rcGen: *std.Build.Step.Compile,
|
||||||
|
generatedApis: std.StringHashMapUnmanaged(*std.Build.Module) = .{},
|
||||||
|
|
||||||
|
pub const BuildSystem = @This();
|
||||||
|
const std = @import("std");
|
||||||
|
const Build = std.Build;
|
||||||
|
const LazyPath = Build.LazyPath;
|
||||||
|
|
||||||
|
const ozz = @import("ozz");
|
||||||
|
|
||||||
|
pub const InitOptions = struct {
|
||||||
|
import_name: []const u8 = "Backlog",
|
||||||
|
backlogRoot: []const u8 = "./BacklogEngine",
|
||||||
|
target: std.Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn init(b: *std.Build, initOptions: InitOptions) BuildSystem {
|
||||||
|
const buildOpts = declareBuildOptions(b);
|
||||||
|
|
||||||
|
var opts = bh.Options{
|
||||||
|
.target = initOptions.target,
|
||||||
|
.optimize = initOptions.optimize,
|
||||||
|
.static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false,
|
||||||
|
.tracy = b.option(bool, "tracy", "builds with tracy support") orelse false,
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nwdep = b.dependency(initOptions.import_name, .{
|
||||||
|
.target = opts.target,
|
||||||
|
.optimize = opts.optimize,
|
||||||
|
.static_build = opts.static_build,
|
||||||
|
});
|
||||||
|
|
||||||
|
var self = BuildSystem{
|
||||||
|
.b = b,
|
||||||
|
.bEngine = nwdep.builder,
|
||||||
|
.opts = opts,
|
||||||
|
.nw_mod = nwdep.module("Backlog"),
|
||||||
|
.backlogRoot = initOptions.backlogRoot,
|
||||||
|
.options = createGameOptions(b, buildOpts, opts),
|
||||||
|
.gltf2ozz = ozz.GltfToOzz.init(nwdep.builder, .{}),
|
||||||
|
.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,
|
||||||
|
.apigen = nwdep.artifact("backlog-apigen"),
|
||||||
|
.loadDynamicsGen = nwdep.artifact("backlog-generate-loadDynamics"),
|
||||||
|
.rcGen = nwdep.artifact("backlog-generate-rc"),
|
||||||
|
.shaderEmbedGen = nwdep.artifact("backlog-shaderEmbedGen"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const exeList = [1]*std.Build.Step.Compile{self.gltf2ozz.exe};
|
||||||
|
const install_tools = b.step("tools", "installs tools needed to generate outputs for the engine");
|
||||||
|
for (exeList) |exe| {
|
||||||
|
const toolsInstall = b.addInstallArtifact(exe, .{
|
||||||
|
.dest_dir = .{ .override = .{ .custom = "tools" } },
|
||||||
|
});
|
||||||
|
|
||||||
|
install_tools.dependOn(&toolsInstall.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const runArtifact = b.addRunArtifact(self.gltf2ozz.exe);
|
||||||
|
if (b.args) |args| {
|
||||||
|
runArtifact.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run_exe = b.step("gltf2ozz", "runs the gltf animation converter.");
|
||||||
|
run_exe.dependOn(&runArtifact.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addDependencyInstalls(self.b, .ReleaseFast);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build Options for the engine,
|
||||||
|
// should generally be written as false = default
|
||||||
|
// true = enabling something
|
||||||
|
const BuildOptions = struct {
|
||||||
|
mutex_job_queue: bool,
|
||||||
|
zero_logging: bool,
|
||||||
|
slow_logging: bool,
|
||||||
|
force_mailbox: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn declareBuildOptions(b: *std.Build) BuildOptions {
|
||||||
|
return .{
|
||||||
|
.mutex_job_queue = b.option(bool, "mutex_job_queue", "temporary test, reverts to old mutex based queue behaviour in jobs.zig:JobManager") orelse false,
|
||||||
|
.zero_logging = b.option(bool, "zero_logging", "disables all logging, only intended for use on job dispatch testing") orelse false,
|
||||||
|
.slow_logging = b.option(bool, "slow_logging", "Disables buffered logging, takes a hit to performance but gain timing information on logging") orelse false,
|
||||||
|
.force_mailbox = b.option(bool, "force_mailbox", "forces mailbox mode for present mode. unlocks framerate to irresponsible levels") orelse false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createGameOptions(b: *std.Build, options: BuildOptions, bhopts: bh.Options) *std.Build.Step.Options {
|
||||||
|
const opts = b.addOptions();
|
||||||
|
|
||||||
|
inline for (@typeInfo(BuildOptions).@"struct".fields) |field| {
|
||||||
|
opts.addOption(bool, field.name, @field(options, field.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// forward the options to the build options
|
||||||
|
opts.addOption(bool, "tracy", bhopts.tracy);
|
||||||
|
opts.addOption(bool, "static_build", bhopts.static_build);
|
||||||
|
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addExtraModule(self: *BuildSystem, mod: *std.Build.Module, moduleName: []const u8) void {
|
||||||
|
const dep = self.b.dependency(moduleName, .{ .target = self.opts.target, .optimize = self.opts.optimize, .static_build = self.opts.static_build });
|
||||||
|
mod.addImport(moduleName, dep.module(moduleName));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addDependencyInstalls(self: *BuildSystem, b: *std.Build, optimize: std.builtin.OptimizeMode) void {
|
||||||
|
if (self.opts.static_build) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline for (DynamicDepList) |d| {
|
||||||
|
b.installArtifact(b.dependency(
|
||||||
|
d.dep,
|
||||||
|
.{ .target = self.opts.target, .optimize = optimize, .static_build = self.opts.static_build },
|
||||||
|
).artifact(d.artifact));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DynamicDepList: []const struct { dep: []const u8, artifact: []const u8 } = &.{
|
||||||
|
.{ .dep = "sdl3", .artifact = "SDL3" },
|
||||||
|
.{ .dep = "spng", .artifact = "spng_c" },
|
||||||
|
.{ .dep = "lua", .artifact = "luac" },
|
||||||
|
.{ .dep = "miniaudio", .artifact = "miniaudio_c" },
|
||||||
|
.{ .dep = "zphysics", .artifact = "joltc" },
|
||||||
|
// .{ .dep = "enet", .artifact = "enet_c" },
|
||||||
|
.{ .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,
|
||||||
|
) *Program {
|
||||||
|
const p = self.b.allocator.create(Program) catch unreachable;
|
||||||
|
p.* = .{
|
||||||
|
.name = name,
|
||||||
|
.opts = self.opts,
|
||||||
|
.buildSystem = self,
|
||||||
|
.allocator = self.b.allocator,
|
||||||
|
};
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generateRc(self: *@This(), programName: []const u8, iconPath: []const u8) !std.Build.LazyPath {
|
||||||
|
const run = self.b.addRunArtifact(self.rcGen);
|
||||||
|
const pfile = self.b.fmt("{s}.rc", .{programName});
|
||||||
|
const output = run.addOutputFileArg(pfile);
|
||||||
|
run.addArg(iconPath);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generateInstallStaticResources(self: *@This(), programName: []const u8, shadersPath: []const u8) !*std.Build.Module {
|
||||||
|
const run = self.b.addRunArtifact(self.shaderEmbedGen);
|
||||||
|
const pfile = self.b.fmt("{s}ShaderGen.zig", .{programName});
|
||||||
|
const output = run.addOutputFileArg(pfile);
|
||||||
|
run.addArg(shadersPath);
|
||||||
|
|
||||||
|
const b = self.b;
|
||||||
|
const mod = self.b.addModule(pfile, .{
|
||||||
|
.target = self.opts.target,
|
||||||
|
.optimize = self.opts.optimize,
|
||||||
|
.root_source_file = output,
|
||||||
|
});
|
||||||
|
mod.addImport("core", self.nwdep.module("core"));
|
||||||
|
|
||||||
|
var dir = try std.fs.cwd().openDir("content/_shaders", .{ .iterate = true });
|
||||||
|
defer dir.close();
|
||||||
|
|
||||||
|
var walker = dir.iterate();
|
||||||
|
while (try walker.next()) |shaderType| {
|
||||||
|
if (shaderType.kind == .directory) {
|
||||||
|
var d2 = try dir.openDir(shaderType.name, .{ .iterate = true });
|
||||||
|
defer d2.close();
|
||||||
|
var w2 = d2.iterate();
|
||||||
|
while (try w2.next()) |shaderName| {
|
||||||
|
const shaderPath = b.fmt("content/_shaders/{s}/{s}", .{ shaderType.name, shaderName.name });
|
||||||
|
mod.addAnonymousImport(shaderName.name, .{
|
||||||
|
.root_source_file = b.path(shaderPath),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========= standalone build instance =======
|
||||||
|
// maybe the default should be like an engine launcher/project launcher or something
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const opts = bh.declareOptions(b);
|
||||||
|
engineDeps.buildGenerators(b, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bh = @import("bh");
|
||||||
|
const engineDeps = @import("build/engineDeps.zig");
|
||||||
|
const program = @import("build/program.zig");
|
||||||
|
const Program = program.Program;
|
||||||
|
|
@ -1,28 +1,23 @@
|
||||||
.{
|
.{ .name = .Backlog, .version = "0.0.0", .dependencies = .{
|
||||||
.name = .Backlog,
|
.assets = .{ .path = "engine/assets" },
|
||||||
.version = "0.0.0",
|
.audio = .{ .path = "engine/audio" },
|
||||||
.dependencies = .{
|
.core = .{ .path = "engine/core" },
|
||||||
.assets = .{ .path = "engine/assets" },
|
.net = .{ .path = "engine/net" },
|
||||||
.audio = .{ .path = "engine/audio" },
|
.papyrus = .{ .path = "engine/papyrus" },
|
||||||
.core = .{ .path = "engine/core" },
|
.physics = .{ .path = "engine/physics" },
|
||||||
.net = .{ .path = "engine/net" },
|
.platform = .{ .path = "engine/platform" },
|
||||||
.papyrus = .{ .path = "engine/papyrus" },
|
.imgui = .{ .path = "engine/imgui" },
|
||||||
.physics = .{ .path = "engine/physics" },
|
.ui = .{ .path = "engine/ui" },
|
||||||
.platform = .{ .path = "engine/platform" },
|
.sys = .{ .path = "engine/sys" },
|
||||||
.imgui = .{ .path = "engine/imgui" },
|
.rend = .{ .path = "engine/rend" },
|
||||||
.ui = .{ .path = "engine/ui" },
|
|
||||||
.sys = .{ .path = "engine/sys" },
|
|
||||||
.rend = .{.path = "engine/rend" },
|
|
||||||
|
|
||||||
.ozz = .{ .path = "lib/ozz" },
|
.ozz = .{ .path = "lib/ozz" },
|
||||||
.spng = .{ .path = "lib/spng" },
|
.spng = .{ .path = "lib/spng" },
|
||||||
.zphysics = .{ .path = "lib/zphysics" },
|
.zphysics = .{ .path = "lib/zphysics" },
|
||||||
|
|
||||||
.sdl3 = .{ .path = "lib/sdl3" },
|
.sdl3 = .{ .path = "lib/sdl3" },
|
||||||
.enet = .{ .path = "lib/enet" },
|
.enet = .{ .path = "lib/enet" },
|
||||||
},
|
.bh = .{ .path = "lib/bh" },
|
||||||
.paths = .{
|
}, .paths = .{
|
||||||
"",
|
"",
|
||||||
},
|
}, .fingerprint = 0xcf9bab998abe37e3 }
|
||||||
.fingerprint = 0xcf9bab998abe37e3
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
const engineDepList = [_][]const u8{
|
||||||
|
"assets",
|
||||||
|
"audio",
|
||||||
|
"core",
|
||||||
|
"net",
|
||||||
|
"papyrus",
|
||||||
|
"platform",
|
||||||
|
"rend",
|
||||||
|
"ui",
|
||||||
|
"imgui",
|
||||||
|
"physics",
|
||||||
|
"sys",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn depList() []const []const u8 {
|
||||||
|
return &engineDepList;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buildGenerators(b: *std.Build, opts: bh.Options) void {
|
||||||
|
const target = opts.target;
|
||||||
|
const optimize = opts.optimize;
|
||||||
|
const static_build = opts.static_build;
|
||||||
|
|
||||||
|
const fwdGeneratorExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-fwd",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateFwd.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-apigen",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateApi.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateShaders = b.addExecutable(.{
|
||||||
|
.name = "backlog-shaderEmbedGen",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateEmbeddedShaders.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateRcExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-rc",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateRc.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateLoadDynamicsExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-loadDynamics",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateLoadDynamics.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
b.installArtifact(fwdGeneratorExe);
|
||||||
|
b.installArtifact(generateLoadDynamicsExe);
|
||||||
|
b.installArtifact(generateExe);
|
||||||
|
b.installArtifact(generateShaders);
|
||||||
|
b.installArtifact(generateRcExe);
|
||||||
|
|
||||||
|
{
|
||||||
|
const loadDynamicsStub = b.addModule("loadDynamicsStub", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = b.path("engine/loadDynamicsStub.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = loadDynamicsStub;
|
||||||
|
|
||||||
|
const mod = b.addModule("Backlog", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = b.path("engine/backlog.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
for (depList()) |depName| {
|
||||||
|
const dep = b.dependency(
|
||||||
|
depName,
|
||||||
|
.{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.static_build = static_build,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const run = b.addRunArtifact(fwdGeneratorExe);
|
||||||
|
const output = run.addOutputFileArg(b.fmt("{s}_fwd.zig", .{depName}));
|
||||||
|
|
||||||
|
const modFwd = b.addModule(depName, .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = output,
|
||||||
|
});
|
||||||
|
|
||||||
|
mod.addImport(b.fmt("{s}", .{depName}), modFwd);
|
||||||
|
modFwd.addImport("module", dep.module(depName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// link in large platform support functions... special case.
|
||||||
|
{
|
||||||
|
const dep = b.dependency("sdl3", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.static_build = static_build,
|
||||||
|
});
|
||||||
|
const lib = dep.module("SDL3");
|
||||||
|
|
||||||
|
mod.addImport("sdl3_fwd", lib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const bh = @import("bh");
|
||||||
|
|
@ -0,0 +1,182 @@
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
pub const AddProgramOptions = struct {
|
||||||
|
name: []const u8,
|
||||||
|
opt: bh.Options,
|
||||||
|
root_source_file: std.Build.LazyPath,
|
||||||
|
};
|
||||||
|
|
||||||
|
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) = .{},
|
||||||
|
buildSystem: *backlog.BuildSystem,
|
||||||
|
iconPath: ?std.Build.LazyPath = null,
|
||||||
|
allocator: std.mem.Allocator, // just set this to the build allocator
|
||||||
|
|
||||||
|
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 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);
|
||||||
|
|
||||||
|
// 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"), // this path sould be generated by generateTrampoline.zig
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
exe.root_module.addImport("core", core);
|
||||||
|
exe.root_module.addImport("trampoline", trampoline);
|
||||||
|
exe.root_module.addOptions("BacklogOptions", self.buildSystem.options);
|
||||||
|
|
||||||
|
// link core
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const Build = std.Build;
|
||||||
|
const LazyPath = Build.LazyPath;
|
||||||
125
build/utils.zig
125
build/utils.zig
|
|
@ -1,19 +1,114 @@
|
||||||
pub fn loadFileAlloc(filename: []const u8, comptime alignment: usize, allocator: std.mem.Allocator) ![]u8 {
|
|
||||||
var file = try std.fs.cwd().openFile(filename, .{});
|
pub fn buildGenerators(b: *std.Build, opts: bh.Options) void {
|
||||||
defer file.close();
|
const target = opts.target;
|
||||||
const filesize = (try file.stat()).size + 1; // add null byte
|
const optimize = opts.optimize;
|
||||||
const buffer: []align(alignment) u8 = try allocator.alignedAlloc(u8, alignment, filesize);
|
const static_build = opts.static_build;
|
||||||
errdefer allocator.free(buffer);
|
|
||||||
try file.reader().readNoEof(buffer[0 .. buffer.len - 1]);
|
const fwdGeneratorExe = b.addExecutable(.{
|
||||||
buffer[buffer.len - 1] = 0;
|
.name = "backlog-generate-fwd",
|
||||||
return buffer;
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateFwd.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-apigen",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateApi.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateShaders = b.addExecutable(.{
|
||||||
|
.name = "backlog-shaderEmbedGen",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateEmbeddedShaders.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateRcExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-rc",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateRc.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const generateLoadDynamicsExe = b.addExecutable(.{
|
||||||
|
.name = "backlog-generate-loadDynamics",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.target = b.graph.host,
|
||||||
|
.optimize = .Debug,
|
||||||
|
.root_source_file = b.path("buildgen/generateLoadDynamics.zig"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
b.installArtifact(fwdGeneratorExe);
|
||||||
|
b.installArtifact(generateLoadDynamicsExe);
|
||||||
|
b.installArtifact(generateExe);
|
||||||
|
b.installArtifact(generateShaders);
|
||||||
|
b.installArtifact(generateRcExe);
|
||||||
|
|
||||||
|
{
|
||||||
|
const loadDynamicsStub = b.addModule("loadDynamicsStub", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = b.path("engine/loadDynamicsStub.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = loadDynamicsStub;
|
||||||
|
|
||||||
|
const mod = b.addModule("Backlog", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = b.path("engine/backlog.zig"),
|
||||||
|
});
|
||||||
|
|
||||||
|
for (depList()) |depName| {
|
||||||
|
const dep = b.dependency(
|
||||||
|
depName,
|
||||||
|
.{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.static_build = static_build,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const run = b.addRunArtifact(fwdGeneratorExe);
|
||||||
|
const output = run.addOutputFileArg(b.fmt("{s}_fwd.zig", .{depName}));
|
||||||
|
|
||||||
|
const modFwd = b.addModule(depName, .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = output,
|
||||||
|
});
|
||||||
|
|
||||||
|
mod.addImport(b.fmt("{s}", .{depName}), modFwd);
|
||||||
|
modFwd.addImport("module", dep.module(depName));
|
||||||
|
|
||||||
|
// mod.addImport(depName, dep.module(depName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// link in large platform support functions... special case.
|
||||||
|
{
|
||||||
|
const dep = b.dependency("sdl3", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.static_build = static_build,
|
||||||
|
});
|
||||||
|
const lib = dep.module("SDL3");
|
||||||
|
|
||||||
|
mod.addImport("sdl3_fwd", lib);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checkAndFormatAst(allocator: std.mem.Allocator, input: []const u8) ![]u8 {
|
|
||||||
var ast = try std.zig.Ast.parse(allocator, @as([:0]const u8, @ptrCast(input)), .zig);
|
|
||||||
const out = try ast.render(allocator);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const bh = @import("bh");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
pub fn loadFileAlloc(filename: []const u8, comptime alignment: usize, allocator: std.mem.Allocator) ![]u8 {
|
||||||
|
var file = try std.fs.cwd().openFile(filename, .{});
|
||||||
|
defer file.close();
|
||||||
|
const filesize = (try file.stat()).size + 1; // add null byte
|
||||||
|
const buffer: []align(alignment) u8 = try allocator.alignedAlloc(u8, alignment, filesize);
|
||||||
|
errdefer allocator.free(buffer);
|
||||||
|
try file.reader().readNoEof(buffer[0 .. buffer.len - 1]);
|
||||||
|
buffer[buffer.len - 1] = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn checkAndFormatAst(allocator: std.mem.Allocator, input: []const u8) ![]u8 {
|
||||||
|
var ast = try std.zig.Ast.parse(allocator, @as([:0]const u8, @ptrCast(input)), .zig);
|
||||||
|
const out = try ast.render(allocator);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
@ -2,7 +2,9 @@ const std = @import("std");
|
||||||
const core = @import("core").module;
|
const core = @import("core").module;
|
||||||
const panickers = core.panickers;
|
const panickers = core.panickers;
|
||||||
|
|
||||||
const realMain = @import("main");
|
// const realMain = @import("main");
|
||||||
|
|
||||||
|
pub const trampoline = @import("trampoline");
|
||||||
|
|
||||||
pub const options = @import("BacklogOptions");
|
pub const options = @import("BacklogOptions");
|
||||||
|
|
||||||
|
|
@ -46,6 +48,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)});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trampoline.launch();
|
||||||
// panickers.attachSegfaultHandler();
|
// panickers.attachSegfaultHandler();
|
||||||
try realMain.main();
|
// try realMain.main();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,32 +5,15 @@ pub fn build(b: *std.Build) void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
var blbuild = Backlog.init(b, .{
|
var buildSystem = Backlog.init(b, .{
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.backlogRoot = "../",
|
.backlogRoot = "../",
|
||||||
});
|
});
|
||||||
|
|
||||||
const sampleGame = blbuild.program(.{
|
const coreTest = buildSystem.addProgram(
|
||||||
.name = "sampleGame",
|
"coreTest",
|
||||||
.desc = "sample game with hot reloading",
|
);
|
||||||
.root_source_file = b.path("sampleGame/sampleGame.zig"),
|
coreTest.setIconPath("projects/content/icons/icon.ico");
|
||||||
});
|
_ = coreTest.compileInstall();
|
||||||
|
|
||||||
sampleGame.setModuleEnabled("imgui", true);
|
|
||||||
sampleGame.setModuleEnabled("audio", true);
|
|
||||||
sampleGame.setModuleEnabled("physics", true);
|
|
||||||
sampleGame.setModuleEnabled("ui", true);
|
|
||||||
sampleGame.setModuleEnabled("sys", true);
|
|
||||||
sampleGame.setModuleEnabled("net", true);
|
|
||||||
|
|
||||||
sampleGame.addExtraModule("gameExtras");
|
|
||||||
sampleGame.addExtraModule("videoplayer");
|
|
||||||
sampleGame.addExtraModule("doomplayer");
|
|
||||||
sampleGame.addExtraModule("bsp");
|
|
||||||
|
|
||||||
sampleGame.setIconPath("icons/icon.ico");
|
|
||||||
|
|
||||||
const sampleGameExe = sampleGame.compileInstall();
|
|
||||||
_ = sampleGameExe;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
// This is a trampoline file, it only depends on core.
|
||||||
|
// Then calls LoadModule on the target module
|
||||||
|
|
||||||
|
const core = @import("core").module;
|
||||||
|
|
||||||
|
pub fn launch() void {
|
||||||
|
core.engine_log("This is where my modules would be loaded!", .{});
|
||||||
|
}
|
||||||
8
todo.txt
8
todo.txt
|
|
@ -1,5 +1,7 @@
|
||||||
how the fuck do i do this
|
I think before i can do anything else
|
||||||
|
|
||||||
1. change it so that the core executable only links core
|
I need to clean up build.zig
|
||||||
|
|
||||||
actual issues we need to fix.
|
engineDepList should be discovered from the filesystem
|
||||||
|
|
||||||
|
many functions should be moved into build/ scripts
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue