kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

android_ndk_sysroot.sh (6730B)


      1 #!/usr/bin/env bash
      2 # Download and cache the Android NDK, exposing its sysroot for kit's aarch64
      3 # Android hosted profile.
      4 #
      5 # usage:
      6 #   scripts/android_ndk_sysroot.sh prepare [aa64]
      7 #   scripts/android_ndk_sysroot.sh path [aa64]
      8 #   scripts/android_ndk_sysroot.sh root
      9 #   scripts/android_ndk_sysroot.sh env [aa64]
     10 
     11 set -eu
     12 
     13 RELEASE="${KIT_ANDROID_NDK_RELEASE:-r27d}"
     14 REPO_XML="${KIT_ANDROID_NDK_REPOSITORY_XML:-https://dl.google.com/android/repository/repository2-1.xml}"
     15 BASE_URL="${KIT_ANDROID_NDK_BASE_URL:-https://dl.google.com/android/repository}"
     16 XDG_CACHE_HOME="${XDG_CACHE_HOME:-${HOME:-}/.cache}"
     17 CACHE="${KIT_ANDROID_NDK_CACHE:-$XDG_CACHE_HOME/kit/android-ndk/$RELEASE}"
     18 
     19 die() { printf 'android-ndk-sysroot: %s\n' "$*" >&2; exit 1; }
     20 
     21 canon_arch() {
     22   case "${1:-aa64}" in
     23     aa64|aarch64|arm64|"") echo aarch64 ;;
     24     all) echo all ;;
     25     *) die "unknown arch '${1:-}' (Android support is aarch64 only)" ;;
     26   esac
     27 }
     28 
     29 host_asset() {
     30   case "$(uname -s 2>/dev/null || echo unknown)" in
     31     Darwin) echo "android-ndk-$RELEASE-darwin.zip" ;;
     32     Linux) echo "android-ndk-$RELEASE-linux.zip" ;;
     33     MINGW*|MSYS*|CYGWIN*) echo "android-ndk-$RELEASE-windows.zip" ;;
     34     *) die "unsupported host OS: $(uname -s 2>/dev/null || echo unknown)" ;;
     35   esac
     36 }
     37 
     38 sha1_file() {
     39   if command -v shasum >/dev/null 2>&1; then
     40     shasum -a 1 "$1" | awk '{ print $1 }'
     41     return 0
     42   fi
     43   if command -v sha1sum >/dev/null 2>&1; then
     44     sha1sum "$1" | awk '{ print $1 }'
     45     return 0
     46   fi
     47   die "missing shasum or sha1sum"
     48 }
     49 
     50 metadata_field() {
     51   local asset="$1" field="$2" xml="$CACHE/repository2-1.xml"
     52   mkdir -p "$CACHE"
     53   if [ "${FORCE:-0}" = 1 ] || [ ! -f "$xml" ]; then
     54     command -v curl >/dev/null 2>&1 || die "curl not found"
     55     curl -fsSL "$REPO_XML" -o "$xml.tmp"
     56     mv "$xml.tmp" "$xml"
     57   fi
     58   case "$field" in
     59     checksum)
     60       awk -v want="$asset" '
     61         /<checksum>/ { c=$0; sub(/^.*<checksum>/, "", c); sub(/<\/checksum>.*$/, "", c) }
     62         /<url>/ { u=$0; sub(/^.*<url>/, "", u); sub(/<\/url>.*$/, "", u); if (u == want) { print c; exit } }
     63       ' "$xml"
     64       ;;
     65     url)
     66       awk -v want="$asset" '
     67         /<url>/ { u=$0; sub(/^.*<url>/, "", u); sub(/<\/url>.*$/, "", u); if (u == want) { print u; exit } }
     68       ' "$xml"
     69       ;;
     70     *) die "internal bad metadata field: $field" ;;
     71   esac
     72 }
     73 
     74 archive_path() { printf '%s/%s\n' "$CACHE" "$(host_asset)"; }
     75 install_root() { printf '%s/android-ndk-%s\n' "$CACHE" "$RELEASE"; }
     76 
     77 verify_archive() {
     78   local path="$1" want="$2" got
     79   [ -n "$want" ] || die "no repository checksum found for $(basename "$path")"
     80   got="$(sha1_file "$path")"
     81   [ "$got" = "$want" ] ||
     82     die "checksum mismatch for $(basename "$path"): got $got want $want"
     83 }
     84 
     85 fetch_archive() {
     86   local asset full_url path want url
     87   asset="$(host_asset)"
     88   path="$(archive_path)"
     89   want="$(metadata_field "$asset" checksum)"
     90   [ -n "$want" ] || die "no repository checksum found for $asset"
     91   url="$(metadata_field "$asset" url)"
     92   [ -n "$url" ] || die "no repository URL found for $asset"
     93   mkdir -p "$CACHE"
     94   if [ -f "$path" ]; then
     95     verify_archive "$path" "$want"
     96     printf 'archive already verified: %s\n' "$path"
     97     return 0
     98   fi
     99   command -v curl >/dev/null 2>&1 || die "curl not found"
    100   full_url="$BASE_URL/$url"
    101   printf 'download: %s\n' "$full_url"
    102   curl -fL --retry 3 --retry-delay 2 --continue-at - -o "$path.part" "$full_url"
    103   mv "$path.part" "$path"
    104   verify_archive "$path" "$want"
    105   printf 'verified: %s\n' "$path"
    106 }
    107 
    108 prebuilt_dir() {
    109   local root="$1" d
    110   for d in "$root"/toolchains/llvm/prebuilt/*; do
    111     [ -d "$d" ] || continue
    112     printf '%s\n' "$d"
    113     return 0
    114   done
    115   return 1
    116 }
    117 
    118 sysroot_path() {
    119   local root d
    120   canon_arch "${1:-aa64}" >/dev/null
    121   root="$(install_root)"
    122   if d="$(prebuilt_dir "$root" 2>/dev/null)"; then
    123     printf '%s/sysroot\n' "$d"
    124     return 0
    125   fi
    126   case "$(uname -s 2>/dev/null || echo unknown)" in
    127     Darwin) printf '%s/toolchains/llvm/prebuilt/darwin-x86_64/sysroot\n' "$root" ;;
    128     Linux) printf '%s/toolchains/llvm/prebuilt/linux-x86_64/sysroot\n' "$root" ;;
    129     MINGW*|MSYS*|CYGWIN*) printf '%s/toolchains/llvm/prebuilt/windows-x86_64/sysroot\n' "$root" ;;
    130     *) die "unsupported host OS: $(uname -s 2>/dev/null || echo unknown)" ;;
    131   esac
    132 }
    133 
    134 prepare() {
    135   local arch root path sr
    136   arch="$(canon_arch "${1:-aa64}")"
    137   [ "$arch" = aarch64 ] || die "prepare requires aa64/aarch64"
    138   root="$(install_root)"
    139   if [ "${FORCE:-0}" != 1 ] && [ -r "$(sysroot_path "$arch")/usr/include/android/native_activity.h" ]; then
    140     printf 'sysroot cached: %s\n' "$(sysroot_path "$arch")"
    141     return 0
    142   fi
    143   fetch_archive
    144   path="$(archive_path)"
    145   rm -rf "$root.tmp"
    146   mkdir -p "$CACHE"
    147   command -v unzip >/dev/null 2>&1 || die "unzip not found"
    148   unzip -q "$path" -d "$root.tmp"
    149   if [ -d "$root.tmp/android-ndk-$RELEASE" ]; then
    150     rm -rf "$root"
    151     mv "$root.tmp/android-ndk-$RELEASE" "$root"
    152     rm -rf "$root.tmp"
    153   else
    154     rm -rf "$root.tmp"
    155     die "archive did not contain android-ndk-$RELEASE"
    156   fi
    157   sr="$(sysroot_path "$arch")"
    158   [ -r "$sr/usr/include/android/native_activity.h" ] ||
    159     die "NDK sysroot missing android/native_activity.h"
    160   [ -d "$sr/usr/lib/aarch64-linux-android" ] ||
    161     die "NDK sysroot missing aarch64 Android libraries"
    162   {
    163     printf 'release=%s\n' "$RELEASE"
    164     printf 'asset=%s\n' "$(basename "$path")"
    165     printf 'url=%s/%s\n' "$BASE_URL" "$(metadata_field "$(basename "$path")" url)"
    166     printf 'sha1=%s\n' "$(metadata_field "$(basename "$path")" checksum)"
    167     printf 'target=aarch64-linux-android\n'
    168   } > "$root/PROVENANCE"
    169   printf 'sysroot ready: %s\n' "$sr"
    170 }
    171 
    172 doctor() {
    173   local asset root sr
    174   asset="$(host_asset)"
    175   root="$(install_root)"
    176   sr="$(sysroot_path aa64)"
    177   printf 'host: %s/%s\n' "$(uname -s 2>/dev/null)" "$(uname -m 2>/dev/null)"
    178   printf 'release: %s\n' "$RELEASE"
    179   printf 'asset: %s\n' "$asset"
    180   printf 'download cache: %s\n' "$CACHE"
    181   printf 'ndk root: %s%s\n' "$root" "$([ -d "$root" ] && echo '' || echo ' (missing)')"
    182   printf 'sysroot: %s%s\n' "$sr" "$([ -d "$sr" ] && echo '' || echo ' (missing)')"
    183   for tool in curl unzip shasum sha1sum; do
    184     if command -v "$tool" >/dev/null 2>&1; then
    185       printf '  OK      %s (%s)\n' "$tool" "$(command -v "$tool")"
    186     else
    187       printf '  MISSING %s\n' "$tool"
    188     fi
    189   done
    190 }
    191 
    192 cmd="${1:-}"
    193 case "$cmd" in
    194   doctor) doctor ;;
    195   fetch) fetch_archive ;;
    196   prepare) shift; prepare "${1:-aa64}" ;;
    197   path) shift; sysroot_path "${1:-aa64}" ;;
    198   root) install_root ;;
    199   env)
    200     shift
    201     printf 'export KIT_SYSROOT=%s\n' "$(sysroot_path "${1:-aa64}")"
    202     ;;
    203   -h|--help|help|"")
    204     sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//'
    205     ;;
    206   *) die "unknown command '$cmd' (try: doctor fetch prepare path root env)" ;;
    207 esac