Skip to content
Open
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
157 changes: 96 additions & 61 deletions extension/android/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
Expand All @@ -12,65 +12,84 @@
set(CMAKE_CXX_STANDARD 17)
endif()

if(NOT ANDROID)
message(FATAL_ERROR "This directory is for Android build only")
endif()

set(EXECUTORCH_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../..")
include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake)
set(_common_compile_options
$<$<CXX_COMPILER_ID:MSVC>:/wd4996>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated-declarations -fPIC>
)
if(NOT ANDROID_PLATFORM)
set(ANDROID_PLATFORM android-30)
endif()

# We need to download fbjni library from maven, and use its "prefab" library and
# headers, and link executorch library against that fbjni library. We don't know
# which NDK is used to compile fbjni, and we need to link our executorch library
# to the version which Android APK links against for runtime to ensure the
# libc++ dependencies are consistent. WARNING # Users need to use the SAME fbjni
# version here and in app gradle dependency for runtime compatibility!
if(NOT FBJNI_VERSION)
set(FBJNI_VERSION 0.7.0)
endif()
if(NOT ANDROID)
find_package(JNI REQUIRED)
if(NOT FBJNI_HEADERS_DIR OR NOT FBJNI_LIBRARY)
message(
FATAL_ERROR
"For non-Android platforms, please specify -DFBJNI_HEADERS_DIR=/path/to/fbjni/include and -DFBJNI_LIBRARY=/path/to/libfbjni.so"
)
endif()

