Skip to content

paddlepaddle: Add version 3.3.1 - #2120

Merged
luhenry merged 13 commits into
mainfrom
port/paddlepaddle
Sep 21, 2026
Merged

luhenry merged 13 commits into
mainfrom
port/paddlepaddle

Conversation

@luhenry

@luhenry luhenry commented Sep 19, 2026 •

Copy link
Copy Markdown
Member

Compiles the whole Paddle CPU framework — 1.3M lines of C++ plus OpenBLAS, protobuf, cryptopp, gloo, warpctc/warprnnt and the rest of third_party/. Upstream publishes no riscv64 wheel.

Mirrors upstream's ci/run_setup.sh, which is the script Paddle's own CI drives; there is no wheel workflow in .github/workflows/.

Differs from upstream

  • WITH_RISCV=ON (new option, patch 0001) - Paddle has no riscv64 build mode at all.
  • WITH_SHARED_PHI=ON/WITH_SHARED_IR=ON - matches the released Linux wheels, which run_setup.sh's own defaults do not.
  • auditwheel repair - upstream hand-tags its wheel manylinux1_x86_64 and runs none.
  • PIP_EXTRA_INDEX_URL/PIP_ONLY_BINARY=numpy,pillow - python/requirements.txt has no riscv64 wheels on public PyPI for numpy and Pillow; upstream's own build image preinstalls them.
  • third_party/openblas moved onto v0.3.28 before the build - openblas.cmake means to do this itself, but cannot in a CI checkout (see the third run below).
  • v0.0.3 and v21.12 fetched into third_party/gloo and third_party/protobuf before the build - gloo.cmake and protobuf.cmake check those tags out from an ExternalProject patch step, and a CI checkout has no tags (see the fifth run below).
  • dnf install lapack blas in the build container - patch 0003 resolves LAPACK/BLAS out of the image instead of an x86-64-only tarball.
  • 10GB swap - parity with build-vtk.yml, though swapon fails on these runners (/ is overlayfs, so it exits Invalid argument and the action soft-passes), which makes the runner's 15GB of RAM the real link budget.

Matrix: cp312/cp313 - upstream ships cp39-cp313 for this release, so cp314 has no upstream counterpart.

Testing

  • paddle.utils.run_check(), upstream's documented post-install check, plus a QR round-trip to exercise LAPACK.

License: Wheel bundles OpenBLAS, reference LAPACK, protobuf, gflags, glog, cryptopp, warpctc, warprnnt and libgfortran/libquadmath (BSD-3-Clause, Boost-1.0 and GPL-3.0-with-GCC-exception), so a gpl_sources job collects the image's gcc sources.

