Files
ghostty/pkg/gtk4-layer-shell/build.zig
Chris Marchesi fe9cf6a266 build: fully transition away from cImport/addTranslateC
This migrates all remaining uses of cImport (and addTranslateC for good
measure) to using translate-c for C translation, ensuring that we are
ready for when cImport is removed from the language, and also that all
sources of C translation are using the same snapshot of the external
package (when can then be updated when we need to fix something).

A couple of notes:

* A few options have been added to support the new translations, namely
  the ability to link libraries (passed through to linkLibrary on the
  Translator side) and whether or not to initialize default values
  (looks like cImport did this without a way to control it, but
  translate-c does not do it by default).

* Using the new library linking option actually simplifies the process
  of translating a number of the C packages as we have been shipping the
  necessary headers for these packages already with the applicable
  libraries. For some of the more complex translation processes though,
  we still include the appropriate directories directly.
2026-09-15 11:01:24 -07:00

161 lines
5.4 KiB
Zig

const std = @import("std");
const translate_c = @import("translate_c");
const version = @import("build.zig.zon").version;
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Zig API
const module = b.addModule("gtk4-layer-shell", .{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const lib: union(enum) {
system,
static: *std.Build.Step.Compile,
} = if (b.systemIntegrationOption("gtk4-layer-shell", .{}))
.system
else
.{ .static = try buildLib(b, .{ .target = target, .optimize = optimize }) };
try translate_c.addImportToModule(b, "gtk4_layer_shell_c", module, .{
.source = .{ .includes = .{
.files = &.{.{ .path = "gtk4-layer-shell.h" }},
} },
.target = target,
.optimize = optimize,
.link_system_libs = if (lib == .system) &.{ "gtk4", "gtk4-layer-shell-0" } else &.{"gtk4"},
.link_libs = if (lib == .static) &.{lib.static} else &.{},
});
}
fn buildLib(b: *std.Build, options: anytype) !*std.Build.Step.Compile {
const lib_version = try std.SemanticVersion.parse(version);
const target = options.target;
const optimize = options.optimize;
// Shared library
const lib = b.addLibrary(.{
.name = "gtk4-layer-shell",
.linkage = .dynamic,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
}),
});
b.installArtifact(lib);
// GTK
lib.root_module.linkSystemLibrary("gtk4", .{
.preferred_link_mode = .dynamic,
.search_strategy = .mode_first,
});
// local deps (non-system layer-shell/wayland)
const deps = try LocalDeps.get(b) orelse return lib;
lib.root_module.addIncludePath(deps.upstream.path("include"));
lib.root_module.addIncludePath(deps.upstream.path("src"));
lib.root_module.addIncludePath(deps.client_header_directory);
for (deps.private_code_files) |source| {
lib.root_module.addCSourceFile(.{ .file = source });
}
lib.installHeadersDirectory(
deps.upstream.path("include"),
"",
.{ .include_extensions = &.{".h"} },
);
// Certain files relating to session lock were removed as we don't use them
const srcs: []const []const u8 = &.{
"gtk4-layer-shell.c",
"layer-surface.c",
"libwayland-shim.c",
"registry.c",
"stolen-from-libwayland.c",
"stubbed-surface.c",
"xdg-surface-server.c",
};
lib.root_module.addCSourceFiles(.{
.root = deps.upstream.path("src"),
.files = srcs,
.flags = &.{
b.fmt("-DGTK_LAYER_SHELL_MAJOR={}", .{lib_version.major}),
b.fmt("-DGTK_LAYER_SHELL_MINOR={}", .{lib_version.minor}),
b.fmt("-DGTK_LAYER_SHELL_MICRO={}", .{lib_version.patch}),
},
});
return lib;
}
const LocalDeps = struct {
var cached: ?LocalDeps = null;
upstream: *std.Build.Dependency,
wayland_protocols: *std.Build.Dependency,
client_header_directory: std.Build.LazyPath,
private_code_files: []std.Build.LazyPath,
fn init(b: *std.Build) !?LocalDeps {
var result: LocalDeps = .{
.upstream = b.lazyDependency("gtk4_layer_shell", .{}) orelse return null,
.wayland_protocols = b.lazyDependency("wayland_protocols", .{}) orelse return null,
.client_header_directory = undefined,
.private_code_files = &.{},
};
// Wayland headers and source files
{
const protocols = [_]struct { []const u8, std.Build.LazyPath }{
.{
"wlr-layer-shell-unstable-v1",
result.upstream.path("protocol/wlr-layer-shell-unstable-v1.xml"),
},
.{
"xdg-shell",
result.wayland_protocols.path("stable/xdg-shell/xdg-shell.xml"),
},
// Even though we don't use session lock, we still need its headers
.{
"ext-session-lock-v1",
result.wayland_protocols.path("staging/ext-session-lock/ext-session-lock-v1.xml"),
},
};
const wf = b.addWriteFiles();
const private_code_files = try b.allocator.alloc(std.Build.LazyPath, protocols.len);
for (protocols, 0..) |protocol, idx| {
const name, const xml = protocol;
const header_scanner = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
header_scanner.addFileArg(xml);
_ = wf.addCopyFile(
header_scanner.addOutputFileArg(name),
b.fmt("{s}-client.h", .{name}),
);
const source_scanner = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
source_scanner.addFileArg(xml);
const source = source_scanner.addOutputFileArg(b.fmt("{s}.c", .{name}));
private_code_files[idx] = source;
}
result.private_code_files = private_code_files;
result.client_header_directory = wf.getDirectory();
}
cached = result;
return result;
}
fn get(b: *std.Build) !?LocalDeps {
if (cached) |c| return c;
return init(b);
}
};