From 2059e060051acd2024360834da435a266d9dc665 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 30 May 2025 09:56:47 +0100 Subject: [PATCH 1/5] Add parallel compile from pybind11 --- pyproject.toml | 1 + setup.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 683ab24ef..ae4b70990 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,7 @@ [build-system] build-backend = "backend" requires = [ + "pybind11", "setuptools>=77", ] backend-path = [ diff --git a/setup.py b/setup.py index ab36c6b17..ec6b47b1c 100644 --- a/setup.py +++ b/setup.py @@ -18,9 +18,12 @@ import warnings from collections.abc import Iterator from typing import Any +from pybind11.setup_helpers import ParallelCompile from setuptools import Extension, setup from setuptools.command.build_ext import build_ext +ParallelCompile("MAX_CONCURRENCY", default=0).install() + def get_version() -> str: version_file = "src/PIL/_version.py" @@ -1048,12 +1051,12 @@ ext_modules = [ Extension("PIL._imagingmorph", ["src/_imagingmorph.c"]), ] - # parse configuration from _custom_build/backend.py while sys.argv[-1].startswith("--pillow-configuration="): _, key, value = sys.argv.pop().split("=", 2) configuration.setdefault(key, []).append(value) + try: setup( cmdclass={"build_ext": pil_build_ext}, From b931402046f840bedc09b3c2b0c4039ac28531dc Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Sat, 31 May 2025 15:14:17 +0200 Subject: [PATCH 2/5] add pybind11 elsewhere so mypy can find it --- .ci/requirements-mypy.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/requirements-mypy.txt b/.ci/requirements-mypy.txt index 86ac2e0b2..645605aa6 100644 --- a/.ci/requirements-mypy.txt +++ b/.ci/requirements-mypy.txt @@ -5,6 +5,7 @@ ipython numpy packaging pyarrow-stubs +pybind11 pytest sphinx types-atheris From 2316c930f9b2985d27894f043f5f2e4787543dca Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 19 Jun 2025 22:46:09 +1000 Subject: [PATCH 3/5] Removed default argument --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ec6b47b1c..233811192 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ from pybind11.setup_helpers import ParallelCompile from setuptools import Extension, setup from setuptools.command.build_ext import build_ext -ParallelCompile("MAX_CONCURRENCY", default=0).install() +ParallelCompile("MAX_CONCURRENCY").install() def get_version() -> str: @@ -1051,12 +1051,12 @@ ext_modules = [ Extension("PIL._imagingmorph", ["src/_imagingmorph.c"]), ] + # parse configuration from _custom_build/backend.py while sys.argv[-1].startswith("--pillow-configuration="): _, key, value = sys.argv.pop().split("=", 2) configuration.setdefault(key, []).append(value) - try: setup( cmdclass={"build_ext": pil_build_ext}, From ecd264fffc680ab05da6a71ff4466c774185ab90 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 21 Jun 2025 22:22:46 +1000 Subject: [PATCH 4/5] Use "parallel" config setting and 4 as defaults --- setup.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index 1134879be..6c2180ebd 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,15 @@ from pybind11.setup_helpers import ParallelCompile from setuptools import Extension, setup from setuptools.command.build_ext import build_ext -ParallelCompile("MAX_CONCURRENCY").install() +configuration: dict[str, list[str]] = {} + +# parse configuration from _custom_build/backend.py +while sys.argv[-1].startswith("--pillow-configuration="): + _, key, value = sys.argv.pop().split("=", 2) + configuration.setdefault(key, []).append(value) + +default = int(configuration.get("parallel", ["4"])[-1]) +ParallelCompile("MAX_CONCURRENCY", default).install() def get_version() -> str: @@ -30,9 +38,6 @@ def get_version() -> str: return f.read().split('"')[1] -configuration: dict[str, list[str]] = {} - - PILLOW_VERSION = get_version() AVIF_ROOT = None FREETYPE_ROOT = None @@ -1047,11 +1052,6 @@ ext_modules = [ ] -# parse configuration from _custom_build/backend.py -while sys.argv[-1].startswith("--pillow-configuration="): - _, key, value = sys.argv.pop().split("=", 2) - configuration.setdefault(key, []).append(value) - try: setup( cmdclass={"build_ext": pil_build_ext}, From 23ed906b622e25466981fa7c2b80f2a1da612661 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 25 Jun 2025 22:00:36 +1000 Subject: [PATCH 5/5] Removed default limit of 4 --- docs/installation/building-from-source.rst | 5 ++--- setup.py | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/installation/building-from-source.rst b/docs/installation/building-from-source.rst index 8988a92ce..4c114a5e2 100644 --- a/docs/installation/building-from-source.rst +++ b/docs/installation/building-from-source.rst @@ -276,10 +276,9 @@ Build options * Config setting: ``-C parallel=n``. Can also be given with environment variable: ``MAX_CONCURRENCY=n``. Pillow can use - multiprocessing to build the extension. Setting ``-C parallel=n`` + multiprocessing to build the extensions. Setting ``-C parallel=n`` sets the number of CPUs to use to ``n``, or can disable parallel building by - using a setting of 1. By default, it uses 4 CPUs, or if 4 are not - available, as many as are present. + using a setting of 1. By default, it uses as many CPUs as are present. * Config settings: ``-C zlib=disable``, ``-C jpeg=disable``, ``-C tiff=disable``, ``-C freetype=disable``, ``-C raqm=disable``, diff --git a/setup.py b/setup.py index 6c2180ebd..aee1b04eb 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ while sys.argv[-1].startswith("--pillow-configuration="): _, key, value = sys.argv.pop().split("=", 2) configuration.setdefault(key, []).append(value) -default = int(configuration.get("parallel", ["4"])[-1]) +default = int(configuration.get("parallel", ["0"])[-1]) ParallelCompile("MAX_CONCURRENCY", default).install() @@ -394,9 +394,7 @@ class pil_build_ext(build_ext): cpu_count = os.cpu_count() if cpu_count is not None: try: - self.parallel = int( - os.environ.get("MAX_CONCURRENCY", min(4, cpu_count)) - ) + self.parallel = int(os.environ.get("MAX_CONCURRENCY", cpu_count)) except TypeError: pass for x in self.feature: