recipes: flet-libwebp 1.6.0 + Pillow WebP support - #119
Merged
Merged
Conversation
Adds libwebp so Pillow (and anything else that wants it) can read and write WebP on device. 1.6.0 is not the newest for its own sake — it is the version Pillow 12.2.0 pins in depends/install_webp.sh, so we track what upstream tests against. Autotools, not CMake, and the reason is Android rather than taste. libwebp's CMakeLists sets SOVERSION unconditionally, producing libwebp.so.7, which APK packaging will not carry; configure goes through libtool, whose linux*android* case sets version_type=none and yields a bare libwebp.so. The Google release tarball is a `make dist` artifact with a pre-generated configure, so there is no autoreconf or autopoint step to go wrong. Two lines in build.sh are load-bearing, each having fixed a real failure: --prefix at configure time, not `make install prefix=`. The latter passed on all three iOS slices and failed on all three Android ones with "cannot install 'libwebp.la' to a directory not ending in /usr/local/lib" — iOS is static-only so libtool never relinks, while Android's libwebp.la links libsharpyuv.la and trips libtool's rpath consistency check. hardcode_into_libs=no. Without it every Android .so carried RUNPATH /Users/<me>/.../wheel/opt/lib, which on CI would publish /home/runner/work/... inside the wheel. A grep guard follows the sed, because the silent failure mode is a published wheel with build-machine paths in it. Android ships the shared libraries and iOS the static ones, matching how each platform resolves them: flet stages .so files into jniLibs, while iOS absorbs the archives into the consuming extension. That split also disposes of the sharpyuv question — on Android libwebp.so declares libsharpyuv.so as its own DT_NEEDED so the symbols resolve transitively, and on iOS Pillow's setup.py already appends -lsharpyuv under `sys.platform == "ios"`. No consumer patch is needed on either. licence_file names COPYING and PATENTS explicitly: PATENTS is the additional IP grant every source header points at, and the automatic search matches COPYING* but not it. 6/6 slices green, including armeabi-v7a.
Answers flet-dev/flet#6806. Our Pillow shipped PIL/_webp.pyi and no PIL/_webp.*.so, so Image.open() on a WebP warned "WEBP support not installed" and then raised UnidentifiedImageError — the requester's diagnosis was correct. Two lines. WebP was never force-disabled the way brotli, raqm and fribidi are in setup-12.x.patch; it was off only because feature detection found no libwebp. Declaring the host dep is enough — the recipe already feeds CPATH/LIBRARY_PATH at {platlib}/opt/{include,lib} on Android and iOS resolves through sysconfig — so the patch is untouched. Nine tests, network-free, with three fixtures totalling 382 bytes. They cover more than "it links": lossless decode asserts exact quadrant colours, lossy decode allows a VP8 tolerance, and the round-trip tests check the RIFF container tag (VP8L for lossless, VP8X for the alpha case). The EXIF test exercises libwebpmux and the animation tests exercise libwebpdemux and libwebpmux, so all three sub-libraries are proven at runtime rather than merely present on the link line. Verified 11/11 EXIT 0 on an Android arm64 emulator and an iOS 18.6 simulator, and 11/11 on desktop Pillow so the assertions are not device-specific. The Android _webp.so links libwebp/libwebpmux/libwebpdemux and the four libraries stage into lib/arm64-v8a/; the iOS extension absorbs them statically, 634 KB against Android's 27 KB, linking only system libraries. build.number 2: the upstream version is unchanged, the recipe is not.
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.
Adds libwebp and rebuilds Pillow against it, so
Image.open()andImage.save()handle WebP on device. Requested in flet#6806.Our Pillow shipped
PIL/_webp.pyiand noPIL/_webp.*.so, so opening a WebP warnedWEBP support not installedand then raisedUnidentifiedImageError. The requester's diagnosis was correct.Why not the
webppackage that was asked forThe request names
webp(anibali/pywebp). Building it would have satisfied the title and not the complaint: it registers no PIL plugin — zeroregister_open/register_extensioncalls inwebp/__init__.py— soPIL.Image.open()would still have raised the same error. It also declaresconan>=2.0inbuild-system.requires, with an arch list containing no Android ABI and the target derived from the build host'splatform.machine(), so cross-compiling it means patching conan out and injecting our own libwebp — i.e. writingflet-libwebpanyway and then bolting a second binding on top.What declining it costs: pywebp's byte-budget encoding (
WebPConfig.target_size/passes) and zero-copy decode into a preallocated numpy array. Animated WebP encode and decode were the strongest argument for it, and they don't survive reading the source —WebPImagePlugin.pybindsWebPAnimDecoder/WebPAnimEncoder, so Pillow already has both.Recipe shape
Autotools, not CMake, for an Android reason rather than a stylistic one: libwebp's
CMakeListscallsset_version()unconditionally, producinglibwebp.so.7, which APK packaging will not carry. configure goes through libtool, whoselinux*android*case setsversion_type=noneand yields a barelibwebp.so. The Google release tarball is amake distartifact with a pre-generatedconfigure, so there is no autoreconf/autopoint step.1.6.0 is not the newest for its own sake — it is the version Pillow 12.2.0 pins in
depends/install_webp.sh, so we track what upstream tests against.Two lines in
build.share load-bearing, each having fixed a real failure:--prefixat configure time, notmake install prefix=. The latter passed on all three iOS slices and failed on all three Android ones withcannot install `libwebp.la` to a directory not ending in /usr/local/lib— iOS is static-only so libtool never relinks, while Android'slibwebp.lalinkslibsharpyuv.laand trips libtool's rpath consistency check.hardcode_into_libs=no. Without it every Android.socarriedRUNPATH /Users/<me>/…/wheel/opt/lib, which on CI would publish/home/runner/work/…inside the wheel. Agrepguard follows the sed, because the silent failure mode is a published wheel with build-machine paths in it.Android ships the shared libraries and iOS the static ones, matching how each resolves them. That split also disposes of sharpyuv without a consumer patch: on Android
libwebp.sodeclareslibsharpyuv.soas its ownDT_NEEDEDso symbols resolve transitively (llvm-readelfshows 0 sharpyuv references in_webp.so), and on iOS Pillow'ssetup.pyalready appends-lsharpyuvundersys.platform == "ios".license_filenamesCOPYINGandPATENTSexplicitly. Auto-discovery would findCOPYINGand silently dropPATENTS, which every libwebp source header points at as the additional patent grant.Pillow
Two lines: the host dep and
build.number: 2. No patch change. WebP was never force-disabled the way brotli/raqm/fribidi are insetup-12.x.patch; it was off only because feature detection found no libwebp, and the recipe already feedsCPATH/LIBRARY_PATHat{platlib}/opt/{include,lib}on Android while iOS resolves through sysconfig.Nine tests, network-free, with three fixtures totalling 382 bytes. They prove more than linkage: lossless decode asserts exact quadrant colours, lossy decode allows a VP8 tolerance, and the round-trips check the RIFF container tag (
VP8Llossless,VP8Xfor the alpha case). The EXIF test exercises libwebpmux and the animation tests exercise libwebpdemux and libwebpmux, so all three sub-libraries are proven at runtime.