Skip to content
Merged
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
147 changes: 147 additions & 0 deletions .github/workflows/build-pnnx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on the `build`/`test` jobs of:
# https://github.com/Tencent/ncnn/blob/master/.github/workflows/pnnx.yml
name: Build pnnx wheels (riscv64)

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

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
# pnnx ships no sdist and no git tag; its PyPI version is the UTC build date
# (tools/pnnx/python/setup.py's set_version() is time.strftime("%Y%m%d")).
# Pinned to the last commit touching tools/pnnx or src/layer/* before the
# 20260526 release's upload_time_iso_8601 (2026-05-26T08:12Z).
PNNX_REF: b76824882e68d4a675c96e3f7e70d0104b2ff9c7

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

build_wheels:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
python: ["cp312", "cp313", "cp314", "cp314t"]
name: Build pnnx ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 180

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

steps:
- name: Checkout ncnn ${{ env.PNNX_REF }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Tencent/ncnn
ref: ${{ env.PNNX_REF }}
sparse-checkout: |
tools/pnnx
LICENSE.txt
persist-credentials: false

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

- name: Patch pnnx source
run: git apply python-wheels/patches/pnnx/${{ env.PNNX_VERSION }}/*.patch

# setuptools only auto-discovers LICENSE* next to setup.py; the repo's
# licence file lives three directories up (ncnn covers the whole tree).
- name: Stage the licence
run: cp LICENSE.txt tools/pnnx/python/LICENSE.txt

- uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
package-dir: tools/pnnx/python
output-dir: wheelhouse/
only: ${{ matrix.python }}-manylinux_riscv64
env:
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# pnnx links libtorch at build time (CMakeLists.txt's find_package(Torch
# REQUIRED), probed via `import torch` when no Torch_INSTALL_DIR is set);
# torch has no riscv64 wheel on public PyPI, only on our own registry.
CIBW_BEFORE_BUILD: "pip install --only-binary=:all: torch"
# The pnnx executable is non-PIE; keep its base above vm.mmap_min_addr once auditwheel's
# patchelf prepends a segment, or it dies silently at exec (gotcha 595).
CIBW_ENVIRONMENT: >-
CMAKE_BUILD_PARALLEL_LEVEL=8
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
PIP_ONLY_BINARY=torch
PNNX_VERSION=${{ env.PNNX_VERSION }}
LDFLAGS="-Wl,-Ttext-segment=0x200000"
# setup.py's CMakeBuild shells out to cmake, which re-probes `import
# torch` itself; an isolated build env would not see the torch
# CIBW_BEFORE_BUILD already installed.
CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation"
# TorchVision and onnxruntime are optional (CMakeLists.txt's own
# find_package(... QUIET) / find_library() fall back to "without"
# when absent); neither has a build-ready riscv64 recipe here, so
# this wheel converts plain TorchScript graphs but skips ONNX
# import/export and torchvision-op fusion.
CIBW_TEST_SOURCES: tools/pnnx/python/tests
# The *_pnnx.py modules pnnx generates import numpy unconditionally.
CIBW_TEST_REQUIRES: pytest packaging numpy
CIBW_TEST_ENVIRONMENT: >-
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
PIP_ONLY_BINARY=torch,numpy
CIBW_TEST_COMMAND: python -m pytest tools/pnnx/python/tests -v

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pnnx-${{ env.PNNX_VERSION }}-${{ matrix.python }}-manylinux_riscv64
path: wheelhouse/*.whl
if-no-files-found: error

publish:
name: Publish pnnx ${{ 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: pnnx-${{ matrix.version }}-*-manylinux_riscv64
5 changes: 5 additions & 0 deletions docs/packages/pnnx.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package-name: pnnx
source-code: https://github.com/Tencent/ncnn/tree/master/tools/pnnx
license: BSD-3-Clause
versions:
- version: 20260526
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Thu, 15 Oct 2026 03:21:35 +0000
Subject: [PATCH] cmake: require c++20 for pytorch 2.13+

Upstream already fixed this (nihui/ncnn@61ea75123d0ea71e4b029742664e3d49b7c8eec6,
merged 2026-09-17), but this port pins pnnx at a commit from before that fix
(2026-05-26, matching the 20260526 PyPI release date). The riscv64 torch wheels
this repo publishes are 2.13.0+cpu and 2.14.0+cpu, both >= 2.13, so without this
backport the build fails: ATen's headers at torch>=2.13 require a C++20
compiler, and the unpatched CMakeLists.txt here only ever requests C++17.

Upstream-Status: Backport [https://github.com/Tencent/ncnn/commit/61ea75123d0ea71e4b029742664e3d49b7c8eec6]
---
tools/pnnx/CMakeLists.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/pnnx/CMakeLists.txt b/tools/pnnx/CMakeLists.txt
index e50ab47..210eb73 100644
--- a/tools/pnnx/CMakeLists.txt
+++ b/tools/pnnx/CMakeLists.txt
@@ -59,7 +59,10 @@ if(Torch_VERSION VERSION_LESS "1.8")
message(FATAL_ERROR "pnnx only supports PyTorch >= 1.8")
endif()

-if(Torch_VERSION VERSION_GREATER_EQUAL "2.1")
+if(Torch_VERSION VERSION_GREATER_EQUAL "2.13")
+ # c++20 is required for using torch 2.13+ headers
+ set(CMAKE_CXX_STANDARD 20)
+elseif(Torch_VERSION VERSION_GREATER_EQUAL "2.1")
# c++17 is required for using torch 2.1+ headers
set(CMAKE_CXX_STANDARD 17)
endif()
--
2.43.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Fri, 23 Oct 2026 23:50:00 +0000
Subject: [PATCH] setup: take the wheel version from PNNX_VERSION

setup.py stamps the wheel with the build date (time.strftime("%Y%m%d")),
which is how upstream versions each release: the release workflow builds
on the day it publishes. This port rebuilds an already-released version
from the commit it was cut from, so the build date is the wrong version:
CI run 38676705597 built pnnx-20261015 wheels for the 20260526 release,
and jobs straddling midnight UTC would produce mixed versions that the
publish step rejects. Let the workflow pass the release's version in
PNNX_VERSION, falling back to the build date when it is unset.

Upstream-Status: Inappropriate [riscv64 port rebuilds a past date-stamped release; upstream versions wheels by their build date]
---
tools/pnnx/python/setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/pnnx/python/setup.py b/tools/pnnx/python/setup.py
index bb3ca546..73560f8a 100644
--- a/tools/pnnx/python/setup.py
+++ b/tools/pnnx/python/setup.py
@@ -10,7 +10,7 @@ from setuptools.command.build_ext import build_ext
from setuptools.command.install import install

def set_version():
- pnnx_version = time.strftime("%Y%m%d", time.localtime())
+ pnnx_version = os.environ.get("PNNX_VERSION") or time.strftime("%Y%m%d", time.localtime())
return pnnx_version

# Parse environment variables
--
2.43.0
Loading