const std = @import("std"); const ShaderStage = enum { fragment, vertex }; pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const sideros = b.createModule(.{ .root_source_file = b.path("src/sideros.zig"), .target = target, .optimize = optimize, }); const mods = b.createModule(.{ .root_source_file = b.path("src/mods/mods.zig"), .target = target, .optimize = optimize, }); mods.addImport("sideros", sideros); const ecs = b.createModule(.{ .root_source_file = b.path("src/ecs/ecs.zig"), .target = target, .optimize = optimize, }); ecs.addImport("sideros", sideros); const renderer = b.createModule(.{ .root_source_file = b.path("src/renderer/Renderer.zig"), .target = target, .optimize = optimize, .link_libc = true, }); renderer.addCSourceFile(.{ .file = b.path("ext/stb_image.c") }); renderer.addImport("sideros", sideros); renderer.addImport("ecs", ecs); ecs.addImport("renderer", renderer); compileAllShaders(b, renderer); sideros.addImport("mods", mods); sideros.addImport("ecs", ecs); sideros.addImport("renderer", renderer); const exe = b.addExecutable(.{ .name = "sideros", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }), }); exe.root_module.addImport("sideros", sideros); sideros.addIncludePath(b.path("ext")); exe.linkSystemLibrary("vulkan"); exe.linkLibC(); const options = b.addOptions(); if (target.result.os.tag == .linux) { const wayland = b.option(bool, "wayland", "Use Wayland to create the main window") orelse false; if (wayland) { exe.linkSystemLibrary("wayland-client"); exe.root_module.addCSourceFile(.{ .file = b.path("ext/xdg-shell.c") }); } else { exe.linkSystemLibrary("xcb"); exe.linkSystemLibrary("xcb-icccm"); } options.addOption(bool, "wayland", wayland); } sideros.addOptions("config", options); b.installArtifact(exe); const root_lib = b.addLibrary(.{ .root_module = sideros, .name = "sideros", }); const install_docs = b.addInstallDirectory(.{ .source_dir = root_lib.getEmittedDocs(), .install_dir = .prefix, .install_subdir = "docs/sideros", }); const docs_step = b.step("docs", "Generate documentation"); docs_step.dependOn(&install_docs.step); const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| { run_cmd.addArgs(args); } const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); const exe_unit_tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }), }); const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); const test_step = b.step("test", "Run unit tests"); test_step.dependOn(&run_exe_unit_tests.step); } fn compileAllShaders(b: *std.Build, module: *std.Build.Module) void { const shaders_dir = if (@hasDecl(@TypeOf(b.build_root.handle), "openIterableDir")) b.build_root.handle.openIterableDir("assets/shaders", .{}) catch @panic("Failed to open shaders directory") else b.build_root.handle.openDir("assets/shaders", .{ .iterate = true }) catch @panic("Failed to open shaders directory"); var file_it = shaders_dir.iterate(); while (file_it.next() catch @panic("Failed to iterate shader directory")) |entry| { if (entry.kind == .file) { const ext = std.fs.path.extension(entry.name); const basename = std.fs.path.basename(entry.name); const name = basename[0 .. basename.len - ext.len]; if (std.mem.eql(u8, ext, ".vert")) { addShader(b, module, name, .vertex); } else if (std.mem.eql(u8, ext, ".frag")) { addShader(b, module, name, .fragment); } } } } fn addShader(b: *std.Build, module: *std.Build.Module, name: []const u8, stage: ShaderStage) void { const mod_name = std.fmt.allocPrint(b.allocator, "{s}_{s}", .{ name, if (stage == .vertex) "vert" else "frag" }) catch @panic(""); const source = std.fmt.allocPrint(b.allocator, "assets/shaders/{s}.{s}", .{ name, if (stage == .vertex) "vert" else "frag" }) catch @panic(""); const outpath = std.fmt.allocPrint(b.allocator, "assets/shaders/{s}_{s}.spv", .{ name, if (stage == .vertex) "vert" else "frag" }) catch @panic(""); const shader_compilation = b.addSystemCommand(&.{"glslc"}); shader_compilation.addArg("-o"); const output = shader_compilation.addOutputFileArg(outpath); shader_compilation.addFileArg(b.path(source)); module.addAnonymousImport(mod_name, .{ .root_source_file = output }); }