- 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
9.9 KiB
EcoArk HarmonyOS Wheel Pipeline
为 EcoArk / HarmonyOS Python 环境 准备的 wheel 重打包与重编译流水线。
用途
- 单 wheel 模式:接收一个
.whl文件,自动检测类型并处理- 纯 Python wheel → 直接重打包为
harmonyos_arm64兼容标签,安装即用 - Native wheel → 交叉编译为 HarmonyOS/arm64 原生 .so 并组装 wheel
- 纯 Python 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 链接中的目标路径。
# 通过 CLI 入口
python3 wheel_pipeline.py --stage-integration
# 或通过 Makefile
make stage-integration
快速开始
单 wheel 模式(向后兼容)
# 纯 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
从源码交叉编译
# 交叉编译 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
清单批量模式
# 读取 packages.txt,逐个拉取源码并生成 wheel
python3 wheel_pipeline.py --manifest packages.txt --output-dir output
# 使用自定义清单
python3 wheel_pipeline.py --manifest my_list.txt
或通过 Makefile:
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
清单模式工作流行为
- 读取
packages.txt(或--manifest指定的文件) - 对每个未注释的条目:
git clone --depth 1 <repo_url>到output/sources/<pkg_name>/- 调用
pipeline/rebuild.rebuild_from_source()生成 wheel
- 收集
output/wheels/下所有.whl文件 - 打包为
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 |
操作步骤:
- 打开 Gitea 仓库 → Actions → 最近成功运行
- 在 workflow 页面底部找到 Artifacts 区域
- 点击
ecoark-wheels-individual进入,选择并下载你需要的单个.whl文件 - 或直接点击
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 步骤才会执行。
配置步骤:
- 在 Gitea 用户设置 → Applications → 创建 Access Token(
reposcope) - 在仓库 → Settings → Secrets → 添加以下两个 secret:
GITEA_TOKEN— 上述 token 值ENABLE_RELEASE_UPLOAD— 设为true激活发布步骤
- 编辑
.gitea/workflows/wheel-pipeline.yaml,取消tags: ['v*']行的注释以启用 tag 触发 - 推送一个 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 环境中安装运行。
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 需要:
- HarmonyOS SDK / OHOS NDK
- 对应架构(arm64)的交叉编译工具链
- Python 头文件与目标 Python 版本匹配
- 所有 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(已排除测试文件 / 构建源码) |
使用方式:
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 clang(aarch64-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 install(Python 3.12+ 需要) |
| meson cross-compilation file | experiments/ohos-aarch64-cross.ini |
以上依赖在构建机上已安装。如需在 CI 中运行,需在 workflow 中先执行
pip install安装构建时依赖。
详细实验记录见 experiments/ 目录。
许可证
本项目许可证见仓库根目录。