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
101 changes: 101 additions & 0 deletions .github/workflows/build-fasttext-wheel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on: https://github.com/messense/fasttext-wheel/blob/master/.github/workflows/Linux.yml
name: Build fasttext-wheel wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'fasttext-wheel version to build (facebookresearch/fastText git tag, e.g. v0.9.2)'
required: true
default: 'v0.9.2'
pull_request:
paths:
- '.github/workflows/build-fasttext-wheel.yml'
- 'patches/fasttext-wheel/**'

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

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

env:
# `inputs.version` is empty on pull_request events; default to v0.9.2 there.
FASTTEXT_WHEEL_VERSION: ${{ inputs.version || 'v0.9.2' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64

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

build_wheels:
needs: [setup]
name: Build fasttext-wheel ${{ inputs.version || 'v0.9.2' }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
strategy:
fail-fast: false
matrix:
# Per-interpreter (not abi3): the pybind11 extension links the version-specific ABI.
python:
- "cp312"
- "cp313"
- "cp314"
- "cp314t"

steps:
# facebookresearch/fastText is the actual source; fasttext-wheel (messense)
# is only a build/publish wrapper around it that renames the distribution.
- name: Checkout fastText ${{ env.FASTTEXT_WHEEL_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: facebookresearch/fastText
ref: ${{ env.FASTTEXT_WHEEL_VERSION }}
persist-credentials: false

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

- name: Patch fastText source
run: git apply python-wheels/patches/fasttext-wheel/${{ env.FASTTEXT_WHEEL_VERSION }}/00*.patch

- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
output-dir: wheelhouse/
only: ${{ matrix.python }}-manylinux_riscv64
env:
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# No pyproject.toml, so `python -m build`'s isolated venv has no pip;
# setup.py's get_pybind_include self-installs pybind11 via `pip install`
# there and fails with "No module named pip". Pre-install its
# install_requires (pybind11, setuptools, numpy) and skip isolation.
CIBW_BEFORE_BUILD: pip install pybind11 setuptools numpy
CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation"
# runtests.py (upstream's `python_test.sh` entry point) lives outside the
# installed package, so run the same gen_unit_tests() suite it calls
# directly against the installed fasttext.tests subpackage instead.
CIBW_TEST_COMMAND: >-
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)"

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: fasttext-wheel-${{ inputs.version || 'v0.9.2' }}-${{ matrix.python }}-manylinux_riscv64
path: wheelhouse/*.whl
if-no-files-found: error

publish:
name: Publish fasttext-wheel ${{ inputs.version || 'v0.9.2' }}
needs: [setup, build_wheels]
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
with:
artifact-pattern: fasttext-wheel-${{ inputs.version || 'v0.9.2' }}-*-manylinux_riscv64
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Tue, 8 Sep 2026 00:00:00 +0000
Subject: [PATCH] setup: rename distribution to fasttext-wheel

Upstream-Status: Inappropriate [downstream redistribution naming, irrelevant to facebookresearch/fastText]

fasttext-wheel is messense's community-maintained PyPI distribution built from
this same source tree, published under a different project name because
`fasttext` on PyPI is a separate, unrelated distribution. messense/fasttext-wheel's
own manylinux.sh build script does this exact rename with a `sed` before
building (`sed -i "s/name='fasttext',/name='fasttext-wheel',/" fastText/setup.py`).
Reapply it here so the built wheel carries the `fasttext-wheel` project name
while the importable `fasttext` package/module path is unchanged.

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

diff --git a/setup.py b/setup.py
index a1b2c3d..e4f5a6b 100644
--- a/setup.py
+++ b/setup.py
@@ -166,7 +166,7 @@ def _get_readme():


setup(
- name='fasttext',
+ name='fasttext-wheel',
version=__version__,
author='Onur Celebi',
author_email='celebio@fb.com',
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Tue, 8 Sep 2026 00:00:00 +0000
Subject: [PATCH] FastText: fix numpy 2.x `copy=False` compatibility

Upstream-Status: To upstream [facebookresearch/fastText archived (read-only) 2024-03-19, blocking new PRs]

`np.array(obj, copy=False)` raised on numpy 1.x only when a copy could not be
avoided but silently allowed one otherwise; numpy 2.0 made `copy=False` a hard
requirement and raises `ValueError: Unable to avoid copy while creating an
array as requested` whenever a copy is actually needed, which
`_FastText.predict`, `_Meter.scores` and `_Meter.precision_recall_curve` hit on
every call. This reproduces off riscv64 (confirmed on macOS/arm64): all four
`test_supervised_predict_*` unit tests fail identically on any platform once
numpy >= 2.0 is installed, which our registry serves as the only riscv64
build. Switching to `np.asarray`, numpy's own documented migration fix,
preserves numpy 1.x behaviour and fixes numpy 2.x.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
python/fasttext_module/fasttext/FastText.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/python/fasttext_module/fasttext/FastText.py b/python/fasttext_module/fasttext/FastText.py
index 1234567..89abcde 100644
--- a/python/fasttext_module/fasttext/FastText.py
+++ b/python/fasttext_module/fasttext/FastText.py
@@ -43,7 +43,7 @@ class _Meter(object):
else:
y_scores, y_true = ([], ())

- return np.array(y_scores, copy=False), np.array(y_true, copy=False)
+ return np.asarray(y_scores), np.asarray(y_true)

def precision_recall_curve(self, label=None):
"""Return precision/recall curve"""
@@ -58,7 +58,7 @@ class _Meter(object):
else:
precision, recall = ([], ())

- return np.array(precision, copy=False), np.array(recall, copy=False)
+ return np.asarray(precision), np.asarray(recall)

def precision_at_recall(self, recall, label=None):
"""Return precision for a given recall"""
@@ -229,7 +229,7 @@ class _FastText(object):
else:
probs, labels = ([], ())

- return labels, np.array(probs, copy=False)
+ return labels, np.asarray(probs)

def get_input_matrix(self):
"""
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Tue, 8 Sep 2026 00:00:00 +0000
Subject: [PATCH] args: fix missing <cstdint> include for uint64_t

Upstream-Status: Backport [https://github.com/facebookresearch/fastText/commit/6c2204ba66776b700095ff73e3e599a908ffd9c3]

args.cc uses `uint64_t` in `getAutotuneModelSize()` without including
`<cstdint>`, relying on it being pulled in transitively by another header.
This happens to hold on the x86_64/aarch64 manylinux images' GCC/libstdc++,
but fails on manylinux_riscv64's (newer, stricter) toolchain with:

src/args.cc:468:3: error: 'uint64_t' was not declared in this scope
src/args.cc:17:1: note: 'uint64_t' is defined in header '<cstdint>';
this is probably fixable by adding '#include <cstdint>'

Upstream hit the same failure under GCC 13 (whose header-dependency
changes stopped transitively exposing <cstdint>, see
https://gcc.gnu.org/gcc-13/porting_to.html#header-dep-changes) and fixed it
in commit 6c2204ba66776b700095ff73e3e599a908ffd9c3 ("fix compile error with
gcc13 #1281 (#1340)", 2023-11-27) by adding the same include, before the
repo was archived (2024-03-19). Backport that one-line fix onto v0.9.2,
whose args.cc still includes `<stdlib.h>` rather than the `<cstdlib>` that
commit's context lines show (an unrelated later modernization), so the
insertion point here is next to the `<stdlib.h>` include instead.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
src/args.cc | 1 +
1 file changed, 1 insertion(+)

diff --git a/src/args.cc b/src/args.cc
index 7ac8c2f..b47bd24 100644
--- a/src/args.cc
+++ b/src/args.cc
@@ -9,6 +9,7 @@
#include "args.h"

#include <stdlib.h>
+#include <cstdint>

#include <iostream>
#include <stdexcept>
--
2.50.1 (Apple Git-155)