mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-14 20:48:00 +00:00
* add copy executable for android job * minor fix * Variable fix * Move to use tgz because zip is not part of the docker image * update compression
206 lines
8.5 KiB
Python
206 lines
8.5 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
# Licensed under the MIT License.
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import pathlib
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
|
|
REPO_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..", "..", "..", ".."))
|
|
BUILD_PY = os.path.join(REPO_DIR, "tools", "ci_build", "build.py")
|
|
JAVA_ROOT = os.path.join(REPO_DIR, "java")
|
|
|
|
sys.path.insert(0, os.path.join(REPO_DIR, "tools", "python"))
|
|
from util import is_windows # noqa: E402
|
|
|
|
# We by default will build all 4 ABIs
|
|
DEFAULT_BUILD_ABIS = ["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]
|
|
|
|
# Onnx Runtime native library is built against NDK API 21 by default
|
|
# It is possible to build from source for Android API levels below 21, but it is not guaranteed
|
|
DEFAULT_ANDROID_MIN_SDK_VER = 21
|
|
|
|
# Android API 24 is the default target API version for Android builds, based on Microsoft 1CS requirements
|
|
# It is possible to build from source using API level 21 and higher as the target SDK version
|
|
DEFAULT_ANDROID_TARGET_SDK_VER = 24
|
|
|
|
|
|
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 = {}
|
|
|
|
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 = os.path.abspath(args.build_dir)
|
|
|
|
# Setup temp environment for building
|
|
temp_env = os.environ.copy()
|
|
temp_env['ANDROID_HOME'] = os.path.abspath(args.android_sdk_path)
|
|
temp_env['ANDROID_NDK_HOME'] = os.path.abspath(args.android_ndk_path)
|
|
|
|
# Temp dirs to hold building results
|
|
intermediates_dir = os.path.join(build_dir, 'intermediates')
|
|
build_config = args.config
|
|
aar_dir = os.path.join(intermediates_dir, 'aar', build_config)
|
|
jnilibs_dir = os.path.join(intermediates_dir, 'jnilibs', build_config)
|
|
exe_dir = os.path.join(intermediates_dir, 'executables', build_config)
|
|
base_build_command = [
|
|
sys.executable, BUILD_PY, '--config=' + build_config
|
|
] + build_settings['build_params']
|
|
header_files_path = ''
|
|
|
|
# Build binary for each ABI, one by one
|
|
for abi in build_settings['build_abis']:
|
|
abi_build_dir = os.path.join(intermediates_dir, abi)
|
|
abi_build_command = base_build_command + [
|
|
'--android_abi=' + abi,
|
|
'--build_dir=' + abi_build_dir
|
|
]
|
|
|
|
if args.include_ops_by_config is not None:
|
|
abi_build_command += ['--include_ops_by_config=' + args.include_ops_by_config]
|
|
|
|
subprocess.run(abi_build_command, env=temp_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
|
|
abi_jnilibs_dir = os.path.join(jnilibs_dir, abi)
|
|
os.makedirs(abi_jnilibs_dir, exist_ok=True)
|
|
for lib_name in ['libonnxruntime.so', 'libonnxruntime4j_jni.so']:
|
|
target_lib_name = os.path.join(abi_jnilibs_dir, lib_name)
|
|
# If the symbolic already exists, delete it first
|
|
# For some reason, os.path.exists will return false for a symbolic link in Linux,
|
|
# add double check with os.path.islink
|
|
if os.path.exists(target_lib_name) or os.path.islink(target_lib_name):
|
|
os.remove(target_lib_name)
|
|
os.symlink(os.path.join(abi_build_dir, build_config, lib_name), target_lib_name)
|
|
|
|
# copy executables for each abi, in case we want to publish those as well
|
|
abi_exe_dir = os.path.join(exe_dir, abi)
|
|
for exe_name in ['libonnxruntime.so', 'onnxruntime_perf_test', 'onnx_test_runner']:
|
|
os.makedirs(abi_exe_dir, exist_ok=True)
|
|
target_exe_name = os.path.join(abi_exe_dir, exe_name)
|
|
shutil.copyfile(os.path.join(abi_build_dir, build_config, exe_name), target_exe_name)
|
|
|
|
# we only need to define the header files path once
|
|
if not header_files_path:
|
|
header_files_path = os.path.join(abi_build_dir, build_config, 'android', 'headers')
|
|
|
|
# The directory to publish final AAR
|
|
aar_publish_dir = os.path.join(build_dir, 'aar_out', build_config)
|
|
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,
|
|
'-DheadersDir=' + header_files_path,
|
|
'-DpublishDir=' + aar_publish_dir,
|
|
'-DminSdkVer=' + str(build_settings['android_min_sdk_version']),
|
|
'-DtargetSdkVer=' + str(build_settings['android_target_sdk_version'])
|
|
]
|
|
|
|
# If not using shell on Window, will not be able to find gradle in path
|
|
use_shell = True if is_windows() else False
|
|
|
|
# clean, build, and publish to a local directory
|
|
subprocess.run(gradle_command + ['clean'], env=temp_env, shell=use_shell, check=True, cwd=JAVA_ROOT)
|
|
subprocess.run(gradle_command + ['build'], env=temp_env, shell=use_shell, check=True, cwd=JAVA_ROOT)
|
|
subprocess.run(gradle_command + ['publish'], env=temp_env, shell=use_shell, 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.
|
|
The output of the final AAR package can be found under [build_dir]/aar_out
|
|
'''
|
|
)
|
|
|
|
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=str, 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("--config", type=str, default="Release",
|
|
choices=["Debug", "MinSizeRel", "Release", "RelWithDebInfo"],
|
|
help="Configuration to build.")
|
|
|
|
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()
|