Skip to content

build-paddlepaddle

build-paddlepaddle #19

# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# Paddle publishes no wheel workflow on GitHub; ci/run_setup.sh is the script
# its own CI drives, so this mirrors that script's Linux CPU environment and
# its `python setup.py bdist_wheel` invocation, narrowed to riscv64.
name: Build paddlepaddle wheels (riscv64)
on:
workflow_dispatch:
inputs:
version:
description: 'Version glob to (re)build; empty builds every version of docs/packages/paddlepaddle.yaml not released yet'
required: false
default: ''
pull_request:
branches: [main]
paths:
- '.github/workflows/build-paddlepaddle.yml'
- 'docs/packages/paddlepaddle.yaml'
- 'patches/paddlepaddle/**'
push:
branches: [main]
paths:
- '.github/workflows/build-paddlepaddle.yml'
- 'docs/packages/paddlepaddle.yaml'
- 'patches/paddlepaddle/**'
run-name: build-paddlepaddle ${{ inputs.version && format('- {0}', inputs.version) || '' }}
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
jobs:
setup:
uses: $/.github/workflows/_setup.yml
with:
package: paddlepaddle
version: ${{ inputs.version }}
build_wheels:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
name: Build paddlepaddle ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 2880 # 48h: 1.3M lines of heavily templated C++ plus the
# third_party world, on the same 4-core runners that
# need this budget for build-vtk.yml.
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
# libpaddle.so links CPython directly, so every interpreter rebuilds the
# whole tree. cp313 is the newest upstream publishes for this release.
python: ["cp312", "cp313"]
env:
PADDLE_VERSION: ${{ matrix.version }}
steps:
- name: Checkout Paddle v${{ matrix.version }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: PaddlePaddle/Paddle
ref: v${{ matrix.version }}
path: Paddle
# `git submodule update --init`, as ci/run_setup.sh runs it: cmake
# skips its own submodule step under WITH_SETUP_INSTALL.
submodules: true
persist-credentials: false
- name: Checkout python-wheels
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: python-wheels
persist-credentials: false
- name: Patch Paddle source
working-directory: Paddle
run: |
git apply ../python-wheels/patches/paddlepaddle/${{ matrix.version }}/*.patch
# The recorded submodule commit is a 0.3.7-era tree that knows no riscv64
# target; openblas.cmake means to move it to CBLAS_TAG itself, but its
# `git checkout v0.3.28` fails silently against a tagless submodule clone.
- name: Move the OpenBLAS submodule to the tag openblas.cmake builds
working-directory: Paddle/third_party/openblas
run: |
git fetch --depth 1 origin tag v0.3.28
git checkout v0.3.28
# gloo.cmake and protobuf.cmake make `git checkout <tag>` an
# ExternalProject patch step, which aborts the build against the tagless
# submodule clone; both tags already name the recorded commit, so only the
# ref is missing and no checkout of our own is needed.
- name: Fetch the submodule tags the third_party patch steps check out
run: |
git -C Paddle/third_party/gloo fetch --depth 1 origin tag v0.0.3
git -C Paddle/third_party/protobuf fetch --depth 1 origin tag v21.12
# Parity with build-vtk.yml's own guard, though swapon fails on these
# runners (/ is overlayfs), so 15GB of RAM is the real link budget.
- name: Set swap space
uses: pierotofy/set-swap-space@fc79b3f67fa8a838184ce84a674ca12238d2c761 # master
with:
swap-size-gb: 10
- name: Write container script
run: |
cat > Paddle/riscv64-build-and-test.sh <<'EOF'
#!/bin/bash
set -e -x
python_exe="/opt/python/${PYTHON_TAG}-${PYTHON_TAG}/bin/python"
py_version="${PYTHON_TAG#cp}"
py_version="${py_version:0:1}.${py_version:1}"
case "$1" in
build)
# patch 3/5 resolves LAPACK_LIB/BLAS_LIB/GFORTRAN_LIB to these, in
# place of an x86-64-only prebuilt tarball; libgfortran comes with
# them, and riscv64 has no libquadmath to ask for.
dnf install -y --setopt=install_weak_deps=False lapack blas
"${python_exe}" -m pip install -U pip setuptools wheel
"${python_exe}" -m pip install -r /paddle/python/requirements.txt
"${python_exe}" -m pip install -r /paddle/paddle/scripts/compile_requirements.txt
# The operator generators under paddle/fluid/operators/generator/
# import yaml, which upstream's own build image preinstalls rather
# than declaring in either requirements file.
"${python_exe}" -m pip install pyyaml
export PYTHON_EXECUTABLE="${python_exe}"
export PY_VERSION="${py_version}"
export CMAKE_BUILD_TYPE=Release
export WITH_RISCV=ON
export WITH_GPU=OFF
export WITH_ROCM=OFF
export WITH_XPU=OFF
export WITH_IPU=OFF
export WITH_TENSORRT=OFF
export WITH_OPENVINO=OFF
export WITH_ONNXRUNTIME=OFF
export WITH_CUDNN_FRONTEND=OFF
export WITH_CINN=OFF
export WITH_DISTRIBUTE=OFF
export WITH_PYTHON=ON
export WITH_TESTING=OFF
export WITH_CPP_TEST=OFF
export WITH_INFERENCE_API_TEST=OFF
export ON_INFER=OFF
export WITH_STRIP=ON
# The released Linux wheels split phi and pir out of libpaddle.so;
# a single object would not link in this runner's memory.
export WITH_SHARED_PHI=ON
export WITH_SHARED_IR=ON
export MAX_JOBS="$(nproc)"
cd /paddle
"${python_exe}" setup.py bdist_wheel
auditwheel show dist/*.whl
auditwheel repair -w /paddle/wheelhouse dist/*.whl
;;
test)
"${python_exe}" -m venv /tmp/venv
. /tmp/venv/bin/activate
pip install -U pip
pip install /paddle/wheelhouse/*.whl
cd /tmp
# Upstream's documented post-install verification.
python -c "import paddle; paddle.utils.run_check()"
# Exercises the liblapack.so.3 patch 3/5 puts in paddle/libs/.
python -c "import paddle; x = paddle.rand([8, 8]); q, r = paddle.linalg.qr(x); assert paddle.allclose(q @ r, x, atol=1e-5)"
;;
*)
echo "usage: $0 <build|test>" >&2
exit 1
;;
esac
EOF
# numpy and Pillow of python/requirements.txt have riscv64 wheels only on
# our registry; only-binary keeps a newer PyPI release from winning the
# resolution and then compiling from sdist (Pillow's needs libjpeg headers
# the image does not carry).
- name: Build wheel
run: |
podman run -t \
--log-driver=none \
--network=host \
-v "${PWD}/Paddle":/paddle \
--workdir /paddle \
-e PYTHON_TAG="${{ matrix.python }}" \
-e PADDLE_VERSION="${PADDLE_VERSION}" \
-e PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ \
-e PIP_ONLY_BINARY=numpy,pillow \
--pull=newer \
"${MANYLINUX_RISCV64_IMAGE}" \
bash /paddle/riscv64-build-and-test.sh build
# Paddle's EXTERNAL_PROJECT_LOG_ARGS sends every third_party configure and
# install step to a stamp log instead of stdout, so a failure there says
# only "Command failed: 1" in the step above.
- name: Show third_party stamp logs
if: failure()
run: |
tail -n 40 -v Paddle/build/third_party/*/src/*-stamp/*-*-*.log || true
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: paddlepaddle-${{ env.PADDLE_VERSION }}-${{ matrix.python }}-manylinux_riscv64
path: Paddle/wheelhouse/*.whl
if-no-files-found: error
- name: Test wheel
run: |
podman run -t \
--log-driver=none \
--network=host \
-v "${PWD}/Paddle":/paddle \
--workdir /paddle \
-e PYTHON_TAG="${{ matrix.python }}" \
-e PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ \
-e PIP_ONLY_BINARY=numpy,pillow \
"${MANYLINUX_RISCV64_IMAGE}" \
bash /paddle/riscv64-build-and-test.sh test
gpl_sources:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
name: Collect GPL sources (gcc) for paddlepaddle ${{ matrix.version }}
runs-on: ubuntu-24.04-riscv
env:
PADDLE_VERSION: ${{ matrix.version }}
steps:
# setup.py copies GFORTRAN_LIB and GNU_RT_LIB_1 into paddle/libs/, which
# patch 3/5 resolves to the image's own libgfortran.so.5 and
# libquadmath.so.0.
- name: Collect gcc source RPM from manylinux_riscv64
uses: riseproject-dev/python-wheels/actions/collect-gpl-sources@main
with:
image: ${{ env.MANYLINUX_RISCV64_IMAGE }}
packages: gcc
output: gpl-sources.tar
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: paddlepaddle-${{ env.PADDLE_VERSION }}-gpl-sources
path: gpl-sources.tar
if-no-files-found: error
publish:
name: Publish paddlepaddle ${{ matrix.version }}
needs: [setup, build_wheels, gpl_sources]
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: paddlepaddle-${{ matrix.version }}-*-manylinux_riscv64
gpl-sources-artifact: paddlepaddle-${{ matrix.version }}-gpl-sources
gpl-sources-description: gcc