Skip to content

Commit bced323

Browse files
authored
fastjet: Add version 3.5.1.4 (#2638)
* fastjet: Add version 3.5.1.4 Build scikit-hep/fastjet from the v3.5.1.4 checkout (with its FastJet, SISCone and fastjet-contrib submodules) on the riscv64 runner, following upstream's wheels.yml: cibuildwheel with upstream's own before-all (Boost 1.88 headers, CGAL 6.0.1) and FASTJET_ENABLE_CGAL=ON, and upstream's pytest suite with the test extra. Carry a licence patch: the wheel ships FastJet, SISCone and the fastjet-contrib libraries and compiles CGAL and Boost headers in, but upstream only packages its own BSD-3-Clause LICENSE. * fastjet: Resolve cp314t dask test deps in a single pip call The cp314t leg installed dask/dask-awkward through the wheel's `dask` extra and distributed through CIBW_TEST_REQUIRES. cibuildwheel runs those as two separate pip invocations, so the second one picked distributed 2026.8.0, upgraded dask to 2026.8.0 and broke dask-awkward 2026.2.1 (requires dask<2025.4.0): test_008-dask.py failed with "Cannot fuse tasks with multiple outputs". The other legs resolve upstream's `test` extra in one go and get dask/distributed 2025.3.1. List dask, dask-awkward and distributed together in test-requires so pip honours dask-awkward's pin.
1 parent 375b3d9 commit bced323

3 files changed

Lines changed: 194 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# SPDX-FileCopyrightText: 2026 The RISE Project
2+
# SPDX-License-Identifier: MIT
3+
---
4+
# This workflow is based on: https://github.com/scikit-hep/fastjet/blob/v3.5.1.4/.github/workflows/wheels.yml
5+
name: Build fastjet wheels (riscv64)
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
version:
11+
description: 'Version glob to (re)build; empty builds every version of docs/packages/fastjet.yaml not released yet'
12+
required: false
13+
default: ''
14+
pull_request:
15+
branches: [main]
16+
paths:
17+
- '.github/workflows/build-fastjet.yml'
18+
- 'docs/packages/fastjet.yaml'
19+
- 'patches/fastjet/**'
20+
push:
21+
branches: [main]
22+
paths:
23+
- '.github/workflows/build-fastjet.yml'
24+
- 'docs/packages/fastjet.yaml'
25+
- 'patches/fastjet/**'
26+
27+
concurrency:
28+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
29+
cancel-in-progress: true
30+
31+
permissions:
32+
contents: read # to fetch code (actions/checkout)
33+
34+
env:
35+
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
36+
37+
jobs:
38+
setup:
39+
uses: $/.github/workflows/_setup.yml
40+
with:
41+
package: fastjet
42+
version: ${{ inputs.version }}
43+
44+
build_wheels:
45+
needs: [setup]
46+
if: needs.setup.outputs.versions != '[]'
47+
name: Build fastjet ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64
48+
runs-on: ubuntu-24.04-riscv
49+
timeout-minutes: 360
50+
strategy:
51+
fail-fast: false
52+
matrix:
53+
version: ${{ fromJSON(needs.setup.outputs.versions) }}
54+
python: ["cp312", "cp313", "cp314", "cp314t"]
55+
env:
56+
FASTJET_VERSION: ${{ matrix.version }}
57+
58+
steps:
59+
- name: Checkout fastjet ${{ env.FASTJET_VERSION }}
60+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
61+
with:
62+
repository: scikit-hep/fastjet
63+
ref: v${{ env.FASTJET_VERSION }}
64+
submodules: recursive
65+
persist-credentials: false
66+
67+
- name: Checkout python-wheels
68+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
69+
with:
70+
path: python-wheels
71+
persist-credentials: false
72+
73+
- name: Patch fastjet source
74+
run: git apply python-wheels/patches/fastjet/${{ env.FASTJET_VERSION }}/*.patch
75+
76+
- name: Build wheels
77+
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
78+
with:
79+
output-dir: wheelhouse/
80+
only: ${{ matrix.python }}-manylinux_riscv64
81+
env:
82+
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
83+
CIBW_CONFIG_SETTINGS: >
84+
"cmake.define.FASTJET_ENABLE_CGAL"="ON"
85+
# Licence notices of the CGAL and Boost headers compiled in by upstream's before-all.
86+
CIBW_BEFORE_BUILD: >-
87+
cp {project}/boost_1_88_0/LICENSE_1_0.txt {project}/LICENSE.boost &&
88+
cp /usr/local/share/doc/CGAL/LICENSE {project}/LICENSE.CGAL &&
89+
cp /usr/local/share/doc/CGAL/LICENSE.GPL {project}/LICENSE.CGAL.GPL &&
90+
cp /usr/local/share/doc/CGAL/LICENSE.LGPL {project}/LICENSE.CGAL.LGPL
91+
# Our registry carries awkward-cpp 56, not PyPI's newest 57: stay on awkward 2.13.0.
92+
CIBW_ENVIRONMENT: >-
93+
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_FASTJET=${{ env.FASTJET_VERSION }}
94+
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
95+
PIP_ONLY_BINARY=numpy,awkward-cpp,pyarrow,pandas,boost-histogram
96+
# pandas (via dask-awkward[test]) has no free-threaded riscv64 wheel, so cp314t gets
97+
# upstream's `test` extra minus dask-awkward's own [test] extra. Keep dask, dask-awkward
98+
# and distributed in the same pip call: cibuildwheel installs the wheel's extras and
99+
# test-requires in two separate pip runs, and splitting them let the second run pull
100+
# distributed 2026.8.0, which upgraded dask past dask-awkward 2026.2.1's dask<2025.4.0
101+
# pin and broke test_008-dask.py ("Cannot fuse tasks with multiple outputs").
102+
CIBW_TEST_EXTRAS: ${{ matrix.python == 'cp314t' && 'dev' || 'test' }}
103+
CIBW_TEST_REQUIRES: ${{ matrix.python == 'cp314t' && 'uproot>=5 dask>=2023.4.0 dask-awkward>=2023.4.2 distributed>=2023.4.0' || '' }}
104+
105+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
106+
with:
107+
name: fastjet-${{ env.FASTJET_VERSION }}-${{ matrix.python }}-manylinux_riscv64
108+
path: wheelhouse/*.whl
109+
if-no-files-found: error
110+
111+
- name: Check the wheel ships the extensions and the bundled licences
112+
run: |
113+
python3 - wheelhouse/*.whl <<'EOF'
114+
import sys, zipfile
115+
116+
names = zipfile.ZipFile(sys.argv[1]).namelist()
117+
for mod in ("fastjet/_ext.", "fastjet/_swig/_fastjet_swig."):
118+
assert any(n.startswith(mod) and n.endswith(".so") for n in names), mod
119+
for lib in ("fastjet", "fastjettools", "fastjetplugins", "siscone", "fastjetcontribfragile"):
120+
assert f"fastjet/lib64/lib{lib}.so" in names, lib
121+
assert not any(n.startswith("fastjet.libs/") for n in names), names
122+
licences = {n.split(".dist-info/licenses/", 1)[1] for n in names if ".dist-info/licenses/" in n} - {""}
123+
for want in ("LICENSE", "LICENSE.boost", "LICENSE.CGAL", "LICENSE.CGAL.GPL", "LICENSE.CGAL.LGPL",
124+
"extern/fastjet-core/COPYING", "extern/fastjet-core/plugins/SISCone/siscone/COPYING",
125+
"extern/fastjet-contrib/COPYING", "extern/fastjet-contrib/Nsubjettiness/COPYING"):
126+
assert want in licences, (want, sorted(licences))
127+
print(sys.argv[1], len(licences), "licence files ok")
128+
EOF
129+
130+
publish:
131+
name: Publish fastjet ${{ matrix.version }}
132+
needs: [setup, build_wheels]
133+
if: needs.setup.outputs.versions != '[]'
134+
strategy:
135+
fail-fast: false
136+
matrix:
137+
version: ${{ fromJSON(needs.setup.outputs.versions) }}
138+
permissions:
139+
contents: write
140+
pull-requests: write
141+
uses: $/.github/workflows/_publish-wheel.yml
142+
secrets:
143+
app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }}
144+
with:
145+
artifact-pattern: fastjet-${{ matrix.version }}-*-manylinux_riscv64

‎docs/packages/fastjet.yaml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package-name: fastjet
2+
source-code: https://github.com/scikit-hep/fastjet
3+
license: BSD-3-Clause AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-or-later AND BSL-1.0
4+
versions:
5+
- version: 3.5.1.4
6+
patched: true
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Ludovic Henry <git@ludovic.dev>
3+
Date: Fri, 2 Oct 2026 12:00:00 +0200
4+
Subject: [PATCH] pyproject: ship licence files of bundled libraries
5+
6+
The wheels compile and ship FastJet (extern/fastjet-core, GPL-2.0-or-later),
7+
SISCone (GPL-2.0-or-later) and the fastjet-contrib packages (each under
8+
its own COPYING) as fastjet/lib64/*.so, and compile CGAL (GPL-3.0-or-later
9+
/ LGPL-3.0-or-later) and Boost (BSL-1.0) headers into libfastjet, but
10+
only carry the binding's own BSD-3-Clause LICENSE.
11+
12+
List the in-tree COPYING files, and widen LICENSE to LICENSE* so the
13+
CGAL and Boost notices staged as LICENSE.<dep> at the project root
14+
before the wheel build are packaged into dist-info/licenses/ too. The
15+
sdist still only matches LICENSE at its root.
16+
17+
Upstream-Status: To upstream [not yet submitted; the same gap exists in every fastjet wheel on PyPI, so it needs a maintainer discussion rather than a drive-by PR]
18+
---
19+
pyproject.toml | 8 +++++++-
20+
1 file changed, 7 insertions(+), 1 deletion(-)
21+
22+
diff --git a/pyproject.toml b/pyproject.toml
23+
index ade2171..741d23d 100644
24+
--- a/pyproject.toml
25+
+++ b/pyproject.toml
26+
@@ -11,7 +11,13 @@ dynamic = ["version"]
27+
requires-python = ">=3.10"
28+
readme = "README.md"
29+
license = "BSD-3-clause"
30+
-license-files = ["LICENSE"]
31+
+license-files = [
32+
+ "LICENSE*",
33+
+ "extern/fastjet-core/COPYING",
34+
+ "extern/fastjet-core/plugins/SISCone/siscone/COPYING",
35+
+ "extern/fastjet-contrib/COPYING",
36+
+ "extern/fastjet-contrib/*/COPYING",
37+
+]
38+
classifiers = [
39+
"Development Status :: 1 - Planning",
40+
"Intended Audience :: Developers",
41+
--
42+
2.43.0
43+

0 commit comments

Comments
 (0)