set(FBJNI_AAR_URL
https://repo1.maven.org/maven2/com/facebook/fbjni/fbjni/${FBJNI_VERSION}/fbjni-${FBJNI_VERSION}.aar
)
set(FBJNI_DOWNLOAD_PATH ${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/fbjni.aar)
add_library(fbjni SHARED IMPORTED)
set_target_properties(fbjni PROPERTIES IMPORTED_LOCATION "${FBJNI_LIBRARY}")
set(_common_compile_options
$<$<CXX_COMPILER_ID:MSVC>:/wd4996>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated-declarations -fPIC>
)
else()
set(_common_compile_options
$<$<CXX_COMPILER_ID:MSVC>:/wd4996>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated-declarations -fPIC>
)
if(NOT ANDROID_PLATFORM)
set(ANDROID_PLATFORM android-30)
endif()

if(NOT EXISTS "${FBJNI_DOWNLOAD_PATH}")
file(DOWNLOAD "${FBJNI_AAR_URL}" "${FBJNI_DOWNLOAD_PATH}")
endif()
# We need to download fbjni library from maven, and use its "prefab" library
# and headers, and link executorch library against that fbjni library. We
# don't know which NDK is used to compile fbjni, and we need to link our
# executorch library to the version which Android APK links against for
# runtime to ensure the libc++ dependencies are consistent. WARNING # Users
# need to use the SAME fbjni version here and in app gradle dependency for
# runtime compatibility!
if(NOT FBJNI_VERSION)
set(FBJNI_VERSION 0.7.0)
endif()

add_custom_command(
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/include/"
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/libs/android.${ANDROID_ABI}/libfbjni.so"
COMMAND unzip -o ${FBJNI_DOWNLOAD_PATH} -d
${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni
DEPENDS "${FBJNI_DOWNLOAD_PATH}"
)
set(FBJNI_AAR_URL
https://repo1.maven.org/maven2/com/facebook/fbjni/fbjni/${FBJNI_VERSION}/fbjni-${FBJNI_VERSION}.aar
)
set(FBJNI_DOWNLOAD_PATH
${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/fbjni.aar
)

add_custom_target(
fbjni_prefab
DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/include/"
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/libs/android.${ANDROID_ABI}/libfbjni.so"
)
if(NOT EXISTS "${FBJNI_DOWNLOAD_PATH}")
file(DOWNLOAD "${FBJNI_AAR_URL}" "${FBJNI_DOWNLOAD_PATH}")
endif()

add_library(fbjni SHARED IMPORTED)
add_dependencies(fbjni fbjni_prefab)
set_target_properties(
fbjni
PROPERTIES
IMPORTED_LOCATION
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/libs/android.${ANDROID_ABI}/libfbjni.so"
)
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/include/"
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/libs/android.${ANDROID_ABI}/libfbjni.so"
COMMAND unzip -o ${FBJNI_DOWNLOAD_PATH} -d
${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni
DEPENDS "${FBJNI_DOWNLOAD_PATH}"
)

add_custom_target(
fbjni_prefab
DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/include/"
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/libs/android.${ANDROID_ABI}/libfbjni.so"
)

executorch_target_link_options_shared_lib(executorch)
add_library(fbjni SHARED IMPORTED)
add_dependencies(fbjni fbjni_prefab)
set_target_properties(
fbjni
PROPERTIES
IMPORTED_LOCATION
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/libs/android.${ANDROID_ABI}/libfbjni.so"
)
endif()

if(ANDROID)
executorch_target_link_options_shared_lib(executorch)
endif()

add_library(
executorch_jni SHARED jni/jni_layer.cpp jni/log.cpp jni/jni_layer_runtime.cpp
Expand Down Expand Up @@ -233,19 +252,35 @@
include("${CMAKE_CURRENT_SOURCE_DIR}/fb/extended_targets/CMakeLists.txt")
endif()

target_include_directories(
executorch_jni
PRIVATE
${_common_include_directories}
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/include/"
)
if(ANDROID)
target_include_directories(
executorch_jni
PRIVATE
${_common_include_directories}
"${CMAKE_CURRENT_BINARY_DIR}/third-party/fbjni/prefab/modules/fbjni/include/"
)
else()
target_include_directories(
executorch_jni
PRIVATE
${_common_include_directories}
${FBJNI_HEADERS_DIR}
${JNI_INCLUDE_DIRS}
)
endif()

target_compile_options(executorch_jni PUBLIC ${_common_compile_options})

target_link_options(
executorch_jni PRIVATE
"LINKER:--version-script,${CMAKE_CURRENT_SOURCE_DIR}/jni/version_script.txt"
)
if(NOT WIN32)
target_link_options(
executorch_jni PRIVATE
"LINKER:--version-script,${CMAKE_CURRENT_SOURCE_DIR}/jni/version_script.txt"
)
endif()
target_link_options_gc_sections(executorch_jni)

target_link_libraries(executorch_jni ${link_libraries} log)
if(ANDROID)
target_link_libraries(executorch_jni ${link_libraries} log)
else()
target_link_libraries(executorch_jni ${link_libraries} ${JNI_LIBRARIES})
endif()
8 changes: 7 additions & 1 deletion extension/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ allprojects {

dependencies {
classpath 'com.android.tools.build:gradle:8.9.0'
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.34.0'
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.31.0'
classpath 'com.diffplug.spotless:spotless-plugin-gradle:8.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.23"
}
}

ext {
fbjniJavaOnlyVersion = "0.7.0"
soLoaderNativeLoaderVersion = "0.10.5"
}

repositories {
Expand Down
17 changes: 8 additions & 9 deletions extension/android/executorch_android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
*/


plugins {
id "com.android.library" version "8.9.0"
id "com.vanniktech.maven.publish" version "0.31.0"
id 'com.diffplug.spotless' version '8.0.0'
alias(libs.plugins.jetbrains.kotlin.android)
}
apply plugin: 'com.android.library'
apply plugin: 'com.vanniktech.maven.publish'
apply plugin: 'com.diffplug.spotless'
apply plugin: 'kotlin-android'

spotless {
kotlin {
Expand All @@ -37,8 +35,8 @@ android {
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

sourceSets {
Expand All @@ -50,7 +48,7 @@ android {
}
}
kotlinOptions {
jvmTarget = "11"
jvmTarget = "17"
freeCompilerArgs += ["-Xjvm-default=all"]
}
}
Expand All @@ -60,6 +58,7 @@ task copyTestRes(type: Exec) {
}

dependencies {
api project(':executorch_java')
implementation 'com.facebook.fbjni:fbjni:0.7.0'
implementation 'com.facebook.soloader:nativeloader:0.10.5'
implementation libs.core.ktx
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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

import android.util.Log as AndroidLog

/**
* Android-specific [Logger] implementation that delegates to [android.util.Log].
*
* Discovered automatically via [java.util.ServiceLoader] when the executorch-android AAR is on the
* classpath.
*/
class AndroidLogger : Logger {
override fun e(tag: String, msg: String) {
AndroidLog.e(tag, msg)
}

override fun w(tag: String, msg: String) {
AndroidLog.w(tag, msg)
}

override fun i(tag: String, msg: String) {
AndroidLog.i(tag, msg)
}

override fun d(tag: String, msg: String) {
AndroidLog.d(tag, msg)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.pytorch.executorch.AndroidLogger
1 change: 1 addition & 0 deletions extension/android/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ junit = { module = "junit:junit", version.ref = "junit" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
[plugins]
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
2 changes: 1 addition & 1 deletion extension/android/jni/jni_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ class ExecuTorchJni : public facebook::jni::HybridClass<ExecuTorchJni> {

return ret;
#else
return facebook::jni::JArrayClass<String>::newArray(0);
return facebook::jni::JArrayClass<jstring>::newArray(0);
#endif
}

Expand Down
30 changes: 30 additions & 0 deletions extension/android/jni/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,34 @@ void access_log_buffer(std::function<void(std::vector<log_entry>&)> accessor) {

} // namespace executorch::extension

#else

#include <cstdio>

namespace executorch::extension {

void access_log_buffer(std::function<void(std::vector<log_entry>&)> accessor) {
// No-op for non-Android
(void)accessor;
}

} // namespace executorch::extension

void et_pal_emit_log_message(
et_timestamp_t timestamp,
et_pal_log_level_t level,
const char* filename,
const char* function,
size_t line,
const char* message,
size_t length) {
(void)timestamp;
(void)filename;
(void)function;
(void)line;
(void)length;
// Fallback console log for JVM desktop
fprintf(stderr, "[ExecuTorch JNI %c] %s\n", level, message);
}

#endif
15 changes: 14 additions & 1 deletion extension/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,17 @@ plugins {

rootProject.name = 'executorch'

include('executorch_android')
// Shared platform-neutral API module (no android.* dependency)
include(':executorch_java')
project(':executorch_java').projectDir = new File(rootDir, '../java')

// Android module — only included when Android SDK is available
if (System.getenv("ANDROID_HOME") != null || System.getenv("ANDROID_SDK_ROOT") != null || new java.io.File(rootDir, "local.properties").exists()) {
include('executorch_android')
} else {
logger.warn("WARNING: ANDROID_HOME is not set, skipping Android subproject.")
}

// Desktop JVM module
include(':executorch_jvm')
project(':executorch_jvm').projectDir = new File(rootDir, '../jvm')
Loading
Loading