diff --git a/requirements/macos.txt b/requirements/macos.txt index 9324a774689d..a45cbb84af45 100644 --- a/requirements/macos.txt +++ b/requirements/macos.txt @@ -11,7 +11,6 @@ jsoncpp libharu libpng libtiff -libzip llvm@14 ninja opencascade @@ -23,4 +22,4 @@ spdlog tbb tinyxml2 tl-expected -zlib +zlib-ng-compat diff --git a/scripts/build_source.sh b/scripts/build_source.sh index bb1bd4a4d783..f5799d9426cc 100755 --- a/scripts/build_source.sh +++ b/scripts/build_source.sh @@ -92,6 +92,13 @@ if [[ $OSTYPE == 'darwin'* ]]; then -D PYTHON_INCLUDE_DIR=${PYTHON_INCLUDE_DIR} \ -D PYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} \ " + + # Homebrew's zlib-ng-compat is keg-only; point CMake at it so MRMesh's + # find_package(ZLIB) resolves to zlib-ng rather than the macOS system zlib. + ZLIB_NG_COMPAT_PREFIX=$(brew --prefix zlib-ng-compat 2>/dev/null || true) + if [ -n "${ZLIB_NG_COMPAT_PREFIX}" ] && [ -d "${ZLIB_NG_COMPAT_PREFIX}" ]; then + MR_CMAKE_OPTIONS="${MR_CMAKE_OPTIONS} -D ZLIB_ROOT=${ZLIB_NG_COMPAT_PREFIX}" + fi fi if [[ $OSTYPE == 'darwin'* ]]; then diff --git a/scripts/build_thirdparty.sh b/scripts/build_thirdparty.sh index fa1a3c760a00..391a27aa0324 100755 --- a/scripts/build_thirdparty.sh +++ b/scripts/build_thirdparty.sh @@ -100,6 +100,15 @@ fi if [[ $OSTYPE == 'darwin'* ]]; then NPROC=$(sysctl -n hw.logicalcpu) + # Homebrew's zlib-ng-compat is keg-only (shadowed by macOS system zlib), + # so CMake's find_package(ZLIB) won't pick it up unless we point at its + # keg prefix explicitly. We want our libzip submodule (built just below) + # and MeshLib's own ZLIB::ZLIB consumers to link against zlib-ng, not the + # macOS-provided zlib. + ZLIB_NG_COMPAT_PREFIX=$(brew --prefix zlib-ng-compat 2>/dev/null || true) + if [ -n "${ZLIB_NG_COMPAT_PREFIX}" ] && [ -d "${ZLIB_NG_COMPAT_PREFIX}" ]; then + MR_CMAKE_OPTIONS="${MR_CMAKE_OPTIONS} -D ZLIB_ROOT=${ZLIB_NG_COMPAT_PREFIX}" + fi else NPROC=$(nproc) fi diff --git a/source/MRMesh/CMakeLists.txt b/source/MRMesh/CMakeLists.txt index 3621ac029714..9cbf90a8ec7e 100644 --- a/source/MRMesh/CMakeLists.txt +++ b/source/MRMesh/CMakeLists.txt @@ -55,8 +55,15 @@ find_package(ZLIB REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE ZLIB::ZLIB) # libzip prior to version 1.11.4 has incorrect CMake config that requires libzip tools to be installed IF(MESHLIB_USE_VCPKG OR APPLE OR EMSCRIPTEN) - # vcpkg, homebrew, and submodule versions are already updated - find_package(libzip REQUIRED) + # vcpkg, homebrew, and submodule versions are already updated. + # On APPLE (and EMSCRIPTEN) we build libzip from thirdparty/libzip and + # install it to MESHLIB_THIRDPARTY_ROOT_DIR, which is not on CMake's default + # find_package search path, so hint it explicitly. The hint is harmless on + # vcpkg-based configurations (they still find the vcpkg-supplied libzip + # via the toolchain-provided CMAKE_PREFIX_PATH). + find_package(libzip REQUIRED + HINTS ${MESHLIB_THIRDPARTY_ROOT_DIR}/lib/cmake/libzip + ) ELSE() # on Ubuntu LTS (22.04, 24.04) we have to use pkg-config instead find_package(PkgConfig REQUIRED) diff --git a/source/MRTest/MRZipCompressTests.cpp b/source/MRTest/MRZipCompressTests.cpp index f8b27379d917..2ec47f238475 100644 --- a/source/MRTest/MRZipCompressTests.cpp +++ b/source/MRTest/MRZipCompressTests.cpp @@ -27,7 +27,7 @@ TEST( MRMesh, CompressSphereToZip ) UniqueTemporaryFolder srcFolder; ASSERT_TRUE( bool( srcFolder ) ); - constexpr int targetVerts = 1000; // increase it to make the file being compressed larger, 100'000 vertices -> 12M bytes + constexpr int targetVerts = 100000; // increase it to make the file being compressed larger, 100'000 vertices -> 12M bytes SphereParams params; params.radius = 1.0f; params.numMeshVertices = targetVerts; @@ -81,9 +81,9 @@ TEST( MRMesh, CompressManySmallFilesToZip ) ASSERT_TRUE( bool( srcFolder ) ); // increase both below numbers to make the files being compressed larger, 200 * 2 files * 60'000 bytes -> 24M bytes - constexpr int numBinaryFiles = 20; + constexpr int numBinaryFiles = 200; constexpr int numJsonFiles = numBinaryFiles; - constexpr size_t bytesPerFile = 6000; + constexpr size_t bytesPerFile = 60000; // Simple LCG used to produce deterministic pseudo-random bytes. // Keeps the test reproducible across runs and platforms while avoiding diff --git a/source/MRTest/MRZlibTests.cpp b/source/MRTest/MRZlibTests.cpp index c4b6bf1724b9..8125d151b625 100644 --- a/source/MRTest/MRZlibTests.cpp +++ b/source/MRTest/MRZlibTests.cpp @@ -157,8 +157,14 @@ TEST( MRMesh, ZlibCompressStats ) EXPECT_EQ( stats.crc32, expectedCrc ); EXPECT_EQ( stats.uncompressedSize, sizeof( cInput ) ); - EXPECT_EQ( stats.compressedSize, c.expectedCompSize ); - EXPECT_EQ( out.str().size(), c.expectedCompSize ); + // Compressed size is not pinned to an exact reference: different + // deflate implementations (stock zlib, zlib-ng, etc.) may encode the + // same input into equivalently valid but slightly differently sized + // output. The internal-consistency check + a small ± window around + // the stock-zlib reference is enough. + EXPECT_EQ( stats.compressedSize, out.str().size() ); + EXPECT_GE( stats.compressedSize, c.expectedCompSize - 4 ); + EXPECT_LE( stats.compressedSize, c.expectedCompSize + 4 ); } } diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index e4734cf29af3..c30842550e68 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -96,14 +96,25 @@ IF(EMSCRIPTEN) set(GDCM_BUILD_TESTING OFF) set(GDCM_BUILD_DOCBOOK_MANPAGES OFF) add_subdirectory(./GDCM) +ENDIF() +# Build libzip from our submodule on Emscripten (no system libzip available) +# and on macOS (so we can link it against Homebrew's zlib-ng-compat drop-in +# replacement for zlib, reached via ZLIB_ROOT / CMAKE_PREFIX_PATH from the +# build scripts). Other platforms still pick libzip up from apt/brew/vcpkg. +IF(EMSCRIPTEN OR APPLE) set(BUILD_TOOLS OFF CACHE BOOL "") set(BUILD_REGRESS OFF CACHE BOOL "") set(BUILD_EXAMPLES OFF CACHE BOOL "") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s USE_ZLIB=1") + IF(EMSCRIPTEN) + # Emscripten ships a bundled zlib port activated by this flag. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s USE_ZLIB=1") + ENDIF() set(LIBZIP_DO_INSTALL ON) add_subdirectory(./libzip) +ENDIF() +IF(EMSCRIPTEN) set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_DISABLE_EXCEPTION_CATCHING=1") set(JSONCPP_WITH_TESTS OFF)