const std = @import("std"); const Module = std.Build.Module; const AddExecutableIcon = struct { obj: *std.Build.Step.Compile, step: std.Build.Step, icon_file: std.Build.LazyPath, resource_file: std.Build.LazyPath, fn init(obj: *std.Build.Step.Compile, icon_file: std.Build.LazyPath) *AddExecutableIcon { const b = obj.step.owner; const self = b.allocator.create(AddExecutableIcon) catch @panic("OOM"); self.obj = obj; self.step = std.Build.Step.init(.{ .id = .custom, .name = "add executable icon", .owner = b, .makeFn = make }); self.icon_file = icon_file; icon_file.addStepDependencies(&self.step); const write_files = b.addWriteFiles(); self.resource_file = write_files.add("resource-file.rc", ""); self.step.dependOn(&write_files.step); self.obj.addWin32ResourceFile(.{ .file = self.resource_file, }); return self; } fn make(step: *std.Build.Step, _: std.Progress.Node) !void { const b = step.owner; const self: *AddExecutableIcon = @fieldParentPtr("step", step); const resource_file = try std.fs.createFileAbsolute(self.resource_file.getPath(b), .{ }); defer resource_file.close(); const relative_icon_path = try std.fs.path.relative( b.allocator, self.resource_file.dirname().getPath(b), self.icon_file.getPath(b) ); std.mem.replaceScalar(u8, relative_icon_path, '\\', '/'); try resource_file.writeAll("IDI_ICON ICON \""); try resource_file.writeAll(relative_icon_path); try resource_file.writeAll("\""); } }; fn buildStbImage(b: *std.Build) *std.Build.Module { const module = b.createModule(.{ .root_source_file = b.path("libs/stb_image/root.zig"), .link_libc = true }); module.addCSourceFile(.{ .file = b.path("libs/stb_image/stb_image.c") }); module.addIncludePath(b.path("libs/stb_image/")); return module; } fn buildCuteAseprite(b: *std.Build, raylib_dep: *std.Build.Dependency) *std.Build.Module { const module = b.createModule(.{ .root_source_file = b.path("libs/cute_aseprite/root.zig"), }); module.addCSourceFile(.{ .file = b.path("libs/cute_aseprite/cute_aseprite.c") }); module.addIncludePath(b.path("libs/cute_aseprite/")); module.linkLibrary(raylib_dep.artifact("raylib")); module.addImport("raylib", raylib_dep.module("raylib")); return module; } pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const known_folders = b.dependency("known-folders", .{}).module("known-folders"); const ini = b.dependency("ini", .{}).module("ini"); const raylib_dep = b.dependency("raylib-zig", .{ .target = target, .optimize = optimize, }); const datetime_dep = b.dependency("zig-datetime", .{ .target = target, .optimize = optimize, }); const profiler_dep = b.dependency("profiler.zig", .{ .target = target, .optimize = optimize, }); const stb_image_lib = buildStbImage(b); const cute_aseprite_lib = buildCuteAseprite(b, raylib_dep); const generate_tool = b.addExecutable(.{ .name = "generate", .root_source_file = b.path("tools/generate.zig"), .target = target, }); const png_to_icon_tool = b.addExecutable(.{ .name = "png-to-icon", .root_source_file = b.path("tools/png-to-icon.zig"), .target = target, }); png_to_icon_tool.root_module.addImport("stb_image", stb_image_lib); const exe = b.addExecutable(.{ .name = "daq-view", .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }); exe.linkLibrary(raylib_dep.artifact("raylib")); exe.root_module.addImport("raylib", raylib_dep.module("raylib")); exe.root_module.addImport("stb_image", stb_image_lib); exe.root_module.addImport("cute_aseprite", cute_aseprite_lib); exe.root_module.addImport("known-folders", known_folders); exe.root_module.addImport("ini", ini); exe.root_module.addImport("datetime", datetime_dep.module("zig-datetime")); // TODO: Add flag to disable in release exe.root_module.addImport("profiler", profiler_dep.module("profiler")); const external_compiler_support_dir = try std.process.getEnvVarOwned(b.allocator, "NIEXTCCOMPILERSUPP"); exe.addSystemIncludePath(.{ .cwd_relative = try std.fs.path.join(b.allocator, &.{ external_compiler_support_dir, "include" }) }); // TODO: Emebed all assets using build.zig // https://github.com/ziglang/zig/issues/14637#issuecomment-1428689051 if (target.result.os.tag == .windows) { exe.subsystem = if (optimize == .Debug) .Console else .Windows; const png_to_icon_step = b.addRunArtifact(png_to_icon_tool); png_to_icon_step.addFileArg(b.path("src/assets/icon.png")); const icon_file = png_to_icon_step.addOutputFileArg("icon.ico"); const add_icon_step = AddExecutableIcon.init(exe, icon_file); exe.step.dependOn(&add_icon_step.step); exe.linkSystemLibrary("Comdlg32"); exe.linkSystemLibrary("ole32"); exe.linkSystemLibrary("uuid"); } b.installArtifact(exe); { // Run genration tool const run_cmd = b.addRunArtifact(generate_tool); if (b.args) |args| { run_cmd.addArgs(args); } const run_step = b.step("generate", "Run sample generation tool"); run_step.dependOn(&run_cmd.step); } { // Run main program 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 program"); run_step.dependOn(&run_cmd.step); } { // Unit tests const unit_tests = b.addTest(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }); const run_unit_tests = b.addRunArtifact(unit_tests); const test_step = b.step("test", "Run unit tests"); test_step.dependOn(&run_unit_tests.step); } }