From ec3c553501f0940f61943fb355c6b390a727e7e8 Mon Sep 17 00:00:00 2001 From: daquexian Date: Thu, 25 Jul 2019 04:20:05 +0800 Subject: [PATCH] NNAPI EP Update (#1483) * Update DNNLibrary * Allow fp16 by default * Add nnapi build in ci * Fix nnapi ep after #1268 * Remove unused variables * Support nnapi in onnx_test_runner * Update DNNLibrary to fix tests * Update build.py for android build support, solve conflict of tools/ci_build/build.py * Support non-ARM Android build, solve conflict of tools/ci_build/build.py * Enable android test by x86_64 android emulator * Add dnnlibrary/NNAPI support in build.py * suppress the verbose adb output * Remove debug logs * Install cmake by pip * Fix undefined host_protoc_path * cmake==3.13.2 in pypi is actually 3.12.2, so install 3.13.2.post1 instead * Fix Android ARM64 build * Use android ndk r20 instead of r19c, fix conflicts in install_deps_android.sh --- cmake/external/DNNLibrary | 2 +- cmake/onnxruntime_mlas.cmake | 71 +++++++++--------- .../nnapi/nnapi_execution_provider.cc | 43 +---------- .../nnapi/nnapi_execution_provider.h | 2 - onnxruntime/test/onnx/main.cc | 11 +++ onnxruntime/test/util/include/providers.h | 5 +- tools/ci_build/build.py | 73 ++++++++++++++----- tools/ci_build/github/android/adb-push.sh | 17 +++++ .../github/android/start_android_emulator.sh | 25 +++++++ ...android-arm64-crosscompile-ci-pipeline.yml | 2 +- .../docker/scripts/install_deps_android.sh | 21 ++---- tools/ci_build/github/linux/run_build.sh | 6 +- 12 files changed, 163 insertions(+), 115 deletions(-) create mode 100755 tools/ci_build/github/android/adb-push.sh create mode 100755 tools/ci_build/github/android/start_android_emulator.sh diff --git a/cmake/external/DNNLibrary b/cmake/external/DNNLibrary index 90cb0f8d60..ab22710a3f 160000 --- a/cmake/external/DNNLibrary +++ b/cmake/external/DNNLibrary @@ -1 +1 @@ -Subproject commit 90cb0f8d60b07e96ca7f0ba92fa50884010599ad +Subproject commit ab22710a3f0166f31c9c14feab98c04bfb86b71b diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake index c784b8c899..619a4c3d08 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -79,70 +79,65 @@ if(MSVC) ) endif() - -elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") - - if(CMAKE_ANDROID_ARCH_ABI MATCHES "^arm.*") - - if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon") +else() + if (CMAKE_SYSTEM_NAME STREQUAL "Android") + if (CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") + set(ARM TRUE) + elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") + set(ARM TRUE) # Android NDK fails to compile sgemma.s + elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64") + set(X86_64 TRUE) + elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86") + set(X86 TRUE) endif() - - set(mlas_platform_srcs - ${ONNXRUNTIME_ROOT}/core/mlas/lib/arm/sgemmc.cpp - ) - else() + execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpmachine + OUTPUT_VARIABLE dumpmachine_output + ERROR_QUIET + ) - message(FATAL_ERROR "Android build is not supported on non-ARM platform now") - + if(dumpmachine_output MATCHES "^arm.*") + set(ARM TRUE) + elseif(dumpmachine_output MATCHES "^aarch64.*") + set(ARM64 TRUE) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86?)$") + set(X86 TRUE) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(X86_64 TRUE) + endif() endif() -else() - - execute_process( - COMMAND ${CMAKE_C_COMPILER} -dumpmachine - OUTPUT_VARIABLE dumpmachine_output - ERROR_QUIET - ) - - if(dumpmachine_output MATCHES "^arm.*") - + if (ARM) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon") set(mlas_platform_srcs ${ONNXRUNTIME_ROOT}/core/mlas/lib/arm/sgemmc.cpp - ) - - elseif(dumpmachine_output MATCHES "^aarch64.*") - + ) + elseif (ARM64) enable_language(ASM) set(mlas_platform_srcs ${ONNXRUNTIME_ROOT}/core/mlas/lib/aarch64/sgemma.s - ) - - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86?)$") - + ) + elseif (X86) enable_language(ASM) set(mlas_platform_srcs_sse2 ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86/SgemmKernelSse2.S - ) + ) set_source_files_properties(${mlas_platform_srcs_sse2} PROPERTIES COMPILE_FLAGS "-msse2") set(mlas_platform_srcs_avx ${ONNXRUNTIME_ROOT}/core/mlas/lib/x86/SgemmKernelAvx.S - ) + ) set_source_files_properties(${mlas_platform_srcs_avx} PROPERTIES COMPILE_FLAGS "-mavx") set(mlas_platform_srcs ${mlas_platform_srcs_sse2} ${mlas_platform_srcs_avx} - ) - - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - + ) + elseif (X86_64) enable_language(ASM) # The LLVM assmebler does not support the .arch directive to enable instruction diff --git a/onnxruntime/core/providers/nnapi/nnapi_execution_provider.cc b/onnxruntime/core/providers/nnapi/nnapi_execution_provider.cc index 83f9d8afed..d1d0cdf7dc 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_execution_provider.cc +++ b/onnxruntime/core/providers/nnapi/nnapi_execution_provider.cc @@ -19,12 +19,12 @@ NnapiExecutionProvider::NnapiExecutionProvider() DeviceAllocatorRegistrationInfo device_info{OrtMemTypeDefault, [](int) { return std::make_unique( std::make_unique(NNAPI, - OrtAllocatorType::OrtDeviceAllocator, 0, OrtMemTypeDefault)); }, + OrtAllocatorType::OrtDeviceAllocator)); }, std::numeric_limits::max()}; InsertAllocator(CreateAllocator(device_info)); DeviceAllocatorRegistrationInfo cpu_allocator_info({OrtMemTypeCPUOutput, - [](int) { return std::make_unique(std::make_unique(NNAPI, OrtAllocatorType::OrtDeviceAllocator, 0, OrtMemTypeCPUOutput)); }, + [](int) { return std::make_unique(std::make_unique(NNAPI, OrtAllocatorType::OrtDeviceAllocator, OrtDevice(), 0, OrtMemTypeCPUOutput)); }, std::numeric_limits::max()}); InsertAllocator(CreateAllocator(cpu_allocator_info)); @@ -32,22 +32,6 @@ NnapiExecutionProvider::NnapiExecutionProvider() NnapiExecutionProvider::~NnapiExecutionProvider() {} -Status NnapiExecutionProvider::CopyTensor(const Tensor& src, Tensor& dst) const { - if (!(strcmp(src.Location().name, NNAPI) == 0 && strcmp(dst.Location().name, CPU) == 0) && - !(strcmp(src.Location().name, CPU) == 0 && strcmp(dst.Location().name, NNAPI) == 0) && - !(strcmp(src.Location().name, NNAPI) == 0 && strcmp(dst.Location().name, NNAPI) == 0)) { - ORT_NOT_IMPLEMENTED(src.Location().name, " copy to ", dst.Location().name, " is not implemented"); - } - - // Todo: Copy for now. May optimize later to avoid copy. - size_t bytes = src.DataType()->Size() * src.Shape().Size(); - const void* src_data = src.DataRaw(); - void* dst_data = dst.MutableDataRaw(); - memcpy(dst_data, src_data, bytes); - - return Status::OK(); -} - std::vector> NnapiExecutionProvider::GetSupportedNodes(const ONNX_NAMESPACE::ModelProto& model_proto) const { dnn::OnnxConverter converter; return converter.GetSupportedNodes(model_proto); @@ -211,28 +195,6 @@ NnapiExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph, common::Status NnapiExecutionProvider::Compile(const std::vector& fused_nodes, std::vector& node_compute_funcs) { for (const auto* fused_node : fused_nodes) { - std::vector input_indexes; - std::vector input_dim_sizes; - std::vector output_indexes; - std::vector output_dim_sizes; - std::vector> output_shapes; - - // Build map from input name to its index in input definitions - std::unordered_map input_map; - const auto& input_defs = fused_node->InputDefs(); - input_map.reserve(input_defs.size()); - for (int i = 0, end = input_defs.size(); i < end; ++i) { - input_map[input_defs[i]->Name()] = i; - } - - // Build map from output name to its index in output definitions - std::unordered_map output_map; - const auto& output_defs = fused_node->OutputDefs(); - output_map.reserve(output_defs.size()); - for (int i = 0, end = output_defs.size(); i < end; ++i) { - output_map[output_defs[i]->Name()] = i; - } - // Reconstruct graph proto from fused node's function body const auto* func_body = fused_node->GetFunctionBody(); if (!func_body) { @@ -248,6 +210,7 @@ common::Status NnapiExecutionProvider::Compile(const std::vectorName(), std::move(dnn_model)); diff --git a/onnxruntime/core/providers/nnapi/nnapi_execution_provider.h b/onnxruntime/core/providers/nnapi/nnapi_execution_provider.h index d68209cc6e..a03eb5c7f4 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_execution_provider.h +++ b/onnxruntime/core/providers/nnapi/nnapi_execution_provider.h @@ -18,8 +18,6 @@ class NnapiExecutionProvider : public IExecutionProvider { common::Status Compile(const std::vector& fused_nodes, std::vector& node_compute_funcs) override; - Status CopyTensor(const Tensor& src, Tensor& dst) const override; - private: std::unordered_map> dnn_models_; std::vector> GetSupportedNodes(const ONNX_NAMESPACE::ModelProto& model_proto) const; diff --git a/onnxruntime/test/onnx/main.cc b/onnxruntime/test/onnx/main.cc index 04f2d6f9fa..382a229745 100644 --- a/onnxruntime/test/onnx/main.cc +++ b/onnxruntime/test/onnx/main.cc @@ -97,6 +97,7 @@ int real_main(int argc, char* argv[], Ort::Env& env) { bool enable_tensorrt = false; bool enable_mem_pattern = true; bool enable_openvino = false; + bool enable_nnapi = false; uint32_t graph_optimization_level{}; bool user_graph_optimization_level_set = false; @@ -155,6 +156,8 @@ int real_main(int argc, char* argv[], Ort::Env& env) { enable_tensorrt = true; } else if (!CompareCString(optarg, ORT_TSTR("openvino"))) { enable_openvino = true; + } else if (!CompareCString(optarg, ORT_TSTR("nnapi"))) { + enable_nnapi = true; } else { usage(); return -1; @@ -277,6 +280,14 @@ int real_main(int argc, char* argv[], Ort::Env& env) { return -1; #endif } + if (enable_nnapi) { +#ifdef USE_NNAPI + ORT_THROW_ON_ERROR(OrtSessionOptionsAppendExecutionProvider_Nnapi(sf)); +#else + fprintf(stderr, "DNNLibrary/NNAPI is not supported in this build"); + return -1; +#endif + } if (user_graph_optimization_level_set) { sf.SetGraphOptimizationLevel(graph_optimization_level); diff --git a/onnxruntime/test/util/include/providers.h b/onnxruntime/test/util/include/providers.h index 296897cca7..9cc04a360a 100644 --- a/onnxruntime/test/util/include/providers.h +++ b/onnxruntime/test/util/include/providers.h @@ -24,4 +24,7 @@ #endif #ifdef USE_OPENVINO #include "core/providers/openvino/openvino_provider_factory.h" -#endif \ No newline at end of file +#endif +#ifdef USE_NNAPI +#include "core/providers/nnapi/nnapi_provider_factory.h" +#endif diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 9100a6a656..9da8b5d002 100755 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -111,6 +111,12 @@ Use the individual flags to only run the specified stages. parser.add_argument("--arm64", action='store_true', help="Create ARM64 makefiles. Requires --update and no existing cache CMake setup. Delete CMakeCache.txt if needed") parser.add_argument("--msvc_toolset", help="MSVC toolset to use. e.g. 14.11") + parser.add_argument("--android", action='store_true', help='Build for Android') + parser.add_argument("--android_abi", type=str, default='arm64-v8a', + help='') + parser.add_argument("--android_api", type=int, default=27, + help='Android API Level, e.g. 21') + parser.add_argument("--android_ndk_path", default="", help="Path to the Android NDK") # Arguments needed by CI parser.add_argument("--cmake_path", default="cmake", help="Path to the CMake program.") @@ -124,6 +130,7 @@ Use the individual flags to only run the specified stages. parser.add_argument("--use_ngraph", action='store_true', help="Build with nGraph.") parser.add_argument("--use_openvino", nargs="?", const="CPU_FP32", choices=["CPU_FP32","GPU_FP32","GPU_FP16","VAD-R_FP16","MYRIAD_FP16"], help="Build with OpenVINO for specific hardware.") + parser.add_argument("--use_dnnlibrary", action='store_true', help="Build with DNNLibrary.") parser.add_argument("--use_nsync", action='store_true', help="Build with NSYNC.") parser.add_argument("--use_preinstalled_eigen", action='store_true', help="Use pre-installed eigen.") parser.add_argument("--eigen_path", help="Path to pre-installed eigen.") @@ -334,6 +341,7 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home "-Donnxruntime_USE_OPENVINO_GPU_FP16=" + ("ON" if args.use_openvino == "GPU_FP16" else "OFF"), "-Donnxruntime_USE_OPENVINO_CPU_FP32=" + ("ON" if args.use_openvino == "CPU_FP32" else "OFF"), "-Donnxruntime_USE_OPENVINO_VAD_R=" + ("ON" if args.use_openvino == "VAD-R_FP16" else "OFF"), + "-Donnxruntime_USE_NNAPI=" + ("ON" if args.use_dnnlibrary else "OFF"), "-Donnxruntime_USE_OPENMP=" + ("ON" if args.use_openmp and not args.use_mklml and not args.use_ngraph else "OFF"), "-Donnxruntime_USE_TVM=" + ("ON" if args.use_tvm else "OFF"), "-Donnxruntime_USE_LLVM=" + ("ON" if args.use_llvm else "OFF"), @@ -372,6 +380,11 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home cmake_args += ["-Donnxruntime_USE_PREINSTALLED_EIGEN=ON", "-Deigen_SOURCE_PATH=" + args.eigen_path] + if args.android: + cmake_args += ["-DCMAKE_TOOLCHAIN_FILE=" + args.android_ndk_path + "/build/cmake/android.toolchain.cmake", + "-DANDROID_PLATFORM=android-" + str(args.android_api), + "-DANDROID_ABI=" + str(args.android_abi)] + if path_to_protoc_exe: cmake_args += ["-DONNX_CUSTOM_PROTOC_EXECUTABLE=%s" % path_to_protoc_exe] @@ -522,10 +535,29 @@ def setup_tensorrt_vars(args): return tensorrt_home +def adb_push(source_dir, src, dest, **kwargs): + return run_subprocess([os.path.join(source_dir, 'tools', 'ci_build', 'github', 'android', 'adb-push.sh'), src, dest], **kwargs) + +def adb_shell(*args, **kwargs): + return run_subprocess(['adb', 'shell', *args], **kwargs) + def run_onnxruntime_tests(args, source_dir, ctest_path, build_dir, configs, enable_python_tests, enable_tvm = False, enable_tensorrt = False, enable_ngraph = False): for config in configs: log.info("Running tests for %s configuration", config) cwd = get_config_build_dir(build_dir, config) + android_x86_64 = args.android_abi == 'x86_64' + if android_x86_64: + run_subprocess(os.path.join(source_dir, 'tools', 'ci_build', 'github', 'android', 'start_android_emulator.sh')) + adb_push(source_dir, 'testdata', '/data/local/tmp/', cwd=cwd) + adb_push(source_dir, os.path.join(source_dir, 'cmake', 'external', 'onnx', 'onnx', 'backend', 'test'), '/data/local/tmp/', cwd=cwd) + adb_push(source_dir, 'onnxruntime_test_all', '/data/local/tmp/', cwd=cwd) + adb_push(source_dir, 'onnx_test_runner', '/data/local/tmp/', cwd=cwd) + adb_shell('cd /data/local/tmp && /data/local/tmp/onnxruntime_test_all') + if args.use_dnnlibrary: + adb_shell('cd /data/local/tmp && /data/local/tmp/onnx_test_runner -e nnapi /data/local/tmp/test') + else: + adb_shell('cd /data/local/tmp && /data/local/tmp/onnx_test_runner /data/local/tmp/test') + continue if enable_tvm: dll_path = os.path.join(build_dir, config, "external", "tvm", config) elif enable_tensorrt: @@ -711,23 +743,24 @@ def build_python_wheel(source_dir, build_dir, configs, use_cuda, use_ngraph, use args.append('--use_openvino') run_subprocess(args, cwd=cwd) -def build_protoc_for_windows_host(cmake_path, source_dir, build_dir, cmake_generator): - if not is_windows(): +def build_protoc_for_host(cmake_path, source_dir, build_dir, args): + if (args.arm or args.arm64) and not is_windows(): raise BuildError('Currently only support building protoc for Windows host while cross-compiling for ARM/ARM64 arch') log.info("Building protoc for host to be used in cross-compiled build process") - protoc_build_dir = os.path.join(build_dir, 'host_protoc') + protoc_build_dir = os.path.join(os.getcwd(), build_dir, 'host_protoc') os.makedirs(protoc_build_dir, exist_ok=True) # Generate step cmd_args = [cmake_path, - os.path.join(source_dir, 'cmake\external\protobuf\cmake'), - '-T', - 'host=x64', - '-G', - cmake_generator, + os.path.join(source_dir, 'cmake', 'external', 'protobuf', 'cmake'), '-Dprotobuf_BUILD_TESTS=OFF', '-Dprotobuf_WITH_ZLIB_DEFAULT=OFF', '-Dprotobuf_BUILD_SHARED_LIBS=OFF'] + if is_windows(): + cmd_args += ['-T', + 'host=x64', + '-G', + args.cmake_generator] run_subprocess(cmd_args, cwd= protoc_build_dir) # Build step cmd_args = [cmake_path, @@ -736,8 +769,12 @@ def build_protoc_for_windows_host(cmake_path, source_dir, build_dir, cmake_gener "--target", "protoc"] run_subprocess(cmd_args) - if not os.path.exists(os.path.join(build_dir, 'host_protoc', 'Release', 'protoc.exe')): - raise BuildError("Couldn't build protoc.exe for host. Failing build.") + # Absolute protoc path is needed for cmake + expected_protoc_path = os.path.join(protoc_build_dir, 'Release', 'protoc.exe') if is_windows() else os.path.join(protoc_build_dir, 'protoc') + if not os.path.exists(expected_protoc_path): + raise BuildError("Couldn't build protoc for host. Failing build.") + + return expected_protoc_path def generate_documentation(source_dir, build_dir, configs): operator_doc_path = os.path.join(source_dir, 'docs', 'ContribOperators.md') @@ -767,13 +804,15 @@ def main(): cmake_extra_defines = args.cmake_extra_defines if args.cmake_extra_defines else [] + cross_compiling = args.arm or args.arm64 or args.android + # if there was no explicit argument saying what to do, default to update, build and test (for native builds). if (args.update == False and args.clean == False and args.build == False and args.test == False): log.debug("Defaulting to running update, build [and test for native builds].") args.update = True args.build = True - if args.arm or args.arm64: - args.test = False + if cross_compiling: + args.test = args.android_abi == 'x86_64' else: args.test = True @@ -806,13 +845,14 @@ def main(): log.info("Build started") if (args.update): cmake_extra_args = [] + path_to_protoc_exe = None if(is_windows()): if (args.x86): cmake_extra_args = ['-A','Win32','-T','host=x64','-G', args.cmake_generator] elif (args.arm or args.arm64): # Cross-compiling for ARM(64) architecture # First build protoc for host to use during cross-compilation - build_protoc_for_windows_host(cmake_path, source_dir, build_dir, args.cmake_generator) + path_to_protoc_exe = build_protoc_for_host(cmake_path, source_dir, build_dir, args) if args.arm: cmake_extra_args = ['-A', 'ARM'] else: @@ -830,6 +870,9 @@ def main(): toolset += ',cuda=' + args.cuda_version cmake_extra_args = ['-A','x64','-T', toolset, '-G', args.cmake_generator] + if args.android: + # Cross-compiling for Android + path_to_protoc_exe = build_protoc_for_host(cmake_path, source_dir, build_dir, args) if is_ubuntu_1604(): if (args.arm or args.arm64): raise BuildError("Only Windows ARM(64) cross-compiled builds supported currently through this script") @@ -847,12 +890,8 @@ def main(): raise UsageError("The test_data_url and test_data_checksum arguments are required.") setup_test_data(build_dir, configs, args.test_data_url, args.test_data_checksum, args.azure_sas_key) - path_to_protoc_exe = None if args.path_to_protoc_exe: path_to_protoc_exe = args.path_to_protoc_exe - # Need to provide path to protoc.exe built for host to be used in the cross-compiled build process - elif args.arm or args.arm64: - path_to_protoc_exe = os.path.join(build_dir, 'host_protoc', 'Release', 'protoc.exe') generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home, tensorrt_home, path_to_protoc_exe, configs, cmake_extra_defines, args, cmake_extra_args) diff --git a/tools/ci_build/github/android/adb-push.sh b/tools/ci_build/github/android/adb-push.sh new file mode 100755 index 0000000000..e017dd746e --- /dev/null +++ b/tools/ci_build/github/android/adb-push.sh @@ -0,0 +1,17 @@ +#! /usr/bin/env bash +# Created by daquexian +# A bash script that push folders recursively, "adb push" doesn't work on some devices + +if [[ $# -ne 2 ]]; then + echo "Usage: $0 src dest" + exit 1 +fi + +src=`realpath $1` +src_basename=`basename $1` +pushd `dirname $src` +if [[ -d $src ]]; then + find $src_basename -type d -print -exec adb shell mkdir -p $2/{} \; > /dev/null +fi +find $src_basename -type f -exec adb push {} $2/{} \; > /dev/null +popd diff --git a/tools/ci_build/github/android/start_android_emulator.sh b/tools/ci_build/github/android/start_android_emulator.sh new file mode 100755 index 0000000000..d6e12e1bb0 --- /dev/null +++ b/tools/ci_build/github/android/start_android_emulator.sh @@ -0,0 +1,25 @@ +#! /usr/bin/env bash +# Created by daquexian + +set -e + +export TERM=xterm + +echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-28;google_apis;x86_64' + +echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n android_emulator -k 'system-images;android-28;google_apis;x86_64' --force + +echo "Starting emulator" + +# Start emulator in background +nohup $ANDROID_HOME/emulator/emulator -avd android_emulator -no-snapshot -no-audio & + +# start server in advance, so that the result of watch will only change when device gets online +$ANDROID_HOME/platform-tools/adb start-server + +echo "Waiting for device to come online" +# Sometimes wait-for-device hangs, so add a timeout here +timeout 60 adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done; input keyevent 82' + +echo "Emulator is online" + diff --git a/tools/ci_build/github/azure-pipelines/android-arm64-crosscompile-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/android-arm64-crosscompile-ci-pipeline.yml index cfd453fa31..64dd6160fc 100644 --- a/tools/ci_build/github/azure-pipelines/android-arm64-crosscompile-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/android-arm64-crosscompile-ci-pipeline.yml @@ -4,7 +4,7 @@ jobs: steps: - template: templates/set-test-data-variables-step.yml - - script: 'tools/ci_build/github/linux/run_dockerbuild.sh -o android -r $(Build.BinariesDirectory) -d cpu -x "--build_wheel"' + - script: 'tools/ci_build/github/linux/run_dockerbuild.sh -o android -r $(Build.BinariesDirectory) -d nnapi -x "--build_wheel"' displayName: 'Command Line Script' - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 diff --git a/tools/ci_build/github/linux/docker/scripts/install_deps_android.sh b/tools/ci_build/github/linux/docker/scripts/install_deps_android.sh index 771b2ae4f2..445e166644 100755 --- a/tools/ci_build/github/linux/docker/scripts/install_deps_android.sh +++ b/tools/ci_build/github/linux/docker/scripts/install_deps_android.sh @@ -1,19 +1,12 @@ #!/bin/bash set -e -mkdir -p /tmp/src -aria2c -q -d /tmp/src https://github.com/Kitware/CMake/releases/download/v3.13.2/cmake-3.13.2.tar.gz -tar -xf /tmp/src/cmake-3.13.2.tar.gz -C /tmp/src -cd /tmp/src/cmake-3.13.2 -./configure --prefix=/usr --parallel=`nproc` --system-curl --system-zlib --system-expat -make -j`nproc` -make install -#download Android NDK r19c -aria2c -q -d /tmp https://dl.google.com/android/repository/android-ndk-r19c-linux-x86_64.zip -unzip -oq /tmp/android-ndk-r19c-linux-x86_64.zip -d /tmp/android-ndk && mv /tmp/android-ndk/* /android-ndk -cd / -rm -rf /tmp/src +# cmake==3.13.2 is actually 3.12.2 lol +python3 -m pip install cmake==3.13.2.post1 + +cmake --version + +# Download Android NDK r20, move /temp_ndk/android-ndk- to /android_ndk +wget -qO- -O temp.zip https://dl.google.com/android/repository/android-ndk-r20-linux-x86_64.zip && unzip -oq temp.zip -d /temp-ndk && mv /temp-ndk/* /android-ndk && rm temp.zip && rm -rf /temp-ndk && ls /android-ndk apt-get -y remove libprotobuf-dev protobuf-compiler - - diff --git a/tools/ci_build/github/linux/run_build.sh b/tools/ci_build/github/linux/run_build.sh index 44af48a2e8..150ebec491 100755 --- a/tools/ci_build/github/linux/run_build.sh +++ b/tools/ci_build/github/linux/run_build.sh @@ -17,7 +17,11 @@ done if [ $BUILD_OS = "android" ]; then pushd /onnxruntime_src mkdir build-android && cd build-android - cmake -DCMAKE_TOOLCHAIN_FILE=/android-ndk/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DONNX_CUSTOM_PROTOC_EXECUTABLE=/usr/bin/protoc ../cmake + if [ $BUILD_DEVICE = "nnapi" ]; then + cmake -DCMAKE_TOOLCHAIN_FILE=/android-ndk/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DONNX_CUSTOM_PROTOC_EXECUTABLE=/usr/bin/protoc -Donnxruntime_USE_NNAPI=ON ../cmake + else + cmake -DCMAKE_TOOLCHAIN_FILE=/android-ndk/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DONNX_CUSTOM_PROTOC_EXECUTABLE=/usr/bin/protoc ../cmake + fi make -j$(nproc) else COMMON_BUILD_ARGS="--skip_submodule_sync --enable_onnx_tests --parallel --build_shared_lib --use_openmp --cmake_path /usr/bin/cmake --ctest_path /usr/bin/ctest"