mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-14 11:35:48 +00:00
build: emit xcframework for libghostty-vt on macOS
On Darwin targets, the build now automatically produces a universal (arm64 + x86_64) XCFramework at lib/ghostty-vt.xcframework under the install prefix. This bundles the fat static library with headers so consumers using Xcode or Swift PM can link libghostty-vt directly.
This commit is contained in:
12
build.zig
12
build.zig
@@ -152,6 +152,18 @@ pub fn build(b: *std.Build) !void {
|
||||
).step);
|
||||
}
|
||||
|
||||
// libghostty-vt xcframework (Apple only, universal binary)
|
||||
if (config.target.result.os.tag.isDarwin()) {
|
||||
const universal = try buildpkg.GhosttyLibVt.initStaticAppleUniversal(
|
||||
b,
|
||||
&config,
|
||||
&deps,
|
||||
&mod,
|
||||
);
|
||||
const xcframework = universal.xcframework();
|
||||
b.getInstallStep().dependOn(xcframework.step);
|
||||
}
|
||||
|
||||
// Helpgen
|
||||
if (config.emit_helpgen) deps.help_strings.install();
|
||||
|
||||
|
||||
@@ -4,9 +4,12 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const RunStep = std.Build.Step.Run;
|
||||
const Config = @import("Config.zig");
|
||||
const GhosttyZig = @import("GhosttyZig.zig");
|
||||
const LibtoolStep = @import("LibtoolStep.zig");
|
||||
const LipoStep = @import("LipoStep.zig");
|
||||
const SharedDeps = @import("SharedDeps.zig");
|
||||
const XCFrameworkStep = @import("XCFrameworkStep.zig");
|
||||
|
||||
/// The step that generates the file.
|
||||
step: *std.Build.Step,
|
||||
@@ -99,6 +102,45 @@ pub fn initShared(
|
||||
return initLib(b, zig, .dynamic);
|
||||
}
|
||||
|
||||
/// Build a macOS universal (arm64 + x86_64) static library using lipo.
|
||||
pub fn initStaticAppleUniversal(
|
||||
b: *std.Build,
|
||||
cfg: *const Config,
|
||||
deps: *const SharedDeps,
|
||||
zig: *const GhosttyZig,
|
||||
) !GhosttyLibVt {
|
||||
const aarch64_zig = try zig.retarget(
|
||||
b,
|
||||
cfg,
|
||||
deps,
|
||||
Config.genericMacOSTarget(b, .aarch64),
|
||||
);
|
||||
const x86_64_zig = try zig.retarget(
|
||||
b,
|
||||
cfg,
|
||||
deps,
|
||||
Config.genericMacOSTarget(b, .x86_64),
|
||||
);
|
||||
|
||||
const aarch64 = try initStatic(b, &aarch64_zig);
|
||||
const x86_64 = try initStatic(b, &x86_64_zig);
|
||||
const universal = LipoStep.create(b, .{
|
||||
.name = "ghostty-vt",
|
||||
.out_name = "libghostty-vt.a",
|
||||
.input_a = aarch64.output,
|
||||
.input_b = x86_64.output,
|
||||
});
|
||||
|
||||
return .{
|
||||
.step = universal.step,
|
||||
.artifact = universal.step,
|
||||
.kind = .static,
|
||||
.output = universal.output,
|
||||
.dsym = null,
|
||||
.pkg_config = null,
|
||||
};
|
||||
}
|
||||
|
||||
fn initLib(
|
||||
b: *std.Build,
|
||||
zig: *const GhosttyZig,
|
||||
@@ -294,6 +336,23 @@ fn requiresPrivate(b: *std.Build) []const u8 {
|
||||
return "";
|
||||
}
|
||||
|
||||
/// Create an XCFramework bundle from the static library.
|
||||
pub fn xcframework(
|
||||
lib_vt: *const GhosttyLibVt,
|
||||
) *XCFrameworkStep {
|
||||
assert(lib_vt.kind == .static);
|
||||
const b = lib_vt.step.owner;
|
||||
return XCFrameworkStep.create(b, .{
|
||||
.name = "ghostty-vt",
|
||||
.out_path = b.pathJoin(&.{ b.install_prefix, "lib/ghostty-vt.xcframework" }),
|
||||
.libraries = &.{.{
|
||||
.library = lib_vt.output,
|
||||
.headers = b.path("include/ghostty"),
|
||||
.dsym = null,
|
||||
}},
|
||||
});
|
||||
}
|
||||
|
||||
pub fn install(
|
||||
self: *const GhosttyLibVt,
|
||||
step: *std.Build.Step,
|
||||
|
||||
@@ -24,6 +24,44 @@ pub fn init(
|
||||
b: *std.Build,
|
||||
cfg: *const Config,
|
||||
deps: *const SharedDeps,
|
||||
) !GhosttyZig {
|
||||
return initInner(b, cfg, deps, "ghostty-vt", "ghostty-vt-c");
|
||||
}
|
||||
|
||||
/// Create a new GhosttyZig with modules retargeted to a different
|
||||
/// architecture. Used to produce universal (fat) binaries on macOS.
|
||||
pub fn retarget(
|
||||
self: *const GhosttyZig,
|
||||
b: *std.Build,
|
||||
cfg: *const Config,
|
||||
deps: *const SharedDeps,
|
||||
target: std.Build.ResolvedTarget,
|
||||
) !GhosttyZig {
|
||||
_ = self;
|
||||
const retargeted_config = try b.allocator.create(Config);
|
||||
retargeted_config.* = cfg.*;
|
||||
retargeted_config.target = target;
|
||||
|
||||
const retargeted_deps = try b.allocator.create(SharedDeps);
|
||||
retargeted_deps.* = try deps.retarget(b, target);
|
||||
|
||||
// Use unique module names to avoid collisions with the original target.
|
||||
const arch_name = @tagName(target.result.cpu.arch);
|
||||
return initInner(
|
||||
b,
|
||||
retargeted_config,
|
||||
retargeted_deps,
|
||||
b.fmt("ghostty-vt-{s}", .{arch_name}),
|
||||
b.fmt("ghostty-vt-c-{s}", .{arch_name}),
|
||||
);
|
||||
}
|
||||
|
||||
fn initInner(
|
||||
b: *std.Build,
|
||||
cfg: *const Config,
|
||||
deps: *const SharedDeps,
|
||||
vt_name: []const u8,
|
||||
vt_c_name: []const u8,
|
||||
) !GhosttyZig {
|
||||
// Terminal module build options
|
||||
var vt_options = cfg.terminalOptions(.lib);
|
||||
@@ -37,7 +75,7 @@ pub fn init(
|
||||
|
||||
return .{
|
||||
.vt = try initVt(
|
||||
"ghostty-vt",
|
||||
vt_name,
|
||||
b,
|
||||
cfg,
|
||||
deps,
|
||||
@@ -46,7 +84,7 @@ pub fn init(
|
||||
),
|
||||
|
||||
.vt_c = try initVt(
|
||||
"ghostty-vt-c",
|
||||
vt_c_name,
|
||||
b,
|
||||
cfg,
|
||||
deps,
|
||||
|
||||
Reference in New Issue
Block a user