Skip to content

Commit

Permalink
build: options to enable/disable terminfo & termcap install
Browse files Browse the repository at this point in the history
Fixes ghostty-org#5253

Add `-Demit-terminfo` and `-Demit-termcap` build options to
enable/disable installtion of source terminfo and termcap files.
  • Loading branch information
jcollie committed Jan 23, 2025
1 parent d4bd222 commit 45b81dc
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 33 deletions.
8 changes: 8 additions & 0 deletions PACKAGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions src/build/Config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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",
Expand Down
44 changes: 22 additions & 22 deletions src/build/GhosttyResources.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,23 @@ 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;

// 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

Expand All @@ -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(&copy_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(&copy_step.step);
}
}

Expand Down
33 changes: 22 additions & 11 deletions src/os/resourcesdir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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" });
}
}
}

Expand Down

0 comments on commit 45b81dc

Please sign in to comment.