mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-06 07:38:21 +00:00
vt: add ghostty_build_info API for querying build configuration (#11725)
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.
This commit is contained in:
17
example/c-vt-build-info/README.md
Normal file
17
example/c-vt-build-info/README.md
Normal file
@@ -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
|
||||
```
|
||||
42
example/c-vt-build-info/build.zig
Normal file
42
example/c-vt-build-info/build.zig
Normal file
@@ -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);
|
||||
}
|
||||
24
example/c-vt-build-info/build.zig.zon
Normal file
24
example/c-vt-build-info/build.zig.zon
Normal file
@@ -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",
|
||||
},
|
||||
}
|
||||
23
example/c-vt-build-info/src/main.c
Normal file
23
example/c-vt-build-info/src/main.c
Normal file
@@ -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>
|
||||
|
||||
86
include/ghostty/vt/build_info.h
Normal file
86
include/ghostty/vt/build_info.h
Normal file
@@ -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()) {
|
||||
|
||||
79
src/terminal/c/build_info.zig
Normal file
79
src/terminal/c/build_info.zig
Normal file
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user