#!/bin/bash # Script to compile the native hooking library for Android set -euo pipefail PROJECT_DIR=$(cd "$(dirname "$0")/.." && pwd) SRC_DIR="$PROJECT_DIR/src" BUILD_DIR="$PROJECT_DIR/build" LIBS_DIR="$PROJECT_DIR/libs" API_LEVEL="${ANDROID_API_LEVEL:-21}" # Qt path detection QT_DIR="${QT_DIR:-$HOME/Qt}" QT_VERSION="${QT_VERSION:-6.10.2}" QT_HOST_DIR="$QT_DIR/$QT_VERSION/android_arm64_v8a" QT_LIB_DIR="$QT_HOST_DIR/lib" SO_NAME="librmhook.so" # --- Auto-detect Android NDK --- find_ndk() { if [ -n "${ANDROID_NDK_HOME:-}" ] && [ -d "$ANDROID_NDK_HOME" ]; then echo "$ANDROID_NDK_HOME"; return fi local brew_ndk brew_ndk=$(find /opt/homebrew /usr/local -path "*/android-ndk/*/toolchains/llvm/prebuilt" -type d 2>/dev/null | head -1) if [ -n "$brew_ndk" ]; then echo "$(dirname "$(dirname "$(dirname "$brew_ndk")")")"; return fi local sdk_ndk sdk_ndk=$(find "$HOME/Library/Android/sdk/ndk" -maxdepth 1 -type d 2>/dev/null | sort -V | tail -1) if [ -n "$sdk_ndk" ] && [ -d "$sdk_ndk" ]; then echo "$sdk_ndk"; return fi for p in /opt/android-ndk /usr/local/android-ndk "$HOME/android-ndk"; do if [ -d "$p" ]; then echo "$p"; return; fi done echo "" } NDK_HOME="$(find_ndk)" CC="" if [ -n "$NDK_HOME" ]; then CC=$(find "$NDK_HOME/toolchains/llvm/prebuilt" -type f \ -name "aarch64-linux-android${API_LEVEL}-clang" -print -quit 2>/dev/null) fi if [ -z "$CC" ]; then echo "❌ aarch64-linux-android clang not found." echo " Set ANDROID_NDK_HOME to your NDK path, or install via:" echo " brew install --cask android-ndk" exit 1 fi echo "🔨 Compiling $SO_NAME..." echo "📦 Qt path: $QT_HOST_DIR" echo "📦 NDK: $NDK_HOME" echo "" # Clean and create build directories rm -rf "$BUILD_DIR" mkdir -p "$BUILD_DIR" # --- Step 0: Build dependencies (shadowhook) --- echo "[0/2] Building hooking library (shadowhook)..." "$LIBS_DIR/build_deps.sh" # --- Step 1: Prepare Qt headers --- echo "[1/2] Preparing Qt headers..." if [ ! -d "$QT_HOST_DIR/include" ]; then echo "⚠️ Qt not found at $QT_HOST_DIR/include" echo " Install with: aqt install-qt all_os android $QT_VERSION -m qtwebsockets --outputdir $QT_DIR" exit 1 fi for qt_lib in \ "$QT_LIB_DIR/libQt6Core_arm64-v8a.so" \ "$QT_LIB_DIR/libQt6Network_arm64-v8a.so" \ "$QT_LIB_DIR/libQt6WebSockets_arm64-v8a.so"; do if [ ! -f "$qt_lib" ]; then echo "ERROR: Required Qt library not found: $qt_lib" exit 1 fi done QT_INCLUDES="-I$QT_HOST_DIR/include" for subdir in "$QT_HOST_DIR/include"/*/; do QT_INCLUDES="$QT_INCLUDES -I$subdir" done echo "✅ Qt headers ready at $QT_HOST_DIR" echo "✅ Qt libraries ready at $QT_LIB_DIR" # --- Step 2: Compile native hooking library --- echo "[2/2] Compiling $SO_NAME..." # shellcheck disable=SC2086 "$CC" -shared -fPIC -O2 -std=c++17 -stdlib=libc++ -fno-exceptions -fno-rtti \ -DQT_NO_VERSION_TAGGING \ -o "$BUILD_DIR/$SO_NAME" \ "$SRC_DIR/rmhook.cpp" \ "$SRC_DIR/Config.cpp" \ $QT_INCLUDES \ -I"$LIBS_DIR/shadowhook/shadowhook/src/main/cpp/include" \ -I"$SRC_DIR" \ -L"$LIBS_DIR" -lshadowhook \ -L"$QT_LIB_DIR" \ -Wl,--no-undefined \ -Wl,-z,defs \ -l:libQt6WebSockets_arm64-v8a.so \ -l:libQt6Network_arm64-v8a.so \ -l:libQt6Core_arm64-v8a.so \ -lc++_shared \ -llog -ldl -lm \ -Wno-incompatible-pointer-types echo "" echo "✅ Compilation successful!" echo "📍 Library: $BUILD_DIR/$SO_NAME ($(ls -lh "$BUILD_DIR/$SO_NAME" | awk '{print $5}'))" echo "" echo "🚀 To inject into the reMarkable application:" echo " ./script/inject.sh" echo ""