#!/bin/bash # Build OpenSSL static libraries for Android targets # This is needed because libsqlite3-sys (SQLCipher) requires libcrypto, # and Android doesn't ship a system libcrypto.so. set -eo pipefail print_step() { echo -e "\n\033[1;34m=== $1 ===\033[0m" } print_success() { echo -e "\033[1;32m$1\033[0m" } print_error() { echo -e "\033[1;31m$1\033[0m" } # Spinner for long-running commands # Usage: run_quiet "description" logfile command [args...] run_quiet() { local desc="$1" local logfile="$2" shift 2 printf " %-40s " "$desc" # Run command in background with output redirected to log file "$@" >>"$logfile" 2>&1 & local pid=$! local spin='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' local i=0 while kill -0 "$pid" 2>/dev/null; do printf "\b%s" "${spin:i++%${#spin}:1}" sleep 0.1 done wait "$pid" local exit_code=$? if [ $exit_code -eq 0 ]; then printf "\b\033[1;32m✓\033[0m\n" else printf "\b\033[1;31m✗\033[0m\n" print_error "Command failed. Last 20 lines of log:" tail -20 "$logfile" print_error "Full log: $logfile" exit 1 fi } # Configuration OPENSSL_VERSION="3.4.1" OPENSSL_SHA256="002a2d6b30b58bf4bea46c43bdd96365aaf8daa6c428782aa4feee06da197df3" ANDROID_API=33 # Resolve paths SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" OPENSSL_BUILD_DIR="$PROJECT_ROOT/rust/target/openssl" OPENSSL_SRC_DIR="$OPENSSL_BUILD_DIR/openssl-$OPENSSL_VERSION" OPENSSL_INSTALL_DIR="$OPENSSL_BUILD_DIR/install" # Auto-detect Android NDK if [ -z "$ANDROID_NDK_HOME" ]; then if [ -n "$NDK_HOME" ]; then ANDROID_NDK_HOME="$NDK_HOME" elif [ -n "$ANDROID_HOME" ]; then NDK_DIR="$ANDROID_HOME/ndk" if [ -d "$NDK_DIR" ]; then NDK_VERSION=$(ls "$NDK_DIR" | sort -V | tail -n 1) if [ -n "$NDK_VERSION" ]; then ANDROID_NDK_HOME="$NDK_DIR/$NDK_VERSION" fi fi fi fi if [ -z "$ANDROID_NDK_HOME" ] || [ ! -d "$ANDROID_NDK_HOME" ]; then print_error "Android NDK not found. Set ANDROID_NDK_HOME or NDK_HOME." exit 1 fi # Detect host OS case "$(uname -s)" in Darwin*) case "$(uname -m)" in arm64 | aarch64) HOST_TAG="darwin-arm64" ;; *) HOST_TAG="darwin-x86_64" ;; esac ;; Linux*) HOST_TAG="linux-x86_64" ;; *) print_error "Unsupported host OS: $(uname -s)" exit 1 ;; esac TOOLCHAIN="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$HOST_TAG" # Target configurations: (rust_target openssl_target arch) TARGETS=( "aarch64-linux-android:android-arm64:aarch64" "armv7-linux-androideabi:android-arm:armv7a" "x86_64-linux-android:android-x86_64:x86_64" ) build_openssl_for_target() { local rust_target="$1" local openssl_target="$2" local arch="$3" local install_prefix="$OPENSSL_INSTALL_DIR/$rust_target" # Skip if already built if [ -f "$install_prefix/lib/libcrypto.a" ]; then print_success "OpenSSL already built for $rust_target (skipping)" return 0 fi print_step "Building OpenSSL for $rust_target ($openssl_target)" # Clean and re-extract source for each target (OpenSSL doesn't support out-of-tree builds well) local build_src="$OPENSSL_BUILD_DIR/build-$rust_target" local logfile="$OPENSSL_BUILD_DIR/$rust_target.log" rm -rf "$build_src" : >"$logfile" cp -r "$OPENSSL_SRC_DIR" "$build_src" cd "$build_src" export ANDROID_NDK_ROOT="$ANDROID_NDK_HOME" export PATH="$TOOLCHAIN/bin:$PATH" run_quiet "Configuring ($openssl_target)..." "$logfile" \ ./Configure "$openssl_target" \ -D__ANDROID_API__=$ANDROID_API \ --prefix="$install_prefix" \ --openssldir="$install_prefix/ssl" \ no-shared \ no-tests \ no-ui-console \ no-stdio \ -fPIC run_quiet "Compiling..." "$logfile" \ make -j"$(nproc 2>/dev/null || sysctl -n hw.ncpu)" build_libs run_quiet "Installing headers & libs..." "$logfile" \ make install_dev cd "$PROJECT_ROOT" rm -rf "$build_src" if [ -f "$install_prefix/lib/libcrypto.a" ]; then print_success " Built OpenSSL for $rust_target" else print_error "Failed to build OpenSSL for $rust_target" print_error "Check log: $logfile" exit 1 fi } # Download OpenSSL source if needed if [ ! -d "$OPENSSL_SRC_DIR" ]; then print_step "Downloading OpenSSL $OPENSSL_VERSION" mkdir -p "$OPENSSL_BUILD_DIR" cd "$OPENSSL_BUILD_DIR" TARBALL="openssl-$OPENSSL_VERSION.tar.gz" if [ ! -f "$TARBALL" ]; then curl -L --progress-bar -o "$TARBALL" "https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/$TARBALL" fi print_step "Verifying tarball integrity" if command -v shasum >/dev/null 2>&1; then ACTUAL_SHA256=$(shasum -a 256 "$TARBALL" | awk '{print $1}') elif command -v sha256sum >/dev/null 2>&1; then ACTUAL_SHA256=$(sha256sum "$TARBALL" | awk '{print $1}') else print_error "No SHA-256 tool found (need shasum or sha256sum)" exit 1 fi if [ "$ACTUAL_SHA256" != "$OPENSSL_SHA256" ]; then print_error "SHA-256 mismatch for $TARBALL" print_error " Expected: $OPENSSL_SHA256" print_error " Actual: $ACTUAL_SHA256" rm -f "$TARBALL" exit 1 fi print_success "SHA-256 verified" tar xzf "$TARBALL" cd "$PROJECT_ROOT" fi # Build for each target for target_spec in "${TARGETS[@]}"; do IFS=':' read -r rust_target openssl_target arch <<<"$target_spec" build_openssl_for_target "$rust_target" "$openssl_target" "$arch" done print_success "All OpenSSL Android builds complete!" echo "Install directory: $OPENSSL_INSTALL_DIR"