Patches

  • 0001-Add-a-WITH_RISCV-build-option.patch - To upstream. Without it Xbyak's x86 JIT assembler, MKL, AVX and -m64 are all selected on riscv64, and libpaddle.so is missing __atomic_exchange_1 (Paddle#62037). It also turns SLEEF off through upstream's own WITH_SLEEF_DEFAULT switch, beside WIN32 and WITH_ROCM (see the sixth run below). riscv64-only.
  • 0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch - To upstream. Four gates pick their branch by listing the non-x86 architectures Paddle knows, so riscv64 falls into the x86 one and fails on <cpuid.h>/<pmmintrin.h>/<immintrin.h>. riscv64-only.
  • 0003-Take-liblapack-and-libblas-from-the-build-environment.patch - To upstream. cmake/external/lapack.cmake downloads one x86-64 tarball for all of Linux, so the wheel would ship x86-64 liblapack.so.3/libblas.so.3/libgfortran.so.3 — as the released linux_aarch64 wheel does today. Resolves liblapack.so.3, libblas.so.3 and libgfortran.so.5 out of the build environment with ${CMAKE_C_COMPILER} -print-file-name= instead, failing at configure time if one is missing; nothing links against them, setup.py only copies them into paddle/libs/ for phi/backends/dynload/lapack.cc to dlopen. It also makes setup.py's GNU_RT_LIB_1 copy conditional, the way the neighbouring GNU_RT_LIB_2 one already is, because there is no libquadmath to ship on riscv64 (see the fourth run). Reproduces on any non-x86 Linux.
  • 0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch - To upstream. cmake/external/python.cmake does find_package(PythonLibs ${PY_VERSION} REQUIRED), and a manylinux image has no linkable libpython to give it: pypa/manylinux configures every interpreter it ships with --disable-shared, so /opt/python/cp3XX-cp3XX carries Python.h and a libpython3.XX.a but no libpython3.XX.so. Nothing in this build links libpython anyway — cmake/generic.cmake's cc_library() already strips python off every non-Windows target's link line and links -Wl,-undefined,dynamic_lookup in its place, citing pybind11's own notes — so the patch keeps the REQUIRED lookup on Windows and elsewhere takes the include directory from PYTHON_EXECUTABLE's own sysconfig, leaving the library optional. Not riscv64-specific: manylinux builds --disable-shared on every architecture.
  • 0005-Give-OpenBLAS-a-riscv64-TARGET.patch - To upstream. OpenBLAS cannot detect a riscv64 host: getarch.c reaches its riscv64 definitions only through -DFORCE_RISCV64_*, which Makefile.system derives from TARGET=. This is the twin of the if(WITH_ARM) set(ARM_ARGS TARGET=ARMV8) already in openblas.cmake; RISCV64_GENERIC builds -march=rv64imafdc -mabi=lp64d, the baseline the wheel has to run on, where the ZVL* targets would compile RVV into a statically linked libopenblas.a. riscv64-only.

First run (35468812304): the cp312 leg failed after 42 minutes, and not in the C++ build — it never reached cmake. PIP_EXTRA_INDEX_URL was set on the test container only, so the build container's pip install -r python/requirements.txt resolved against public PyPI alone: numpy compiled from its sdist for 21 minutes, and Pillow then failed with RequiredDependencyException: jpeg, since the manylinux image carries no libjpeg headers. The cp313 leg was still inside the same numpy build. Fixed by passing the registry and PIP_ONLY_BINARY=numpy,pillow to the build container too; a pip install --dry-run --report rehearsal for cp312 and cp313 against both indexes now resolves every requirement to a wheel (numpy, protobuf and Pillow from pypi.riseproject.dev, safetensors' own riscv64 wheel from PyPI, the rest pure-Python).

Second run (35477018075): pip now resolves in ~13 minutes with nothing built from source, and both legs instead died in cmake configure — cp313 at 23 minutes, cp312 at 18 — still without compiling a single file:

CMake Error at .../FindPackageHandleStandardArgs.cmake:290 (message):
  Could NOT find PythonLibs (missing: PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS)
  (Required is at least version "3.13")
Call Stack (most recent call first):
  cmake/external/python.cmake:21 (find_package)

Patch 0004 above is the fix. Rehearsed locally on x86_64 against the patched file in both branches it can take — a distro libpython found, and -DCMAKE_DISABLE_FIND_PACKAGE_PythonLibs=TRUE for the manylinux case — where configure and generate both succeed, python becomes the INTERFACE target cc_library()'s add_dependencies() edge still accepts, and a shared library built the way cc_library() builds libpaddle.so links with its Py_* symbols undefined and no libpython in DT_NEEDED. Deliberately not done: pointing PYTHON_LIBRARY at the static libpython3.13.a to satisfy find_package(). CPython adds CFLAGSFORSHARED (-fPIC) only when LIBRARY differs from LDLIBRARY, which a --disable-shared build never does, so that archive holds no position-independent code and the link of libpaddle.so would have failed at the very end of a multi-hour build instead of at configure time.

The error: pathspec 'v0.3.28' did not match any file(s) known to git line in the same log was read as harmless here. It was not — see the third run.

