Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-ghosttykit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
export PATH="/usr/local/bin:$PATH"
zig version
fi
cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=universal -Doptimize=ReleaseFast
cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native -Doptimize=ReleaseFast

- name: Package xcframework
if: steps.check-release.outputs.exists == 'false'
Expand Down
18 changes: 13 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,16 @@ jobs:
fi
npm install --global "create-dmg@${CREATE_DMG_VERSION}"

- name: Download pre-built GhosttyKit.xcframework
- name: Cache GhosttyKit.xcframework
id: cache-ghosttykit-release
if: steps.guard_release_assets.outputs.skip_all != 'true'
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: GhosttyKit.xcframework
key: ghosttykit-v2-${{ hashFiles('.gitmodules', 'ghostty') }}

- name: Download pre-built GhosttyKit.xcframework
if: steps.guard_release_assets.outputs.skip_all != 'true' && steps.cache-ghosttykit-release.outputs.cache-hit != 'true'
run: |
./scripts/download-prebuilt-ghosttykit.sh

Expand Down Expand Up @@ -236,7 +244,7 @@ jobs:
xcodebuild -scheme programa -configuration Release -derivedDataPath build-universal \
-destination 'generic/platform=macOS' \
-clonedSourcePackagesDirPath .spm-cache \
ARCHS="arm64 x86_64" \
ARCHS="arm64" \
ONLY_ACTIVE_ARCH=NO \
CODE_SIGNING_ALLOWED=NO build

Expand All @@ -253,9 +261,9 @@ jobs:
echo "App binary architectures: $APP_ARCHS"
echo "CLI binary architectures: $CLI_ARCHS"
echo "Ghostty helper architectures: $HELPER_ARCHS"
[[ "$APP_ARCHS" == *arm64* && "$APP_ARCHS" == *x86_64* ]]
[[ "$CLI_ARCHS" == *arm64* && "$CLI_ARCHS" == *x86_64* ]]
[[ "$HELPER_ARCHS" == *arm64* && "$HELPER_ARCHS" == *x86_64* ]]
[[ "$APP_ARCHS" == "arm64" ]]
[[ "$CLI_ARCHS" == "arm64" ]]
[[ "$HELPER_ARCHS" == "arm64" ]]

- name: Build remote daemon release assets and inject manifest
if: steps.guard_release_assets.outputs.skip_all != 'true'
Expand Down
19 changes: 14 additions & 5 deletions scripts/ensure-ghosttykit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ else
echo "==> Building GhosttyKit.xcframework (this may take a few minutes)..."
(
cd ghostty
zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=universal -Doptimize=ReleaseFast
zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native -Doptimize=ReleaseFast
)
echo "$GHOSTTY_KEY" > "$LOCAL_KEY_STAMP"
echo "$GHOSTTY_SHA" > "$LEGACY_LOCAL_SHA_STAMP"
Expand All @@ -140,10 +140,19 @@ else
echo "==> Cached GhosttyKit.xcframework at $CACHE_XCFRAMEWORK"
fi

MACOS_ARCHIVE="$CACHE_XCFRAMEWORK/macos-arm64_x86_64/libghostty.a"
if [[ -f "$MACOS_ARCHIVE" ]]; then
# Xcode 26 can fail to resolve symbols from Ghostty's universal static archive
# until its ranlib index is refreshed after reuse or copy.
# The macos slice dir is named by its arch(s): macos-arm64 (native, arm64-only) or
# macos-arm64_x86_64 (universal) — match whichever exists. A non-matching glob leaves
# the literal pattern, which the -f guard rejects, so this is safe under `set -e`.
MACOS_ARCHIVE=""
for _macos_archive in "$CACHE_XCFRAMEWORK"/macos-*/libghostty.a; do
if [[ -f "$_macos_archive" ]]; then
MACOS_ARCHIVE="$_macos_archive"
break
fi
done
if [[ -n "$MACOS_ARCHIVE" ]]; then
# Xcode 26 can fail to resolve symbols from Ghostty's static archive until its
# ranlib index is refreshed after reuse or copy.
echo "==> Refreshing libghostty archive index..."
if ! command -v xcrun >/dev/null 2>&1; then
echo "error: xcrun is required to refresh libghostty archive index." >&2
Expand Down
33 changes: 28 additions & 5 deletions tests/test_ci_universal_release_settings.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
#!/usr/bin/env bash
# Regression test for universal GhosttyKit and Release build settings.
# Regression test for arm64-only GhosttyKit and Release build settings.
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"

for file in \
"$ROOT_DIR/.github/workflows/build-ghosttykit.yml" \
"$ROOT_DIR/scripts/setup.sh"
"$ROOT_DIR/scripts/ensure-ghosttykit.sh"
do
if ! grep -Fq -- '-Dxcframework-target=universal' "$file"; then
echo "FAIL: $file must build GhosttyKit with -Dxcframework-target=universal"
if ! grep -Fq -- '-Dxcframework-target=native' "$file"; then
echo "FAIL: $file must build GhosttyKit with -Dxcframework-target=native (arm64-only)"
exit 1
fi
if grep -Fq -- '-Dxcframework-target=universal' "$file"; then
echo "FAIL: $file must not build GhosttyKit as universal"
exit 1
fi
done

RELEASE_YML="$ROOT_DIR/.github/workflows/release.yml"

if ! grep -Fq 'ARCHS="arm64"' "$RELEASE_YML"; then
echo "FAIL: release.yml must build the Release app with ARCHS=\"arm64\" only"
exit 1
fi

if grep -Fq 'ARCHS="arm64 x86_64"' "$RELEASE_YML"; then
echo "FAIL: release.yml must not build the Release app as universal (arm64 x86_64)"
exit 1
fi

for var in APP_ARCHS CLI_ARCHS HELPER_ARCHS; do
if ! grep -Fq "[[ \"\$${var}\" == \"arm64\" ]]" "$RELEASE_YML"; then
echo "FAIL: release.yml must verify \$${var} is exactly arm64 (single-arch)"
exit 1
fi
done
Expand All @@ -25,4 +48,4 @@ if ! awk '
exit 1
fi

echo "PASS: GhosttyKit builds universal and Release configs disable ONLY_ACTIVE_ARCH"
echo "PASS: GhosttyKit builds arm64-only and Release configs build/verify arm64-only"
Loading