99 lines
4.6 KiB
Bash
99 lines
4.6 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# Cross-compiles better-sqlite3 for the embedded Node 18.20.4 (nodejs-mobile) ABI
|
||
|
|
# for all three Android ABIs and writes the resulting better_sqlite3.node binaries
|
||
|
|
# into nodejs-assets/nodejs-project/prebuilds/<abi>/. main.js installs the one
|
||
|
|
# matching the device's actual process.arch at runtime — see
|
||
|
|
# installBetterSqlite3Prebuild().
|
||
|
|
#
|
||
|
|
# Unlike the old Node-12 build, NO binder.cpp patch is needed: Node 18's V8 10.2
|
||
|
|
# still exposes the (deprecated) v8::Object::CreationContext() that better-sqlite3
|
||
|
|
# 12.x uses, so it compiles as-is (deprecation warning only).
|
||
|
|
#
|
||
|
|
# Requires: Android NDK (ANDROID_HOME or ANDROID_NDK_HOME set), the Node 18 runtime
|
||
|
|
# staged into the plugin (scripts/install-node18-runtime.sh), and `npm install`
|
||
|
|
# already run in nodejs-assets/nodejs-project.
|
||
|
|
#
|
||
|
|
# Usage: ./scripts/build-better-sqlite3-node18.sh [abi ...] (default: all three)
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
NODE_TARGET="18.20.4"
|
||
|
|
API=24 # matches android/variables.gradle minSdkVersion
|
||
|
|
|
||
|
|
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%/}"
|
||
|
|
|
||
|
|
[[ -d "$PKG_SRC" ]] || { echo "Error: $PKG_SRC not found. Run npm install in nodejs-project first." >&2; exit 1; }
|
||
|
|
[[ -n "$NDK" && -d "$NDK" ]] || { echo "Error: Android NDK not found (set ANDROID_NDK_HOME or ANDROID_HOME)." >&2; exit 1; }
|
||
|
|
[[ -x "$GYP" ]] || { echo "Error: $GYP not found. Run npm install in nodejs-project first." >&2; exit 1; }
|
||
|
|
grep -q "18" "$NODEDIR/include/node/node_version.h" || { echo "Error: $NODEDIR is not the Node 18 runtime — run scripts/install-node18-runtime.sh first." >&2; exit 1; }
|
||
|
|
|
||
|
|
TOOLCHAIN="$NDK/toolchains/llvm/prebuilt/linux-x86_64"
|
||
|
|
|
||
|
|
abi_arch() { case "$1" in arm64-v8a) echo arm64;; armeabi-v7a) echo arm;; x86_64) echo x64;; *) echo "" ;; esac; }
|
||
|
|
abi_cc() { case "$1" in
|
||
|
|
arm64-v8a) echo "aarch64-linux-android${API}-clang" ;;
|
||
|
|
armeabi-v7a) echo "armv7a-linux-androideabi${API}-clang" ;;
|
||
|
|
x86_64) echo "x86_64-linux-android${API}-clang" ;;
|
||
|
|
esac; }
|
||
|
|
|
||
|
|
build_one() {
|
||
|
|
local abi="$1"
|
||
|
|
local gyp_arch cc cxx
|
||
|
|
gyp_arch="$(abi_arch "$abi")"; cc="$(abi_cc "$abi")"; cxx="${cc}++"
|
||
|
|
[[ -n "$gyp_arch" ]] || { echo "Unknown ABI: $abi" >&2; exit 1; }
|
||
|
|
|
||
|
|
# better-sqlite3's binding.gyp (via nodejs-mobile's common.gypi) needs the real
|
||
|
|
# libnode.so (not the .gz) to add it as a NEEDED entry at link time.
|
||
|
|
local 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
|
||
|
|
|
||
|
|
local build_dir="$MOBILE_DIR/build-output/better-sqlite3-$abi"
|
||
|
|
echo "── Building better-sqlite3 for $abi ($gyp_arch) against Node $NODE_TARGET ──"
|
||
|
|
rm -rf "$build_dir"; mkdir -p "$build_dir"
|
||
|
|
rsync -a --exclude=build --exclude=prebuilds "$PKG_SRC/" "$build_dir/"
|
||
|
|
|
||
|
|
(
|
||
|
|
cd "$build_dir"
|
||
|
|
CC="$TOOLCHAIN/bin/$cc" CXX="$TOOLCHAIN/bin/$cxx" AR="$TOOLCHAIN/bin/llvm-ar" \
|
||
|
|
GYP_DEFINES="OS=android" "$GYP" configure \
|
||
|
|
--target="$NODE_TARGET" --arch="$gyp_arch" --nodedir="$NODEDIR"
|
||
|
|
|
||
|
|
# nodejs-mobile's common.gypi only adds libnode.so as a NEEDED entry when
|
||
|
|
# target_arch=="x86_64", but gyp reports "x64" — so the rule never fires and
|
||
|
|
# the addon can't resolve V8/Node symbols (e.g. v8::Isolate::GetCurrent) at
|
||
|
|
# dlopen time on Android. Inject the ABI's libnode.so into the link so its
|
||
|
|
# SONAME (libnode.so) is recorded as NEEDED. (patchelf isn't required.)
|
||
|
|
local mk="build/better_sqlite3.target.mk"
|
||
|
|
if [[ -f "$mk" ]] && ! grep -q 'libnode\.so' "$mk"; then
|
||
|
|
sed -i "s#^\([[:space:]]*\)-llog\$#\1-llog $libnode_dir/libnode.so#" "$mk"
|
||
|
|
grep -q 'libnode\.so' "$mk" || { echo "Error: failed to inject libnode.so into $mk" >&2; exit 1; }
|
||
|
|
fi
|
||
|
|
|
||
|
|
CC="$TOOLCHAIN/bin/$cc" CXX="$TOOLCHAIN/bin/$cxx" AR="$TOOLCHAIN/bin/llvm-ar" \
|
||
|
|
make -C build BUILDTYPE=Release
|
||
|
|
)
|
||
|
|
|
||
|
|
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"
|
||
|
|
}
|
||
|
|
|
||
|
|
ABIS=("$@")
|
||
|
|
[[ ${#ABIS[@]} -eq 0 ]] && ABIS=(x86_64 arm64-v8a armeabi-v7a)
|
||
|
|
for abi in "${ABIS[@]}"; do build_one "$abi"; done
|
||
|
|
|
||
|
|
echo "Done. Verify with: file $PREBUILDS_DIR/*/better_sqlite3.node"
|