#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$SCRIPT_DIR" SDK_DIR="$PROJECT_DIR/android-sdk" NDK_DIR="$SDK_DIR/ndk/27.2.12479018" TOOLBIN="$NDK_DIR/toolchains/llvm/prebuilt/linux-x86_64/bin" TMP_DIR="$PROJECT_DIR/.tmp-android-build" GIT_SRC_DIR="$TMP_DIR/git-src" HOST_GIT_DIR="$PROJECT_DIR/build/host-git" HOST_GIT_BINARY="$HOST_GIT_DIR/libgit.so" ANDROID_JNI_DIR="$PROJECT_DIR/app/src/main/jniLibs" ANDROID_API=24 log() { printf '\n[%s] %s\n' "compile-git" "$1" } require_path() { if [ ! -e "$1" ]; then echo "Required path not found: $1" >&2 exit 1 fi } require_tool() { if ! command -v "$1" >/dev/null 2>&1; then echo "Missing required tool: $1" >&2 exit 1 fi } ensure_git_source() { mkdir -p "$TMP_DIR" if [ ! -d "$GIT_SRC_DIR/.git" ]; then log "Cloning Git source" git clone --depth 1 https://github.com/git/git.git "$GIT_SRC_DIR" else log "Using existing Git source checkout" fi } common_git_make_args() { printf '%s\n' \ NO_OPENSSL=YesPlease \ NO_CURL=YesPlease \ NO_EXPAT=YesPlease \ NO_GETTEXT=YesPlease \ NO_TCLTK=YesPlease \ NO_PERL=YesPlease \ NO_PYTHON=YesPlease \ NO_INSTALL_HARDLINKS=YesPlease \ NO_ICONV=YesPlease \ NO_REGEX=NeedsStartEnd \ HAVE_ALLOCA_H=YesPlease \ HAVE_PATHS_H=YesPlease \ HAVE_CLOCK_GETTIME=YesPlease \ HAVE_CLOCK_MONOTONIC=YesPlease \ HAVE_GETDELIM=YesPlease \ FREAD_READS_DIRECTORIES=UnfortunatelyYes \ CSPRNG_METHOD= } build_host_git() { log "Building Git for development host" cd "$GIT_SRC_DIR" make clean >/dev/null 2>&1 || true mapfile -t make_args < <(common_git_make_args) make -j"$(nproc 2>/dev/null || printf 4)" "${make_args[@]}" git mkdir -p "$HOST_GIT_DIR" cp git "$HOST_GIT_BINARY" chmod 755 "$HOST_GIT_BINARY" log "Host test Git binary: $HOST_GIT_BINARY" "$HOST_GIT_BINARY" --version } build_android_git_for_abi() { local abi="$1" local cc="$2" local output_dir="$ANDROID_JNI_DIR/$abi" require_path "$TOOLBIN/${cc}" log "Building Git for Android $abi" cd "$GIT_SRC_DIR" make clean >/dev/null 2>&1 || true mapfile -t make_args < <(common_git_make_args) make -j"$(nproc 2>/dev/null || printf 4)" \ uname_S=Android \ uname_O=Android \ NO_PTHREADS=YesPlease \ NO_LIBGEN_H=YesPlease \ HAVE_DEV_TTY=YesPlease \ CC="$cc" \ AR=llvm-ar \ RANLIB=llvm-ranlib \ STRIP=llvm-strip \ "${make_args[@]}" \ git log "Validating Android $abi binary" file git readelf -h git | sed -n '1,12p' mkdir -p "$output_dir" llvm-strip -s git -o "$output_dir/libgit.so" chmod 755 "$output_dir/libgit.so" ls -lh "$output_dir/libgit.so" } build_android_git() { require_path "$NDK_DIR" export PATH="$TOOLBIN:$PATH" build_android_git_for_abi "arm64-v8a" "aarch64-linux-android${ANDROID_API}-clang" build_android_git_for_abi "armeabi-v7a" "armv7a-linux-androideabi${ANDROID_API}-clang" build_android_git_for_abi "x86" "i686-linux-android${ANDROID_API}-clang" build_android_git_for_abi "x86_64" "x86_64-linux-android${ANDROID_API}-clang" } print_usage() { cat <&2 print_usage >&2 exit 1 ;; esac require_tool git require_tool make require_tool perl require_tool clang require_tool pkg-config require_tool readelf ensure_git_source case "${1:---all}" in --host) build_host_git ;; --android) build_android_git ;; --all) build_host_git build_android_git ;; esac } main "$@"