Drop-in aapt2, aidl, zipalign, and split-select binaries for
Linux on ARM64 — the four Android SDK build-tools that
Gradle/AGP actually invokes during a normal app build.
Google's sdkmanager only ships these for linux-x86_64. On a
Raspberry Pi, Asahi Linux machine, ARM Chromebook, Ampere server,
or native-arm64 WSL, AGP fails with exec format error until you
swap in arm64 builds. This project ships those, automatically
rebuilt as upstream AOSP publishes new build-tools source tags.
You already need the matching build-tools installed via
sdkmanager first (the Java parts — apksigner, dx, etc. — come
from there; we only replace the four native binaries).
sdkmanager "build-tools;36.1.0"Then run the installer:
curl -fsSL https://raw.githubusercontent.com/Commit451/android-arm-build-tools/main/install.sh | bashThat picks up the latest Release, detects your SDK via
$ANDROID_HOME / $ANDROID_SDK_ROOT / ~/Android/Sdk, and drops
the binaries into $SDK/build-tools/<version>/.
To pin a specific version, or use a non-default SDK path:
curl -fsSL https://raw.githubusercontent.com/Commit451/android-arm-build-tools/main/install.sh -o install.sh
chmod +x install.sh
./install.sh --version 36.0.0 --sdk /opt/android-sdkAvailable versions are listed on the Releases tab.
The script refuses to run on non-aarch64 hosts and on hosts that
don't already have the matching build-tools/<version>/ directory.
Android Gradle Plugin 9.x stopped using the SDK's aapt2 and
instead pulls its own from Maven
(com.android.tools.build:aapt2:<agp-version>:linux), which is
x86_64-only. The drop-in above is still needed by other steps,
but on AGP 9+ you also have to tell Gradle to use the arm64
binary directly.
Prefer putting the override in your user-level Gradle properties file so every Android project on that ARM64 machine picks it up without committing machine-specific paths to an app repository:
mkdir -p ~/.gradle
cat >> ~/.gradle/gradle.properties <<'EOF'
android.aapt2FromMavenOverride=/home/you/Android/Sdk/build-tools/36.1.0/aapt2
EOFUse the full path to the aapt2 that this project's installer
just wrote. If you only want the override for one project, you can
instead add the same property to that project's gradle.properties.
Do not put it in local.properties; AGP does not read this override
from there.
Restart the Gradle daemon (./gradlew --stop) after changing the
property so it picks up the new binary.
If you're on AGP 8.x or older you can skip this step — those
versions still shell out to $SDK/build-tools/<v>/aapt2.
After install, this should work in any AGP project without "exec format error":
./gradlew :app:assembleDebugOr smoke-test the binary directly:
$ANDROID_HOME/build-tools/36.1.0/aapt2 version
# Android Asset Packaging Tool (aapt) 2.X-...Binaries are built on Debian 12 (Bookworm) — glibc 2.36, GCC 12 — so they need glibc 2.36+ and GLIBCXX_3.4.30+ at runtime. Distros that work out of the box:
- Raspberry Pi OS Bookworm (glibc 2.36) ✅
- Debian 12+ ✅
- Ubuntu 22.04+ ✅ (glibc 2.35 — close enough; libstdc++ matches)
- Fedora 38+ / Asahi Linux ✅
- Anything newer than the above ✅
If you're on something older, build from source against your distro's libc.
We ship the versions where AOSP has tagged public source we can build from. As of writing:
37.0.0— Android 17 GA, built fromandroid-17.0.0_r136.1.0— Android 16 QPR1, built fromandroid-16.0.0_r336.0.0— Android 16 GA, built fromandroid-16.0.0_r135.0.1— Android 15, built fromplatform-tools-35.0.1
AGP doesn't require build-tools to match compileSdk, so any of
the above paired with e.g. compileSdk 37 works fine.
sdkmanager sometimes publishes a build-tools version before AOSP
tags the corresponding source publicly. During that gap, the resolver
marks the version no-source and no arm64 release is published yet.
37.0.0 used to be in that state; it is now built from
android-17.0.0_r1 and available on the Releases tab. When a future
source tag appears, our daily workflow auto-detects it and publishes a
matching arm64 build (no action needed on this end). See DEV.md
for the resolver design.
All builds are on the Releases tab.
A GitHub Actions workflow runs daily, resolves each sdkmanager
build-tools version to an AOSP source ref (legacy platform-tools-*
tag or the newer android-NN.0.0_rN scheme), and publishes a
fresh release when something new shows up.
If you'd rather grab a single binary directly, each Release has
aapt2, aidl, zipalign, split-select, a combined .tar.xz,
and SHA256SUMS attached.
See DEV.md.
Refs
- https://github.com/termux/android-build-tools
- https://github.com/lzhiyong/android-sdk-tools
- https://github.com/nmeum/android-tools
MIT. See LICENSE.
\ ゜o゜)ノ