Build #13's PATH wrapper trick failed because tauri-cli invokes the linker with an absolute path (/opt/android-sdk/ndk/.../bin/aarch64-linux-android24- clang), which bypasses \$PATH entirely. The pthread_shim logs confirmed the broken API-24 stubs were still being linked: WZP_pthread_shim: dlsym(RTLD_DEFAULT, pthread_create) returned NULL: libdl.a is a stub --- use libdl.so instead Move the fix up a level — into the Dockerfile itself. On image build, for each of the four android ABIs × {clang, clang++}, rename `${abi}24-${suffix}` to `${abi}24-${suffix}.orig` and replace it with a shell wrapper that exec()s `${abi}26-${suffix}`. Any call to the API-24 wrapper — via PATH, absolute path, or otherwise — now transparently runs the API-26 wrapper, which uses the real libc.so/libdl.so bindings. The old bash-c /tmp/wrappers workaround in build-tauri-android.sh is removed now that the image handles it at the right layer. Also add `--shell` to build-tauri-android.sh: opens an interactive docker container on the remote with the same mounts/env as the build, so I can iterate on cargo tauri android build / manually patch files / etc. without the full git push → ssh → rebuild → install loop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
128 lines
5.6 KiB
Docker
128 lines
5.6 KiB
Docker
# =============================================================================
|
|
# WZ Phone — Android build environment (Debian 12 / Bookworm)
|
|
#
|
|
# Supports both:
|
|
# 1. Legacy Kotlin+JNI Android app (via cargo-ndk + gradle)
|
|
# 2. Tauri 2.x Mobile Android app (via tauri-cli + Node/npm)
|
|
#
|
|
# Toolchain:
|
|
# - Debian 12 (cmake 3.25, no Android cross-compilation bugs)
|
|
# - JDK 17 (Gradle 8.5 + AGP 8.2.0 compatible)
|
|
# - NDK 26.1 (last stable before scudo/MTE crash on NDK 27+)
|
|
# - Node.js 20 LTS (for Tauri frontend build)
|
|
# - Rust stable with all 4 Android targets + cargo-ndk + tauri-cli 2.x
|
|
#
|
|
# Build: docker build -t wzp-android-builder -f Dockerfile.android-builder .
|
|
# =============================================================================
|
|
FROM debian:bookworm
|
|
|
|
ARG NDK_VERSION=26.1.10909125
|
|
ARG ANDROID_API=34
|
|
# Tauri 2.x mobile targets compileSdk 36 + build-tools 35 by default. Install
|
|
# both 34 (legacy Kotlin app) and 35/36 (Tauri mobile) so the same image works
|
|
# for both pipelines.
|
|
ARG ANDROID_API_TAURI=36
|
|
ARG BUILD_TOOLS_TAURI=35.0.0
|
|
|
|
ENV DEBIAN_FRONTEND=noninteractive \
|
|
ANDROID_HOME=/opt/android-sdk \
|
|
JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
|
|
|
|
ENV ANDROID_NDK_HOME=$ANDROID_HOME/ndk/$NDK_VERSION \
|
|
ANDROID_NDK=$ANDROID_HOME/ndk/$NDK_VERSION
|
|
|
|
# ── System packages ──────────────────────────────────────────────────────────
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
build-essential \
|
|
cmake \
|
|
curl \
|
|
git \
|
|
libssl-dev \
|
|
pkg-config \
|
|
unzip \
|
|
wget \
|
|
zip \
|
|
openjdk-17-jdk-headless \
|
|
ca-certificates \
|
|
libasound2-dev \
|
|
file \
|
|
xz-utils \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# ── Node.js 20 LTS (required by Tauri for frontend build) ────────────────────
|
|
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
|
&& apt-get install -y --no-install-recommends nodejs \
|
|
&& rm -rf /var/lib/apt/lists/* \
|
|
&& node --version \
|
|
&& npm --version
|
|
|
|
# ── Android SDK + NDK 26.1 ──────────────────────────────────────────────────
|
|
RUN mkdir -p $ANDROID_HOME/cmdline-tools \
|
|
&& cd /tmp \
|
|
&& wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdtools.zip \
|
|
&& unzip -qo cmdtools.zip -d $ANDROID_HOME/cmdline-tools \
|
|
&& mv $ANDROID_HOME/cmdline-tools/cmdline-tools $ANDROID_HOME/cmdline-tools/latest \
|
|
&& rm cmdtools.zip
|
|
|
|
RUN yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/null 2>&1 \
|
|
&& $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install \
|
|
"platforms;android-${ANDROID_API}" \
|
|
"build-tools;${ANDROID_API}.0.0" \
|
|
"platforms;android-${ANDROID_API_TAURI}" \
|
|
"build-tools;${BUILD_TOOLS_TAURI}" \
|
|
"ndk;${NDK_VERSION}" \
|
|
"platform-tools" \
|
|
2>&1 | grep -v '^\[' > /dev/null
|
|
|
|
# Work around broken API-24 libc/libdl stubs in the NDK. Rust's pre-compiled
|
|
# libstd.rlib for aarch64-linux-android links against pthread_create / dlsym
|
|
# from the sysroot. With --target=...24, those resolve to the API-24 "stub"
|
|
# libc.a/libdl.a that return "libdl.a is a stub --- use libdl.so instead" at
|
|
# runtime. API-26 has real dynamic bindings. Tauri-cli hard-codes the
|
|
# android24-clang path so env var overrides don't stick.
|
|
#
|
|
# Permanent fix inside the image: replace every `${abi}24-clang` binary with
|
|
# a shim that exec()s the corresponding `${abi}26-clang`. Any build using
|
|
# this image now transparently gets the API-26 sysroot even when the caller
|
|
# asks for API-24.
|
|
RUN set -eux; \
|
|
BIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin; \
|
|
for abi in aarch64-linux-android armv7a-linux-androideabi i686-linux-android x86_64-linux-android; do \
|
|
for suffix in clang clang++; do \
|
|
mv "$BIN/${abi}24-${suffix}" "$BIN/${abi}24-${suffix}.orig"; \
|
|
printf '#!/bin/sh\nexec "%s/%s26-%s" "$@"\n' "$BIN" "$abi" "$suffix" > "$BIN/${abi}24-${suffix}"; \
|
|
chmod +x "$BIN/${abi}24-${suffix}"; \
|
|
done; \
|
|
done
|
|
|
|
# Make SDK world-readable so builder user can access it
|
|
RUN chmod -R a+rX $ANDROID_HOME
|
|
|
|
# ── Builder user (1000:1000) ─────────────────────────────────────────────────
|
|
RUN groupadd -g 1000 builder \
|
|
&& useradd -m -u 1000 -g 1000 -s /bin/bash builder
|
|
|
|
USER builder
|
|
WORKDIR /home/builder
|
|
|
|
# ── Rust toolchain ───────────────────────────────────────────────────────────
|
|
# Install all 4 Android targets (Tauri Mobile builds for all ABIs by default;
|
|
# cargo-ndk legacy path only needs arm64-v8a — both workflows supported).
|
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
|
|
| sh -s -- -y --default-toolchain stable \
|
|
&& . $HOME/.cargo/env \
|
|
&& rustup target add \
|
|
aarch64-linux-android \
|
|
armv7-linux-androideabi \
|
|
i686-linux-android \
|
|
x86_64-linux-android \
|
|
&& cargo install cargo-ndk \
|
|
&& cargo install tauri-cli --version "^2.0" --locked
|
|
|
|
ENV PATH="/home/builder/.cargo/bin:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$JAVA_HOME/bin:$PATH"
|
|
|
|
# NDK_HOME is the env var tauri-cli checks (in addition to ANDROID_NDK_HOME)
|
|
ENV NDK_HOME=$ANDROID_NDK_HOME
|
|
|
|
WORKDIR /build/source
|