Skip to content

Commit fc68073

Browse files
authored
mecab: add build-mecab.yml for riscv64 wheels (#1390)
* **Package**: `mecab` * **Version**: `0.996.13` * **Source**: https://github.com/shogo82148/mecab (monorepo, `mecab/python`) * **Docs**: https://shogo82148.github.io/mecab/ Compiles a SWIG binding over shogo82148's actively-maintained MeCab fork into a per-interpreter wheel. Upstream publishes no riscv64 wheel. Mirrors [upstream's `test-linux-python.yml`](https://github.com/shogo82148/mecab/blob/v0.996.13/.github/workflows/test-linux-python.yml) for building and installing libmecab; upstream's own release job drives a similar recipe in `.github/build-wheel-linux.sh`. **Differs from upstream** - Installs `gettext-devel` before `autogen.sh` - `configure.ac`'s `AM_ICONV` needs its m4 macros, absent from the manylinux image. **Testing** - Installs `unidic-lite` and tokenizes a sample sentence, mirroring the sibling `mecab-python3` port's approach - upstream's own `test.py` needs a built `mecab-ipadic`, heavier than a pure-Python dictionary. **License**: OK **Patches** - `0001-Add-LICENSE-matching-setuptools-default-license_files-glob.patch` - To upstream, blocked (this port may only touch riseproject-dev/python-wheels). Without it, the wheel's `dist-info/licenses/` carries only `COPYING`/`AUTHORS`, not the BSD text the package declares itself under - reproduces off riscv64 too. Built on cp312/cp313/cp314/cp314t manylinux_riscv64 in CI; all 4 wheels built and the tokenization test passed.
1 parent 3a34603 commit fc68073

2 files changed

Lines changed: 172 additions & 0 deletions

File tree

.github/workflows/build-mecab.yml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# SPDX-FileCopyrightText: 2026 The RISE Project
2+
# SPDX-License-Identifier: MIT
3+
---
4+
# This workflow is based on: https://github.com/shogo82148/mecab/blob/v0.996.13/.github/workflows/test-linux-python.yml
5+
name: Build mecab wheels (riscv64)
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
version:
11+
description: 'mecab version to build (git tag without leading v, e.g. 0.996.13)'
12+
required: true
13+
default: '0.996.13'
14+
pull_request:
15+
paths:
16+
- '.github/workflows/build-mecab.yml'
17+
- 'patches/mecab/**'
18+
19+
concurrency:
20+
group: ${{ github.workflow }}-${{ inputs.version || '0.996.13' }}-${{ 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 0.996.13 there.
28+
MECAB_VERSION: ${{ inputs.version || '0.996.13' }}
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 mecab ${{ inputs.version || '0.996.13' }} ${{ matrix.python }}-manylinux_riscv64
38+
runs-on: ubuntu-24.04-riscv
39+
timeout-minutes: 60
40+
strategy:
41+
fail-fast: false
42+
matrix:
43+
# Upstream builds no cp314t Linux wheel yet; the extension declares no
44+
# free-threading support either way, so cp314t just re-enables the GIL
45+
# on import (CLAUDE.md gotcha 127) rather than failing.
46+
python: ["cp312", "cp313", "cp314", "cp314t"]
47+
48+
steps:
49+
- name: Checkout mecab ${{ env.MECAB_VERSION }}
50+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
51+
with:
52+
repository: shogo82148/mecab
53+
ref: v${{ env.MECAB_VERSION }}
54+
persist-credentials: false
55+
56+
- name: Checkout python-wheels
57+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
58+
with:
59+
path: python-wheels
60+
persist-credentials: false
61+
62+
- name: Patch mecab source
63+
run: git apply python-wheels/patches/mecab/${{ env.MECAB_VERSION }}/*.patch
64+
65+
- uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
66+
with:
67+
package-dir: mecab/python
68+
env:
69+
CIBW_ARCHS: riscv64
70+
CIBW_BUILD: ${{ matrix.python }}-manylinux_riscv64
71+
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
72+
# setup.py always links a system libmecab via mecab-config; this repo
73+
# is the MeCab C++ core and the Python binding in one monorepo, so
74+
# build the core (mecab/mecab) from the same checkout/tag the binding
75+
# comes from. configure.ac has no committed configure script (needs
76+
# autogen.sh/autoreconf) and its AM_ICONV macro needs gettext's m4
77+
# files, absent from the manylinux image.
78+
CIBW_BEFORE_ALL_LINUX: |
79+
set -eux
80+
dnf install -y gettext-devel
81+
cd {project}/mecab
82+
./autogen.sh
83+
./configure --enable-utf8-only
84+
make -j"$(nproc)"
85+
make install
86+
ldconfig
87+
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
88+
# Mirrors the sibling mecab-python3 port: install unidic-lite (a small
89+
# pure-Python dictionary package) so the test exercises real
90+
# tokenization instead of failing on "no dictionaries found".
91+
CIBW_TEST_REQUIRES: unidic-lite
92+
CIBW_TEST_COMMAND: >-
93+
python -c "import MeCab, unidic_lite; t = MeCab.Tagger('-d ' + unidic_lite.DICDIR); r = t.parse('太郎はこの本を女性に渡した。'); assert 'EOS' in r and '太郎' in r, r; print(r)"
94+
95+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
96+
with:
97+
name: mecab-${{ env.MECAB_VERSION }}-${{ matrix.python }}-manylinux_riscv64
98+
path: ./wheelhouse/*.whl
99+
if-no-files-found: error
100+
101+
publish:
102+
name: Publish mecab ${{ inputs.version || '0.996.13' }}
103+
needs: [setup, build_wheels]
104+
permissions:
105+
contents: write
106+
pull-requests: write
107+
uses: $/.github/workflows/_publish-wheel.yml
108+
with:
109+
artifact-pattern: mecab-${{ inputs.version || '0.996.13' }}-*-manylinux_riscv64
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
From 3c987e4e01cd9dd9a0c57fee502aea58b6e512a9 Mon Sep 17 00:00:00 2001
2+
From: Ludovic Henry <git@ludovic.dev>
3+
Date: Mon, 7 Sep 2026 17:11:24 +0200
4+
Subject: [PATCH] Add LICENSE matching setuptools' default license_files glob
5+
6+
setuptools only auto-discovers license files at the package root that
7+
match LICEN[CS]E*/COPYING*/NOTICE*/AUTHORS*. The mecab/python binding
8+
declares itself under "GPL-2.0-only OR LGPL-2.1-only OR BSD-3-Clause"
9+
but ships no license text of its own -- release.yml's script-dist step
10+
copies the parent mecab/ tree's COPYING, BSD, GPL, LGPL and AUTHORS
11+
files alongside python/* before building the sdist, yet only COPYING*
12+
and AUTHORS* match setuptools' glob, so BSD/GPL/LGPL never reach the
13+
wheel's dist-info/licenses/ -- and building straight from this git
14+
checkout skips that script-dist copy entirely.
15+
16+
Add a LICENSE file duplicating the BSD text (the license this package
17+
declares itself under) so it is picked up by the default glob with no
18+
setup.py/pyproject.toml change, mirroring how the sibling mecab-python3
19+
port resolves the same gap.
20+
21+
Upstream-Status: To upstream [blocked: this port may only touch riseproject-dev/python-wheels]
22+
---
23+
mecab/python/LICENSE | 29 +++++++++++++++++++++++++++++
24+
1 file changed, 29 insertions(+)
25+
create mode 100644 mecab/python/LICENSE
26+
27+
diff --git a/mecab/python/LICENSE b/mecab/python/LICENSE
28+
new file mode 100644
29+
index 0000000..9ae6ded
30+
--- /dev/null
31+
+++ b/mecab/python/LICENSE
32+
@@ -0,0 +1,29 @@
33+
+Copyright (c) 2001-2008, Taku Kudo
34+
+Copyright (c) 2004-2008, Nippon Telegraph and Telephone Corporation
35+
+All rights reserved.
36+
+
37+
+Redistribution and use in source and binary forms, with or without modification, are
38+
+permitted provided that the following conditions are met:
39+
+
40+
+ * Redistributions of source code must retain the above
41+
+ copyright notice, this list of conditions and the
42+
+ following disclaimer.
43+
+
44+
+ * Redistributions in binary form must reproduce the above
45+
+ copyright notice, this list of conditions and the
46+
+ following disclaimer in the documentation and/or other
47+
+ materials provided with the distribution.
48+
+
49+
+ * Neither the name of the Nippon Telegraph and Telegraph Corporation
50+
+ nor the names of its contributors may be used to endorse or
51+
+ promote products derived from this software without specific
52+
+ prior written permission.
53+
+
54+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
55+
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
56+
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
57+
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
58+
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59+
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
60+
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61+
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62+
--
63+
2.50.1 (Apple Git-155)

0 commit comments

Comments
 (0)