Add Android ARM64 release packaging

ober

cc7af8de1b4c1f3bff8aeaff98439f3e355eb2ac

diff --git a/Makefile b/Makefile
index 464234f..568d87d 100644
--- a/Makefile
+++ b/Makefile
@@ -141,6 +141,7 @@ help:
 	@echo "  jerboa-macos-arm64    Build for macOS arm64                 -> dist/macos-arm64/"
 	@echo "  jerboa-linux-amd64    Cross-build for Linux x86_64 (musl)   -> dist/linux-amd64/"
 	@echo "  jerboa-linux-arm64    Cross-build for Linux arm64 (musl)     -> dist/linux-arm64/"
+	@echo "  jerboa-android-arm64  Build on Termux/Android arm64          -> dist/android-arm64/"
 	@echo "  jerboa-freebsd-amd64  Cross-build for FreeBSD amd64          -> dist/freebsd-amd64/"
 	@echo "  jerboa-cross          Generic: CHEZ_TARGET_MACHINE=<mt> CROSS_CC=<cc>"
 	@echo "                        (e.g. tarm64le -> dist/linux-arm64/, ta6fb -> freebsd-amd64)"
@@ -431,7 +432,7 @@ install:
 #
 # Generic form (builds the cross Chez on demand via chez-cross):
 #   make jerboa-cross CHEZ_TARGET_MACHINE=ta6le CROSS_CC=x86_64-linux-musl-gcc
-.PHONY: jerboa-cross jerboa-macos-arm64 jerboa-linux-amd64 jerboa-linux-arm64 jerboa-freebsd-amd64 jerboa-portable
+.PHONY: jerboa-cross jerboa-macos-arm64 jerboa-linux-amd64 jerboa-linux-arm64 jerboa-android-arm64 jerboa-freebsd-amd64 jerboa-portable
 jerboa-cross: chez build mcp-check lsp-gen chez-cross
 	@test -n "$(CHEZ_TARGET_MACHINE)" \
 		|| { echo "ERROR: set CHEZ_TARGET_MACHINE=<machine-type>" >&2; exit 1; }
@@ -481,6 +482,17 @@ jerboa-linux-arm64: chez build mcp-check lsp-gen
 		CC=aarch64-linux-musl-gcc \
 		$(SCHEME) --libdirs $(LIBDIRS) --script support/build-jerboa-multicall.ss
 
+jerboa-android-arm64: jerboa
+	@case "$(HOST_UNAME_O)-$(HOST_UNAME_M)" in \
+		Android-aarch64|Android-arm64) ;; \
+		*) echo "ERROR: android-arm64 release artifact must be built on Termux/Android arm64" >&2; exit 1 ;; \
+	esac
+	@mkdir -p dist/android-arm64
+	@cp -f dist/jerboa dist/android-arm64/jerboa
+	@chmod 0755 dist/android-arm64/jerboa
+	@for link in jmcp jlsp jerbuild jpkg; do ln -sf jerboa dist/android-arm64/$$link; done
+	@echo "=== Staged jerboa multicall: android-arm64 -> dist/android-arm64/ ==="
+
 jerboa-freebsd-amd64: chez build mcp-check lsp-gen
 	@test -x "$(JERBOA_HOME)/support/cross-cc-freebsd-amd64" || { echo "ERROR: support/cross-cc-freebsd-amd64 not found/executable" >&2; exit 1; }
 	@if test ! -d "$(JERBOA_HOME)/.chez-cross-ta6fb" || test ! -f "$(CHEZ_BUILD_DIR)/xc-ta6fb/s/xpatch"; then \
@@ -507,7 +519,7 @@ jerboa-portable: check-cross-tools jerboa-macos-arm64 jerboa-linux-amd64 jerboa-
 # maintainers can call `release-artifacts` to cross-build and package all
 # supported bootstrap toolchains in one pass.
 RELEASE_VERSION ?= $(shell git describe --tags --exact-match 2>/dev/null || printf 'v%s\n' "$(PROJECT_VERSION)")
-RELEASE_TARGET ?= $(shell host="$(HOST_UNAME_S)-$(HOST_UNAME_M)"; if [ "$$host" = Darwin-arm64 ]; then echo macos-arm64; elif [ "$$host" = Linux-x86_64 ]; then echo linux-amd64; elif [ "$$host" = Linux-aarch64 ] || [ "$$host" = Linux-arm64 ]; then echo linux-arm64; elif [ "$$host" = FreeBSD-amd64 ] || [ "$$host" = FreeBSD-x86_64 ]; then echo freebsd-amd64; else echo unknown; fi)
+RELEASE_TARGET ?= $(shell host="$(HOST_UNAME_S)-$(HOST_UNAME_M)"; if [ "$(HOST_UNAME_O)" = Android ] && { [ "$(HOST_UNAME_M)" = aarch64 ] || [ "$(HOST_UNAME_M)" = arm64 ]; }; then echo android-arm64; elif [ "$$host" = Darwin-arm64 ]; then echo macos-arm64; elif [ "$$host" = Linux-x86_64 ]; then echo linux-amd64; elif [ "$$host" = Linux-aarch64 ] || [ "$$host" = Linux-arm64 ]; then echo linux-arm64; elif [ "$$host" = FreeBSD-amd64 ] || [ "$$host" = FreeBSD-x86_64 ]; then echo freebsd-amd64; else echo unknown; fi)
 RELEASE_TARGETS ?= macos-arm64 linux-amd64 linux-arm64 freebsd-amd64
 RELEASE_DIR ?= dist/release
 RELEASE_REPO ?= ~lisp/jerboa
diff --git a/data/cookbooks.sexp b/data/cookbooks.sexp
index d4d2cd4..478c3cc 100644
--- a/data/cookbooks.sexp
+++ b/data/cookbooks.sexp
@@ -6526,4 +6526,16 @@
      "portable")
    ("title"
      .
-     "Choose a writable build temp directory on Termux")))
+     "Choose a writable build temp directory on Termux"))
+ (("code"
+    .
+    "# Makefile target detection\nHOST_UNAME_O := $(shell uname -o 2>/dev/null || true)\nRELEASE_TARGET ?= $(shell host=\"$(HOST_UNAME_S)-$(HOST_UNAME_M)\"; if [ \"$(HOST_UNAME_O)\" = Android ] && { [ \"$(HOST_UNAME_M)\" = aarch64 ] || [ \"$(HOST_UNAME_M)\" = arm64 ]; }; then echo android-arm64; elif [ \"$$host\" = Linux-aarch64 ] || [ \"$$host\" = Linux-arm64 ]; then echo linux-arm64; else echo unknown; fi)\n\n# Stage the native Termux-built multicall binary\njerboa-android-arm64: jerboa\n\t@case \"$(HOST_UNAME_O)-$(HOST_UNAME_M)\" in Android-aarch64|Android-arm64) ;; *) exit 1 ;; esac\n\t@mkdir -p dist/android-arm64\n\t@cp -f dist/jerboa dist/android-arm64/jerboa\n\n# Package and upload\nmake jerboa-android-arm64\nmake release-artifact RELEASE_VERSION=v0.2.4 RELEASE_TARGET=android-arm64\nmake release-upload RELEASE_VERSION=v0.2.4") ("id" . "android-arm64-sourcehut-release-artifact")
+   ("imports")
+   ("notes"
+     .
+     "Termux reports uname -s as Linux and uname -o as Android, so release installers must distinguish Android ARM64 from generic Linux ARM64. Package validation should look for an ELF aarch64 binary with Android in file(1) output. Build and package this target on Termux rather than with the normal Linux musl cross target.")
+   ("tags" "release" "sourcehut" "termux" "android" "arm64"
+     "install")
+   ("title"
+     .
+     "Package a Termux Android ARM64 release artifact")))
diff --git a/support/ensure-jerboa.sh b/support/ensure-jerboa.sh
index 4728915..1ac6946 100755
--- a/support/ensure-jerboa.sh
+++ b/support/ensure-jerboa.sh
@@ -10,6 +10,7 @@
 #   JERBOA_RELEASE_REPO=~lisp/jerboa
 # For testing or unusual hosts, override target detection with:
 #   JERBOA_RELEASE_TARGET=macos-arm64
+#   JERBOA_RELEASE_TARGET=android-arm64
 
 set -eu
 
@@ -29,10 +30,17 @@ if [ "${JERBOA_RELEASE_TARGET:-}" ]; then
 else
     os=$(uname -s)
     arch=$(uname -m)
