From 003d318fbf90b98e4ae3ae118841da8efcfd8cae Mon Sep 17 00:00:00 2001 From: ddidderr Date: Mon, 12 Oct 2026 19:29:26 +0200 Subject: [PATCH] build(macos): build the original Swift app against the Rust core Ghostty's macOS app stays the original, unchanged Swift app (agreed scope); it is wired to the Rust core instead of the Zig core. scripts/macos-swift-app.sh (`just macos-swift-app `) mirrors the Zig build's GhosttyXcodebuild.zig: 1. scripts/xcframework.sh builds the Rust libghostty (identical include/ghostty.h ABI) as /macos/GhosttyKit.xcframework, 2. `just install /zig-out` provides the resources the Xcode project bundles from ../zig-out/share (ghostty, terminfo, completions, man, locale, vim, nvim, bat), 3. xcodebuild -target Ghostty in a clean environment. macOS + Xcode only; DRY_RUN=1 previews the steps (verified on Linux). Test Plan: - DRY_RUN=1 scripts/macos-swift-app.sh ../ghostty - on macOS: just macos-swift-app ../ghostty && open the built app --- README.md | 16 +++++++++++ docs/rewrite/STATUS.md | 12 +++++---- justfile | 5 ++++ scripts/macos-swift-app.sh | 55 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100755 scripts/macos-swift-app.sh diff --git a/README.md b/README.md index c6a5a64..e1b997b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,22 @@ Windows test suites also run under Wine (`just test-windows-wine`), macOS has not been run natively. The Swift macOS app is not part of the port; it is a client of the libghostty C API. +### The macOS app (original Swift app on the Rust core) + +Ghostty's macOS app stays the original Swift app, unchanged. It is wired to +the Rust core instead of the Zig core: the Rust `libghostty` exports the +identical `include/ghostty.h` ABI. On a Mac with Xcode: + +```sh +just macos-swift-app ../ghostty # Release; or: just macos-swift-app ../ghostty Debug +``` + +This builds the Rust core as `GhosttyKit.xcframework` into +`/macos/`, installs the resources into `/zig-out/share` +(what the Xcode project bundles) and runs `xcodebuild`, mirroring +`zig build -Demit-macos-app`. Not runnable on this Linux machine +(`DRY_RUN=1` previews the steps). + ## Building and running Requirements: Rust (edition 2024), GTK ≥ 4.14, libadwaita ≥ 1.5, diff --git a/docs/rewrite/STATUS.md b/docs/rewrite/STATUS.md index 7c4ad9d..6f63dfa 100644 --- a/docs/rewrite/STATUS.md +++ b/docs/rewrite/STATUS.md @@ -109,11 +109,12 @@ Legend: ⬜ todo · 🟨 in progress · ✅ done (gate passed, committed) · ⚠ ## Phase 9 — macOS Swift app → Rust (AppKit via objc2; compile-checked) | WP | Scope | Owner | State | Notes | |---|---|---|---|---| -| MA1 | foundation: crate, app/AppDelegate, menu, Ghostty.App/Config wrappers, helpers, bundle script, design doc | sonnet | ✅ | compile-checked; MA2–MA5 on hold pending user decision | -| MA2 | Ghostty/ incl. Surface View (Metal layer, input, IME, DnD, a11y) | – | ⬜ | after MA1 | -| MA3 | Features/Terminal (windows, tabs, styles) + Splits | – | ⬜ | after MA1 | -| MA4 | QuickTerminal, Command Palette, Settings, About, Clipboard, Global Keybinds, Secure Input, Services, App Icon | – | ⬜ | after MA1 | -| MA5 | AppleScript, Update (Sparkle), App Intents (assess) | – | ⬜ | after MA1 | +| MA1 | foundation: crate, app/AppDelegate, menu, Ghostty.App/Config wrappers, helpers, bundle script, design doc | sonnet | ↩️ | reverted (cfded0e): user decision — keep the original Swift app, wire it to the Rust core | +| MSW | `just macos-swift-app`: original Swift app built against the Rust libghostty (xcframework + resources + xcodebuild) | opus | ✅ | macOS-only; dry-run verified here | +| MA2 | Ghostty/ incl. Surface View (Metal layer, input, IME, DnD, a11y) | – | ✖ | after MA1 | cancelled +| MA3 | Features/Terminal (windows, tabs, styles) + Splits | – | ✖ | after MA1 | cancelled +| MA4 | QuickTerminal, Command Palette, Settings, About, Clipboard, Global Keybinds, Secure Input, Services, App Icon | – | ✖ | after MA1 | cancelled +| MA5 | AppleScript, Update (Sparkle), App Intents (assess) | – | ✖ | after MA1 | cancelled ## Log - 2026-10-11: Phase 0 complete; Phase 1 launched. @@ -171,3 +172,4 @@ Legend: ⬜ todo · 🟨 in progress · ✅ done (gate passed, committed) · ⚠ - 2026-10-12: Stop-hook: live D-Bus/portal behaviour still unexercised → LIVE launched (private buses; user session untouched). - 2026-10-12: LIVE committed (3605 tests). Remaining unverifiable here: native macOS, native Windows (Wine-tested), IME (no input-method daemon installed). - 2026-10-12: Stop-hook: Swift macOS app is part of Ghostty 1.3.1 → Phase 9 (port to Rust/AppKit) started with MA1. +- 2026-10-12: User: Swift app was agreed out of scope; the /goal hook should not have overridden that. Phase 9 reverted; instead the original Swift app is wired to the Rust core (`just macos-swift-app`). diff --git a/justfile b/justfile index 9c9f677..9726433 100644 --- a/justfile +++ b/justfile @@ -306,3 +306,8 @@ visual-parity *scenarios: live-dbus *scenarios: scripts/live-dbus/build-rust.sh RUST_BIN="${RUST_BIN:-target/vp/production/ghostty}" scripts/live-dbus-test.sh {{scenarios}} + +# Build Ghostty's original Swift macOS app against the Rust core (macOS only; +# DRY_RUN=1 to preview). Example: just macos-swift-app ../ghostty +macos-swift-app src config="Release": + scripts/macos-swift-app.sh {{ src }} {{ config }} diff --git a/scripts/macos-swift-app.sh b/scripts/macos-swift-app.sh new file mode 100755 index 0000000..eb66792 --- /dev/null +++ b/scripts/macos-swift-app.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Build Ghostty's ORIGINAL Swift macOS app (unchanged) against the Rust core. +# +# Ghostty's Xcode project (/macos/Ghostty.xcodeproj) links +# `macos/GhosttyKit.xcframework` and bundles resources from `../zig-out/share` +# (see the Zig build's src/build/GhosttyXcodebuild.zig). The Rust libghostty +# exports the identical include/ghostty.h ABI, so this script produces both +# from the Rust workspace and then runs xcodebuild, exactly like +# `zig build -Demit-macos-app`: +# 1. scripts/xcframework.sh -> /macos/GhosttyKit.xcframework +# 2. `just install` -> /zig-out/share/{ghostty,terminfo,...} +# 3. xcodebuild -target Ghostty -configuration (clean env, like Zig) +# +# Usage: scripts/macos-swift-app.sh [Release|Debug|ReleaseLocal] +# Runs only on macOS (Xcode required). DRY_RUN=1 prints the commands instead. +set -euo pipefail + +cd "$(dirname "$0")/.." +src=${1:?usage: $0 [Release|Debug|ReleaseLocal]} +config=${2:-Release} +src=$(cd "$src" && pwd) +[ -d "$src/macos/Ghostty.xcodeproj" ] || { + echo "error: $src/macos/Ghostty.xcodeproj not found" >&2 + exit 1 +} + +run() { + if [ "${DRY_RUN:-}" = 1 ]; then + printf '+' + printf ' %q' "$@" + printf '\n' + else + "$@" + fi +} + +if [ "${DRY_RUN:-}" != 1 ] && [ "$(uname -s)" != Darwin ]; then + echo "error: building the macOS app requires macOS with Xcode (use DRY_RUN=1 to preview)" >&2 + exit 1 +fi + +# Debug configuration pairs with the dev profile (debug app id), like Zig. +profile=production +[ "$config" = Debug ] && profile=dev + +# 1. The Rust core as GhosttyKit.xcframework where the Xcode project expects it. +run scripts/xcframework.sh universal "$profile" "$src/macos/GhosttyKit.xcframework" + +# 2. Resources the Xcode project copies from ../zig-out/share. +run just install "$src/zig-out" + +# 3. xcodebuild with a clean environment (only PATH), as GhosttyXcodebuild.zig. +run env -i PATH="$PATH" sh -c "cd '$src/macos' && xcodebuild -target Ghostty -configuration '$config'" + +echo "Ghostty.app: $src/macos/build/$config/Ghostty.app"