Third run (35480013120): both legs red again, cp312 after 40 minutes and cp313 after 31, and for the first time the failures are ordinary dependency bugs rather than wiring — but the C++ tree is still untouched, so the cost question below is still open. Nothing in either log suggests the memory wall: no OOM kill, no cc1plus: out of memory, no virtual memory exhausted, no No space left on device, and 40 minutes against a 2880-minute budget. The two failures are

getarch.c:1193:2: error: #error "This arch/CPU is not supported by OpenBLAS."
make[4]: *** [Makefile.prebuild:62: getarch] Error 1

CMake Error at .../extern_lapack-stamp/extern_lapack-configure-Release.cmake:49 (message):
  Command failed: 1

extern_lapack is the earlier of the two — it is the only failure on cp313, which never got as far as OpenBLAS — and its diagnostic is gone: Paddle's EXTERNAL_PROJECT_LOG_ARGS sets LOG_CONFIGURE 1, so the job prints Command failed: 1 and the path of a stamp log that dies with the runner. Rather than spend a round recovering it, patch 0003 now drops the Reference-LAPACK source build and takes liblapack.so.3, libblas.so.3, libgfortran.so.5 and libquadmath.so.0 from the build image, which is where libgfortran/libquadmath had to come from anyway. Rocky 10 riscv64 ships exactly the sonames phi/backends/dynload/lapack.cc dlopens, build-casadi.yml and build-mlx.yml already dnf install those packages in this image, a missing one now fails in the first configure minute instead of at minute 33, and a Fortran build comes off a 4-core runner. The workflow also tails the third_party/*/src/*-stamp/*.log files on failure, so the next dependency failure says why.

extern_openblas is the run-2 note's "red herring", now run to ground. The submodule is not at v0.3.28: Paddle records third_party/openblas at 5f36f18, whose Makefile.rule reads VERSION = 0.3.7 — openblas.cmake's default CBLAS_TAG, with Linux getting v0.3.28 only through that runtime git checkout — and 0.3.7's getarch.c has no riscv64 target at all, not even FORCE_RISCV64_GENERIC. That is why the #error is at line 1193 where v0.3.28 has it at 1853. Since actions/checkout clones submodules without tags, the git checkout v0.3.28 can never succeed and nothing checks that it did, so configure proceeded against a 2019 OpenBLAS. The workflow now moves the submodule onto the tag (git fetch --depth 1 origin tag v0.3.28), and patch 0005 supplies the TARGET= that OpenBLAS needs on riscv64 at any version.

Fourth run (35482612162): both diagnoses above were right — Move the OpenBLAS submodule… and Patch Paddle source both succeeded on both legs — and then both legs died in 30 seconds inside the build container, on the dnf line that shipped with them:

Package libgfortran-14.3.1-4.4.el10.riscv64 is already installed.
No match for argument: libquadmath
Error: Unable to find a match: libquadmath

lapack and blas resolved fine, so the premise held; the two packages added to that line as insurance were the only things wrong with it. libgfortran was already in the image, and libquadmath cannot be: GCC builds it only where __float128 is a type distinct from long double, so there is none for riscv64 or aarch64, and dnf fails the whole transaction on one unmatched argument. Patch 0003 asked for libquadmath.so.0 too, and its FATAL_ERROR would have stopped the next configure, so it no longer resolves GNU_RT_LIB_1 at all — which leaves setup.py's unconditional shutil.copy() of it with nothing to copy, hence the second hunk guarding it exactly as GNU_RT_LIB_2 already is. That hunk is architecture-agnostic on purpose: it is the bug on every platform GCC ships no libquadmath for, and upstream's aarch64 wheel only survives it by shipping the x86-64 libquadmath.so.0 out of the tarball this patch replaces.

Both hunks of patch 0003 are now generated from the pristine v3.3.1 files with difflib rather than hand-written — a hand-written setup.py hunk whose context matched the file byte-for-byte was still rejected, and the generated one applies — and the patched setup.py parses.

