From 297dc704b8152946dfd92d5b72915afed61368ec Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 3 Sep 2026 20:20:47 +0200 Subject: [PATCH 1/3] libclang: add build-libclang.yml for riscv64 wheels Compiles libclang.so from the LLVM 18.1.1 source release inside manylinux_2_39_riscv64 and packages it via upstream's own setup_ext.py, mirroring libclang-linux-amd64.yml/libclang-linux-aarch64.yml narrowed to riscv64. Upstream publishes no riscv64 wheel. --- .github/workflows/build-libclang.yml | 130 +++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 .github/workflows/build-libclang.yml diff --git a/.github/workflows/build-libclang.yml b/.github/workflows/build-libclang.yml new file mode 100644 index 000000000..6228c5ecf --- /dev/null +++ b/.github/workflows/build-libclang.yml @@ -0,0 +1,130 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Based on: https://github.com/sighingnow/libclang/blob/llvm-18.1.1/.github/workflows/libclang-linux-amd64.yml +name: Build libclang wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'libclang version to build (LLVM release tag without the llvm- prefix, e.g. 18.1.1)' + required: true + default: '18.1.1' + pull_request: + paths: + - '.github/workflows/build-libclang.yml' + +concurrency: + group: ${{ github.workflow }}-${{ inputs.version || '18.1.1' }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + LIBCLANG_VERSION: ${{ inputs.version || '18.1.1' }} + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + + build_wheels: + needs: [setup] + name: Build libclang ${{ inputs.version || '18.1.1' }} py2.py3-none-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 1440 # full LLVM/Clang compile from source + + steps: + - name: Checkout libclang llvm-${{ env.LIBCLANG_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: sighingnow/libclang + ref: llvm-${{ env.LIBCLANG_VERSION }} + persist-credentials: false + + - name: Pull manylinux_riscv64 image + run: docker pull "${MANYLINUX_RISCV64_IMAGE}" + + # libstdc++-static is CRB-only; upstream's cross-compiled aarch64/x86_64 jobs + # get it from their apt/manylinux2010 images without asking. + - name: Build libclang.so and the wheel + run: | + docker run --rm -v "$(pwd):/work" -w /work -e LIBCLANG_VERSION "${MANYLINUX_RISCV64_IMAGE}" bash -c ' + set -euxo pipefail + dnf -y --enablerepo=crb install libstdc++-static + curl -fsSL -o "llvm-project-${LIBCLANG_VERSION}.src.tar.xz" \ + "https://github.com/llvm/llvm-project/releases/download/llvmorg-${LIBCLANG_VERSION}/llvm-project-${LIBCLANG_VERSION}.src.tar.xz" + tar xf "llvm-project-${LIBCLANG_VERSION}.src.tar.xz" + mv "llvm-project-${LIBCLANG_VERSION}.src" "llvm-project-${LIBCLANG_VERSION}" + mkdir -p "llvm-project-${LIBCLANG_VERSION}/build" + cd "llvm-project-${LIBCLANG_VERSION}/build" + cmake ../llvm \ + -DLLVM_ENABLE_PROJECTS=clang \ + -DBUILD_SHARED_LIBS=OFF \ + -DLLVM_ENABLE_ZLIB=OFF \ + -DLLVM_ENABLE_ZSTD=OFF \ + -DLLVM_ENABLE_TERMINFO=OFF \ + -DLLVM_TARGETS_TO_BUILD=RISCV \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O2 -g -DNDEBUG -static-libgcc -static-libstdc++" + make libclang -j"$(nproc)" + strip lib/libclang.so + du -csh lib/libclang.so + file lib/libclang.so + ldd lib/libclang.so + nm --dynamic --undefined-only --with-symbol-versions lib/libclang.so + cd /work + cp "llvm-project-${LIBCLANG_VERSION}/build/lib/libclang.so" native/ + pybin=/opt/python/cp312-cp312/bin + "$pybin/pip" install -q wheel + "$pybin/python3" setup_ext.py bdist_wheel --plat-name=manylinux_2_39_riscv64 + "$pybin/pip" install -q dist/*.whl + "$pybin/python3" - < Date: Fri, 4 Sep 2026 08:15:11 +0200 Subject: [PATCH 2/3] libclang: install setuptools before running setup_ext.py setup_ext.py imports distutils directly; Python 3.12 dropped it from the stdlib and pip install wheel alone doesn't pull in setuptools' compatibility shim, so the wheel build died with ModuleNotFoundError after the full LLVM/Clang compile finished (gotcha 211). --- .github/workflows/build-libclang.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-libclang.yml b/.github/workflows/build-libclang.yml index 6228c5ecf..7dd861071 100644 --- a/.github/workflows/build-libclang.yml +++ b/.github/workflows/build-libclang.yml @@ -78,7 +78,9 @@ jobs: cd /work cp "llvm-project-${LIBCLANG_VERSION}/build/lib/libclang.so" native/ pybin=/opt/python/cp312-cp312/bin - "$pybin/pip" install -q wheel + # setup_ext.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 "$pybin/python3" setup_ext.py bdist_wheel --plat-name=manylinux_2_39_riscv64 "$pybin/pip" install -q dist/*.whl "$pybin/python3" - < Date: Fri, 4 Sep 2026 18:19:56 +0200 Subject: [PATCH 3/3] libclang: pin wheel==0.43.0 for the packaging step wheel>=0.44.0 dropped wheel.bdist_wheel.get_platform in favour of setuptools' own bundled bdist_wheel command. Upstream's setup_ext.py imports get_platform directly from wheel.bdist_wheel, so an unpinned `pip install -U wheel` now breaks it with: ImportError: cannot import name 'get_platform' from 'wheel.bdist_wheel' right after last commit's distutils fix gets past the first import. Reproduced and fixed against the real setup_ext.py + a stub native/ tree in quay.io/pypa/manylinux_2_39_riscv64 (no LLVM rebuild needed): wheel 0.48.0 fails identically, wheel==0.43.0 produces a real wheel. Filed as gotcha 225. --- .github/workflows/build-libclang.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-libclang.yml b/.github/workflows/build-libclang.yml index 7dd861071..f566517c0 100644 --- a/.github/workflows/build-libclang.yml +++ b/.github/workflows/build-libclang.yml @@ -80,7 +80,9 @@ jobs: pybin=/opt/python/cp312-cp312/bin # setup_ext.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 + # wheel>=0.44.0 dropped wheel.bdist_wheel.get_platform, which setup_ext.py + # imports directly; pin to the last version that still exports it. + "$pybin/pip" install -q -U setuptools "wheel==0.43.0" "$pybin/python3" setup_ext.py bdist_wheel --plat-name=manylinux_2_39_riscv64 "$pybin/pip" install -q dist/*.whl "$pybin/python3" - <