build: add static library target for libghostty-vt

Refactor GhosttyLibVt to support both shared and static library
builds via a shared initLib helper that accepts a LinkMode. The
shared and static entry points (initShared, initStatic) delegate
to this common path.

For static builds, compiler_rt and ubsan_rt are bundled to avoid
undefined symbol errors. Debug symbols (dsymutil) are skipped for
static libs since they are not linked. The install artifact uses
a "-static" suffix internally but installs as "libghostty-vt.a"
via a new installLib method. Wasm is excluded from static builds
since it has no meaningful static vs shared distinction.
This commit is contained in:
Mitchell Hashimoto
2026-03-21 14:33:09 -07:00
parent 1438a2fe4b
commit 8d6be5a3dd
7 changed files with 201 additions and 9 deletions

View File

@@ -0,0 +1,18 @@
# Example: `ghostty-vt` Static Linking
This contains a simple example of how to statically link the `ghostty-vt`
C library with a C program using the `ghostty-vt-static` artifact. It is
otherwise identical to the `c-vt` example.
This uses a `build.zig` and `Zig` to build the C program so that we
can reuse a lot of our build logic and depend directly on our source
tree, but Ghostty emits a standard C library that can be used with any
C tooling.
## Usage
Run the program:
```shell-session
zig build run
```

View File

@@ -0,0 +1,44 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const run_step = b.step("run", "Run the app");
const exe_mod = b.createModule(.{
.target = target,
.optimize = optimize,
});
exe_mod.addCSourceFiles(.{
.root = b.path("src"),
.files = &.{"main.c"},
});
// You'll want to use a lazy dependency here so that ghostty is only
// downloaded if you actually need it.
if (b.lazyDependency("ghostty", .{
// Setting simd to false will force a pure static build that
// doesn't even require libc, but it has a significant performance
// penalty. If your embedding app requires libc anyway, you should
// always keep simd enabled.
// .simd = false,
})) |dep| {
// Use "ghostty-vt-static" for static linking instead of
// "ghostty-vt" which provides a shared library.
exe_mod.linkLibrary(dep.artifact("ghostty-vt-static"));
}
// Exe
const exe = b.addExecutable(.{
.name = "c_vt_static",
.root_module = exe_mod,
});
b.installArtifact(exe);
// Run
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd.addArgs(args);
run_step.dependOn(&run_cmd.step);
}

View File

@@ -0,0 +1,24 @@
.{
.name = .c_vt_static,
.version = "0.0.0",
.fingerprint = 0xa592a9fdd5d87ed2,
.minimum_zig_version = "0.15.1",
.dependencies = .{
// Ghostty dependency. In reality, you'd probably use a URL-based
// dependency like the one showed (and commented out) below this one.
// We use a path dependency here for simplicity and to ensure our
// examples always test against the source they're bundled with.
.ghostty = .{ .path = "../../" },
// Example of what a URL-based dependency looks like:
// .ghostty = .{
// .url = "https://github.com/ghostty-org/ghostty/archive/COMMIT.tar.gz",
// .hash = "N-V-__8AAMVLTABmYkLqhZPLXnMl-KyN38R8UVYqGrxqO36s",
// },
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}

View File

@@ -0,0 +1,36 @@
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <ghostty/vt.h>
int main() {
GhosttyOscParser parser;
if (ghostty_osc_new(NULL, &parser) != GHOSTTY_SUCCESS) {
return 1;
}
// Setup change window title command to change the title to "hello"
ghostty_osc_next(parser, '0');
ghostty_osc_next(parser, ';');
const char *title = "hello";
for (size_t i = 0; i < strlen(title); i++) {
ghostty_osc_next(parser, title[i]);
}
// End parsing and get command
GhosttyOscCommand command = ghostty_osc_end(parser, 0);
// Get and print command type
GhosttyOscCommandType type = ghostty_osc_command_type(command);
printf("Command type: %d\n", type);
// Extract and print the title
if (ghostty_osc_command_data(command, GHOSTTY_OSC_DATA_CHANGE_WINDOW_TITLE_STR, &title)) {
printf("Extracted title: %s\n", title);
} else {
printf("Failed to extract title\n");
}
ghostty_osc_free(parser);
return 0;
}