macos: strip non-extern symbols at link time (CMake + mrbind)#6058
Merged
Conversation
`-Wl,-x` is the linker's equivalent of `strip -x` — drops local symbols (most of __LINKEDIT, ~67% of mrmeshpy.so) while keeping externs that dyld binds. Skipped in Debug. Affects every macOS distribution that consumes our libs (.whl, .pkg, NuGet, zip), not just wheels. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous `-s` skip-on-macos left mrmeshpy.so's 86 MB __LINKEDIT intact (about 70% of the wheel's macOS bloat). Apple's ld doesn't accept `-s`, but it does accept `-Wl,-x` (drops local symbols, keeps externs that dyld binds), the linker analog of `strip -x`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
adalisk-emikhaylov
approved these changes
May 7, 2026
Fedr
approved these changes
May 7, 2026
Grantim
added a commit
that referenced
this pull request
May 7, 2026
Companion to PR #6058. PR-A stripped our own libs at link; this strips the third-party deps that we bundle into wheels/.pkg/NuGet/etc. - Linux: VCPKG_LINKER_FLAGS_RELEASE -Wl,-s in x64+arm64 triplets so vcpkg ports drop .symtab/.strtab/.debug_* during their own release link (~15 MB across the bundled chain). Strip-at-link sidesteps the patchelf alignment bug that broke #6057's auditwheel --strip attempt. - macOS: chmod +w + strip -x every brew dylib in install_brew_requirements.sh so delocate-wheel/install_name_tool/.pkg copy already-trimmed binaries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
Grantim
added a commit
that referenced
this pull request
May 7, 2026
Companion to PR #6058. PR-A stripped our own libs at link; this strips the third-party deps that we bundle into wheels/.pkg/NuGet/etc. - Linux: VCPKG_LINKER_FLAGS_RELEASE -Wl,-s in x64+arm64 triplets so vcpkg ports drop .symtab/.strtab/.debug_* during their own release link (~15 MB across the bundled chain). Strip-at-link sidesteps the patchelf alignment bug that broke #6057's auditwheel --strip attempt. - macOS: chmod +w + strip -x every brew dylib in install_brew_requirements.sh so delocate-wheel/install_name_tool/.pkg copy already-trimmed binaries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2 tasks
Grantim
added a commit
that referenced
this pull request
May 7, 2026
Drops ~43 MB of __LINKEDIT (mostly local symbol names) from each bundled brew dylib that delocate copies into the wheel — verified ~−2.5 MB compressed / ~−44 MB uncompressed per macOS pip wheel. libopenvdb.dylib alone shrinks 61.7 MB → 20.7 MB. Per-file find loop, not `-exec ... +`: strip warns + exits 1 on signed dylibs, which would abort a batched invocation and leave later files unstripped. codesign re-signs ad-hoc so dyld doesn't SIGKILL on load. Companion to #6058 (our libs) and #6063 (linux third-party). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
Grantim
added a commit
that referenced
this pull request
May 7, 2026
* investigate: brew strip diagnostic on macOS Cellar PR #6063 v1 ran strip+codesign on brew dylibs but the resulting wheel's libopenvdb.dylib was byte-identical. Instrument the script to: count and total-size all Cellar dylibs before/after, sha256 a sample (libopenvdb), print codesign details, and run strip per-file with stderr captured. Goal: confirm whether bytes actually change on disk and what strip is saying when we can't see its output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * deps: strip + re-sign brew dylibs after install on macOS Drops ~43 MB of __LINKEDIT (mostly local symbol names) from each bundled brew dylib that delocate copies into the wheel — verified ~−2.5 MB compressed / ~−44 MB uncompressed per macOS pip wheel. libopenvdb.dylib alone shrinks 61.7 MB → 20.7 MB. Per-file find loop, not `-exec ... +`: strip warns + exits 1 on signed dylibs, which would abort a batched invocation and leave later files unstripped. codesign re-signs ad-hoc so dyld doesn't SIGKILL on load. Companion to #6058 (our libs) and #6063 (linux third-party). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Grantim
added a commit
that referenced
this pull request
May 7, 2026
…6063) * deps: strip third-party libs at install time (vcpkg + brew) Companion to PR #6058. PR-A stripped our own libs at link; this strips the third-party deps that we bundle into wheels/.pkg/NuGet/etc. - Linux: VCPKG_LINKER_FLAGS_RELEASE -Wl,-s in x64+arm64 triplets so vcpkg ports drop .symtab/.strtab/.debug_* during their own release link (~15 MB across the bundled chain). Strip-at-link sidesteps the patchelf alignment bug that broke #6057's auditwheel --strip attempt. - macOS: chmod +w + strip -x every brew dylib in install_brew_requirements.sh so delocate-wheel/install_name_tool/.pkg copy already-trimmed binaries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(brew strip): walk Cellar/ instead of lib/ \$BREW_PREFIX/lib contains only symlinks into Cellar/, so the previous find -type f matched nothing. Walking Cellar reaches the real .dylib files. Verified separately: linux vcpkg side stripped libopenvdb.so .strtab from 2.07 MB to 0; mac libopenvdb.dylib __LINKEDIT was unchanged because of this bug. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: retrigger CI (prepare-image was cancelled mid-flight) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(brew strip): re-sign dylibs with ad-hoc signature after strip strip invalidates the existing ad-hoc signature, and dyld then SIGKILLs any process trying to load the dylib (Apple Silicon enforces this hard). Symptom on the previous run: python3.10 -m ensurepip got Killed: 9. Fix: codesign --force --sign - immediately after strip in the same find chain. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * deps: drop macOS brew strip, scope PR to Linux only The macOS brew strip ran in CI but produced byte-identical libopenvdb.dylib in the wheel — strip+codesign on brew bottles appears to be a silent no-op, likely due to hardened-runtime signature handling. Linux savings (~3 MB compressed via vcpkg triplet -Wl,-s) are real and worth shipping; macOS investigation moves to a separate branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
The wheel-size investigation found that on macOS our shipped Mach-O binaries carry their full local symbol table in
__LINKEDIT. Onmrmeshpy.sothat's 86 MB out of 119 MB (72% of the file), with similar ratios onlibMRMesh/libMRViewer/libMRVoxels/libMRMcp/libMRIOExtras/etc. Linux strips by default; only macOS doesn't.This PR adds
-Wl,-x(the linker analog ofstrip -x— drops local symbols, keeps externs that dyld binds) on the macOS link line for non-Debug configs, in two places:cmake/Modules/CompilerOptions.cmake—add_link_options($<$<NOT:$<CONFIG:Debug>>:-Wl,-x>)in the existing Apple branch. Covers every CMake target (our libs,libMeshLibC2, in-tree thirdparty wrapped viaadd_subdirectory).scripts/mrbind/generate.mk:243— replaces$(if $(IS_MACOS),,-s)(which skipped strip on macOS because Apple'sldrejects-s) with$(if $(IS_MACOS),-Wl$(comma)-x,-s). Coversmrmeshpy.soand the other mrbind-generated Python bindings, which are linked outside the CMake tree.This benefits every macOS distribution — wheels, the
.pkginstaller'sMeshLib.framework, theruntimes/osx-*/native/slice of NuGet, the zip distribution. Replaces #6057 (a wheel-only attempt where the strip placement was ineffective).Verified savings — mac wheels (both archs)
.whl.whlmrmeshpy.so(the dominant binary) before/after:__TEXT__LINKEDIT__TEXTis byte-identical on both archs (sanity check: strip removed no code). Most of__LINKEDITis mangled symbol names — DEFLATE crushes them ~10×, so the ~80 MB uncompressed save lands as ~9 MB compressed on the wheel.Per-binary
__LINKEDIT(arm64; x86_64 deltas are within ±10% of these):mrmeshpy.solibMRViewer.dyliblibMRMesh.dyliblibMRVoxels.dyliblibMRMcp.dylibmrviewerpy.solibMRIOExtras.dylibEquivalent verification on the
.pkgfrommacos-build-test: every bundled dylib inMeshLib.frameworkis also stripped (e.g.,libMRMesh.dylib__LINKEDIT3.04 → 0.58 MB).mrmeshpy.soisn't in the.pkg(only the framework C++ libs + companion Python modules are), but the same lever benefits anyone consuming the framework or NuGet.Test plan
CI under
full-ci+test-pip-buildproduces all relevant artifacts:macos-build-test (arm64, Release)greenmacos-build-test (x64, Release)greenmacos-build-test (arm64, Debug)green (Debug skips strip — confirmed via generator expression)test-pip-build / macos-pip-build (arm64)greentest-pip-build / macos-pip-build (x86)greentest-pip-build / macos-pip-test (arm64, ...)green (6 Python versions)test-pip-build / macos-pip-test (x86, ...)green (6 Python versions)mrmeshpy.so__LINKEDITshrinks ~98% on both archs__TEXTbyte-identical on every binaryDistributives_macos-arm.pkgframework dylibs also strippedRisk
Low.
-Wl,-xis the standard release-build linker option used by Apple's own SDK and most C++ projects shipping macOS dylibs. Doesn't affect dyld linkage, exception unwinding (CFI tables live in__TEXT's__unwind_info/__eh_frame),__cxa_*lookups (in__DATA_CONST), or pybind11 entry points (PyInit_*is extern). All 12 macos-pip-test jobs (2 archs × 6 Python versions) pass —import meshlib.mrmeshpyand friends all work after dyld linkage. Rollback is a one-line revert per file.Follow-up
PR-B (separate) will strip third-party deps that we consume (vcpkg-installed libs on Linux+Windows via triplet linker flag, brew-installed dylibs on macOS via CI post-install strip).
🤖 Generated with Claude Code