Repository: python-pillow/Pillow

Issue:
Failure to build on macOS with Python 3.9.0
### What did you do?

I'm a Homebrew maintainer, trying to build Pillow as part of a Homebrew package: https://github.com/Homebrew/homebrew-core/pull/62795 on macOS with Python 3.9.0. This is one example, but other packages using Pillow fail in the same way.

### What did you expect to happen?

Compilation succeeds.

### What actually happened?

```
    The headers or library files could not be found for zlib,
    a required dependency when compiling Pillow from source.
```

### What are your OS, Python and Pillow versions?

* OS: macOS 10.13 to 10.15
* Python: 3.9.0
* Pillow: 7.2.0


Discussion:
In two days, on October 15, Pillow 8.0 is due to be released, along with corresponding Python 3.9 wheels. Will that solve your problem?
I have seen this merged PR: https://github.com/python-pillow/Pillow/pull/4842
As far as I understand it, the problem is not fixed by this PR, which is simply adding `/usr/local/opt/zlib/include` to the list of search paths. However, for most Homebrew users, the zlib package is *not* installed (and this directory does not exist), because most software on macOS links to system zlib.

The system zlib headers exist, and Pillow should be finding them and using them. It's also possible for Homebrew to give some help, by setting an appropriate environment variable: is there a suitable variable that Pillow would check?
> In two days, on October 15, Pillow 8.0 is due to be released, along with corresponding Python 3.9 wheels. Will that solve your problem?

My problem is building from source, so no, the wheels will not help.
> The system zlib headers exist, and Pillow should be finding them and using them.

If you think this is a silly question, please bear with me - where do they exist? What path are you referring to?
Not a silly question at all… the way that it works on recent macOS versions is very unusual. The toolchain can install multiple SDKs, with one SDK being "default", and there is nothing in `/usr/include`.

In 99% of cases, the `zlib` headers are in one of two places, namely:

```
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/zlib.h
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/zlib.h
```

The prefix for that can be obtained by running:

```
$ xcrun --show-sdk-path
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
```
So I guess the solution for Pillow, if it wants to look up header files, would be to try and run `xcrun --show-sdk-path`, and if works add `$(xcrun --show-sdk-path)/usr/include` to its search path.

In the meantime, is there an environment variable we could pass to the existing 7.2.0 version to unbreak our builds?
How about specifying the path through `python3.9 setup.py build_ext -I/a/b install`?
Hum, often we're not calling `setup.py` ourselves, it's done by `pip` or in some `Makefile`. Is there a suitable `PIP_INSTALL_PARAMS` that could work?
https://pillow.readthedocs.io/en/latest/installation.html#building-from-source
> If the prerequisites are installed in the standard library locations for your machine (e.g. /usr or /usr/local), no additional configuration should be required. If they are installed in a non-standard location, you may need to configure setuptools to use those locations by editing setup.py or setup.cfg, or by adding environment variables on the command line:
>
> CFLAGS="-I/usr/pkg/include" python3 -m pip install --upgrade Pillow
I've created PR #4974 to resolve this properly. Let us know if you have any feedback on that.
Adding `CFLAGS` seems to get the build past this stage. However, I get a later failure with:

```
    src/_imagingft.c:25:10: fatal error: 'ft2build.h' file not found
    #include <ft2build.h>
             ^~~~~~~~~~~~
```

We're never use `freetype` before for this build, and it used to pass. Does Pillow now require freetype? I would expect it to detect it and, if it does not find it, not use it.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -477,6 +477,18 @@ def build_extensions(self):
                 _add_directory(library_dirs, "/usr/X11/lib")
                 _add_directory(include_dirs, "/usr/X11/include")
 
+            # SDK install path
+            try:
+                sdk_path = (
+                    subprocess.check_output(["xcrun", "--show-sdk-path"])
+                    .strip()
+                    .decode("latin1")
+                )
+            except Exception:
+                sdk_path = None
+            if sdk_path:
+                _add_directory(library_dirs, os.path.join(sdk_path, "usr", "lib"))
+                _add_directory(include_dirs, os.path.join(sdk_path, "usr", "include"))
         elif (
             sys.platform.startswith("linux")
             or sys.platform.startswith("gnu")


Test patch: