diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/build.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/build.zig')
| -rw-r--r-- | vendor/libghostty-vt/build.zig | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/build.zig b/vendor/libghostty-vt/build.zig new file mode 100644 index 00000000..45ad3ba1 --- /dev/null +++ b/vendor/libghostty-vt/build.zig @@ -0,0 +1,371 @@ +const std = @import("std"); +const assert = std.debug.assert; +const builtin = @import("builtin"); +const buildpkg = @import("src/build/main.zig"); + +/// App version from build.zig.zon. +const app_zon_version = @import("build.zig.zon").version; + +/// Libghostty version. We use a separate version from the app. +const lib_version = "0.1.0"; + +/// Minimum required zig version. +const minimum_zig_version = @import("build.zig.zon").minimum_zig_version; + +comptime { + buildpkg.requireZig(minimum_zig_version); +} + +pub fn build(b: *std.Build) !void { + // This defines all the available build options (e.g. `-D`). If you + // want to know what options are available, you can run `--help` or + // you can read `src/build/Config.zig`. + + // If we have a VERSION file (present in source tarballs) then we + // use that as the version source of truth. Otherwise we fall back + // to what is in the build.zig.zon. + const file_version: ?[]const u8 = if (b.build_root.handle.readFileAlloc( + b.allocator, + "VERSION", + 128, + )) |content| std.mem.trim( + u8, + content, + &std.ascii.whitespace, + ) else |_| null; + + const config = try buildpkg.Config.init( + b, + file_version orelse app_zon_version, + ); + const test_filters = b.option( + [][]const u8, + "test-filter", + "Filter for test. Only applies to Zig tests.", + ) orelse &[0][]const u8{}; + + // Ghostty dependencies used by many artifacts. + const deps = try buildpkg.SharedDeps.init(b, &config); + + // The modules exported for Zig consumers of libghostty. If you're + // writing a Zig program that uses libghostty, read this file. + const mod = try buildpkg.GhosttyZig.init( + b, + &config, + &deps, + ); + + // All our steps which we'll hook up later. The steps are shown + // up here just so that they are more self-documenting. + const run_step = b.step("run", "Run the app"); + const run_valgrind_step = b.step( + "run-valgrind", + "Run the app under valgrind", + ); + const test_step = b.step("test", "Run tests"); + const test_lib_vt_step = b.step( + "test-lib-vt", + "Run libghostty-vt tests", + ); + const test_valgrind_step = b.step( + "test-valgrind", + "Run tests under valgrind", + ); + const translations_step = b.step( + "update-translations", + "Update translation files", + ); + + // Ghostty resources like terminfo, shell integration, themes, etc. + const resources = try buildpkg.GhosttyResources.init(b, &config, &deps); + const i18n = if (config.i18n) try buildpkg.GhosttyI18n.init(b, &config) else null; + + // Ghostty executable, the actual runnable Ghostty program. + const exe = try buildpkg.GhosttyExe.init(b, &config, &deps); + + // Ghostty docs + const docs = try buildpkg.GhosttyDocs.init(b, &deps); + if (config.emit_docs) { + docs.install(); + } else if (config.target.result.os.tag.isDarwin()) { + // If we aren't emitting docs we need to emit a placeholder so + // our macOS xcodeproject builds since it expects the `share/man` + // directory to exist to copy into the app bundle. + docs.installDummy(b.getInstallStep()); + } + + // Ghostty webdata + const webdata = try buildpkg.GhosttyWebdata.init(b, &deps); + if (config.emit_webdata) webdata.install(); + + // Ghostty bench tools + const bench = try buildpkg.GhosttyBench.init(b, &deps); + if (config.emit_bench) bench.install(); + + // Ghostty dist tarball + const dist = try buildpkg.GhosttyDist.init(b, &config); + { + const step = b.step("dist", "Build the dist tarball"); + step.dependOn(dist.install_step); + const check_step = b.step("distcheck", "Install and validate the dist tarball"); + check_step.dependOn(dist.check_step); + check_step.dependOn(dist.install_step); + } + + // libghostty-vt + const libghostty_vt_shared = shared: { + if (config.target.result.cpu.arch.isWasm()) { + break :shared try buildpkg.GhosttyLibVt.initWasm( + b, + &mod, + ); + } + + break :shared try buildpkg.GhosttyLibVt.initShared( + b, + &mod, + ); + }; + libghostty_vt_shared.install(b.getInstallStep()); + + // libghostty-vt static lib + const libghostty_vt_static = try buildpkg.GhosttyLibVt.initStatic( + b, + &mod, + ); + if (config.is_dep) { + // If we're a dependency, we need to install everything as-is + // so that dep.artifact("ghostty-vt-static") works. + libghostty_vt_static.install(b.getInstallStep()); + } else { + // If we're not a dependency, we rename the static lib to + // be idiomatic. On Windows, we use a distinct name to avoid + // colliding with the DLL import library (ghostty-vt.lib). + const static_lib_name = if (config.target.result.os.tag == .windows) + "ghostty-vt-static.lib" + else + "libghostty-vt.a"; + b.getInstallStep().dependOn(&b.addInstallLibFile( + libghostty_vt_static.output, + static_lib_name, + ).step); + } + + // Helpgen + if (config.emit_helpgen) deps.help_strings.install(); + + // Runtime "none" is libghostty, anything else is an executable. + if (config.app_runtime != .none) { + if (config.emit_exe) { + exe.install(); + resources.install(); + if (i18n) |v| v.install(); + } + } else if (!config.emit_lib_vt) { + // The macOS Ghostty Library + // + // This is NOT libghostty (even though its named that for historical + // reasons). It is just the glue between Ghostty GUI on macOS and + // the full Ghostty GUI core. + const lib_shared = try buildpkg.GhosttyLib.initShared(b, &deps); + const lib_static = try buildpkg.GhosttyLib.initStatic(b, &deps); + + // We shouldn't have this guard but we don't currently + // build on macOS this way ironically so we need to fix that. + if (!config.target.result.os.tag.isDarwin()) { + lib_shared.installHeader(); // Only need one header + if (config.target.result.os.tag == .windows) { + lib_shared.install("ghostty.dll"); + lib_static.install("ghostty-static.lib"); + } else { + lib_shared.install("libghostty.so"); + lib_static.install("libghostty.a"); + } + } + } + + // macOS only artifacts. These will error if they're initialized for + // other targets. + if (config.target.result.os.tag.isDarwin() and + (config.emit_xcframework or config.emit_macos_app)) + { + // Ghostty xcframework + const xcframework = try buildpkg.GhosttyXCFramework.init( + b, + &deps, + config.xcframework_target, + ); + if (config.emit_xcframework) { + xcframework.install(); + + // The xcframework build always installs resources because our + // macOS xcode project contains references to them. + resources.install(); + if (i18n) |v| v.install(); + } + + // Ghostty macOS app + const macos_app = try buildpkg.GhosttyXcodebuild.init( + b, + &config, + .{ + .xcframework = &xcframework, + .docs = &docs, + .i18n = if (i18n) |v| &v else null, + .resources = &resources, + }, + ); + if (config.emit_macos_app) { + macos_app.install(); + } + } + + // Run step + run: { + if (config.app_runtime != .none) { + const run_cmd = b.addRunArtifact(exe.exe); + if (b.args) |args| run_cmd.addArgs(args); + + // Set the proper resources dir so things like shell integration + // work correctly. If we're running `zig build run` in Ghostty, + // this also ensures it overwrites the release one with our debug + // build. + run_cmd.setEnvironmentVariable( + "GHOSTTY_RESOURCES_DIR", + b.getInstallPath(.prefix, "share/ghostty"), + ); + + run_step.dependOn(&run_cmd.step); + break :run; + } + + assert(config.app_runtime == .none); + + // On macOS we can run the macOS app. For "run" we always force + // a native-only build so that we can run as quickly as possible. + if (config.target.result.os.tag.isDarwin() and + (config.emit_xcframework or config.emit_macos_app)) + { + const xcframework_native = try buildpkg.GhosttyXCFramework.init( + b, + &deps, + .native, + ); + const macos_app_native_only = try buildpkg.GhosttyXcodebuild.init( + b, + &config, + .{ + .xcframework = &xcframework_native, + .docs = &docs, + .i18n = if (i18n) |v| &v else null, + .resources = &resources, + }, + ); + + // Run uses the native macOS app + run_step.dependOn(&macos_app_native_only.open.step); + + // If we have no test filters, install the tests too + if (test_filters.len == 0) { + macos_app_native_only.addTestStepDependencies(test_step); + } + } + } + + // Valgrind + if (config.app_runtime != .none) { + // We need to rebuild Ghostty with a baseline CPU target. + const valgrind_exe = exe: { + var valgrind_config = config; + valgrind_config.target = valgrind_config.baselineTarget(); + break :exe try buildpkg.GhosttyExe.init( + b, + &valgrind_config, + &deps, + ); + }; + + const run_cmd = b.addSystemCommand(&.{ + "valgrind", + "--leak-check=full", + "--num-callers=50", + b.fmt("--suppressions={s}", .{b.pathFromRoot("valgrind.supp")}), + "--gen-suppressions=all", + }); + run_cmd.addArtifactArg(valgrind_exe.exe); + if (b.args) |args| run_cmd.addArgs(args); + run_valgrind_step.dependOn(&run_cmd.step); + } + + // Zig module tests + { + const mod_vt_test = b.addTest(.{ + .root_module = mod.vt, + .filters = test_filters, + }); + const mod_vt_test_run = b.addRunArtifact(mod_vt_test); + test_lib_vt_step.dependOn(&mod_vt_test_run.step); + + const mod_vt_c_test = b.addTest(.{ + .root_module = mod.vt_c, + .filters = test_filters, + }); + const mod_vt_c_test_run = b.addRunArtifact(mod_vt_c_test); + test_lib_vt_step.dependOn(&mod_vt_c_test_run.step); + } + + // Tests + { + // Full unit tests + const test_exe = b.addTest(.{ + .name = "ghostty-test", + .filters = test_filters, + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = config.baselineTarget(), + .optimize = .Debug, + .strip = false, + .omit_frame_pointer = false, + .unwind_tables = .sync, + }), + // Crash on x86_64 without this + .use_llvm = true, + }); + if (config.emit_test_exe) b.installArtifact(test_exe); + _ = try deps.add(test_exe); + + // Verify our internal libghostty header. + const ghostty_h = b.addTranslateC(.{ + .root_source_file = b.path("include/ghostty.h"), + .target = config.baselineTarget(), + .optimize = .Debug, + }); + test_exe.root_module.addImport("ghostty.h", ghostty_h.createModule()); + + // Normal test running + const test_run = b.addRunArtifact(test_exe); + test_step.dependOn(&test_run.step); + + // Normal tests always test our libghostty modules + //test_step.dependOn(test_lib_vt_step); + + // Valgrind test running + const valgrind_run = b.addSystemCommand(&.{ + "valgrind", + "--leak-check=full", + "--num-callers=50", + b.fmt("--suppressions={s}", .{b.pathFromRoot("valgrind.supp")}), + "--gen-suppressions=all", + }); + valgrind_run.addArtifactArg(test_exe); + test_valgrind_step.dependOn(&valgrind_run.step); + } + + // update-translations does what it sounds like and updates the "pot" + // files. These should be committed to the repo. + if (i18n) |v| { + translations_step.dependOn(v.update_step); + } else { + try translations_step.addError("cannot update translations when i18n is disabled", .{}); + } +} |