Fifth run (35483780322): the furthest any round has got — 45 minutes on cp312, 47 on cp313, roughly 40 of them inside third_party/ — and every round-3 and round-4 fix held: the OpenBLAS submodule move, all five patches and the corrected dnf line all succeeded on both legs, and pip resolved every requirement to a wheel with nothing built from source. Still not the memory wall, and this time the log says so unambiguously: no Killed, no cc1plus: out of memory, no virtual memory exhausted, no No space left on device, no OOM-killer output and no timeout, against a 2880-minute budget. The Set swap space step reported swapon: /swapfile: swapon failed: Invalid argument with Swap: 0B both before and after, as expected on these runners.

Both legs died in the same place, at 6% with Paddle's own C++ tree still untouched:

[  6%] Performing patch step for 'extern_gloo'
error: pathspec 'v0.0.3' did not match any file(s) known to git
gmake[2]: *** [CMakeFiles/extern_gloo.dir/build.make:114: third_party/gloo/src/extern_gloo-stamp/extern_gloo-patch] Error 1

This is the third run's OpenBLAS cause with the opposite symptom. gloo.cmake sets PATCH_COMMAND git checkout -- . && git checkout ${GLOO_TAG}, so where openblas.cmake ran its checkout through execute_process with no RESULT_VARIABLE and quietly built the stale tree, this one is an ExternalProject patch step and takes the whole build down instead. third_party/gloo is recorded at 8b6b61d, which is exactly what refs/tags/v0.0.3 names, so nothing needs moving here — only the ref is missing, and a shallow tag fetch is the entire fix.

Rather than fix one dependency per round, the rest of cmake/external/ was swept for the same shape, which found one more that this configuration reaches and run 5 had not got to yet: protobuf.cmake's build_protobuf() patch step is an unconditional cd <src> && git checkout v21.12, and third_party/protobuf is recorded at f0dc78d, which is refs/tags/v21.12^{}. It would have failed identically a few minutes later. Everything else is safe — eigen, warpctc, warprnnt, cccl, libxsmm and the paddle/fluid/fp8 cutlass switch name commits rather than tags, and the tag-name checkouts in pybind11, pocketfft, gtest, cub, openvino and rocksdb are gated on GCC < 9, APPLE, WITH_TESTING OR WITH_DISTRIBUTE, CUDA, WITH_OPENVINO and the parameter-server tree respectively, none of which this build reaches.

Rehearsed locally for both submodules by reproducing exactly what actions/checkout leaves behind — git init, git remote add origin, git fetch --depth 1 origin <recorded sha>, git checkout FETCH_HEAD — which reproduces run 5's pathspec message verbatim, is fixed by git fetch --depth 1 origin tag <tag>, and then checks out to the commit that was already there, so neither submodule's tree changes. No patch is needed: this is a CI-checkout artefact, not an upstream bug, since a developer's own git clone --recursive has the tags.

Sixth run (35487425503): 2h33m on cp312 and 2h40m on cp313 — over three times any previous round, and the first to reach Paddle's own C++ tree. Every earlier fix held: pip resolved to wheels, all five patches applied, the OpenBLAS move and both tag fetches worked, and the whole of third_party/ built, SLEEF, gloo and protobuf included. Still not the memory wall, and again the logs say so unambiguously: no Killed, no cc1plus: out of memory, no virtual memory exhausted, no No space left on device, no OOM-killer output, no ld fatal error and no timeout. The pre-build probe logged Mem: 15Gi total, 14Gi available, Swap: 0B.

Both legs failed identically and deterministically at 21% of phi_core, on one translation unit:

[ 21%] Building CXX object paddle/phi/CMakeFiles/phi_core.dir/kernels/funcs/gru_compute.cc.o
.../phi/kernels/funcs/activation_functor.h:75:12: error: 'Sleef_sinf1_u35' was not declared in this scope; did you mean 'Sleef_sinf_u35'?
.../phi/kernels/funcs/activation_functor.h:89:12: error: 'Sleef_sind1_u10' was not declared in this scope; did you mean 'Sleef_sinhf_u10'?
gmake[2]: *** [paddle/phi/CMakeFiles/phi_core.dir/kernels/funcs/gru_compute.cc.o] Error 1

Eight errors in all — the Sine and Cosine specialisations for float, double, float16 and bfloat16.

The cause is patch 0001's own. It set WITH_SLEEF OFF ... FORCE inside the WITH_RISCV block at CMakeLists.txt:686, but cmake/third_party.cmake is included at line 591, so cmake/sleef.cmake had already run add_definitions(-DPADDLE_WITH_SLEEF) by the time the block was reached — the configure log says -- Compile with Sleef support in plain sight. The only consumer still reading the FORCE was paddle/phi/CMakeLists.txt's if(WITH_SLEEF) list(APPEND PHI_DEPS sleef), processed by add_subdirectory() after the block, so the build was compiling the SLEEF path and linking no SLEEF; had the header declared the symbols this would have surfaced hours later as undefined references at the final link instead. activation_functor.h gates on PADDLE_WITH_SLEEF alone and not on AVX, so patch 0001's original note about SLEEF being reachable only through AVX paths was wrong as well.

Enabling SLEEF properly is not the alternative. SLEEF 3.6.1's src/libm/CMakeLists.txt leaves DSP_SCALAR out of SLEEF_ARCH_RISCV64's header list, alone among its six architectures, and DSP_SCALAR is the only entry carrying no ISA-name argument — which mkrename.c reads as the symbol suffix, making it the only section that emits unsuffixed scalar declarations. The generated riscv64 sleef.h therefore declares Sleef_sinf1_u35purec and never Sleef_sinf1_u35. That looks like a SLEEF bug worth reporting upstream, but not one a wheel port should carry a patch for.

Patch 0001 now makes the decision at CMakeLists.txt:356 instead, adding OR WITH_RISCV to upstream's own WITH_SLEEF_DEFAULT beside WIN32 and WITH_ROCM. That runs before third_party is included, and it sees WITH_RISCV because setup.py forwards every WITH_* environment variable to cmake as a -D, which populates the cache before CMakeLists.txt runs at all. WITH_SLEEF is then consistently off, PADDLE_WITH_SLEEF is never defined, Sine/Cosine fall back to libm, and the SLEEF ExternalProject — about 25 minutes per leg here — goes away. The other options that block forces were checked for the same leak: WITH_AVX and WITH_MKL default to ${AVX_FOUND} and so were already off on riscv64, while WITH_XBYAK defaults on and cmake/external/xbyak.cmake does add_definitions(-DPADDLE_WITH_XBYAK -DXBYAK64), which leaked identically — harmlessly here, since cpu_info.h uses the macro only to skip defining cpuid() and the jit/gen subdirectory is added after the block, and cpu_info.cc.o compiled clean at 19%.

Verified against a pristine v3.3.1 checkout with both git apply --check and patch -p1 -F 0.

Still draft. The sixth run finally put Paddle's own C++ in front of the compiler, and the first answer is encouraging: 21% of phi_core built in roughly 100 minutes on a 4-core riscv64 runner, inside 15GB with no swap, with no memory pressure anywhere in the log. It is only a first answer. The remaining 79% of phi_core, libpaddle.so's own sources and the final link of a library that is 193MB on aarch64 are all still unproven, and that link in 15GB with no swap remains the original open risk. MAX_JOBS is deliberately left at nproc so that, if the compile does hit the memory ceiling, the failure is attributable rather than confounded with a parallelism change — and if the next run dies on memory rather than on another ordinary compile error, that is the resource wall, and parking under it is the call.

Paddle has no riscv64 support at all -- there is not one "riscv" string
in the v3.3.1 tree -- but nothing in it is architecturally x86-only
either. WITH_ARM, WITH_SW, WITH_MIPS and WITH_LOONGARCH already switch
off Xbyak's x86 JIT assembler, MKL and AVX and route the affected
kernels through their scalar fallbacks, and upstream ships linux_aarch64
wheels built that way. This adds a fourth such architecture.

