aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/build/GhosttyXcodebuild.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/build/GhosttyXcodebuild.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/build/GhosttyXcodebuild.zig')
-rw-r--r--vendor/libghostty-vt/src/build/GhosttyXcodebuild.zig203
1 files changed, 203 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/build/GhosttyXcodebuild.zig b/vendor/libghostty-vt/src/build/GhosttyXcodebuild.zig
new file mode 100644
index 00000000..81af994c
--- /dev/null
+++ b/vendor/libghostty-vt/src/build/GhosttyXcodebuild.zig
@@ -0,0 +1,203 @@
+const Ghostty = @This();
+
+const std = @import("std");
+const builtin = @import("builtin");
+const RunStep = std.Build.Step.Run;
+const Config = @import("Config.zig");
+const Docs = @import("GhosttyDocs.zig");
+const I18n = @import("GhosttyI18n.zig");
+const Resources = @import("GhosttyResources.zig");
+const XCFramework = @import("GhosttyXCFramework.zig");
+
+build: *std.Build.Step.Run,
+open: *std.Build.Step.Run,
+copy: *std.Build.Step.Run,
+xctest: *std.Build.Step.Run,
+
+pub const Deps = struct {
+ xcframework: *const XCFramework,
+ docs: *const Docs,
+ i18n: ?*const I18n,
+ resources: *const Resources,
+};
+
+pub fn init(
+ b: *std.Build,
+ config: *const Config,
+ deps: Deps,
+) !Ghostty {
+ const xc_config = switch (config.optimize) {
+ .Debug => "Debug",
+ .ReleaseSafe,
+ .ReleaseSmall,
+ .ReleaseFast,
+ => "ReleaseLocal",
+ };
+
+ const xc_arch: ?[]const u8 = switch (deps.xcframework.target) {
+ // Universal is our default target, so we don't have to
+ // add anything.
+ .universal => null,
+
+ // Native we need to override the architecture in the Xcode
+ // project with the -arch flag.
+ .native => switch (builtin.cpu.arch) {
+ .aarch64 => "arm64",
+ .x86_64 => "x86_64",
+ else => @panic("unsupported macOS arch"),
+ },
+ };
+
+ const env = try std.process.getEnvMap(b.allocator);
+ const app_path = b.fmt("macos/build/{s}/Ghostty.app", .{xc_config});
+
+ // Our step to build the Ghostty macOS app.
+ const build = build: {
+ // External environment variables can mess up xcodebuild, so
+ // we create a new empty environment.
+ const env_map = try b.allocator.create(std.process.EnvMap);
+ env_map.* = .init(b.allocator);
+ if (env.get("PATH")) |v| try env_map.put("PATH", v);
+
+ const step = RunStep.create(b, "xcodebuild");
+ step.has_side_effects = true;
+ step.cwd = b.path("macos");
+ step.env_map = env_map;
+ step.addArgs(&.{
+ "xcodebuild",
+ "-target",
+ "Ghostty",
+ "-configuration",
+ xc_config,
+ });
+
+ // If we have a specific architecture, we need to pass it
+ // to xcodebuild.
+ if (xc_arch) |arch| step.addArgs(&.{ "-arch", arch });
+
+ // We need the xcframework
+ deps.xcframework.addStepDependencies(&step.step);
+
+ // We also need all these resources because the xcode project
+ // references them via symlinks.
+ deps.resources.addStepDependencies(&step.step);
+ if (deps.i18n) |v| v.addStepDependencies(&step.step);
+ deps.docs.installDummy(&step.step);
+
+ // Expect success
+ step.expectExitCode(0);
+
+ break :build step;
+ };
+
+ const xctest = xctest: {
+ const env_map = try b.allocator.create(std.process.EnvMap);
+ env_map.* = .init(b.allocator);
+ if (env.get("PATH")) |v| try env_map.put("PATH", v);
+
+ const step = RunStep.create(b, "xcodebuild test");
+ step.has_side_effects = true;
+ step.cwd = b.path("macos");
+ step.env_map = env_map;
+ step.addArgs(&.{
+ "xcodebuild",
+ "test",
+ "-scheme",
+ "Ghostty",
+ "-skip-testing",
+ "GhosttyUITests",
+ });
+ if (xc_arch) |arch| step.addArgs(&.{ "-arch", arch });
+
+ // We need the xcframework
+ deps.xcframework.addStepDependencies(&step.step);
+
+ // We also need all these resources because the xcode project
+ // references them via symlinks.
+ deps.resources.addStepDependencies(&step.step);
+ if (deps.i18n) |v| v.addStepDependencies(&step.step);
+ deps.docs.installDummy(&step.step);
+
+ // Expect success
+ step.expectExitCode(0);
+
+ break :xctest step;
+ };
+
+ // Our step to open the resulting Ghostty app.
+ const open = open: {
+ const disable_save_state = RunStep.create(b, "disable save state");
+ disable_save_state.has_side_effects = true;
+ disable_save_state.addArgs(&.{
+ "/usr/libexec/PlistBuddy",
+ "-c",
+ // We'll have to change this to `Set` if we ever put this
+ // into our Info.plist.
+ "Add :NSQuitAlwaysKeepsWindows bool false",
+ b.fmt("{s}/Contents/Info.plist", .{app_path}),
+ });
+ disable_save_state.expectExitCode(0);
+ disable_save_state.step.dependOn(&build.step);
+
+ const open = RunStep.create(b, "run Ghostty app");
+ open.has_side_effects = true;
+ open.cwd = b.path("");
+ open.addArgs(&.{b.fmt(
+ "{s}/Contents/MacOS/ghostty",
+ .{app_path},
+ )});
+
+ // Open depends on the app
+ open.step.dependOn(&build.step);
+ open.step.dependOn(&disable_save_state.step);
+
+ // This overrides our default behavior and forces logs to show
+ // up on stderr (in addition to the centralized macOS log).
+ open.setEnvironmentVariable("GHOSTTY_LOG", "stderr,macos");
+
+ // Configure how we're launching
+ open.setEnvironmentVariable("GHOSTTY_MAC_LAUNCH_SOURCE", "zig_run");
+
+ if (b.args) |args| {
+ open.addArgs(args);
+ }
+
+ break :open open;
+ };
+
+ // Our step to copy the app bundle to the install path.
+ // We have to use `cp -R` because there are symlinks in the
+ // bundle.
+ const copy = copy: {
+ const step = RunStep.create(b, "copy app bundle");
+ step.addArgs(&.{ "cp", "-R" });
+ step.addFileArg(b.path(app_path));
+ step.addArg(b.fmt("{s}", .{b.install_path}));
+ step.step.dependOn(&build.step);
+ break :copy step;
+ };
+
+ return .{
+ .build = build,
+ .open = open,
+ .copy = copy,
+ .xctest = xctest,
+ };
+}
+
+pub fn install(self: *const Ghostty) void {
+ const b = self.copy.step.owner;
+ b.getInstallStep().dependOn(&self.copy.step);
+}
+
+pub fn installXcframework(self: *const Ghostty) void {
+ const b = self.build.step.owner;
+ b.getInstallStep().dependOn(&self.build.step);
+}
+
+pub fn addTestStepDependencies(
+ self: *const Ghostty,
+ other_step: *std.Build.Step,
+) void {
+ other_step.dependOn(&self.xctest.step);
+}