205 lines
6.3 KiB
Zig
205 lines
6.3 KiB
Zig
const std = @import("std");
|
|
|
|
pub fn build(b: *std.Build) !void {
|
|
const target = b.standardTargetOptions(.{});
|
|
const optimize = b.standardOptimizeOption(.{});
|
|
|
|
const is_wasm = target.result.cpu.arch.isWasm();
|
|
const is_debug = (optimize == .Debug);
|
|
|
|
const has_tracy = b.option(bool, "tracy", "Tracy integration") orelse is_debug;
|
|
const has_imgui = b.option(bool, "imgui", "ImGui integration") orelse is_debug;
|
|
|
|
const exe_mod = b.createModule(.{
|
|
.root_source_file = b.path("src/main.zig"),
|
|
});
|
|
|
|
const build_options = b.addOptions();
|
|
build_options.addOption(bool, "has_imgui", has_imgui);
|
|
exe_mod.addOptions("build_options", build_options);
|
|
|
|
const dep_sokol = b.dependency("sokol", .{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
.with_sokol_imgui = has_imgui
|
|
});
|
|
exe_mod.linkLibrary(dep_sokol.artifact("sokol_clib"));
|
|
exe_mod.addImport("sokol", dep_sokol.module("sokol"));
|
|
|
|
if (has_imgui) {
|
|
if (b.lazyDependency("cimgui", .{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
})) |dep_cimgui| {
|
|
const cimgui = b.lazyImport(@This(), "cimgui").?;
|
|
const cimgui_conf = cimgui.getConfig(true);
|
|
exe_mod.addImport("cimgui", dep_cimgui.module(cimgui_conf.module_name));
|
|
dep_sokol.artifact("sokol_clib").root_module.addIncludePath(dep_cimgui.path(cimgui_conf.include_dir));
|
|
}
|
|
}
|
|
|
|
const dep_stb = b.dependency("stb", .{});
|
|
exe_mod.addImport("stb_image", dep_stb.module("stb_image"));
|
|
exe_mod.addImport("stb_vorbis", dep_stb.module("stb_vorbis"));
|
|
|
|
const dep_tracy = b.dependency("tracy", .{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
.tracy_enable = has_tracy,
|
|
.tracy_only_localhost = true
|
|
});
|
|
if (has_tracy) {
|
|
exe_mod.linkLibrary(dep_tracy.artifact("tracy"));
|
|
}
|
|
exe_mod.addImport("tracy", dep_tracy.module("tracy"));
|
|
|
|
if (is_wasm) {
|
|
// TODO:
|
|
} else {
|
|
exe_mod.resolved_target = target;
|
|
exe_mod.optimize = optimize;
|
|
const exe = buildNative(b, .{
|
|
.name = "sokol_template_v2",
|
|
.root_module = exe_mod
|
|
});
|
|
b.installArtifact(exe);
|
|
|
|
{
|
|
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_tests = b.addTest(.{ .root_module = exe_mod, });
|
|
const run_exe_tests = b.addRunArtifact(exe_tests);
|
|
|
|
const test_step = b.step("test", "Run tests");
|
|
test_step.dependOn(&run_exe_tests.step);
|
|
}
|
|
}
|
|
}
|
|
|
|
const BuildNativeOptions = struct {
|
|
name: []const u8,
|
|
root_module: *std.Build.Module,
|
|
win32_has_console: ?bool = null,
|
|
win32_png_icon: ?std.Build.LazyPath = null
|
|
};
|
|
|
|
fn buildNative(
|
|
b: *std.Build,
|
|
opts: BuildNativeOptions,
|
|
) *std.Build.Step.Compile {
|
|
const exe = b.addExecutable(.{
|
|
.name = opts.name,
|
|
.root_module = opts.root_module,
|
|
});
|
|
|
|
const target = opts.root_module.resolved_target.?;
|
|
if (target.result.os.tag == .windows) {
|
|
const optimize = opts.root_module.optimize.?;
|
|
const has_console = opts.win32_has_console orelse (optimize == .Debug);
|
|
exe.subsystem = if (has_console) .Console else .Windows;
|
|
|
|
if (opts.win32_png_icon) |win32_png_icon| {
|
|
const png_to_icon_tool = buildPngToIconTool(b, b.graph.host, .ReleaseSafe);
|
|
|
|
const png_to_icon_step = b.addRunArtifact(png_to_icon_tool);
|
|
png_to_icon_step.addFileArg(win32_png_icon);
|
|
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);
|
|
}
|
|
}
|
|
|
|
return exe;
|
|
}
|
|
|
|
fn buildPngToIconTool(
|
|
b: *std.Build,
|
|
target: std.Build.ResolvedTarget,
|
|
optimize: std.builtin.OptimizeMode,
|
|
) *std.Build.Step.Compile {
|
|
const mod = b.createModule(.{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
.root_source_file = b.path("tools/png-to-icon.zig"),
|
|
});
|
|
|
|
const dep_stb = b.dependency("stb", .{});
|
|
mod.addImport("stb_image", dep_stb.module("stb_image"));
|
|
|
|
return b.addExecutable(.{
|
|
.name = "png-to-icon",
|
|
.root_module = mod,
|
|
});
|
|
}
|
|
|
|
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.root_module.addWin32ResourceFile(.{
|
|
.file = self.resource_file,
|
|
});
|
|
|
|
return self;
|
|
}
|
|
|
|
fn make(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
|
|
const b = step.owner;
|
|
const self: *AddExecutableIcon = @fieldParentPtr("step", step);
|
|
|
|
const relative_icon_path = try std.fs.path.relative(
|
|
b.allocator,
|
|
"",
|
|
null,
|
|
self.resource_file.dirname().getPath(b),
|
|
self.icon_file.getPath(b)
|
|
);
|
|
std.mem.replaceScalar(u8, relative_icon_path, '\\', '/');
|
|
|
|
{
|
|
const cwd = std.Io.Dir.cwd();
|
|
const resource_file = try cwd.createFile(b.graph.io, self.resource_file.getPath(b), .{ });
|
|
defer resource_file.close(b.graph.io);
|
|
|
|
var buff: [4*4096]u8 = undefined;
|
|
var file_writer = resource_file.writer(b.graph.io, &buff);
|
|
const w = &file_writer.interface;
|
|
|
|
try w.writeAll("IDI_ICON ICON \"");
|
|
try w.writeAll(relative_icon_path);
|
|
try w.writeAll("\"");
|
|
}
|
|
}
|
|
};
|