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
131 changes: 131 additions & 0 deletions .github/workflows/build-cppyy-cling.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on: https://github.com/wlav/cppyy-backend/blob/cppyy-cling-6.32.8/.github/workflows/cling-wheels.yml
name: Build cppyy-cling wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'Version glob to (re)build; empty builds every version of docs/packages/cppyy-cling.yaml not released yet'
required: false
default: ''
pull_request:
branches: [main]
paths:
- '.github/workflows/build-cppyy-cling.yml'
- 'docs/packages/cppyy-cling.yaml'
- 'patches/cppyy-cling/**'
push:
branches: [main]
paths:
- '.github/workflows/build-cppyy-cling.yml'
- 'docs/packages/cppyy-cling.yaml'
- 'patches/cppyy-cling/**'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions:
contents: read # to fetch code (actions/checkout)

env:
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
WHEEL_PLATFORM_TAG: manylinux_2_39_riscv64

jobs:
setup:
uses: $/.github/workflows/_setup.yml
with:
package: cppyy-cling
version: ${{ inputs.version }}

build_wheels:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
name: Build cppyy-cling ${{ matrix.version }} py2.py3-none-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 1440 # full LLVM/Clang + Cling build from source

env:
CPPYY_CLING_VERSION: ${{ matrix.version }}

