Skip to content

macOS: build libzip from submodule against Homebrew zlib-ng-compat#5950

Closed
Fedr wants to merge 7 commits intomasterfrom
ci/macos-zlib-ng-compat
Closed

macOS: build libzip from submodule against Homebrew zlib-ng-compat#5950
Fedr wants to merge 7 commits intomasterfrom
ci/macos-zlib-ng-compat

Conversation

@Fedr
Copy link
Copy Markdown
Contributor

@Fedr Fedr commented Apr 21, 2026

Summary

Routes macOS's compressZip / MRZlib hot path through zlib-ng (compat mode), without adding any new submodule.

  • Build the existing thirdparty/libzip submodule (pinned to v1.11.4) on macOS as well as Emscripten. Other platforms continue to pick up libzip from apt / brew / vcpkg.
  • Swap the Homebrew zlib requirement for zlib-ng-compat, which installs a drop-in libz.dylib / zlib.h / zlib.pc. The formula is keg_only :shadowed_by_macos, so scripts/build_thirdparty.sh and scripts/build_source.sh now export ZLIB_ROOT=\$(brew --prefix zlib-ng-compat) on darwin.
  • libzip's internal find_package(ZLIB) and MRMesh's top-level find_package(ZLIB) both resolve to zlib-ng-compat on macOS. The Emscripten path is untouched (still uses -s USE_ZLIB=1).
  • libzip is dropped from requirements/macos.txt (we build our own), and zlib is replaced by zlib-ng-compat (drop-in).

Benchmark precedent: on Rocky (#5932 + #5933 measurement), the same substitution produced ~60%+ speedup on `MRMesh.CompressSphereToZip` / `MRMesh.CompressManySmallFilesToZip`.

Why scoped to macOS only: apt, Rocky-vcpkg and Windows-vcpkg each need their own mechanism (#5932 is the vcpkg-overlay side; apt would need a submodule zlib-ng). This PR lands cleanly without extra submodules or overlay ports because brew already packages `zlib-ng-compat`.

Test plan

  • macOS x64 Release + macOS arm64 Debug + arm64 Release CI green
  • Verify `brew install zlib-ng-compat` is picked up by macOS workflow without requiring `brew link --overwrite`
  • Confirm `MRMesh.CompressSphereToZip` and `MRMesh.CompressManySmallFilesToZip` timings (from test: add compress-to-zip tests #5933) show the expected drop vs. previous runs
  • Ensure C++ / C examples and NuGet patch steps still pass

Related

🤖 Generated with Claude Code

Previously macOS picked up libzip from Homebrew, which is linked against
Homebrew's stock zlib. To get zlib-ng's deflate into the compressZip hot
path on macOS, we now build the thirdparty/libzip submodule (already
pinned to v1.11.4) on macOS as well, and swap the brew 'zlib' requirement
for the 'zlib-ng-compat' drop-in replacement. The replacement formula is
keg-only, so scripts/build_{thirdparty,source}.sh export ZLIB_ROOT
pointing at its keg prefix; both libzip's internal find_package(ZLIB) and
MRMesh's top-level find_package(ZLIB) then resolve to zlib-ng.

No changes on other platforms.
Fedr added 2 commits April 21, 2026 20:36
MRMesh.ZlibCompressStats pinned stats.compressedSize against the size of
the stock-zlib reference blobs (cRawLevel9 / cWrappedLevel9). zlib-ng's
deflate matcher emits 1-2 bytes less for the same input at the same
level, which is a valid, lossless re-encoding but trips the equality
check on any build that links zlib-ng instead of stock zlib (e.g. the
macOS zlib-ng-compat swap in this PR, or the vcpkg zlib-ng overlay in
#5932).

Keep the engine-independent assertions (CRC-32, uncompressed size,
internal consistency between stats.compressedSize and the stream write
count) and relax compressed-size to a ±4-byte window around the
reference. The parametrized ZlibCompress / ZlibDecompress suites
already run a round-trip check, which catches any real encoder
regression.
After dropping libzip from Homebrew requirements in favour of the
thirdparty/libzip submodule build, the main MeshLib cmake invocation
(a separate process from the thirdparty build) could no longer locate
libzipConfig.cmake: it lives under MESHLIB_THIRDPARTY_ROOT_DIR/lib/cmake/
libzip/, which is not on CMake's default find_package search path on a
macOS runner without a stale Homebrew libzip in /opt/homebrew. The
x64 Release legs happened to have such a stale copy; arm64 Debug did
not, exposing the bug.

Fix: pass HINTS pointing at the thirdparty install location. Same
pattern already used for libdeflate in #5952; harmless on vcpkg-based
configurations because their toolchain file supplies CMAKE_PREFIX_PATH
ahead of the hint.
@Fedr
Copy link
Copy Markdown
Contributor Author

Fedr commented Apr 23, 2026

Closing in favour of #5959 (zlib-ng native, cross-platform). Comparison summary of MRMesh.CompressSphereToZip wallclock on macOS — the platform this PR uniquely targeted:

Platform master / stock zlib #5950 zlib-ng-compat #5959 zlib-ng native
macOS x64 Release 1317 ms 639 ms 665 ms
macOS arm64 Release 822 ms 302 ms 294 ms
macOS arm64 Debug 4920 ms 4116 ms 2886 ms

Release legs are within noise. arm64 Debug actually favours #5959 by ~30 % (4116 ms vs 2886 ms).

On top of that, #5950 meaningfully increases build time on every macOS run because it stops using Homebrew's pre-built libzip bottle and instead builds thirdparty/libzip from submodule in every image / workflow invocation — paid once per macOS CI job. #5959 doesn't incur that cost: libzip stays on the brew bottle and only adds a small thirdparty/zlib-ng submodule (built once inside the image, then cached).

Combined with the cross-platform coverage (all five platform families vs macOS-only), #5959 is strictly the better path. Closing this PR and its branch.

@Fedr Fedr closed this Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant