#!/usr/bin/env bash # Static deps for Android into third_party/prefix-android-ABI: mbedTLS and # libcurl (HTTP(S) only, mbedTLS), the same pair the Linux release uses -- # a phone has no system libcurl and bionic's CA store is /system/etc/security, # so libcurl is built here rather than taken from the platform. # # scripts/build_third_party_android.sh arm64-v8a|x86_64 [all|mbedtls|curl] # # Needs the NDK in ANDROID_NDK_HOME (a directory with # build/cmake/android.toolchain.cmake). On NixOS the packaged one is: # export ANDROID_NDK_HOME=$( # NIXPKGS_ALLOW_UNFREE=1 nix build --impure --no-link --print-out-paths \ # 'nixpkgs#androidenv.androidPkgs.ndk-bundle')/libexec/android-sdk/ndk-bundle # Host tools: cmake ninja make. set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" ABI="${1:?usage: $0 arm64-v8a|x86_64 [all|mbedtls|curl]}" TP="$ROOT/third_party" PREFIX="$TP/prefix-android-$ABI" SRC="$TP/src" WORK="$TP/build-android-$ABI" JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}" MBEDTLS_VER=3.6.7 MBEDTLS_SHA=a7e8bcbec0e6f761b4af24f25677626b35f762f68eef79c08677a363212d11f6 CURL_VER=8.22.0 CURL_SHA=f7ef3ae8a22e521f289803fe93543eb64c329b58aa73a9e224dfd915a2a5f4f7 # Android 7.0: what bionic gives the engine (threads, exec, /system CA store). API_LEVEL="${API_LEVEL:-24}" # Per-app CAs land in the user store; the system bundle is the readable one. CA_PATH=/system/etc/security/cacerts NDK="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-}}" if [[ -z "$NDK" || ! -f "$NDK/build/cmake/android.toolchain.cmake" ]]; then echo "set ANDROID_NDK_HOME to an NDK (see the header of this script)" >&2 exit 1 fi TOOLCHAIN="$NDK/build/cmake/android.toolchain.cmake" need() { command -v "$1" >/dev/null || { echo "missing: $1" >&2; exit 1; }; } need cmake need ninja mkdir -p "$PREFIX" "$SRC" "$WORK" fetch() { # file sha url... local file="$1" sha="$2" u shift 2 if [[ -f "$SRC/$file" ]] && echo "$sha $SRC/$file" | sha256sum -c --quiet - 2>/dev/null; then return 0 fi for u in "$@"; do echo " try $u" if curl -fsSL --retry 2 --connect-timeout 15 --max-time 600 -o "$SRC/$file.part" "$u" && echo "$sha $SRC/$file.part" | sha256sum -c --quiet -; then mv "$SRC/$file.part" "$SRC/$file" return 0 fi done rm -f "$SRC/$file.part" echo "download failed: $file" >&2 exit 1 } unpack() { # file dir rm -rf "${WORK:?}/$2" tar -C "$WORK" -xf "$SRC/$1" } gh() { # path -> GitHub URL candidates (CN proxies first) printf '%s\n' "https://ghfast.top/https://github.com/$1" \ "https://ghproxy.net/https://github.com/$1" "https://github.com/$1" } cmake_android() { # src build args... local s="$1" b="$2" shift 2 cmake -S "$s" -B "$b" -G Ninja \ -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" \ -DANDROID_ABI="$ABI" -DANDROID_PLATFORM="android-$API_LEVEL" \ -DANDROID_NDK="$NDK" \ -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$PREFIX" \ -DCMAKE_PREFIX_PATH="$PREFIX" -DCMAKE_INSTALL_LIBDIR=lib \ -DCMAKE_POSITION_INDEPENDENT_CODE=OFF \ "$@" cmake --build "$b" -j"$JOBS" cmake --install "$b" } build_mbedtls() { local f="mbedtls-$MBEDTLS_VER.tar.bz2" mapfile -t urls < <(gh "Mbed-TLS/mbedtls/releases/download/mbedtls-$MBEDTLS_VER/$f") fetch "$f" "$MBEDTLS_SHA" "${urls[@]}" unpack "$f" "mbedtls-$MBEDTLS_VER" # 3.6.x keeps its own entropy source on Android, no /dev/urandom probing. cmake_android "$WORK/mbedtls-$MBEDTLS_VER" "$WORK/mbedtls-$MBEDTLS_VER/build" \ -DENABLE_TESTING=OFF -DENABLE_PROGRAMS=OFF -DGEN_FILES=OFF \ -DUSE_STATIC_MBEDTLS_LIBRARY=ON -DUSE_SHARED_MBEDTLS_LIBRARY=OFF \ -DMBEDTLS_FATAL_WARNINGS=OFF echo "mbedTLS $MBEDTLS_VER -> $PREFIX" } build_curl() { local f="curl-$CURL_VER.tar.xz" mapfile -t urls < <(gh "curl/curl/releases/download/curl-${CURL_VER//./_}/$f") fetch "$f" "$CURL_SHA" "https://curl.se/download/$f" "${urls[@]}" unpack "$f" "curl-$CURL_VER" cmake_android "$WORK/curl-$CURL_VER" "$WORK/curl-$CURL_VER/build" \ -DBUILD_SHARED_LIBS=OFF -DBUILD_STATIC_LIBS=ON \ -DCURL_USE_MBEDTLS=ON -DCURL_USE_OPENSSL=OFF \ -DMBEDTLS_INCLUDE_DIR="$PREFIX/include" \ -DMBEDTLS_LIBRARY="$PREFIX/lib/libmbedtls.a" \ -DMBEDX509_LIBRARY="$PREFIX/lib/libmbedx509.a" \ -DMBEDCRYPTO_LIBRARY="$PREFIX/lib/libmbedcrypto.a" \ -DCURL_CA_BUNDLE=none -DCURL_CA_PATH="$CA_PATH" \ -DHTTP_ONLY=ON -DCURL_DISABLE_LDAP=ON -DCURL_USE_LIBPSL=OFF \ -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=OFF -DUSE_LIBIDN2=OFF \ -DUSE_NGHTTP2=OFF -DCURL_ZLIB=OFF -DCURL_BROTLI=OFF -DCURL_ZSTD=OFF \ -DCURL_USE_GSSAPI=OFF -DENABLE_THREADED_RESOLVER=ON \ -DBUILD_CURL_EXE=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF \ -DBUILD_LIBCURL_DOCS=OFF -DBUILD_MISC_DOCS=OFF -DENABLE_CURL_MANUAL=OFF echo "curl $CURL_VER -> $PREFIX" } case "${2:-all}" in mbedtls) build_mbedtls ;; curl) build_curl ;; all) build_mbedtls build_curl ;; *) echo "usage: $0 ABI [all|mbedtls|curl]" >&2 exit 1 ;; esac echo "DONE android-$ABI"