Some checks failed
Build Release Binaries / build-amd64 (push) Failing after 3m48s
cmake 3.28 works when ANDROID_NDK is set (not just ANDROID_NDK_HOME). Relaxed version check from <=3.26 to <=3.30. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
241 lines
9.8 KiB
Bash
Executable File
241 lines
9.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# WZ Phone — Android APK build script for Debian 12 (Bookworm)
|
|
#
|
|
# Sets up a complete build environment from scratch and produces a debug APK.
|
|
# Idempotent — safe to run multiple times (skips already-installed components).
|
|
#
|
|
# Tested on: Debian 12 x86_64, cross-compiling to aarch64-linux-android
|
|
#
|
|
# Why these specific versions:
|
|
#
|
|
# cmake 3.25-3.28 (system package from apt)
|
|
# cmake 3.25 (Debian 12) and 3.28 (Ubuntu 24.04) both work.
|
|
# cmake 3.31+ has armv7/aarch64 flag conflicts in Android-Determine.cmake.
|
|
# cmake 4.x drops cmake_minimum_required < 3.5.
|
|
# Do NOT use pip cmake — it bundles its own modules with different bugs.
|
|
# CRITICAL: must set ANDROID_NDK=$ANDROID_NDK_HOME (cmake checks ANDROID_NDK).
|
|
#
|
|
# NDK 26.1.10909125 (r26b)
|
|
# NDK 27+ ships a newer libc++_shared.so with different scudo allocator
|
|
# defaults. On Android 16 devices with MTE (Memory Tagging Extension)
|
|
# enabled (e.g. Nothing A059), NDK 27's scudo crashes during malloc/calloc.
|
|
# NDK 26.1 is the last stable version for these devices.
|
|
# Matches build.gradle.kts: ndkVersion = "26.1.10909125"
|
|
#
|
|
# JDK 17 (openjdk-17-jdk-headless)
|
|
# Gradle 8.5 + AGP 8.2.0 officially support JDK 17.
|
|
# JDK 21 works for compilation but has Gradle daemon compat issues.
|
|
#
|
|
# Rust stable (currently 1.94.1)
|
|
# Edition 2024, MSRV 1.85. Stable channel is fine.
|
|
#
|
|
# ANDROID_NDK=$ANDROID_NDK_HOME (BOTH must be set)
|
|
# cmake's Android platform module checks ANDROID_NDK (no _HOME suffix).
|
|
# cargo-ndk sets ANDROID_NDK_HOME. Both must point to the same path.
|
|
#
|
|
# Usage:
|
|
# chmod +x scripts/build-android.sh
|
|
# ./scripts/build-android.sh # build from current tree
|
|
# WZP_CLONE=1 ./scripts/build-android.sh # clone fresh from git
|
|
# WZP_COMMIT=2092245 ./scripts/build-android.sh # pin to specific commit
|
|
#
|
|
# Environment variables (all optional):
|
|
# WZP_CLONE Set to 1 to clone from git instead of using current dir
|
|
# WZP_REPO Git clone URL (default: ssh://git@git.manko.yoga:222/manawenuz/wz-phone)
|
|
# WZP_BRANCH Branch to checkout (default: feat/android-voip-client)
|
|
# WZP_COMMIT Commit to pin to (default: HEAD)
|
|
# WZP_WORKDIR Build directory (default: /tmp/wzp-build)
|
|
# ANDROID_API SDK platform level (default: 34)
|
|
# NDK_VERSION NDK version string (default: 26.1.10909125)
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Configuration
|
|
# ---------------------------------------------------------------------------
|
|
CLONE="${WZP_CLONE:-0}"
|
|
REPO="${WZP_REPO:-ssh://git@git.manko.yoga:222/manawenuz/wz-phone}"
|
|
BRANCH="${WZP_BRANCH:-feat/android-voip-client}"
|
|
COMMIT="${WZP_COMMIT:-}"
|
|
WORKDIR="${WZP_WORKDIR:-/tmp/wzp-build}"
|
|
ANDROID_API="${ANDROID_API:-34}"
|
|
NDK_VERSION="${NDK_VERSION:-26.1.10909125}"
|
|
|
|
ANDROID_HOME="${ANDROID_HOME:-$HOME/android-sdk}"
|
|
ANDROID_NDK_HOME="$ANDROID_HOME/ndk/$NDK_VERSION"
|
|
# cmake checks ANDROID_NDK (not _HOME) — both must be set
|
|
ANDROID_NDK="$ANDROID_NDK_HOME"
|
|
JAVA_HOME="/usr/lib/jvm/java-17-openjdk-$(dpkg --print-architecture)"
|
|
CMDLINE_TOOLS_URL="https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"
|
|
|
|
export ANDROID_HOME ANDROID_NDK_HOME ANDROID_NDK JAVA_HOME
|
|
export PATH="$JAVA_HOME/bin:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$HOME/.cargo/bin:$PATH"
|
|
|
|
log() { echo -e "\n\033[1;36m>>> $*\033[0m"; }
|
|
err() { echo -e "\033[1;31mERROR: $*\033[0m" >&2; exit 1; }
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 1: System packages (cmake 3.25, JDK 17, make, git, etc.)
|
|
# ---------------------------------------------------------------------------
|
|
log "Installing system packages"
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -qq
|
|
apt-get install -y -qq \
|
|
build-essential \
|
|
cmake \
|
|
curl \
|
|
git \
|
|
libssl-dev \
|
|
pkg-config \
|
|
unzip \
|
|
wget \
|
|
zip \
|
|
openjdk-17-jdk-headless \
|
|
2>/dev/null
|
|
|
|
# Verify critical versions
|
|
log "Verifying build environment"
|
|
echo " cmake: $(cmake --version | head -1)"
|
|
echo " java: $(java -version 2>&1 | head -1)"
|
|
echo " make: $(make --version | head -1)"
|
|
|
|
CMAKE_MAJOR=$(cmake --version | head -1 | grep -oP '\d+' | head -1)
|
|
CMAKE_MINOR=$(cmake --version | head -1 | grep -oP '\d+' | sed -n '2p')
|
|
if [ "$CMAKE_MAJOR" -gt 3 ] || { [ "$CMAKE_MAJOR" -eq 3 ] && [ "$CMAKE_MINOR" -gt 30 ]; }; then
|
|
err "cmake $(cmake --version | head -1) is too new! Need cmake <= 3.28.x. cmake 3.31+ has Android cross-compilation bugs."
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 2: Rust toolchain
|
|
# ---------------------------------------------------------------------------
|
|
log "Setting up Rust toolchain"
|
|
if ! command -v rustup &>/dev/null; then
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
|
|
source "$HOME/.cargo/env"
|
|
fi
|
|
rustup default stable
|
|
rustup target add aarch64-linux-android
|
|
echo " rustc: $(rustc --version)"
|
|
echo " cargo: $(cargo --version)"
|
|
|
|
if ! command -v cargo-ndk &>/dev/null; then
|
|
log "Installing cargo-ndk"
|
|
cargo install cargo-ndk
|
|
fi
|
|
echo " ndk: $(cargo ndk --version)"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 3: Android SDK + NDK 26.1
|
|
# ---------------------------------------------------------------------------
|
|
log "Setting up Android SDK + NDK $NDK_VERSION"
|
|
if [ ! -f "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" ]; then
|
|
log "Downloading Android command-line tools"
|
|
mkdir -p "$ANDROID_HOME/cmdline-tools"
|
|
TMPZIP=$(mktemp /tmp/cmdline-tools-XXXXX.zip)
|
|
wget -q -O "$TMPZIP" "$CMDLINE_TOOLS_URL"
|
|
unzip -qo "$TMPZIP" -d "$ANDROID_HOME/cmdline-tools"
|
|
mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest" 2>/dev/null || true
|
|
rm -f "$TMPZIP"
|
|
fi
|
|
|
|
yes | sdkmanager --licenses >/dev/null 2>&1 || true
|
|
|
|
if [ ! -d "$ANDROID_NDK_HOME" ]; then
|
|
log "Installing NDK $NDK_VERSION (this takes a few minutes)"
|
|
sdkmanager --install \
|
|
"platforms;android-${ANDROID_API}" \
|
|
"build-tools;${ANDROID_API}.0.0" \
|
|
"ndk;${NDK_VERSION}" \
|
|
"platform-tools" \
|
|
2>&1 | grep -v "^\[" || true
|
|
fi
|
|
|
|
[ -d "$ANDROID_NDK_HOME" ] || err "NDK not found at $ANDROID_NDK_HOME"
|
|
echo " NDK: $ANDROID_NDK_HOME"
|
|
echo " SDK: $ANDROID_HOME"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 4: Source code
|
|
# ---------------------------------------------------------------------------
|
|
if [ "$CLONE" = "1" ]; then
|
|
log "Cloning $REPO (branch: $BRANCH)"
|
|
if [ -d "$WORKDIR/.git" ]; then
|
|
cd "$WORKDIR"
|
|
git fetch origin
|
|
else
|
|
rm -rf "$WORKDIR"
|
|
git clone --branch "$BRANCH" --recurse-submodules "$REPO" "$WORKDIR"
|
|
cd "$WORKDIR"
|
|
fi
|
|
git checkout "$BRANCH"
|
|
git pull origin "$BRANCH" || true
|
|
git submodule update --init --recursive
|
|
|
|
if [ -n "$COMMIT" ]; then
|
|
log "Pinning to commit $COMMIT"
|
|
git checkout "$COMMIT"
|
|
fi
|
|
else
|
|
# Use current directory (assume we're in the repo root)
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
WORKDIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
cd "$WORKDIR"
|
|
[ -f "Cargo.toml" ] || err "Not in repo root. Run from repo root or set WZP_CLONE=1"
|
|
fi
|
|
|
|
echo " HEAD: $(git log --oneline -1)"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 5: Build native Rust library (.so)
|
|
# ---------------------------------------------------------------------------
|
|
log "Building Rust native library (arm64-v8a, release)"
|
|
cargo ndk -t arm64-v8a \
|
|
-o "$WORKDIR/android/app/src/main/jniLibs" \
|
|
build --release -p wzp-android
|
|
|
|
SO="$WORKDIR/android/app/src/main/jniLibs/arm64-v8a/libwzp_android.so"
|
|
[ -f "$SO" ] || err ".so not found at $SO"
|
|
echo " Built: $SO ($(du -h "$SO" | cut -f1))"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 6: Generate debug keystore (if missing)
|
|
# ---------------------------------------------------------------------------
|
|
KEYSTORE="$WORKDIR/android/keystore/wzp-debug.jks"
|
|
if [ ! -f "$KEYSTORE" ]; then
|
|
log "Generating debug keystore"
|
|
mkdir -p "$(dirname "$KEYSTORE")"
|
|
keytool -genkey -v \
|
|
-keystore "$KEYSTORE" \
|
|
-keyalg RSA -keysize 2048 -validity 10000 \
|
|
-alias wzp-debug \
|
|
-storepass android -keypass android \
|
|
-dname "CN=WZP Debug" 2>&1 | tail -1
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 7: Build Android APK
|
|
# ---------------------------------------------------------------------------
|
|
log "Building APK (debug)"
|
|
cd "$WORKDIR/android"
|
|
chmod +x ./gradlew
|
|
./gradlew assembleDebug --no-daemon --warning-mode=none
|
|
|
|
APK=$(find . -name "app-debug*.apk" -path "*/outputs/apk/*" | head -1)
|
|
[ -n "$APK" ] || err "APK not found"
|
|
APK_ABS="$(cd "$(dirname "$APK")" && pwd)/$(basename "$APK")"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Done
|
|
# ---------------------------------------------------------------------------
|
|
log "Build complete!"
|
|
echo ""
|
|
echo " ┌──────────────────────────────────────────────────────────┐"
|
|
echo " │ APK: $APK_ABS"
|
|
echo " │ Size: $(du -h "$APK_ABS" | cut -f1)"
|
|
echo " │ SHA256: $(sha256sum "$APK_ABS" | cut -d' ' -f1)"
|
|
echo " └──────────────────────────────────────────────────────────┘"
|
|
echo ""
|
|
echo " Install: adb install -r $APK_ABS"
|
|
echo ""
|