mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-14 03:25:50 +00:00
libghostty: build universal xcframework and release it on tip (#12149)
This produces a `ghostty-vt.xcframework` for `zig build -Demit-lib-vt`
when the host is macOS and the target is Apple platforms. Our CI has
been updated to release this via tip channels (GH releases and our blob
storage), too.
The xcframework contains binaries for macOS Universal (x86_64 +
aarch64), iOS, and iOS simulator.
I've added a Swift example we run in CI to verify this works. Users can
also drag and drop the XCFramework directly into Xcode.
## Example
```swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "swift-vt-xcframework",
platforms: [.macOS(.v13)],
targets: [
.executableTarget(
name: "swift-vt-xcframework",
dependencies: ["GhosttyVt"],
path: "Sources",
linkerSettings: [
.linkedLibrary("c++"),
]
),
.binaryTarget(
name: "GhosttyVt",
path: "../../zig-out/lib/ghostty-vt.xcframework"
),
]
)
```
```swift
import GhosttyVt
// Create a terminal with a small grid
var terminal: GhosttyTerminal?
var opts = GhosttyTerminalOptions(
cols: 80,
rows: 24,
max_scrollback: 0
)
let result = ghostty_terminal_new(nil, &terminal, opts)
guard result == GHOSTTY_SUCCESS, let terminal else {
fatalError("Failed to create terminal")
}
// Write some VT-encoded content
let text = "Hello from \u{1b}[1mSwift\u{1b}[0m via xcframework!\r\n"
text.withCString { ptr in
ghostty_terminal_vt_write(terminal, ptr, strlen(ptr))
}
// Format the terminal contents as plain text
var fmtOpts = GhosttyFormatterTerminalOptions()
fmtOpts.size = MemoryLayout<GhosttyFormatterTerminalOptions>.size
fmtOpts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN
fmtOpts.trim = true
var formatter: GhosttyFormatter?
let fmtResult = ghostty_formatter_terminal_new(nil, &formatter, terminal, fmtOpts)
guard fmtResult == GHOSTTY_SUCCESS, let formatter else {
fatalError("Failed to create formatter")
}
var buf: UnsafeMutablePointer<UInt8>?
var len: Int = 0
let allocResult = ghostty_formatter_format_alloc(formatter, nil, &buf, &len)
guard allocResult == GHOSTTY_SUCCESS, let buf else {
fatalError("Failed to format")
}
print("Plain text (\(len) bytes):")
print(String(cString: buf))
ghostty_free(nil, buf, len)
ghostty_formatter_free(formatter)
ghostty_terminal_free(terminal)
```
This commit is contained in:
105
.github/workflows/release-tip.yml
vendored
105
.github/workflows/release-tip.yml
vendored
@@ -219,6 +219,7 @@ jobs:
|
||||
)
|
||||
runs-on: namespace-profile-ghostty-sm
|
||||
env:
|
||||
GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }}
|
||||
ZIG_LOCAL_CACHE_DIR: /zig/local-cache
|
||||
ZIG_GLOBAL_CACHE_DIR: /zig/global-cache
|
||||
steps:
|
||||
@@ -260,6 +261,110 @@ jobs:
|
||||
libghostty-vt-source.tar.gz.minisig
|
||||
token: ${{ secrets.GH_RELEASE_TOKEN }}
|
||||
|
||||
- name: Prep R2 Storage
|
||||
run: |
|
||||
mkdir -p blob/${GHOSTTY_COMMIT_LONG}
|
||||
cp libghostty-vt-source.tar.gz blob/${GHOSTTY_COMMIT_LONG}/libghostty-vt-source.tar.gz
|
||||
- name: Upload to R2
|
||||
uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c # v1.4
|
||||
with:
|
||||
r2-account-id: ${{ secrets.CF_R2_TIP_ACCOUNT_ID }}
|
||||
r2-access-key-id: ${{ secrets.CF_R2_TIP_AWS_KEY }}
|
||||
r2-secret-access-key: ${{ secrets.CF_R2_TIP_SECRET_KEY }}
|
||||
r2-bucket: ghostty-tip
|
||||
source-dir: blob
|
||||
destination-dir: ./
|
||||
|
||||
- name: Echo Release URLs
|
||||
run: |
|
||||
echo "Release URLs:"
|
||||
echo " Source Tarball: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/libghostty-vt-source.tar.gz"
|
||||
|
||||
build-lib-vt-xcframework:
|
||||
needs: [setup]
|
||||
if: |
|
||||
needs.setup.outputs.should_skip != 'true' &&
|
||||
(
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(
|
||||
github.repository_owner == 'ghostty-org' &&
|
||||
github.ref_name == 'main'
|
||||
)
|
||||
)
|
||||
runs-on: namespace-profile-ghostty-macos-tahoe
|
||||
env:
|
||||
GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }}
|
||||
ZIG_LOCAL_CACHE_DIR: /Users/runner/zig/local-cache
|
||||
ZIG_GLOBAL_CACHE_DIR: /Users/runner/zig/global-cache
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Cache
|
||||
uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
|
||||
with:
|
||||
cache: |
|
||||
xcode
|
||||
path: |
|
||||
/Users/runner/zig
|
||||
|
||||
# TODO(tahoe): https://github.com/NixOS/nix/issues/13342
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Xcode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.3.app
|
||||
|
||||
- name: Build XCFramework
|
||||
run: nix develop -c zig build -Demit-lib-vt -Doptimize=ReleaseFast
|
||||
|
||||
- name: Zip XCFramework
|
||||
run: |
|
||||
cd zig-out/lib
|
||||
zip -9 -r ../../ghostty-vt.xcframework.zip ghostty-vt.xcframework
|
||||
|
||||
- name: Sign XCFramework
|
||||
run: |
|
||||
echo -n "${{ secrets.MINISIGN_KEY }}" > minisign.key
|
||||
echo -n "${{ secrets.MINISIGN_PASSWORD }}" > minisign.password
|
||||
nix develop -c minisign -S -m ghostty-vt.xcframework.zip -s minisign.key < minisign.password
|
||||
|
||||
- name: Update Release
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
name: 'Ghostty Tip ("Nightly")'
|
||||
prerelease: true
|
||||
tag_name: tip
|
||||
target_commitish: ${{ github.sha }}
|
||||
files: |
|
||||
ghostty-vt.xcframework.zip
|
||||
ghostty-vt.xcframework.zip.minisig
|
||||
token: ${{ secrets.GH_RELEASE_TOKEN }}
|
||||
|
||||
- name: Prep R2 Storage
|
||||
run: |
|
||||
mkdir -p blob/${GHOSTTY_COMMIT_LONG}
|
||||
cp ghostty-vt.xcframework.zip blob/${GHOSTTY_COMMIT_LONG}/ghostty-vt.xcframework.zip
|
||||
- name: Upload to R2
|
||||
uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c # v1.4
|
||||
with:
|
||||
r2-account-id: ${{ secrets.CF_R2_TIP_ACCOUNT_ID }}
|
||||
r2-access-key-id: ${{ secrets.CF_R2_TIP_AWS_KEY }}
|
||||
r2-secret-access-key: ${{ secrets.CF_R2_TIP_SECRET_KEY }}
|
||||
r2-bucket: ghostty-tip
|
||||
source-dir: blob
|
||||
destination-dir: ./
|
||||
|
||||
- name: Echo Release URLs
|
||||
run: |
|
||||
echo "Release URLs:"
|
||||
echo " XCFramework: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/ghostty-vt.xcframework.zip"
|
||||
|
||||
build-macos:
|
||||
needs: [setup]
|
||||
if: |
|
||||
|
||||
48
.github/workflows/test.yml
vendored
48
.github/workflows/test.yml
vendored
@@ -89,6 +89,7 @@ jobs:
|
||||
- build-examples-zig
|
||||
- build-examples-cmake
|
||||
- build-examples-cmake-windows
|
||||
- build-examples-swift
|
||||
- build-cmake
|
||||
- build-flatpak
|
||||
- build-libghostty-vt
|
||||
@@ -181,6 +182,7 @@ jobs:
|
||||
outputs:
|
||||
zig: ${{ steps.list.outputs.zig }}
|
||||
cmake: ${{ steps.list.outputs.cmake }}
|
||||
swift: ${{ steps.list.outputs.swift }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
@@ -193,6 +195,9 @@ jobs:
|
||||
cmake=$(ls example/*/CMakeLists.txt 2>/dev/null | xargs -n1 dirname | xargs -n1 basename | jq -R -s -c 'split("\n") | map(select(. != ""))')
|
||||
echo "$cmake" | jq .
|
||||
echo "cmake=$cmake" >> "$GITHUB_OUTPUT"
|
||||
swift=$(ls example/*/Package.swift 2>/dev/null | xargs -n1 dirname | xargs -n1 basename | jq -R -s -c 'split("\n") | map(select(. != ""))')
|
||||
echo "$swift" | jq .
|
||||
echo "swift=$swift" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build-examples-zig:
|
||||
strategy:
|
||||
@@ -290,6 +295,49 @@ jobs:
|
||||
cmake -B build -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=${{ github.workspace }}
|
||||
cmake --build build
|
||||
|
||||
build-examples-swift:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dir: ${{ fromJSON(needs.list-examples.outputs.swift) }}
|
||||
name: Example ${{ matrix.dir }}
|
||||
runs-on: namespace-profile-ghostty-macos-tahoe
|
||||
needs: [test, list-examples]
|
||||
env:
|
||||
ZIG_LOCAL_CACHE_DIR: /Users/runner/zig/local-cache
|
||||
ZIG_GLOBAL_CACHE_DIR: /Users/runner/zig/global-cache
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Cache
|
||||
uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
|
||||
with:
|
||||
cache: |
|
||||
xcode
|
||||
path: |
|
||||
/Users/runner/zig
|
||||
|
||||
# TODO(tahoe): https://github.com/NixOS/nix/issues/13342
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
determinate: true
|
||||
- uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Xcode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.3.app
|
||||
|
||||
- name: Build XCFramework
|
||||
run: nix develop -c zig build -Demit-lib-vt
|
||||
|
||||
- name: Build and Run Example
|
||||
run: |
|
||||
cd example/${{ matrix.dir }}
|
||||
swift run
|
||||
|
||||
build-cmake:
|
||||
runs-on: namespace-profile-ghostty-sm
|
||||
needs: test
|
||||
|
||||
14
build.zig
14
build.zig
@@ -152,6 +152,20 @@ pub fn build(b: *std.Build) !void {
|
||||
).step);
|
||||
}
|
||||
|
||||
// libghostty-vt xcframework (Apple only, universal binary).
|
||||
// Only when building on macOS (not cross-compiling) since
|
||||
// xcodebuild is required.
|
||||
if (builtin.os.tag.isDarwin() and config.target.result.os.tag.isDarwin()) {
|
||||
const apple_libs = try buildpkg.GhosttyLibVt.initStaticAppleUniversal(
|
||||
b,
|
||||
&config,
|
||||
&deps,
|
||||
&mod,
|
||||
);
|
||||
const xcframework = buildpkg.GhosttyLibVt.xcframework(&apple_libs, b);
|
||||
b.getInstallStep().dependOn(xcframework.step);
|
||||
}
|
||||
|
||||
// Helpgen
|
||||
if (config.emit_helpgen) deps.help_strings.install();
|
||||
|
||||
|
||||
1
example/.gitignore
vendored
1
example/.gitignore
vendored
@@ -3,3 +3,4 @@ dist/
|
||||
node_modules/
|
||||
example.wasm*
|
||||
build/
|
||||
.build/
|
||||
|
||||
21
example/swift-vt-xcframework/Package.swift
Normal file
21
example/swift-vt-xcframework/Package.swift
Normal file
@@ -0,0 +1,21 @@
|
||||
// swift-tools-version: 5.9
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "swift-vt-xcframework",
|
||||
platforms: [.macOS(.v13)],
|
||||
targets: [
|
||||
.executableTarget(
|
||||
name: "swift-vt-xcframework",
|
||||
dependencies: ["GhosttyVt"],
|
||||
path: "Sources",
|
||||
linkerSettings: [
|
||||
.linkedLibrary("c++"),
|
||||
]
|
||||
),
|
||||
.binaryTarget(
|
||||
name: "GhosttyVt",
|
||||
path: "../../zig-out/lib/ghostty-vt.xcframework"
|
||||
),
|
||||
]
|
||||
)
|
||||
23
example/swift-vt-xcframework/README.md
Normal file
23
example/swift-vt-xcframework/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# swift-vt-xcframework
|
||||
|
||||
Demonstrates consuming libghostty-vt from a Swift Package using the
|
||||
pre-built XCFramework. Creates a terminal, writes VT sequences into it,
|
||||
and formats the screen contents as plain text.
|
||||
|
||||
This example requires the XCFramework to be built first.
|
||||
|
||||
## Building
|
||||
|
||||
First, build the XCFramework from the repository root:
|
||||
|
||||
```shell-session
|
||||
zig build -Demit-lib-vt
|
||||
```
|
||||
|
||||
Then build and run the Swift package:
|
||||
|
||||
```shell-session
|
||||
cd example/swift-vt-xcframework
|
||||
swift build
|
||||
swift run
|
||||
```
|
||||
47
example/swift-vt-xcframework/Sources/main.swift
Normal file
47
example/swift-vt-xcframework/Sources/main.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
import Foundation
|
||||
import GhosttyVt
|
||||
|
||||
// Create a terminal with a small grid
|
||||
var terminal: GhosttyTerminal?
|
||||
var opts = GhosttyTerminalOptions(
|
||||
cols: 80,
|
||||
rows: 24,
|
||||
max_scrollback: 0
|
||||
)
|
||||
let result = ghostty_terminal_new(nil, &terminal, opts)
|
||||
guard result == GHOSTTY_SUCCESS, let terminal else {
|
||||
fatalError("Failed to create terminal")
|
||||
}
|
||||
|
||||
// Write some VT-encoded content
|
||||
let text = "Hello from \u{1b}[1mSwift\u{1b}[0m via xcframework!\r\n"
|
||||
text.withCString { ptr in
|
||||
ghostty_terminal_vt_write(terminal, ptr, strlen(ptr))
|
||||
}
|
||||
|
||||
// Format the terminal contents as plain text
|
||||
var fmtOpts = GhosttyFormatterTerminalOptions()
|
||||
fmtOpts.size = MemoryLayout<GhosttyFormatterTerminalOptions>.size
|
||||
fmtOpts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN
|
||||
fmtOpts.trim = true
|
||||
|
||||
var formatter: GhosttyFormatter?
|
||||
let fmtResult = ghostty_formatter_terminal_new(nil, &formatter, terminal, fmtOpts)
|
||||
guard fmtResult == GHOSTTY_SUCCESS, let formatter else {
|
||||
fatalError("Failed to create formatter")
|
||||
}
|
||||
|
||||
var buf: UnsafeMutablePointer<UInt8>?
|
||||
var len: Int = 0
|
||||
let allocResult = ghostty_formatter_format_alloc(formatter, nil, &buf, &len)
|
||||
guard allocResult == GHOSTTY_SUCCESS, let buf else {
|
||||
fatalError("Failed to format")
|
||||
}
|
||||
|
||||
print("Plain text (\(len) bytes):")
|
||||
let data = Data(bytes: buf, count: len)
|
||||
print(String(data: data, encoding: .utf8) ?? "<invalid UTF-8>")
|
||||
|
||||
ghostty_free(nil, buf, len)
|
||||
ghostty_formatter_free(formatter)
|
||||
ghostty_terminal_free(terminal)
|
||||
@@ -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,93 @@ pub fn initShared(
|
||||
return initLib(b, zig, .dynamic);
|
||||
}
|
||||
|
||||
/// Apple platform targets for xcframework slices.
|
||||
pub const ApplePlatform = enum {
|
||||
macos_universal,
|
||||
ios,
|
||||
ios_simulator,
|
||||
// tvOS, watchOS, and visionOS are not yet supported by Zig's
|
||||
// standard library (missing PATH_MAX, mcontext fields, etc.).
|
||||
|
||||
/// Platforms that have device + simulator pairs, gated on SDK detection.
|
||||
const sdk_platforms = [_]struct {
|
||||
os_tag: std.Target.Os.Tag,
|
||||
device: ApplePlatform,
|
||||
simulator: ApplePlatform,
|
||||
}{
|
||||
.{ .os_tag = .ios, .device = .ios, .simulator = .ios_simulator },
|
||||
};
|
||||
};
|
||||
|
||||
/// Static libraries for each Apple platform, keyed by `ApplePlatform`.
|
||||
pub const AppleLibs = std.EnumMap(ApplePlatform, GhosttyLibVt);
|
||||
|
||||
/// Build static libraries for all available Apple platforms.
|
||||
/// Always builds a macOS universal (arm64 + x86_64) fat binary.
|
||||
/// Additional platforms are included if their SDK is detected.
|
||||
pub fn initStaticAppleUniversal(
|
||||
b: *std.Build,
|
||||
cfg: *const Config,
|
||||
deps: *const SharedDeps,
|
||||
zig: *const GhosttyZig,
|
||||
) !AppleLibs {
|
||||
var result: AppleLibs = .{};
|
||||
|
||||
// macOS universal (arm64 + x86_64)
|
||||
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,
|
||||
});
|
||||
result.put(.macos_universal, .{
|
||||
.step = universal.step,
|
||||
.artifact = universal.step,
|
||||
.kind = .static,
|
||||
.output = universal.output,
|
||||
.dsym = null,
|
||||
.pkg_config = null,
|
||||
});
|
||||
|
||||
// Additional Apple platforms, each gated on SDK availability.
|
||||
for (ApplePlatform.sdk_platforms) |p| {
|
||||
const target_query: std.Target.Query = .{
|
||||
.cpu_arch = .aarch64,
|
||||
.os_tag = p.os_tag,
|
||||
.os_version_min = Config.osVersionMin(p.os_tag),
|
||||
};
|
||||
if (detectAppleSDK(b.resolveTargetQuery(target_query).result)) {
|
||||
const dev_zig = try zig.retarget(b, cfg, deps, b.resolveTargetQuery(target_query));
|
||||
result.put(p.device, try initStatic(b, &dev_zig));
|
||||
|
||||
const sim_zig = try zig.retarget(b, cfg, deps, b.resolveTargetQuery(.{
|
||||
.cpu_arch = .aarch64,
|
||||
.os_tag = p.os_tag,
|
||||
.os_version_min = Config.osVersionMin(p.os_tag),
|
||||
.abi = .simulator,
|
||||
.cpu_model = .{ .explicit = &std.Target.aarch64.cpu.apple_a17 },
|
||||
}));
|
||||
result.put(p.simulator, try initStatic(b, &sim_zig));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn initLib(
|
||||
b: *std.Build,
|
||||
zig: *const GhosttyZig,
|
||||
@@ -294,6 +384,59 @@ fn requiresPrivate(b: *std.Build) []const u8 {
|
||||
return "";
|
||||
}
|
||||
|
||||
/// Create an XCFramework bundle from Apple platform static libraries.
|
||||
pub fn xcframework(
|
||||
apple_libs: *const AppleLibs,
|
||||
b: *std.Build,
|
||||
) *XCFrameworkStep {
|
||||
// Generate a headers directory with a module map for Swift PM.
|
||||
// We can't use include/ directly because it contains a module map
|
||||
// for GhosttyKit (the macOS app library).
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.addCopyDirectory(
|
||||
b.path("include/ghostty"),
|
||||
"ghostty",
|
||||
.{ .include_extensions = &.{".h"} },
|
||||
);
|
||||
_ = wf.add("module.modulemap",
|
||||
\\module GhosttyVt {
|
||||
\\ umbrella header "ghostty/vt.h"
|
||||
\\ export *
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
const headers = wf.getDirectory();
|
||||
|
||||
var libraries: [AppleLibs.len]XCFrameworkStep.Library = undefined;
|
||||
var lib_count: usize = 0;
|
||||
for (std.enums.values(ApplePlatform)) |platform| {
|
||||
if (apple_libs.get(platform)) |lib| {
|
||||
libraries[lib_count] = .{
|
||||
.library = lib.output,
|
||||
.headers = headers,
|
||||
.dsym = null,
|
||||
};
|
||||
lib_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return XCFrameworkStep.create(b, .{
|
||||
.name = "ghostty-vt",
|
||||
.out_path = b.pathJoin(&.{ b.install_prefix, "lib/ghostty-vt.xcframework" }),
|
||||
.libraries = libraries[0..lib_count],
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns true if the Apple SDK for the given target is installed.
|
||||
fn detectAppleSDK(target: std.Target) bool {
|
||||
_ = std.zig.LibCInstallation.findNative(.{
|
||||
.allocator = std.heap.page_allocator,
|
||||
.target = &target,
|
||||
.verbose = false,
|
||||
}) catch return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
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