Make Java API available on Android (#3030)
This commit is contained in:
Родитель
ca2ed17ba7
Коммит
37a905f557
15
BUILD.md
15
BUILD.md
|
@ -274,18 +274,18 @@ To build ONNX Runtime with the NN API EP, first install Android NDK (see [Androi
|
|||
|
||||
#### Build Instructions
|
||||
|
||||
The basic build commands are below. There are also some other parameters for building the Android version under See [Android Build instructions](#android) for more details.
|
||||
The basic build commands are below. There are also some other parameters for building the Android version. See [Android Build instructions](#android) for more details.
|
||||
|
||||
##### Cross compiling on Windows
|
||||
|
||||
```bash
|
||||
./build.bat --android --android_ndk_path <android ndk path> --dnnlibrary
|
||||
./build.bat --android --android_sdk_path <android sdk path> --android_ndk_path <android ndk path> --dnnlibrary
|
||||
```
|
||||
|
||||
##### Cross compiling on Linux
|
||||
|
||||
```bash
|
||||
./build.sh --android --android_ndk_path <android ndk path> --dnnlibrary
|
||||
./build.sh --android --android_sdk_path <android sdk path> --android_ndk_path <android ndk path> --dnnlibrary
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -580,21 +580,22 @@ ls -l /code/onnxruntime/build/Linux/MinSizeRel/dist/*.whl
|
|||
|
||||
#### Pre-Requisites
|
||||
|
||||
Install Android NDK from https://developer.android.com/ndk/downloads
|
||||
Install Android NDK in Android Studio or https://developer.android.com/ndk/downloads
|
||||
|
||||
#### Build Instructions
|
||||
|
||||
##### Cross compiling on Windows
|
||||
|
||||
```bash
|
||||
./build.bat --android --android_ndk_path <android ndk path> --android_abi <android abi, e.g., arm64-v8a (default) or armeabi-v7a> --android_api <android api level, e.g., 27 (default)>
|
||||
./build.bat --android --android_sdk_path <android sdk path> --android_ndk_path <android ndk path> --android_abi <android abi, e.g., arm64-v8a (default) or armeabi-v7a> --android_api <android api level, e.g., 27 (default)>
|
||||
```
|
||||
|
||||
##### Cross compiling on Linux
|
||||
|
||||
```bash
|
||||
./build.sh --android --android_ndk_path <android ndk path> --android_abi <android abi, e.g., arm64-v8a (default) or armeabi-v7a> --android_api <android api level, e.g., 27 (default)>
|
||||
./build.sh --android --android_sdk_path <android sdk path> --android_ndk_path <android ndk path> --android_abi <android abi, e.g., arm64-v8a (default) or armeabi-v7a> --android_api <android api level, e.g., 27 (default)>
|
||||
```
|
||||
|
||||
If you want to use NNAPI Execution Provider on Android, see [docs/execution_providers/NNAPI-ExecutionProvider.md](/docs/execution_providers/NNAPI-ExecutionProvider.md).
|
||||
Android Archive (AAR) files, which can be imported directly in Android Studio, will be generated in your_build_dir/java/build/outputs/aar.
|
||||
|
||||
If you want to use NNAPI Execution Provider on Android, see [docs/execution_providers/NNAPI-ExecutionProvider.md](/docs/execution_providers/NNAPI-ExecutionProvider.md).
|
||||
|
|
|
@ -279,7 +279,6 @@ if(onnxruntime_BUILD_SHARED_LIB OR onnxruntime_ENABLE_PYTHON)
|
|||
find_package(PythonLibs 3.5 REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp 3.4 REQUIRED)
|
||||
find_package(PythonLibs 3.4 REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
# Setup Java compilation
|
||||
include(FindJava)
|
||||
find_package(Java REQUIRED)
|
||||
find_package(JNI REQUIRED)
|
||||
include(UseJava)
|
||||
include_directories(${JNI_INCLUDE_DIRS})
|
||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
find_package(JNI REQUIRED)
|
||||
include_directories(${JNI_INCLUDE_DIRS})
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
|
||||
|
||||
set(JAVA_ROOT ${REPO_ROOT}/java)
|
||||
|
@ -81,8 +83,13 @@ onnxruntime_add_include_to_target(onnxruntime4j_jni onnxruntime_session)
|
|||
target_include_directories(onnxruntime4j_jni PRIVATE ${REPO_ROOT}/include ${JAVA_ROOT}/build/headers)
|
||||
target_link_libraries(onnxruntime4j_jni PUBLIC onnxruntime)
|
||||
|
||||
set(JAVA_PACKAGE_OUTPUT_DIR ${JAVA_OUTPUT_DIR}/build)
|
||||
file(MAKE_DIRECTORY ${JAVA_PACKAGE_OUTPUT_DIR})
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(ANDROID_PACKAGE_OUTPUT_DIR ${JAVA_PACKAGE_OUTPUT_DIR}/android)
|
||||
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_OUTPUT_DIR})
|
||||
endif()
|
||||
# expose native libraries to the gradle build process
|
||||
file(MAKE_DIRECTORY ${JAVA_OUTPUT_DIR}/build)
|
||||
set(JAVA_PACKAGE_DIR ai/onnxruntime/native/)
|
||||
set(JAVA_NATIVE_LIB_DIR ${JAVA_OUTPUT_DIR}/native-lib)
|
||||
set(JAVA_NATIVE_JNI_DIR ${JAVA_OUTPUT_DIR}/native-jni)
|
||||
|
@ -90,7 +97,20 @@ set(JAVA_PACKAGE_LIB_DIR ${JAVA_NATIVE_LIB_DIR}/${JAVA_PACKAGE_DIR})
|
|||
set(JAVA_PACKAGE_JNI_DIR ${JAVA_NATIVE_JNI_DIR}/${JAVA_PACKAGE_DIR})
|
||||
file(MAKE_DIRECTORY ${JAVA_PACKAGE_LIB_DIR})
|
||||
file(MAKE_DIRECTORY ${JAVA_PACKAGE_JNI_DIR})
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(ANDROID_PACKAGE_JNILIBS_DIR ${JAVA_OUTPUT_DIR}/android)
|
||||
set(ANDROID_PACKAGE_ABI_DIR ${ANDROID_PACKAGE_JNILIBS_DIR}/${ANDROID_ABI})
|
||||
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_JNILIBS_DIR})
|
||||
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_ABI_DIR})
|
||||
endif()
|
||||
add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:onnxruntime> ${JAVA_PACKAGE_LIB_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime>)
|
||||
add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:onnxruntime4j_jni> ${JAVA_PACKAGE_JNI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime4j_jni>)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:onnxruntime> ${ANDROID_PACKAGE_ABI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime>)
|
||||
add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:onnxruntime4j_jni> ${ANDROID_PACKAGE_ABI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime4j_jni>)
|
||||
endif()
|
||||
# run the build process (this copies the results back into CMAKE_CURRENT_BINARY_DIR)
|
||||
add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${GRADLE_EXECUTABLE} cmakeBuild -DcmakeBuildDir=${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${JAVA_ROOT})
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${GRADLE_EXECUTABLE} -b build-android.gradle -c settings-android.gradle build -DjniLibsDir=${ANDROID_PACKAGE_JNILIBS_DIR} -DbuildDir=${ANDROID_PACKAGE_OUTPUT_DIR} WORKING_DIRECTORY ${JAVA_ROOT})
|
||||
endif()
|
||||
|
|
|
@ -574,6 +574,13 @@ add_test(NAME onnx_test_pytorch_converted
|
|||
add_test(NAME onnx_test_pytorch_operator
|
||||
COMMAND onnx_test_runner ${PROJECT_SOURCE_DIR}/external/onnx/onnx/backend/test/data/pytorch-operator)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
list(APPEND android_shared_libs log android)
|
||||
if (onnxruntime_USE_NNAPI)
|
||||
list(APPEND android_shared_libs neuralnetworks)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#perf test runner
|
||||
set(onnxruntime_perf_test_src_dir ${TEST_SRC_DIR}/perftest)
|
||||
set(onnxruntime_perf_test_src_patterns
|
||||
|
@ -611,6 +618,9 @@ if (onnxruntime_BUILD_SHARED_LIB)
|
|||
if(NOT WIN32)
|
||||
list(APPEND onnxruntime_perf_test_libs nsync_cpp)
|
||||
endif()
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
list(APPEND onnxruntime_perf_test_libs ${android_shared_libs})
|
||||
endif()
|
||||
target_link_libraries(onnxruntime_perf_test PRIVATE ${onnxruntime_perf_test_libs} Threads::Threads)
|
||||
if(WIN32)
|
||||
target_link_libraries(onnxruntime_perf_test PRIVATE debug dbghelp advapi32)
|
||||
|
@ -650,6 +660,9 @@ if (onnxruntime_BUILD_SHARED_LIB)
|
|||
if(NOT WIN32)
|
||||
list(APPEND onnxruntime_shared_lib_test_LIBS nsync_cpp)
|
||||
endif()
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
list(APPEND onnxruntime_shared_lib_test_LIBS ${android_shared_libs})
|
||||
endif()
|
||||
AddTest(DYN
|
||||
TARGET onnxruntime_shared_lib_test
|
||||
SOURCES ${onnxruntime_shared_lib_test_SRC} ${TEST_SRC_DIR}/providers/test_main.cc
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
def jniLibsDir = System.properties['jniLibsDir']
|
||||
def buildDir = System.properties['buildDir']
|
||||
|
||||
project.buildDir = buildDir
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
|
||||
android {
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = [jniLibsDir]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.1.1'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.1'
|
||||
testImplementation 'com.google.protobuf:protobuf-java:3.10.0'
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
rootProject.name = 'onnxruntime'
|
||||
rootProject.buildFileName = 'build-android.gradle'
|
|
@ -0,0 +1,2 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="ai.onnxruntime" />
|
|
@ -44,14 +44,16 @@ final class OnnxRuntime {
|
|||
if (loaded) {
|
||||
return;
|
||||
}
|
||||
Path tempDirectory = Files.createTempDirectory("onnxruntime-java");
|
||||
Path tempDirectory = isAndroid() ? null : Files.createTempDirectory("onnxruntime-java");
|
||||
try {
|
||||
load(tempDirectory, ONNXRUNTIME_LIBRARY_NAME);
|
||||
load(tempDirectory, ONNXRUNTIME_JNI_LIBRARY_NAME);
|
||||
ortApiHandle = initialiseAPIBase(ORT_API_VERSION_1);
|
||||
loaded = true;
|
||||
} finally {
|
||||
cleanUp(tempDirectory.toFile());
|
||||
if (!isAndroid()) {
|
||||
cleanUp(tempDirectory.toFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +74,15 @@ final class OnnxRuntime {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isAndroid() {
|
||||
try {
|
||||
Class.forName("android.app.Activity");
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a shared library by name.
|
||||
*
|
||||
|
@ -80,6 +91,12 @@ final class OnnxRuntime {
|
|||
* @throws IOException If the file failed to read or write.
|
||||
*/
|
||||
private static void load(Path tempDirectory, String library) throws IOException {
|
||||
// On Android, we simply use System.loadLibrary
|
||||
if (isAndroid()) {
|
||||
System.loadLibrary("onnxruntime4j_jni");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1) The user may skip loading of this library:
|
||||
String skip = System.getProperty("onnxruntime.native." + library + ".skip");
|
||||
if (Boolean.TRUE.toString().equalsIgnoreCase(skip)) {
|
||||
|
|
|
@ -120,6 +120,7 @@ Use the individual flags to only run the specified stages.
|
|||
help='')
|
||||
parser.add_argument("--android_api", type=int, default=27,
|
||||
help='Android API Level, e.g. 21')
|
||||
parser.add_argument("--android_sdk_path", type=str, help='Path to the Android SDK')
|
||||
parser.add_argument("--android_ndk_path", default="", help="Path to the Android NDK")
|
||||
|
||||
# Arguments needed by CI
|
||||
|
@ -443,7 +444,7 @@ def clean_targets(cmake_path, build_dir, configs):
|
|||
|
||||
run_subprocess(cmd_args)
|
||||
|
||||
def build_targets(cmake_path, build_dir, configs, parallel):
|
||||
def build_targets(args, cmake_path, build_dir, configs, parallel):
|
||||
for config in configs:
|
||||
log.info("Building targets for %s configuration", config)
|
||||
build_dir2 = get_config_build_dir(build_dir, config)
|
||||
|
@ -463,7 +464,11 @@ def build_targets(cmake_path, build_dir, configs, parallel):
|
|||
cmd_args += [ "--" ]
|
||||
cmd_args += build_tool_args
|
||||
|
||||
run_subprocess(cmd_args)
|
||||
env = {}
|
||||
if args.android:
|
||||
env['ANDROID_SDK_ROOT']=args.android_sdk_path
|
||||
|
||||
run_subprocess(cmd_args, env=env)
|
||||
|
||||
def add_dir_if_exists(dir, dir_list):
|
||||
if (os.path.isdir(dir)):
|
||||
|
@ -994,7 +999,7 @@ def main():
|
|||
setup_dml_build(args, cmake_path, build_dir, configs)
|
||||
|
||||
if (args.build):
|
||||
build_targets(cmake_path, build_dir, configs, args.parallel)
|
||||
build_targets(args, cmake_path, build_dir, configs, args.parallel)
|
||||
|
||||
if args.test :
|
||||
run_onnxruntime_tests(args, source_dir, ctest_path, build_dir, configs,
|
||||
|
|
|
@ -10,6 +10,6 @@ jobs:
|
|||
displayName: Clone submodules
|
||||
- script: echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'ndk-bundle'
|
||||
displayName: Install Android NDK
|
||||
- script: tools/ci_build/build.py --android --build_dir build --android_ndk $ANDROID_HOME/ndk-bundle --android_abi=x86_64 --skip_submodule_sync --parallel --use_dnnlibrary
|
||||
- script: tools/ci_build/build.py --android --build_dir build --android_sdk_path $ANDROID_HOME --android_ndk_path $ANDROID_HOME/ndk-bundle --android_abi=x86_64 --skip_submodule_sync --parallel --use_dnnlibrary
|
||||
displayName: Build and Test on Android Emulator
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче