mirror of
https://github.com/ApfelTeeSaft/OpenRoyale.git
synced 2026-08-26 19:33:32 +00:00
88 lines
5.4 KiB
Bash
88 lines
5.4 KiB
Bash
#!/usr/bin/env bash
|
|
# build_native_direct.sh - build the required native libs for an ABI using the NDK clang DIRECTLY.
|
|
#
|
|
# We invoke the NDK's clang++ with a target triple instead of the CMake toolchain, because the NDK's
|
|
# build/cmake/ integration is not present in this checkout. Produces the three libs the app loads:
|
|
# libg.so - reconstructed Titan JNI skeleton (native/src/libg/**) [REAL reconstruction]
|
|
# libfmod.so- official arm64 binary if in native/third_party/fmod/<abi>/, else the fmod stub [stub]
|
|
# libcr.so - built from native/third_party/libcr/src if present (SONAME libmod.so), else stub [stub]
|
|
#
|
|
# Usage: build_native_direct.sh <arm64-v8a|armeabi-v7a> [minApi]
|
|
# Output: app/src/main/jniLibs/<abi>/ (for armeabi-v7a it will NOT overwrite the seeded ORIGINAL
|
|
# libs unless FORCE_V7A=1 - the original 32-bit engine is higher-fidelity than the skeleton).
|
|
set -euo pipefail
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJ="$(cd "$HERE/../.." && pwd)"
|
|
ABI="${1:?usage: build_native_direct.sh <arm64-v8a|armeabi-v7a> [minApi]}"
|
|
MINAPI="${2:-21}"
|
|
|
|
NDK="${ANDROID_NDK_HOME:-$PROJ/tools/android-sdk/ndk/26.3.11579264}"
|
|
TC="$NDK/toolchains/llvm/prebuilt/linux-x86_64"
|
|
CLANGXX="$TC/bin/clang++"; NM="$TC/bin/llvm-nm"
|
|
[ -x "$CLANGXX" ] || { echo "NDK clang++ not found at $CLANGXX"; exit 2; }
|
|
case "$ABI" in
|
|
arm64-v8a) TRIPLE="aarch64-linux-android${MINAPI}";;
|
|
armeabi-v7a) TRIPLE="armv7a-linux-androideabi${MINAPI}";;
|
|
*) echo "unsupported ABI '$ABI'"; exit 1;;
|
|
esac
|
|
|
|
DEST="$PROJ/app/src/main/jniLibs/$ABI"; mkdir -p "$DEST"
|
|
B="$PROJ/.build/native/$ABI"; rm -rf "$B"; mkdir -p "$B"
|
|
# -static-libstdc++ links libc++ statically so the reconstructed libg.so is SELF-CONTAINED (no
|
|
# NEEDED libc++_shared.so). libc++_shared.so is NOT a system library on Android, and we don't bundle
|
|
# it - without static libc++ the app would UnsatisfiedLinkError at load. The original engine linked
|
|
# the on-device system libstdc++.so; static libc++ is the modern, bundle-free equivalent.
|
|
CXXFLAGS=(--target="$TRIPLE" -fPIC -shared -std=c++17 -O2 -fexceptions -frtti -static-libstdc++
|
|
-I "$PROJ/native/include" -I "$PROJ/native/third_party/fmod/include")
|
|
echo "==> Native build $ABI ($TRIPLE), NDK r26d clang"
|
|
|
|
# --- libg: the reconstructed engine JNI skeleton (always rebuilt) ---
|
|
# The FMOD 1.05.11 headers are on the include path so the reconstructed audio subsystem compiles.
|
|
# We link the real libfmod.so ONLY once libg actually references FMOD (matching the original's
|
|
# NEEDED libfmod.so). NOTE: the old FMOD .so has a legacy symbol table modern lld rejects for direct
|
|
# linking, so when FMOD calls appear we link via a clean import stub (native/third_party/fmod/import)
|
|
# generated by gen_fmod_import.sh; at runtime the real libfmod.so resolves them.
|
|
mapfile -t LIBG_SRC < <(find "$PROJ/native/src/libg" -name '*.cpp')
|
|
FMOD_LINK=()
|
|
if grep -rqlE '\bFMOD_|FMOD::' "$PROJ/native/src/libg" 2>/dev/null; then
|
|
IMPORT="$PROJ/native/third_party/fmod/import/$ABI/libfmod.so"
|
|
# auto-generate the link-clean FMOD import stub if missing (and the real lib is present)
|
|
if [ ! -f "$IMPORT" ] && [ -f "$PROJ/native/third_party/fmod/$ABI/libfmod.so" ]; then
|
|
ANDROID_NDK_HOME="$NDK" bash "$HERE/gen_fmod_import.sh" "$ABI" >/dev/null 2>&1 || true
|
|
fi
|
|
if [ -f "$IMPORT" ]; then FMOD_LINK=(-L "$PROJ/native/third_party/fmod/import/$ABI" -lfmod); \
|
|
else echo " (WARN: libg references FMOD but no import stub could be generated)"; fi
|
|
fi
|
|
"$CLANGXX" "${CXXFLAGS[@]}" "${LIBG_SRC[@]}" "${FMOD_LINK[@]}" -llog -landroid -o "$B/libg.so"
|
|
echo " libg.so : $("$NM" -D --defined-only "$B/libg.so" | grep -cE 'Java_com_supercell|JNI_OnLoad') JNI exports"
|
|
|
|
# --- libfmod: official binary if present, else stub ---
|
|
if [ -f "$PROJ/native/third_party/fmod/$ABI/libfmod.so" ]; then
|
|
cp "$PROJ/native/third_party/fmod/$ABI/libfmod.so" "$B/libfmod.so"; echo " libfmod.so: official arm64 binary"
|
|
else
|
|
"$CLANGXX" "${CXXFLAGS[@]}" -Wl,-soname,libfmod.so \
|
|
"$PROJ/native/compatibility/fmod_shim/fmod_stub.cpp" -llog -o "$B/libfmod.so"; echo " libfmod.so: STUB (audio disabled)"
|
|
fi
|
|
|
|
# --- libcr: OPTIONAL. Built ONLY if the OWNED source is present (SONAME libmod.so like the original).
|
|
# If no source is provided, libcr is simply omitted - the app's System.loadLibrary("cr") is wrapped in
|
|
# catch(UnsatisfiedLinkError), so a missing libcr is tolerated (mod features just absent). ---
|
|
mapfile -t LIBCR_SRC < <(find "$PROJ/native/third_party/libcr/src" \( -name '*.c' -o -name '*.cpp' \) 2>/dev/null || true)
|
|
if [ "${#LIBCR_SRC[@]}" -gt 0 ]; then
|
|
"$CLANGXX" "${CXXFLAGS[@]}" -Wl,-soname,libmod.so -I "$PROJ/native/third_party/libcr/include" \
|
|
"${LIBCR_SRC[@]}" -llog -lz -landroid -o "$B/libcr.so"; echo " libcr.so : built from OWNED source"
|
|
else
|
|
echo " libcr.so : (omitted - no source in native/third_party/libcr/src; loadLibrary(\"cr\") is optional)"
|
|
fi
|
|
|
|
# --- publish to jniLibs ---
|
|
if [ "$ABI" = armeabi-v7a ] && [ -f "$DEST/libg.so" ] && [ "${FORCE_V7A:-0}" != 1 ]; then
|
|
echo " (armeabi-v7a: keeping seeded ORIGINAL libs in jniLibs; set FORCE_V7A=1 to overwrite with reconstruction)"
|
|
else
|
|
# We fully own this ABI dir - clear the libs we manage so a now-omitted optional lib (e.g. libcr
|
|
# when no source is present) does not linger from a previous run.
|
|
rm -f "$DEST/libg.so" "$DEST/libfmod.so" "$DEST/libcr.so"
|
|
cp "$B"/*.so "$DEST/"
|
|
echo " -> published to jniLibs/$ABI/:"; for f in "$DEST"/*.so; do echo " $(basename "$f") [$(file -b "$f" | cut -d, -f1-2)]"; done
|
|
fi
|