+    flavor=$(uname -o 2>/dev/null || true)
     case "$os-$arch" in
         Darwin-arm64) target=macos-arm64 ;;
         Linux-x86_64|Linux-amd64) target=linux-amd64 ;;
-        Linux-aarch64|Linux-arm64) target=linux-arm64 ;;
+        Linux-aarch64|Linux-arm64)
+            if [ "$flavor" = Android ]; then
+                target=android-arm64
+            else
+                target=linux-arm64
+            fi
+            ;;
         FreeBSD-amd64|FreeBSD-x86_64) target=freebsd-amd64 ;;
         *)
             echo "ERROR: unsupported platform: $os $arch" >&2
@@ -42,7 +50,7 @@ else
 fi
 
 case "$target" in
-    macos-arm64|linux-amd64|linux-arm64|freebsd-amd64) ;;
+    macos-arm64|linux-amd64|linux-arm64|android-arm64|freebsd-amd64) ;;
     *)
         echo "ERROR: unsupported release target: $target" >&2
         exit 1
@@ -83,7 +91,26 @@ sha256_file() {
     fi
 }
 
-tmp=$(mktemp -d "${TMPDIR:-/tmp}/jerboa-bootstrap.XXXXXX")
+choose_tmp_parent() {
+    if [ -n "${TMPDIR:-}" ] && [ -d "$TMPDIR" ] && [ -w "$TMPDIR" ]; then
+        printf '%s\n' "$TMPDIR"
+        return
+    fi
+    if [ -n "${PREFIX:-}" ] && [ -d "$PREFIX/tmp" ] && [ -w "$PREFIX/tmp" ]; then
+        printf '%s\n' "$PREFIX/tmp"
+        return
+    fi
+    if [ -d /tmp ] && [ -w /tmp ]; then
+        printf '%s\n' /tmp
+        return
+    fi
+
+    mkdir -p "$bindir/.tmp"
+    printf '%s\n' "$bindir/.tmp"
+}
+
+tmp_parent=$(choose_tmp_parent)
+tmp=$(mktemp -d "$tmp_parent/jerboa-bootstrap.XXXXXX")
 trap 'rm -rf "$tmp"' EXIT HUP INT TERM
 
 archive="$tmp/$file"
diff --git a/support/install.sh b/support/install.sh
index 2675243..c1a811e 100755
--- a/support/install.sh
+++ b/support/install.sh
@@ -28,7 +28,7 @@ Environment:
   JERBOA_RELEASE_REPO    SourceHut repo path (default: ~lisp/jerboa)
   JERBOA_RELEASE_ORIGIN  SourceHut origin (default: https://git.sr.ht)
   JERBOA_RELEASE_BASE    Complete release base URL override
-  JERBOA_RELEASE_TARGET  Target override, e.g. linux-amd64
+  JERBOA_RELEASE_TARGET  Target override, e.g. linux-amd64 or android-arm64
 EOF
 }
 
@@ -126,6 +126,24 @@ sha256_file() {
     fi
 }
 
+choose_tmp_parent() {
+    if [ -n "${TMPDIR:-}" ] && [ -d "$TMPDIR" ] && [ -w "$TMPDIR" ]; then
+        printf '%s\n' "$TMPDIR"
+        return
+    fi
+    if [ -n "${PREFIX:-}" ] && [ -d "$PREFIX/tmp" ] && [ -w "$PREFIX/tmp" ]; then
+        printf '%s\n' "$PREFIX/tmp"
+        return
+    fi
+    if [ -d /tmp ] && [ -w /tmp ]; then
+        printf '%s\n' /tmp
+        return
+    fi
+
+    mkdir -p "$bindir/.tmp"
+    printf '%s\n' "$bindir/.tmp"
+}
+
 highest_version() {
     awk '
         $0 ~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ {
@@ -174,10 +192,17 @@ detect_target() {
 
     os=$(uname -s)
     arch=$(uname -m)
+    flavor=$(uname -o 2>/dev/null || true)
     case "$os-$arch" in
+        Linux-aarch64|Linux-arm64)
+            if [ "$flavor" = Android ]; then
+                echo android-arm64
+            else
+                echo linux-arm64
+            fi
+            ;;
         Darwin-arm64) echo macos-arm64 ;;
         Linux-x86_64|Linux-amd64) echo linux-amd64 ;;
