mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-14 11:35:48 +00:00
build: add GhosttyVt module map to xcframework and Swift example
The xcframework now generates its own headers directory with a GhosttyVt module map instead of reusing include/ directly, which contains the GhosttyKit module map for the macOS app. The generated directory copies the ghostty headers and adds a module.modulemap that exposes ghostty/vt.h as the umbrella header. A new swift-vt-xcframework example demonstrates consuming the xcframework from a Swift Package. It creates a terminal, writes VT sequences, and formats the output as plain text, verifying the full round-trip works with swift build and swift run.
This commit is contained in:
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
|
||||
```
|
||||
45
example/swift-vt-xcframework/Sources/main.swift
Normal file
45
example/swift-vt-xcframework/Sources/main.swift
Normal file
@@ -0,0 +1,45 @@
|
||||
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)
|
||||
@@ -342,12 +342,30 @@ pub fn xcframework(
|
||||
) *XCFrameworkStep {
|
||||
assert(lib_vt.kind == .static);
|
||||
const b = lib_vt.step.owner;
|
||||
|
||||
// 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 *
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
|
||||
return XCFrameworkStep.create(b, .{
|
||||
.name = "ghostty-vt",
|
||||
.out_path = b.pathJoin(&.{ b.install_prefix, "lib/ghostty-vt.xcframework" }),
|
||||
.libraries = &.{.{
|
||||
.library = lib_vt.output,
|
||||
.headers = b.path("include/ghostty"),
|
||||
.headers = wf.getDirectory(),
|
||||
.dsym = null,
|
||||
}},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user