build.zig
Ref: Size: 8.7 KiB
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const config_mod = b.createModule(.{
.root_source_file = b.path("src/config.zig"),
.target = target,
.optimize = optimize,
});
const scale_tracker_mod = b.createModule(.{
.root_source_file = b.path("src/scale_tracker.zig"),
.target = target,
.optimize = optimize,
});
// Lazy-fetch the ghostty dependency. On the first invocation this
// materializes the package; subsequent builds use the local cache.
const ghostty_dep = b.lazyDependency("ghostty", .{});
// zig-wayland scanner — generates protocol bindings at build time
const wayland_dep = b.dependency("wayland", .{});
const Scanner = @import("wayland").Scanner;
const scanner = Scanner.create(b, .{});
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
scanner.generate("wl_compositor", 6);
scanner.generate("wl_seat", 9);
scanner.generate("wl_data_device_manager", 3);
scanner.generate("wl_output", 4);
scanner.generate("xdg_wm_base", 6);
// wayland module — generated bindings + our Connection wrapper
const wayland_generated_mod = b.createModule(.{
.root_source_file = scanner.result,
.target = target,
.optimize = optimize,
});
const wayland_mod = b.createModule(.{
.root_source_file = b.path("src/wayland.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
wayland_mod.addImport("wayland", wayland_generated_mod);
wayland_mod.addImport("scale_tracker", scale_tracker_mod);
wayland_mod.linkSystemLibrary("wayland-client", .{});
wayland_mod.linkSystemLibrary("xkbcommon", .{});
_ = wayland_dep; // referenced via Scanner
// vt module — wraps ghostty-vt
const vt_mod = b.createModule(.{
.root_source_file = b.path("src/vt.zig"),
.target = target,
.optimize = optimize,
});
if (ghostty_dep) |dep| {
vt_mod.addImport("ghostty-vt", dep.module("ghostty-vt"));
}
// Main executable module
const exe_mod = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
exe_mod.addImport("vt", vt_mod);
exe_mod.addImport("wayland-client", wayland_mod);
exe_mod.addImport("config", config_mod);
const exe = b.addExecutable(.{
.name = "waystty",
.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 waystty");
run_step.dependOn(&run_cmd.step);
// pty module — forkpty-based PTY spawn
const pty_mod = b.createModule(.{
.root_source_file = b.path("src/pty.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
pty_mod.linkSystemLibrary("util", .{});
exe_mod.addImport("pty", pty_mod);
const test_step = b.step("test", "Run unit tests");
// Test pty.zig
const pty_test_mod = b.createModule(.{
.root_source_file = b.path("src/pty.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
pty_test_mod.linkSystemLibrary("util", .{});
const pty_tests = b.addTest(.{
.root_module = pty_test_mod,
});
test_step.dependOn(&b.addRunArtifact(pty_tests).step);
// Test scale_tracker.zig
const scale_tracker_test_mod = b.createModule(.{
.root_source_file = b.path("src/scale_tracker.zig"),
.target = target,
.optimize = optimize,
});
const scale_tracker_tests = b.addTest(.{
.root_module = scale_tracker_test_mod,
});
test_step.dependOn(&b.addRunArtifact(scale_tracker_tests).step);
// Test wayland.zig
const wayland_test_mod = b.createModule(.{
.root_source_file = b.path("src/wayland.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
wayland_test_mod.addImport("wayland", wayland_generated_mod);
wayland_test_mod.addImport("scale_tracker", scale_tracker_mod);
wayland_test_mod.linkSystemLibrary("wayland-client", .{});
wayland_test_mod.linkSystemLibrary("xkbcommon", .{});
const wayland_tests = b.addTest(.{
.root_module = wayland_test_mod,
});
test_step.dependOn(&b.addRunArtifact(wayland_tests).step);
// Test main.zig (and transitively vt.zig via its import)
const main_test_mod = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
main_test_mod.addImport("vt", vt_mod);
main_test_mod.addImport("wayland-client", wayland_mod);
main_test_mod.addImport("config", config_mod);
const main_tests = b.addTest(.{
.root_module = main_test_mod,
});
test_step.dependOn(&b.addRunArtifact(main_tests).step);
// Test vt.zig directly (runs the ghostty-vt smoke test)
const vt_test_mod = b.createModule(.{
.root_source_file = b.path("src/vt.zig"),
.target = target,
.optimize = optimize,
});
if (ghostty_dep) |dep| {
vt_test_mod.addImport("ghostty-vt", dep.module("ghostty-vt"));
}
const vt_tests = b.addTest(.{
.root_module = vt_test_mod,
});
test_step.dependOn(&b.addRunArtifact(vt_tests).step);
// font module — fontconfig lookup + freetype rasterization + glyph atlas
const font_mod = b.createModule(.{
.root_source_file = b.path("src/font.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
font_mod.addImport("config", config_mod);
font_mod.linkSystemLibrary("fontconfig", .{});
font_mod.linkSystemLibrary("freetype2", .{});
exe_mod.addImport("font", font_mod);
// Test font.zig
const font_test_mod = b.createModule(.{
.root_source_file = b.path("src/font.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
font_test_mod.addImport("config", config_mod);
font_test_mod.linkSystemLibrary("fontconfig", .{});
font_test_mod.linkSystemLibrary("freetype2", .{});
const font_tests = b.addTest(.{
.root_module = font_test_mod,
});
test_step.dependOn(&b.addRunArtifact(font_tests).step);
// vulkan-zig — generate Vulkan bindings from vk.xml
const vulkan_headers_dep = b.dependency("vulkan_headers", .{});
const vulkan_zig_dep = b.dependency("vulkan", .{
.registry = vulkan_headers_dep.path("registry/vk.xml"),
});
const vulkan_module = vulkan_zig_dep.module("vulkan-zig");
// Compile cell shaders to SPIR-V via glslc
const glslc_vert = b.addSystemCommand(&.{ "glslc", "--target-env=vulkan1.2" });
glslc_vert.addFileArg(b.path("shaders/cell.vert"));
glslc_vert.addArg("-o");
const cell_vert_spv = glslc_vert.addOutputFileArg("cell.vert.spv");
const glslc_frag = b.addSystemCommand(&.{ "glslc", "--target-env=vulkan1.2" });
glslc_frag.addFileArg(b.path("shaders/cell.frag"));
glslc_frag.addArg("-o");
const cell_frag_spv = glslc_frag.addOutputFileArg("cell.frag.spv");
// Collect renderer.zig + both SPV blobs into one WriteFiles directory so
// that @embedFile("cell.vert.spv") resolves correctly relative to renderer.zig.
const renderer_dir = b.addWriteFiles();
const renderer_zig_path = renderer_dir.addCopyFile(b.path("src/renderer.zig"), "renderer.zig");
_ = renderer_dir.addCopyFile(cell_vert_spv, "cell.vert.spv");
_ = renderer_dir.addCopyFile(cell_frag_spv, "cell.frag.spv");
// renderer module
const renderer_mod = b.createModule(.{
.root_source_file = renderer_zig_path,
.target = target,
.optimize = optimize,
.link_libc = true,
});
renderer_mod.addImport("vulkan", vulkan_module);
renderer_mod.linkSystemLibrary("dl", .{});
exe_mod.addImport("vulkan", vulkan_module);
exe_mod.addImport("renderer", renderer_mod);
main_test_mod.addImport("vulkan", vulkan_module);
main_test_mod.addImport("renderer", renderer_mod);
main_test_mod.addImport("font", font_mod);
// Test renderer.zig
const renderer_test_mod = b.createModule(.{
.root_source_file = renderer_zig_path,
.target = target,
.optimize = optimize,
.link_libc = true,
});
renderer_test_mod.addImport("vulkan", vulkan_module);
renderer_test_mod.linkSystemLibrary("dl", .{});
const renderer_tests = b.addTest(.{
.root_module = renderer_test_mod,
});
test_step.dependOn(&b.addRunArtifact(renderer_tests).step);
}