const std = @import("std"); const Build = std.Build; const Scanner = @import("wayland").Scanner; pub fn build(b: *Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const strip = b.option(bool, "strip", "Omit debug information") orelse false; const pie = b.option(bool, "pie", "Build a Position Independent Executable") orelse false; // Allow packagers and Nix users to swap in their own config.zig without // patching the source tree, which is how one configures dwm too. const config_path = b.option( []const u8, "config", "Path to a config.zig to use instead of src/config.zig", ); const scanner = Scanner.create(b, .{}); scanner.addCustomProtocol(b.path("protocol/river-window-management-v1.xml")); scanner.addCustomProtocol(b.path("protocol/river-xkb-bindings-v1.xml")); scanner.addCustomProtocol(b.path("protocol/river-layer-shell-v1.xml")); scanner.addCustomProtocol(b.path("protocol/river-input-management-v1.xml")); scanner.addCustomProtocol(b.path("protocol/river-libinput-config-v1.xml")); scanner.addCustomProtocol(b.path("protocol/river-xkb-config-v1.xml")); // Besides the river protocols we are an ordinary Wayland client: wl_shm and // wl_compositor back the tab bar, wl_seat lets us click on it. scanner.generate("wl_compositor", 4); scanner.generate("wl_shm", 1); scanner.generate("wl_seat", 7); scanner.generate("wl_output", 4); scanner.generate("river_window_manager_v1", 4); scanner.generate("river_xkb_bindings_v1", 3); scanner.generate("river_layer_shell_v1", 1); scanner.generate("river_input_manager_v1", 1); scanner.generate("river_libinput_config_v1", 1); scanner.generate("river_xkb_config_v1", 1); const wayland = b.createModule(.{ .root_source_file = scanner.result }); const xkbcommon = b.dependency("xkbcommon", .{}).module("xkbcommon"); // action.zig is deliberately free of any Wayland or compositor state so // that config.zig can import it without a dependency cycle back into the // window manager. const action = b.createModule(.{ .root_source_file = b.path("src/action.zig"), }); action.addImport("xkbcommon", xkbcommon); // Likewise Wayland-free, for the same reason: config.zig declares input // device settings with these types, and the protocol objects they end up on // live in src/InputManager.zig. const input = b.createModule(.{ .root_source_file = b.path("src/input.zig"), }); const config = b.createModule(.{ .root_source_file = if (config_path) |p| .{ .cwd_relative = p } else b.path("src/config.zig"), }); config.addImport("action", action); config.addImport("input", input); config.addImport("xkbcommon", xkbcommon); { const exe = b.addExecutable(.{ .name = "att_wm", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .strip = strip, .link_libc = true, }), }); exe.root_module.addImport("wayland", wayland); exe.root_module.addImport("xkbcommon", xkbcommon); exe.root_module.addImport("action", action); exe.root_module.addImport("input", input); exe.root_module.addImport("config", config); exe.root_module.linkSystemLibrary("wayland-client", .{}); exe.root_module.linkSystemLibrary("xkbcommon", .{}); exe.pie = pie; b.installArtifact(exe); } { const ctl = b.addExecutable(.{ .name = "att_wmctl", .root_module = b.createModule(.{ .root_source_file = b.path("src/ctl.zig"), .target = target, .optimize = optimize, .strip = strip, .link_libc = true, }), }); ctl.pie = pie; b.installArtifact(ctl); } { const tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("src/test.zig"), .target = target, .optimize = optimize, .link_libc = true, }), }); tests.root_module.addImport("action", action); tests.root_module.addImport("input", input); tests.root_module.linkSystemLibrary("xkbcommon", .{}); const run_tests = b.addRunArtifact(tests); b.step("test", "Run unit tests").dependOn(&run_tests.step); } }