-        Linux-aarch64|Linux-arm64) echo linux-arm64 ;;
         FreeBSD-amd64|FreeBSD-x86_64) echo freebsd-amd64 ;;
         *) error "unsupported platform: $os $arch" ;;
     esac
@@ -200,7 +225,7 @@ esac
 
 target=$(detect_target)
 case "$target" in
-    macos-arm64|linux-amd64|linux-arm64|freebsd-amd64) ;;
+    macos-arm64|linux-amd64|linux-arm64|android-arm64|freebsd-amd64) ;;
     *) error "unsupported release target: $target" ;;
 esac
 
@@ -221,7 +246,8 @@ base=${JERBOA_RELEASE_BASE:-${repo_url}/refs/download/${version}}
 url="${base%/}/${file}"
 sum_url="${url}.sha256"
 
-tmp=$(mktemp -d "${TMPDIR:-/tmp}/jerboa-install.XXXXXX")
+tmp_parent=$(choose_tmp_parent)
+tmp=$(mktemp -d "$tmp_parent/jerboa-install.XXXXXX")
 trap 'rm -rf "$tmp"' EXIT HUP INT TERM
 
 archive="$tmp/$file"
diff --git a/support/package-jerboa-release.sh b/support/package-jerboa-release.sh
index a7d3110..190ff84 100755
--- a/support/package-jerboa-release.sh
+++ b/support/package-jerboa-release.sh
@@ -5,12 +5,30 @@ set -eu
 
 usage() {
     echo "Usage: $0 VERSION TARGET [RELEASE_DIR]" >&2
-    echo "  TARGET: macos-arm64 | linux-amd64 | linux-arm64 | freebsd-amd64" >&2
+    echo "  TARGET: macos-arm64 | linux-amd64 | linux-arm64 | android-arm64 | freebsd-amd64" >&2
 }
 
 [ "${1:-}" ] || { usage; exit 2; }
 [ "${2:-}" ] || { usage; exit 2; }
 
+choose_tmp_parent() {
+    if [ -n "${TMPDIR:-}" ] && [ -d "$TMPDIR" ] && [ -w "$TMPDIR" ]; then
+        printf '%s\n' "$TMPDIR"
+        return
+    fi
+    if [ -n "${PREFIX:-}" ] && [ -d "$PREFIX/tmp" ] && [ -w "$PREFIX/tmp" ]; then
+        printf '%s\n' "$PREFIX/tmp"
+        return
+    fi
+    if [ -d /tmp ] && [ -w /tmp ]; then
+        printf '%s\n' /tmp
+        return
+    fi
+
+    mkdir -p "${release_dir:-dist/release}/tmp"
+    printf '%s\n' "${release_dir:-dist/release}/tmp"
+}
+
 version=$1
 target=$2
 release_dir=${3:-dist/release}
@@ -19,7 +37,7 @@ versioned="${release_dir}/${name}.tar.gz"
 alias_tar="${release_dir}/jerboa-${target}.tar.gz"
 
 case "$target" in
-    macos-arm64|linux-amd64|linux-arm64|freebsd-amd64) ;;
+    macos-arm64|linux-amd64|linux-arm64|android-arm64|freebsd-amd64) ;;
     *)
         echo "ERROR: unsupported release target: $target" >&2
         exit 1
@@ -41,6 +59,7 @@ case "$target:$file_desc" in
     macos-arm64:*"Mach-O 64-bit executable arm64"*) ;;
     linux-amd64:*"ELF 64-bit LSB executable, x86-64"*) ;;
     linux-arm64:*"ELF 64-bit LSB executable, ARM aarch64"*) ;;
+    android-arm64:*"ELF 64-bit LSB"*"ARM aarch64"*"Android"*) ;;
     freebsd-amd64:*"ELF 64-bit LSB executable, x86-64"*"FreeBSD"*) ;;
     *)
         echo "ERROR: $source_bin does not look like target $target" >&2
@@ -50,7 +69,8 @@ case "$target:$file_desc" in
 esac
 
 mkdir -p "$release_dir"
-tmp=$(mktemp -d "${TMPDIR:-/tmp}/jerboa-release.XXXXXX")
+tmp_parent=$(choose_tmp_parent)
+tmp=$(mktemp -d "$tmp_parent/jerboa-release.XXXXXX")
 trap 'rm -rf "$tmp"' EXIT HUP INT TERM
 
 mkdir -p "$tmp/$name/bin"