mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-01 15:38:35 +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);
|
const mod_vt_test_run = b.addRunArtifact(mod_vt_test);
|
||||||
test_lib_vt_step.dependOn(&mod_vt_test_run.step);
|
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
|
// Tests
|
||||||
|
@@ -498,6 +498,7 @@ pub fn terminalOptions(self: *const Config) TerminalBuildOptions {
|
|||||||
.artifact = .ghostty,
|
.artifact = .ghostty,
|
||||||
.simd = self.simd,
|
.simd = self.simd,
|
||||||
.oniguruma = true,
|
.oniguruma = true,
|
||||||
|
.c_abi = false,
|
||||||
.slow_runtime_safety = switch (self.optimize) {
|
.slow_runtime_safety = switch (self.optimize) {
|
||||||
.Debug => true,
|
.Debug => true,
|
||||||
.ReleaseSafe,
|
.ReleaseSafe,
|
||||||
|
@@ -26,7 +26,7 @@ pub fn initShared(
|
|||||||
const target = zig.vt.resolved_target.?;
|
const target = zig.vt.resolved_target.?;
|
||||||
const lib = b.addSharedLibrary(.{
|
const lib = b.addSharedLibrary(.{
|
||||||
.name = "ghostty-vt",
|
.name = "ghostty-vt",
|
||||||
.root_module = zig.vt,
|
.root_module = zig.vt_c,
|
||||||
});
|
});
|
||||||
lib.installHeader(
|
lib.installHeader(
|
||||||
b.path("include/ghostty/vt.h"),
|
b.path("include/ghostty/vt.h"),
|
||||||
|
@@ -5,18 +5,17 @@ const GhosttyZig = @This();
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Config = @import("Config.zig");
|
const Config = @import("Config.zig");
|
||||||
const SharedDeps = @import("SharedDeps.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: *std.Build.Module,
|
||||||
|
vt_c: *std.Build.Module,
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
b: *std.Build,
|
b: *std.Build,
|
||||||
cfg: *const Config,
|
cfg: *const Config,
|
||||||
deps: *const SharedDeps,
|
deps: *const SharedDeps,
|
||||||
) !GhosttyZig {
|
) !GhosttyZig {
|
||||||
// General build options
|
|
||||||
const general_options = b.addOptions();
|
|
||||||
try cfg.addOptions(general_options);
|
|
||||||
|
|
||||||
// Terminal module build options
|
// Terminal module build options
|
||||||
var vt_options = cfg.terminalOptions();
|
var vt_options = cfg.terminalOptions();
|
||||||
vt_options.artifact = .lib;
|
vt_options.artifact = .lib;
|
||||||
@@ -25,7 +24,41 @@ pub fn init(
|
|||||||
// conditionally do this.
|
// conditionally do this.
|
||||||
vt_options.oniguruma = false;
|
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"),
|
.root_source_file = b.path("src/lib_vt.zig"),
|
||||||
.target = cfg.target,
|
.target = cfg.target,
|
||||||
.optimize = cfg.optimize,
|
.optimize = cfg.optimize,
|
||||||
@@ -45,5 +78,5 @@ pub fn init(
|
|||||||
try SharedDeps.addSimd(b, vt, null);
|
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,
|
//! by thousands of users for years. However, the API itself (functions,
|
||||||
//! types, etc.) may change without warning. We're working on stabilizing
|
//! types, etc.) may change without warning. We're working on stabilizing
|
||||||
//! this in the future.
|
//! this in the future.
|
||||||
|
const lib = @This();
|
||||||
|
|
||||||
// The public API below reproduces a lot of terminal/main.zig but
|
// 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/`
|
// is separate because (1) we need our root file to be in `src/`
|
||||||
@@ -68,7 +69,7 @@ pub const Attribute = terminal.Attribute;
|
|||||||
comptime {
|
comptime {
|
||||||
// If we're building the C library (vs. the Zig module) then
|
// If we're building the C library (vs. the Zig module) then
|
||||||
// we want to reference the C API so that it gets exported.
|
// 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;
|
const c = terminal.c_api;
|
||||||
@export(&c.osc_new, .{ .name = "ghostty_osc_new" });
|
@export(&c.osc_new, .{ .name = "ghostty_osc_new" });
|
||||||
@export(&c.osc_free, .{ .name = "ghostty_osc_free" });
|
@export(&c.osc_free, .{ .name = "ghostty_osc_free" });
|
||||||
@@ -81,8 +82,8 @@ comptime {
|
|||||||
|
|
||||||
test {
|
test {
|
||||||
_ = terminal;
|
_ = terminal;
|
||||||
|
|
||||||
// Tests always test the C API and shared C functions
|
|
||||||
_ = terminal.c_api;
|
|
||||||
_ = @import("lib/main.zig");
|
_ = @import("lib/main.zig");
|
||||||
|
if (comptime terminal.options.c_abi) {
|
||||||
|
_ = terminal.c_api;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
/// True if we're building the C library libghostty-vt.
|
/// Options set by Zig build.zig and exposed via `terminal_options`.
|
||||||
pub const is_c_lib = @import("root") == @import("../lib_vt.zig");
|
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
/// The target artifact to build. This will gate some functionality.
|
/// The target artifact to build. This will gate some functionality.
|
||||||
artifact: Artifact,
|
artifact: Artifact,
|
||||||
@@ -26,6 +24,10 @@ pub const Options = struct {
|
|||||||
/// generally be disabled in production builds.
|
/// generally be disabled in production builds.
|
||||||
slow_runtime_safety: bool,
|
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.
|
/// Add the required build options for the terminal module.
|
||||||
pub fn add(
|
pub fn add(
|
||||||
self: Options,
|
self: Options,
|
||||||
@@ -34,6 +36,7 @@ pub const Options = struct {
|
|||||||
) void {
|
) void {
|
||||||
const opts = b.addOptions();
|
const opts = b.addOptions();
|
||||||
opts.addOption(Artifact, "artifact", self.artifact);
|
opts.addOption(Artifact, "artifact", self.artifact);
|
||||||
|
opts.addOption(bool, "c_abi", self.c_abi);
|
||||||
opts.addOption(bool, "oniguruma", self.oniguruma);
|
opts.addOption(bool, "oniguruma", self.oniguruma);
|
||||||
opts.addOption(bool, "simd", self.simd);
|
opts.addOption(bool, "simd", self.simd);
|
||||||
opts.addOption(bool, "slow_runtime_safety", self.slow_runtime_safety);
|
opts.addOption(bool, "slow_runtime_safety", self.slow_runtime_safety);
|
||||||
|
@@ -73,9 +73,9 @@ test "command type" {
|
|||||||
));
|
));
|
||||||
defer free(p);
|
defer free(p);
|
||||||
|
|
||||||
p.next('0');
|
next(p, '0');
|
||||||
p.next(';');
|
next(p, ';');
|
||||||
p.next('a');
|
next(p, 'a');
|
||||||
const cmd = p.end(0);
|
const cmd = end(p, 0);
|
||||||
try testing.expectEqual(.change_window_title, commandType(cmd));
|
try testing.expectEqual(.change_window_title, commandType(cmd));
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const build_options = @import("terminal_options");
|
|
||||||
|
|
||||||
const charsets = @import("charsets.zig");
|
const charsets = @import("charsets.zig");
|
||||||
const sanitize = @import("sanitize.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 parse_table = @import("parse_table.zig");
|
||||||
pub const search = @import("search.zig");
|
pub const search = @import("search.zig");
|
||||||
pub const size = @import("size.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 x11_color = @import("x11_color.zig");
|
||||||
|
|
||||||
pub const Charset = charsets.Charset;
|
pub const Charset = charsets.Charset;
|
||||||
@@ -62,9 +61,11 @@ pub const Attribute = sgr.Attribute;
|
|||||||
|
|
||||||
pub const isSafePaste = sanitize.isSafePaste;
|
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.
|
/// 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 (options.c_abi) @import("c/main.zig") else void;
|
||||||
pub const c_api = if (is_c_lib) @import("c/main.zig") else void;
|
|
||||||
|
|
||||||
test {
|
test {
|
||||||
@import("std").testing.refAllDecls(@This());
|
@import("std").testing.refAllDecls(@This());
|
||||||
|
@@ -7,11 +7,11 @@ const osc = @This();
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
const build_options = @import("terminal_options");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
const LibEnum = @import("../lib/enum.zig").Enum;
|
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 RGB = @import("color.zig").RGB;
|
||||||
const kitty_color = @import("kitty/color.zig");
|
const kitty_color = @import("kitty/color.zig");
|
||||||
const osc_color = @import("osc/color.zig");
|
const osc_color = @import("osc/color.zig");
|
||||||
@@ -175,7 +175,7 @@ pub const Command = union(Key) {
|
|||||||
conemu_guimacro: []const u8,
|
conemu_guimacro: []const u8,
|
||||||
|
|
||||||
pub const Key = LibEnum(
|
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.
|
// NOTE: Order matters, see LibEnum documentation.
|
||||||
&.{
|
&.{
|
||||||
"invalid",
|
"invalid",
|
||||||
|
Reference in New Issue
Block a user