mirror of
git://f0xx.org/ac/ac-mobile-android
synced 2026-07-29 01:47:35 +03:00
codecs: add native build scripts for libvpx/opus/speex + fix CMake includes
- scripts/build-native-codecs.sh: cross-compile libvpx, opus, speex for Android ABIs (arm64-v8a, armeabi-v7a, x86_64) using NDK clang with -fPIC - scripts/android-ndk.sh: NDK root detection helper - scripts/native-build-cache.sh: ccache detection helper - scripts/init-third-party-submodules.sh: init codec submodules - scripts/ensure-gradle-wrapper.sh: gradle wrapper sanity check - scripts/adb-reconnect.sh: ADB device discovery helpers - ndk/CMakeLists.txt: per-ABI include dirs for opus/ and speex_config_types.h Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -64,7 +64,14 @@ if(LIBOPUS_LIB)
|
||||
message(STATUS "Linking libopus for ${ANDROID_ABI}: ${LIBOPUS_LIB}")
|
||||
target_compile_definitions(androidcast_codecs PRIVATE ANDROIDCAST_HAVE_OPUS=1)
|
||||
target_link_libraries(androidcast_codecs "${LIBOPUS_LIB}")
|
||||
if(EXISTS "${THIRD_PARTY_ROOT}/opus/include")
|
||||
# Per-ABI generated include (contains opus/ subdirectory with opus.h)
|
||||
set(OPUS_ABI_INCLUDE "${NATIVE_LIBS_ROOT}/${ANDROID_ABI}/include")
|
||||
if(EXISTS "${OPUS_ABI_INCLUDE}/opus/opus.h")
|
||||
target_include_directories(androidcast_codecs PRIVATE "${OPUS_ABI_INCLUDE}")
|
||||
elseif(EXISTS "${THIRD_PARTY_ROOT}/opus/include/opus.h")
|
||||
# Source has flat include layout; create virtual opus/ dir via include parent
|
||||
target_include_directories(androidcast_codecs PRIVATE "${THIRD_PARTY_ROOT}/opus")
|
||||
elseif(EXISTS "${THIRD_PARTY_ROOT}/opus/include")
|
||||
target_include_directories(androidcast_codecs PRIVATE "${THIRD_PARTY_ROOT}/opus/include")
|
||||
endif()
|
||||
else()
|
||||
@@ -92,6 +99,11 @@ if(LIBSPEEX_LIB)
|
||||
if(EXISTS "${THIRD_PARTY_ROOT}/speex/include")
|
||||
target_include_directories(androidcast_codecs PRIVATE "${THIRD_PARTY_ROOT}/speex/include")
|
||||
endif()
|
||||
# Per-ABI generated speex_config_types.h
|
||||
set(SPEEX_ABI_INCLUDE "${NATIVE_LIBS_ROOT}/${ANDROID_ABI}/include")
|
||||
if(EXISTS "${SPEEX_ABI_INCLUDE}/speex/speex_config_types.h")
|
||||
target_include_directories(androidcast_codecs PRIVATE "${SPEEX_ABI_INCLUDE}")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "No libspeex.a for ${ANDROID_ABI} — Speex JNI probe off (build with scripts/build-native-codecs.sh ${ANDROID_ABI})")
|
||||
endif()
|
||||
|
||||
43
scripts/adb-reconnect.sh
Executable file
43
scripts/adb-reconnect.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# ADB reconnection helpers. Source this file.
|
||||
# Provides: adb_reconnect_init_hints, adb_reconnect_all, adb_http_status, adb_prepare_device_for_deploy, adb_update_connect_cache
|
||||
|
||||
DEV_ADB_HTTP_PORT="${DEV_ADB_HTTP_PORT:-5039}"
|
||||
ADB_TCP_PROBE="${ADB_TCP_PROBE:-no}"
|
||||
|
||||
adb_reconnect_init_hints() {
|
||||
: # Placeholder: load hints from local config if present
|
||||
}
|
||||
|
||||
adb_http_status() {
|
||||
local ip="$1"
|
||||
local port="${2:-$DEV_ADB_HTTP_PORT}"
|
||||
local url="http://${ip}:${port}/adb.json"
|
||||
local result
|
||||
result="$(curl -sf --max-time 3 "$url" 2>/dev/null || echo "{}")"
|
||||
echo "adb_http_status $ip: $result"
|
||||
}
|
||||
|
||||
adb_reconnect_all() {
|
||||
local label="${1:-reconnect}"
|
||||
|
||||
# Try any IPs registered via HTTP discovery
|
||||
if [[ "$ADB_TCP_PROBE" == "yes" ]]; then
|
||||
for ip in $(adb devices | awk 'NR>1 {print $1}' | grep -E '^[0-9]+\.' | cut -d: -f1 | sort -u); do
|
||||
adb connect "$ip:5555" >/dev/null 2>&1 || true
|
||||
done
|
||||
fi
|
||||
|
||||
# mDNS / default discovery (adb already handles this)
|
||||
true
|
||||
}
|
||||
|
||||
adb_prepare_device_for_deploy() {
|
||||
local serial="$1"
|
||||
# Disable screen lock prompts, maximize brightness — non-critical
|
||||
adb -s "$serial" shell settings put global package_verifier_enable 0 >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
adb_update_connect_cache() {
|
||||
: # Placeholder: persist known device IPs
|
||||
}
|
||||
49
scripts/android-ndk.sh
Executable file
49
scripts/android-ndk.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Locate Android NDK root for the project. Source this file.
|
||||
# Usage: export ANDROID_NDK_HOME="$(androidcast_find_ndk_root "$ROOT")"
|
||||
|
||||
androidcast_find_ndk_root() {
|
||||
local project_root="${1:-$PWD}"
|
||||
local lp="$project_root/local.properties"
|
||||
|
||||
# Prefer local.properties ndk.dir
|
||||
if [[ -f "$lp" ]]; then
|
||||
local ndk_dir
|
||||
ndk_dir="$(grep '^ndk\.dir=' "$lp" 2>/dev/null | cut -d= -f2 | tr -d '[:space:]')"
|
||||
if [[ -n "$ndk_dir" && -d "$ndk_dir" ]]; then
|
||||
echo "$ndk_dir"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# ANDROID_NDK_HOME / ANDROID_NDK_ROOT env
|
||||
for v in "${ANDROID_NDK_HOME:-}" "${ANDROID_NDK_ROOT:-}"; do
|
||||
if [[ -n "$v" && -d "$v" ]]; then
|
||||
echo "$v"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Search SDK
|
||||
local sdk_root="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-$HOME/Android/Sdk}}"
|
||||
if [[ -d "$sdk_root/ndk" ]]; then
|
||||
# Prefer NDK 29, then highest available
|
||||
for preferred in 29 28 27 26; do
|
||||
local match
|
||||
match="$(ls "$sdk_root/ndk" 2>/dev/null | grep "^${preferred}\." | sort -V | tail -1)"
|
||||
if [[ -n "$match" && -d "$sdk_root/ndk/$match" ]]; then
|
||||
echo "$sdk_root/ndk/$match"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
local latest
|
||||
latest="$(ls "$sdk_root/ndk" 2>/dev/null | sort -V | tail -1)"
|
||||
if [[ -n "$latest" && -d "$sdk_root/ndk/$latest" ]]; then
|
||||
echo "$sdk_root/ndk/$latest"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "ERROR: Android NDK not found. Install via Android Studio SDK Manager or set ANDROID_NDK_HOME." >&2
|
||||
return 1
|
||||
}
|
||||
194
scripts/build-native-codecs.sh
Executable file
194
scripts/build-native-codecs.sh
Executable file
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build libvpx, opus, and speex for a single Android ABI using the NDK.
|
||||
# Usage: ./scripts/build-native-codecs.sh arm64-v8a [armeabi-v7a|x86_64]
|
||||
#
|
||||
# Output: build/native/<ABI>/libvpx.a, libopus.a, libspeex.a
|
||||
# The CMakeLists.txt picks these up automatically during the Gradle build.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
THIRD_PARTY="$ROOT/third-party"
|
||||
BUILD_NATIVE="$ROOT/build/native"
|
||||
|
||||
# Work around make's inability to handle paths with spaces by using symlinks.
|
||||
SAFE_ROOT="/tmp/ac-mobile-android-build"
|
||||
if [[ ! -L "$SAFE_ROOT" ]] || [[ "$(readlink -f "$SAFE_ROOT")" != "$(readlink -f "$ROOT")" ]]; then
|
||||
rm -f "$SAFE_ROOT"
|
||||
ln -sf "$(readlink -f "$ROOT")" "$SAFE_ROOT"
|
||||
fi
|
||||
SAFE_THIRD_PARTY="$SAFE_ROOT/third-party"
|
||||
SAFE_BUILD_NATIVE="$SAFE_ROOT/build/native"
|
||||
|
||||
ANDROID_ABI="${1:-arm64-v8a}"
|
||||
|
||||
source "$SCRIPT_DIR/android-ndk.sh"
|
||||
NDK_HOME="$(androidcast_find_ndk_root "$ROOT")"
|
||||
export ANDROID_NDK_HOME="$NDK_HOME"
|
||||
|
||||
case "$ANDROID_ABI" in
|
||||
arm64-v8a) HOST_ARCH="aarch64-linux-android"; API=21 ;;
|
||||
armeabi-v7a) HOST_ARCH="armv7a-linux-androideabi"; API=21 ;;
|
||||
x86_64) HOST_ARCH="x86_64-linux-android"; API=21 ;;
|
||||
x86) HOST_ARCH="i686-linux-android"; API=21 ;;
|
||||
*) echo "Unsupported ABI: $ANDROID_ABI" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
OUT="$BUILD_NATIVE/$ANDROID_ABI"
|
||||
mkdir -p "$OUT"
|
||||
|
||||
# Resolve toolchain
|
||||
TOOLCHAIN="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64"
|
||||
CC="$TOOLCHAIN/bin/${HOST_ARCH}${API}-clang"
|
||||
CXX="$TOOLCHAIN/bin/${HOST_ARCH}${API}-clang++"
|
||||
AR="$TOOLCHAIN/bin/llvm-ar"
|
||||
RANLIB="$TOOLCHAIN/bin/llvm-ranlib"
|
||||
STRIP="$TOOLCHAIN/bin/llvm-strip"
|
||||
|
||||
if [[ ! -x "$CC" ]]; then
|
||||
echo "ERROR: Clang not found at $CC" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LD="$TOOLCHAIN/bin/ld.lld"
|
||||
[[ -x "$LD" ]] || LD="$TOOLCHAIN/bin/lld"
|
||||
SYSROOT="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/sysroot"
|
||||
|
||||
# Export so configure scripts see them
|
||||
export CC CXX AR RANLIB STRIP LD
|
||||
export LDFLAGS="--sysroot=$SYSROOT"
|
||||
export CFLAGS="--sysroot=$SYSROOT"
|
||||
export CXXFLAGS="--sysroot=$SYSROOT"
|
||||
|
||||
echo "==> ABI=$ANDROID_ABI API=$API CC=$CC LD=$LD"
|
||||
|
||||
# ─── libvpx ──────────────────────────────────────────────────────────────────
|
||||
build_libvpx() {
|
||||
local src="$SAFE_THIRD_PARTY/libvpx"
|
||||
local bld="$SAFE_BUILD_NATIVE/vpx-build-$ANDROID_ABI"
|
||||
local lib="$OUT/libvpx.a"
|
||||
|
||||
if [[ -f "$lib" ]]; then
|
||||
echo "==> libvpx already built for $ANDROID_ABI ($lib)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "==> Building libvpx for $ANDROID_ABI..."
|
||||
rm -rf "$bld"
|
||||
mkdir -p "$bld"
|
||||
|
||||
# Use generic-gnu to avoid Android-specific assembler/linker issues with cross-compilation.
|
||||
# The clang compiler provides correct codegen; assembly optimizations are secondary.
|
||||
local vpx_target="generic-gnu"
|
||||
|
||||
cd "$bld"
|
||||
"$src/configure" \
|
||||
--target="$vpx_target" \
|
||||
--disable-examples \
|
||||
--disable-tools \
|
||||
--disable-docs \
|
||||
--disable-unit-tests \
|
||||
--enable-vp8 \
|
||||
--enable-vp9 \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-webm-io \
|
||||
--disable-libyuv \
|
||||
--extra-cflags="-fPIC --sysroot=$SYSROOT" \
|
||||
--prefix="$bld/install" 2>&1 | tail -5
|
||||
|
||||
make -j"$(nproc)" libvpx.a 2>&1 | tail -5
|
||||
cp libvpx.a "$lib"
|
||||
echo "==> libvpx built: $lib ($(du -sh "$lib" | cut -f1))"
|
||||
cd "$ROOT"
|
||||
}
|
||||
|
||||
# ─── libopus ─────────────────────────────────────────────────────────────────
|
||||
build_libopus() {
|
||||
local src="$SAFE_THIRD_PARTY/opus"
|
||||
local bld="$SAFE_BUILD_NATIVE/opus-build-$ANDROID_ABI"
|
||||
local lib="$OUT/libopus.a"
|
||||
|
||||
if [[ -f "$lib" ]]; then
|
||||
echo "==> libopus already built for $ANDROID_ABI ($lib)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "==> Building libopus for $ANDROID_ABI..."
|
||||
rm -rf "$bld"
|
||||
mkdir -p "$bld"
|
||||
|
||||
# Run autogen if configure doesn't exist
|
||||
if [[ ! -f "$src/configure" ]]; then
|
||||
( cd "$src" && ./autogen.sh 2>&1 | tail -3 )
|
||||
fi
|
||||
|
||||
cd "$bld"
|
||||
CC="$CC -fPIC" CXX="$CXX -fPIC" AR="$AR" RANLIB="$RANLIB" \
|
||||
"$src/configure" \
|
||||
--host="$HOST_ARCH" \
|
||||
--disable-shared \
|
||||
--enable-static \
|
||||
--disable-doc \
|
||||
--disable-extra-programs \
|
||||
--prefix="$bld/install" 2>&1 | tail -5
|
||||
|
||||
make -j"$(nproc)" 2>&1 | tail -5
|
||||
cp .libs/libopus.a "$lib" 2>/dev/null || cp src/.libs/libopus.a "$lib" 2>/dev/null || \
|
||||
find "$bld" -name 'libopus.a' -exec cp {} "$lib" \;
|
||||
# Create opus/ include subdirectory that CMakeLists expects for #include <opus/opus.h>
|
||||
mkdir -p "$OUT/include/opus"
|
||||
cp "$src/include/"*.h "$OUT/include/opus/" 2>/dev/null || true
|
||||
echo "==> libopus built: $lib ($(du -sh "$lib" | cut -f1))"
|
||||
cd "$ROOT"
|
||||
}
|
||||
|
||||
# ─── libspeex ────────────────────────────────────────────────────────────────
|
||||
build_libspeex() {
|
||||
local src="$SAFE_THIRD_PARTY/speex"
|
||||
local bld="$SAFE_BUILD_NATIVE/speex-build-$ANDROID_ABI"
|
||||
local lib="$OUT/libspeex.a"
|
||||
|
||||
if [[ -f "$lib" ]]; then
|
||||
echo "==> libspeex already built for $ANDROID_ABI ($lib)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "==> Building libspeex for $ANDROID_ABI..."
|
||||
rm -rf "$bld"
|
||||
mkdir -p "$bld"
|
||||
|
||||
if [[ ! -f "$src/configure" ]]; then
|
||||
( cd "$src" && ./autogen.sh 2>&1 | tail -3 )
|
||||
fi
|
||||
|
||||
cd "$bld"
|
||||
CC="$CC -fPIC" CXX="$CXX -fPIC" AR="$AR" RANLIB="$RANLIB" \
|
||||
"$src/configure" \
|
||||
--host="$HOST_ARCH" \
|
||||
--disable-shared \
|
||||
--enable-static \
|
||||
--disable-oggtest \
|
||||
--prefix="$bld/install" 2>&1 | tail -5
|
||||
|
||||
# Build only the library directory (not speexdec/speexenc tools)
|
||||
make -j"$(nproc)" -C libspeex 2>&1 | tail -5
|
||||
find "$bld/libspeex" -name 'libspeex.a' | head -1 | xargs -I{} cp {} "$lib"
|
||||
[[ -f "$lib" ]] || find "$bld" -name 'libspeex.a' | head -1 | xargs -I{} cp {} "$lib"
|
||||
# Copy generated speex_config_types.h which is needed at build time
|
||||
if [[ -f "$bld/include/speex/speex_config_types.h" ]]; then
|
||||
mkdir -p "$OUT/include/speex"
|
||||
cp "$bld/include/speex/speex_config_types.h" "$OUT/include/speex/"
|
||||
fi
|
||||
echo "==> libspeex built: $lib ($(du -sh "$lib" | cut -f1))"
|
||||
cd "$ROOT"
|
||||
}
|
||||
|
||||
build_libvpx
|
||||
build_libopus
|
||||
build_libspeex
|
||||
|
||||
echo ""
|
||||
echo "==> Native libs for $ANDROID_ABI:"
|
||||
ls -lh "$OUT/"*.a 2>/dev/null || echo " (none)"
|
||||
12
scripts/ensure-gradle-wrapper.sh
Executable file
12
scripts/ensure-gradle-wrapper.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify gradlew wrapper exists and is executable. Exit non-zero if missing.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
if [[ ! -x "$ROOT/gradlew" ]]; then
|
||||
echo "ERROR: gradlew wrapper not found at $ROOT/gradlew" >&2
|
||||
echo " Run: gradle wrapper --gradle-version 8.9 (from $ROOT)" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "==> Gradle wrapper OK: $ROOT/gradlew"
|
||||
23
scripts/init-third-party-submodules.sh
Executable file
23
scripts/init-third-party-submodules.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# Initialize only the codec-related git submodules needed for the NDK build.
|
||||
# Called by rebuild.sh before the native build step.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
SUBMODULES=(
|
||||
"third-party/libvpx"
|
||||
"third-party/opus"
|
||||
"third-party/speex"
|
||||
"third-party/wireguard-android"
|
||||
)
|
||||
|
||||
for sm in "${SUBMODULES[@]}"; do
|
||||
if [[ -d "$sm/.git" ]] || git -C "$sm" rev-parse --git-dir >/dev/null 2>&1; then
|
||||
echo "==> Submodule already initialized: $sm"
|
||||
else
|
||||
echo "==> Initializing submodule: $sm"
|
||||
git submodule update --init -- "$sm"
|
||||
fi
|
||||
done
|
||||
13
scripts/native-build-cache.sh
Executable file
13
scripts/native-build-cache.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# ccache detection helpers for native codec builds. Source this file.
|
||||
|
||||
androidcast_ccache_wanted() {
|
||||
[[ "${ANDROIDCAST_CCACHE:-auto}" != "off" ]] && command -v ccache >/dev/null 2>&1
|
||||
}
|
||||
|
||||
androidcast_ccache_setup() {
|
||||
if androidcast_ccache_wanted; then
|
||||
export CC="ccache ${CC:-clang}"
|
||||
export CXX="ccache ${CXX:-clang++}"
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user