Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .ci/scripts/build_android_instrumentation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ fi
which "${PYTHON_EXECUTABLE}"

build_android_test() {
pushd extension/android_test
ANDROID_HOME="${ANDROID_SDK:-/opt/android/sdk}" ./gradlew testDebugUnitTest
ANDROID_HOME="${ANDROID_SDK:-/opt/android/sdk}" ./gradlew build assembleAndroidTest
mkdir -p extension/android/executorch_android/src/androidTest/resources
cp extension/module/test/resources/add.pte extension/android/executorch_android/src/androidTest/resources
pushd extension/android
ANDROID_HOME="${ANDROID_SDK:-/opt/android/sdk}" ./gradlew :executorch_android:testDebugUnitTest
ANDROID_HOME="${ANDROID_SDK:-/opt/android/sdk}" ./gradlew :executorch_android:assembleAndroidTest
popd
}

Expand All @@ -24,8 +26,7 @@ collect_artifacts_to_be_uploaded() {
# Collect Java library test
JAVA_LIBRARY_TEST_DIR="${ARTIFACTS_DIR_NAME}/library_test_dir"
mkdir -p "${JAVA_LIBRARY_TEST_DIR}"
cp extension/android_test/build/outputs/apk/debug/*.apk "${JAVA_LIBRARY_TEST_DIR}"
cp extension/android_test/build/outputs/apk/androidTest/debug/*.apk "${JAVA_LIBRARY_TEST_DIR}"
cp extension/android/executorch_android/build/outputs/apk/androidTest/debug/*.apk "${JAVA_LIBRARY_TEST_DIR}"
}

main() {
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/_android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ jobs:
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-linux.sh --build-tool buck2
export ARTIFACTS_DIR_NAME=artifacts-to-be-uploaded

mkdir -p ${ARTIFACTS_DIR_NAME}/fp32-xnnpack-custom
bash examples/models/llama/install_requirements.sh
bash ".ci/scripts/test_llama.sh" -model stories110M -build_tool cmake -dtype fp16 -mode portable -upload ${ARTIFACTS_DIR_NAME}/fp32-xnnpack-custom

# Build LLM Demo for Android
export BUILD_AAR_DIR=aar-out
mkdir -p $BUILD_AAR_DIR
bash build/build_android_library.sh ${ARTIFACTS_DIR_NAME}
bash .ci/scripts/build_android_instrumentation.sh ${ARTIFACTS_DIR_NAME}

mkdir -p ${ARTIFACTS_DIR_NAME}/fp32-xnnpack-custom
bash ".ci/scripts/test_llama.sh" -model stories110M -build_tool cmake -dtype fp16 -mode portable -upload ${ARTIFACTS_DIR_NAME}/fp32-xnnpack-custom

mkdir -p examples/demo-apps/android/LlamaDemo/app/libs
cp aar-out/executorch.aar examples/demo-apps/android/LlamaDemo/app/libs
pushd examples/demo-apps/android/LlamaDemo
Expand Down Expand Up @@ -94,7 +96,6 @@ jobs:
curl -O https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/llm_demo/app-debug.apk
curl -O https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/llm_demo/app-debug-androidTest.apk
curl -O https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/fp32-xnnpack-custom/model.zip
curl -o android-test-debug.apk https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/library_test_dir/executorch-debug.apk
curl -o android-test-debug-androidTest.apk https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/library_test_dir/executorch-debug-androidTest.apk
unzip model.zip
mv *.pte model.pte
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/doc-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
with:
job-name: Build doc
runner: linux.2xlarge
docker-image: executorch-ubuntu-22.04-clang12
docker-image: executorch-ubuntu-22.04-clang12-android
submodules: 'true'
repository: pytorch/executorch
upload-artifact: docs
Expand Down Expand Up @@ -70,8 +70,8 @@ jobs:

# Build javadoc:
cd extension/android
./gradlew javadoc
cp -rf build/docs/javadoc "${RUNNER_DOCS_DIR}"
ANDROID_HOME="${ANDROID_SDK:-/opt/android/sdk}" ./gradlew :executorch_android:javaDocReleaseGeneration
cp -rf executorch_android/build/intermediates/java_doc_dir/release/javaDocReleaseGeneration "${RUNNER_DOCS_DIR}/javadoc"
cd ../..

# If it's main branch, add noindex tag to all .html files to exclude from Google Search indexing.
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ jobs:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
timeout: 90
script: |
FILES_NEEDS_FORMAT=$(/opt/google-java-format -n extension/android/src/main/java/org/pytorch/executorch/*.java \
examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/*.java \
FILES_NEEDS_FORMAT=$(/opt/google-java-format -n \
extension/android/executorch_android/src/main/java/org/pytorch/executorch/*.java \
examples/demo-apps/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/*.java \
extension/benchmark/android/benchmark/app/src/main/java/org/pytorch/minibench/*.java)
if [ -n "$FILES_NEEDS_FORMAT" ]; then
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/pull.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
- runner: linux.arm64.2xlarge
docker-image: executorch-ubuntu-22.04-clang12
# TODO: Need to figure out why buck2 doesnt work on Graviton instances.
- runner: linux.arm64.2xlarge
- runner: linux.arm64.2xlarge
build-tool: buck2
fail-fast: false
with:
Expand Down Expand Up @@ -420,7 +420,6 @@ jobs:
permissions:
id-token: write
contents: read
needs: test-llama-runner-linux

unittest:
uses: ./.github/workflows/_unittest.yml
Expand Down
51 changes: 22 additions & 29 deletions build/build_android_library.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,9 @@ if [[ -z "${PYTHON_EXECUTABLE:-}" ]]; then
fi
which "${PYTHON_EXECUTABLE}"

build_jar() {
pushd extension/android
./gradlew build
popd
mkdir -p "${BUILD_AAR_DIR}/libs"
cp extension/android/build/libs/executorch.jar "${BUILD_AAR_DIR}/libs/"
copy_src() {
cp -r extension/android/build.gradle extension/android/settings.gradle extension/android/gradlew extension/android/gradle extension/android/gradlew.bat extension/android/gradle.properties "${BUILD_AAR_DIR}"
cp -r extension/android/executorch_android "${BUILD_AAR_DIR}/executorch_android"
}

build_android_native_library() {
Expand Down Expand Up @@ -96,44 +93,40 @@ build_android_native_library() {
cmake --build "${CMAKE_OUT}"/extension/android -j "${CMAKE_JOBS}" --config "${EXECUTORCH_CMAKE_BUILD_TYPE}"

# Copy artifacts to ABI specific directory
mkdir -p "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}"
cp "${CMAKE_OUT}"/extension/android/*.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
mkdir -p "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}"
cp "${CMAKE_OUT}"/extension/android/*.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"

# Copy QNN related so library
if [ -n "$QNN_SDK_ROOT" ] && [ "$ANDROID_ABI" == "arm64-v8a" ]; then
cp "${CMAKE_OUT}"/lib/libqnn_executorch_backend.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtp.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnSystem.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtpV69Stub.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtpV73Stub.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtpV75Stub.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/hexagon-v69/unsigned/libQnnHtpV69Skel.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/hexagon-v73/unsigned/libQnnHtpV73Skel.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/hexagon-v75/unsigned/libQnnHtpV75Skel.so "${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/"
cp "${CMAKE_OUT}"/lib/libqnn_executorch_backend.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtp.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnSystem.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtpV69Stub.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtpV73Stub.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/aarch64-android/libQnnHtpV75Stub.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/hexagon-v69/unsigned/libQnnHtpV69Skel.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/hexagon-v73/unsigned/libQnnHtpV73Skel.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
cp "${QNN_SDK_ROOT}"/lib/hexagon-v75/unsigned/libQnnHtpV75Skel.so "${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/"
fi

# Copy MTK related so library
if [ -n "$NEURON_BUFFER_ALLOCATOR_LIB" ] && [ -n "$NEURON_USDK_ADAPTER_LIB" ] && [ "$ANDROID_ABI" == "arm64-v8a" ]; then
cp "${CMAKE_OUT}"/backends/mediatek/libneuron_backend.so ${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/
cp "${NEURON_BUFFER_ALLOCATOR_LIB}" ${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/
cp "${NEURON_USDK_ADAPTER_LIB}" ${BUILD_AAR_DIR}/jni/${ANDROID_ABI}/
cp "${CMAKE_OUT}"/backends/mediatek/libneuron_backend.so ${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/
cp "${NEURON_BUFFER_ALLOCATOR_LIB}" ${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/
cp "${NEURON_USDK_ADAPTER_LIB}" ${BUILD_AAR_DIR}/executorch_android/src/main/jniLibs/${ANDROID_ABI}/
fi
}

build_aar() {
echo \<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" \
package=\"org.pytorch.executorch\"\> \
\<uses-sdk android:minSdkVersion=\"19\" /\> \
\</manifest\> > "${BUILD_AAR_DIR}/AndroidManifest.xml"
pushd "${BUILD_AAR_DIR}"
# Rename libexecutorch_jni.so to libexecutorch.so for soname consistency
# between Java and JNI
find jni -type f -name "libexecutorch_jni.so" -exec bash -c 'mv "$1" "${1/_jni/}"' bash {} \;
find . -type f -name "libexecutorch_jni.so" -exec bash -c 'mv "$1" "${1/_jni/}"' bash {} \;
if [ "$EXECUTORCH_CMAKE_BUILD_TYPE" == "Release" ]; then
find jni -type f -name "*.so" -exec "$ANDROID_NDK"/toolchains/llvm/prebuilt/*/bin/llvm-strip {} \;
find . -type f -name "*.so" -exec "$ANDROID_NDK"/toolchains/llvm/prebuilt/*/bin/llvm-strip {} \;
fi
# Zip all necessary files into the AAR file
zip -r executorch.aar libs jni/*/libexecutorch.so jni/*/libqnn*.so jni/*/libQnn*.so jni/*/libneuron_backend.so jni/*/libneuron_buffer_allocator.so jni/*/libneuronusdk_adapter.mtk.so AndroidManifest.xml
ANDROID_HOME="${ANDROID_SDK:-/opt/android/sdk}" ./gradlew build
cp executorch_android/build/outputs/aar/executorch_android-debug.aar executorch.aar
popd
}

Expand All @@ -149,7 +142,7 @@ main() {

ARTIFACTS_DIR_NAME="$1"

build_jar
copy_src
for ANDROID_ABI in "${ANDROID_ABIS[@]}"; do
build_android_native_library ${ANDROID_ABI}
done
Expand Down
8 changes: 3 additions & 5 deletions build/run_android_emulator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ adb push model.pte /data/local/tmp/llama
adb push tokenizer.bin /data/local/tmp/llama
adb shell am instrument -w -r com.example.executorchllamademo.test/androidx.test.runner.AndroidJUnitRunner

adb uninstall org.pytorch.executorch || true
adb uninstall org.pytorch.executorch.test || true
adb install -t android-test-debug.apk
adb install -t android-test-debug-androidTest.apk
# adb uninstall org.pytorch.executorch.test || true
# adb install -t android-test-debug-androidTest.apk

adb shell am instrument -w -r org.pytorch.executorch.test/androidx.test.runner.AndroidJUnitRunner
# adb shell am instrument -w -r org.pytorch.executorch.test/androidx.test.runner.AndroidJUnitRunner
16 changes: 8 additions & 8 deletions extension/android/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ oncall("executorch")
fb_android_library(
name = "executorch",
srcs = [
"src/main/java/org/pytorch/executorch/DType.java",
"src/main/java/org/pytorch/executorch/EValue.java",
"src/main/java/org/pytorch/executorch/Module.java",
"src/main/java/org/pytorch/executorch/NativePeer.java",
"src/main/java/org/pytorch/executorch/Tensor.java",
"src/main/java/org/pytorch/executorch/annotations/Experimental.java",
"executorch_android/src/main/java/org/pytorch/executorch/DType.java",
"executorch_android/src/main/java/org/pytorch/executorch/EValue.java",
"executorch_android/src/main/java/org/pytorch/executorch/Module.java",
"executorch_android/src/main/java/org/pytorch/executorch/NativePeer.java",
"executorch_android/src/main/java/org/pytorch/executorch/Tensor.java",
"executorch_android/src/main/java/org/pytorch/executorch/annotations/Experimental.java",
],
autoglob = False,
language = "JAVA",
Expand All @@ -23,8 +23,8 @@ fb_android_library(
fb_android_library(
name = "executorch_llama",
srcs = [
"src/main/java/org/pytorch/executorch/extension/llm/LlmCallback.java",
"src/main/java/org/pytorch/executorch/extension/llm/LlmModule.java",
"executorch_android/src/main/java/org/pytorch/executorch/extension/llm/LlmCallback.java",
"executorch_android/src/main/java/org/pytorch/executorch/extension/llm/LlmModule.java",
],
autoglob = False,
language = "JAVA",
Expand Down
42 changes: 24 additions & 18 deletions extension/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
allprojects {
buildscript {
ext {
minSdkVersion = 21
targetSdkVersion = 34
compileSdkVersion = 34
buildToolsVersion = '33.0.1'

plugins {
id 'java-library'
}
fbjniJavaOnlyVersion = "0.5.1"
soLoaderNativeLoaderVersion = "0.10.5"
}

group 'org.pytorch.executorch'
repositories {
google()
mavenCentral()
}

repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.9.0'
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.31.0'
}

}

task makeJar(type: Jar) {
dependencies {
implementation 'com.facebook.fbjni:fbjni-java-only:0.5.1'
implementation 'com.facebook.soloader:nativeloader:0.10.5'
repositories {
google()
jcenter()
mavenCentral()
}
}
85 changes: 85 additions & 0 deletions extension/android/executorch_android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

plugins {
id "com.android.library" version "8.9.0"
id "com.vanniktech.maven.publish" version "0.31.0"
}

android {
namespace = "org.pytorch.executorch"
compileSdk = 34

defaultConfig {
minSdk = 23

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

sourceSets {
androidTest {
resources.srcDirs += [ 'src/androidTest/resources' ]
}
}
}

dependencies {
implementation 'com.facebook.fbjni:fbjni-java-only:0.5.1'
implementation 'com.facebook.soloader:nativeloader:0.10.5'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'commons-io:commons-io:2.4'
}

import com.vanniktech.maven.publish.SonatypeHost

mavenPublishing {
publishToMavenCentral(SonatypeHost.DEFAULT)
signAllPublications()

coordinates("org.pytorch", "executorch-android", "0.5.0-SNAPSHOT")

pom {
name = "ExecuTorch Android"
description = "ExecuTorch Android API"
inceptionYear = "2025"
url = "https://github.com/pytorch/executorch/"
licenses {
license {
name = "BSD 3-Clause"
url = "https://github.com/pytorch/executorch/blob/main/LICENSE"
distribution = "https://github.com/pytorch/executorch/blob/main/LICENSE"
}
}
developers {
developer {
id = "pytorch"
name = "pytorch"
url = "https://github.com/pytorch/executorch/"
}
}
scm {
url = "https://github.com/pytorch/executorch.git"
connection = "scm:git:https://github.com/pytorch/executorch"
developerConnection = "scm:git:git@github.com:pytorch/executorch.git"
}
}

}

repositories {
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/

package com.example.executorch;
package org.pytorch.executorch;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -34,13 +34,10 @@
import org.apache.commons.io.FileUtils;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
import org.pytorch.executorch.extension.llm.LlmModule;
import org.pytorch.executorch.extension.llm.LlmCallback;
import org.pytorch.executorch.Module;
import org.pytorch.executorch.EValue;
import org.pytorch.executorch.Tensor;
import org.pytorch.executorch.extension.llm.LlmModule;

/** Unit tests for {@link LlmModule}. */
/** Unit tests for {@link org.pytorch.executorch.extension.llm.LlmModule}. */
@RunWith(AndroidJUnit4.class)
public class LlmModuleInstrumentationTest implements LlmCallback {
private static String TEST_FILE_NAME = "/tinyllama_portable_fp16_h.pte";
Expand Down
Loading
Loading