Skip to content

build: split lib-vt static sections - #4

Closed
fornwall wants to merge 2 commits into
mainfrom
one-text-section
Closed

fornwall wants to merge 2 commits into
mainfrom
one-text-section

Conversation

@fornwall

@fornwall fornwall commented Aug 9, 2026 •

Copy link
Copy Markdown
Owner

The lib-vt Zig compilation unit was emitted as one text and data section, so linker garbage collection retained the entire C API.

Enable per-function and per-data sections for static artifacts. Force LLVM code generation because the self-hosted x86 backend accepts these flags without splitting the unit, while leaving shared artifacts unchanged.

Ghostling size impact

Ghostling PR #17 updates Ghostling for the current lib-vt API and Zig 0.16. Its branch links the shared ghostty-vt target, while current Ghostty provides a ghostty-vt-static imported target with GHOSTTY_STATIC and the platform link dependencies. Changing that one target makes Ghostling build successfully against the static lib-vt.

I built the PR #17 branch twice against adjacent Ghostty commits, changing only whether this patch was applied: f64f4ac before and f848494 after.

Static Ghostling Stripped bytes Linked ghostty_* definitions
Before 3,500,600 189
With this PR 3,115,576 64
Savings 385,024 (376 KiB, 11.00%) 125

For context, the stripped shared build was 1,433,088 bytes for ghostling plus 2,006,064 bytes for libghostty-vt.so, or 3,439,152 bytes together. The patched static executable was 323,576 bytes (9.41%) smaller than that two-file payload.

Seeing similar savings in another internal program embedding libghostty.

Measurement environment

  • Linux 7.0.0-29-generic x86_64
  • Ghostling PR #17 at 89da5be, Raylib 5.5, and current Ghostty (f64f4ac versus this PR's f848494)
  • Zig 0.16.0 from /home/linuxbrew/.linuxbrew/bin/zig, GCC 15.2.0, GNU ld/strip 2.46, CMake 4.2.3, and Ninja 1.13.2
  • X11 development libraries from Linuxbrew, including libXinerama 1.1.6

Both static variants changed Ghostling's link target to ghostty-vt-static and used:

cmake -B build -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_EXE_LINKER_FLAGS_RELEASE=-Wl,--gc-sections \
  -DFETCHCONTENT_SOURCE_DIR_GHOSTTY=<ghostty-worktree> \
  -DFETCHCONTENT_SOURCE_DIR_RAYLIB=<raylib-5.5-source> \
  -DCMAKE_INCLUDE_PATH=/home/linuxbrew/.linuxbrew/include \
  -DCMAKE_LIBRARY_PATH=/home/linuxbrew/.linuxbrew/lib
cmake --build build
strip --strip-all ghostling

This compiles Ghostling and Raylib with -O3 -DNDEBUG. Ghostty's CMake wrapper maps the Release configuration to Zig ReleaseFast and invokes zig build -Demit-lib-vt -Doptimize=ReleaseFast.

Verification

  • A native Debug build emits 6,519 text sections in the Zig object instead of one; a ReleaseFast build emits 1,150.
  • A minimal embedder referencing one C API function retains one ghostty_* symbol instead of all 189.
  • The stripped ReleaseFast minimal test executable is 82 KiB with section GC versus 2.1 MiB without it.
  • Native Linux, cross-compiled Windows, and cross-compiled macOS builds pass. COFF emits .text$... and .rdata$... sections; Mach-O emits MH_SUBSECTIONS_VIA_SYMBOLS.

Tradeoffs

  • The ReleaseFast static archive grew from 18,975,324 to 19,497,556 bytes (522,232 bytes, 2.75%) because it contains more section metadata. Consumers only realize the size reduction when their linker enables section garbage collection.
  • More input sections can increase linker work and memory use. This was not benchmarked.
  • Forcing LLVM is necessary for the flags to take effect on the self-hosted x86 backend. It means static lib-vt builds require an LLVM-enabled Zig compiler and may use more compile time or memory, especially for Debug builds. Shared lib-vt builds are unchanged.

LLVM references

The lib-vt Zig compilation unit was emitted as one text and data
section, so linker garbage collection retained the entire C API.

Enable per-function and per-data sections for static artifacts. Force
LLVM code generation because the self-hosted x86 backend accepts these
flags without splitting the unit, while leaving shared artifacts
unchanged.

Signed-off-by: Fredrik Fornwall <fredrik@fornwall.net>
We can continue to let x86-64 Linux use the self-hosted backend for
debug builds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant