Skip to content
Open
2 changes: 1 addition & 1 deletion docs/source/using-executorch-android.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ All ExecuTorch Android libraries are packaged into an Android library (AAR), exe

The AAR artifact contains the Java library for users to integrate with their Java/Kotlin application code, as well as the corresponding JNI library (.so file), which is loaded by the Java code during initialization.

- [Java library](https://github.com/pytorch/executorch/tree/main/extension/android/executorch_android/src/main/java/org/pytorch/executorch)
- [Java library](https://github.com/pytorch/executorch/tree/main/extension/java/src/main/java/org/pytorch/executorch) <!-- @lint-ignore (path exists only after this PR lands) -->
- [Java API Reference (Javadoc)](https://pytorch.org/executorch/main/javadoc/index.html)
- JNI contains the JNI binding for the corresponding Java code, and ExecuTorch native library, including
- Core ExecuTorch runtime libraries
Expand Down
45 changes: 30 additions & 15 deletions extension/android/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,35 @@ load("@fbsource//tools/build_defs/android:fb_android_library.bzl", "fb_android_l

oncall("executorch")

# NOTE: the platform-neutral sources live in the shared source directory
# extension/java/src/main/java and are referenced here in place, so the
# Android targets keep their historical names, ownership, and attributes
# (required_for_source_only_abi, pure_kotlin, deps) while compiling the
# exact same classes as before the move. Log.kt is the Android-backed
# implementation of the org.pytorch.executorch.Log facade that the shared
# sources reference.
#
# MAINTENANCE: Gradle globs the shared directory (java.srcDirs) while the
# srcs lists below are explicit per-file. When adding a shared source under
# extension/java/src/main/java, add it to the matching target here in the
# same change — otherwise the OSS AAR picks it up while this build silently
# omits it.

non_fbcode_target(_kind = fb_android_library,
name = "executorch",
warnings_as_errors = False,
required_for_source_only_abi = True,
srcs = [
"executorch_android/src/main/java/org/pytorch/executorch/BackendOptionsMap.kt",
"executorch_android/src/main/java/org/pytorch/executorch/DType.kt",
"executorch_android/src/main/java/org/pytorch/executorch/EValue.kt",
"executorch_android/src/main/java/org/pytorch/executorch/ExecuTorchRuntime.kt",
"executorch_android/src/main/java/org/pytorch/executorch/ExecutorchRuntimeException.kt",
"executorch_android/src/main/java/org/pytorch/executorch/MethodMetadata.kt",
"executorch_android/src/main/java/org/pytorch/executorch/Module.kt",
"executorch_android/src/main/java/org/pytorch/executorch/Tensor.kt",
"executorch_android/src/main/java/org/pytorch/executorch/annotations/Experimental.kt",
"../java/src/main/java/org/pytorch/executorch/BackendOptionsMap.kt",
"../java/src/main/java/org/pytorch/executorch/DType.kt",
"../java/src/main/java/org/pytorch/executorch/EValue.kt",
"../java/src/main/java/org/pytorch/executorch/ExecuTorchRuntime.kt",
"../java/src/main/java/org/pytorch/executorch/ExecutorchRuntimeException.kt",
"../java/src/main/java/org/pytorch/executorch/MethodMetadata.kt",
"../java/src/main/java/org/pytorch/executorch/Module.kt",
"../java/src/main/java/org/pytorch/executorch/Tensor.kt",
"../java/src/main/java/org/pytorch/executorch/annotations/Experimental.kt",
"executorch_android/src/main/java/org/pytorch/executorch/Log.kt",
],
autoglob = False,
language = "KOTLIN",
Expand All @@ -34,8 +49,8 @@ non_fbcode_target(_kind = fb_android_library,
name = "executorch_training",
warnings_as_errors = False,
srcs = [
"executorch_android/src/main/java/org/pytorch/executorch/training/SGD.kt",
"executorch_android/src/main/java/org/pytorch/executorch/training/TrainingModule.kt",
"../java/src/main/java/org/pytorch/executorch/training/SGD.kt",
"../java/src/main/java/org/pytorch/executorch/training/TrainingModule.kt",
],
autoglob = False,
language = "KOTLIN",
Expand All @@ -50,10 +65,10 @@ non_fbcode_target(_kind = fb_android_library,
name = "executorch_llama",
warnings_as_errors = False,
srcs = [
"executorch_android/src/main/java/org/pytorch/executorch/extension/llm/LlmCallback.kt",
"executorch_android/src/main/java/org/pytorch/executorch/extension/llm/LlmGenerationConfig.kt",
"executorch_android/src/main/java/org/pytorch/executorch/extension/llm/LlmModule.kt",
"executorch_android/src/main/java/org/pytorch/executorch/extension/llm/LlmModuleConfig.kt",
"../java/src/main/java/org/pytorch/executorch/extension/llm/LlmCallback.kt",
"../java/src/main/java/org/pytorch/executorch/extension/llm/LlmGenerationConfig.kt",
"../java/src/main/java/org/pytorch/executorch/extension/llm/LlmModule.kt",
"../java/src/main/java/org/pytorch/executorch/extension/llm/LlmModuleConfig.kt",
],
autoglob = False,
language = "KOTLIN",
Expand Down
5 changes: 4 additions & 1 deletion extension/android/executorch_android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ plugins {

spotless {
kotlin {
target '**/*.kt'
target '**/*.kt', '../../java/src/main/java/**/*.kt'
ktfmt()
}
}
Expand Down Expand Up @@ -44,6 +44,9 @@ android {
sourceSets {
main {
jniLibs.srcDirs = ['../../../cmake-out-android-so/']
// Platform-neutral API sources shared with the desktop JVM artifact.
// They are compiled directly into this AAR, keeping it self-contained.
java.srcDirs += ['../../java/src/main/java']
}
androidTest {
resources.srcDirs += ['src/androidTest/resources']
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.
*/

package org.pytorch.executorch

/**
* Platform logging facade used by the shared sources under extension/java.
*
* <p>The shared sources reference [Log] by simple name (same package, no import), and each platform
* artifact compiles its own implementation:
* <ul>
* <li>Android (this file): delegates to [android.util.Log], so logcat output — tags, priorities,
* and messages — is byte-for-byte identical to logging directly from the caller.
* <li>Desktop JVM (extension/jvm, added separately): a console-backed implementation.
* </ul>
*
* The shared source set itself contains no [Log] definition, so there is exactly one implementation
* per artifact and no duplicate-class collision.
*/
internal object Log {
@JvmStatic fun v(tag: String, msg: String): Int = android.util.Log.v(tag, msg)

@JvmStatic fun d(tag: String, msg: String): Int = android.util.Log.d(tag, msg)

@JvmStatic fun i(tag: String, msg: String): Int = android.util.Log.i(tag, msg)

@JvmStatic fun w(tag: String, msg: String): Int = android.util.Log.w(tag, msg)

@JvmStatic fun w(tag: String, msg: String, tr: Throwable): Int = android.util.Log.w(tag, msg, tr)

@JvmStatic fun e(tag: String, msg: String): Int = android.util.Log.e(tag, msg)

@JvmStatic fun e(tag: String, msg: String, tr: Throwable): Int = android.util.Log.e(tag, msg, tr)
}
42 changes: 42 additions & 0 deletions extension/java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ExecuTorch shared Java sources

This directory holds the **platform-neutral** Java/Kotlin API sources
(`Module`, `Tensor`, `EValue`, `DType`, `LlmModule`, `AsrModule`, training,
…) that are shared by every Java-platform artifact.

## How the sources are consumed

These sources are **not** published as their own artifact. Each platform
build compiles them directly into its own, self-contained artifact by
referencing this directory as an additional source root:

- **Android** (`extension/android/executorch_android`) adds
`../../java/src/main/java` via `java.srcDirs`, so the shipping AAR embeds
the same classes it always has — no new transitive dependency, unchanged
bytecode target (Java 11), unchanged manifest.
- **Desktop JVM** (`extension/jvm`, added separately) compiles the same
sources into its own jar.

## Contract for sources in this directory

1. **No platform APIs.** Sources here must not import `android.*`,
`java.awt.*`, or any other platform-specific API. The only permitted
dependencies are the JDK, fbjni, and soloader.
2. **Logging goes through the `org.pytorch.executorch.Log` facade.** The
facade is referenced by simple name (same package, no import) and is
*not* defined in this directory. Each platform artifact compiles exactly
one implementation (Android: backed by `android.util.Log`; desktop:
console-backed), so there is never a duplicate-class collision and each
platform keeps its native logging behavior.
3. **Native library loading stays per-platform.** Shared sources load the
native library through soloader's `NativeLoader`, whose delegate is
configured by the platform runtime, not by a cross-platform mutable
global.

## Adding a source here

Gradle (`extension/android/executorch_android/build.gradle`) globs this whole
directory, but `extension/android/BUCK` lists each shared file explicitly.
**Update the matching BUCK target's `srcs` in the same change** whenever you
add or remove a file here — otherwise the OSS AAR picks it up while the Buck
build silently omits it.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

package org.pytorch.executorch

import android.util.Log
import com.facebook.jni.HybridData
import com.facebook.jni.annotations.DoNotStrip
import java.nio.Buffer
Expand Down
Loading