steps:
- name: Checkout cppyy-backend cppyy-cling-${{ env.CPPYY_CLING_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: wlav/cppyy-backend
ref: cppyy-cling-${{ env.CPPYY_CLING_VERSION }}
path: cppyy-backend
persist-credentials: false

- name: Checkout python-wheels
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: python-wheels
persist-credentials: false

- name: Apply patches
working-directory: cppyy-backend
run: git apply -v ../python-wheels/patches/cppyy-cling/${{ env.CPPYY_CLING_VERSION }}/*.patch

# Upstream's own cibuildwheel config runs this as `before-all`; it pulls
# ROOT's release source tarball from root.cern.ch and copies its
# interpreter/ subtree (Cling + the LLVM/Clang monorepo) into cling/src.
- name: Fetch Cling's ROOT source tree
working-directory: cppyy-backend/cling
run: python3 create_src_directory.py

- name: Pull manylinux_riscv64 image
run: docker pull "${MANYLINUX_RISCV64_IMAGE}"

- name: Build the wheel
run: |
docker run --rm -v "$(pwd)/cppyy-backend/cling:/work" -w /work \
-e WHEEL_PLATFORM_TAG \
"${MANYLINUX_RISCV64_IMAGE}" bash -c '
set -euxo pipefail
pybin=/opt/python/cp312-cp312/bin
# setup.py does `import distutils`, removed from the stdlib in 3.12;
# setuptools (unlike wheel alone) installs the shim that resolves it.
"$pybin/pip" install -q -U setuptools wheel
# AUDITWHEEL_PLAT/_PYTHON_HOST_PLATFORM: setup.py only recognizes
# manylinux1/2010/2014 by /etc/redhat-release (gotcha patch 1); set
# the former so it builds Release (not debug-laden RelWithDebInfo)
# like every other published platform, and the latter is what the
# custom bdist_wheel command (via distutils get_platform()) tags
# the wheel with.
AUDITWHEEL_PLAT="${WHEEL_PLATFORM_TAG}" _PYTHON_HOST_PLATFORM="${WHEEL_PLATFORM_TAG}" \
"$pybin/python3" setup.py bdist_wheel
"$pybin/pip" install -q dist/*.whl
"$pybin/python3" -c "import cppyy_backend"
'

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cppyy-cling-${{ env.CPPYY_CLING_VERSION }}-py2.py3-none-manylinux_riscv64
path: cppyy-backend/cling/dist/*.whl
if-no-files-found: error

publish:
name: Publish cppyy-cling ${{ matrix.version }}
needs: [setup, build_wheels]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
secrets:
app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }}
with:
artifact-pattern: cppyy-cling-${{ matrix.version }}-*-manylinux_riscv64
5 changes: 5 additions & 0 deletions docs/packages/cppyy-cling.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package-name: cppyy-cling
source-code: https://github.com/wlav/cppyy-backend
license: 'LLVM/Cling: University of Illinois/NCSA Open Source License; ROOT: LGPL 2.1'
versions:
- version: 6.32.8
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Thu, 15 Oct 2026 06:29:40 +0000
Subject: [PATCH] setup: recognize current-generation manylinux images

Upstream-Status: To upstream [not yet submitted; generalizes a check that predates manylinux_2_28+]

is_manylinux() only recognizes manylinux1/manylinux2010/manylinux2014 by
matching three hardcoded /etc/redhat-release strings (CentOS 5.11/6.10/
7.9.2009). quay.io/pypa/manylinux_2_39_riscv64 (this repo's riscv64 image,
PEP 600) is Rocky Linux 10-based and matches none of them, so
is_manylinux() silently returns False inside it. That flag drives two
decisions in my_cmake_build.run(): the CMake build type (Release vs.
RelWithDebInfo, the latter keeping full debug info -- "too large for
wheels" per this same file's own comment) and the default STDCXX (17 vs.
20), plus my_install.run()'s cxxversion-advertising rewrite ("reset the
default cxxversion to 20 if no user override" on real manylinux builds).
Misdetecting manylinux here would ship a riscv64 wheel built differently
(bigger, debug-laden, and advertising a C++ standard it wasn't actually
built with) from every other published platform.

All pypa/manylinux images, including the newer PEP 600 (_2_28/_2_34/
_2_39) generations, bake in AUDITWHEEL_PLAT (the policy auditwheel itself
targets, e.g. manylinux_2_39_riscv64) -- a stable, generation-independent
marker. Check it first and keep the existing string match as a fallback
for the images it already recognized.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
cling/setup.py | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/cling/setup.py b/cling/setup.py
index d7826bf..8dbdf4e 100755
--- a/cling/setup.py
+++ b/cling/setup.py
@@ -44,6 +44,11 @@ def is_manylinux():
global _is_manylinux
if _is_manylinux is None:
_is_manylinux = False
+ # all pypa/manylinux images, including the PEP 600 generations that
+ # post-date the CentOS-release checks below, export this.
+ if os.environ.get('AUDITWHEEL_PLAT', '').startswith('manylinux'):
+ _is_manylinux = True
+ return _is_manylinux
try:
for line in open('/etc/redhat-release').readlines():
# mark manylinux1, manylinux2010, or manylinux2014
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Thu, 15 Oct 2026 06:30:19 +0000
Subject: [PATCH] setup: scope LLVM targets to build on riscv64 linux

Upstream-Status: To upstream [not yet submitted; mirrors the existing macOS arm64 branch below it]

my_cmake_build.run() never passes -DLLVM_TARGETS_TO_BUILD on Linux (only
macOS arm64 and Windows get an explicit value); src/interpreter/
CMakeLists.txt does have a `ROOT_ARCHITECTURE MATCHES riscv64` branch that
would set it to "RISCV;NVPTX", the same shape as its AArch64/ARM/PowerPC/
SystemZ branches, but ROOT_ARCHITECTURE is never set in this cling-only
build (src/CMakeLists.txt never include()s ROOT's SetUpLinux.cmake), so
that branch is unreachable and dispatch falls through to the "all" case:
every LLVM backend (x86, arm, aarch64, powerpc, systemz, riscv, ...), not
just the one the build runs on. That turns an already multi-hour
from-source LLVM+Clang+Cling build into one compiling backends that can
never be used on this host.

LLVM_TARGETS_TO_BUILD is a CACHE variable; src/interpreter/CMakeLists.txt
only set()s it (no FORCE), so a value supplied on the cmake command line
-- as this patch adds -- wins over that fallback, the same way the macOS
arm64 branch immediately above already overrides it for that platform.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
cling/setup.py | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/cling/setup.py b/cling/setup.py
index 8dbdf4e..d390f5b 100755
--- a/cling/setup.py
+++ b/cling/setup.py
@@ -169,6 +169,10 @@ class my_cmake_build(_build):
import platform
if 'arm64' in platform.machine():
CMAKE_COMMAND += ['-DLLVM_TARGETS_TO_BUILD=ARM;AArch64;NVPTX']
+ elif 'linux' in sys.platform:
+ import platform
+ if 'riscv64' in platform.machine():
+ CMAKE_COMMAND += ['-DLLVM_TARGETS_TO_BUILD=RISCV;NVPTX']
CMAKE_COMMAND.append('-DCMAKE_INSTALL_PREFIX='+prefix)

log.info('Running cmake for cppyy-cling: %s', ' '.join(CMAKE_COMMAND))
Loading