mirror of
https://github.com/Gathin23/cleanyourtv.git
synced 2026-11-07 10:46:07 -10:00
On an arm64 host the image came out arm64, and eight minutes in :app:mergeReleaseResources failed: the Linux AAPT2 the Android Gradle plugin downloads is published for x86-64 only. Both twins now pass --platform linux/amd64 to docker build and docker run; on an x86-64 computer that changes nothing. The reporter's run under Rosetta built in 7m20s cold and installed on an Android TV 9 set. docker-build.md's Apple Silicon section says so, names the Rosetta and Colima settings, and gives the one command that removes an arm64 image an older copy left behind. The first-run tests expect the flag on the build, the shell twin is run once more to see it on the run, and a source check covers the PowerShell twin where pwsh is missing.
89 lines
4.5 KiB
Bash
Executable File
89 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Build the launcher or an add-on inside Docker, so this computer needs no JDK or Android SDK.
|
|
# Usage: tools/docker-build.sh [launcher | addons/<name>] [gradle task ...]
|
|
# tools/docker-build.sh the launcher, assembleRelease
|
|
# tools/docker-build.sh addons/weather an add-on
|
|
# tools/docker-build.sh launcher testReleaseUnitTest lintRelease assembleRelease
|
|
# The APK lands where a native build puts it (<project>/app/build/outputs/apk/release/).
|
|
# Install the launcher with: SKIP_BUILD=1 TV_HOST=<tv ip> launcher/build-and-install.sh
|
|
# Guide, signing key included: tools/docker-build.md
|
|
set -euo pipefail
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
PROJECT="${1:-launcher}"
|
|
[ $# -gt 0 ] && shift
|
|
TASKS=("$@")
|
|
[ ${#TASKS[@]} -gt 0 ] || TASKS=(assembleRelease)
|
|
IMAGE="${IMAGE:-cleanyourtv-android-build}"
|
|
GRADLE_VOLUME="${GRADLE_VOLUME:-cleanyourtv-gradle}"
|
|
# Where the debug signing key lives inside the container. The default is the image's own, kept in the Gradle volume;
|
|
# KEY_DIR picks another place in it, HOST_KEY_DIR mounts a folder from this computer (your ~/.android, say).
|
|
KEY_DIR="${KEY_DIR:-/gradle/.android}"
|
|
|
|
PROJECT="${PROJECT%/}"
|
|
if [ ! -f "$ROOT/$PROJECT/settings.gradle" ] && [ ! -f "$ROOT/$PROJECT/settings.gradle.kts" ]; then
|
|
echo "ERROR: $PROJECT is not a Gradle project in this repository (try launcher or addons/<name>)." >&2
|
|
exit 1
|
|
fi
|
|
command -v docker >/dev/null || { echo "ERROR: docker is not installed or not on PATH." >&2; exit 1; }
|
|
|
|
KEY_ARGS=()
|
|
if [ -n "${HOST_KEY_DIR:-}" ]; then
|
|
# Docker bind-mounts an absolute path that is there, and nothing else: given a folder that is not there it
|
|
# creates it (empty, and owned by root on Linux), and given a relative path it reads the name as a volume. So
|
|
# /key would be an empty folder or volume, the build would sign with a new debug key, and the next install over
|
|
# the app already on the TV would fail with INSTALL_FAILED_UPDATE_INCOMPATIBLE - the failure "The signing key"
|
|
# in tools/docker-build.md explains, reached without a word. A quoted '~/.android' lands here too: no shell
|
|
# expands a tilde inside a variable. A drive-letter path is absolute as well, which is the form a Windows
|
|
# reader's HOST_KEY_DIR takes under Git Bash - tools/theme.sh reads C:/Users/... the same way (#1796).
|
|
case "$HOST_KEY_DIR" in
|
|
/*|[A-Za-z]:[\\/]*) ;;
|
|
*)
|
|
echo "ERROR: HOST_KEY_DIR=$HOST_KEY_DIR is not an absolute path." >&2
|
|
echo "Docker reads a relative one as the name of a volume, so the build would make a new debug key." >&2
|
|
echo "Pass the folder your native build uses: \"\$HOME/.android\" ('~/.android' in quotes is not expanded)." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
if [ ! -d "$HOST_KEY_DIR" ]; then
|
|
echo "ERROR: HOST_KEY_DIR=$HOST_KEY_DIR is not a folder on this computer." >&2
|
|
echo "Docker would not mount your native key there, the build would make a new debug key, and an install" >&2
|
|
echo "over the app already on the TV would fail with INSTALL_FAILED_UPDATE_INCOMPATIBLE (tools/docker-build.md)." >&2
|
|
exit 1
|
|
fi
|
|
KEY_ARGS=(-v "$HOST_KEY_DIR:/key")
|
|
KEY_DIR=/key
|
|
fi
|
|
|
|
# Always x86-64, on an Apple Silicon Mac or an ARM board too: the Linux AAPT2 the Android Gradle plugin downloads
|
|
# is published for x86-64 only, so an arm64 image stops at :app:mergeReleaseResources minutes in (#2941). Docker
|
|
# Desktop runs it under Rosetta or QEMU; on an x86-64 computer the flag changes nothing.
|
|
PLATFORM=linux/amd64
|
|
if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
|
|
echo "Building the $IMAGE image once (JDK 17, Android SDK 34, build-tools 34.0.0; a few minutes)..."
|
|
docker build --platform "$PLATFORM" -t "$IMAGE" "$ROOT/tools/docker"
|
|
fi
|
|
|
|
# Git Bash on Windows rewrites /paths in arguments and gives POSIX paths Docker can't mount.
|
|
SRC="$ROOT"
|
|
USER_ARGS=()
|
|
case "$(uname -s)" in
|
|
MINGW* | MSYS* | CYGWIN*)
|
|
export MSYS_NO_PATHCONV=1
|
|
SRC="$(cd "$ROOT" && pwd -W)"
|
|
;;
|
|
*)
|
|
# The caller's uid, so the build output is not owned by root.
|
|
USER_ARGS=(--user "$(id -u):$(id -g)")
|
|
;;
|
|
esac
|
|
# The whole repository is mounted: an add-on's gradlew may call ../../launcher/gradlew.
|
|
docker run --rm --platform "$PLATFORM" ${USER_ARGS[@]+"${USER_ARGS[@]}"} ${KEY_ARGS[@]+"${KEY_ARGS[@]}"} \
|
|
-v "$SRC:/repo" -v "$GRADLE_VOLUME:/gradle" -w "/repo/$PROJECT" \
|
|
-e ANDROID_USER_HOME="$KEY_DIR" \
|
|
"$IMAGE" sh ./gradlew --no-daemon --console=plain "${TASKS[@]}"
|
|
|
|
for apk in "$ROOT/$PROJECT"/app/build/outputs/apk/*/*.apk; do
|
|
[ -f "$apk" ] && echo "APK: ${apk#"$ROOT"/} ($(wc -c < "$apk" | tr -d ' ') B)"
|
|
done
|
|
exit 0
|