From 3376153a44e5269b9aee5e6d2524954c171e717b Mon Sep 17 00:00:00 2001 From: Uzair Aftab Date: Sat, 29 Aug 2026 21:13:56 +0200 Subject: [PATCH] build: support native freestanding libghostty-vt Native freestanding targets cannot emit shared libraries and do not provide an OS page size, stack unwinder, hosted SIMD dependencies, or filesystem-backed Kitty graphics. Build only the static artifact for those targets, define the minimum alignment used for terminal pages, disable hosted-only defaults, and install the public headers with the archive. --- build.zig | 33 ++++++++++++++++++++++++++------- src/build/Config.zig | 7 ++++--- src/build/GhosttyLibVt.zig | 4 +++- src/lib_vt.zig | 21 +++++++++++++++++---- src/terminal/build_options.zig | 3 +-- 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/build.zig b/build.zig index 41ac5f04c..5204b3d87 100644 --- a/build.zig +++ b/build.zig @@ -125,26 +125,36 @@ pub fn build(b: *std.Build) !void { } // libghostty-vt - const libghostty_vt_shared = shared: { + const native_freestanding = config.target.result.os.tag == .freestanding and + !config.target.result.cpu.arch.isWasm(); + const libghostty_vt_shared: ?buildpkg.GhosttyLibVt = shared: { if (config.target.result.cpu.arch.isWasm()) { break :shared try buildpkg.GhosttyLibVt.initWasm( b, &mod, ); } + if (native_freestanding) break :shared null; break :shared try buildpkg.GhosttyLibVt.initShared( b, &mod, ); }; - libghostty_vt_shared.install(b.getInstallStep()); + if (libghostty_vt_shared) |shared| { + shared.install(b.getInstallStep()); - const type_schema_test = b.addSystemCommand(&.{"python3"}); - type_schema_test.addFileArg(b.path("src/terminal/c/types-schema-verify.py")); - type_schema_test.addFileArg(b.path("src/terminal/c/types.schema.json")); - type_schema_test.addFileArg(libghostty_vt_shared.output); - test_lib_vt_schema_step.dependOn(&type_schema_test.step); + const type_schema_test = b.addSystemCommand(&.{"python3"}); + type_schema_test.addFileArg(b.path("src/terminal/c/types-schema-verify.py")); + type_schema_test.addFileArg(b.path("src/terminal/c/types.schema.json")); + type_schema_test.addFileArg(shared.output); + test_lib_vt_schema_step.dependOn(&type_schema_test.step); + } else { + try test_lib_vt_schema_step.addError( + "cannot execute the ABI manifest for a native freestanding target", + .{}, + ); + } // libghostty-vt static lib const libghostty_vt_static = try buildpkg.GhosttyLibVt.initStatic( @@ -167,6 +177,15 @@ pub fn build(b: *std.Build) !void { libghostty_vt_static.output, static_lib_name, ).step); + + if (native_freestanding) { + b.getInstallStep().dependOn(&b.addInstallDirectory(.{ + .source_dir = b.path("include/ghostty"), + .install_dir = .header, + .install_subdir = "ghostty", + .include_extensions = &.{".h"}, + }).step); + } } // libghostty-vt xcframework (Apple only, universal binary). diff --git a/src/build/Config.zig b/src/build/Config.zig index c90f3781b..71fa4d289 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -240,9 +240,10 @@ pub fn init(b: *std.Build, appVersion: []const u8, libVersion: []const u8) !Conf "simd", "Build with SIMD-accelerated code paths. Results in significant performance improvements.", ) orelse simd: { - // We can't build our SIMD dependencies for Wasm. Note that we may - // still use SIMD features in the Wasm-builds. - if (target.result.cpu.arch.isWasm()) break :simd false; + // We can't build our SIMD dependencies for Wasm or freestanding + // targets. Note that we may still use SIMD features in the Wasm-builds. + if (target.result.cpu.arch.isWasm() or + target.result.os.tag == .freestanding) break :simd false; break :simd true; }; diff --git a/src/build/GhosttyLibVt.zig b/src/build/GhosttyLibVt.zig index a97fdf78f..690f864c5 100644 --- a/src/build/GhosttyLibVt.zig +++ b/src/build/GhosttyLibVt.zig @@ -246,7 +246,9 @@ fn initLib( // Enable PIC so the static library can be linked into PIE // executables, which is the default on most Linux distributions. - lib.root_module.pic = true; + // Native freestanding targets don't have a dynamic loader and some, + // such as Xtensa, don't support PIC relocations. + lib.root_module.pic = target.result.os.tag != .freestanding; } if (target.result.os.tag == .windows) { diff --git a/src/lib_vt.zig b/src/lib_vt.zig index 325f0e138..2a45d1cd4 100644 --- a/src/lib_vt.zig +++ b/src/lib_vt.zig @@ -424,6 +424,15 @@ comptime { pub const std_options: std.Options = opts: { var options: std.Options = .{}; + if (native_freestanding) { + // Freestanding targets don't have an OS page size. We still need an + // alignment for terminal page allocations, and 16 covers everything + // stored in a page without requiring 4 KiB-aligned embedded heaps. + options.page_size_min = 16; + options.page_size_max = 16; + options.allow_stack_tracing = false; + } + if (builtin.target.cpu.arch.isWasm()) { // In non-debug modes, we want to ship effectively no logging // warn and lower add ~200KB at the time of this comment. @@ -464,10 +473,14 @@ pub const std_options: std.Options = opts: { /// traces on panic, std.debug.print, etc.). These builds are for /// development, where the roughly 160KB of binary size it costs is /// worth it. -const debug_machinery: bool = builtin.is_test or switch (builtin.mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, -}; +const native_freestanding = builtin.target.os.tag == .freestanding and + !builtin.target.cpu.arch.isWasm(); + +const debug_machinery: bool = !native_freestanding and + (builtin.is_test or switch (builtin.mode) { + .Debug, .ReleaseSafe => true, + .ReleaseFast, .ReleaseSmall => false, + }); /// The panic handler for when this file is the root module. /// diff --git a/src/terminal/build_options.zig b/src/terminal/build_options.zig index 725fccfd0..8fc2c3e90 100644 --- a/src/terminal/build_options.zig +++ b/src/terminal/build_options.zig @@ -263,8 +263,7 @@ pub const Options = struct { /// targets, so it is always disabled there regardless of the /// feature setting. pub fn kittyGraphics(self: Options, target: std.Target) bool { - if (target.cpu.arch == .wasm32 and target.os.tag == .freestanding) - return false; + if (target.os.tag == .freestanding) return false; return self.features.kitty_graphics; }