Skip to content
Open
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
157 changes: 157 additions & 0 deletions .github/workflows/build-tilelang.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on upstream's own wheel build/publish setup:
# https://github.com/tile-ai/tilelang/blob/v0.1.13/.github/workflows/dist.yml
name: Build tilelang wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'tilelang version to build (git tag without leading v, e.g. 0.1.13)'
required: true
default: '0.1.13'
pull_request:
paths:
- '.github/workflows/build-tilelang.yml'

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

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

env:
TILELANG_VERSION: ${{ inputs.version || '0.1.13' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64

jobs:
setup:
uses: $/.github/workflows/_setup.yml

build_sdist:
needs: [setup]
# The sdist just packages the source tree plus the vendored TVM/CUTLASS/
# composable_kernel submodules (see pyproject's [tool.scikit-build.sdist]);
# build it once on x86 instead of burning a scarce riscv runner (gotcha 4).
name: Build tilelang ${{ inputs.version || '0.1.13' }} sdist
runs-on: ubuntu-latest
timeout-minutes: 30
env:
# Otherwise the sdist's version carries a dirty git-hash suffix that the
# later wheel build (no .git in the extracted sdist) can never reproduce.
NO_VERSION_LABEL: 'ON'
outputs:
sdist_name: ${{ steps.sdist.outputs.sdist_name }}
steps:
- name: Checkout tilelang v${{ env.TILELANG_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: tile-ai/tilelang
ref: v${{ env.TILELANG_VERSION }}
submodules: recursive
fetch-depth: 1
persist-credentials: false

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

- name: Patch tilelang source
run: |
git apply python-wheels/patches/tilelang/${{ env.TILELANG_VERSION }}/00*.patch

- name: Setup Python and uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: '3.12'
activate-environment: true
enable-cache: false

- name: Build sdist
id: sdist
run: |
uv run --no-project --with=build -m -- build --sdist --outdir=dist
sdists=(dist/*.tar.gz)
echo "sdist_name=$(basename "${sdists[0]}")" >> "$GITHUB_OUTPUT"

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: tilelang-${{ env.TILELANG_VERSION }}-sdist
path: dist/*.tar.gz
if-no-files-found: error

build_wheels:
needs: [setup, build_sdist]
name: Build tilelang ${{ inputs.version || '0.1.13' }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 600
strategy:
fail-fast: false
matrix:
# pyproject sets wheel.py-api = "cp38" (upstream ships a single
# cp38-abi3 wheel, no free-threaded build - dist.yml: "let user to
# build from source for now"), so one build covers every supported
# interpreter. Build with cp312: tilelang hard-depends on
# apache-tvm-ffi at runtime, whose own riscv64 wheel is cp312-abi3+,
# so nothing below cp312 could import the result on riscv64 anyway.
python: [cp312]
steps:
- name: Download sdist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: tilelang-${{ env.TILELANG_VERSION }}-sdist
path: dist/

- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
package-dir: dist/${{ needs.build_sdist.outputs.sdist_name }}
env:
CIBW_BUILD: ${{ matrix.python }}-*
CIBW_ARCHS: riscv64
CIBW_SKIP: '*-musllinux_*'
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
CIBW_BUILD_FRONTEND: build
# Upstream's own [tool.cibuildwheel.linux] always sets USE_CUDA=ON
# and USE_ROCM=ON and installs a CUDA toolkit via dnf; override for
# the CPU-only build upstream documents but never ships itself
# (docs/get_started/Installation.md: "USE_CUDA: ... set to OFF to
# build a CPU version", "USE_LLVM: enable LLVM backend for CPU
# codegen"). USE_LLVM=ON auto-detects llvm-config from PATH.
CIBW_BEFORE_ALL_LINUX: dnf -y --enablerepo=crb install llvm-devel
CIBW_ENVIRONMENT_LINUX: >-
USE_CUDA=OFF USE_ROCM=OFF USE_LLVM=ON
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
UV_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
UV_INDEX_STRATEGY=unsafe-best-match
CIBW_TEST_ENVIRONMENT_LINUX: >-
PIP_ONLY_BINARY=:all:
UV_ONLY_BINARY=:all:
# Mirror upstream's own repair-wheel-command, dropping the
# CUDA-only excludes (no libcuda/CUDA toolkit in a CPU-only build).
# libtvm_ffi.so/libz3.so* come from the apache-tvm-ffi/z3-solver
# dependency wheels, not bundled here.
CIBW_REPAIR_WHEEL_COMMAND_LINUX: >-
auditwheel -v repair --exclude libtvm_ffi.so --exclude 'libz3.so*' -w {dest_dir} {wheel}
CIBW_TEST_COMMAND: 'python -c "import tilelang; print(tilelang.__version__)"'

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

publish:
name: Publish tilelang ${{ inputs.version || '0.1.13' }}
needs: [setup, build_wheels]
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
with:
artifact-pattern: tilelang-${{ inputs.version || '0.1.13' }}-*-manylinux_riscv64
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
From 0e6a6a1f4c1a5cd3c8c3e0b1a0f6b6a6d1e0c0a1 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Thu, 10 Sep 2026 14:43:22 +0000
Subject: [PATCH] exclude torch-c-dlpack-ext from the riscv64 dependency set

Upstream-Status: Inappropriate [riscv64 CI-specific: drops a torch C-extension accelerator with no riscv64 wheel anywhere; not something upstream would want for its general audience]

torch-c-dlpack-ext is an unconditional dependency for python_version <
'3.14', but it ships no riscv64 wheel on PyPI or pypi.riseproject.dev, so
`pip install` of the riscv64 wheel fails to resolve on any interpreter
below 3.14. Upstream's own comment above the dependency says it is a soft
accelerator, not a hard requirement: "Without it, TVM FFI may require JIT
compilation on first import." Gate it off on riscv64 with an extra
platform_machine marker so the rest of the dependency set (all of which do
have riscv64 wheels) resolves normally; every other architecture keeps the
exact same dependency.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index 1111111..2222222 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,7 +30,7 @@ dependencies = [
"apache-tvm-ffi>=0.1.11,<0.1.13",
# torch-c-dlpack-ext provides prebuilt torch extensions.
# Without it, TVM FFI may require JIT compilation on first import.
- "torch-c-dlpack-ext; python_version < '3.14'",
+ "torch-c-dlpack-ext; python_version < '3.14' and platform_machine != 'riscv64'",
"cloudpickle",
"ml-dtypes",
"numpy>=1.23.5",
--
2.50.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
From b37abc7edf7b3349a341180d2ebaaba0ac45e9b9 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Thu, 10 Sep 2026 20:00:00 +0200
Subject: [PATCH] cap the cython build requirement below 3.3

Upstream-Status: To upstream [not submitted: cannot open issues/PRs against tile-ai/tilelang from this environment; cross-platform bug, not riscv64-specific]

build-system.requires pins "cython>=3.1.0" with no upper bound. Cython
3.3.0 (Cython/Utility/ModuleSetupCode.c) added a hard #error when a
Limited API build targets below Python 3.9:

#if Py_LIMITED_API < 0x03090000
#error "Cython 3.3 requires the Python Limited API version to be
3.9 or greater."

tilelang's own scikit-build config sets `wheel.py-api = "cp38"`, so
SKBUILD_SABI_VERSION is 3.8 and tilelang_cython_wrapper's generated
.cpp fails to compile once an unbounded resolve picks up Cython
3.3.0 (the current latest release on PyPI). This is not
architecture-specific: any build resolving cython>=3.3 against the
existing cp38 Limited API target breaks the same way. Cap it below
3.3 so the resolver keeps picking a Cython release that predates this
check, matching the Cython version tilelang's own CI has actually
been built and tested against.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index dbb451e..1edf272 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -74,7 +74,7 @@ torch = [

[build-system]
requires = [
- "cython>=3.1.0",
+ "cython>=3.1.0,<3.3",
"scikit-build-core",
"z3-solver>=4.13.0,<4.15.5",
# Not for auditwheel, explicitly add patchelf for repairing libz3.so.
--
2.50.1 (Apple Git-155)