rewrite build.zig to not use makeFn
This commit is contained in:
parent
7632329c92
commit
4764f153e6
BIN
assets/icon.png
Normal file
BIN
assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 454 B |
302
build.zig
302
build.zig
@ -6,9 +6,57 @@ pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const dep_stb = b.dependency("stb", .{});
|
||||
const ctx = Context.init(b, dep_stb.module("stb_image"));
|
||||
|
||||
var run_cmd_step: *std.Build.Step = undefined;
|
||||
switch (try buildProject(ctx, target, optimize)) {
|
||||
.native => |exe| {
|
||||
b.installArtifact(exe);
|
||||
|
||||
{
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
run_cmd_step = &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);
|
||||
// }
|
||||
},
|
||||
.wasm => {
|
||||
// TODO:
|
||||
// b.getInstallStep().dependOn(build_step);
|
||||
//
|
||||
// const dep_emsdk = dep_sokol.builder.dependency("emsdk", .{});
|
||||
// const emrun_step = sokol.emRunStep(b, .{ .name = "index", .emsdk = dep_emsdk });
|
||||
// emrun_step.step.dependOn(build_step);
|
||||
// run_cmd_step = &emrun_step.step;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const run_step = b.step("run", "Run game");
|
||||
run_step.dependOn(run_cmd_step);
|
||||
}
|
||||
|
||||
const ProjectResult = union(enum) {
|
||||
native: *std.Build.Step.Compile,
|
||||
wasm: *std.Build.Step,
|
||||
};
|
||||
|
||||
fn buildProject(ctx: Context, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) !ProjectResult {
|
||||
const b = ctx.b;
|
||||
|
||||
const name = "sokol_template_v2";
|
||||
|
||||
const assets_dir = "assets";
|
||||
const assets_dir = b.path("assets");
|
||||
const asset_files = [_][]const u8{
|
||||
"sokoban/sokoban_tilesheet.png",
|
||||
"sokoban/sokoban_tilesheet@2.png",
|
||||
@ -18,10 +66,8 @@ pub fn build(b: *std.Build) !void {
|
||||
"impact-sounds/footstep_concrete_000.ogg"
|
||||
};
|
||||
|
||||
const asset_dir_realpath = try b.build_root.join(b.graph.arena, &.{ assets_dir });
|
||||
|
||||
const is_wasm = target.result.cpu.arch.isWasm();
|
||||
const is_debug = (optimize == .Debug);
|
||||
const is_debug = optimize == .Debug;
|
||||
|
||||
const has_imgui = b.option(bool, "imgui", "ImGui integration") orelse is_debug;
|
||||
const assets_from_filesystem = b.option(bool, "assets-filesystem", "Allow reading assets from filesystem") orelse is_debug;
|
||||
@ -31,6 +77,9 @@ pub fn build(b: *std.Build) !void {
|
||||
has_tracy = b.option(bool, "tracy", "Tracy integration") orelse is_debug;
|
||||
}
|
||||
|
||||
const win32_has_console = null;
|
||||
const win32_icon_png: ?Build.LazyPath = b.path("assets/icon.png");
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.root_source_file = b.path("src/main.zig"),
|
||||
.target = target,
|
||||
@ -52,10 +101,10 @@ pub fn build(b: *std.Build) !void {
|
||||
{
|
||||
const build_options = b.addOptions();
|
||||
build_options.addOption(bool, "has_imgui", has_imgui);
|
||||
build_options.addOption(?[]const u8, "assets_dir", if (assets_from_filesystem) asset_dir_realpath else null);
|
||||
build_options.addOption(?[]const u8, "assets_dir", if (assets_from_filesystem) assets_dir.getPath(b) else null);
|
||||
platform_mod.addOptions("build_options", build_options);
|
||||
|
||||
platform_mod.addImport("embedded_assets", try createEmbeddedAssets(b, assets_dir, &asset_files));
|
||||
platform_mod.addImport("embedded_assets", try createAssetsModule(b, assets_dir, &asset_files));
|
||||
|
||||
const math_mod = b.createModule(.{
|
||||
.root_source_file = b.path("src/platform/math.zig")
|
||||
@ -118,206 +167,121 @@ pub fn build(b: *std.Build) !void {
|
||||
platform_mod.addImport("tracy", dep_tracy.module("tracy"));
|
||||
}
|
||||
|
||||
var run_cmd_step: *std.Build.Step = undefined;
|
||||
if (is_wasm) {
|
||||
@panic("TODO: Test wasm support on 0.17");
|
||||
|
||||
// const build_step = buildWasm(b, .{
|
||||
// .name = "index",
|
||||
// .root_module = exe_mod,
|
||||
// .dep_sokol = dep_sokol,
|
||||
// });
|
||||
// b.getInstallStep().dependOn(build_step);
|
||||
//
|
||||
// const dep_emsdk = dep_sokol.builder.dependency("emsdk", .{});
|
||||
// const emrun_step = sokol.emRunStep(b, .{ .name = "index", .emsdk = dep_emsdk });
|
||||
// emrun_step.step.dependOn(build_step);
|
||||
// run_cmd_step = &emrun_step.step;
|
||||
|
||||
// TODO: Create a zip archive of all of the files. Would be useful for easier itch.io upload
|
||||
return ProjectResult{
|
||||
.wasm = buildWasm(b, .{
|
||||
.name = "index",
|
||||
.root_module = exe_mod,
|
||||
.dep_sokol = dep_sokol,
|
||||
})
|
||||
};
|
||||
} else {
|
||||
const exe = buildNative(b, .{
|
||||
const exe = b.addExecutable(.{
|
||||
.name = name,
|
||||
.root_module = exe_mod
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
{
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
run_cmd_step = &run_cmd.step;
|
||||
}
|
||||
if (target.result.os.tag == .windows) {
|
||||
const has_console = win32_has_console orelse (optimize == .Debug);
|
||||
exe.subsystem = if (has_console) .Console else .Windows;
|
||||
|
||||
{
|
||||
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);
|
||||
if (win32_icon_png) |icon_png| {
|
||||
buildWin32ResourceFile(ctx, exe.root_module, .{
|
||||
.icon_png = icon_png
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const run_step = b.step("run", "Run game");
|
||||
run_step.dependOn(run_cmd_step);
|
||||
return ProjectResult{
|
||||
.native = exe
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn createEmbeddedAssets(
|
||||
fn createAssetsModule(
|
||||
b: *std.Build,
|
||||
assets_dir: []const u8,
|
||||
assets_dir: Build.LazyPath,
|
||||
asset_files: []const []const u8
|
||||
) !*std.Build.Module {
|
||||
const write_files = b.addWriteFiles();
|
||||
|
||||
var embedded_assets: std.ArrayList(u8) = .empty;
|
||||
defer embedded_assets.deinit(b.allocator);
|
||||
var mod_contents: std.ArrayList(u8) = .empty;
|
||||
defer mod_contents.deinit(b.allocator);
|
||||
|
||||
try embedded_assets.appendSlice(b.allocator, "pub const files = .{\n");
|
||||
const mod_embedded_assets = b.createModule(.{});
|
||||
try mod_contents.appendSlice(b.allocator, "pub const files = .{\n");
|
||||
const mod = b.createModule(.{});
|
||||
for (asset_files) |asset_file| {
|
||||
mod_embedded_assets.addAnonymousImport(asset_file, .{
|
||||
.root_source_file = b.path(b.pathJoin(&.{ assets_dir, asset_file }))
|
||||
mod.addAnonymousImport(asset_file, .{
|
||||
.root_source_file = assets_dir.path(b, asset_file)
|
||||
});
|
||||
|
||||
try embedded_assets.appendSlice(b.allocator, " .{ ");
|
||||
try mod_contents.appendSlice(b.allocator, " .{ ");
|
||||
|
||||
try embedded_assets.appendSlice(b.allocator, ".name = \"");
|
||||
try embedded_assets.appendSlice(b.allocator, asset_file);
|
||||
try embedded_assets.appendSlice(b.allocator, "\"");
|
||||
try mod_contents.appendSlice(b.allocator, ".name = \"");
|
||||
try mod_contents.appendSlice(b.allocator, asset_file);
|
||||
try mod_contents.appendSlice(b.allocator, "\"");
|
||||
|
||||
try embedded_assets.appendSlice(b.allocator, ", ");
|
||||
try mod_contents.appendSlice(b.allocator, ", ");
|
||||
|
||||
try embedded_assets.appendSlice(b.allocator, ".contents = @embedFile(\"");
|
||||
try embedded_assets.appendSlice(b.allocator, asset_file);
|
||||
try embedded_assets.appendSlice(b.allocator, "\")");
|
||||
try mod_contents.appendSlice(b.allocator, ".contents = @embedFile(\"");
|
||||
try mod_contents.appendSlice(b.allocator, asset_file);
|
||||
try mod_contents.appendSlice(b.allocator, "\")");
|
||||
|
||||
try embedded_assets.appendSlice(b.allocator, " },\n");
|
||||
try mod_contents.appendSlice(b.allocator, " },\n");
|
||||
}
|
||||
try embedded_assets.appendSlice(b.allocator, "};\n");
|
||||
mod_embedded_assets.root_source_file = write_files.add("embedded_assets.zig", embedded_assets.items);
|
||||
try mod_contents.appendSlice(b.allocator, "};\n");
|
||||
mod.root_source_file = write_files.add("assets.zig", mod_contents.items);
|
||||
|
||||
return mod_embedded_assets;
|
||||
return mod;
|
||||
}
|
||||
|
||||
const BuildNativeOptions = struct {
|
||||
name: []const u8,
|
||||
root_module: *std.Build.Module,
|
||||
win32_has_console: ?bool = null,
|
||||
win32_png_icon: ?std.Build.LazyPath = null
|
||||
const Context = struct {
|
||||
b: *std.Build,
|
||||
png_to_icon: *Build.Step.Compile,
|
||||
create_win32_resource: *Build.Step.Compile,
|
||||
|
||||
pub fn init(b: *std.Build, stb_image: *Build.Module) Context {
|
||||
return Context{
|
||||
.b = b,
|
||||
.png_to_icon = b.addExecutable(.{
|
||||
.name = "png-to-icon",
|
||||
.root_module = b.createModule(.{
|
||||
.target = b.graph.host,
|
||||
.root_source_file = b.path("scripts/png-to-icon.zig"),
|
||||
.imports = &.{
|
||||
.{ .name = "stb_image", .module = stb_image }
|
||||
}
|
||||
})
|
||||
}),
|
||||
.create_win32_resource = b.addExecutable(.{
|
||||
.name = "create-win32-resource",
|
||||
.root_module = b.createModule(.{
|
||||
.target = b.graph.host,
|
||||
.root_source_file = b.path("scripts/create-win32-resource.zig"),
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fn buildNative(
|
||||
b: *std.Build,
|
||||
opts: BuildNativeOptions,
|
||||
) *std.Build.Step.Compile {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = opts.name,
|
||||
.root_module = opts.root_module,
|
||||
});
|
||||
const Win32ResourceFileOptions = struct {
|
||||
icon_png: Build.LazyPath
|
||||
};
|
||||
|
||||
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;
|
||||
fn buildWin32ResourceFile(ctx: Context, mod: *Build.Module, opts: Win32ResourceFileOptions) void {
|
||||
const b = ctx.b;
|
||||
|
||||
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 png_to_icon_step = b.addRunArtifact(ctx.png_to_icon);
|
||||
png_to_icon_step.addFileArg(opts.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);
|
||||
}
|
||||
}
|
||||
const resource_file_step = b.addRunArtifact(ctx.create_win32_resource);
|
||||
resource_file_step.addFileArg(icon_file);
|
||||
const resource_file = resource_file_step.addOutputFileArg("resource-file.rc");
|
||||
|
||||
return exe;
|
||||
mod.addWin32ResourceFile(.{ .file = resource_file });
|
||||
}
|
||||
|
||||
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("\"");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const BuildWasmOptions = struct {
|
||||
name: []const u8,
|
||||
root_module: *std.Build.Module,
|
||||
|
||||
31
scripts/create-win32-resource.zig
Normal file
31
scripts/create-win32-resource.zig
Normal file
@ -0,0 +1,31 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
const io = init.io;
|
||||
const arena = init.arena.allocator();
|
||||
const args = try init.minimal.args.toSlice(arena);
|
||||
|
||||
if (args.len != 3) {
|
||||
std.debug.print("Usage: ./create-win32-resource-file <icon> <output>", .{});
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
const icon_file_path = args[1];
|
||||
const output_file_path = args[2];
|
||||
|
||||
const cwd = Io.Dir.cwd();
|
||||
|
||||
const output_file = try cwd.createFile(io, output_file_path, .{});
|
||||
defer output_file.close(io);
|
||||
|
||||
var buff: [4*4096]u8 = undefined;
|
||||
var file_writer = output_file.writer(io, &buff);
|
||||
const writer = &file_writer.interface;
|
||||
|
||||
try writer.writeAll("IDI_ICON ICON \"");
|
||||
try writer.writeAll(icon_file_path);
|
||||
try writer.writeAll("\"");
|
||||
|
||||
try writer.flush();
|
||||
}
|
||||
@ -1,27 +1,26 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const STBImage = @import("stb_image");
|
||||
|
||||
// https://en.wikipedia.org/wiki/ICO_(file_format)#Icon_file_structure
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const allocator = gpa.allocator();
|
||||
defer _ = gpa.deinit();
|
||||
|
||||
const args = try std.process.argsAlloc(allocator);
|
||||
defer std.process.argsFree(allocator, args);
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
const io = init.io;
|
||||
const gpa = init.gpa;
|
||||
const arena = init.arena.allocator();
|
||||
const args = try init.minimal.args.toSlice(arena);
|
||||
|
||||
if (args.len != 3) {
|
||||
std.debug.print("Usage: ./png-to-icon <png-file> <output-ico>", .{});
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
const cwd = std.fs.cwd();
|
||||
const cwd = Io.Dir.cwd();
|
||||
const input_png_path = args[1];
|
||||
const output_ico_path = args[2];
|
||||
|
||||
const input_png_data = try cwd.readFileAlloc(allocator, input_png_path, 1024 * 1024 * 5);
|
||||
defer allocator.free(input_png_data);
|
||||
const input_png_data = try cwd.readFileAlloc(io, input_png_path, gpa, .unlimited);
|
||||
defer gpa.free(input_png_data);
|
||||
|
||||
const png_image = try STBImage.load(input_png_data);
|
||||
defer png_image.deinit();
|
||||
@ -29,29 +28,30 @@ pub fn main() !void {
|
||||
std.debug.assert(png_image.width > 0 and png_image.width <= 256);
|
||||
std.debug.assert(png_image.height > 0 and png_image.height <= 256);
|
||||
|
||||
const output_ico_file = try std.fs.cwd().createFile(output_ico_path, .{ });
|
||||
defer output_ico_file.close();
|
||||
const output_ico_file = try cwd.createFile(io, output_ico_path, .{});
|
||||
defer output_ico_file.close(io);
|
||||
|
||||
var buffer: [4096 * 4]u8 = undefined;
|
||||
var writer = output_ico_file.writer(&buffer);
|
||||
var file_writer = output_ico_file.writer(io, &buffer);
|
||||
const writer = &file_writer.interface;
|
||||
|
||||
// ICONDIR structure
|
||||
try writer.interface.writeInt(u16, 0, .little); // Must always be zero
|
||||
try writer.interface.writeInt(u16, 1, .little); // Image type. 1 for .ICO
|
||||
try writer.interface.writeInt(u16, 1, .little); // Number of images
|
||||
try writer.writeInt(u16, 0, .little); // Must always be zero
|
||||
try writer.writeInt(u16, 1, .little); // Image type. 1 for .ICO
|
||||
try writer.writeInt(u16, 1, .little); // Number of images
|
||||
|
||||
// ICONDIRENTRY structure
|
||||
try writer.interface.writeInt(u8, @truncate(png_image.width), .little); // Image width
|
||||
try writer.interface.writeInt(u8, @truncate(png_image.height), .little); // Image height
|
||||
try writer.interface.writeInt(u8, 0, .little); // Number of colors in color pallete. 0 means that color pallete is not used
|
||||
try writer.interface.writeInt(u8, 0, .little); // Must always be zero
|
||||
try writer.interface.writeInt(u16, 0, .little); // Color plane
|
||||
try writer.interface.writeInt(u16, 32, .little); // Bits per pixel
|
||||
try writer.interface.writeInt(u32, @intCast(input_png_data.len), .little); // Image size in bytes
|
||||
try writer.interface.writeInt(u32, 22, .little); // Offset to image data from the start
|
||||
try writer.writeInt(u8, @truncate(png_image.width), .little); // Image width
|
||||
try writer.writeInt(u8, @truncate(png_image.height), .little); // Image height
|
||||
try writer.writeInt(u8, 0, .little); // Number of colors in color pallete. 0 means that color pallete is not used
|
||||
try writer.writeInt(u8, 0, .little); // Must always be zero
|
||||
try writer.writeInt(u16, 0, .little); // Color plane
|
||||
try writer.writeInt(u16, 32, .little); // Bits per pixel
|
||||
try writer.writeInt(u32, @intCast(input_png_data.len), .little); // Image size in bytes
|
||||
try writer.writeInt(u32, 22, .little); // Offset to image data from the start
|
||||
|
||||
// PNG image data
|
||||
try writer.interface.writeAll(input_png_data);
|
||||
try writer.interface.flush();
|
||||
try writer.writeAll(input_png_data);
|
||||
try writer.flush();
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user