Build libpython Android Wheels #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build libpython Android Wheels | |
| on: | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| name: Build | |
| runs-on: macos-15 | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13.8' | |
| - name: setup Android NDK | |
| id: setup-ndk | |
| uses: nttld/setup-ndk@v1 | |
| with: | |
| ndk-version: r27c | |
| - name: clone ksproject | |
| run: git clone --depth 1 --branch gradle_support https://github.com/kivy-school/ksproject ksproject | |
| - name: build libpython wheels | |
| env: | |
| ANDROID_HOME: /Users/runner/Library/Android/sdk | |
| ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }} | |
| KIVYSCHOOL_PREBUILT_DISABLE: '1' | |
| run: | | |
| mkdir -p dist/libpython | |
| python ksproject/scripts/build_python_target.py \ | |
| --ndk "$ANDROID_NDK_ROOT" \ | |
| --out-dir dist/libpython | |
| - name: inject SSL libs into wheels | |
| run: | | |
| python3 - <<'PYEOF' | |
| import zipfile, re | |
| from pathlib import Path | |
| work_dir = Path("ksproject/.build-target") | |
| wheel_dir = Path("dist/libpython") | |
| abi_map = {"arm64_v8a": "arm64-v8a", "x86_64": "x86_64"} | |
| for whl_path in sorted(wheel_dir.rglob("*.whl")): | |
| m = re.search(r"android_\d+_(\w+)$", whl_path.stem) | |
| if not m: | |
| continue | |
| abi_tag = m.group(1) | |
| abi = abi_map.get(abi_tag, abi_tag) | |
| ssl_so = next(work_dir.rglob(f"*{abi}*/lib/libssl_python.so"), None) | |
| cryp_so = next(work_dir.rglob(f"*{abi}*/lib/libcrypto_python.so"), None) | |
| extra = [p for p in (ssl_so, cryp_so) if p] | |
| if not extra: | |
| print(f"WARNING: no SSL .so found for {abi}, skipping") | |
| continue | |
| print(f"Patching {whl_path.name}: adding {[p.name for p in extra]}") | |
| tmp = whl_path.with_name(whl_path.name + ".tmp") | |
| with zipfile.ZipFile(whl_path, "r") as zin, \ | |
| zipfile.ZipFile(tmp, "w", zipfile.ZIP_DEFLATED, compresslevel=9) as zout: | |
| for item in zin.infolist(): | |
| zout.writestr(item, zin.read(item.filename)) | |
| for lib in extra: | |
| arcname = f"libpython/prefix/{abi}/lib/{lib.name}" | |
| print(f" + {arcname}") | |
| zout.write(str(lib), arcname) | |
| whl_path.unlink() | |
| tmp.rename(whl_path) | |
| PYEOF | |
| - run: find dist/libpython -name "*.whl" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: libpython-android-wheels | |
| path: dist/libpython/**/*.whl | |
| anaconda_upload: | |
| name: Upload to Anaconda | |
| needs: [build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: libpython-android-wheels | |
| path: wheels/ | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13.8' | |
| - name: install anaconda client | |
| run: pip install anaconda-client | |
| - name: publish to anaconda | |
| env: | |
| ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }} | |
| run: | | |
| find wheels -name "*.whl" | while read FILE; do | |
| anaconda upload --force "$FILE" --summary "libpython Android wheel" | |
| done |