Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions .github/workflows/build-imagecodecs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,32 @@ jobs:
# dropped like upstream's own customize_build_macports does; wavpack is
# packaged but too old (5.6.0, predates the multithreaded-encoding API
# _wavpack.pyx calls); libdeflate isn't packaged either, so it's built
# from its own small upstream source.
# from its own small upstream source. Rocky 10's snappy predates the
# compression-level API (snappy_compress_with_level, SNAPPY_*_COMPRESSION_LEVEL)
# that _snappy.pyx uses from 2026.10.10, so snappy is built from source too --
# at 1.3.1: the API is absent from snappy 1.2.2 (the latest tag until 1.3.0)
# and first appears in the 1.3.0 tag's snappy-c.h.
CIBW_BEFORE_ALL_LINUX: |
dnf install -y \
lcms2-devel lz4-devel libzstd-devel liblerc-devel openjpeg2-devel \
libjpeg-turbo-devel xz-devel libpng-devel libtiff-devel libwebp-devel \
zlib-ng-compat-devel brotli-devel snappy-devel giflib-devel bzip2-devel
zlib-ng-compat-devel brotli-devel giflib-devel bzip2-devel
curl -sSL https://github.com/ebiggers/libdeflate/archive/refs/tags/v1.26.tar.gz | tar xz -C /tmp
cmake -S /tmp/libdeflate-1.26 -B /tmp/libdeflate-1.26/build -DCMAKE_BUILD_TYPE=Release -DLIBDEFLATE_BUILD_STATIC_LIB=OFF -DLIBDEFLATE_BUILD_GZIP=OFF
cmake --build /tmp/libdeflate-1.26/build -j"$(nproc)"
cmake --install /tmp/libdeflate-1.26/build
curl -sSLf https://github.com/google/snappy/archive/refs/tags/1.3.1.tar.gz | tar xz -C /tmp
cmake -S /tmp/snappy-1.3.1 -B /tmp/snappy-1.3.1/build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DSNAPPY_BUILD_TESTS=OFF -DSNAPPY_BUILD_BENCHMARKS=OFF -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_POLICY_VERSION_MINIMUM=3.5
cmake --build /tmp/snappy-1.3.1/build -j"$(nproc)"
cmake --install /tmp/snappy-1.3.1/build
ldconfig
# CPATH puts /usr/local/include (snappy 1.3.1, libdeflate) ahead of any
# older system header of the same name.
CIBW_ENVIRONMENT: >-
IMAGECODECS_RISCV64=1
CPATH=/usr/local/include
LIBRARY_PATH=/usr/local/lib
LD_LIBRARY_PATH=/usr/local/lib
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
CIBW_TEST_REQUIRES: pytest tifffile
CIBW_TEST_SOURCES: tests
Expand Down
1 change: 1 addition & 0 deletions docs/packages/imagecodecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ versions:
- filename: imagecodecs-2026.8.16-cp314-cp314t-manylinux_2_35_riscv64.manylinux_2_39_riscv64.whl
sha256: 5d775d794373da6b92d124f477dea1f7ba1f2b01eeef33db70d7a1f0502ed2f8
requires-python: '>=3.12'
- version: 2026.10.10
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
From d1cf8a782d921f42fdb4afe4785b62d741f0179a Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Sat, 12 Sep 2026 01:27:31 +0200
Subject: [PATCH] setup: add a riscv64 (Rocky 10 / pypi.riseproject.dev) build
customization

setup.py's customize_build dispatch relies on importing
imagecodecs_distributor_setup, but that module is not reliably
importable from inside cibuildwheel's isolated `python -m build`
subprocess (build isolation does not put the project directory on
sys.path), so the build silently falls back to customize_build_default
-- which still tries to compile the jpegxr extension against jxrlib,
a library Rocky 10 does not package for riscv64 at all.

