Files
ecoarkpywhl/README.md
root 553b83953c
Some checks failed
EcoArk Wheel Pipeline CI / build (push) Failing after 1m41s
feat: add manifest-driven batch rebuild, numpy cross-compilation, and CI pipeline updates
- Add pipeline/manifest.py for packages.txt parsing
- Implement real numpy cross-compilation (rebuild.py) with OHOS NDK + vendored meson
- Extend CLI with --manifest, --build-from-source, --stage-integration modes
- Add recipes/, experiments/, and scripts/ for integration staging and artifact upload
- Update CI workflow with manifest validation, artifact upload, and release publishing
- Update Makefile and README with new targets and documentation
2026-05-13 14:16:24 +08:00

256 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# EcoArk HarmonyOS Wheel Pipeline
**EcoArk / HarmonyOS Python 环境** 准备的 wheel 重打包与重编译流水线。
## 用途
- **单 wheel 模式**:接收一个 `.whl` 文件,自动检测类型并处理
- 纯 Python wheel → 直接重打包为 `harmonyos_arm64` 兼容标签,安装即用
- Native wheel → 交叉编译为 HarmonyOS/arm64 原生 .so 并组装 wheel
- **清单批量模式**:通过 `packages.txt` 清单文件,逐个拉取源码仓库,执行重编,最终打成 zip 包
## 目录结构
```
ecoarkpywhl/
├── wheel_pipeline.py # CLI 入口(最简调用)
├── packages.txt # 待处理项目清单(格式说明见下文)
├── pipeline/
│ ├── cli.py # 参数解析 & 主流程(含 --build-from-source 模式)
│ ├── manifest.py # packages.txt 解析器
│ ├── detect.py # 检测 wheel 类型(纯 Python / native
│ ├── repack.py # 纯 Python wheel 重打包
│ └── rebuild.py # Native wheel 交叉编译 + wheel 组装
├── recipes/
│ └── numpy_integration_manifest.json # numpy 集成暂存配方
├── scripts/
│ ├── stage_integration.py # 集成暂存脚本
│ └── upload_release_assets.py # Gitea Release 上传脚本
├── experiments/ # 交叉编译实验记录
├── Makefile # 常用命令
├── output/ # 输出目录wheels/、sources/
└── README.md
```
## packages.txt — 项目清单
`packages.txt` 定义需要批量重编的包列表,格式:
```
package_name:git_repository_url
```
- 每行一个包,`:` 前为包名,后为 git clone URL
- 空行和以 `#` 开头的行被忽略
- 所有行被注释的 `packages.txt` 是安全的空清单
### 示例
```
# numpy:https://github.com/numpy/numpy.git
# scipy:https://github.com/scipy/scipy.git
```
去掉 `#` 即激活对应包。
## 集成暂存模式Integration Staging
将已编译的 native .so 文件从 wheel 中提取并组织到 `output/integration/<pkg>/` 目录,
附带 README 和 manifest说明各模块在 EcoArk pythonrunner main-so 链接中的目标路径。
```bash
# 通过 CLI 入口
python3 wheel_pipeline.py --stage-integration
# 或通过 Makefile
make stage-integration
```
## 快速开始
### 单 wheel 模式(向后兼容)
```bash
# 纯 Python wheel → 重打包
python3 wheel_pipeline.py some_pure_package.whl
# 指定输出目录
python3 wheel_pipeline.py some_pure_package.whl --output-dir /tmp/wheels
# Native wheel → 触发重编译入口
python3 wheel_pipeline.py some_native_package.whl
```
### 从源码交叉编译
```bash
# 交叉编译 numpy 1.26.4 并产出 HarmonyOS arm64 wheel
python3 wheel_pipeline.py --build-from-source numpy --package-version 1.26.4
# 强制重新编译(跳过缓存)
python3 wheel_pipeline.py --build-from-source numpy --package-version 1.26.4 --rebuild
```
### 清单批量模式
```bash
# 读取 packages.txt逐个拉取源码并生成 wheel
python3 wheel_pipeline.py --manifest packages.txt --output-dir output
# 使用自定义清单
python3 wheel_pipeline.py --manifest my_list.txt
```
或通过 Makefile:
```bash
make repack INPUT=some_package.whl
make rebuild INPUT=some_native_package.whl
make manifest MANIFEST=packages.txt
make build-numpy VERSION=1.26.4
```
## 清单模式工作流行为
1. 读取 `packages.txt`(或 `--manifest` 指定的文件)
2. 对每个未注释的条目:
- `git clone --depth 1 <repo_url>``output/sources/<pkg_name>/`
- 调用 `pipeline/rebuild.rebuild_from_source()` 生成 wheel
3. 收集 `output/wheels/` 下所有 `.whl` 文件
4. 打包为 `output/ecoark-rebuild-output.zip`
### CI 中的产物路径
| 产物 | 路径 | 获取方式 |
|------|------|----------|
| 单个 wheel | `output/wheels/<pkg>-<ver>-cp312-cp312-harmonyos_arm64.whl` | **artifact**: `ecoark-wheels-individual` |
| 汇总 zip 包 | `output/ecoark-rebuild-output.zip` | **artifact**: `ecoark-harmonyos-wheels` |
| Release 附件 | 同上 | **Gitea Release**(需配置 token + tag push |
> **artifact** = 在 Gitea Actions 运行结果页面直接下载(无需配置,即时可用)
> **Release** = 在 Gitea 仓库 Releases 页面长期保留(需配置 token推 tag 时触发)
## Gitea Actions 流水线
当前工作流(`.gitea/workflows/wheel-pipeline.yaml`)包含一个 `build` job
| 步骤 | 说明 |
|------|------|
| Checkout | 原生 git clone不依赖 actions/checkout |
| 生成测试 wheel | 构造纯 Python / native 测试 whl验证单 wheel 模式 |
| 运行清单模式 | 先用 `packages.txt`(空清单 → no-op再用临时清单验证 |
| 上传总 zip artifact | `scripts/upload_artifacts.py``ecoark-harmonyos-wheels`Gitea Runtime API |
| 上传单个 .whl artifacts | `scripts/upload_artifacts.py``ecoark-wheels-individual`Gitea Runtime API |
| 上传到 Gitea Release | `scripts/upload_release_assets.py`(需要 `GITEA_TOKEN` + `ENABLE_RELEASE_UPLOAD` 两个 secrets见下方说明 |
## 从 CI 获取产物
### 方式一:直接下载 artifact零配置即时可用
每次 CI 构建完成后,在 Gitea Actions 运行结果页面可以下载两类 artifact。
artifact 上传使用 `scripts/upload_artifacts.py` 通过 Gitea Actions Runtime API 完成,
**不依赖任何 GitHub-specific action**(如 `actions/upload-artifact`)。
| Artifact 名称 | 内容 | 适用场景 |
|---------------|------|----------|
| `ecoark-harmonyos-wheels` | 所有 wheel 打包成的 **一个 zip** | 一次下载全部 |
| `ecoark-wheels-individual` | 每个 `.whl` 文件**独立存放** | 只需特定一个 wheel |
操作步骤:
1. 打开 Gitea 仓库 → **Actions** → 最近成功运行
2. 在 workflow 页面底部找到 **Artifacts** 区域
3. 点击 `ecoark-wheels-individual` 进入,选择并下载你需要的单个 `.whl` 文件
4. 或直接点击 `ecoark-harmonyos-wheels` 下载汇总 zip
> 不需要 pip不需要安装任何工具浏览器直接下载 `.whl` 后即可用于 HarmonyOS Python 环境的 `pip install some_package.whl`。
### 方式二Gitea Release长期保留需配置
通过推 tag 触发自动发布wheel 会以 Release 附件形式上传,长期可访问。
Release 上传通过 `scripts/upload_release_assets.py` 完成,由 `GITEA_TOKEN` +
`ENABLE_RELEASE_UPLOAD` 两个 secrets 共同控制。
Workflow 中使用 `if: secrets.GITEA_TOKEN != '' && secrets.ENABLE_RELEASE_UPLOAD == 'true'`
条件守卫,只有两个 secret 都**正确设置**后 Release 步骤才会执行。
配置步骤:
1. 在 Gitea 用户设置 → **Applications** → 创建 Access Token`repo` scope
2. 在仓库 → **Settings****Secrets** → 添加以下两个 secret
- `GITEA_TOKEN` — 上述 token 值
- `ENABLE_RELEASE_UPLOAD` — 设为 `true` 激活发布步骤
3. 编辑 `.gitea/workflows/wheel-pipeline.yaml`,取消 `tags: ['v*']` 行的注释以启用 tag 触发
4. 推送一个 tag例如 `git tag v0.1.0 && git push origin v0.1.0`CI 会自动:
- 构建 wheel
- 创建/更新对应 tag 的 Gitea Release
- 将每个 `.whl` 和 zip 包上传为 Release 附件
## 限制
| 场景 | 状态 |
|------|------|
| 纯 Python wheel → 重打包安装 | ✅ 支持 |
| Pure Python → 重新打 tag | ✅ 支持 |
| Native wheel → HarmonyOS 交叉编译 + wheel 产出 | ✅ 已支持numpy 1.26.4 验证通过19 个 AArch64 .so |
| 从源码编译到产出 .whl | ✅ `pipeline/rebuild.py``build_numpy_wheel()` 真实实现 |
| 依赖复杂的 native 包scipy 等) | 🚧 需逐个包适配,底层依赖链未移植 |
| Gitea Release 自动发布 | 🚧 需配 `ENABLE_RELEASE_UPLOAD` + `GITEA_TOKEN` 两个 secrets |
### 纯 Python wheel
纯 Python wheel文件名中包含 `py3-none-any` 等标签,且不含 `.so`/`.pyd` 文件)可以直接重打包为 `harmonyos_arm64` 标签,在 HarmonyOS Python 环境中安装运行。
```bash
python3 wheel_pipeline.py mypackage.whl -o output/
# → output/mypackage-1.0.0-py3-none-harmonyos_arm64.whl
```
### Native wheel — 交叉编译
含 C/C++/Rust 等 native 扩展的 wheel 需要:
1. HarmonyOS SDK / OHOS NDK
2. 对应架构arm64的交叉编译工具链
3. Python 头文件与目标 Python 版本匹配
4. 所有 C 依赖也已移植到 HarmonyOS
**当前已支持:** numpy 1.26.4 全流程交叉编译通过
| 阶段 | 状态 |
|------|------|
| meson setup + compile | ✅ 311 个编译目标全部通过 |
| .so → AArch64 ELF | ✅ 19 个 .so逐个校验 e_machine=0xB7 |
| SOABI 修正 | ✅ `cpython-312-x86_64-linux-gnu``cpython-312-arm64-linux-ohos` |
| wheel 组装 | ✅ 含 19 个 .so + 纯 Python 文件 + metadata |
| 体积 | ✅ ~12.9 MB已排除测试文件 / 构建源码) |
**使用方式:**
```bash
python3 wheel_pipeline.py --build-from-source numpy --package-version 1.26.4
```
**待收口到正式发布的问题:**
- SOABI 标签需与目标运行时完全对齐
- pyconfig.h 需为 aarch64-linux-ohos + musl 重新生成
- 如需 BLAS 性能需交叉编译 OpenBLAS当前 `-Dallow-noblas=true`
### 编译环境需求
执行 `--build-from-source` 交叉编译需要以下环境(当前构建机器已具备):
| 依赖 | 说明 |
|------|------|
| OHOS NDK clangaarch64-linux-ohos | `/home/program/tools/command-line-tools/sdk/default/openharmony/native/llvm` |
| Cython ≥0.29.34 | pip install |
| meson-python ≥0.15.0 | pip install |
| ninja | pip install |
| setuptools | pip installPython 3.12+ 需要) |
| meson cross-compilation file | `experiments/ohos-aarch64-cross.ini` |
> 以上依赖在构建机上已安装。如需在 CI 中运行,需在 workflow 中先执行 `pip install` 安装构建时依赖。
详细实验记录见 `experiments/` 目录。
## 许可证
本项目许可证见仓库根目录。