From 4210ef7873b6104400fec35af4acc82969df4f8f Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Wed, 22 Jan 2025 22:29:25 -0600 Subject: [PATCH] build: options to enable/disable terminfo & termcap install Fixes #5253 Add `-Demit-terminfo` and `-Demit-termcap` build options to enable/disable installtion of source terminfo and termcap files. --- PACKAGING.md | 8 +++++++ src/build/Config.zig | 17 +++++++++++++ src/build/GhosttyResources.zig | 44 +++++++++++++++++----------------- src/os/resourcesdir.zig | 33 ++++++++++++++++--------- 4 files changed, 69 insertions(+), 33 deletions(-) diff --git a/PACKAGING.md b/PACKAGING.md index 82c7c56739..9ccaa6274a 100644 --- a/PACKAGING.md +++ b/PACKAGING.md @@ -118,6 +118,14 @@ relevant to package maintainers: version, glibc, etc. Run `zig targets` to a get a full list of available targets. +- `-Demit-terminfo`: Install the Ghostty terminfo source file. Defaults to + `false` except on Windows where it defaults to `true`. Except for Windows, + this file is not required for proper operation as compiled versions of the + terminfo file are installed. + +- `-Demit-termcap`: Install the Ghostty termcap file. This may be useful for + some systems. Defaults to false. + > [!WARNING] > > **The GLFW runtime is not meant for distribution.** The GLFW runtime diff --git a/src/build/Config.zig b/src/build/Config.zig index 71dffce4ab..d368915c5c 100644 --- a/src/build/Config.zig +++ b/src/build/Config.zig @@ -55,6 +55,8 @@ emit_helpgen: bool = false, emit_docs: bool = false, emit_webdata: bool = false, emit_xcframework: bool = false, +emit_terminfo: bool = false, +emit_termcap: bool = false, /// Environmental properties env: std.process.EnvMap, @@ -306,6 +308,21 @@ pub fn init(b: *std.Build) !Config { break :emit_docs path != null; }; + config.emit_terminfo = b.option( + bool, + "emit-terminfo", + "Install Ghostty terminfo source file", + ) orelse switch (target.result.os.tag) { + .windows => true, + else => false, + }; + + config.emit_termcap = b.option( + bool, + "emit-termcap", + "Install Ghostty termcap file", + ) orelse false; + config.emit_webdata = b.option( bool, "emit-webdata", diff --git a/src/build/GhosttyResources.zig b/src/build/GhosttyResources.zig index 018fef62eb..5224b88bbf 100644 --- a/src/build/GhosttyResources.zig +++ b/src/build/GhosttyResources.zig @@ -23,9 +23,12 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // Write it var wf = b.addWriteFiles(); - const src_source = wf.add("share/terminfo/ghostty.terminfo", str.items); - const src_install = b.addInstallFile(src_source, "share/terminfo/ghostty.terminfo"); - try steps.append(&src_install.step); + const source = wf.add("ghostty.terminfo", str.items); + + if (cfg.emit_terminfo) { + const source_install = b.addInstallFile(source, "share/terminfo/ghostty.terminfo"); + try steps.append(&source_install.step); + } // Windows doesn't have the binaries below. if (cfg.target.result.os.tag == .windows) break :terminfo; @@ -33,10 +36,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // Convert to termcap source format if thats helpful to people and // install it. The resulting value here is the termcap source in case // that is used for other commands. - { + if (cfg.emit_termcap) { const run_step = RunStep.create(b, "infotocap"); - run_step.addArg("infotocap"); - run_step.addFileArg(src_source); + run_step.addArgs(&.{ "infotocap", "-" }); + run_step.setStdIn(.{ .lazy_path = source }); const out_source = run_step.captureStdOut(); _ = run_step.captureStdErr(); // so we don't see stderr @@ -48,24 +51,21 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { { const run_step = RunStep.create(b, "tic"); run_step.addArgs(&.{ "tic", "-x", "-o" }); - const path = run_step.addOutputFileArg("terminfo"); - run_step.addFileArg(src_source); + const path = run_step.addOutputDirectoryArg("share/terminfo"); + run_step.addArg("-"); + run_step.setStdIn(.{ .lazy_path = source }); _ = run_step.captureStdErr(); // so we don't see stderr - // Depend on the terminfo source install step so that Zig build - // creates the "share" directory for us. - run_step.step.dependOn(&src_install.step); - - { - // Use cp -R instead of Step.InstallDir because we need to preserve - // symlinks in the terminfo database. Zig's InstallDir step doesn't - // handle symlinks correctly yet. - const copy_step = RunStep.create(b, "copy terminfo db"); - copy_step.addArgs(&.{ "cp", "-R" }); - copy_step.addFileArg(path); - copy_step.addArg(b.fmt("{s}/share", .{b.install_path})); - try steps.append(©_step.step); - } + try steps.append(&run_step.step); + + // Use cp -R instead of Step.InstallDir because we need to preserve + // symlinks in the terminfo database. Zig's InstallDir step doesn't + // handle symlinks correctly yet. + const copy_step = RunStep.create(b, "copy terminfo db"); + copy_step.addArgs(&.{ "cp", "-R" }); + copy_step.addFileArg(path); + copy_step.addArg(b.fmt("{s}/share", .{b.install_path})); + try steps.append(©_step.step); } } diff --git a/src/os/resourcesdir.zig b/src/os/resourcesdir.zig index c0f82dec5d..fdd3ff61fc 100644 --- a/src/os/resourcesdir.zig +++ b/src/os/resourcesdir.zig @@ -21,7 +21,16 @@ pub fn resourcesDir(alloc: std.mem.Allocator) !?[]const u8 { // This is the sentinel value we look for in the path to know // we've found the resources directory. - const sentinel = "terminfo/ghostty.termcap"; + const sentinels = switch (comptime builtin.target.os.tag) { + .windows => &.{ + "terminfo/ghostty.terminfo", + }, + else => &.{ + "terminfo/x/xterm-ghostty", + "terminfo/ghostty.termcap", + "terminfo/ghostty.terminfo", + }, + }; // Get the path to our running binary var exe_buf: [std.fs.max_path_bytes]u8 = undefined; @@ -33,18 +42,20 @@ pub fn resourcesDir(alloc: std.mem.Allocator) !?[]const u8 { while (std.fs.path.dirname(exe)) |dir| { exe = dir; - // On MacOS, we look for the app bundle path. - if (comptime builtin.target.isDarwin()) { - if (try maybeDir(&dir_buf, dir, "Contents/Resources", sentinel)) |v| { - return try std.fs.path.join(alloc, &.{ v, "ghostty" }); + inline for (sentinels) |sentinel| { + // On MacOS, we look for the app bundle path. + if (comptime builtin.target.isDarwin()) { + if (try maybeDir(&dir_buf, dir, "Contents/Resources", sentinel)) |v| { + return try std.fs.path.join(alloc, &.{ v, "ghostty" }); + } } - } - // On all platforms, we look for a /usr/share style path. This - // is valid even on Mac since there is nothing that requires - // Ghostty to be in an app bundle. - if (try maybeDir(&dir_buf, dir, "share", sentinel)) |v| { - return try std.fs.path.join(alloc, &.{ v, "ghostty" }); + // On all platforms, we look for a /usr/share style path. This + // is valid even on Mac since there is nothing that requires + // Ghostty to be in an app bundle. + if (try maybeDir(&dir_buf, dir, "share", sentinel)) |v| { + return try std.fs.path.join(alloc, &.{ v, "ghostty" }); + } } }