From 4f734d295f7ce2e31c650e1971b45dae7f19c8d1 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 20 May 2023 15:38:36 +1000 Subject: [PATCH 1/4] Use --config-settings instead of deprecated --global-option --- .github/workflows/test-mingw.yml | 2 +- MANIFEST.in | 1 + Makefile | 4 ++-- _custom_build/backend.py | 31 +++++++++++++++++++++++++++++++ docs/installation.rst | 24 ++++++++++++------------ pyproject.toml | 4 ++++ 6 files changed, 51 insertions(+), 15 deletions(-) create mode 100755 _custom_build/backend.py create mode 100644 pyproject.toml diff --git a/.github/workflows/test-mingw.yml b/.github/workflows/test-mingw.yml index a109ec0d8b5..5a737a1ee89 100644 --- a/.github/workflows/test-mingw.yml +++ b/.github/workflows/test-mingw.yml @@ -80,7 +80,7 @@ jobs: pushd depends && ./install_extra_test_images.sh && popd - name: Build Pillow - run: SETUPTOOLS_USE_DISTUTILS="stdlib" CFLAGS="-coverage" python3 -m pip install --global-option="build_ext" . + run: SETUPTOOLS_USE_DISTUTILS="stdlib" CFLAGS="-coverage" python3 -m pip install . - name: Test Pillow run: | diff --git a/MANIFEST.in b/MANIFEST.in index f51551303f6..606e7e074aa 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -15,6 +15,7 @@ graft src graft depends graft winbuild graft docs +graft _custom_build # build/src control detritus exclude .appveyor.yml diff --git a/Makefile b/Makefile index e41f3641108..776649b2834 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ install: .PHONY: install-coverage install-coverage: - CFLAGS="-coverage -Werror=implicit-function-declaration" python3 -m pip -v install --global-option="build_ext" . + CFLAGS="-coverage -Werror=implicit-function-declaration" python3 -m pip -v install . python3 selftest.py .PHONY: debug @@ -74,7 +74,7 @@ debug: # for our stuff, kills optimization, and redirects to dev null so we # see any build failures. make clean > /dev/null - CFLAGS='-g -O0' python3 -m pip -v install --global-option="build_ext" . > /dev/null + CFLAGS='-g -O0' python3 -m pip -v install . > /dev/null .PHONY: release-test release-test: diff --git a/_custom_build/backend.py b/_custom_build/backend.py new file mode 100755 index 00000000000..31a954824b9 --- /dev/null +++ b/_custom_build/backend.py @@ -0,0 +1,31 @@ +import sys + +from setuptools.build_meta import * # noqa: F401, F403 +from setuptools.build_meta import _BuildMetaBackend + + +class _CustomBuildMetaBackend(_BuildMetaBackend): + def run_setup(self, setup_script="setup.py"): + if self.config_settings: + flags = [] + for key in ("enable", "disable", "vendor"): + settings = self.config_settings.get(key) + if settings: + if not isinstance(settings, list): + settings = [settings] + for value in settings: + flags.append("--" + key + "-" + value) + if self.config_settings.get("debug") == "true": + flags.append("--debug") + if flags: + sys.argv = sys.argv[:1] + ["build_ext"] + flags + sys.argv[1:] + return super().run_setup(setup_script) + + def build_wheel( + self, wheel_directory, config_settings=None, metadata_directory=None + ): + self.config_settings = config_settings + return super().build_wheel(wheel_directory, config_settings, metadata_directory) + + +build_wheel = _CustomBuildMetaBackend().build_wheel diff --git a/docs/installation.rst b/docs/installation.rst index ad27b67eeaf..514d20e7422 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -380,40 +380,40 @@ Build Options using a setting of 1. By default, it uses 4 CPUs, or if 4 are not available, as many as are present. -* Build flags: ``--disable-zlib``, ``--disable-jpeg``, - ``--disable-tiff``, ``--disable-freetype``, ``--disable-raqm``, - ``--disable-lcms``, ``--disable-webp``, ``--disable-webpmux``, - ``--disable-jpeg2000``, ``--disable-imagequant``, ``--disable-xcb``. +* Config settings: ``-C disable=zlib``, ``-C disable=jpeg``, + ``-C disable=tiff``, ``-C disable=freetype``, ``-C disable=raqm``, + ``-C disable=lcms``, ``-C disable=webp``, ``-C disable=webpmux``, + ``-C disable=jpeg2000``, ``-C disable=imagequant``, ``-C disable=xcb``. Disable building the corresponding feature even if the development libraries are present on the building machine. -* Build flags: ``--enable-zlib``, ``--enable-jpeg``, - ``--enable-tiff``, ``--enable-freetype``, ``--enable-raqm``, - ``--enable-lcms``, ``--enable-webp``, ``--enable-webpmux``, - ``--enable-jpeg2000``, ``--enable-imagequant``, ``--enable-xcb``. +* Config settings: ``-C enable=zlib``, ``-C enable=jpeg``, + ``-C enable=tiff``, ``-C enable=freetype``, ``-C enable=raqm``, + ``-C enable=lcms``, ``-C enable=webp``, ``-C enable=webpmux``, + ``-C enable=jpeg2000``, ``-C enable=imagequant``, ``-C enable=xcb``. Require that the corresponding feature is built. The build will raise an exception if the libraries are not found. Webpmux (WebP metadata) relies on WebP support. Tcl and Tk also must be used together. -* Build flags: ``--vendor-raqm``, ``--vendor-fribidi``. +* Config settings: ``-C vendor=raqm``, ``-C vendor=fribidi``. These flags are used to compile a modified version of libraqm and a shim that dynamically loads libfribidi at runtime. These are used to compile the standard Pillow wheels. Compiling libraqm requires a C99-compliant compiler. -* Build flag: ``--disable-platform-guessing``. Skips all of the +* Build flag: ``-C disable=platform-guessing``. Skips all of the platform dependent guessing of include and library directories for automated build systems that configure the proper paths in the environment variables (e.g. Buildroot). -* Build flag: ``--debug``. Adds a debugging flag to the include and +* Build flag: ``-C debug=true``. Adds a debugging flag to the include and library search process to dump all paths searched for and found to stdout. Sample usage:: - python3 -m pip install --upgrade Pillow --global-option="build_ext" --global-option="--enable-[feature]" + python3 -m pip install --upgrade Pillow -C enable=[feature] Platform Support ---------------- diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000000..cf31b6407ee --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,4 @@ +[build-system] +requires = ["setuptools >= 40.8.0", "wheel"] +build-backend = "backend" +backend-path = ["_custom_build"] From 18da2d0b2d01ab7bf9371451416379c0edca84f4 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 20 May 2023 15:19:58 +1000 Subject: [PATCH 2/4] Removed inplace target --- Makefile | 5 ----- tox.ini | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 776649b2834..57d756b47e3 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,6 @@ help: @echo " docserve run an HTTP server on the docs directory" @echo " html make HTML docs" @echo " htmlview open the index page built by the html target in your browser" - @echo " inplace make inplace extension" @echo " install make and install" @echo " install-coverage make and install with C coverage" @echo " lint run the lint checks" @@ -54,10 +53,6 @@ help: @echo " release-test run code and package tests before release" @echo " test run tests on installed Pillow" -.PHONY: inplace -inplace: clean - python3 -m pip install -e --global-option="build_ext" --global-option="--inplace" . - .PHONY: install install: python3 -m pip -v install . diff --git a/tox.ini b/tox.ini index 458a0010734..a79089f5177 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ extras = tests commands = make clean - {envpython} -m pip install --global-option="build_ext" --global-option="--inplace" . + {envpython} -m pip install . {envpython} selftest.py {envpython} -m pytest -W always {posargs} allowlist_externals = From 2d0b13b812eea5238a8df6dc03b3fa4a6c55559e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 4 Jun 2023 22:37:17 +1000 Subject: [PATCH 3/4] Swapped config key and value --- _custom_build/backend.py | 31 +++++++++++++++++++++++++++---- docs/installation.rst | 22 +++++++++++----------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/_custom_build/backend.py b/_custom_build/backend.py index 31a954824b9..86fe6081733 100755 --- a/_custom_build/backend.py +++ b/_custom_build/backend.py @@ -7,14 +7,37 @@ class _CustomBuildMetaBackend(_BuildMetaBackend): def run_setup(self, setup_script="setup.py"): if self.config_settings: - flags = [] - for key in ("enable", "disable", "vendor"): + + def config_has(key, value): settings = self.config_settings.get(key) if settings: if not isinstance(settings, list): settings = [settings] - for value in settings: - flags.append("--" + key + "-" + value) + return value in settings + + flags = [] + for dependency in ( + "zlib", + "jpeg", + "tiff", + "freetype", + "raqm", + "lcms", + "webp", + "webpmux", + "jpeg2000", + "imagequant", + "xcb", + ): + if config_has(dependency, "enable"): + flags.append("--enable-" + dependency) + elif config_has(dependency, "disable"): + flags.append("--disable-" + dependency) + for dependency in ("raqm", "fribidi"): + if config_has(dependency, "vendor"): + flags.append("--vendor-" + dependency) + if self.config_settings.get("platform-guessing") == "disable": + flags.append("--disable-platform-guessing") if self.config_settings.get("debug") == "true": flags.append("--debug") if flags: diff --git a/docs/installation.rst b/docs/installation.rst index 514d20e7422..6720d2dce6b 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -380,28 +380,28 @@ Build Options using a setting of 1. By default, it uses 4 CPUs, or if 4 are not available, as many as are present. -* Config settings: ``-C disable=zlib``, ``-C disable=jpeg``, - ``-C disable=tiff``, ``-C disable=freetype``, ``-C disable=raqm``, - ``-C disable=lcms``, ``-C disable=webp``, ``-C disable=webpmux``, - ``-C disable=jpeg2000``, ``-C disable=imagequant``, ``-C disable=xcb``. +* Config settings: ``-C zlib=disable``, ``-C jpeg=disable``, + ``-C tiff=disable``, ``-C freetype=disable``, ``-C raqm=disable``, + ``-C lcms=disable``, ``-C webp=disable``, ``-C webpmux=disable``, + ``-C jpeg2000=disable``, ``-C imagequant=disable``, ``-C xcb=disable``. Disable building the corresponding feature even if the development libraries are present on the building machine. -* Config settings: ``-C enable=zlib``, ``-C enable=jpeg``, - ``-C enable=tiff``, ``-C enable=freetype``, ``-C enable=raqm``, - ``-C enable=lcms``, ``-C enable=webp``, ``-C enable=webpmux``, - ``-C enable=jpeg2000``, ``-C enable=imagequant``, ``-C enable=xcb``. +* Config settings: ``-C zlib=enable``, ``-C jpeg=enable``, + ``-C tiff=enable``, ``-C freetype=enable``, ``-C raqm=enable``, + ``-C lcms=enable``, ``-C webp=enable``, ``-C webpmux=enable``, + ``-C jpeg2000=enable``, ``-C imagequant=enable``, ``-C xcb=enable``. Require that the corresponding feature is built. The build will raise an exception if the libraries are not found. Webpmux (WebP metadata) relies on WebP support. Tcl and Tk also must be used together. -* Config settings: ``-C vendor=raqm``, ``-C vendor=fribidi``. +* Config settings: ``-C raqm=vendor``, ``-C fribidi=vendor``. These flags are used to compile a modified version of libraqm and a shim that dynamically loads libfribidi at runtime. These are used to compile the standard Pillow wheels. Compiling libraqm requires a C99-compliant compiler. -* Build flag: ``-C disable=platform-guessing``. Skips all of the +* Build flag: ``-C platform-guessing=disable``. Skips all of the platform dependent guessing of include and library directories for automated build systems that configure the proper paths in the environment variables (e.g. Buildroot). @@ -413,7 +413,7 @@ Build Options Sample usage:: - python3 -m pip install --upgrade Pillow -C enable=[feature] + python3 -m pip install --upgrade Pillow -C [feature]=enable Platform Support ---------------- From 38d63868bf395ac1eb4869bc415de424f0863e45 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 14 Jun 2023 15:46:24 +1000 Subject: [PATCH 4/4] Do not import internal class --- _custom_build/backend.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/_custom_build/backend.py b/_custom_build/backend.py index 86fe6081733..9b3265a949f 100755 --- a/_custom_build/backend.py +++ b/_custom_build/backend.py @@ -1,10 +1,12 @@ import sys from setuptools.build_meta import * # noqa: F401, F403 -from setuptools.build_meta import _BuildMetaBackend +from setuptools.build_meta import build_wheel +backend_class = build_wheel.__self__.__class__ -class _CustomBuildMetaBackend(_BuildMetaBackend): + +class _CustomBuildMetaBackend(backend_class): def run_setup(self, setup_script="setup.py"): if self.config_settings: