mirror of
https://github.com/zoriya/zig-wayland.git
synced 2025-12-06 07:06:12 +00:00
185 lines
6.8 KiB
Zig
185 lines
6.8 KiB
Zig
const std = @import("std");
|
|
const Build = std.Build;
|
|
const fs = std.fs;
|
|
const mem = std.mem;
|
|
|
|
pub fn build(b: *Build) void {
|
|
const target = b.standardTargetOptions(.{});
|
|
const optimize = b.standardOptimizeOption(.{});
|
|
|
|
const scanner = Scanner.create(b, .{});
|
|
|
|
const wayland = b.createModule(.{ .source_file = scanner.result });
|
|
|
|
scanner.generate("wl_compositor", 1);
|
|
scanner.generate("wl_shm", 1);
|
|
scanner.generate("wl_seat", 2);
|
|
scanner.generate("wl_output", 1);
|
|
|
|
inline for ([_][]const u8{ "globals", "list", "listener", "seats" }) |example| {
|
|
const exe = b.addExecutable(.{
|
|
.name = example,
|
|
.root_source_file = .{ .path = "example/" ++ example ++ ".zig" },
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
|
|
exe.addModule("wayland", wayland);
|
|
scanner.addCSource(exe);
|
|
exe.linkLibC();
|
|
exe.linkSystemLibrary("wayland-client");
|
|
|
|
b.installArtifact(exe);
|
|
}
|
|
|
|
const test_step = b.step("test", "Run the tests");
|
|
{
|
|
const scanner_tests = b.addTest(.{
|
|
.root_source_file = .{ .path = "src/scanner.zig" },
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
|
|
scanner_tests.addModule("wayland", wayland);
|
|
|
|
test_step.dependOn(&scanner_tests.step);
|
|
}
|
|
{
|
|
const ref_all = b.addTest(.{
|
|
.root_source_file = .{ .path = "src/ref_all.zig" },
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
|
|
ref_all.addModule("wayland", wayland);
|
|
scanner.addCSource(ref_all);
|
|
ref_all.linkLibC();
|
|
ref_all.linkSystemLibrary("wayland-client");
|
|
ref_all.linkSystemLibrary("wayland-server");
|
|
ref_all.linkSystemLibrary("wayland-egl");
|
|
ref_all.linkSystemLibrary("wayland-cursor");
|
|
test_step.dependOn(&ref_all.step);
|
|
}
|
|
}
|
|
|
|
pub const Scanner = struct {
|
|
run: *Build.Step.Run,
|
|
result: Build.LazyPath,
|
|
|
|
/// Path to the system protocol directory, stored to avoid invoking pkg-config N times.
|
|
wayland_protocols_path: []const u8,
|
|
|
|
// TODO remove these when the workaround for zig issue #131 is no longer needed.
|
|
compiles: std.ArrayListUnmanaged(*Build.Step.Compile) = .{},
|
|
c_sources: std.ArrayListUnmanaged(Build.LazyPath) = .{},
|
|
|
|
pub const Options = struct {
|
|
/// Path to the wayland.xml file.
|
|
/// If null, the output of `pkg-config --variable=pkgdatadir wayland-scanner` will be used.
|
|
wayland_xml_path: ?[]const u8 = null,
|
|
/// Path to the wayland-protocols installation.
|
|
/// If null, the output of `pkg-config --variable=pkgdatadir wayland-protocols` will be used.
|
|
wayland_protocols_path: ?[]const u8 = null,
|
|
};
|
|
|
|
pub fn create(b: *Build, options: Options) *Scanner {
|
|
const wayland_xml_path = options.wayland_xml_path orelse blk: {
|
|
const pc_output = b.run(&.{ "pkg-config", "--variable=pkgdatadir", "wayland-scanner" });
|
|
break :blk b.pathJoin(&.{ mem.trim(u8, pc_output, &std.ascii.whitespace), "wayland.xml" });
|
|
};
|
|
const wayland_protocols_path = options.wayland_protocols_path orelse blk: {
|
|
const pc_output = b.run(&.{ "pkg-config", "--variable=pkgdatadir", "wayland-protocols" });
|
|
break :blk mem.trim(u8, pc_output, &std.ascii.whitespace);
|
|
};
|
|
|
|
const zig_wayland_dir = fs.path.dirname(@src().file) orelse ".";
|
|
const exe = b.addExecutable(.{
|
|
.name = "zig-wayland-scanner",
|
|
.root_source_file = .{ .path = b.pathJoin(&.{ zig_wayland_dir, "src/scanner.zig" }) },
|
|
});
|
|
|
|
const run = b.addRunArtifact(exe);
|
|
|
|
run.addArg("-o");
|
|
const result = run.addOutputFileArg("wayland.zig");
|
|
|
|
run.addArg("-i");
|
|
run.addFileArg(.{ .path = wayland_xml_path });
|
|
|
|
const scanner = b.allocator.create(Scanner) catch @panic("OOM");
|
|
scanner.* = .{
|
|
.run = run,
|
|
.result = result,
|
|
.wayland_protocols_path = wayland_protocols_path,
|
|
};
|
|
|
|
return scanner;
|
|
}
|
|
|
|
/// Scan protocol xml provided by the wayland-protocols package at the given path
|
|
/// relative to the wayland-protocols installation. (e.g. "stable/xdg-shell/xdg-shell.xml")
|
|
pub fn addSystemProtocol(scanner: *Scanner, relative_path: []const u8) void {
|
|
const b = scanner.run.step.owner;
|
|
const full_path = b.pathJoin(&.{ scanner.wayland_protocols_path, relative_path });
|
|
|
|
scanner.run.addArg("-i");
|
|
scanner.run.addFileArg(.{ .path = full_path });
|
|
|
|
scanner.generateCSource(full_path);
|
|
}
|
|
|
|
/// Scan the protocol xml at the given path.
|
|
pub fn addCustomProtocol(scanner: *Scanner, path: []const u8) void {
|
|
scanner.run.addArg("-i");
|
|
scanner.run.addFileArg(.{ .path = path });
|
|
|
|
scanner.generateCSource(path);
|
|
}
|
|
|
|
/// Generate code for the given global interface at the given version,
|
|
/// as well as all interfaces that can be created using it at that version.
|
|
/// If the version found in the protocol xml is less than the requested version,
|
|
/// an error will be printed and code generation will fail.
|
|
/// Code is always generated for wl_display, wl_registry, wl_callback, and wl_buffer.
|
|
pub fn generate(scanner: *Scanner, global_interface: []const u8, version: u32) void {
|
|
var buffer: [32]u8 = undefined;
|
|
const version_str = std.fmt.bufPrint(&buffer, "{}", .{version}) catch unreachable;
|
|
|
|
scanner.run.addArgs(&.{ "-g", global_interface, version_str });
|
|
}
|
|
|
|
/// Generate and add the necessary C source to the compilation unit.
|
|
/// Once https://github.com/ziglang/zig/issues/131 is resolved we can remove this.
|
|
pub fn addCSource(scanner: *Scanner, compile: *Build.Step.Compile) void {
|
|
const b = scanner.run.step.owner;
|
|
|
|
for (scanner.c_sources.items) |c_source| {
|
|
compile.addCSourceFile(.{
|
|
.file = c_source,
|
|
.flags = &.{ "-std=c99", "-O2" },
|
|
});
|
|
}
|
|
|
|
scanner.compiles.append(b.allocator, compile) catch @panic("OOM");
|
|
}
|
|
|
|
/// Once https://github.com/ziglang/zig/issues/131 is resolved we can remove this.
|
|
fn generateCSource(scanner: *Scanner, protocol: []const u8) void {
|
|
const b = scanner.run.step.owner;
|
|
const cmd = b.addSystemCommand(&.{ "wayland-scanner", "private-code", protocol });
|
|
|
|
const out_name = mem.concat(b.allocator, u8, &.{ fs.path.stem(protocol), "-protocol.c" }) catch @panic("OOM");
|
|
|
|
const c_source = cmd.addOutputFileArg(out_name);
|
|
|
|
for (scanner.compiles.items) |compile| {
|
|
compile.addCSourceFile(.{
|
|
.file = c_source,
|
|
.flags = &.{ "-std=c99", "-O2" },
|
|
});
|
|
}
|
|
|
|
scanner.c_sources.append(b.allocator, c_source) catch @panic("OOM");
|
|
}
|
|
};
|