mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-14 20:48:00 +00:00
Add Android AAR packaging script for ORT-Mobile (#7138)
* Add Android aar packaging script for ORT-Mobile * Address CR comments
This commit is contained in:
parent
0fdef1bf47
commit
d500c5952b
5 changed files with 326 additions and 10 deletions
|
|
@ -41,6 +41,11 @@ set(JAVA_OUTPUT_JAR ${JAVA_ROOT}/build/libs/onnxruntime.jar)
|
|||
set(GRADLE_ARGS clean jar)
|
||||
if(WIN32)
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} -Dorg.gradle.daemon=false)
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
# For Android build, we may run gradle multiple times in same build,
|
||||
# sometimes gradle JVM will run out of memory if we keep the daemon running
|
||||
# it is better to not keep a daemon running
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} --no-daemon)
|
||||
endif()
|
||||
if(onnxruntime_USE_CUDA)
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} -DUSE_CUDA=1)
|
||||
|
|
@ -188,6 +193,11 @@ endif()
|
|||
set(GRADLE_ARGS cmakeBuild -DcmakeBuildDir=${CMAKE_CURRENT_BINARY_DIR})
|
||||
if(WIN32)
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} -Dorg.gradle.daemon=false)
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
# For Android build, we may run gradle multiple times in same build,
|
||||
# sometimes gradle JVM will run out of memory if we keep the daemon running
|
||||
# it is better to not keep a daemon running
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} --no-daemon)
|
||||
endif()
|
||||
if(onnxruntime_USE_CUDA)
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} -DUSE_CUDA=1)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,29 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
def jniLibsDir = System.properties['jniLibsDir']
|
||||
def buildDir = System.properties['buildDir']
|
||||
def publishDir = System.properties['publishDir']
|
||||
def minSdkVer = System.properties['minSdkVer']
|
||||
def targetSdkVer = System.properties['targetSdkVer']
|
||||
|
||||
// Since Android requires a higher numbers indicating more recent versions
|
||||
// This function assume ORT version number will be in formart of A.B.C such as 1.7.0
|
||||
// We generate version code A[0{0,1}]B[0{0,1}]C,
|
||||
// for example '1.7.0' -> 10700, '1.6.15' -> 10615
|
||||
def getVersionCode(String version){
|
||||
String[] codes = version.split('\\.');
|
||||
// This will have problem if we have 3 digit [sub]version number, such as 1.7.199
|
||||
// but it is highly unlikely to happen
|
||||
String versionCodeStr = String.format("%d%02d%02d", codes[0] as int, codes[1] as int, codes[2] as int);
|
||||
return versionCodeStr as int;
|
||||
}
|
||||
|
||||
project.buildDir = buildDir
|
||||
project.version = rootProject.file('../VERSION_NUMBER').text.trim()
|
||||
project.group = "com.microsoft.onnxruntime"
|
||||
|
||||
def mavenArtifactId = project.name + '-mobile'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
|
|
@ -30,13 +50,12 @@ android {
|
|||
buildToolsVersion "29.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
minSdkVersion minSdkVer
|
||||
targetSdkVersion targetSdkVer
|
||||
versionCode = getVersionCode(project.version)
|
||||
versionName = project.version
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
@ -44,15 +63,18 @@ android {
|
|||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
debuggable false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
|
@ -60,6 +82,27 @@ android {
|
|||
jniLibs.srcDirs = [jniLibsDir]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier "sources"
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
}
|
||||
|
||||
task javadoc(type: Javadoc) {
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier = 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives javadocJar
|
||||
archives sourcesJar
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
@ -67,3 +110,53 @@ dependencies {
|
|||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
|
||||
testImplementation 'com.google.protobuf:protobuf-java:3.10.0'
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
groupId = project.group
|
||||
artifactId = mavenArtifactId
|
||||
version = project.version
|
||||
|
||||
// Three artifacts, the `aar`, the sources and the javadoc
|
||||
artifact("$buildDir/outputs/aar/${project.name}-release.aar")
|
||||
artifact javadocJar
|
||||
artifact sourcesJar
|
||||
|
||||
pom {
|
||||
name = 'onnx-runtime'
|
||||
description = 'ONNX Runtime is a performance-focused inference engine for ONNX (Open Neural Network Exchange) models.'
|
||||
url = 'https://microsoft.github.io/onnxruntime/'
|
||||
licenses {
|
||||
license {
|
||||
name = 'MIT License'
|
||||
url = 'https://opensource.org/licenses/MIT'
|
||||
}
|
||||
}
|
||||
organization {
|
||||
name = 'Microsoft'
|
||||
url = 'http://www.microsoft.com'
|
||||
}
|
||||
scm {
|
||||
connection = 'scm:git:git://github.com:microsoft/onnxruntime.git'
|
||||
developerConnection = 'scm:git:ssh://github.com/microsoft/onnxruntime.git'
|
||||
url = 'http://github.com/microsoft/onnxruntime'
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'onnxruntime'
|
||||
name = 'ONNX Runtime'
|
||||
email = 'onnxruntime@microsoft.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//publish to filesystem repo
|
||||
repositories{
|
||||
maven {
|
||||
url "$publishDir"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,8 +280,12 @@ def parse_arguments():
|
|||
choices=["armeabi-v7a", "arm64-v8a", "x86", "x86_64"],
|
||||
help="Specify the target Android Application Binary Interface (ABI)")
|
||||
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")
|
||||
parser.add_argument(
|
||||
"--android_sdk_path", type=str, default=os.environ.get("ANDROID_HOME", ""),
|
||||
help="Path to the Android SDK")
|
||||
parser.add_argument(
|
||||
"--android_ndk_path", type=str, default=os.environ.get("ANDROID_NDK_HOME", ""),
|
||||
help="Path to the Android NDK")
|
||||
parser.add_argument("--android_cpp_shared", action="store_true",
|
||||
help="Build with shared libc++ instead of the default static libc++.")
|
||||
parser.add_argument("--android_run_emulator", action="store_true",
|
||||
|
|
@ -797,8 +801,13 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home
|
|||
cmake_args += ["-Donnxruntime_NNAPI_MIN_API=" + str(args.nnapi_min_api)]
|
||||
|
||||
if args.android:
|
||||
if not args.android_ndk_path:
|
||||
raise BuildError("android_ndk_path required to build for Android")
|
||||
if not args.android_sdk_path:
|
||||
raise BuildError("android_sdk_path required to build for Android")
|
||||
cmake_args += [
|
||||
"-DCMAKE_TOOLCHAIN_FILE=" + args.android_ndk_path + "/build/cmake/android.toolchain.cmake",
|
||||
"-DCMAKE_TOOLCHAIN_FILE=" + os.path.join(
|
||||
args.android_ndk_path, 'build', 'cmake', 'android.toolchain.cmake'),
|
||||
"-DANDROID_PLATFORM=android-" + str(args.android_api),
|
||||
"-DANDROID_ABI=" + str(args.android_abi)
|
||||
]
|
||||
|
|
|
|||
180
tools/ci_build/github/android/build_aar_package.py
Normal file
180
tools/ci_build/github/android/build_aar_package.py
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
REPO_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..", "..", "..", ".."))
|
||||
BUILD_PY = os.path.normpath(os.path.join(REPO_DIR, "tools", "ci_build", "build.py"))
|
||||
JAVA_ROOT = os.path.normpath(os.path.join(REPO_DIR, "java"))
|
||||
|
||||
# We by default will build all 4 ABIs
|
||||
DEFAULT_BUILD_ABIS = ["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]
|
||||
# Android API 21 is the lowest API version we support
|
||||
DEFAULT_ANDROID_MIN_SDK_VER = 21
|
||||
# Android API 28 is the default target API version for Android builds
|
||||
DEFAULT_ANDROID_TARGET_SDK_VER = 28
|
||||
|
||||
|
||||
def _parse_build_settings(args):
|
||||
_setting_file = args.build_settings_file.resolve()
|
||||
|
||||
if not _setting_file.is_file():
|
||||
raise FileNotFoundError('Build config file {} is not a file.'.format(_setting_file))
|
||||
|
||||
with open(_setting_file) as f:
|
||||
_build_settings_data = json.load(f)
|
||||
|
||||
build_settings = {}
|
||||
build_settings['android_sdk_path'] = args.android_sdk_path
|
||||
build_settings['android_ndk_path'] = args.android_ndk_path
|
||||
|
||||
if 'build_flavor' in _build_settings_data:
|
||||
build_settings['build_flavor'] = _build_settings_data['build_flavor']
|
||||
else:
|
||||
raise ValueError('build_flavor is required in the build config file')
|
||||
|
||||
if 'build_abis' in _build_settings_data:
|
||||
build_settings['build_abis'] = _build_settings_data['build_abis']
|
||||
else:
|
||||
build_settings['build_abis'] = DEFAULT_BUILD_ABIS
|
||||
|
||||
build_params = []
|
||||
if 'build_params' in _build_settings_data:
|
||||
build_params += _build_settings_data['build_params']
|
||||
else:
|
||||
raise ValueError('build_params is required in the build config file')
|
||||
|
||||
if 'android_min_sdk_version' in _build_settings_data:
|
||||
build_settings['android_min_sdk_version'] = _build_settings_data['android_min_sdk_version']
|
||||
else:
|
||||
build_settings['android_min_sdk_version'] = DEFAULT_ANDROID_MIN_SDK_VER
|
||||
build_params += ['--android_api=' + str(build_settings['android_min_sdk_version'])]
|
||||
|
||||
if 'android_target_sdk_version' in _build_settings_data:
|
||||
build_settings['android_target_sdk_version'] = _build_settings_data['android_target_sdk_version']
|
||||
else:
|
||||
build_settings['android_target_sdk_version'] = DEFAULT_ANDROID_TARGET_SDK_VER
|
||||
|
||||
if build_settings['android_min_sdk_version'] > build_settings['android_target_sdk_version']:
|
||||
raise ValueError(
|
||||
'android_min_sdk_version {} cannot be larger than android_target_sdk_version {}'.format(
|
||||
build_settings['android_min_sdk_version'], build_settings['android_target_sdk_version']
|
||||
))
|
||||
|
||||
build_settings['build_params'] = build_params
|
||||
return build_settings
|
||||
|
||||
|
||||
def _build_aar(args):
|
||||
build_settings = _parse_build_settings(args)
|
||||
build_dir = args.build_dir
|
||||
|
||||
# Setup temp environment for building
|
||||
my_env = os.environ.copy()
|
||||
my_env['ANDROID_HOME'] = build_settings['android_sdk_path']
|
||||
my_env['ANDROID_NDK_HOME'] = build_settings['android_ndk_path']
|
||||
|
||||
# Temp dirs to hold building results
|
||||
_intermediates_dir = os.path.join(build_dir, 'intermediates')
|
||||
_build_flavor = build_settings['build_flavor']
|
||||
_aar_dir = os.path.join(_intermediates_dir, 'aar', _build_flavor)
|
||||
_jnilibs_dir = os.path.join(_intermediates_dir, 'jnilibs', _build_flavor)
|
||||
_base_build_command = [
|
||||
'python3', BUILD_PY, '--config=' + _build_flavor
|
||||
] + build_settings['build_params']
|
||||
|
||||
# Build binary for each ABI, one by one
|
||||
for abi in build_settings['build_abis']:
|
||||
_build_dir = os.path.join(_intermediates_dir, abi)
|
||||
_build_command = _base_build_command + [
|
||||
'--android_abi=' + abi,
|
||||
'--build_dir=' + _build_dir
|
||||
]
|
||||
|
||||
if args.include_ops_by_config is not None:
|
||||
_build_command += ['--include_ops_by_config=' + args.include_ops_by_config]
|
||||
|
||||
subprocess.run(_build_command, env=my_env, shell=False, check=True, cwd=REPO_DIR)
|
||||
|
||||
# create symbolic links for libonnxruntime.so and libonnxruntime4j_jni.so
|
||||
# to jnilibs/[abi] for later compiling the aar package
|
||||
_jnilibs_abi_dir = os.path.join(_jnilibs_dir, abi)
|
||||
os.makedirs(_jnilibs_abi_dir, exist_ok=True)
|
||||
for lib_name in ['libonnxruntime.so', 'libonnxruntime4j_jni.so']:
|
||||
_target_lib_name = os.path.join(_jnilibs_abi_dir, lib_name)
|
||||
# if the symbolic already exists, delete it first
|
||||
if os.path.exists(_target_lib_name):
|
||||
os.remove(_target_lib_name)
|
||||
os.symlink(os.path.join(_build_dir, _build_flavor, lib_name), _target_lib_name)
|
||||
|
||||
# The directory to publish final AAR
|
||||
_aar_publish_dir = os.path.join(build_dir, 'aar_out', _build_flavor)
|
||||
os.makedirs(_aar_publish_dir, exist_ok=True)
|
||||
|
||||
# get the common gradle command args
|
||||
_gradle_command = [
|
||||
'gradle',
|
||||
'--no-daemon',
|
||||
'-b=build-android.gradle',
|
||||
'-c=settings-android.gradle',
|
||||
'-DjniLibsDir=' + _jnilibs_dir,
|
||||
'-DbuildDir=' + _aar_dir,
|
||||
'-DpublishDir=' + _aar_publish_dir,
|
||||
'-DminSdkVer=' + str(build_settings['android_min_sdk_version']),
|
||||
'-DtargetSdkVer=' + str(build_settings['android_target_sdk_version'])
|
||||
]
|
||||
|
||||
# clean, build, and publish to a local directory
|
||||
subprocess.run(_gradle_command + ['clean'], env=my_env, shell=False, check=True, cwd=JAVA_ROOT)
|
||||
subprocess.run(_gradle_command + ['build'], env=my_env, shell=False, check=True, cwd=JAVA_ROOT)
|
||||
subprocess.run(_gradle_command + ['publish'], env=my_env, shell=False, check=True, cwd=JAVA_ROOT)
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
os.path.basename(__file__),
|
||||
description='''Create Android Archive (AAR) package for one or more Android ABI(s)
|
||||
and building properties specified in the given build config file, see
|
||||
tools/ci_build/github/android/default_mobile_aar_build_settings.json for details
|
||||
'''
|
||||
)
|
||||
|
||||
parser.add_argument("--android_sdk_path", type=str, default=os.environ.get("ANDROID_HOME", ""),
|
||||
help="Path to the Android SDK")
|
||||
|
||||
parser.add_argument("--android_ndk_path", type=str, default=os.environ.get("ANDROID_NDK_HOME", ""),
|
||||
help="Path to the Android NDK")
|
||||
|
||||
parser.add_argument('--build_dir', type=pathlib.Path, default=os.path.join(REPO_DIR, 'build_android_aar'),
|
||||
help='Provide the root directory for build output')
|
||||
|
||||
parser.add_argument(
|
||||
"--include_ops_by_config", type=str,
|
||||
help="Include ops from config file. See /docs/Reduced_Operator_Kernel_build.md for more information.")
|
||||
|
||||
parser.add_argument('build_settings_file', type=pathlib.Path,
|
||||
help='Provide the file contains settings for building AAR')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
# Android SDK and NDK path are required
|
||||
if not args.android_sdk_path:
|
||||
raise ValueError('android_sdk_path is required')
|
||||
if not args.android_ndk_path:
|
||||
raise ValueError('android_ndk_path is required')
|
||||
|
||||
_build_aar(args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"build_abis": [
|
||||
"armeabi-v7a",
|
||||
"arm64-v8a",
|
||||
"x86",
|
||||
"x86_64"
|
||||
],
|
||||
"build_flavor": "Release",
|
||||
"android_min_sdk_version": 21,
|
||||
"android_target_sdk_version": 28,
|
||||
"build_params": [
|
||||
"--android",
|
||||
"--parallel",
|
||||
"--cmake_generator=Ninja",
|
||||
"--build_java",
|
||||
"--build_shared_lib",
|
||||
"--minimal_build=extended",
|
||||
"--disable_rtti",
|
||||
"--disable_ml_ops",
|
||||
"--disable_exceptions",
|
||||
"--use_nnapi",
|
||||
"--skip_tests"
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue