From 17c927afa31173f707b9709ab86afd4e7606c919 Mon Sep 17 00:00:00 2001 From: Garrett Mills Date: Sun, 2 Aug 2026 13:22:36 -0500 Subject: [PATCH] Add a fish version of the Android env helper Only the env helper needs a per-shell variant, since it has to mutate the calling shell; android-setup.sh is executed rather than sourced and already works from fish. The fish version finds NDK/JDK candidates via `find` rather than globs because fish raises an error on a wildcard matching nothing, and "SDK with no ndk/ directory yet" is a normal state the helper has to report cleanly. Also switch the bash helper's NDK selection to `find | sort -V` so the two agree: glob order is lexicographic, which would rank 9.x above 10.x. Verified both pick the same NDK and JDK on this machine and against a fixture with 9.0.111 / 10.0.222 / 28.2.333 / 30.0.999-beta2 installed. --- README.md | 9 +++- scripts/android-env.fish | 89 ++++++++++++++++++++++++++++++++++++++++ scripts/android-env.sh | 7 ++-- 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100755 scripts/android-env.fish diff --git a/README.md b/README.md index 8c2510b..ce80d32 100644 --- a/README.md +++ b/README.md @@ -145,9 +145,16 @@ Every Android command needs `ANDROID_HOME` / `NDK_HOME` / `JAVA_HOME`. Source the helper once per shell — it auto-detects all three: ```bash -source scripts/android-env.sh +source scripts/android-env.sh # bash / zsh ``` +```fish +source scripts/android-env.fish # fish +``` + +Only the env helper is shell-specific (it has to mutate the calling shell); +`android-setup.sh` is executed rather than sourced, so it works from any shell. + Then, from the project root: ```bash diff --git a/scripts/android-env.fish b/scripts/android-env.fish new file mode 100755 index 0000000..ec0bc5e --- /dev/null +++ b/scripts/android-env.fish @@ -0,0 +1,89 @@ +#!/usr/bin/env fish +# +# android-env.fish — export the environment the Android build needs (fish shell). +# +# SOURCE this, don't execute it: +# +# source scripts/android-env.fish +# cargo tauri android dev --open +# +# bash/zsh users want scripts/android-env.sh instead — only the *env* script is +# shell-specific, since it has to mutate the calling shell. ./scripts/android-setup.sh +# is executed rather than sourced, so it already works from any shell. +# +# Everything is auto-detected, so there are no machine-specific paths to keep in +# sync. Run ./scripts/android-setup.sh first to install the pieces. + +function _mtgc_android_env + # --- SDK --- + set -l sdk $HOME/Android/Sdk + if set -q ANDROID_HOME; and test -n "$ANDROID_HOME" + set sdk $ANDROID_HOME + end + if not test -d $sdk + echo "android-env: no Android SDK at $sdk (run ./scripts/android-setup.sh)" >&2 + return 1 + end + + # --- NDK: newest *stable* installed (skip beta/rc/canary) --- + # `find` rather than a glob: fish raises an error on a wildcard that matches + # nothing, and an SDK with no ndk/ directory at all is a normal state here. + # `sort -V` so 9.x doesn't outrank 10.x the way plain lexicographic would. + set -l ndk "" + for d in (find $sdk/ndk -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort -V) + set -l rev (sed -n 's/^Pkg.Revision *= *//p' $d/source.properties 2>/dev/null) + switch "$rev" + case '*beta*' '*rc*' '*canary*' + continue + end + set ndk $d + end + if test -z "$ndk" + echo "android-env: no stable NDK under $sdk/ndk (run ./scripts/android-setup.sh)" >&2 + return 1 + end + + # --- JDK: Gradle/AGP reject very new JDKs; prefer Studio's bundled JBR 21 --- + # Ordered by preference; globbed locations go through `find` for the same + # unmatched-wildcard reason as above. + set -l studio $HOME/.local/share/JetBrains/Toolbox/apps/android-studio + set -l candidates \ + $studio/jbr \ + (find $studio -mindepth 2 -maxdepth 2 -type d -name jbr 2>/dev/null | sort -V) \ + $HOME/android-studio/jbr \ + /opt/android-studio/jbr \ + (find /usr/lib/jvm -maxdepth 1 -name 'java-21-openjdk*' 2>/dev/null | sort -V) \ + (find /usr/lib/jvm -maxdepth 1 -name 'java-17-openjdk*' 2>/dev/null | sort -V) + + set -l jdk "" + for d in $candidates + # Test for javac specifically: a JRE-only or leftover-empty directory + # under /usr/lib/jvm must not count. + if test -x $d/bin/javac + set jdk $d + break + end + end + if test -z "$jdk" + echo "android-env: no JDK 21/17 found (Gradle rejects the system default)" >&2 + return 1 + end + + set -gx ANDROID_HOME $sdk + set -gx NDK_HOME $ndk + set -gx JAVA_HOME $jdk + # adb/emulator live here; harmless if already present. + if not contains $sdk/platform-tools $PATH + set -gx PATH $sdk/platform-tools $PATH + end + + echo "ANDROID_HOME=$ANDROID_HOME" + echo "NDK_HOME=$NDK_HOME" + echo "JAVA_HOME=$JAVA_HOME" +end + +_mtgc_android_env +set -l _mtgc_ok $status +functions -e _mtgc_android_env +# Leave the sourced file's exit status reflecting whether detection succeeded. +test $_mtgc_ok -eq 0 diff --git a/scripts/android-env.sh b/scripts/android-env.sh index 89415d7..6ff078d 100755 --- a/scripts/android-env.sh +++ b/scripts/android-env.sh @@ -21,14 +21,15 @@ _mtgc_android_env() { fi # --- NDK: newest *stable* installed (skip beta/rc/canary) --- + # `sort -V` so 9.x doesn't outrank 10.x the way plain lexicographic would. local best="" - for d in "$sdk"/ndk/*; do - [ -d "$d" ] || continue + while IFS= read -r d; do + [ -n "$d" ] || continue case "$(sed -n 's/^Pkg.Revision *= *//p' "$d/source.properties" 2>/dev/null)" in *beta*|*rc*|*canary*) continue ;; esac best="$d" - done + done < <(find "$sdk/ndk" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort -V) ndk="$best" if [ -z "$ndk" ]; then echo "android-env: no stable NDK under $sdk/ndk (run ./scripts/android-setup.sh)" >&2