mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-01 07:28:37 +00:00
build: use build options to configure terminal C ABI mode (#8945)
Fixes various issues: - C ABI detection was faulty, which caused some Zig programs to use the C ABI mode and some C programs not to. Let's be explicit. - Unit tests now tests C ABI mode. - Build binary no longer rebuilds on any terminal change (a regression). - Zig programs can choose to depend on the C ABI version of the terminal lib by using the `ghostty-vt-c` module.
This commit is contained in:
@@ -255,6 +255,15 @@ pub fn build(b: *std.Build) !void {
|
||||
});
|
||||
const mod_vt_test_run = b.addRunArtifact(mod_vt_test);
|
||||
test_lib_vt_step.dependOn(&mod_vt_test_run.step);
|
||||
|
||||
const mod_vt_c_test = b.addTest(.{
|
||||
.root_module = mod.vt_c,
|
||||
.target = config.target,
|
||||
.optimize = config.optimize,
|
||||
.filters = test_filters,
|
||||
});
|
||||
const mod_vt_c_test_run = b.addRunArtifact(mod_vt_c_test);
|
||||
test_lib_vt_step.dependOn(&mod_vt_c_test_run.step);
|
||||
}
|
||||
|
||||
// Tests
|
||||
|
@@ -498,6 +498,7 @@ pub fn terminalOptions(self: *const Config) TerminalBuildOptions {
|
||||
.artifact = .ghostty,
|
||||
.simd = self.simd,
|
||||
.oniguruma = true,
|
||||
.c_abi = false,
|
||||
.slow_runtime_safety = switch (self.optimize) {
|
||||
.Debug => true,
|
||||
.ReleaseSafe,
|
||||
|
@@ -26,7 +26,7 @@ pub fn initShared(
|
||||
const target = zig.vt.resolved_target.?;
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "ghostty-vt",
|
||||
.root_module = zig.vt,
|
||||
.root_module = zig.vt_c,
|
||||
});
|
||||
lib.installHeader(
|
||||
b.path("include/ghostty/vt.h"),
|
||||
|
@@ -5,18 +5,17 @@ const GhosttyZig = @This();
|
||||
const std = @import("std");
|
||||
const Config = @import("Config.zig");
|
||||
const SharedDeps = @import("SharedDeps.zig");
|
||||
const TerminalBuildOptions = @import("../terminal/build_options.zig").Options;
|
||||
|
||||
/// The `_c`-suffixed modules are built with the C ABI enabled.
|
||||
vt: *std.Build.Module,
|
||||
vt_c: *std.Build.Module,
|
||||
|
||||
pub fn init(
|
||||
b: *std.Build,
|
||||
cfg: *const Config,
|
||||
deps: *const SharedDeps,
|
||||
) !GhosttyZig {
|
||||
// General build options
|
||||
const general_options = b.addOptions();
|
||||
try cfg.addOptions(general_options);
|
||||
|
||||
// Terminal module build options
|
||||
var vt_options = cfg.terminalOptions();
|
||||
vt_options.artifact = .lib;
|
||||
@@ -25,7 +24,41 @@ pub fn init(
|
||||
// conditionally do this.
|
||||
vt_options.oniguruma = false;
|
||||
|
||||
const vt = b.addModule("ghostty-vt", .{
|
||||
return .{
|
||||
.vt = try initVt(
|
||||
"ghostty-vt",
|
||||
b,
|
||||
cfg,
|
||||
deps,
|
||||
vt_options,
|
||||
),
|
||||
|
||||
.vt_c = try initVt(
|
||||
"ghostty-vt-c",
|
||||
b,
|
||||
cfg,
|
||||
deps,
|
||||
options: {
|
||||
var dup = vt_options;
|
||||
dup.c_abi = true;
|
||||
break :options dup;
|
||||
},
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
fn initVt(
|
||||
name: []const u8,
|
||||
b: *std.Build,
|
||||
cfg: *const Config,
|
||||
deps: *const SharedDeps,
|
||||
vt_options: TerminalBuildOptions,
|
||||
) !*std.Build.Module {
|
||||
// General build options
|
||||
const general_options = b.addOptions();
|
||||
try cfg.addOptions(general_options);
|
||||
|
||||
const vt = b.addModule(name, .{
|
||||
.root_source_file = b.path("src/lib_vt.zig"),
|
||||
.target = cfg.target,
|
||||
.optimize = cfg.optimize,
|
||||
@@ -45,5 +78,5 @@ pub fn init(
|
||||
try SharedDeps.addSimd(b, vt, null);
|
||||
}
|
||||
|
||||
return .{ .vt = vt };
|
||||
return vt;
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
//! by thousands of users for years. However, the API itself (functions,
|
||||
//! types, etc.) may change without warning. We're working on stabilizing
|
||||
//! this in the future.
|
||||
const lib = @This();
|
||||
|
||||
// The public API below reproduces a lot of terminal/main.zig but
|
||||
// is separate because (1) we need our root file to be in `src/`
|
||||
@@ -68,7 +69,7 @@ pub const Attribute = terminal.Attribute;
|
||||
comptime {
|
||||
// If we're building the C library (vs. the Zig module) then
|
||||
// we want to reference the C API so that it gets exported.
|
||||
if (terminal.is_c_lib) {
|
||||
if (@import("root") == lib) {
|
||||
const c = terminal.c_api;
|
||||
@export(&c.osc_new, .{ .name = "ghostty_osc_new" });
|
||||
@export(&c.osc_free, .{ .name = "ghostty_osc_free" });
|
||||
@@ -81,8 +82,8 @@ comptime {
|
||||
|
||||
test {
|
||||
_ = terminal;
|
||||
|
||||
// Tests always test the C API and shared C functions
|
||||
_ = terminal.c_api;
|
||||
_ = @import("lib/main.zig");
|
||||
if (comptime terminal.options.c_abi) {
|
||||
_ = terminal.c_api;
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
/// True if we're building the C library libghostty-vt.
|
||||
pub const is_c_lib = @import("root") == @import("../lib_vt.zig");
|
||||
|
||||
/// Options set by Zig build.zig and exposed via `terminal_options`.
|
||||
pub const Options = struct {
|
||||
/// The target artifact to build. This will gate some functionality.
|
||||
artifact: Artifact,
|
||||
@@ -26,6 +24,10 @@ pub const Options = struct {
|
||||
/// generally be disabled in production builds.
|
||||
slow_runtime_safety: bool,
|
||||
|
||||
/// Force C ABI mode on or off. If not set, then it will be set based on
|
||||
/// Options.
|
||||
c_abi: bool,
|
||||
|
||||
/// Add the required build options for the terminal module.
|
||||
pub fn add(
|
||||
self: Options,
|
||||
@@ -34,6 +36,7 @@ pub const Options = struct {
|
||||
) void {
|
||||
const opts = b.addOptions();
|
||||
opts.addOption(Artifact, "artifact", self.artifact);
|
||||
opts.addOption(bool, "c_abi", self.c_abi);
|
||||
opts.addOption(bool, "oniguruma", self.oniguruma);
|
||||
opts.addOption(bool, "simd", self.simd);
|
||||
opts.addOption(bool, "slow_runtime_safety", self.slow_runtime_safety);
|
||||
|
@@ -73,9 +73,9 @@ test "command type" {
|
||||
));
|
||||
defer free(p);
|
||||
|
||||
p.next('0');
|
||||
p.next(';');
|
||||
p.next('a');
|
||||
const cmd = p.end(0);
|
||||
next(p, '0');
|
||||
next(p, ';');
|
||||
next(p, 'a');
|
||||
const cmd = end(p, 0);
|
||||
try testing.expectEqual(.change_window_title, commandType(cmd));
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const build_options = @import("terminal_options");
|
||||
|
||||
const charsets = @import("charsets.zig");
|
||||
const sanitize = @import("sanitize.zig");
|
||||
@@ -21,7 +20,7 @@ pub const page = @import("page.zig");
|
||||
pub const parse_table = @import("parse_table.zig");
|
||||
pub const search = @import("search.zig");
|
||||
pub const size = @import("size.zig");
|
||||
pub const tmux = if (build_options.tmux_control_mode) @import("tmux.zig") else struct {};
|
||||
pub const tmux = if (options.tmux_control_mode) @import("tmux.zig") else struct {};
|
||||
pub const x11_color = @import("x11_color.zig");
|
||||
|
||||
pub const Charset = charsets.Charset;
|
||||
@@ -62,9 +61,11 @@ pub const Attribute = sgr.Attribute;
|
||||
|
||||
pub const isSafePaste = sanitize.isSafePaste;
|
||||
|
||||
pub const Options = @import("build_options.zig").Options;
|
||||
pub const options = @import("terminal_options");
|
||||
|
||||
/// This is set to true when we're building the C library.
|
||||
pub const is_c_lib = @import("build_options.zig").is_c_lib;
|
||||
pub const c_api = if (is_c_lib) @import("c/main.zig") else void;
|
||||
pub const c_api = if (options.c_abi) @import("c/main.zig") else void;
|
||||
|
||||
test {
|
||||
@import("std").testing.refAllDecls(@This());
|
||||
|
@@ -7,11 +7,11 @@ const osc = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const build_options = @import("terminal_options");
|
||||
const mem = std.mem;
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = mem.Allocator;
|
||||
const LibEnum = @import("../lib/enum.zig").Enum;
|
||||
const is_c_lib = @import("build_options.zig").is_c_lib;
|
||||
const RGB = @import("color.zig").RGB;
|
||||
const kitty_color = @import("kitty/color.zig");
|
||||
const osc_color = @import("osc/color.zig");
|
||||
@@ -175,7 +175,7 @@ pub const Command = union(Key) {
|
||||
conemu_guimacro: []const u8,
|
||||
|
||||
pub const Key = LibEnum(
|
||||
if (is_c_lib) .c else .zig,
|
||||
if (build_options.c_abi) .c else .zig,
|
||||
// NOTE: Order matters, see LibEnum documentation.
|
||||
&.{
|
||||
"invalid",
|
||||
|
Reference in New Issue
Block a user