From dd04856482d3c38746da989901b1cdeeb8580c7c Mon Sep 17 00:00:00 2001 From: Alessandro De Blasis Date: Fri, 10 Apr 2026 06:52:48 +0200 Subject: [PATCH 1/5] build: add ghostty-internal pkg-config modules (shared + static) --- src/build/GhosttyLib.zig | 87 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/src/build/GhosttyLib.zig b/src/build/GhosttyLib.zig index 4e15fbbf4..7d73ed8ea 100644 --- a/src/build/GhosttyLib.zig +++ b/src/build/GhosttyLib.zig @@ -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 change -lghostty 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, }; } @@ -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,54 @@ 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: -L${{libdir}} -lghostty + \\Libs.private: + \\Requires.private: + , .{ b.install_prefix, deps.config.version })), + .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 staticLibraryName(os_tag: std.Target.Os.Tag) []const u8 { + return if (os_tag == .windows) + "ghostty-static.lib" + else + "libghostty.a"; +} From 4fd16ef9bcb73e19c2fdb406107803f819dc7d92 Mon Sep 17 00:00:00 2001 From: Alessandro De Blasis Date: Sat, 11 Apr 2026 02:59:50 +0200 Subject: [PATCH 2/5] build: install ghostty-internal dll/static with new names Rename the internal library's install names to match the new ghostty-internal pkg-config module convention: ghostty.dll -> ghostty-internal.dll ghostty-static.lib -> ghostty-internal-static.lib libghostty.so -> ghostty-internal.so libghostty.a -> ghostty-internal.a This is the glue library between Ghostty's app shells and the GUI core, historically (mis)named "libghostty". It is not the public libghostty-vt API. --- build.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index e8c784611..276fdbc40 100644 --- a/build.zig +++ b/build.zig @@ -190,11 +190,11 @@ pub fn build(b: *std.Build) !void { 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"); + lib_shared.install("ghostty-internal.dll"); + lib_static.install("ghostty-internal-static.lib"); } else { - lib_shared.install("libghostty.so"); - lib_static.install("libghostty.a"); + lib_shared.install("ghostty-internal.so"); + lib_static.install("ghostty-internal.a"); } } } From 1988ac94d4815b878e34258a543d17707024f209 Mon Sep 17 00:00:00 2001 From: Alessandro De Blasis Date: Sat, 11 Apr 2026 03:00:39 +0200 Subject: [PATCH 3/5] build: point ghostty-internal pkg-config files at direct paths Switch the shared ghostty-internal.pc Libs: line from -lghostty to a direct ${libdir}/ path, matching what the -static module already does. The name-per-OS helpers now emit: shared: ghostty-internal.dll (Windows) / ghostty-internal.so (other) static: ghostty-internal-static.lib (Windows) / ghostty-internal.a Direct paths sidestep the GNU-ld -l search template, which expects libghostty-internal.so/.a on Unix - we drop the lib prefix to match the ghostty-internal pkg-config module name. Also update the LipoStep out_name for the macOS universal static archive to ghostty-internal.a for consistency. --- src/build/GhosttyLib.zig | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/build/GhosttyLib.zig b/src/build/GhosttyLib.zig index 7d73ed8ea..a6667e334 100644 --- a/src/build/GhosttyLib.zig +++ b/src/build/GhosttyLib.zig @@ -155,8 +155,8 @@ pub fn initShared( // pkg-config // // pkg-config's --static only expands Libs.private / Requires.private; - // it doesn't change -lghostty into an archive-only reference when - // both shared and static libraries are installed. Install a dedicated + // 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); @@ -184,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, }); @@ -255,10 +255,10 @@ fn pkgConfigFiles( \\Description: Ghostty internal library (not for external use) \\Version: {f} \\Cflags: -I${{includedir}} - \\Libs: -L${{libdir}} -lghostty + \\Libs: ${{libdir}}/{s} \\Libs.private: \\Requires.private: - , .{ b.install_prefix, deps.config.version })), + , .{ b.install_prefix, deps.config.version, sharedLibraryName(os_tag) })), .static = wf.add("ghostty-internal-static.pc", b.fmt( \\prefix={s} \\includedir=${{prefix}}/include @@ -276,9 +276,16 @@ fn pkgConfigFiles( }; } +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-static.lib" + "ghostty-internal-static.lib" else - "libghostty.a"; + "ghostty-internal.a"; } From 935b08acea92e4c9a6772d0518022e6659a9be68 Mon Sep 17 00:00:00 2001 From: Alessandro De Blasis Date: Sat, 11 Apr 2026 03:01:12 +0200 Subject: [PATCH 4/5] test/windows: load ghostty-internal.dll in CRT init reproducer The internal glue DLL was renamed from ghostty.dll to ghostty-internal.dll. Update the LoadLibraryA call and the comment block so this regression test still exercises the right artifact. --- test/windows/test_dll_init.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/windows/test_dll_init.c b/test/windows/test_dll_init.c index 68363304f..7215e2b69 100644 --- a/test/windows/test_dll_init.c +++ b/test/windows/test_dll_init.c @@ -1,17 +1,18 @@ /* - * Minimal reproducer for the libghostty DLL CRT initialization issue. + * Minimal reproducer for the ghostty-internal DLL CRT initialization issue. * * Before the fix (DllMain calling __vcrt_initialize / __acrt_initialize), - * loading ghostty.dll and calling any function that touches the C runtime - * crashed with "access violation writing 0x0000000000000024" because Zig's - * _DllMainCRTStartup does not initialize the MSVC C runtime for DLL targets. + * loading ghostty-internal.dll and calling any function that touches the C + * runtime crashed with "access violation writing 0x0000000000000024" because + * Zig's _DllMainCRTStartup does not initialize the MSVC C runtime for DLL + * targets. * * This test loads the DLL and calls ghostty_info, which exercises the CRT * (string handling, memory). If it returns a version string without * crashing, the CRT is properly initialized. * * Build: zig cc test_dll_init.c -o test_dll_init.exe -target native-native-msvc - * Run: copy ..\..\zig-out\lib\ghostty.dll . && test_dll_init.exe + * Run: copy ..\..\zig-out\lib\ghostty-internal.dll . && test_dll_init.exe * * Expected output (after fix): * ghostty_info: @@ -29,7 +30,7 @@ typedef struct { typedef ghostty_info_s (*ghostty_info_fn)(void); int main(void) { - HMODULE dll = LoadLibraryA("ghostty.dll"); + HMODULE dll = LoadLibraryA("ghostty-internal.dll"); if (!dll) { fprintf(stderr, "LoadLibrary failed: %lu\n", GetLastError()); return 1; From 19bf63ab714ddd5807df5ec2df0572c7fd9ac94a Mon Sep 17 00:00:00 2001 From: Alessandro De Blasis Date: Sat, 11 Apr 2026 03:02:08 +0200 Subject: [PATCH 5/5] test/windows: update README for ghostty-internal.dll rename Match the dll filename rename so the copy/run instructions stay accurate. --- test/windows/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/windows/README.md b/test/windows/README.md index d9047d841..da2be7521 100644 --- a/test/windows/README.md +++ b/test/windows/README.md @@ -4,13 +4,13 @@ Manual test programs for Windows-specific functionality. ## test_dll_init.c -Regression test for the DLL CRT initialization fix. Loads ghostty.dll -at runtime and calls ghostty_info + ghostty_init to verify the MSVC C -runtime is properly initialized. +Regression test for the DLL CRT initialization fix. Loads +ghostty-internal.dll at runtime and calls ghostty_info + ghostty_init to +verify the MSVC C runtime is properly initialized. ### Build -First build ghostty.dll, then compile the test: +First build ghostty-internal.dll, then compile the test: ``` zig build -Dapp-runtime=none -Demit-exe=false @@ -22,7 +22,7 @@ zig cc test_dll_init.c -o test_dll_init.exe -target native-native-msvc From this directory: ``` -copy ..\..\zig-out\lib\ghostty.dll . && test_dll_init.exe +copy ..\..\zig-out\lib\ghostty-internal.dll . && test_dll_init.exe ``` Expected output (after the CRT fix):