Android build now works end-to-end: JDK pin, p4a venv fix, kivy recipe
- build.sh: pin JAVA_HOME to java-17-openjdk for the build only (Gradle 8.14.3 can't parse this machine's default java-26 class files). - build.sh: delete p4a's internal pymodules venv before every run — it re-runs `python -m venv` without --clear on each build and corrupts its own pip (confirmed two dist-info dirs coexisting). - CLAUDE.md / android/README.md: document all three build-tooling fixes from this session (kivy python_depends, p4a venv corruption, JDK pin) so a future session/rebuild doesn't have to re-diagnose them. Confirmed: full BUILD SUCCESSFUL Gradle run, APK produced at android/bin/eventtracker-0.1-arm64-v8a-debug.apk. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
cd9f9456e9
commit
5e7cb1ced9
3 changed files with 100 additions and 9 deletions
55
CLAUDE.md
55
CLAUDE.md
|
|
@ -9,14 +9,21 @@ Context for future Claude sessions working on this repo.
|
||||||
relocatable data path, taskbar icon, "Time Since" column.
|
relocatable data path, taskbar icon, "Time Since" column.
|
||||||
- Repo is pushed to `repo.tas-tech.net/tas-tech.net/event-tracker`
|
- Repo is pushed to `repo.tas-tech.net/tas-tech.net/event-tracker`
|
||||||
(private — will go public once there's a tagged release).
|
(private — will go public once there's a tagged release).
|
||||||
- Android build (`android/`) is in progress. Native recipe compilation
|
- **Android build (`android/`) works end-to-end** — `./build.sh android
|
||||||
(SDL2, OpenSSL, sqlite3, pyjnius, hostpython3) succeeds. The last
|
debug` produces `android/bin/eventtracker-0.1-arm64-v8a-debug.apk`.
|
||||||
blocker was a p4a upstream bug in the `kivy` recipe's `python_depends`
|
Confirmed via a full `BUILD SUCCESSFUL` Gradle run, not just "recipes
|
||||||
— see "Android companion — design decisions" below for the fix
|
compiled." Three real, distinct bugs had to be fixed to get here (all
|
||||||
(`android/p4a-recipes/kivy`). Not yet confirmed working end-to-end —
|
now baked into `build.sh`/`buildozer.spec`, nothing left to redo):
|
||||||
next session should check whether the user has run
|
1. p4a's `kivy` recipe pulling in unused `requests`/`charset-normalizer`
|
||||||
`./build.sh android debug` since that fix landed and, if not, ask for
|
that couldn't actually install — `android/p4a-recipes/kivy`.
|
||||||
the latest log tail before touching anything else Android-related.
|
2. p4a's own internal pymodules venv corrupting itself on every
|
||||||
|
re-build — `build.sh` deletes it before each run.
|
||||||
|
3. Gradle's build-script compiler rejecting this machine's default JDK
|
||||||
|
(java-26) — `build.sh` pins `JAVA_HOME` to `java-17-openjdk` for
|
||||||
|
just this build.
|
||||||
|
See "Android companion — design decisions" below for the full
|
||||||
|
root-cause writeup on each. Not yet installed/tested on an actual
|
||||||
|
phone — that's the next real checkpoint, not another build fix.
|
||||||
- **Outstanding, agreed but not implemented**: split `config.json` into
|
- **Outstanding, agreed but not implemented**: split `config.json` into
|
||||||
two files — event list (safe to sync between machines) vs. data file
|
two files — event list (safe to sync between machines) vs. data file
|
||||||
path (must stay local per-device, same principle as the Android app's
|
path (must stay local per-device, same principle as the Android app's
|
||||||
|
|
@ -212,6 +219,38 @@ android/
|
||||||
mode than the one it fixed. Don't reintroduce it as a quick fix for a
|
mode than the one it fixed. Don't reintroduce it as a quick fix for a
|
||||||
future build error without checking whether it's actually leaking
|
future build error without checking whether it's actually leaking
|
||||||
something first.
|
something first.
|
||||||
|
- **`build.sh` deletes p4a's internal pymodules venv before every run** —
|
||||||
|
separate from `android/build/venv` (ours, for buildozer/cython) and
|
||||||
|
separate from the `p4a-recipes` bug above. p4a creates its own
|
||||||
|
throwaway venv per arch at
|
||||||
|
`.buildozer/android/platform/build-<arch>/build/venv` to pip-install
|
||||||
|
pure-Python deps, and unconditionally re-runs `python -m venv venv`
|
||||||
|
over it on *every* build without `--clear`. First build: ensurepip
|
||||||
|
bootstraps whatever pip version shipped with this system's Python
|
||||||
|
(25.3). p4a then runs `pip install -U pip` inside it (26.2.1). Next
|
||||||
|
build: `python -m venv` re-invokes ensurepip, which unpacks its older
|
||||||
|
bundled pip back over the newer one without removing the newer
|
||||||
|
version's now-orphaned files — confirmed by hand, both
|
||||||
|
`pip-25.3.dist-info` and `pip-26.2.1.dist-info` present in the same
|
||||||
|
site-packages afterward, producing exactly the kind of mismatched-file
|
||||||
|
crash you'd expect (`ImportError: cannot import name
|
||||||
|
'BuildDependencyInstallError' from 'pip._internal.exceptions'` — a
|
||||||
|
newer file expecting a class only the newer exceptions.py defines).
|
||||||
|
`build.sh` just deletes that venv before every buildozer invocation;
|
||||||
|
costs a few seconds (pip + Cython reinstall in a tiny throwaway venv),
|
||||||
|
leaves the expensive SDK/NDK/recipe build state untouched.
|
||||||
|
- **`build.sh` pins `JAVA_HOME` to `java-17-openjdk` for the build only**
|
||||||
|
— this machine's `archlinux-java` default is java-26 (rolling
|
||||||
|
release), and Gradle 8.14.3 (pulled in by this p4a version) ships a
|
||||||
|
Groovy/ASM build-script compiler that can't parse that new a class
|
||||||
|
file: `BUG! ... Unsupported class file major version 70`. java-17 is
|
||||||
|
installed alongside the default (`archlinux-java status` lists both);
|
||||||
|
`JAVA_HOME_FOR_BUILD` at the top of `build.sh` points at it without
|
||||||
|
touching the system-wide default JDK used by everything else. If this
|
||||||
|
ever needs to change (different machine, JDK package renamed), that's
|
||||||
|
the one line to edit — `build.sh` fails loudly with a clear message if
|
||||||
|
the path doesn't exist rather than silently falling through to
|
||||||
|
whatever `java` resolves to on PATH.
|
||||||
|
|
||||||
## Conventions for changes
|
## Conventions for changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ Run on the Linux machine you're building from (not the phone):
|
||||||
```sh
|
```sh
|
||||||
command -v buildozer && buildozer version 2>&1
|
command -v buildozer && buildozer version 2>&1
|
||||||
command -v java && java -version 2>&1
|
command -v java && java -version 2>&1
|
||||||
|
archlinux-java status 2>&1
|
||||||
python3 -c "import cython; print('cython:', cython.__version__)" 2>&1
|
python3 -c "import cython; print('cython:', cython.__version__)" 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -32,9 +33,19 @@ python3 -c "import cython; print('cython:', cython.__version__)" 2>&1
|
||||||
**Arch / EndeavourOS:**
|
**Arch / EndeavourOS:**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo pacman -S --needed jdk-openjdk
|
sudo pacman -S --needed jdk17-openjdk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Gradle (pulled in by buildozer/p4a) needs a JDK it actually supports —
|
||||||
|
`jdk-openjdk` on a rolling-release system tracks whatever's newest, and
|
||||||
|
a too-new JDK breaks Gradle's build-script compiler with `Unsupported
|
||||||
|
class file major version …`. `jdk17-openjdk` specifically, installed
|
||||||
|
alongside whatever your system default is (`archlinux-java status`
|
||||||
|
lists both — no need to switch the default). `build.sh` points this
|
||||||
|
build at it via `JAVA_HOME` on its own; if `archlinux-java status` shows
|
||||||
|
it under a different name on your machine, update
|
||||||
|
`JAVA_HOME_FOR_BUILD` at the top of `build.sh` to match.
|
||||||
|
|
||||||
buildozer and cython go in an isolated venv, not system Python — see
|
buildozer and cython go in an isolated venv, not system Python — see
|
||||||
next step. (No `pip install --break-system-packages`; that pollutes the
|
next step. (No `pip install --break-system-packages`; that pollutes the
|
||||||
system Python site-packages for no reason when a venv does the job.)
|
system Python site-packages for no reason when a venv does the job.)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,18 @@
|
||||||
# buildozer through it directly. Usage: ./build.sh android debug
|
# buildozer through it directly. Usage: ./build.sh android debug
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ---- Configuration ----
|
||||||
|
# Gradle 8.14.3 (pulled in by this p4a/buildozer version) ships a
|
||||||
|
# Groovy/ASM build-script compiler that doesn't understand class files
|
||||||
|
# newer than it was built against. This system's `java` default is
|
||||||
|
# java-26-openjdk (`archlinux-java status`), and Gradle chokes on it:
|
||||||
|
# BUG! ... Unsupported class file major version 70
|
||||||
|
# java-17-openjdk is also installed on this machine and works — set only
|
||||||
|
# for this build, via JAVA_HOME below, so the system-wide default JDK
|
||||||
|
# (used by everything else) is untouched. If Arch's package layout ever
|
||||||
|
# changes this path, `archlinux-java status` shows the current one.
|
||||||
|
JAVA_HOME_FOR_BUILD="/usr/lib/jvm/java-17-openjdk"
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
VENV_BIN="$SCRIPT_DIR/build/venv/bin"
|
VENV_BIN="$SCRIPT_DIR/build/venv/bin"
|
||||||
BUILDOZER="$VENV_BIN/buildozer"
|
BUILDOZER="$VENV_BIN/buildozer"
|
||||||
|
|
@ -12,7 +24,14 @@ if [ ! -x "$BUILDOZER" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$JAVA_HOME_FOR_BUILD" ]; then
|
||||||
|
echo "Expected JDK not found at $JAVA_HOME_FOR_BUILD — run 'archlinux-java status' and update JAVA_HOME_FOR_BUILD in this script." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
export JAVA_HOME="$JAVA_HOME_FOR_BUILD"
|
||||||
|
export PATH="$JAVA_HOME/bin:$PATH"
|
||||||
# Running buildozer by absolute path skips everything `source venv/bin/activate`
|
# Running buildozer by absolute path skips everything `source venv/bin/activate`
|
||||||
# normally sets up, so it's replicated by hand:
|
# normally sets up, so it's replicated by hand:
|
||||||
# - PATH: buildozer shells out to find tools like `cython`, which only
|
# - PATH: buildozer shells out to find tools like `cython`, which only
|
||||||
|
|
@ -23,4 +42,26 @@ cd "$SCRIPT_DIR"
|
||||||
# a venv, uses --user, and pip refuses (no user site-packages in a venv).
|
# a venv, uses --user, and pip refuses (no user site-packages in a venv).
|
||||||
export PATH="$VENV_BIN:$PATH"
|
export PATH="$VENV_BIN:$PATH"
|
||||||
export VIRTUAL_ENV="$SCRIPT_DIR/build/venv"
|
export VIRTUAL_ENV="$SCRIPT_DIR/build/venv"
|
||||||
|
|
||||||
|
# p4a creates its OWN throwaway venv per arch (.buildozer/.../build/venv,
|
||||||
|
# distinct from our build/venv above) to pip-install pure-Python deps for
|
||||||
|
# the app, and unconditionally re-runs `python -m venv venv` over it on
|
||||||
|
# every single build — without --clear. The first time, ensurepip bundles
|
||||||
|
# whatever pip version shipped with this system's Python (e.g. 25.3); if
|
||||||
|
# a previous build then ran `pip install -U pip` inside it (p4a does this
|
||||||
|
# every time too), the NEXT build's `python -m venv` re-invokes ensurepip,
|
||||||
|
# which unpacks its older bundled pip back over the newer one WITHOUT
|
||||||
|
# removing the newer version's now-orphaned files — two dist-info dirs
|
||||||
|
# end up coexisting, and a newer file (e.g. build_env/installer.py,
|
||||||
|
# importing a class only the newer pip's exceptions.py defines) can end
|
||||||
|
# up paired with an older file that doesn't define it, e.g.:
|
||||||
|
# ImportError: cannot import name 'BuildDependencyInstallError' from
|
||||||
|
# 'pip._internal.exceptions'
|
||||||
|
# Confirmed by hand: pip-25.3.dist-info and pip-26.2.1.dist-info both
|
||||||
|
# present in the same site-packages after a second build. Deleting that
|
||||||
|
# venv before every build keeps it single-version and costs a few
|
||||||
|
# seconds (pip + Cython reinstall) — cheap next to the SDK/NDK/recipe
|
||||||
|
# build state, which this leaves untouched.
|
||||||
|
rm -rf "$SCRIPT_DIR"/.buildozer/android/platform/build-*/build/venv
|
||||||
|
|
||||||
exec "$BUILDOZER" "$@"
|
exec "$BUILDOZER" "$@"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue