Skip to content

Build libpython Android Wheels #2

Build libpython Android Wheels

Build libpython Android Wheels #2

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