vt: add ghostty_build_info API for querying build configuration
Add a new C API function ghostty_build_info() that exposes compile-time build options to library consumers. This allows callers to query whether SIMD, Kitty graphics protocol, and tmux control mode support were enabled at build time.pull/11725/head
parent
a49747df52
commit
c3b7fd8477
|
|
@ -0,0 +1,17 @@
|
|||
# Example: `ghostty-vt` Build Info
|
||||
|
||||
This contains a simple example of how to use the `ghostty-vt` build info
|
||||
API to query compile-time build configuration.
|
||||
|
||||
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
|
||||
```
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
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| {
|
||||
exe_mod.linkLibrary(dep.artifact("ghostty-vt"));
|
||||
}
|
||||
|
||||
// Exe
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "c_vt_build_info",
|
||||
.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);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.{
|
||||
.name = .c_vt_build_info,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0xc6b57ed4f83fb16,
|
||||
.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",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include <stdio.h>
|
||||
#include <ghostty/vt.h>
|
||||
|
||||
//! [build-info-query]
|
||||
void query_build_info() {
|
||||
bool simd = false;
|
||||
bool kitty_graphics = false;
|
||||
bool tmux_control_mode = false;
|
||||
|
||||
ghostty_build_info(GHOSTTY_BUILD_INFO_SIMD, &simd);
|
||||
ghostty_build_info(GHOSTTY_BUILD_INFO_KITTY_GRAPHICS, &kitty_graphics);
|
||||
ghostty_build_info(GHOSTTY_BUILD_INFO_TMUX_CONTROL_MODE, &tmux_control_mode);
|
||||
|
||||
printf("SIMD: %s\n", simd ? "enabled" : "disabled");
|
||||
printf("Kitty graphics: %s\n", kitty_graphics ? "enabled" : "disabled");
|
||||
printf("Tmux control mode: %s\n", tmux_control_mode ? "enabled" : "disabled");
|
||||
}
|
||||
//! [build-info-query]
|
||||
|
||||
int main() {
|
||||
query_build_info();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
* - @ref osc "OSC Parser" - Parse OSC (Operating System Command) sequences
|
||||
* - @ref sgr "SGR Parser" - Parse SGR (Select Graphic Rendition) sequences
|
||||
* - @ref paste "Paste Utilities" - Validate paste data safety
|
||||
* - @ref build_info "Build Info" - Query compile-time build configuration
|
||||
* - @ref allocator "Memory Management" - Memory management and custom allocators
|
||||
* - @ref wasm "WebAssembly Utilities" - WebAssembly convenience functions
|
||||
*
|
||||
|
|
@ -45,6 +46,7 @@
|
|||
* @section examples_sec Examples
|
||||
*
|
||||
* Complete working examples:
|
||||
* - @ref c-vt-build-info/src/main.c - Build info query example
|
||||
* - @ref c-vt/src/main.c - OSC parser example
|
||||
* - @ref c-vt-encode-key/src/main.c - Key encoding example
|
||||
* - @ref c-vt-encode-mouse/src/main.c - Mouse encoding example
|
||||
|
|
@ -55,6 +57,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/** @example c-vt-build-info/src/main.c
|
||||
* This example demonstrates how to query compile-time build configuration
|
||||
* such as SIMD support, Kitty graphics, and tmux control mode availability.
|
||||
*/
|
||||
|
||||
/** @example c-vt/src/main.c
|
||||
* This example demonstrates how to use the OSC parser to parse an OSC sequence,
|
||||
* extract command information, and retrieve command-specific data like window titles.
|
||||
|
|
@ -100,6 +107,7 @@ extern "C" {
|
|||
|
||||
#include <ghostty/vt/types.h>
|
||||
#include <ghostty/vt/allocator.h>
|
||||
#include <ghostty/vt/build_info.h>
|
||||
#include <ghostty/vt/color.h>
|
||||
#include <ghostty/vt/focus.h>
|
||||
#include <ghostty/vt/formatter.h>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* @file build_info.h
|
||||
*
|
||||
* Build info - query compile-time build configuration of libghostty-vt.
|
||||
*/
|
||||
|
||||
#ifndef GHOSTTY_VT_BUILD_INFO_H
|
||||
#define GHOSTTY_VT_BUILD_INFO_H
|
||||
|
||||
/** @defgroup build_info Build Info
|
||||
*
|
||||
* Query compile-time build configuration of libghostty-vt.
|
||||
*
|
||||
* These values reflect the options the library was built with and are
|
||||
* constant for the lifetime of the process.
|
||||
*
|
||||
* ## Basic Usage
|
||||
*
|
||||
* Use ghostty_build_info() to query individual build options:
|
||||
*
|
||||
* @snippet c-vt-build-info/src/main.c build-info-query
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ghostty/vt/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Build info data types that can be queried.
|
||||
*
|
||||
* Each variant documents the expected output pointer type.
|
||||
*/
|
||||
typedef enum {
|
||||
/** Invalid data type. Never results in any data extraction. */
|
||||
GHOSTTY_BUILD_INFO_INVALID = 0,
|
||||
|
||||
/**
|
||||
* Whether SIMD-accelerated code paths are enabled.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_BUILD_INFO_SIMD = 1,
|
||||
|
||||
/**
|
||||
* Whether Kitty graphics protocol support is available.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_BUILD_INFO_KITTY_GRAPHICS = 2,
|
||||
|
||||
/**
|
||||
* Whether tmux control mode support is available.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_BUILD_INFO_TMUX_CONTROL_MODE = 3,
|
||||
} GhosttyBuildInfo;
|
||||
|
||||
/**
|
||||
* Query a compile-time build configuration value.
|
||||
*
|
||||
* The caller must pass a pointer to the correct output type for the
|
||||
* requested data (see GhosttyBuildInfo variants for types).
|
||||
*
|
||||
* @param data The build info field to query
|
||||
* @param out Pointer to store the result (type depends on data parameter)
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
|
||||
* data type is invalid
|
||||
*
|
||||
* @ingroup build_info
|
||||
*/
|
||||
GhosttyResult ghostty_build_info(GhosttyBuildInfo data, void *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* GHOSTTY_VT_BUILD_INFO_H */
|
||||
|
|
@ -217,6 +217,7 @@ comptime {
|
|||
@export(&c.grid_ref_row, .{ .name = "ghostty_grid_ref_row" });
|
||||
@export(&c.grid_ref_graphemes, .{ .name = "ghostty_grid_ref_graphemes" });
|
||||
@export(&c.grid_ref_style, .{ .name = "ghostty_grid_ref_style" });
|
||||
@export(&c.build_info, .{ .name = "ghostty_build_info" });
|
||||
|
||||
// On Wasm we need to export our allocator convenience functions.
|
||||
if (builtin.target.cpu.arch.isWasm()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
const std = @import("std");
|
||||
const build_options = @import("terminal_options");
|
||||
const Result = @import("result.zig").Result;
|
||||
|
||||
const log = std.log.scoped(.build_info_c);
|
||||
|
||||
/// C: GhosttyBuildInfo
|
||||
pub const BuildInfo = enum(c_int) {
|
||||
invalid = 0,
|
||||
simd = 1,
|
||||
kitty_graphics = 2,
|
||||
tmux_control_mode = 3,
|
||||
|
||||
/// Output type expected for querying the data of the given kind.
|
||||
pub fn OutType(comptime self: BuildInfo) type {
|
||||
return switch (self) {
|
||||
.invalid => void,
|
||||
.simd, .kitty_graphics, .tmux_control_mode => bool,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn get(
|
||||
data: BuildInfo,
|
||||
out: ?*anyopaque,
|
||||
) callconv(.c) Result {
|
||||
if (comptime std.debug.runtime_safety) {
|
||||
_ = std.meta.intToEnum(BuildInfo, @intFromEnum(data)) catch {
|
||||
log.warn("build_info invalid data value={d}", .{@intFromEnum(data)});
|
||||
return .invalid_value;
|
||||
};
|
||||
}
|
||||
|
||||
return switch (data) {
|
||||
inline else => |comptime_data| getTyped(
|
||||
comptime_data,
|
||||
@ptrCast(@alignCast(out)),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
fn getTyped(
|
||||
comptime data: BuildInfo,
|
||||
out: *data.OutType(),
|
||||
) Result {
|
||||
switch (data) {
|
||||
.invalid => return .invalid_value,
|
||||
.simd => out.* = build_options.simd,
|
||||
.kitty_graphics => out.* = build_options.kitty_graphics,
|
||||
.tmux_control_mode => out.* = build_options.tmux_control_mode,
|
||||
}
|
||||
|
||||
return .success;
|
||||
}
|
||||
|
||||
test "get simd" {
|
||||
const testing = std.testing;
|
||||
var value: bool = undefined;
|
||||
try testing.expectEqual(Result.success, get(.simd, @ptrCast(&value)));
|
||||
try testing.expectEqual(build_options.simd, value);
|
||||
}
|
||||
|
||||
test "get kitty_graphics" {
|
||||
const testing = std.testing;
|
||||
var value: bool = undefined;
|
||||
try testing.expectEqual(Result.success, get(.kitty_graphics, @ptrCast(&value)));
|
||||
try testing.expectEqual(build_options.kitty_graphics, value);
|
||||
}
|
||||
|
||||
test "get tmux_control_mode" {
|
||||
const testing = std.testing;
|
||||
var value: bool = undefined;
|
||||
try testing.expectEqual(Result.success, get(.tmux_control_mode, @ptrCast(&value)));
|
||||
try testing.expectEqual(build_options.tmux_control_mode, value);
|
||||
}
|
||||
|
||||
test "get invalid" {
|
||||
try std.testing.expectEqual(Result.invalid_value, get(.invalid, null));
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
const buildpkg = @import("build_info.zig");
|
||||
pub const cell = @import("cell.zig");
|
||||
pub const color = @import("color.zig");
|
||||
pub const focus = @import("focus.zig");
|
||||
|
|
@ -17,6 +18,8 @@ pub const style = @import("style.zig");
|
|||
pub const terminal = @import("terminal.zig");
|
||||
|
||||
// The full C API, unexported.
|
||||
pub const build_info = buildpkg.get;
|
||||
|
||||
pub const osc_new = osc.new;
|
||||
pub const osc_free = osc.free;
|
||||
pub const osc_reset = osc.reset;
|
||||
|
|
@ -136,6 +139,7 @@ pub const grid_ref_graphemes = grid_ref.grid_ref_graphemes;
|
|||
pub const grid_ref_style = grid_ref.grid_ref_style;
|
||||
|
||||
test {
|
||||
_ = buildpkg;
|
||||
_ = cell;
|
||||
_ = color;
|
||||
_ = grid_ref;
|
||||
|
|
|
|||
Loading…
Reference in New Issue