Files
DarkRoom/tools/fetch-android-runtime.sh
dtourolle 84fade99ec Put the developer docs under docs/dev and index the folder for users first
docs/ had 26 developer documents flat beside the manual, and the two
audiences are very differently sized: most readers want the manual and
the gesture reference, a few want the register, the designs and the
measurements. The manual and gestures.md stay at the top; everything for
someone changing the code moves to docs/dev/, and the two documents that
name their own successors — the v0.1 milestone and the UI-refinement plan
— go to docs/dev/archive/ rather than being deleted, since both are still
cited. docs/README.md is the index, users first.

Every reference follows: code comments, Cargo manifests, the workflows,
the pre-commit hook, the bench and traceability tools (which locate the
repo root by docs/dev/requirements.md now), packaging, the Docker READMEs,
CLAUDE.md, CONTRIBUTING.md and the README. The matrix links one level
deeper and is regenerated. Links out of the moved documents into the tree
gain a level; a link checker over every Markdown file finds none broken.
2026-09-20 21:16:03 +02:00

97 lines
4.6 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Fetch the inference runtime the Android APK carries (docs/dev/inference.md §3).
#
# ./tools/fetch-android-runtime.sh [DEST]
#
# Two Maven artefacts, pinned to each other by ONNX Runtime's own POM:
#
# com.microsoft.onnxruntime:onnxruntime-android-qnn MIT
# com.qualcomm.qti:qnn-runtime Qualcomm AI Engine Direct SDK licence
#
# The first is ONNX Runtime built with the CPU, QNN, XNNPACK, NNAPI and WebGPU
# providers; the second is Qualcomm's HTP backend — the ARM-side compiler and
# the per-generation Hexagon "skel" the DSP loads. Both ship as AARs whose
# `jni/arm64-v8a/` is what an APK's `lib/arm64-v8a/` wants, so this script
# unpacks exactly that and nothing else, plus the licence texts, which travel
# with the libraries (§3.1).
#
# ## What is and is not taken from the Qualcomm package
#
# Every HTP generation has its own skel and stub, 16 MB a pair. `QNN_HTP_ARCHS`
# names the ones to ship; the default is the generations in devices sold since
# the 8 Gen 2 (V73 — the MagicPad 2's 8s Gen 3 is one), through the 8 Elite
# (V79) and its successor (V81). V66–V69 are 2020–2021 silicon and are left
# out, which is 50 MB the tablet never loads. `libQnnHtpPrepare.so`, the
# on-device graph compiler, is 84 MB and cannot be left out: it is what turns
# an int8 ONNX graph into something the DSP runs, once per device (§5).
#
# `libQnnGpu.so` and `libQnnDsp*.so` are not taken: the Adreno rung measured
# slower than the Hexagon everywhere the Hexagon exists (§1.1), and the cDSP
# path is the pre-HTP generation.
#
# ## Why a script and not a checked-in copy
#
# 150 MB of vendor binaries in LFS, re-fetched by every clone, for files that
# Maven serves with checksums. The cache directory keeps them across builds;
# CI's is the target cache it already mounts.
set -euo pipefail
ORT_VERSION="${ORT_VERSION:-1.29.0}"
QNN_VERSION="${QNN_VERSION:-2.42.0}"
QNN_HTP_ARCHS="${QNN_HTP_ARCHS:-73 75 79 81}"
DEST="${1:-${PWD}/target-android/runtime}"
MAVEN="https://repo1.maven.org/maven2"
fetch() {
# A Maven artefact and its SHA-1, verified before anything is unpacked.
local group="$1" artefact="$2" version="$3" out="$4"
local url="${MAVEN}/${group//.//}/${artefact}/${version}/${artefact}-${version}.aar"
if [[ -f "${out}" && -f "${out}.sha1" ]] \
&& [[ "$(sha1sum "${out}" | cut -d' ' -f1)" == "$(cut -c1-40 "${out}.sha1")" ]]; then
return
fi
echo "==> fetching ${artefact} ${version}"
curl -fsSL -o "${out}.sha1" "${url}.sha1"
curl -fsSL -o "${out}" "${url}"
[[ "$(sha1sum "${out}" | cut -d' ' -f1)" == "$(cut -c1-40 "${out}.sha1")" ]] || {
echo "error: ${artefact}-${version}.aar does not match its published SHA-1" >&2
rm -f "${out}"
exit 1
}
}
mkdir -p "${DEST}/aar" "${DEST}/lib"
fetch com.microsoft.onnxruntime onnxruntime-android-qnn "${ORT_VERSION}" \
"${DEST}/aar/onnxruntime-android-qnn-${ORT_VERSION}.aar"
fetch com.qualcomm.qti qnn-runtime "${QNN_VERSION}" \
"${DEST}/aar/qnn-runtime-${QNN_VERSION}.aar"
# The ONNX Runtime POM names the QNN version it was built against; a pair
# that disagrees loads and then fails at the first graph, which is the kind
# of failure the probe would only report as "Hexagon failed".
pom="${DEST}/aar/onnxruntime-android-qnn-${ORT_VERSION}.pom"
[[ -f "${pom}" ]] || curl -fsSL -o "${pom}" \
"${MAVEN}/com/microsoft/onnxruntime/onnxruntime-android-qnn/${ORT_VERSION}/onnxruntime-android-qnn-${ORT_VERSION}.pom"
wanted="$(sed -n '/<artifactId>qnn-runtime<\/artifactId>/{n;s/.*<version>\(.*\)<\/version>.*/\1/p}' "${pom}")"
if [[ -n "${wanted}" && "${wanted}" != "${QNN_VERSION}" ]]; then
echo "error: ONNX Runtime ${ORT_VERSION} was built against QNN ${wanted}, not ${QNN_VERSION}" >&2
exit 1
fi
rm -rf "${DEST}/lib"
mkdir -p "${DEST}/lib"
unzip -q -o -j "${DEST}/aar/onnxruntime-android-qnn-${ORT_VERSION}.aar" \
'jni/arm64-v8a/libonnxruntime.so' -d "${DEST}/lib"
members=(jni/arm64-v8a/libQnnHtp.so jni/arm64-v8a/libQnnHtpPrepare.so jni/arm64-v8a/libQnnSystem.so)
for arch in ${QNN_HTP_ARCHS}; do
members+=("jni/arm64-v8a/libQnnHtpV${arch}Skel.so" "jni/arm64-v8a/libQnnHtpV${arch}Stub.so")
done
unzip -q -o -j "${DEST}/aar/qnn-runtime-${QNN_VERSION}.aar" "${members[@]}" -d "${DEST}/lib"
unzip -q -o -j "${DEST}/aar/qnn-runtime-${QNN_VERSION}.aar" 'LICENSE.pdf' 'NOTICE.txt' -d "${DEST}" 2>/dev/null || true
mv -f "${DEST}/LICENSE.pdf" "${DEST}/QNN-LICENSE.pdf" 2>/dev/null || true
mv -f "${DEST}/NOTICE.txt" "${DEST}/QNN-NOTICE.txt" 2>/dev/null || true
echo "==> runtime in ${DEST}/lib:"
du -sh "${DEST}/lib" | cut -f1 | sed 's/^/ /'
ls "${DEST}/lib" | sed 's/^/ /'