Skip to content

Commit

Permalink
[progress #146] custom bindings refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
tiawl committed Apr 6, 2024
1 parent 3a96150 commit 6af2072
Show file tree
Hide file tree
Showing 10 changed files with 442 additions and 327 deletions.
134 changes: 84 additions & 50 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const zig_version = @import ("builtin").zig_version;

const glfw = @import ("build/glfw.zig");
const vk = @import ("build/vk.zig");
const imgui = @import ("build/imgui.zig");
const shaders = @import ("build/shaders.zig");

const utils = @import ("build/utils.zig");
Expand All @@ -20,82 +21,112 @@ pub fn build (builder: *std.Build) !void

fn requirements () !void
{
if (zig_version.order (try std.SemanticVersion.parse (zon.min_zig_version)) == .lt)
std.debug.panic ("{s} needs at least Zig {s} to be build", .{ zon.name, zon.min_zig_version, });
if (zig_version.order (
try std.SemanticVersion.parse (zon.min_zig_version)) == .lt)
std.debug.panic ("{s} needs at least Zig {s} to be build",
.{ zon.name, zon.min_zig_version, });
}

fn turbo (builder: *std.Build, profile: *Profile) !void
{
profile.optimize = .ReleaseFast;
profile.variables.addOption ([] const u8, "log_dir", "");
profile.variables.addOption (u8, "log_level", 0);
profile.variables.addOption ([] const [] const [] const u8, "vk_optional_extensions", &.{});
profile.command = &.{ "glslc", "-O", try std.fmt.allocPrint (builder.allocator, "--target-env=vulkan1.{s}", .{ profile.options.vkminor, }), };
profile.variables.addOption ([] const [] const [] const u8,
"vk_optional_extensions", &.{});
profile.command = &.{ "glslc", "-O", try std.fmt.allocPrint (
builder.allocator, "--target-env=vulkan1.{s}",
.{ profile.options.vkminor, }), };
}

fn verbose (builder: *std.Build, profile: *Profile) !void
fn dev (builder: *std.Build, profile: *Profile) !void
{
const log_dir = "log";

// Make log directory if not present only in verbose mode
// Make log directory if not present only in dev mode
builder.build_root.handle.makeDir (log_dir) catch |err|
{
// Do not return error if log directory already exists
if (err != std.fs.File.OpenError.PathAlreadyExists) return err;
};

profile.optimize = .Debug;
profile.variables.addOption ([] const u8, "log_dir", try builder.build_root.join (builder.allocator, &.{ log_dir, }));
profile.variables.addOption ([] const u8, "log_dir",
try builder.build_root.join (builder.allocator, &.{ log_dir, }));
profile.variables.addOption (u8, "log_level", 2);
profile.variables.addOption ([] const [] const [] const u8, "vk_optional_extensions", &.{
&.{ "EXT", "DEVICE_ADDRESS_BINDING_REPORT", },
&.{ "EXT", "VALIDATION_FEATURES", },
&.{ "KHR", "SHADER_NON_SEMANTIC_INFO", },
});
profile.command = &.{ "glslc", try std.fmt.allocPrint (builder.allocator, "--target-env=vulkan1.{s}", .{ profile.options.vkminor, }), };
profile.variables.addOption ([] const [] const [] const u8,
"vk_optional_extensions", &.{
&.{ "EXT", "DEVICE_ADDRESS_BINDING_REPORT", },
&.{ "EXT", "VALIDATION_FEATURES", },
&.{ "KHR", "SHADER_NON_SEMANTIC_INFO", },
});
profile.command = &.{ "glslc", try std.fmt.allocPrint (builder.allocator,
"--target-env=vulkan1.{s}", .{ profile.options.vkminor, }), };
}

fn default (builder: *std.Build, profile: *Profile) !void
{
profile.optimize = builder.standardOptimizeOption (.{});
profile.variables.addOption ([] const u8, "log_dir", profile.options.logdir);
profile.variables.addOption (u8, "log_level", 1);
profile.variables.addOption ([] const [] const [] const u8, "vk_optional_extensions", &.{
&.{ "EXT", "DEVICE_ADDRESS_BINDING_REPORT", },
});
profile.command = &.{ "glslc", try std.fmt.allocPrint (builder.allocator, "--target-env=vulkan1.{s}", .{ profile.options.vkminor, }), };
profile.variables.addOption ([] const [] const [] const u8,
"vk_optional_extensions", &.{
&.{ "EXT", "DEVICE_ADDRESS_BINDING_REPORT", },
});
profile.command = &.{ "glslc", try std.fmt.allocPrint (builder.allocator,
"--target-env=vulkan1.{s}", .{ profile.options.vkminor, }), };
}

fn parse_options (builder: *std.Build) !Profile
{
const options = Options {
.verbose = builder.option (bool, std.meta.fieldInfo (Options, .verbose).name, "Build " ++ zon.name ++ " with full logging features. Default: " ++ (if (@field (Options.default, std.meta.fieldInfo (Options, .verbose).name)) "enabled" else "disabled") ++ ".")
orelse @field (Options.default, std.meta.fieldInfo (Options, .verbose).name),
.turbo = builder.option (bool, std.meta.fieldInfo (Options, .turbo).name, "Build " ++ zon.name ++ " with optimized features. Default: " ++ (if (@field (Options.default, std.meta.fieldInfo (Options, .turbo).name)) "enabled" else "disabled") ++ ".")
.dev = builder.option (bool, std.meta.fieldInfo (Options, .dev).name,
"Build " ++ zon.name ++ " with full logging features. Default: " ++
(if (@field (Options.default, std.meta.fieldInfo (Options, .dev).name))
"enabled" else "disabled") ++ ".")
orelse @field (Options.default, std.meta.fieldInfo (Options, .dev).name),
.turbo = builder.option (bool, std.meta.fieldInfo (Options, .turbo).name,
"Build " ++ zon.name ++ " with optimized features. Default: " ++
(if (@field (Options.default, std.meta.fieldInfo (Options, .turbo).name))
"enabled" else "disabled") ++ ".")
orelse @field (Options.default, std.meta.fieldInfo (Options, .turbo).name),
.logdir = builder.option ([] const u8, std.meta.fieldInfo (Options, .logdir).name, "Absolute path to log directory. If not specified, logs are not registered in a file.")
.logdir = builder.option ([] const u8,
std.meta.fieldInfo (Options, .logdir).name,
"Absolute path to log directory. If not specified, logs are not registered in a file.")
orelse @field (Options.default, std.meta.fieldInfo (Options, .logdir).name),
.vkminor = builder.option ([] const u8, std.meta.fieldInfo (Options, .vkminor).name, "Vulkan minor version to use: Possible values: 0, 1, 2 or 3. Default value: " ++ @field (Options.default, std.meta.fieldInfo (Options, .vkminor).name) ++ ".")
.vkminor = builder.option ([] const u8,
std.meta.fieldInfo (Options, .vkminor).name,
"Vulkan minor version to use: Possible values: 0, 1, 2 or 3. Default value: " ++
@field (Options.default, std.meta.fieldInfo (Options, .vkminor).name) ++ ".")
orelse @field (Options.default, std.meta.fieldInfo (Options, .vkminor).name),
};

_ = std.fmt.parseInt (u2, options.vkminor, 10) catch std.debug.panic ("-D{s} value should be 0, 1, 2 or 3", .{ std.meta.fieldInfo (Options, .vkminor).name, });
_ = std.fmt.parseInt (u2, options.vkminor, 10) catch
std.debug.panic ("-D{s} value should be 0, 1, 2 or 3",
.{ std.meta.fieldInfo (Options, .vkminor).name, });

if (options.turbo and options.verbose)
std.debug.panic ("-D{s} and -D{s} can not be used together", .{ std.meta.fieldInfo (Options, .turbo).name, std.meta.fieldInfo (Options, .verbose).name, })
if (options.turbo and options.dev)
std.debug.panic ("-D{s} and -D{s} can not be used together",
.{ std.meta.fieldInfo (Options, .turbo).name,
std.meta.fieldInfo (Options, .dev).name, })
else if (options.turbo and options.logdir.len > 0)
std.debug.panic ("-D{s} and -D{s} can not be used together", .{ std.meta.fieldInfo (Options, .turbo).name, std.meta.fieldInfo (Options, .logdir).name, });
std.debug.panic ("-D{s} and -D{s} can not be used together",
.{ std.meta.fieldInfo (Options, .turbo).name,
std.meta.fieldInfo (Options, .logdir).name, });

var profile: Profile = undefined;
profile.target = builder.standardTargetOptions (.{});
profile.options = options;
profile.variables = builder.addOptions ();
profile.variables.addOption ([] const u8, std.meta.fieldInfo (@TypeOf (zon), .name).name, zon.name);
profile.variables.addOption ([] const u8, std.meta.fieldInfo (@TypeOf (zon), .version).name, zon.version);
profile.variables.addOption ([] const u8, "vk_minor", profile.options.vkminor);
profile.variables.addOption ([] const u8,
std.meta.fieldInfo (@TypeOf (zon), .name).name, zon.name);
profile.variables.addOption ([] const u8,
std.meta.fieldInfo (@TypeOf (zon), .version).name, zon.version);
profile.variables.addOption ([] const u8, "vk_minor",
profile.options.vkminor);

if (profile.options.turbo) try turbo (builder, &profile)
else if (profile.options.verbose) try verbose (builder, &profile)
else if (profile.options.dev) try dev (builder, &profile)
else try default (builder, &profile);

return profile;
Expand All @@ -112,7 +143,8 @@ fn link (builder: *std.Build, profile: *const Profile) !*std.Build.Module
const cimgui = imgui_dep.artifact ("cimgui");

const c = builder.createModule (.{
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "raw.zig", }), },
.root_source_file = .{ .path = try builder.build_root.join (
builder.allocator, &.{ "src", "binding", "raw.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
Expand All @@ -123,7 +155,8 @@ fn link (builder: *std.Build, profile: *const Profile) !*std.Build.Module
return c;
}

fn import (builder: *std.Build, exe: *std.Build.Step.Compile, profile: *const Profile) !void
fn import (builder: *std.Build, exe: *std.Build.Step.Compile,
profile: *const Profile) !void
{
const datetime_dep = builder.dependency ("zig-datetime", .{
.target = profile.target,
Expand All @@ -135,38 +168,36 @@ fn import (builder: *std.Build, exe: *std.Build.Step.Compile, profile: *const Pr
const c = try link (builder, profile);
const glfw_module = try glfw.import (builder, profile, c);
const vk_module = try vk.import (builder, profile, c);

const imgui = builder.createModule (.{
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "imgui.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
imgui.addImport ("c", c);
imgui.addImport ("glfw", glfw_module);
imgui.addImport ("vk", vk_module);
const imgui_module =
try imgui.import (builder, profile, c, glfw_module, vk_module);

const build_options = profile.variables.createModule ();
const logger = builder.createModule (.{
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "src", "logger.zig", }), },
.root_source_file = .{ .path = try builder.build_root.join (
builder.allocator, &.{ "src", "logger.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
logger.addImport ("build", build_options);
logger.addImport ("datetime", datetime);

const instance = builder.createModule (.{
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator,
&.{ "src", "vk", "instance", if (profile.options.turbo) "turbo.zig" else "default.zig", }), },
.root_source_file = .{ .path = try builder.build_root.join (
builder.allocator, &.{ "src", "vk", "instance",
if (profile.options.turbo) "turbo.zig" else "default.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
instance.addImport ("logger", logger);
instance.addImport ("vk", vk_module);

for ([_] struct { name: [] const u8, ptr: *std.Build.Module, } {
.{ .name = "datetime", .ptr = datetime, }, .{ .name = "shader", .ptr = shaders_module, },
.{ .name = "glfw", .ptr = glfw_module, }, .{ .name = "vk", .ptr = vk_module, },
.{ .name = "imgui", .ptr = imgui, }, .{ .name = "logger", .ptr = logger, },
.{ .name = "datetime", .ptr = datetime, },
.{ .name = "shader", .ptr = shaders_module, },
.{ .name = "glfw", .ptr = glfw_module, },
.{ .name = "vk", .ptr = vk_module, },
.{ .name = "imgui", .ptr = imgui_module, },
.{ .name = "logger", .ptr = logger, },
.{ .name = "instance", .ptr = instance, },
}) |module| exe.root_module.addImport (module.name, module.ptr);
}
Expand All @@ -175,7 +206,8 @@ fn run_exe (builder: *std.Build, profile: *const Profile) !void
{
const exe = builder.addExecutable (.{
.name = zon.name,
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "src", "main.zig", }), },
.root_source_file = .{ .path = try builder.build_root.join (
builder.allocator, &.{ "src", "main.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
Expand All @@ -196,8 +228,10 @@ fn run_test (builder: *std.Build, profile: *const Profile) !void
const unit_tests = builder.addTest (.{
.target = profile.target,
.optimize = profile.optimize,
.test_runner = try builder.build_root.join (builder.allocator, &.{ "test", "runner.zig", }),
.root_source_file = .{ .path = try builder.build_root.join (builder.allocator, &.{ "test", "main.zig", }), },
.test_runner = try builder.build_root.join (builder.allocator,
&.{ "test", "runner.zig", }),
.root_source_file = .{ .path = try builder.build_root.join (
builder.allocator, &.{ "test", "main.zig", }), },
});
unit_tests.step.dependOn (builder.getInstallStep ());

Expand Down
39 changes: 23 additions & 16 deletions build/glfw.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ const std = @import ("std");

const Profile = @import ("utils.zig").Profile;

pub fn import (builder: *std.Build, profile: *const Profile, c: *std.Build.Module) !*std.Build.Module
pub fn import (builder: *std.Build, profile: *const Profile,
c: *std.Build.Module) !*std.Build.Module
{
const path = try builder.build_root.join (builder.allocator, &.{ "src", "binding", "glfw", });
const path = try builder.build_root.join (builder.allocator,
&.{ "src", "binding", "glfw", });

var modules = std.ArrayList (*std.Build.Module).init (builder.allocator);

Expand All @@ -17,35 +19,39 @@ pub fn import (builder: *std.Build, profile: *const Profile, c: *std.Build.Modul
switch (entry.kind)
{
.file => {
if (!std.mem.eql (u8, entry.name, "glfw.zig"))
{
try modules.append (builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, entry.name, }), },
.target = profile.target,
.optimize = profile.optimize,
}));
modules.items [modules.items.len - 1].addImport ("c", c);
}
},
if (!std.mem.eql (u8, entry.name, "glfw.zig"))
{
try modules.append (builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (
builder.allocator, &.{ path, entry.name, }), },
.target = profile.target,
.optimize = profile.optimize,
}));
modules.items [modules.items.len - 1].addImport ("c", c);
}
},
else => {},
}
}

const glfw = builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator, &.{ path, "glfw.zig", }), },
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator,
&.{ path, "glfw.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
glfw.addImport ("c", c);

for (modules.items) |module|
{
const name = std.fs.path.stem (std.fs.path.basename (module.root_source_file.?.getPath (builder)));
const name = std.fs.path.stem (
std.fs.path.basename (module.root_source_file.?.getPath (builder)));
glfw.addImport (name, module);
module.addImport ("glfw", glfw);
for (modules.items) |other|
{
const other_name = std.fs.path.stem (std.fs.path.basename (other.root_source_file.?.getPath (builder)));
const other_name = std.fs.path.stem (
std.fs.path.basename (other.root_source_file.?.getPath (builder)));
if (std.mem.eql (u8, name, other_name)) continue;
module.addImport (other_name, other);
}
Expand All @@ -54,7 +60,8 @@ pub fn import (builder: *std.Build, profile: *const Profile, c: *std.Build.Modul
return glfw;
}

pub fn lib (builder: *std.Build, profile: *const Profile) *std.Build.Step.Compile
pub fn lib (builder: *std.Build,
profile: *const Profile) *std.Build.Step.Compile
{
const dep = builder.dependency ("glfw", .{
.target = profile.target,
Expand Down
64 changes: 64 additions & 0 deletions build/imgui.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const std = @import ("std");

const Profile = @import ("utils.zig").Profile;

pub fn import (builder: *std.Build, profile: *const Profile,
c: *std.Build.Module, glfw: *std.Build.Module,
vk: *std.Build.Module) !*std.Build.Module
{
const path = try builder.build_root.join (builder.allocator,
&.{ "src", "binding", "imgui", });

var modules = std.ArrayList (*std.Build.Module).init (builder.allocator);

var dir = try builder.build_root.handle.openDir (path, .{ .iterate = true, });
defer dir.close ();

var it = dir.iterate ();
while (try it.next ()) |entry|
{
switch (entry.kind)
{
.file => {
if (!std.mem.eql (u8, entry.name, "imgui.zig"))
{
try modules.append (builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (
builder.allocator, &.{ path, entry.name, }), },
.target = profile.target,
.optimize = profile.optimize,
}));
modules.items [modules.items.len - 1].addImport ("c", c);
modules.items [modules.items.len - 1].addImport ("glfw", glfw);
modules.items [modules.items.len - 1].addImport ("vk", vk);
}
},
else => {},
}
}

const imgui = builder.createModule (.{
.root_source_file = .{ .path = try std.fs.path.join (builder.allocator,
&.{ path, "imgui.zig", }), },
.target = profile.target,
.optimize = profile.optimize,
});
imgui.addImport ("c", c);

for (modules.items) |module|
{
const name = std.fs.path.stem (
std.fs.path.basename (module.root_source_file.?.getPath (builder)));
imgui.addImport (name, module);
module.addImport ("imgui", imgui);
for (modules.items) |other|
{
const other_name = std.fs.path.stem (
std.fs.path.basename (other.root_source_file.?.getPath (builder)));
if (std.mem.eql (u8, name, other_name)) continue;
module.addImport (other_name, other);
}
}

return imgui;
}
2 changes: 1 addition & 1 deletion build/utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub const zon = .{ .name = "spaceporn", .version = "0.1.0", .min_zig_version = "

pub const Options = struct
{
verbose: bool = false,
dev: bool = false,
turbo: bool = false,
logdir: [] const u8 = "",
vkminor: [] const u8 = "2",
Expand Down
Loading

0 comments on commit 6af2072

Please sign in to comment.