Three patches: a WITH_RISCV option mirroring WITH_LOONGARCH (plus
-latomic and no -m64), PADDLE_WITH_RISCV added to the four x86-intrinsic
gates that pick their branch by listing non-x86 architectures, and a
source build of Reference-LAPACK because upstream's prebuilt
lapack_lnx tarball is x86-64 only -- the released linux_aarch64 wheel
ships x86-64 liblapack.so.3/libblas.so.3/libgfortran.so.3 today.

Everything else auto-disables: WITH_MKL and WITH_AVX default to
${AVX_FOUND}, WITH_ONEDNN needs AVX2, the AVX-512 fusion kernels are
dropped from the build without AVX512F_FOUND, and CINN/CUDA/ROCm/XPU are
off by default.
@github-actions

github-actions Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-21 07:43 UTC

luhenry added a commit that referenced this pull request Sep 19, 2026
Not architecturally blocked: every x86-specific component in Paddle's
CPU build auto-disables on riscv64 except WITH_XBYAK, which upstream's
own non-x86 blocks already force off, and upstream ships linux_aarch64
wheels built that way. Three patches cover the five arch gates plus the
x86-only prebuilt LAPACK. Open risk is build cost, not portability.
The build container ran pip without PIP_EXTRA_INDEX_URL, so
python/requirements.txt resolved against public PyPI only: numpy compiled
from its sdist for 21 minutes and Pillow then failed outright, since the
manylinux image carries no libjpeg headers. The test container already
pointed at pypi.riseproject.dev; the build one has to as well.

only-binary for numpy and pillow keeps a newer PyPI release from winning
the resolution and compiling from sdist once our registry lags a version
behind. A dry-run resolution for cp312 and cp313 against both indexes now
picks wheels for every requirement: numpy, protobuf and pillow from our
registry, safetensors' own riscv64 wheel and pure-Python wheels for the
rest.

Also drop the swap step's OOM-guard claim: swapon fails with EINVAL on
these runners because / is overlayfs (this job and a green deltalake run
both report it), so the link has 15GB of RAM and no swap.
The cp313 build died in cmake configure, 23 minutes in, before compiling
anything:

  Could NOT find PythonLibs (missing: PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS)
  (Required is at least version "3.13")
  cmake/external/python.cmake:21 (find_package)

cmake/external/python.cmake demands a linkable libpython on every
platform, and a manylinux image has none to offer: pypa/manylinux builds
each of its interpreters with --disable-shared, so /opt/python/cp313-cp313
carries Python.h and libpython3.13.a but no libpython3.13.so, and
FindPythonLibs does not accept a static archive. Nothing in this
configuration wants the library anyway - cmake/generic.cmake's
cc_library() strips `python` off the link line of every non-Windows
target and links "-Wl,-undefined,dynamic_lookup" instead, leaving the
CPython symbols for the interpreter that loads libpaddle.so, and the
remaining PYTHON_LIBRARIES readers are the cc_test() executables
(WITH_TESTING=OFF) and a pair of dead variables.

Patch 0004 keeps the REQUIRED lookup on Windows and elsewhere takes the
include directory from PYTHON_EXECUTABLE's own sysconfig, leaving the
library optional. Satisfying find_package() by pointing PYTHON_LIBRARY at
libpython3.13.a would have been the wrong repair, and an expensive one:
CPython adds CFLAGSFORSHARED (-fPIC) only when LIBRARY differs from
LDLIBRARY, which never holds for --disable-shared, so the archive holds no
position-independent code and the link of libpaddle.so would have failed
at the very end of a multi-hour build instead of at configure time.

Rehearsed locally on x86_64 against the patched file with cmake, in both
the branch a distro libpython takes and the branch manylinux takes
(-DCMAKE_DISABLE_FIND_PACKAGE_PythonLibs): configure and generate both
succeed, `python` becomes an INTERFACE target that cc_library()'s
add_dependencies() edge still accepts, and a shared library built the way
cc_library() builds libpaddle.so links with the Py_* symbols left
undefined and no libpython in DT_NEEDED.
luhenry added a commit that referenced this pull request Sep 20, 2026
…tic libpython; queue: record paddlepaddle's second CI run

