#!/usr/bin/env bash # Cross-compiles better-sqlite3 for arm64-v8a and armeabi-v7a (real Android # devices) and writes the resulting better_sqlite3.node binaries into # nodejs-assets/nodejs-project/prebuilds//. main.js installs the one # matching the device's actual process.arch at runtime — see main.js's # installBetterSqlite3Prebuild(). # # The existing x86_64 build (emulator) in # nodejs-assets/nodejs-project/node_modules/better-sqlite3/build/Release/ # already covers nodejs-assets/nodejs-project/prebuilds/x86_64/ via # fix-better-sqlite3-android.sh; re-copy it manually if that build changes: # cp nodejs-assets/nodejs-project/node_modules/better-sqlite3/build/Release/better_sqlite3.node \ # nodejs-assets/nodejs-project/prebuilds/x86_64/ # # Requires: Android NDK (ANDROID_HOME or ANDROID_NDK_HOME set), and # `npm install` already run in nodejs-assets/nodejs-project (so # better-sqlite3's source + nodejs-mobile-gyp are present). # # Usage: ./scripts/build-better-sqlite3-arm.sh set -euo pipefail MOBILE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" PKG_SRC="$MOBILE_DIR/nodejs-assets/nodejs-project/node_modules/better-sqlite3" PREBUILDS_DIR="$MOBILE_DIR/nodejs-assets/nodejs-project/prebuilds" GYP="$MOBILE_DIR/nodejs-assets/nodejs-project/node_modules/.bin/nodejs-mobile-gyp" NODEDIR="$MOBILE_DIR/node_modules/nodejs-mobile-cordova/libs/android/libnode" NDK="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-}}" if [[ -z "$NDK" ]]; then SDK="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}" [[ -n "$SDK" ]] && NDK="$(ls -d "$SDK"/ndk/*/ 2>/dev/null | sort -V | tail -1)" fi NDK="${NDK%/}" if [[ ! -d "$PKG_SRC" ]]; then echo "Error: $PKG_SRC not found. Run npm install in nodejs-assets/nodejs-project first." >&2 exit 1 fi if [[ -z "$NDK" || ! -d "$NDK" ]]; then echo "Error: Android NDK not found. Set ANDROID_NDK_HOME (or ANDROID_HOME with an ndk/ subdir)." >&2 exit 1 fi if [[ ! -x "$GYP" ]]; then echo "Error: $GYP not found. Run npm install in nodejs-assets/nodejs-project first." >&2 exit 1 fi TOOLCHAIN="$NDK/toolchains/llvm/prebuilt/linux-x86_64" API=24 # matches android/variables.gradle minSdkVersion # Each ABI's libnode.so ships gzipped; better-sqlite3's binding.gyp (via # nodejs-mobile's common.gypi) needs the real .so to add it as a NEEDED entry. for abi in arm64-v8a armeabi-v7a; do LIBNODE_DIR="$NODEDIR/bin/$abi" if [[ ! -f "$LIBNODE_DIR/libnode.so" && -f "$LIBNODE_DIR/libnode.so.gz" ]]; then gunzip -k "$LIBNODE_DIR/libnode.so.gz" fi done build_one() { local abi="$1" gyp_arch="$2" cc="$3" cxx="$4" local build_dir="$MOBILE_DIR/build-output/better-sqlite3-$abi" echo "── Building better-sqlite3 for $abi ($gyp_arch) ──" rm -rf "$build_dir" mkdir -p "$build_dir" rsync -a --exclude=build --exclude=prebuilds "$PKG_SRC/" "$build_dir/" # v8::Object::CreationContext() was removed in newer V8; nodejs-mobile's # bundled V8 (Node 12.19) only has the old non-checked accessor. Same patch # as fix-better-sqlite3-android.sh. sed -i 's/obj->GetCreationContext().ToLocalChecked()/obj->CreationContext()/' \ "$build_dir/src/util/binder.cpp" ( cd "$build_dir" CC="$TOOLCHAIN/bin/$cc" \ CXX="$TOOLCHAIN/bin/$cxx" \ AR="$TOOLCHAIN/bin/llvm-ar" \ GYP_DEFINES="OS=android" \ "$GYP" configure --target=12.19.0 --arch="$gyp_arch" --nodedir="$NODEDIR" CC="$TOOLCHAIN/bin/$cc" \ CXX="$TOOLCHAIN/bin/$cxx" \ AR="$TOOLCHAIN/bin/llvm-ar" \ "$GYP" build ) mkdir -p "$PREBUILDS_DIR/$abi" cp "$build_dir/build/Release/better_sqlite3.node" "$PREBUILDS_DIR/$abi/better_sqlite3.node" echo "Wrote $PREBUILDS_DIR/$abi/better_sqlite3.node" } build_one arm64-v8a arm64 aarch64-linux-android${API}-clang aarch64-linux-android${API}-clang++ build_one armeabi-v7a arm armv7a-linux-androideabi${API}-clang armv7a-linux-androideabi${API}-clang++ echo "Done. Verify with: file $PREBUILDS_DIR/*/better_sqlite3.node"