Add customize_build_riscv64, selected via an IMAGECODECS_RISCV64 env
var checked directly in the dispatch chain (no import needed), so it
does not depend on that mechanism working. It trims EXTENSIONS to the
codecs backed by Rocky 10 appstream/crb dnf packages (plus lzf, which
bundles its own source and needs no system library), drops jpegxr
(like upstream's own customize_build_macports already does when
jxrlib is unavailable) and wavpack (Rocky 10 packages WavPack 5.6.0,
which predates the worker_threads/OPEN_THREADS_SHFT multithreaded-
encoding API imagecodecs' _wavpack.pyx calls unconditionally), and
clears the jpeg8 legacy sources so it builds against libjpeg-turbo 3
(matching every other customize_build_* preset that runs on a modern
libjpeg-turbo).

Upstream-Status: Inappropriate [riscv64/pypi.riseproject.dev-specific build customization]
---
setup.py | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/setup.py b/setup.py
index 3a91795..30e4e56 100644
--- a/setup.py
+++ b/setup.py
@@ -677,6 +677,24 @@ def customize_build_cibuildwheel(
extensions.pop('jpegxl', None)


+def customize_build_riscv64(
+ extensions: dict[str, Any],
+ options: dict[str, Any],
+) -> None:
+ """Customize build for Rocky 10 riscv64 (pypi.riseproject.dev)."""
+ keep = {
+ 'shared', 'imcd', 'bmp', 'brotli', 'bz2', 'ccitt', 'cms', 'czi',
+ 'deflate', 'gif', 'jpeg2k', 'jpeg8', 'lerc', 'ljpeg', 'lz4', 'lzf',
+ 'lzma', 'pixarlog', 'png', 'snappy', 'tiff', 'webp', 'zlib', 'zstd',
+ }
+ del options['shared_utility_qualified_name']
+ extensions['jpeg2k']['include_dirs'].append('/usr/include/openjpeg-2.5')
+ extensions['jpeg8']['sources'] = [] # use libjpeg-turbo 3
+ for name in list(extensions):
+ if name not in keep:
+ extensions.pop(name)
+
+
def customize_build_condaforge(
extensions: dict[str, Any],
options: dict[str, Any],
@@ -1024,7 +1042,9 @@ if 'sdist' not in sys.argv:
with add_to_path(HERE):
from imagecodecs_distributor_setup import customize_build
except ImportError:
- if os.environ.get('PYODIDE', ''):
+ if os.environ.get('IMAGECODECS_RISCV64', ''):
+ customize_build = customize_build_riscv64
+ elif os.environ.get('PYODIDE', ''):
customize_build = customize_build_pyodide
elif os.environ.get('COMPUTERNAME', '').startswith('CG-'):
customize_build = customize_build_cgohlke
--
2.50.1 (Apple Git-155)

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
From 7ee627a1f393d5c9ae83bdd3def1ee1c54089961 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Fri, 11 Sep 2026 23:02:16 +0200
Subject: [PATCH] _png: drop the png_set_cICP call, unavailable before libpng
1.6.45

png_set_cICP() was added to libpng in 1.6.45 (Jan 2025); Rocky 10
riscv64's system libpng-devel is 1.6.40, which does not declare or
export the symbol at all, so the Cython-generated call fails to
compile (implicit-function-declaration under GCC 14) and would fail
to link even with that warning silenced.

Drop the call so png_encode compiles against libpng 1.6.40; passing
primaries/transfer/matrix to png_encode becomes a silent no-op
instead of writing a cICP chunk, since that colour-primaries metadata
is not the primary use case this port targets.

Upstream-Status: Inappropriate [riscv64/pypi.riseproject.dev-specific: works around an older system libpng on the manylinux_riscv64 image, not an imagecodecs bug]
---
imagecodecs/_png.pyx | 10 ----------
1 file changed, 10 deletions(-)

diff --git a/imagecodecs/_png.pyx b/imagecodecs/_png.pyx
index 10eb338..0082e21 100644
--- a/imagecodecs/_png.pyx
+++ b/imagecodecs/_png.pyx
@@ -307,16 +307,6 @@ def png_encode(
PNG_FILTER_TYPE_DEFAULT
)

- if primaries_ >= 0 or transfer_ >= 0 or matrix_ >= 0:
- png_set_cICP(
- png_ptr,
- info_ptr,
- <png_byte> (primaries_ if primaries_ >= 0 else 2),
- <png_byte> (transfer_ if transfer_ >= 0 else 2),
- <png_byte> (matrix_ if matrix_ >= 0 else 2),
- 1
- )
-
png_write_info(png_ptr, info_ptr)
png_set_compression_level(png_ptr, level_)
png_set_compression_strategy(png_ptr, strategy_)
--
2.50.1 (Apple Git-155)

Loading