paddlepaddle PR #2120's second run got past the pip failure gotcha 422
covers and stopped in cmake configure instead, 23 minutes in and still
before compiling anything: cmake/external/python.cmake does
find_package(PythonLibs REQUIRED), and a manylinux image has no linkable
libpython to offer, because pypa/manylinux configures every interpreter it
ships with --disable-shared.

Gotcha 428 is the deprecated-module sibling of 374. Where 374's project
could ask for Development.Module and be done, FindPythonLibs has no
headers-only mode, so the entry records the two things worth knowing
before touching such a project: that pointing PYTHON_LIBRARY at the
static libpythonX.Y.a passes configure and then fails at the *final*
link, since CPython adds -fPIC only when LIBRARY differs from LDLIBRARY;
and that the project may already strip libpython from its own non-Windows
link lines, as Paddle's cmake/generic.cmake does, which makes the
REQUIRED vestigial and the fix a no-op for every link line. It also
records the local x86_64 rehearsal, which costs a minute against a
multi-hour riscv64 job: include the patched .cmake from a throwaway
project, force the manylinux branch with
-DCMAKE_DISABLE_FIND_PACKAGE_PythonLibs=TRUE, and check the resulting .so
with nm -D and readelf -d.

The queue entry also notes that the same log's red "error: pathspec
v0.3.28 did not match any file(s) known to git" is a red herring from
openblas.cmake version-syncing a shallow submodule, not the failure.
Run 3 of PR #2120 failed in third_party on both interpreters.

extern_openblas stopped at getarch.c's "This arch/CPU is not supported
by OpenBLAS": actions/checkout clones submodules without tags, so
openblas.cmake's own `git checkout v0.3.28` fails and leaves the
recorded submodule commit, a 0.3.7-era tree with no riscv64 target at
all. Move the submodule to the tag openblas.cmake builds, and add the
TARGET=RISCV64_GENERIC that OpenBLAS needs on riscv64 because getarch
only reaches its riscv64 branch through -DFORCE_RISCV64_*.

extern_lapack stopped at its cmake configure step, whose output
EXTERNAL_PROJECT_LOG_ARGS keeps in a stamp log the job never printed.
Resolve liblapack.so.3, libblas.so.3, libgfortran.so.5 and
libquadmath.so.0 out of the build image instead of building
Reference-LAPACK from source: nothing links against them, setup.py only
copies them into paddle/libs/ for phi/backends/dynload/lapack.cc to
dlopen, and a missing one now fails at configure time. Also print the
stamp logs when a build fails, so the next third_party failure says why.
Run 4's build container died in 30 seconds on the dnf line the previous
commit added: "Error: Unable to find a match: libquadmath". libquadmath
is built only where __float128 is a type distinct from long double, so
GCC ships none for riscv64 and Rocky packages none - the same reason
aarch64 has none. Drop it from the dnf line, where libgfortran was also
redundant (already in the image, and a dependency of lapack anyway).

Patch 3/5 asked for libquadmath.so.0 too, and its FATAL_ERROR would have
stopped the next configure, so stop resolving GNU_RT_LIB_1 at all. That
leaves it empty, which setup.py's unconditional shutil.copy() cannot
take, so guard that copy the way the neighbouring GNU_RT_LIB_2 one
already is - architecture-agnostically, since this is the bug on every
platform without a libquadmath. Both hunks are now generated from the
pristine v3.3.1 files rather than hand-written, and verified to apply;
the patched setup.py parses.
…k out

Run 5 of PR #2120 got 40 minutes into third_party on both interpreters -
past every round-3 and round-4 fix, which all held - and then died in the
same class of bug as OpenBLAS, one dependency further on:

  Performing patch step for 'extern_gloo'
  error: pathspec 'v0.0.3' did not match any file(s) known to git

