diff --git a/build.zig b/build.zig index bf7221aad..a5e5407b6 100644 --- a/build.zig +++ b/build.zig @@ -29,15 +29,7 @@ pub fn build(b: *std.Build) !void { // If we aren't emitting docs we need to emit a placeholder so // our macOS xcodeproject builds since it expects the `share/man` // directory to exist to copy into the app bundle. - var wf = b.addWriteFiles(); - const path = "share/man/.placeholder"; - b.getInstallStep().dependOn(&b.addInstallFile( - wf.add( - path, - "emit-docs not true so no man pages", - ), - path, - ).step); + docs.installDummy(b.getInstallStep()); } // Ghostty webdata @@ -155,6 +147,12 @@ pub fn build(b: *std.Build) !void { &xcframework_native, ); + // The app depends on the resources and i18n to be in the + // install directory too. + resources.addStepDependencies(&macos_app_native_only.build.step); + i18n.addStepDependencies(&macos_app_native_only.build.step); + docs.installDummy(&macos_app_native_only.build.step); + const run_step = b.step("run", "Run the app"); run_step.dependOn(&macos_app_native_only.open.step); } diff --git a/src/build/GhosttyDocs.zig b/src/build/GhosttyDocs.zig index 4b5dbfd92..b95b56f74 100644 --- a/src/build/GhosttyDocs.zig +++ b/src/build/GhosttyDocs.zig @@ -93,5 +93,32 @@ pub fn init( pub fn install(self: *const GhosttyDocs) void { const b = self.steps[0].owner; - for (self.steps) |step| b.getInstallStep().dependOn(step); + self.addStepDependencies(b.getInstallStep()); +} + +pub fn addStepDependencies( + self: *const GhosttyDocs, + other_step: *std.Build.Step, +) void { + for (self.steps) |step| other_step.dependOn(step); +} + +/// Installs some dummy files to satisfy the folder structure of docs +/// without actually generating any documentation. This is useful +/// when the `emit-docs` option is not set to true, but we still +/// need the rough directory structure to exist, such as for the macOS +/// app. +pub fn installDummy(self: *const GhosttyDocs, step: *std.Build.Step) void { + _ = self; + + const b = step.owner; + var wf = b.addWriteFiles(); + const path = "share/man/.placeholder"; + step.dependOn(&b.addInstallFile( + wf.add( + path, + "emit-docs not true so no man pages", + ), + path, + ).step); } diff --git a/src/build/GhosttyI18n.zig b/src/build/GhosttyI18n.zig index e0f6b5611..7667d30c3 100644 --- a/src/build/GhosttyI18n.zig +++ b/src/build/GhosttyI18n.zig @@ -50,7 +50,14 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyI18n { } pub fn install(self: *const GhosttyI18n) void { - for (self.steps) |step| self.owner.getInstallStep().dependOn(step); + self.addStepDependencies(self.owner.getInstallStep()); +} + +pub fn addStepDependencies( + self: *const GhosttyI18n, + other_step: *std.Build.Step, +) void { + for (self.steps) |step| other_step.dependOn(step); } fn createUpdateStep(b: *std.Build) !*std.Build.Step { diff --git a/src/build/GhosttyResources.zig b/src/build/GhosttyResources.zig index 34b5e35f8..ef04b21fd 100644 --- a/src/build/GhosttyResources.zig +++ b/src/build/GhosttyResources.zig @@ -397,5 +397,12 @@ fn addLinuxAppResources( pub fn install(self: *const GhosttyResources) void { const b = self.steps[0].owner; - for (self.steps) |step| b.getInstallStep().dependOn(step); + self.addStepDependencies(b.getInstallStep()); +} + +pub fn addStepDependencies( + self: *const GhosttyResources, + other_step: *std.Build.Step, +) void { + for (self.steps) |step| other_step.dependOn(step); } diff --git a/src/build/GhosttyXcodebuild.zig b/src/build/GhosttyXcodebuild.zig index 87c060976..38596b474 100644 --- a/src/build/GhosttyXcodebuild.zig +++ b/src/build/GhosttyXcodebuild.zig @@ -6,8 +6,9 @@ const RunStep = std.Build.Step.Run; const Config = @import("Config.zig"); const XCFramework = @import("GhosttyXCFramework.zig"); -xcodebuild: *std.Build.Step.Run, +build: *std.Build.Step.Run, open: *std.Build.Step.Run, +copy: *std.Build.Step.Run, pub fn init( b: *std.Build, @@ -22,6 +23,8 @@ pub fn init( => "Release", }; + 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 @@ -74,13 +77,11 @@ pub fn init( const open = open: { const open = RunStep.create(b, "run Ghostty app"); open.has_side_effects = true; - open.cwd = b.path("macos"); - open.addArgs(&.{ - b.fmt( - "build/{s}/Ghostty.app/Contents/MacOS/ghostty", - .{xc_config}, - ), - }); + open.cwd = b.path(""); + open.addArgs(&.{b.fmt( + "{s}/Contents/MacOS/ghostty", + .{app_path}, + )}); // Open depends on the app open.step.dependOn(&build.step); @@ -105,13 +106,31 @@ pub fn init( 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 .{ - .xcodebuild = build, + .build = build, .open = open, + .copy = copy, }; } pub fn install(self: *const Ghostty) void { - const b = self.xcodebuild.step.owner; - b.getInstallStep().dependOn(&self.xcodebuild.step); + 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); }