Skip to content

Commit 7fc70aa

Browse files
authored
Android improve prebuilt workflow and provide tutorial (#3841)
* Improve the workflow for Android prebuilt Don't depend on demo app. Instead, build JAR/JNI/AAR directly * Update tutorial to use prebuilt libs * Fix release build * fix ci.sh * update AAR Link
1 parent c02d508 commit 7fc70aa

File tree

10 files changed

+207
-39
lines changed

10 files changed

+207
-39
lines changed

.github/workflows/android.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ on:
99
paths:
1010
- .ci/docker/**
1111
- .github/workflows/android.yml
12+
- build/build_android_library.sh
13+
- build/test_android_ci.sh
1214
- install_requirements.sh
1315
- examples/demo-apps/android/**
1416
- extension/android/**
@@ -45,6 +47,8 @@ jobs:
4547
BUILD_TOOL=${{ matrix.build-tool }}
4648
# Setup MacOS dependencies as there is no Docker support on MacOS atm
4749
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-linux.sh "${BUILD_TOOL}"
50+
# Build Android library
51+
bash build/build_android_library.sh
4852
# Build Android demo app
4953
bash build/test_android_ci.sh
5054
@@ -61,8 +65,8 @@ jobs:
6165
cp cmake-out-android-x86_64/lib/*.a artifacts-to-be-uploaded/x86_64/
6266
cp cmake-out-android-x86_64/extension/android/*.so artifacts-to-be-uploaded/x86_64/
6367
# Copyp AAR to S3
64-
cp build_aar/executorch.aar artifacts-to-be-uploaded/
65-
cp build_aar/executorch-llama.aar artifacts-to-be-uploaded/
68+
cp executorch.aar artifacts-to-be-uploaded/
69+
cp executorch-llama.aar artifacts-to-be-uploaded/
6670
6771
# Upload the app and its test suite to S3 so that they can be downloaded by the test job
6872
upload-artifacts:

build/build_android_library.sh

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
set -ex
9+
10+
build_jar() {
11+
pushd extension/android
12+
./gradlew build
13+
popd
14+
cp extension/android/build/libs/executorch.jar "${BUILD_AAR_DIR}/libs"
15+
}
16+
17+
build_android_native_library() {
18+
ANDROID_ABI="$1"
19+
ANDROID_NDK="${ANDROID_NDK:-/opt/ndk}"
20+
CMAKE_OUT="cmake-out-android-$1"
21+
cmake . -DCMAKE_INSTALL_PREFIX="${CMAKE_OUT}" \
22+
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \
23+
-DANDROID_ABI="${ANDROID_ABI}" \
24+
-DANDROID_PLATFORM=android-23 \
25+
-DEXECUTORCH_BUILD_XNNPACK=ON \
26+
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
27+
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
28+
-DEXECUTORCH_BUILD_OPTIMIZED=ON \
29+
-DCMAKE_BUILD_TYPE=Release \
30+
-B"${CMAKE_OUT}"
31+
32+
if [ "$(uname)" == "Darwin" ]; then
33+
CMAKE_JOBS=$(( $(sysctl -n hw.ncpu) - 1 ))
34+
else
35+
CMAKE_JOBS=$(( $(nproc) - 1 ))
36+
fi
37+
cmake --build "${CMAKE_OUT}" -j "${CMAKE_JOBS}" --target install --config Release
38+
39+
cmake examples/models/llama2 \
40+
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
41+
-DANDROID_ABI="$ANDROID_ABI" \
42+
-DANDROID_PLATFORM=android-23 \
43+
-DCMAKE_INSTALL_PREFIX="${CMAKE_OUT}" \
44+
-DEXECUTORCH_BUILD_XNNPACK=ON \
45+
-DCMAKE_BUILD_TYPE=Release \
46+
-B"${CMAKE_OUT}"/examples/models/llama2
47+
48+
cmake --build "${CMAKE_OUT}"/examples/models/llama2 -j "${CMAKE_JOBS}" --config Release
49+
50+
cmake extension/android \
51+
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
52+
-DANDROID_ABI="${ANDROID_ABI}" \
53+
-DANDROID_PLATFORM=android-23 \
54+
-DCMAKE_INSTALL_PREFIX="${CMAKE_OUT}" \
55+
-DEXECUTORCH_BUILD_LLAMA_JNI=ON \
56+
-DCMAKE_BUILD_TYPE=Release \
57+
-B"${CMAKE_OUT}"/extension/android
58+
59+
cmake --build "${CMAKE_OUT}"/extension/android -j "${CMAKE_JOBS}" --config Release
60+
61+
cp "${CMAKE_OUT}"/extension/android/*.so "${BUILD_AAR_DIR}/jni/$1/"
62+
}
63+
64+
build_aar() {
65+
echo \<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" \
66+
package=\"org.pytorch.executorch\"\> \
67+
\<uses-sdk android:minSdkVersion=\"19\" /\> \
68+
\</manifest\> > "${BUILD_AAR_DIR}/AndroidManifest.xml"
69+
pushd "${BUILD_AAR_DIR}"
70+
# Rename libexecutorch_jni.so to libexecutorch.so for soname consistency
71+
# between Java and JNI
72+
mv jni/arm64-v8a/libexecutorch_jni.so jni/arm64-v8a/libexecutorch.so
73+
mv jni/x86_64/libexecutorch_jni.so jni/x86_64/libexecutorch.so
74+
zip -r executorch.aar libs jni/arm64-v8a/libexecutorch.so jni/x86_64/libexecutorch.so AndroidManifest.xml
75+
76+
rm jni/arm64-v8a/libexecutorch.so jni/x86_64/libexecutorch.so
77+
zip -r executorch-llama.aar libs jni/arm64-v8a/libexecutorch_llama_jni.so jni/x86_64/libexecutorch_llama_jni.so AndroidManifest.xml
78+
popd
79+
cp "${BUILD_AAR_DIR}/executorch-llama.aar" .
80+
cp "${BUILD_AAR_DIR}/executorch.aar" .
81+
}
82+
83+
BUILD_AAR_DIR="$(mktemp -d)"
84+
export BUILD_AAR_DIR
85+
mkdir -p "${BUILD_AAR_DIR}/jni/arm64-v8a" "${BUILD_AAR_DIR}/jni/x86_64" "${BUILD_AAR_DIR}/libs"
86+
build_jar
87+
build_android_native_library arm64-v8a
88+
build_android_native_library x86_64
89+
build_aar

build/test_android_ci.sh

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,47 +18,23 @@ export_model() {
1818
cp "${MODEL_NAME}_xnnpack_fp32.pte" "${ASSETS_DIR}"
1919
}
2020

21-
build_android_native_library() {
22-
pushd examples/demo-apps/android/LlamaDemo
23-
CMAKE_OUT="cmake-out-android-$1" ANDROID_NDK=/opt/ndk ANDROID_ABI="$1" ./gradlew setup
24-
popd
25-
cp "cmake-out-android-$1"/extension/android/*.so build_aar/jni/$1/
26-
}
27-
2821
build_android_demo_app() {
22+
mkdir -p examples/demo-apps/android/ExecuTorchDemo/app/libs
23+
cp executorch.aar examples/demo-apps/android/ExecuTorchDemo/app/libs
2924
pushd examples/demo-apps/android/ExecuTorchDemo
3025
ANDROID_HOME=/opt/android/sdk ./gradlew build
3126
popd
3227
}
3328

3429
build_android_llama_demo_app() {
30+
mkdir -p examples/demo-apps/android/LlamaDemo/app/libs
31+
cp executorch-llama.aar examples/demo-apps/android/LlamaDemo/app/libs
3532
pushd examples/demo-apps/android/LlamaDemo
3633
ANDROID_HOME=/opt/android/sdk ./gradlew build
3734
ANDROID_HOME=/opt/android/sdk ./gradlew assembleAndroidTest
3835
popd
3936
}
4037

41-
build_aar() {
42-
cp extension/android/build/libs/executorch.jar build_aar/libs
43-
echo \<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" \
44-
package=\"org.pytorch.executorch\"\> \
45-
\<uses-sdk android:minSdkVersion=\"19\" /\> \
46-
\</manifest\> > build_aar/AndroidManifest.xml
47-
pushd build_aar
48-
mv jni/arm64-v8a/libexecutorch_jni.so jni/arm64-v8a/libexecutorch.so
49-
mv jni/x86_64/libexecutorch_jni.so jni/x86_64/libexecutorch.so
50-
zip -r executorch.aar libs jni AndroidManifest.xml
51-
52-
rm jni/arm64-v8a/libexecutorch.so jni/x86_64/libexecutorch.so
53-
zip -r executorch-llama.aar libs jni AndroidManifest.xml
54-
popd
55-
}
56-
57-
mkdir -p build_aar/jni/arm64-v8a build_aar/jni/x86_64 build_aar/libs
58-
59-
build_android_native_library arm64-v8a
60-
build_android_native_library x86_64
6138
export_model
6239
build_android_demo_app
6340
build_android_llama_demo_app
64-
build_aar
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Using Android prebuilt libraries (AAR)
2+
3+
We provide two prebuilt Android libraries (AAR), `executorch.aar` for generic use case (image/audio processing) and `executorch_llama.aar` for LLAMA use case.
4+
5+
## Contents of libraries
6+
- `executorch.aar`
7+
- [Java library](https://github.com/pytorch/executorch/tree/release/0.2/extension/android/src/main/java/org/pytorch/executorch)
8+
- JNI contains the JNI binding for [NativePeer.java](https://github.com/pytorch/executorch/blob/release/0.2/extension/android/src/main/java/org/pytorch/executorch/NativePeer.java) and ExecuTorch native library, including core ExecuTorch runtime libraries, XNNPACK backend, Portable kernels, Optimized kernels, and Quantized kernels.
9+
- Comes with two ABI variants, arm64-v8a and x86_64.
10+
- `executorch_llama.aar`
11+
- [Java library](https://github.com/pytorch/executorch/tree/release/0.2/extension/android/src/main/java/org/pytorch/executorch) (Note: it contains the same Java classes as the previous Java, but it does not contain the JNI binding for generic Module/NativePeer Java code).
12+
- JNI contains the JNI binding for [LlamaModule.java](https://github.com/pytorch/executorch/blob/release/0.2/extension/android/src/main/java/org/pytorch/executorch/LlamaModule.java) and ExecuTorch native library, including core ExecuTorch runtime libraries, XNNPACK backend, Portable kernels, Optimized kernels, Quantized kernels, and LLAMA-specific Custom ops library.
13+
- Comes with two ABI variants, arm64-v8a and x86_64.
14+
15+
## Downloading AAR
16+
[executorch.aar](https://ossci-android.s3.us-west-1.amazonaws.com/executorch/release/0.2.1/executorch.aar) (sha1sum: af7690394fd978603abeff40cf64bd2df0dc793a)
17+
[executorch_llama.aar](https://ossci-android.s3.us-west-1.amazonaws.com/executorch/release/0.2.1/executorch-llama.aar) (sha1sum: 2973b1c41aa2c2775482d7cc7c803d0f6ca282c1)
18+
19+
## Using prebuilt libraries
20+
21+
To add the Java library to your app, simply download the AAR, and add it to your gradle build rule.
22+
23+
In your app working directory, such as example executorch/examples/demo-apps/android/LlamaDemo,
24+
```
25+
mkdir -p app/libs
26+
curl https://ossci-android.s3.us-west-1.amazonaws.com/executorch/release/0.2.1/executorch-llama.aar -o app/libs/executorch.aar
27+
```
28+
29+
And include it in gradle:
30+
```
31+
# app/build.grardle.kts
32+
dependencies {
33+
implementation(files("libs/executorch-llama.aar"))
34+
}
35+
```
36+
37+
Now you can compile your app with the ExecuTorch Android library.

examples/demo-apps/android/LlamaDemo/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
.cxx
1010
local.properties
1111
*.so
12+
*.aar

examples/demo-apps/android/LlamaDemo/README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,33 @@ adb push tokenizer.bin /data/local/tmp/llama
2727

2828
Note: The demo app searches in `/data/local/tmp/llama` for .pte and .bin files as LLAMA model and tokenizer.
2929

30-
## Build JNI library
30+
## Build library
31+
For the demo app to build, we need to build the ExecuTorch AAR library first.
32+
33+
The AAR library contains the required Java package and the corresponding JNI
34+
library for using ExecuTorch in your Android app.
35+
36+
### Alternative 1: Use prebuilt AAR library (recommended)
37+
38+
1. Open a terminal window and navigate to the root directory of the `executorch`.
39+
2. Run the following command to download the prebuilt library:
40+
```bash
41+
bash examples/demo-apps/android/LlamaDemo/download_prebuilt_lib.sh
42+
```
43+
44+
The prebuilt AAR library contains the Java library and the JNI binding for
45+
NativePeer.java and ExecuTorch native library, including core ExecuTorch
46+
runtime libraries, XNNPACK backend, Portable kernels, Optimized kernels,
47+
and Quantized kernels. It comes with two ABI variants, arm64-v8a and x86_64.
48+
49+
If you want to use the prebuilt library for your own app, please refer to
50+
[Using Android prebuilt libraries (AAR)](./android-prebuilt-library.md) for
51+
tutorial.
52+
53+
If you need to use other dependencies (like tokenizer), please refer to
54+
Alternative 2: Build from local machine option.
55+
56+
### Alternative 2: Build from local machine
3157
1. Open a terminal window and navigate to the root directory of the `executorch`.
3258
2. Set the following environment variables:
3359
```bash

examples/demo-apps/android/LlamaDemo/app/build.gradle.kts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ dependencies {
5656
implementation("androidx.camera:camera-core:1.3.0-rc02")
5757
implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha12")
5858
implementation("com.facebook.fbjni:fbjni:0.5.1")
59-
implementation("org.pytorch.executorch:executorch") {
60-
exclude("com.facebook.fbjni", "fbjni-java-only")
61-
}
59+
implementation(files("libs/executorch-llama.aar"))
6260
testImplementation("junit:junit:4.13.2")
6361
androidTestImplementation("androidx.test.ext:junit:1.1.5")
6462
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
@@ -76,3 +74,12 @@ tasks.register("setup") {
7674
}
7775
}
7876
}
77+
78+
tasks.register("download_prebuilt_lib") {
79+
doFirst {
80+
exec {
81+
commandLine("sh", "examples/demo-apps/android/LlamaDemo/download_prebuilt_lib.sh")
82+
workingDir("../../../../../")
83+
}
84+
}
85+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
set -eu
9+
10+
AAR_URL="https://ossci-android.s3.us-west-1.amazonaws.com/executorch/release/0.2.1/executorch-llama.aar"
11+
AAR_SHASUM="2973b1c41aa2c2775482d7cc7c803d0f6ca282c1"
12+
13+
LIBS_PATH="$(dirname "$0")/app/libs"
14+
AAR_PATH="${LIBS_PATH}/executorch-llama.aar"
15+
16+
mkdir -p "$LIBS_PATH"
17+
18+
if [[ ! -f "${AAR_PATH}" || "${AAR_SHASUM}" != $(shasum "${AAR_PATH}" | awk '{print $1}') ]]; then
19+
curl "${AAR_URL}" -o "${AAR_PATH}"
20+
fi

examples/demo-apps/android/LlamaDemo/settings.gradle.kts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,3 @@ dependencyResolutionManagement {
2525
rootProject.name = "ExecuTorch Demo"
2626

2727
include(":app")
28-
29-
includeBuild("../../../../extension/android")

examples/demo-apps/android/LlamaDemo/setup.sh

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ cmake extension/android \
4747

4848
cmake --build "${CMAKE_OUT}"/extension/android -j "${CMAKE_JOBS}" --config Release
4949

50-
JNI_LIBS_PATH="examples/demo-apps/android/LlamaDemo/app/src/main/jniLibs"
51-
mkdir -p "${JNI_LIBS_PATH}/${ANDROID_ABI}"
52-
cp "${CMAKE_OUT}"/extension/android/libexecutorch_llama_jni.so "${JNI_LIBS_PATH}/${ANDROID_ABI}/"
50+
BUILD_AAR_DIR="$(mktemp -d)"
51+
mkdir -p "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}" "${BUILD_AAR_DIR}/libs"
52+
cp "${CMAKE_OUT}"/extension/android/libexecutorch_llama_jni.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}"
53+
cp extension/android/build/libs/executorch.jar "${BUILD_AAR_DIR}/libs"
54+
echo \<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" \
55+
package=\"org.pytorch.executorch\"\> \
56+
\<uses-sdk android:minSdkVersion=\"19\" /\> \
57+
\</manifest\> > "${BUILD_AAR_DIR}/AndroidManifest.xml"
58+
pushd "${BUILD_AAR_DIR}"
59+
zip -r executorch-llama.aar libs jni/${ANDROID_ABI} AndroidManifest.xml
60+
popd
61+
mkdir -p examples/demo-apps/android/LlamaDemo/app/libs
62+
mv "${BUILD_AAR_DIR}/executorch-llama.aar" examples/demo-apps/android/LlamaDemo/app/libs

0 commit comments

Comments
 (0)