gloo.cmake's PATCH_COMMAND is `git checkout -- . && git checkout
${GLOO_TAG}`, and actions/checkout gives a submodule its recorded commit
without any tags, so that ref does not exist. Where openblas.cmake runs its
checkout through execute_process with no RESULT_VARIABLE and silently builds
the stale tree, this one is an ExternalProject patch step, so it takes the
whole build down instead.

third_party/gloo is recorded at 8b6b61d, which is exactly what
refs/tags/v0.0.3 names, so nothing needs moving here: only the ref is
missing, and a shallow tag fetch is the whole fix.

Sweeping the rest of cmake/external for the same shape found one more that
this configuration reaches and run 5 had not got to yet: protobuf.cmake's
build_protobuf() patch step is an unconditional `cd <src> && git checkout
v21.12`, and third_party/protobuf is recorded at f0dc78d, which is
refs/tags/v21.12^{}. It would have failed identically a few minutes later.
Everything else is safe - eigen, warpctc, warprnnt, cccl, libxsmm and the
fp8 cutlass switch name commits rather than tags, and the tag-name
checkouts in pybind11, pocketfft, gtest, cub, openvino and rocksdb are
gated on GCC < 9, APPLE, WITH_TESTING/WITH_DISTRIBUTE, CUDA, WITH_OPENVINO
and the parameter-server tree, none of which this build reaches.

Rehearsed locally for both submodules by reproducing what actions/checkout
leaves behind, a repo fetched at the recorded commit with no tags: the
checkout fails with run 5's exact message, the tag fetch supplies the ref,
and the checkout then lands on the commit that was already there.
Round 6 reached Paddle's own C++ tree and stopped at 21% of phi_core, on
kernels/funcs/gru_compute.cc: eight "'Sleef_sinf1_u35' was not declared
in this scope" errors out of activation_functor.h's Sine/Cosine
specialisations, which select the SLEEF entry points on PADDLE_WITH_SLEEF
alone.

Patch 1/5 already meant to keep SLEEF out of a riscv64 build, but its
set(WITH_SLEEF OFF ... FORCE) sat in the WITH_RISCV block at
CMakeLists.txt:686, and cmake/third_party.cmake is included at line 591 -
so cmake/sleef.cmake had already run add_definitions(-DPADDLE_WITH_SLEEF)
by then. The only consumer still reading the FORCE was
paddle/phi/CMakeLists.txt's `if(WITH_SLEEF) list(APPEND PHI_DEPS sleef)`,
leaving the build compiling the SLEEF path and not linking SLEEF. The
configure log shows the result plainly: "-- Compile with Sleef support".

Move the decision to upstream's own WITH_SLEEF_DEFAULT switch at
CMakeLists.txt:356, next to WIN32 and WITH_ROCM, which runs before
third_party is included and is reached because setup.py forwards every
WITH_* environment variable as a -D, so WITH_RISCV is already in the
cache. WITH_SLEEF is then consistently OFF, PADDLE_WITH_SLEEF is never
defined, and Sine/Cosine fall back to libm - the configuration Paddle
already ships for Windows and ROCm. It also drops the SLEEF
ExternalProject, roughly 25 minutes per leg on these runners.

Turning SLEEF on instead is not an option here: SLEEF 3.6.1's
src/libm/CMakeLists.txt leaves DSP_SCALAR out of SLEEF_ARCH_RISCV64's
header list, alone among its six architectures, and DSP_SCALAR is the
only entry carrying no ISA name - the only one mkrename.c emits
unsuffixed scalar declarations from. The generated riscv64 sleef.h
declares Sleef_sinf1_u35purec and never Sleef_sinf1_u35.
@luhenry
luhenry marked this pull request as ready for review September 21, 2026 00:35
@luhenry
luhenry merged commit e8442b2 into main Sep 21, 2026
11 checks passed
@luhenry
luhenry deleted the port/paddlepaddle branch September 21, 2026 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant