Pin exported surface to intended API and shrink - #77
Merged
Merged
Conversation
jserv
added a commit
that referenced
this pull request
Aug 4, 2026
…macOS dylibs Address the cubic review on PR #77. gen-export-list.sh: a missing or unreadable manifest was masked because set -e saw the successful trailing sort, so a broken input could emit a map that omits the API and still reach the linker. Read the manifests in a checked step, and drop the || true on the comm intersection: comm reads $defined, and already returns 0 for an empty intersection, so the guard only swallowed real read errors. A missing manifest or defined-syms now fails the build; a legitimate empty intersection still succeeds. install.mk: strip -x rewrites the Mach-O and invalidates the ad-hoc signature ld64 puts on arm64 binaries. Apple's strip re-signs, but lld or an older toolchain does not, and dyld then refuses the installed dylib. Re-sign with codesign --force --sign - after strip on Darwin; CODESIGN_RESIGN is the no-op : builtin elsewhere. Two other review items are not defects. The underscore ABI is exported on macOS: nm prints the Mach-O double underscore __Xdebug, the Darwin sed strips one to _Xdebug which the ^_X match keeps, and the macho formatter re-adds it (verified: all 7 _X* globals exported). The test twin's .so name matches this tree's compat-lib convention; .dylib is only autoconf-built Motif. Validated on macOS and Linux (docker ubuntu24, clang-18, GNU ld 2.42): check-unit, symbol-coverage, generator error-propagation, and make install with a codesign-valid stripped dylib.
Contributor
Author
|
Addressed in e9a1c5b. Fixed:
Not defects, so left as-is:
Validated on macOS and Linux (docker ubuntu 24.04, clang-18, GNU ld 2.42): |
libX11-compat exported every non-static symbol (~1100), leaking ~400
internal helpers into the dynamic table. Restrict the exported set to
the surface the project already enumerates, and shrink the library along
the way.
Generate a linker export list (ELF version script / Mach-O
-exported_symbols_list) from the union of {api,shim,private}-symbols.txt
(the core->libXft private contract) and whitebox-symbols.txt, intersected
with the symbols the build actually defines. The intersection keeps the
list valid under strict linkers (lld and binutils 2.43 default to
--no-undefined-version), so the manifests can stay a cross-platform
superset. GLX/FORMAT identity is tracked by a single link-config stamp
that regenerates the map and relinks on change.
Export the core-defined libX11 underscore ABI (_Xdebug, _XGetHostname,
...) by pattern: real libX11 exports those globals and legacy clients
link them directly (violawww's libIMG references _Xdebug), which the
X[A-Z]* manifests do not cover.
Shrink: -ffunction-sections/-fdata-sections plus --gc-sections /
-dead_strip collect code no exported symbol reaches, notably the
duplicated in-core Xft/Fc copy that only libXft-compat consumes.
Install-time strip -x slims the deployed libraries a further ~6% while
the dev build keeps local symbols for backtraces. A source pass marks 12
single-TU helpers static and deletes 2 dead functions.
Net exported surface: 727 (macOS) / 725 (Linux) = 682 public + 24 shim +
13 libXft-private + 7 underscore-ABI + 1 Motif-tier whitebox. Shipped
library 588,720 to 524,192 bytes installed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
libX11-compat exported every non-static symbol (~1100), leaking ~400 internal helpers into the dynamic table. Restrict the exported set to the surface the project already enumerates, and shrink the library along the way.
Generate a linker export list (ELF version script / Mach-O -exported_symbols_list) from the union of {api,shim,private}-symbols.txt (the core->libXft private contract) and whitebox-symbols.txt, intersected with the symbols the build actually defines. The intersection keeps the list valid under strict linkers (lld and binutils 2.43 default to --no-undefined-version), so the manifests can stay a cross-platform superset. GLX/FORMAT identity is tracked by a single link-config stamp that regenerates the map and relinks on change.
Export the core-defined libX11 underscore ABI (_Xdebug, _XGetHostname, ...) by pattern: real libX11 exports those globals and legacy clients link them directly (violawww's libIMG references _Xdebug), which the X[A-Z]* manifests do not cover.
Shrink: -ffunction-sections/-fdata-sections plus --gc-sections / -dead_strip collect code no exported symbol reaches, notably the duplicated in-core Xft/Fc copy that only libXft-compat consumes. Install-time strip -x slims the deployed libraries a further ~6% while the dev build keeps local symbols for backtraces. A source pass marks 12 single-TU helpers static and deletes 2 dead functions.
Net exported surface: 727 (macOS) / 725 (Linux) = 682 public + 24 shim + 13 libXft-private + 7 underscore-ABI + 1 Motif-tier whitebox. Shipped library 588,720 to 524,192 bytes installed.
Summary by cubic
Pin
libX11-compatexports to the intended API and dead-strip unused code to shrink the installed library (588,720 → 524,192 bytes). Keeps legacy_X*ABI available while hiding ~400 internal helpers.Refactors
tests/api-symbols.txt,tests/shim-symbols.txt,tests/private-symbols.txt, andtests/whitebox-symbols.txt, intersected with defined symbols; auto-regenerated on GLX/format changes; generator fails on missing/unreadable inputs.--gc-sectionson Linux and-exported_symbols_listwith-dead_stripon macOS; keep_X*ABI exported by pattern; addtests/test-xlibint-link.c.libX11-compat-test.sofor whitebox tests; shippedlibX11-compat.soremains pinned.-ffunction-sections -fdata-sections; mark 12 helpersstaticand remove 2 dead functions.libXft-compatlink with-Wl,--no-undefinedon Linux; gate off under-fsanitizebuilds.Migration
strip -x; on macOS they are re-signed after strip. OverrideSTRIP=:(or a custom tool) if needed.Written for commit 7851587. Summary will update on new commits.