From c6a94f95cfd0bde49213ea90800d29ee106fbc49 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Tue, 19 May 2020 07:30:45 +1000 Subject: [PATCH] Update Android instructions (#3971) Update Android build instructions to provide more information. Add info on testing directly on Android Update build.py to better support using Ninja generator to build Android on Windows. --- BUILD.md | 81 ++++++++++++++++++++++++++++++++++++++--- docs/Android_testing.md | 81 +++++++++++++++++++++++++++++++++++++++++ tools/ci_build/build.py | 26 ++++++++----- 3 files changed, 174 insertions(+), 14 deletions(-) create mode 100644 docs/Android_testing.md diff --git a/BUILD.md b/BUILD.md index d214681fa9..18877bbb87 100644 --- a/BUILD.md +++ b/BUILD.md @@ -83,7 +83,7 @@ For other system requirements and other dependencies, please see [this section]( |Description|Command|Additional description| |-----------|-----------|-----------| |**Basic build**|build.bat (Windows)
./build.sh (Linux)|| -|**Debug build**|--config RelWithDebInfo|Debug build| +|**Release build**|--config Release|Release build. Other valid config values are RelWithDebInfo and Debug.| |**Use OpenMP**|--use_openmp|OpenMP will parallelize some of the code for potential performance improvements. This is not recommended for running on single threads.| |**Build using parallel processing**|--parallel|This is strongly recommended to speed up the build.| |**Build Shared Library**|--build_shared_lib|| @@ -829,19 +829,90 @@ ls -l /code/onnxruntime/build/Linux/MinSizeRel/dist/*.whl #### Pre-Requisites -Install Android NDK in Android Studio or https://developer.android.com/ndk/downloads +The SDK and NDK packages can be installed via Android Studio or the sdkmanager command line tool. +Android Studio is more convenient but a larger installation. +The command line tools are smaller and usage can be scripted, but are a little more complicated to setup. They also require a Java runtime environment to be available. + +General Info: + - API levels: https://developer.android.com/guide/topics/manifest/uses-sdk-element.html + - Android ABIs: https://developer.android.com/ndk/guides/abis + - System Images: https://developer.android.com/topic/generic-system-image + +##### Android Studio + +Install Android Studio from https://developer.android.com/studio + +Install any additional SDK Platforms if necessary + - File->Settings->Appearance & Behavior->System Settings->Android SDK to see what is currently installed + - Note that the SDK path you need to use as --android_sdk_path when building ORT is also on this configuration page + - Most likely you don't require additional SDK Platform packages as the latest platform can target earlier API levels. + +Install an NDK version + - File->Settings->Appearance & Behavior->System Settings->Android SDK + - 'SDK Tools' tab + - Select 'Show package details' checkbox at the bottom to see specific versions. + By default the latest will be installed which should be fine. + - The NDK path will be the 'ndk/{version}' subdirectory of the SDK path shown + - e.g. if 21.1.6352462 is installed it will be {SDK path}/ndk/21.1.6352462 + +##### sdkmanager from command line tools + - If necessary install the Java Runtime Environment and set the JAVA_HOME environment variable to point to it + - https://www.java.com/en/download/ + - Windows note: You MUST install the 64-bit version (https://www.java.com/en/download/manual.jsp) otherwise sdkmanager will only list x86 packages + and the latest NDK is x64 only. + - For sdkmanager to work it needs a certain directory structure. + First create the top level directory for the Android infrastructure. + - in our example we'll call that `.../Android/` + - Download the command line tools from the 'Command line tools only' section towards the bottom + of https://developer.android.com/studio + - Create a directory called 'cmdline-tools' under your top level directory + - giving `.../Android/cmdline-tools` + - extract the 'tools' directory from the command line tools zip file into this directory + - giving `.../Android/cmdline-tools/tools` + - Windows note: preferably extract using 7-zip. + If using the built in Windows zip extract tool you will need to fix the directory structure + by moving the jar files from `tools\lib\_` up to `tools\lib` + - See https://stackoverflow.com/questions/27364963/could-not-find-or-load-main-class-com-android-sdkmanager-main + - you should now be able to run Android/cmdline-tools/bin/sdkmanager[.bat] successfully + - if you see an error about it being unable to save settings and the sdkmanager help text, + your directory structure is incorrect. + - see the final steps in this answer to double check: https://stackoverflow.com/a/61176718 + + - Run `.../Android/cmdline-tools/bin/sdkmanager --list` to see the packages available + + - Install the SDK Platform + - Generally installing the latest is fine. You pick an API level when compiling the code and the latest platform will support many recent API levels + - e.g. `sdkmanager --install "platforms;android-29"` + - This will install into the 'platforms' directory of our top level directory + - so the 'Android' directory in our example + - The SDK path to use as --android_sdk_path when building is this top level directory + + - Install the NDK + - Find the available NDK versions by running `sdkmanager --list` + - Install + - you can install a specific version or the latest (called 'ndk-bundle') + - e.g. `sdkmanager --install "ndk;21.1.6352462"` + - NDK path in our example with this install would be `.../Android/ndk/21.1.6352462` + - NOTE: If you install the ndk-bundle package the path will be `.../Android/ndk-bundle` as there's no version number #### Build Instructions ##### Cross compiling on Windows -```bash -./build.bat --android --android_sdk_path --android_ndk_path --android_abi --android_api +The [Ninja](https://ninja-build.org/) generator needs to be used to build on Windows as the Visual Studio generator doesn't support Android. + +``` +./build.bat --android --android_sdk_path --android_ndk_path --android_abi --android_api --cmake_generator Ninja +``` + +e.g. using the paths from our example +``` +./build.bat --android --android_sdk_path .../Android --android_ndk_path .../Android/ndk/21.1.6352462 --android_abi arm64-v8a --android_api 27 --cmake_generator Ninja ``` ##### Cross compiling on Linux -```bash +``` ./build.sh --android --android_sdk_path --android_ndk_path --android_abi --android_api ``` diff --git a/docs/Android_testing.md b/docs/Android_testing.md new file mode 100644 index 0000000000..2caffa2a24 --- /dev/null +++ b/docs/Android_testing.md @@ -0,0 +1,81 @@ +# Testing Android Changes using the Emulator + +See [BUILD.md](../Build.md#Android) for Android build instructions and information on the locations of the various files referred to here. + +## Install the emulator + +If using Android Studio this is included in the base install. + +If using sdkmanager install the emulator by running + - `sdkmanager[.bat] --install "emulator"` + +The emulator will emulate the Android device not its processor, so you need to build onnxruntime +with an ABI that's valid for the host machine, and install a system image that matches. +For example you can emulate a Pixel 3 device on an Intel 64-bit host, but it will require a binary built against x86_64 +rather than the arm64-v8a ABI of the real device. + +e.g. on Intel 64-bit you would build with `--android_abi x86_64` to create onnxruntime libraries/executables that can be run on the Android emulator + +## Create the device to emulate + +### Android Studio + +Tools->AVD Manager->Create Virtual Device... + +Once created the emulator can be started using the 'play' button in AVD Manager. + +### sdkmanager + +First install a system image. Use `sdkmanager --list` to see the available system images. + +e.g. `sdkmanager --install "system-images;android-27;default;x86_64` + +Create the virtual device using avdmanager[.bat] (which should be in the same directory as sdkmanager[.bat]). + +e.g. `avdmanager create avd -n android27_emulator -k "system-images;android-27;default;x86_64"` + +Run the emulator +e.g. `.../Android/emulator/emulator -avd android27_emulator -partition-size 2048 -no-snapshot -no-audio` + +## Testing running a model on the emulator directly + +Use ADB to copy files and execute commands + +https://developer.android.com/studio/command-line/adb + +ADB is located in the 'platform-tools' folder of the SDK directory. + +Copy onnx_test_runner and the directory of the model to test (in ONNX test directory format) to /data/local/tmp. + +``` +adb push /build///onnx_test_runner /data/local/tmp/ +adb push /build///testdata/transform/gemm_activation_fusion /data/local/tmp/ +``` + +e.g. on Windows that might be +``` +\platform-tools\adb.exe push \build\Windows\Debug\onnx_test_runner /data/local/tmp/testdata +\platform-tools\adb.exe push \build\Windows\Debug\testdata\transform\gemm_activation_fusion /data/local/tmp/ +``` + +You may need to change permissions to make onnx_test_runner executable: +`\platform-tools\adb.exe shell chmod +x /data/local/tmp/onnx_test_runner` + +Run onnx_test_runner with the model directory: +`\platform-tools\adb.exe shell 'cd /data/local/tmp && ./onnx_test_runner gemm_activation_fusion'` + +The output should look something like this: + +``` +D:\Android\platform-tools> .\adb.exe shell 'cd /data/local/tmp && ./onnx_test_runner gemm_activation_fusion' +result: + Models: 1 + Total test cases: 1 + Succeeded: 1 + Not implemented: 0 + Failed: 0 + Stats by Operator type: + Not implemented(0): + Failed: +Failed Test Cases: +``` \ No newline at end of file diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 066c453d69..3095ab266f 100755 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -831,7 +831,7 @@ def build_targets(args, cmake_path, build_dir, configs, parallel): build_tool_args = [] if parallel: num_cores = str(multiprocessing.cpu_count()) - if is_windows(): + if is_windows() and args.cmake_generator != 'Ninja': build_tool_args += [ "/maxcpucount:" + num_cores, # if nodeReuse is true, msbuild processes will stay around for a bit after the build completes @@ -1417,8 +1417,11 @@ def build_protoc_for_host(cmake_path, source_dir, build_dir, args): '-Dprotobuf_WITH_ZLIB_DEFAULT=OFF', '-Dprotobuf_BUILD_SHARED_LIBS=OFF' ] + + is_ninja = args.cmake_generator == 'Ninja' + if is_windows(): - if args.cmake_generator != 'Ninja': + if not is_ninja: cmd_args += ['-T', 'host=x64'] cmd_args += ['-G', args.cmake_generator] elif is_macOS() and args.use_xcode: @@ -1433,14 +1436,19 @@ def build_protoc_for_host(cmake_path, source_dir, build_dir, args): run_subprocess(cmd_args) # 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, 'Release', 'protoc') - if is_macOS() and args.use_xcode - else os.path.join(protoc_build_dir, 'protoc'))) + config_dir = '' + suffix = '' + + if (is_windows() and not is_ninja) or (is_macOS() and args.use_xcode): + config_dir = 'Release' + + if is_windows(): + suffix = '.exe' + + expected_protoc_path = os.path.join(protoc_build_dir, config_dir, 'protoc' + suffix) + if not os.path.exists(expected_protoc_path): - raise BuildError("Couldn't build protoc for host. Failing build.") + raise BuildError("Couldn't find {}. Host build of protoc failed.".format(expected_protoc_path)) return expected_protoc_path