#!/usr/bin/env sh android_sdk_root() { if [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "$ANDROID_SDK_ROOT" ]; then printf '%s\n' "$ANDROID_SDK_ROOT" return 0 fi if [ -n "${ANDROID_HOME:-}" ] && [ -d "$ANDROID_HOME" ]; then printf '%s\n' "$ANDROID_HOME" return 0 fi if [ -n "${LOCALAPPDATA:-}" ]; then local_sdk="$LOCALAPPDATA/Android/Sdk" if command -v cygpath >/dev/null 2>&1; then local_sdk="$(cygpath -u "$local_sdk")" fi if [ -d "$local_sdk" ]; then printf '%s\n' "$local_sdk" return 0 fi fi if [ -d "$HOME/Android/Sdk" ]; then printf '%s\n' "$HOME/Android/Sdk" return 0 fi return 1 } latest_android_package_dir() { root="$1" package="$2" package_root="$root/$package" [ -d "$package_root" ] || return 1 latest="$( for dir in "$package_root"/*; do [ -d "$dir" ] || continue version="${dir##*/}" printf '%s\n' "$version" done | grep -E '^[0-9]+(\.[0-9]+)*$' | sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n 1 )" [ -n "$latest" ] || return 1 printf '%s/%s\n' "$package_root" "$latest" } android_sdkmanager_command() { root="$1" for candidate in \ "$root/cmdline-tools/latest/bin/sdkmanager" \ "$root/cmdline-tools/latest/bin/sdkmanager.bat" \ "$root/tools/bin/sdkmanager" \ "$root/tools/bin/sdkmanager.bat" do if [ -x "$candidate" ] || [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done if [ -d "$root/cmdline-tools" ]; then for version in "$root/cmdline-tools"/*; do [ -d "$version" ] || continue [ "${version##*/}" = "latest" ] && continue for candidate in "$version/bin/sdkmanager" "$version/bin/sdkmanager.bat"; do if [ -x "$candidate" ] || [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done done fi if command -v sdkmanager >/dev/null 2>&1; then command -v sdkmanager return 0 fi return 1 } latest_version_from_stdin() { sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n | tail -n 1 } latest_available_android_package_version() { root="$1" sdkmanager_cmd="$2" package="$3" output="$("$sdkmanager_cmd" "--sdk_root=$root" --list)" || return 1 printf '%s\n' "$output" | sed -n "s/^[[:space:]]*$package;\\([0-9][0-9.]*\\)[[:space:]]*|.*/\\1/p" | latest_version_from_stdin } accept_android_sdk_licenses() { i=0 while [ "$i" -lt 100 ]; do printf '%s\n' "y" i="$((i + 1))" done } install_android_sdk_package() { root="$1" sdkmanager_cmd="$2" package_id="$3" accept_android_sdk_licenses | "$sdkmanager_cmd" "--sdk_root=$root" --install "$package_id" >&2 } record_android_package_update() { package="$1" installed_before="$2" available="$3" selected="$4" action="$5" case "$package" in ndk) ANDROID_NDK_INSTALLED_BEFORE="$installed_before" ANDROID_NDK_AVAILABLE_VERSION="$available" ANDROID_NDK_UPDATE_ACTION="$action" ;; cmake) ANDROID_CMAKE_INSTALLED_BEFORE="$installed_before" ANDROID_CMAKE_AVAILABLE_VERSION="$available" ANDROID_CMAKE_UPDATE_ACTION="$action" ;; esac export ANDROID_NDK_INSTALLED_BEFORE ANDROID_NDK_AVAILABLE_VERSION ANDROID_NDK_UPDATE_ACTION export ANDROID_CMAKE_INSTALLED_BEFORE ANDROID_CMAKE_AVAILABLE_VERSION ANDROID_CMAKE_UPDATE_ACTION printf '%s\n' "$selected" >/dev/null } ensure_latest_android_package_dir() { root="$1" package="$2" sdkmanager_cmd="${3:-}" installed_dir="$(latest_android_package_dir "$root" "$package" 2>/dev/null || true)" installed_before="${installed_dir##*/}" [ -n "$installed_dir" ] || installed_before="" available_version="" action="using-installed" if [ -n "$sdkmanager_cmd" ]; then available_version="$(latest_available_android_package_version "$root" "$sdkmanager_cmd" "$package")" || return 1 if [ -n "$available_version" ]; then if [ -z "$installed_before" ]; then install_android_sdk_package "$root" "$sdkmanager_cmd" "$package;$available_version" || return 1 action="installed-latest-available" else newest="$(printf '%s\n%s\n' "$installed_before" "$available_version" | latest_version_from_stdin)" if [ "$newest" = "$available_version" ] && [ "$available_version" != "$installed_before" ]; then install_android_sdk_package "$root" "$sdkmanager_cmd" "$package;$available_version" || return 1 action="installed-latest-available" else action="already-latest-available" fi fi else action="available-version-not-listed" fi elif [ -z "$installed_dir" ]; then printf '%s\n' "No installed Android SDK package was found under $root/$package, and sdkmanager was not found." >&2 return 1 fi selected_dir="$(latest_android_package_dir "$root" "$package")" || return 1 record_android_package_update "$package" "$installed_before" "$available_version" "${selected_dir##*/}" "$action" printf '%s\n' "$selected_dir" } set_android_sdk_toolchain_environment() { sdk_root="$(android_sdk_root)" || { printf '%s\n' "Android SDK root was not found. Install command-line tools or set ANDROID_SDK_ROOT." >&2 return 1 } sdkmanager_cmd="$(android_sdkmanager_command "$sdk_root" || true)" ndk_dir="$(ensure_latest_android_package_dir "$sdk_root" ndk "$sdkmanager_cmd")" || return 1 cmake_dir="$(ensure_latest_android_package_dir "$sdk_root" cmake "$sdkmanager_cmd")" || return 1 cmake_command="$cmake_dir/bin/cmake" [ -x "$cmake_command" ] || { printf '%s\n' "Android SDK CMake executable not found: $cmake_command" >&2 return 1 } export ANDROID_HOME="$sdk_root" export ANDROID_SDK_ROOT="$sdk_root" export ANDROID_NDK_HOME="$ndk_dir" export ANDROID_NDK_ROOT="$ndk_dir" export ANDROID_CMAKE_COMMAND="$cmake_command" export ANDROID_NDK_VERSION="${ndk_dir##*/}" export ANDROID_CMAKE_VERSION="${cmake_dir##*/}" export ANDROID_SDKMANAGER_COMMAND="$sdkmanager_cmd" }