Repository: python-pillow/Pillow

Issue:
Bad interaction between Homebrew and the freetype detection logic
The freetype detection logic in setup.py is interacting poorly with Homebrew's build environment (https://github.com/Homebrew/homebrew/pull/29096).

Basically, XQuartz has an older freetype that still has a `include/ft2build.h` header. This gets picked up first in this loop:

https://github.com/python-imaging/Pillow/blob/958397ae029048dba329b2ef1035b2a4a7b272d2/setup.py#L388-L396

however, our compiler wrappers strip out XQuartz paths by default. Since Homebrew's freetype is newer and only has `include/freetype2/ft2build.h`, the compiler then can't find the header and compilation fails.

I think the simplest and most correct fix would be to skip looking in XQuartz if Homebrew's freetype is detected. IOW, skip this:

https://github.com/python-imaging/Pillow/blob/958397ae029048dba329b2ef1035b2a4a7b272d2/setup.py#L224-L226

Thanks! Let me know if there is anything I can do to help.



Discussion:
@jacknagel Can you send a pull request? As long as the change doesn't affect other platforms, sounds good to me


Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -205,25 +205,31 @@ def build_extensions(self):
             # darwin ports installation directories
             _add_directory(library_dirs, "/opt/local/lib")
             _add_directory(include_dirs, "/opt/local/include")
-            
-            # if homebrew is installed, use its lib and include directories
+
+            # if Homebrew is installed, use its lib and include directories
             import subprocess
             try:
-                prefix = subprocess.check_output(['brew', '--prefix'])
-                if prefix:
-                    prefix = prefix.strip()
-                    _add_directory(library_dirs, os.path.join(prefix, 'lib'))
-                    _add_directory(include_dirs, os.path.join(prefix, 'include'))
-                    
-                    # freetype2 is a key-only brew under opt/
-                    _add_directory(library_dirs, os.path.join(prefix, 'opt', 'freetype', 'lib'))
-                    _add_directory(include_dirs, os.path.join(prefix, 'opt', 'freetype', 'include'))
+                prefix = subprocess.check_output(['brew', '--prefix']).strip()
             except:
-                pass # homebrew not installed
-            
-            # freetype2 ships with X11 (after homebrew, so that homebrew freetype is preferred)
-            _add_directory(library_dirs, "/usr/X11/lib")
-            _add_directory(include_dirs, "/usr/X11/include")
+                # Homebrew not installed
+                prefix = None
+
+            ft_prefix = None
+
+            if prefix:
+                # add Homebrew's include and lib directories
+                _add_directory(library_dirs, os.path.join(prefix, 'lib'))
+                _add_directory(include_dirs, os.path.join(prefix, 'include'))
+                ft_prefix = os.path.join(prefix, 'opt', 'freetype')
+
+            if ft_prefix and os.path.isdir(ft_prefix):
+                # freetype might not be linked into Homebrew's prefix
+                _add_directory(library_dirs, os.path.join(ft_prefix, 'lib'))
+                _add_directory(include_dirs, os.path.join(ft_prefix, 'include'))
+            else:
+                # fall back to freetype from XQuartz if Homebrew's freetype is missing
+                _add_directory(library_dirs, "/usr/X11/lib")
+                _add_directory(include_dirs, "/usr/X11/include")
 
         elif sys.platform.startswith("linux"):
             arch_tp = (plat.processor(), plat.architecture()[0])


Test patch: