feat(lib): port libghostty, Ghostty's embedded C API
Ports apprt/embedded.zig, main_c.zig and config/CApi.zig + c_get.zig as crates/ghostty-lib (cdylib/staticlib/rlib `libghostty`), exporting every function of the unchanged include/ghostty.h - the ABI Ghostty's Swift macOS/iOS app links against. The embedded runtime implements the runtime traits over the host's C callbacks, so the real core drives it. - ghostty-core selects the renderer per target: Metal on Apple (surface NSView/UIView via RtSurface::platform_view), OpenGL elsewhere. - ghostty_config_get follows Zig's c_get rules via a CValue type (143 supported keys, checked against the Zig field types). - The inspector C API is complete; its Metal backend replaces ImGui's Metal renderer and has not run. Verification: generated C ABI probe (sizeof/alignof/offsetof of every struct/union, 755 enum values, every function linked, nm exports, headers byte-identical to upstream); a C host on Linux covering init, CLI actions, config, app, keys, focus and color scheme; an opt-in test-platform feature creating real surfaces on Linux with headless EGL and a pty (13 tests). Apple targets are clippy-clean but not run; the Swift app has not been built against it. Test Plan: - cargo test -p ghostty-lib (and --features test-platform) - cargo clippy --target aarch64-apple-darwin -p ghostty-lib (cross env in docs/rewrite/notes/macos-M1.md)
This commit is contained in:
1 parent
4787565397
commit
49d4ecefae
47 files changed
+10296
-34
No files matched your search
@@ -0,0 +1,98 @@
|
||||
//! `ghostty_benchmark_cli` (ZIG/src/benchmark/CApi.zig).
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use std::ffi::{CStr, c_char};
|
||||
|
||||
use ghostty_bench::{args::Args, benches};
|
||||
|
||||
/// Split the argument string like `std.process.ArgIteratorGeneral(.{})`:
|
||||
/// whitespace separated, with double quotes grouping and backslash
|
||||
/// escapes inside quotes.
|
||||
fn split_args(s: &str) -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
let mut cur = String::new();
|
||||
let mut have = false;
|
||||
let mut in_quote = false;
|
||||
let mut chars = s.chars().peekable();
|
||||
while let Some(c) = chars.next() {
|
||||
match c {
|
||||
'"' => {
|
||||
in_quote = !in_quote;
|
||||
have = true;
|
||||
}
|
||||
'\\' if in_quote => {
|
||||
if let Some(n) = chars.next() {
|
||||
cur.push(n);
|
||||
}
|
||||
}
|
||||
c if c.is_whitespace() && !in_quote => {
|
||||
if have {
|
||||
out.push(std::mem::take(&mut cur));
|
||||
have = false;
|
||||
}
|
||||
}
|
||||
c => {
|
||||
cur.push(c);
|
||||
have = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if have {
|
||||
out.push(cur);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Run the Ghostty benchmark CLI with the given action and arguments.
|
||||
///
|
||||
/// # Safety
|
||||
/// `action_name` and `args` must be NUL terminated strings.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn ghostty_benchmark_cli(
|
||||
action_name: *const c_char,
|
||||
args: *const c_char,
|
||||
) -> bool {
|
||||
if action_name.is_null() || args.is_null() {
|
||||
return false;
|
||||
}
|
||||
// SAFETY: per the function contract.
|
||||
let (action, args) = unsafe { (CStr::from_ptr(action_name), CStr::from_ptr(args)) };
|
||||
let action = action.to_string_lossy();
|
||||
if !benches::ACTIONS.contains(&action.as_ref()) {
|
||||
log::warn!("unknown action={action}");
|
||||
return false;
|
||||
}
|
||||
let argv = split_args(&args.to_string_lossy());
|
||||
let parsed = match Args::parse(argv) {
|
||||
Ok(a) => a,
|
||||
Err(err) => {
|
||||
log::warn!("failed to run action={action} err={err}");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
match benches::main_action(&action, parsed) {
|
||||
Ok(_) => true,
|
||||
Err(err) => {
|
||||
log::warn!("failed to run action={action} err={err}");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn split_args_basic() {
|
||||
assert_eq!(split_args("a b c"), ["a", "b", "c"]);
|
||||
assert_eq!(split_args("--x=\"a b\" c"), ["--x=a b", "c"]);
|
||||
assert_eq!(split_args(" ").len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_action_returns_false() {
|
||||
// SAFETY: valid NUL terminated strings.
|
||||
assert!(!unsafe { ghostty_benchmark_cli(c"nope".as_ptr(), c"".as_ptr()) });
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user