Skip to content

Commit bdced75

Browse files
authored
build: export only the public API on Windows, not every symbol (#79)
-Wl,--export-all-symbols dumped every internal helper (FSE_*, HUF_*, COVER_*, ...) into the PE export table alongside the real public API - inconsistent with the tight -fvisibility=hidden surface built for ELF/Mach-O. zstd.h already gates its public API on ZSTD_DLL_EXPORT: with it defined, ZSTDLIB_API expands to __declspec(dllexport) for exactly the symbols tagged in zstd.h, the PE equivalent of ZSTDLIB_VISIBLE. Switch Windows to -DZSTD_DLL_EXPORT=1 and keep -fvisibility=hidden on (it also governs whether lld auto-exports undecorated globals on PE) instead of --export-all-symbols. Verified against a cross-compiled windows-x86_64 libzstd.dll: export count drops from 576 to 185 symbols, and every ZSTD_*/ZDICT_* symbol the Java bindings actually call (77, cross-checked against Bindings.java) is still present.
1 parent 955dc96 commit bdced75

1 file changed

Lines changed: 9 additions & 4 deletions

File tree

scripts/build-zstd.sh

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,14 @@ trap 'rm -rf "$WORK"' EXIT
9898
# -DZSTD_MULTITHREAD off -> single-threaded, no pthread dependency (hermetic)
9999
# -DXXH_NAMESPACE -> matches zstd's own build, avoids xxhash symbol clashes
100100
# ELF/Mach-O: -fvisibility=hidden + zstd's ZSTDLIB_VISIBLE keeps the surface
101-
# minimal. Windows/MinGW: drop hidden visibility and let lld auto-export every
102-
# symbol into the PE export table (the classic, reliable MinGW DLL path).
101+
# minimal. Windows/MinGW: -fvisibility=hidden stays on too (it governs whether
102+
# lld auto-exports undecorated globals on PE, same as ELF/Mach-O) and
103+
# -DZSTD_DLL_EXPORT=1 flips zstd.h's ZSTDLIB_API to __declspec(dllexport) for
104+
# just the public API - the PE analogue of ZSTDLIB_VISIBLE, giving the same
105+
# tight export set on all three platforms instead of dumping every internal
106+
# symbol (FSE_*, HUF_*, COVER_*, ...) into the DLL's export table.
103107
VIS_FLAG="-fvisibility=hidden"
108+
DLL_EXPORT_FLAG=""
104109
LINK_EXTRA=""
105110
# Strip the symbol/debug tables at link time. An unstripped ELF .so carries full
106111
# debug_info and is ~6x larger than needed (4.0M -> ~250K); -s drops it. PE/COFF
@@ -109,7 +114,7 @@ LINK_EXTRA=""
109114
# those are deleted after the link below rather than suppressed via strip.
110115
STRIP_FLAG="-s"
111116
case "$CLASSIFIER" in
112-
windows-*) VIS_FLAG=""; LINK_EXTRA="-Wl,--export-all-symbols"; STRIP_FLAG="" ;;
117+
windows-*) DLL_EXPORT_FLAG="-DZSTD_DLL_EXPORT=1"; STRIP_FLAG="" ;;
113118
# Full RELRO + immediate binding: GOT is remapped read-only after startup
114119
# relocation, closing off the classic GOT-overwrite exploit primitive.
115120
# ELF-only (-z is a GNU ld/lld ELF flag; Mach-O/PE have no equivalent).
@@ -129,7 +134,7 @@ esac
129134
# zstd_v0{1,2,3}.c decoders per legacy/zstd_legacy.h) — those predate zstd's
130135
# 1.0 stabilization and are vanishingly unlikely to show up in the wild.
131136
CFLAGS="-O3 $ARCH_FLAG -DNDEBUG -DZSTD_LEGACY_SUPPORT=4 -DXXH_NAMESPACE=ZSTD_ $VIS_FLAG \
132-
-I$ZSTD_LIB -I$ZSTD_LIB/common -fPIC"
137+
$DLL_EXPORT_FLAG -I$ZSTD_LIB -I$ZSTD_LIB/common -fPIC"
133138

134139
# xargs -P keeps all $JOBS slots saturated (a fixed-size batch-then-wait loop
135140
# idles every other core behind the batch's slowest TU) and, unlike bare `&` +

0 commit comments

Comments
 (0)