build: add ghostty-internal pkg-config modules (shared + static) (#12214)

## Summary
Mirror the `libghostty-vt-static` pkg-config pattern from #12210 for the
internal library.

- Add `ghostty-internal.pc` (shared, `-lghostty`) and
`ghostty-internal-static.pc` (static, direct archive reference) so
consumers can discover either variant via pkg-config
- Named `ghostty-internal` to distinguish from the public
`libghostty-vt` API
- Static module points at the platform-correct archive name
(`ghostty-static.lib` on Windows, `libghostty.a` elsewhere)
- pkg-config files are generated during shared builds and installed via
`GhosttyLib.install()`

## Test plan

- [x] `zig build` succeeds (default target)
- [x] `ghostty-internal.pc` and `ghostty-internal-static.pc` appear in
`zig-out/share/pkgconfig/`
- [x] Static `.pc` points at `ghostty-static.lib` (Windows) /
`libghostty.a` (Unix)
- [x] Shared `.pc` uses standard `-L -l` flags
- [x] Existing `libghostty-vt` pkg-config files are unaffected
This commit is contained in:
Mitchell Hashimoto
2026-04-12 13:18:03 -07:00
committed by GitHub
4 changed files with 110 additions and 17 deletions

View File

@@ -13,6 +13,8 @@ step: *std.Build.Step,
/// The final static library file
output: std.Build.LazyPath,
dsym: ?std.Build.LazyPath,
pkg_config: ?std.Build.LazyPath,
pkg_config_static: ?std.Build.LazyPath,
pub fn initStatic(
b: *std.Build,
@@ -54,6 +56,8 @@ pub fn initStatic(
.step = &lib.step,
.output = lib.getEmittedBin(),
.dsym = null,
.pkg_config = null,
.pkg_config_static = null,
};
// Create a static lib that contains all our dependencies.
@@ -70,6 +74,8 @@ pub fn initStatic(
// Static libraries cannot have dSYMs because they aren't linked.
.dsym = null,
.pkg_config = null,
.pkg_config_static = null,
};
}
@@ -146,10 +152,20 @@ pub fn initShared(
break :dsymutil output;
};
// pkg-config
//
// pkg-config's --static only expands Libs.private / Requires.private;
// it doesn't rewrite Libs: into an archive-only reference when both
// shared and static libraries are installed. Install a dedicated
// static module so consumers can request the archive explicitly.
const pcs = pkgConfigFiles(b, deps);
return .{
.step = &lib.step,
.output = lib.getEmittedBin(),
.dsym = dsymutil,
.pkg_config = pcs.shared,
.pkg_config_static = pcs.static,
};
}
@@ -168,7 +184,7 @@ pub fn initMacOSUniversal(
const universal = LipoStep.create(b, .{
.name = "ghostty",
.out_name = "libghostty.a",
.out_name = "ghostty-internal.a",
.input_a = aarch64.output,
.input_b = x86_64.output,
});
@@ -180,13 +196,31 @@ pub fn initMacOSUniversal(
// You can't run dsymutil on a universal binary, you have to
// do it on the individual binaries.
.dsym = null,
.pkg_config = null,
.pkg_config_static = null,
};
}
pub fn install(self: *const GhosttyLib, name: []const u8) void {
const b = self.step.owner;
const step = b.getInstallStep();
const lib_install = b.addInstallLibFile(self.output, name);
b.getInstallStep().dependOn(&lib_install.step);
step.dependOn(&lib_install.step);
if (self.pkg_config) |pc| {
step.dependOn(&b.addInstallFileWithDir(
pc,
.prefix,
"share/pkgconfig/ghostty-internal.pc",
).step);
}
if (self.pkg_config_static) |pc| {
step.dependOn(&b.addInstallFileWithDir(
pc,
.prefix,
"share/pkgconfig/ghostty-internal-static.pc",
).step);
}
}
pub fn installHeader(self: *const GhosttyLib) void {
@@ -197,3 +231,61 @@ pub fn installHeader(self: *const GhosttyLib) void {
);
b.getInstallStep().dependOn(&header_install.step);
}
const PkgConfigFiles = struct {
shared: std.Build.LazyPath,
static: std.Build.LazyPath,
};
fn pkgConfigFiles(
b: *std.Build,
deps: *const SharedDeps,
) PkgConfigFiles {
const os_tag = deps.config.target.result.os.tag;
const wf = b.addWriteFiles();
return .{
.shared = wf.add("ghostty-internal.pc", b.fmt(
\\prefix={s}
\\includedir=${{prefix}}/include
\\libdir=${{prefix}}/lib
\\
\\Name: ghostty-internal
\\URL: https://github.com/ghostty-org/ghostty
\\Description: Ghostty internal library (not for external use)
\\Version: {f}
\\Cflags: -I${{includedir}}
\\Libs: ${{libdir}}/{s}
\\Libs.private:
\\Requires.private:
, .{ b.install_prefix, deps.config.version, sharedLibraryName(os_tag) })),
.static = wf.add("ghostty-internal-static.pc", b.fmt(
\\prefix={s}
\\includedir=${{prefix}}/include
\\libdir=${{prefix}}/lib
\\
\\Name: ghostty-internal-static
\\URL: https://github.com/ghostty-org/ghostty
\\Description: Ghostty internal library, static (not for external use)
\\Version: {f}
\\Cflags: -I${{includedir}}
\\Libs: ${{libdir}}/{s}
\\Libs.private:
\\Requires.private:
, .{ b.install_prefix, deps.config.version, staticLibraryName(os_tag) })),
};
}
fn sharedLibraryName(os_tag: std.Target.Os.Tag) []const u8 {
return if (os_tag == .windows)
"ghostty-internal.dll"
else
"ghostty-internal.so";
}
fn staticLibraryName(os_tag: std.Target.Os.Tag) []const u8 {
return if (os_tag == .windows)
"ghostty-internal-static.lib"
else
"ghostty-internal.a";
}