Skip to content

Commit cb89cbf

Browse files
committed
fasttext-wheel: add build-fasttext-wheel.yml for riscv64 wheels
Builds fastText's pybind11 extension from facebookresearch/fastText v0.9.2, renamed to the fasttext-wheel PyPI distribution messense publishes it under, with patches fixing a numpy 2.x regression in predict()/scores() and a riscv64-only missing <cstdint> include (backported from an upstream commit that fixed the same failure under GCC 13, before the repo was archived). setup.py has no pyproject.toml declaring pybind11 as a build dependency; its get_pybind_include self-installs pybind11 via `pip install` when missing, but the isolated build venv `python -m build` creates has no pip module, so that self-install fails. Pre-install pybind11/setuptools/numpy (its install_requires) and build without isolation instead.
1 parent 96d5da2 commit cb89cbf

4 files changed

Lines changed: 233 additions & 0 deletions
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# SPDX-FileCopyrightText: 2026 The RISE Project
2+
# SPDX-License-Identifier: MIT
3+
---
4+
# This workflow is based on: https://github.com/messense/fasttext-wheel/blob/master/.github/workflows/Linux.yml
5+
name: Build fasttext-wheel wheels (riscv64)
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
version:
11+
description: 'fasttext-wheel version to build (facebookresearch/fastText git tag, e.g. v0.9.2)'
12+
required: true
13+
default: 'v0.9.2'
14+
pull_request:
15+
paths:
16+
- '.github/workflows/build-fasttext-wheel.yml'
17+
- 'patches/fasttext-wheel/**'
18+
19+
concurrency:
20+
group: ${{ github.workflow }}-${{ inputs.version || 'v0.9.2' }}-${{ github.head_ref || github.run_id }}
21+
cancel-in-progress: true
22+
23+
permissions:
24+
contents: read # to fetch code (actions/checkout)
25+
26+
env:
27+
# `inputs.version` is empty on pull_request events; default to v0.9.2 there.
28+
FASTTEXT_WHEEL_VERSION: ${{ inputs.version || 'v0.9.2' }}
29+
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
30+
31+
jobs:
32+
setup:
33+
uses: $/.github/workflows/_setup.yml
34+
35+
build_wheels:
36+
needs: [setup]
37+
name: Build fasttext-wheel ${{ inputs.version || 'v0.9.2' }} ${{ matrix.python }}-manylinux_riscv64
38+
runs-on: ubuntu-24.04-riscv
39+
strategy:
40+
fail-fast: false
41+
matrix:
42+
# Per-interpreter (not abi3): the pybind11 extension links the version-specific ABI.
43+
python:
44+
- "cp312"
45+
- "cp313"
46+
- "cp314"
47+
- "cp314t"
48+
49+
steps:
50+
# facebookresearch/fastText is the actual source; fasttext-wheel (messense)
51+
# is only a build/publish wrapper around it that renames the distribution.
52+
- name: Checkout fastText ${{ env.FASTTEXT_WHEEL_VERSION }}
53+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
54+
with:
55+
repository: facebookresearch/fastText
56+
ref: ${{ env.FASTTEXT_WHEEL_VERSION }}
57+
persist-credentials: false
58+
59+
- name: Checkout python-wheels
60+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
61+
with:
62+
path: python-wheels
63+
persist-credentials: false
64+
65+
- name: Patch fastText source
66+
run: git apply python-wheels/patches/fasttext-wheel/${{ env.FASTTEXT_WHEEL_VERSION }}/00*.patch
67+
68+
- name: Build wheels
69+
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
70+
with:
71+
output-dir: wheelhouse/
72+
only: ${{ matrix.python }}-manylinux_riscv64
73+
env:
74+
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
75+
# No pyproject.toml, so `python -m build`'s isolated venv has no pip;
76+
# setup.py's get_pybind_include self-installs pybind11 via `pip install`
77+
# there and fails with "No module named pip". Pre-install its
78+
# install_requires (pybind11, setuptools, numpy) and skip isolation.
79+
CIBW_BEFORE_BUILD: pip install pybind11 setuptools numpy
80+
CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation"
81+
# runtests.py (upstream's `python_test.sh` entry point) lives outside the
82+
# installed package, so run the same gen_unit_tests() suite it calls
83+
# directly against the installed fasttext.tests subpackage instead.
84+
CIBW_TEST_COMMAND: >-
85+
python -c "import unittest, sys; from fasttext.tests.test_script import gen_unit_tests; r = unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(gen_unit_tests())); sys.exit(0 if r.wasSuccessful() else 1)"
86+
87+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
88+
with:
89+
name: fasttext-wheel-${{ inputs.version || 'v0.9.2' }}-${{ matrix.python }}-manylinux_riscv64
90+
path: wheelhouse/*.whl
91+
if-no-files-found: error
92+
93+
publish:
94+
name: Publish fasttext-wheel ${{ inputs.version || 'v0.9.2' }}
95+
needs: [setup, build_wheels]
96+
permissions:
97+
contents: write
98+
pull-requests: write
99+
uses: $/.github/workflows/_publish-wheel.yml
100+
with:
101+
artifact-pattern: fasttext-wheel-${{ inputs.version || 'v0.9.2' }}-*-manylinux_riscv64
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Ludovic Henry <git@ludovic.dev>
3+
Date: Tue, 8 Sep 2026 00:00:00 +0000
4+
Subject: [PATCH] setup: rename distribution to fasttext-wheel
5+
6+
Upstream-Status: Inappropriate [downstream redistribution naming, irrelevant to facebookresearch/fastText]
7+
8+
fasttext-wheel is messense's community-maintained PyPI distribution built from
9+
this same source tree, published under a different project name because
10+
`fasttext` on PyPI is a separate, unrelated distribution. messense/fasttext-wheel's
11+
own manylinux.sh build script does this exact rename with a `sed` before
12+
building (`sed -i "s/name='fasttext',/name='fasttext-wheel',/" fastText/setup.py`).
13+
Reapply it here so the built wheel carries the `fasttext-wheel` project name
14+
while the importable `fasttext` package/module path is unchanged.
15+
16+
Signed-off-by: Ludovic Henry <git@ludovic.dev>
17+
---
18+
setup.py | 2 +-
19+
1 file changed, 1 insertion(+), 1 deletion(-)
20+
21+
diff --git a/setup.py b/setup.py
22+
index a1b2c3d..e4f5a6b 100644
23+
--- a/setup.py
24+
+++ b/setup.py
25+
@@ -166,7 +166,7 @@ def _get_readme():
26+
27+
28+
setup(
29+
- name='fasttext',
30+
+ name='fasttext-wheel',
31+
version=__version__,
32+
author='Onur Celebi',
33+
author_email='celebio@fb.com',
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Ludovic Henry <git@ludovic.dev>
3+
Date: Tue, 8 Sep 2026 00:00:00 +0000
4+
Subject: [PATCH] FastText: fix numpy 2.x `copy=False` compatibility
5+
6+
Upstream-Status: To upstream [facebookresearch/fastText archived (read-only) 2024-03-19, blocking new PRs]
7+
8+
`np.array(obj, copy=False)` raised on numpy 1.x only when a copy could not be
9+
avoided but silently allowed one otherwise; numpy 2.0 made `copy=False` a hard
10+
requirement and raises `ValueError: Unable to avoid copy while creating an
11+
array as requested` whenever a copy is actually needed, which
12+
`_FastText.predict`, `_Meter.scores` and `_Meter.precision_recall_curve` hit on
13+
every call. This reproduces off riscv64 (confirmed on macOS/arm64): all four
14+
`test_supervised_predict_*` unit tests fail identically on any platform once
15+
numpy >= 2.0 is installed, which our registry serves as the only riscv64
16+
build. Switching to `np.asarray`, numpy's own documented migration fix,
17+
preserves numpy 1.x behaviour and fixes numpy 2.x.
18+
19+
Signed-off-by: Ludovic Henry <git@ludovic.dev>
20+
---
21+
python/fasttext_module/fasttext/FastText.py | 6 +++---
22+
1 file changed, 3 insertions(+), 3 deletions(-)
23+
24+
diff --git a/python/fasttext_module/fasttext/FastText.py b/python/fasttext_module/fasttext/FastText.py
25+
index 1234567..89abcde 100644
26+
--- a/python/fasttext_module/fasttext/FastText.py
27+
+++ b/python/fasttext_module/fasttext/FastText.py
28+
@@ -43,7 +43,7 @@ class _Meter(object):
29+
else:
30+
y_scores, y_true = ([], ())
31+
32+
- return np.array(y_scores, copy=False), np.array(y_true, copy=False)
33+
+ return np.asarray(y_scores), np.asarray(y_true)
34+
35+
def precision_recall_curve(self, label=None):
36+
"""Return precision/recall curve"""
37+
@@ -58,7 +58,7 @@ class _Meter(object):
38+
else:
39+
precision, recall = ([], ())
40+
41+
- return np.array(precision, copy=False), np.array(recall, copy=False)
42+
+ return np.asarray(precision), np.asarray(recall)
43+
44+
def precision_at_recall(self, recall, label=None):
45+
"""Return precision for a given recall"""
46+
@@ -229,7 +229,7 @@ class _FastText(object):
47+
else:
48+
probs, labels = ([], ())
49+
50+
- return labels, np.array(probs, copy=False)
51+
+ return labels, np.asarray(probs)
52+
53+
def get_input_matrix(self):
54+
"""
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Ludovic Henry <git@ludovic.dev>
3+
Date: Tue, 8 Sep 2026 00:00:00 +0000
4+
Subject: [PATCH] args: fix missing <cstdint> include for uint64_t
5+
6+
Upstream-Status: Backport [https://github.com/facebookresearch/fastText/commit/6c2204ba66776b700095ff73e3e599a908ffd9c3]
7+
8+
args.cc uses `uint64_t` in `getAutotuneModelSize()` without including
9+
`<cstdint>`, relying on it being pulled in transitively by another header.
10+
This happens to hold on the x86_64/aarch64 manylinux images' GCC/libstdc++,
11+
but fails on manylinux_riscv64's (newer, stricter) toolchain with:
12+
13+
src/args.cc:468:3: error: 'uint64_t' was not declared in this scope
14+
src/args.cc:17:1: note: 'uint64_t' is defined in header '<cstdint>';
15+
this is probably fixable by adding '#include <cstdint>'
16+
17+
Upstream hit the same failure under GCC 13 (whose header-dependency
18+
changes stopped transitively exposing <cstdint>, see
19+
https://gcc.gnu.org/gcc-13/porting_to.html#header-dep-changes) and fixed it
20+
in commit 6c2204ba66776b700095ff73e3e599a908ffd9c3 ("fix compile error with
21+
gcc13 #1281 (#1340)", 2023-11-27) by adding the same include, before the
22+
repo was archived (2024-03-19). Backport that one-line fix onto v0.9.2,
23+
whose args.cc still includes `<stdlib.h>` rather than the `<cstdlib>` that
24+
commit's context lines show (an unrelated later modernization), so the
25+
insertion point here is next to the `<stdlib.h>` include instead.
26+
27+
Signed-off-by: Ludovic Henry <git@ludovic.dev>
28+
---
29+
src/args.cc | 1 +
30+
1 file changed, 1 insertion(+)
31+
32+
diff --git a/src/args.cc b/src/args.cc
33+
index 7ac8c2f..b47bd24 100644
34+
--- a/src/args.cc
35+
+++ b/src/args.cc
36+
@@ -9,6 +9,7 @@
37+
#include "args.h"
38+
39+
#include <stdlib.h>
40+
+#include <cstdint>
41+
42+
#include <iostream>
43+
#include <stdexcept>
44+
--
45+
2.50.1 (Apple Git-155)

0 commit comments

Comments
 (0)