Skip to content

Wheels: link FreeType against the bundled HarfBuzz - #9913

Open
akx wants to merge 1 commit into
python-pillow:mainfrom
akx:harfing
Open

Wheels: link FreeType against the bundled HarfBuzz#9913
akx wants to merge 1 commit into
python-pillow:mainfrom
akx:harfing

Conversation

@akx

@akx akx commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Follows up on #8497.

This came up as a side effect of #9909, where the last commit needed to increase the allowed comparison epsilon for the Arabic-language test, since different platforms in the CI stack would render it slightly differently... and it's a doozy! 😄

FreeType's autofitter can use HarfBuzz to work out which glyphs a script covers, so it can derive blue zones for scripts such as Arabic.

Only the Windows wheels were built that way. macOS passed --with-harfbuzz=no (so no HarfBuzz interop, no way, no how), and Linux left it unconfigured, which meant FreeType defaulted to dlopening HarfBuzz at runtime with the name "libharfbuzz.so.0".

However, auditwheel renames shared libraries to avoid conflicts, so the Linux wheels ended up with a FreeType that would only find HarfBuzz if the system had its own copy with the name "libharfbuzz.so.0".


In the current 12.3 wheel off PyPI, the interop symbols do not exist:

$ wget https://files.pythonhosted.org/packages/c7/da/32c752228ae345f489e3a42499d817b6c3996da7e8a3bc7a04fc806b243b/pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl
$ unzip pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl PIL/.dylibs/libfreetype.6.dylib
$ nm -u PIL/.dylibs/libfreetype.6.dylib | grep _hb_ot_
$

but in a wheel built by CI off this branch (see akx#18):

$ unzip 'dist-macOS arm64.zip'
Archive:  dist-macOS arm64.zip
  inflating: pillow-13.0.0.dev0-cp311-cp311-macosx_11_0_arm64.whl
  inflating: pillow-13.0.0.dev0-cp312-cp312-macosx_11_0_arm64.whl
  inflating: pillow-13.0.0.dev0-cp313-cp313-macosx_11_0_arm64.whl
  inflating: pillow-13.0.0.dev0-cp314-cp314-macosx_11_0_arm64.whl
  inflating: pillow-13.0.0.dev0-cp314-cp314t-macosx_11_0_arm64.whl
  inflating: pillow-13.0.0.dev0-cp315-cp315-macosx_11_0_arm64.whl
  inflating: pillow-13.0.0.dev0-cp315-cp315t-macosx_11_0_arm64.whl
  inflating: pillow-13.0.0.dev0-pp311-pypy311_pp73-macosx_11_0_arm64.whl
$ unzip pillow-13.0.0.dev0-cp314-cp314-macosx_11_0_arm64.whl PIL/.dylibs/libfreetype.6.dylib
$ nm -u PIL/.dylibs/libfreetype.6.dylib | grep _hb_ot_
_hb_ot_layout_collect_lookups
_hb_ot_layout_lookup_collect_glyphs
_hb_ot_layout_lookup_would_substitute
_hb_ot_tags_from_script_and_language
$

FreeType's autofitter can use HarfBuzz to work out which glyphs
a script covers, so it can derive blue zones for scripts such as Arabic.

Only the Windows wheels were built to allow that.
macOS passed --with-harfbuzz=no, and Linux left it unconfigured,
which meant FreeType defaulted to `dlopen`ing HarfBuzz at runtime
with the name "libharfbuzz.so.0".

`auditwheel`, part of the wheeling process, renames shared libraries
to avoid conflicts, so the Linux wheels ended up with a FreeType that
would only find HarfBuzz if the system had its own copy with the name
"libharfbuzz.so.0"; the bundled copy was never used.
@akx

This comment was marked as outdated.

fi
# FreeType and HarfBuzz each want the other:
# HarfBuzz reads font data through FreeType, and FreeType's autofitter asks HarfBuzz which glyphs a script covers.
# Break the cycle by building FreeType twice, so that the FreeType we ship is linked against the HarfBuzz we ship.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unusual that this should be required, right? Have FreeType or Harfbuzz discussed this anywhere?

@akx akx Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google search autocomplete (on a different device, on mobile right now) suggests https://www.google.com/search?q=freetype+harfbuzz+circular+dependency if you start typing "freetype harf", so that suggests it's a known thing.

Here's a recent-ish Debian bug about it https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1124239

Freetype notes the circular dependency in the release announcement for 2.14.0 on https://freetype.org/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants