diff --git a/.github/workflows/build-hdf5plugin.yml b/.github/workflows/build-hdf5plugin.yml index fbea70ac4f4..9d2279c2c38 100644 --- a/.github/workflows/build-hdf5plugin.yml +++ b/.github/workflows/build-hdf5plugin.yml @@ -109,12 +109,12 @@ jobs: - name: Check wheel contents run: | python3 - wheelhouse/*.whl <<'EOF' - import sys, zipfile + import os, sys, zipfile names = zipfile.ZipFile(sys.argv[1]).namelist() plugins = {n.rsplit("/", 1)[1] for n in names if n.startswith("hdf5plugin/plugins/") and n.endswith(".so")} - assert plugins == { + expected = { "libh5blosc.so", "libh5blosc2.so", "libh5bshuf.so", @@ -126,11 +126,20 @@ jobs: "libh5sz3.so", "libh5zfp.so", "libh5zstd.so", - }, plugins + } + licence_count = 35 + + # 7.1.0 adds the HTJ2K filter, which brings h5z-htj2k and the OpenJPH + # it vendors, hence two more licences. + if tuple(int(p) for p in os.environ["HDF5PLUGIN_VERSION"].split(".")) >= (7, 1): + expected.add("libh5htj2k.so") + licence_count += 2 + + assert plugins == expected, plugins licences = {n.split(".dist-info/licenses/", 1)[1] for n in names if ".dist-info/licenses/" in n and not n.endswith("/")} - assert len(licences) == 35, licences + assert len(licences) == licence_count, licences EOF - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/docs/packages/hdf5plugin.yaml b/docs/packages/hdf5plugin.yaml index 48d7817e845..3d050d98777 100644 --- a/docs/packages/hdf5plugin.yaml +++ b/docs/packages/hdf5plugin.yaml @@ -9,3 +9,4 @@ versions: - filename: hdf5plugin-7.0.0-py3-none-manylinux_2_39_riscv64.whl sha256: 4516f388aec70cf01db4af615eb969abe9ed132acd8387ca56fa5fc7fdd7d196 requires-python: '>=3.9' +- version: 7.1.0 diff --git a/patches/hdf5plugin/7.1.0/0001-Gate-blosc2-s-shuffle-SIMD-macros-on-the-actual-host.patch b/patches/hdf5plugin/7.1.0/0001-Gate-blosc2-s-shuffle-SIMD-macros-on-the-actual-host.patch new file mode 100644 index 00000000000..2cd9efea0b5 --- /dev/null +++ b/patches/hdf5plugin/7.1.0/0001-Gate-blosc2-s-shuffle-SIMD-macros-on-the-actual-host.patch @@ -0,0 +1,69 @@ +From 514a45ae078d6698870e8cda12d4d7565bb1cd25 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Fri, 11 Sep 2026 10:02:30 +0200 +Subject: [PATCH] Gate blosc2's shuffle SIMD macros on the actual host + architecture + +_get_blosc2_plugin() force-enables SHUFFLE_SSE2_ENABLED, +SHUFFLE_AVX2_ENABLED, SHUFFLE_AVX512_ENABLED and SHUFFLE_NEON_ENABLED +for every architecture except ppc64le, on the implicit assumption that +"not ppc64le" means "x86 or ARM". On riscv64 this breaks the build: + +c-blosc2's blosc/shuffle.c picks its CPU-detection branch purely from +these ENABLED macros (independently of whether the corresponding +per-ISA .c file actually compiled any code, which is separately gated +on the compiler's own __SSE2__/__AVX2__/__ARM_NEON__ macros). With +SHUFFLE_SSE2_ENABLED/AVX2_ENABLED/AVX512_ENABLED defined but no x86 +target, the `#if ... && (defined(__i386__) || defined(__x86_64__) ...)` +branch is skipped, so shuffle.c falls through to +`#elif defined(SHUFFLE_NEON_ENABLED)` -- also force-defined here -- and +compiles blosc_get_cpu_features() against `getauxval(AT_HWCAP) & +HWCAP_ARM_NEON`, an ARM-only hwcap constant that doesn't exist on +riscv64 (confirmed against glibc's riscv64 ): a hard +compile error. Even if that branch were skipped too, the AVX512 sources +included at file scope for any non-ppc64le target reference +`is_shuffle_avx2`/`is_bshuf_AVX512`, symbols that shuffle-avx2.c never +defines when __AVX2__ isn't set -- an undefined-reference link error. + +Use HostConfig.ARCH (already used a few lines below in this same +function for the ARM_7/ARM_8 -flax-vector-conversions case) to gate +each SIMD family on the architecture it actually targets: PPC_64 -> +Altivec, ARM_7/ARM_8 -> NEON, X86_32/X86_64 -> SSE2/AVX2/AVX512. Every +other architecture (riscv64 included) now defines none of these +macros, so shuffle.c takes its "no hardware acceleration" branch and +c-blosc2 falls back to shuffle-generic.c/bitshuffle-generic.c, exactly +as blosc (v1)'s own _get_blosc_plugin() already does today via its +sse2=/avx2= HDF5PluginExtension kwargs (only populated when +HostConfig.has_sse2()/has_avx2() are true, which are unconditionally +false off X86_32/X86_64). + +Upstream-Status: To upstream [not submitted: no cross-repo issue/PR contributions from this port] + +Signed-off-by: Ludovic Henry +--- + setup.py | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/setup.py b/setup.py +index 24a8f1d..ad281d7 100644 +--- a/setup.py ++++ b/setup.py +@@ -1316,14 +1316,15 @@ def _get_blosc2_plugin(): + f"{blosc2_dir}/include", + ] + define_macros = [("HAVE_PLUGINS", 1)] +- if platform.machine() == "ppc64le": ++ if HostConfig.ARCH == "PPC_64": + define_macros.append(("SHUFFLE_ALTIVEC_ENABLED", 1)) + define_macros.append(("NO_WARN_X86_INTRINSICS", None)) +- else: ++ elif HostConfig.ARCH in ("ARM_7", "ARM_8"): ++ define_macros.append(("SHUFFLE_NEON_ENABLED", 1)) ++ elif HostConfig.ARCH in ("X86_32", "X86_64"): + define_macros.append(("SHUFFLE_SSE2_ENABLED", 1)) + define_macros.append(("SHUFFLE_AVX2_ENABLED", 1)) + define_macros.append(("SHUFFLE_AVX512_ENABLED", 1)) +- define_macros.append(("SHUFFLE_NEON_ENABLED", 1)) + + # Add ZFP instead of using static library since compilation options are different + sources += glob("lib/c-blosc2-zfp/src/*.c") diff --git a/patches/hdf5plugin/7.1.0/0002-Ship-the-licences-of-what-the-wheel-actually-bundles.patch b/patches/hdf5plugin/7.1.0/0002-Ship-the-licences-of-what-the-wheel-actually-bundles.patch new file mode 100644 index 00000000000..10556ac60b5 --- /dev/null +++ b/patches/hdf5plugin/7.1.0/0002-Ship-the-licences-of-what-the-wheel-actually-bundles.patch @@ -0,0 +1,85 @@ +From f2705e89c149de8bf84b6a4e01385c08f91a8aa7 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Fri, 18 Sep 2026 12:17:42 +0000 +Subject: [PATCH] Ship the licences of what the wheel actually bundles + +license-files only lists the top-level MIT LICENSE, so the built wheel +carries no attribution for the ~30 vendored compression libraries and +HDF5 filter plugins that setup.py statically compiles in by default +(blosc, c-blosc, c-blosc2, bitshuffle, bzip2, charls, fcidecomp, +h5z-htj2k and its vendored OpenJPH, lz4, PyTables' bzip2/blosc2 +wrappers, snappy, SPERR, SZ, SZ3, zfp, zlib, zstd, and the HDF5 +headers used to build against). Confirmed against the real PyPI 7.0.0 +wheel: its dist-info/licenses/ holds only LICENSE. + +doc/information.rst already documents which lib/**/LICENSE* file +covers which bundled piece (with two stale paths: the LZ4 and ZSTD +plugin sources it points at lib/LZ4 and lib/HDF5Plugin-Zstandard, which +don't exist in this tree -- they now live under +lib/hdf5_plugins/{LZ4,ZSTD}). List every one of those files (plus the +package's own lib/hdf5_plugins/COPYING that covers both plugins) via +PEP 639's license-files so setuptools packages them into +dist-info/licenses/ alongside the top-level LICENSE, matching what the +default (nothing stripped via HDF5PLUGIN_STRIP) build actually ships. + +Upstream-Status: To upstream [not submitted: no cross-repo issue/PR contributions from this port] + +Signed-off-by: Ludovic Henry +--- + pyproject.toml | 40 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 39 insertions(+), 1 deletion(-) + +diff --git a/pyproject.toml b/pyproject.toml +index 62030d2..d13a06e 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -10,7 +10,45 @@ authors = [ + description = "HDF5 Plugins for Windows, MacOS, and Linux" + readme = "README.rst" + requires-python = ">=3.9" +-license-files = ["LICENSE"] ++license-files = [ ++ "LICENSE", ++ "lib/bitshuffle/LICENSE", ++ "lib/bzip2/LICENSE", ++ "lib/c-blosc/LICENSE.txt", ++ "lib/c-blosc/LICENSES/BITSHUFFLE.txt", ++ "lib/c-blosc/LICENSES/FASTLZ.txt", ++ "lib/c-blosc/LICENSES/LZ4.txt", ++ "lib/c-blosc/LICENSES/SNAPPY.txt", ++ "lib/c-blosc/LICENSES/ZLIB.txt", ++ "lib/c-blosc/internal-complibs/zlib-1.3.1/LICENSE", ++ "lib/c-blosc2/LICENSE.txt", ++ "lib/c-blosc2/LICENSES/BITSHUFFLE.txt", ++ "lib/c-blosc2/LICENSES/FASTLZ.txt", ++ "lib/c-blosc2/LICENSES/LZ4.txt", ++ "lib/c-blosc2/LICENSES/ZLIB.txt", ++ "lib/c-blosc2/LICENSES/ZSTD.txt", ++ "lib/charls/LICENSE.md", ++ "lib/fcidecomp/LICENSE", ++ "lib/h5z-htj2k/LICENSE", ++ "lib/h5z-htj2k/vendored/OpenJPH/LICENSE", ++ "lib/H5Z-SPERR/LICENSE", ++ "lib/H5Z-ZFP/LICENSE", ++ "lib/hdf5/COPYING", ++ "lib/hdf5-blosc/LICENSES/BLOSC.txt", ++ "lib/hdf5-blosc/LICENSES/BLOSC_HDF5.txt", ++ "lib/hdf5-blosc/LICENSES/H5PY.txt", ++ "lib/hdf5_plugins/COPYING", ++ "lib/hdf5_plugins/LZ4/Additional_Legal/LICENSE", ++ "lib/hdf5_plugins/ZSTD/Additional_Legal/LICENSE", ++ "lib/lz4-clib/LICENSE", ++ "lib/PyTables/LICENSE.txt", ++ "lib/snappy/COPYING", ++ "lib/SPERR/LICENSE", ++ "lib/SZ/copyright-and-BSD-license.txt", ++ "lib/SZ3/copyright-and-BSD-license.txt", ++ "lib/zfp/LICENSE", ++ "lib/zstd/LICENSE", ++] + classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", +-- +2.43.0 +