Skip to content

Commit 2852979

Browse files
Upgrade pillow to v12.3.0 (#151)
* Pillow: add build, test workflows for 12.3.0 Compared to upstream: - use uv and RISE registry in wheel build step to get riscv64 binaries - Refresh the same lto libavif patch we've used for previous versions so it applies on 12.3.0 - Add patches to - use uv in Pillow/.ci directory scripts - patch tests to work with gcc 13, since that is the default on the RISC-V runners - patch libdir assumption for riscv64 (upstream hard-coded to x86-64; should be considered for upstream riscv64 support) - skip grabclipboard_wl_clipboard test from `pytest` invocation --------- Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
1 parent 0457bf2 commit 2852979

7 files changed

Lines changed: 441 additions & 0 deletions

.github/workflows/build-pillow.yml

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
name: Build pillow wheels (riscv64)
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
version:
8+
description: 'pillow version to build (git tag without leading v, e.g. 12.3.0)'
9+
required: true
10+
default: '12.3.0'
11+
pull_request:
12+
paths:
13+
- '.github/workflows/build-pillow.yml'
14+
- '.github/workflows/test-pillow.yml'
15+
- 'patches/pillow/**'
16+
17+
concurrency:
18+
group: ${{ github.workflow }}-${{ inputs.version || '12.3.0' }}-${{ github.head_ref || github.run_id }}
19+
cancel-in-progress: true
20+
21+
permissions:
22+
contents: read # to fetch code (actions/checkout)
23+
24+
env:
25+
PILLOW_VERSION: ${{ inputs.version || '12.3.0' }}
26+
UV_EXTRA_INDEX_URL: https://pypi.riseproject.dev/simple/
27+
UV_INDEX_STRATEGY: unsafe-best-match
28+
UV_ONLY_BINARY: ':all:'
29+
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
30+
31+
jobs:
32+
build_wheels:
33+
name: Build pillow ${{ inputs.version || '12.3.0' }} ${{ matrix.python }}-manylinux_riscv64
34+
runs-on: ubuntu-24.04-riscv
35+
strategy:
36+
fail-fast: false
37+
matrix:
38+
python: ["cp312", "cp313", "cp314", "cp314t"]
39+
40+
steps:
41+
- name: Checkout pillow v${{ env.PILLOW_VERSION }}
42+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
43+
with:
44+
repository: python-pillow/Pillow
45+
ref: ${{ env.PILLOW_VERSION }}
46+
submodules: true
47+
persist-credentials: false
48+
49+
- name: Checkout python-wheels
50+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
51+
with:
52+
path: python-wheels
53+
persist-credentials: false
54+
55+
# Works around a GCC LTO bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110812)
56+
# hit when building libavif as a Pillow wheel dependency on riscv64.
57+
- name: Patch pillow source
58+
run: |
59+
git apply python-wheels/patches/pillow/${{ env.PILLOW_VERSION }}/00*.patch
60+
61+
- name: Install Python
62+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
63+
with:
64+
python-version: '3.12'
65+
activate-environment: true
66+
enable-cache: false
67+
68+
- name: Build wheels
69+
uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0
70+
env:
71+
CIBW_BUILD: ${{ matrix.python }}-manylinux_riscv64
72+
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
73+
# libjpeg-turbo doesn't provide riscv64 SIMD before v3.2, and the
74+
# version vendored by Pillow's wheel build is older than that; also
75+
# disable arch-specific AOM optimization, see
76+
# https://aomedia.issues.chromium.org/issues/492439207. Passed as
77+
# cmake flags (picked up by the libavif build) rather than patching
78+
# Pillow sources, matching the fix proven previously in
79+
# wheel_builder/wheel_builder/Pillow/gitlab-ci.yml.
80+
HOST_CMAKE_FLAGS: "-DWITH_SIMD=0 -DAOM_TARGET_CPU=generic"
81+
CIBW_ENVIRONMENT_PASS_LINUX: HOST_CMAKE_FLAGS
82+
CIBW_BUILD_FRONTEND: "build[uv]"
83+
CIBW_ENVIRONMENT: >-
84+
UV_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
85+
UV_INDEX_STRATEGY=unsafe-best-match
86+
UV_ONLY_BINARY=:all:
87+
88+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
89+
with:
90+
name: pillow-${{ env.PILLOW_VERSION }}-${{ matrix.python }}-manylinux_riscv64
91+
path: ./wheelhouse/*.whl
92+
if-no-files-found: error
93+
94+
publish:
95+
name: Publish pillow ${{ inputs.version || '12.3.0' }} to GitLab
96+
needs: [build_wheels]
97+
# Only publish when the workflow was triggered from main with a specific
98+
# version. Manual trigger is the only entry point, so checking the ref is
99+
# enough to gate uploads.
100+
if: github.ref == 'refs/heads/main'
101+
runs-on: ubuntu-latest
102+
permissions:
103+
contents: write
104+
pull-requests: write
105+
106+
steps:
107+
- name: Publish wheels and open docs PR
108+
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
109+
with:
110+
artifact-pattern: pillow-${{ env.PILLOW_VERSION }}-*-manylinux_riscv64
111+
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
112+
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
113+
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
114+
gh-token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/test-pillow.yml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
---
2+
name: Test pillow (riscv64)
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
version:
8+
description: 'pillow version to test (git tag without leading v, e.g. 12.3.0)'
9+
required: true
10+
default: '12.3.0'
11+
pull_request:
12+
paths:
13+
- '.github/workflows/test-pillow.yml'
14+
15+
concurrency:
16+
group: ${{ github.workflow }}-${{ inputs.version || '12.3.0' }}-${{ github.head_ref || github.run_id }}
17+
cancel-in-progress: true
18+
19+
permissions:
20+
contents: read # to fetch code (actions/checkout)
21+
22+
env:
23+
FORCE_COLOR: 1
24+
PIP_DISABLE_PIP_VERSION_CHECK: 1
25+
PILLOW_VERSION: ${{ inputs.version || '12.3.0' }}
26+
27+
jobs:
28+
test:
29+
permissions:
30+
contents: read
31+
name: "Test pillow ${{ inputs.version || '12.3.0' }} — Python ${{ matrix.python-version }} on ${{ matrix.os }}"
32+
runs-on: ${{ matrix.os }}
33+
34+
strategy:
35+
fail-fast: false
36+
matrix:
37+
include:
38+
- os: ubuntu-24.04-riscv
39+
python-version: '3.12'
40+
41+
steps:
42+
- name: Checkout pillow v${{ env.PILLOW_VERSION }}
43+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
44+
with:
45+
repository: python-pillow/Pillow
46+
ref: ${{ env.PILLOW_VERSION }}
47+
submodules: true
48+
persist-credentials: false
49+
50+
- name: Checkout python-wheels
51+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
52+
with:
53+
path: python-wheels
54+
persist-credentials: false
55+
56+
# Works around a GCC LTO bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110812)
57+
# hit when building libavif as a Pillow wheel dependency on riscv64.
58+
- name: Patch pillow source
59+
run: |
60+
git apply python-wheels/patches/pillow/${{ env.PILLOW_VERSION }}/00*.patch
61+
62+
- name: Set up Python ${{ matrix.python-version }}
63+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
64+
with:
65+
python-version: ${{ matrix.python-version }}
66+
activate-environment: true
67+
enable-cache: false
68+
69+
- name: Install Linux dependencies
70+
run: |
71+
.ci/install.sh
72+
env:
73+
GHA_PYTHON_VERSION: ${{ matrix.python-version }}
74+
75+
- name: Build
76+
run: |
77+
.ci/build.sh
78+
79+
- name: Test
80+
run: |
81+
xvfb-run -s '-screen 0 1024x768x24' sway&
82+
export WAYLAND_DISPLAY=wayland-1
83+
.ci/test.sh
84+
85+
- name: Prepare to upload errors
86+
if: failure()
87+
run: |
88+
mkdir -p Tests/errors
89+
90+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
91+
if: failure()
92+
with:
93+
name: "pillow-${{ env.PILLOW_VERSION }}-py${{ matrix.python-version }}-${{ matrix.os }}-errors"
94+
path: Tests/errors
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
From 1bbab6afa8f1bf6d64d3db7b977975e45235c80d Mon Sep 17 00:00:00 2001
2+
From: Trevor Gamblin <tgamblin@baylibre.com>
3+
Date: Thu, 23 Jul 2026 13:20:47 -0400
4+
Subject: [PATCH] .ci: test.sh: skip test_grabclipboard_wl_clipboard
5+
6+
This test depends on a Wayland server and XDG_RUNTIME_DIR to be set. We
7+
don't want to rely on a graphical configuration on the runners, so skip
8+
it.
9+
10+
Upstream-Status: Inappropriate [workaround for RISC-V runner builds]
11+
12+
Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
13+
---
14+
.ci/test.sh | 2 +-
15+
1 file changed, 1 insertion(+), 1 deletion(-)
16+
17+
diff --git a/.ci/test.sh b/.ci/test.sh
18+
index 87a605d84..910e7094e 100755
19+
--- a/.ci/test.sh
20+
+++ b/.ci/test.sh
21+
@@ -4,4 +4,4 @@ set -e
22+
23+
python3 -c "from PIL import Image"
24+
25+
-python3 -bb -m pytest -vv -x -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests $REVERSE
26+
+python3 -bb -m pytest -vv -x -k "not test_grabclipboard_wl_clipboard" -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests $REVERSE
27+
--
28+
2.55.0
29+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
From de055b09de48b863c8c779fa6ac9cca59cbba07f Mon Sep 17 00:00:00 2001
2+
From: Trevor Gamblin <tgamblin@baylibre.com>
3+
Date: Thu, 23 Jul 2026 08:54:31 -0400
4+
Subject: [PATCH] Pillow: .ci: use 'uv pip'
5+
6+
We use uv in our workflows, so replace 'python3 -m pip' with 'uv pip' in
7+
the .ci scripts run by the Pillow pipelines.
8+
9+
Upstream-Status: Inappropriate [different Python management tooling]
10+
11+
Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
12+
---
13+
.ci/after_success.sh | 2 +-
14+
.ci/install.sh | 24 ++++++++++++------------
15+
2 files changed, 13 insertions(+), 13 deletions(-)
16+
17+
diff --git a/.ci/after_success.sh b/.ci/after_success.sh
18+
index 6da27b975..daacfd20d 100755
19+
--- a/.ci/after_success.sh
20+
+++ b/.ci/after_success.sh
21+
@@ -1,5 +1,5 @@
22+
#!/bin/bash
23+
24+
# gather the coverage data
25+
-python3 -m pip install coverage
26+
+uv pip install coverage
27+
python3 -m coverage xml
28+
diff --git a/.ci/install.sh b/.ci/install.sh
29+
index db680db96..f96e8d99a 100755
30+
--- a/.ci/install.sh
31+
+++ b/.ci/install.sh
32+
@@ -22,24 +22,24 @@ sudo apt-get -qq install libfreetype6-dev liblcms2-dev libtiff-dev python3-tk\
33+
cmake meson imagemagick libharfbuzz-dev libfribidi-dev\
34+
sway wl-clipboard libopenblas-dev nasm
35+
36+
-python3 -m pip install --upgrade pip
37+
-python3 -m pip install --upgrade wheel
38+
-python3 -m pip install coverage
39+
-python3 -m pip install defusedxml
40+
-python3 -m pip install ipython
41+
-python3 -m pip install olefile
42+
-python3 -m pip install -U pytest
43+
-python3 -m pip install -U pytest-cov
44+
-python3 -m pip install -U pytest-timeout
45+
+uv pip install --upgrade pip
46+
+uv pip install --upgrade wheel
47+
+uv pip install coverage
48+
+uv pip install defusedxml
49+
+uv pip install ipython
50+
+uv pip install olefile
51+
+uv pip install -U pytest
52+
+uv pip install -U pytest-cov
53+
+uv pip install -U pytest-timeout
54+
# optional test dependencies, only install if there's a binary package.
55+
-python3 -m pip install --only-binary=:all: numpy || true
56+
-python3 -m pip install --only-binary=:all: pyarrow || true
57+
+uv pip install --only-binary=:all: numpy || true
58+
+uv pip install --only-binary=:all: pyarrow || true
59+
60+
# PyQt6 doesn't support PyPy3
61+
if [[ $GHA_PYTHON_VERSION == 3.* ]]; then
62+
sudo apt-get -qq install libegl1 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxkbcommon-x11-0
63+
# pyqt6 doesn't yet support free-threading; only install if a wheel is available
64+
- python3 -m pip install --only-binary=:all: pyqt6 || true
65+
+ uv pip install --only-binary=:all: pyqt6 || true
66+
fi
67+
68+
# webp
69+
--
70+
2.55.0
71+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
From 672262c8715b24485f82e18580fe33786dbce2b9 Mon Sep 17 00:00:00 2001
2+
From: Trevor Gamblin <tgamblin@baylibre.com>
3+
Date: Thu, 23 Jul 2026 10:57:00 -0400
4+
Subject: [PATCH] depends: install_libavif.sh: fix cache LIBDIR for non-x86_64
5+
hosts
6+
7+
The GitHub Actions cache restore/save paths hardcode
8+
LIBDIR=/usr/lib/x86_64-linux-gnu, but on riscv64 the multiarch install
9+
path is /usr/lib/riscv64-linux-gnu. The cache-save cp then fails:
10+
11+
cp: cannot stat '/usr/lib/x86_64-linux-gnu/libavif.so*': No such file or directory
12+
13+
Because that cp isn't the last command in an && list, `set -e`
14+
doesn't stop the script there either, so it falls through with a
15+
stale working directory and breaks the next dependency's `pushd
16+
depends` in .ci/install.sh:
17+
18+
.ci/install.sh: line 58: pushd: depends: No such file or directory
19+
20+
Derive LIBDIR from `uname -m` instead of hardcoding the triplet.
21+
22+
Upstream-Status: To upstream [relevant for non-x86_64 CI runners]
23+
24+
Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
25+
---
26+
depends/install_libavif.sh | 4 ++--
27+
1 file changed, 2 insertions(+), 2 deletions(-)
28+
29+
diff --git a/depends/install_libavif.sh b/depends/install_libavif.sh
30+
index b837f6d65..ae4d7f87a 100755
31+
--- a/depends/install_libavif.sh
32+
+++ b/depends/install_libavif.sh
33+
@@ -5,7 +5,7 @@ version=1.4.2
34+
35+
if [[ "$GHA_LIBAVIF_CACHE_HIT" == "true" ]]; then
36+
37+
- LIBDIR=/usr/lib/x86_64-linux-gnu
38+
+ LIBDIR=/usr/lib/$(uname -m)-linux-gnu
39+
40+
# Copy cached files into place
41+
sudo cp ~/cache-libavif/lib/* $LIBDIR/
42+
@@ -80,7 +80,7 @@ else
43+
44+
if [ -n "$GITHUB_ACTIONS" ] && [ "$(uname)" != "Darwin" ]; then
45+
# Copy to cache
46+
- LIBDIR=/usr/lib/x86_64-linux-gnu
47+
+ LIBDIR=/usr/lib/$(uname -m)-linux-gnu
48+
rm -rf ~/cache-libavif
49+
mkdir -p ~/cache-libavif/lib
50+
mkdir -p ~/cache-libavif/include
51+
--
52+
2.55.0
53+

0 commit comments

Comments
 (0)