| # Getting Started on Android with CMake | 
 |  | 
 | <!-- | 
 | Notes to those updating this guide: | 
 |  | 
 |     * This document should be __simple__ and cover essential items only. | 
 |       Notes for optional components should go in separate files. | 
 | --> | 
 |  | 
 | This guide walks through cross-compiling IREE core runtime towards the Android | 
 | platform. Cross-compiling IREE compilers towards Android is not supported at the | 
 | moment. | 
 |  | 
 | Cross-compilation involves both a *host* platform and a *target* platform. One | 
 | invokes compiler toolchains on the host platform to generate libraries and | 
 | executables that can be run on the target platform. | 
 |  | 
 | ## Prerequisites | 
 |  | 
 | ### Set up host development environment | 
 |  | 
 | The host platform should have been set up for developing IREE. Right now Linux | 
 | and Windows are supported. Please make sure you have followed the steps for | 
 | [Linux](./getting_started_linux_cmake.md) or | 
 | [Windows](./getting_started_windows_cmake.md). | 
 |  | 
 | ### Install Android NDK | 
 |  | 
 | Android NDK provides compiler toolchains for compiling C/C++ code to target | 
 | Android. You can download it | 
 | [here](https://developer.android.com/ndk/downloads). We recommend to download | 
 | the latest release; the steps in following sections may assume that. | 
 |  | 
 | Alternatively, if you have installed | 
 | [Android Studio](https://developer.android.com/studio), you can follow | 
 | [this guide](https://developer.android.com/studio/projects/install-ndk) to | 
 | install Android NDK. | 
 |  | 
 | After downloading, it is recommended to set the `ANDROID_NDK` environment | 
 | variable pointing to the directory. For Linux, you can `export` in your shell's | 
 | rc file. For Windows, you can search "environment variable" in the taskbar or | 
 | use `Windows` + `R` to open the "Run" dialog to run `rundll32 | 
 | sysdm.cpl,EditEnvironmentVariables`. | 
 |  | 
 | ### Install Android Debug Bridge (ADB) | 
 |  | 
 | For Linux, search your the distro's package manager to install `adb`. For | 
 | example, on Ubuntu: | 
 |  | 
 | ```shell | 
 | $ sudo apt install adb | 
 | ``` | 
 |  | 
 | For Windows, it's easier to get `adb` via Android Studio. `adb` is included in | 
 | the Android SDK Platform-Tools package. You can download this package with the | 
 | [SDK Manager](https://developer.android.com/studio/intro/update#sdk-manager), | 
 | which installs it at `android_sdk/platform-tools/`. Or if you want the | 
 | standalone Android SDK Platform-Tools package, you can | 
 | [download it here](https://developer.android.com/studio/releases/platform-tools). | 
 | You may also want to add the folder to the `PATH` environment variable. | 
 |  | 
 | ## Configure and build | 
 |  | 
 | ### Configure on Linux | 
 |  | 
 | ```shell | 
 | # Assuming in IREE source root | 
 | $ cmake -G Ninja -B build-android  \ | 
 |     -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \ | 
 |     -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-29 \ | 
 |     -DIREE_BUILD_COMPILER=OFF -DIREE_BUILD_SAMPLES=OFF \ | 
 |     -DIREE_HOST_C_COMPILER=`which clang` -DIREE_HOST_CXX_COMPILER=`which clang++` | 
 | ``` | 
 |  | 
 | *   The above configures IREE to cross-compile towards 64-bit | 
 |     (`-DANDROID_ABI="arm64-v8a"`) Android 10 (`-DANDROID_PLATFORM=android-29`). | 
 |     This may require the latest Android NDK release. You can choose the suitable | 
 |     [`ANDROID_ABI`](https://developer.android.com/ndk/guides/cmake#android_abi) | 
 |     and | 
 |     [`ANDROID_PLATFORM`](https://en.wikipedia.org/wiki/Android_version_history) | 
 |     for your target device. You can also refer to Android NDK's | 
 |     [CMake documentation](https://developer.android.com/ndk/guides/cmake) for | 
 |     more toolchain arguments. | 
 | *   Building IREE compilers and samples for Android is not supported at the | 
 |     moment; they will be enabled soon. | 
 | *   We need to define `IREE_HOST_{C|CXX}_COMPILER` to Clang here because IREE | 
 |     does [not support](https://github.com/google/iree/issues/1269) GCC well at | 
 |     the moment. | 
 |  | 
 | ### Configure on Windows | 
 |  | 
 | On Windows, we will need the full path to the `cl.exe` compiler. This can be | 
 | obtained by | 
 | [opening a developer command prompt window](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt) | 
 | and type `where cl.exe`. Then in a command prompt (`cmd.exe`): | 
 |  | 
 | ```cmd | 
 | REM Assuming in IREE source root | 
 | > cmake -G Ninja -B build-android  \ | 
 |     -DCMAKE_TOOLCHAIN_FILE="%ANDROID_NDK%/build/cmake/android.toolchain.cmake" \ | 
 |     -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-29 \ | 
 |     -DIREE_BUILD_COMPILER=OFF -DIREE_BUILD_SAMPLES=OFF \ | 
 |     -DIREE_HOST_C_COMPILER="<full-path-to-cl.exe>" \ | 
 |     -DIREE_HOST_CXX_COMPILER="<full-path-to-cl.exe>" \ | 
 |     -DLLVM_HOST_TRIPLE="x86_64-pc-windows-msvc" | 
 | ``` | 
 |  | 
 | *   See the Linux section in the above for explanations of the used arguments. | 
 | *   We need to define `LLVM_HOST_TRIPLE` in the above because LLVM cannot | 
 |     properly detect host triple under Android CMake toolchain file. This might | 
 |     be fixed later. | 
 |  | 
 | ### Build all targets | 
 |  | 
 | ```shell | 
 | $ cmake --build build-android/ | 
 | ``` | 
 |  | 
 | ## Test on Android | 
 |  | 
 | Make sure you | 
 | [enable developer options and USB debugging](https://developer.android.com/studio/debug/dev-options#enable) | 
 | for your Android device. | 
 |  | 
 | Connect your Android device to the development machine and make sure you can see | 
 | the device when: | 
 |  | 
 | ```shell | 
 | $ adb devices | 
 |  | 
 | List of devices attached | 
 | XXXXXXXXXXX     device | 
 | ``` | 
 |  | 
 | Then you can run all device tests via | 
 |  | 
 | ```shell | 
 | $ cd build-android | 
 | $ ctest --output-on-failure | 
 | ``` | 
 |  | 
 | The above command will upload necessary build artifacts to the Android device's | 
 | `/data/local/tmp` directory, run the tests there, and report status back. | 
 |  | 
 | Alternatively, if you want to invoke a specific HAL backend on a IREE module: | 
 |  | 
 | ### VMLA HAL backend | 
 |  | 
 | Translate a source MLIR into IREE module: | 
 |  | 
 | ```shell | 
 | # Assuming in IREE source root | 
 | $ build-android/host/bin/iree-translate \ | 
 |     -iree-mlir-to-vm-bytecode-module \ | 
 |     -iree-hal-target-backends=vmla \ | 
 |     iree/tools/test/simple.mlir \ | 
 |     -o /tmp/simple-vmla.vmfb | 
 | ``` | 
 |  | 
 | Then push the IREE runtime executable and module to the device: | 
 |  | 
 | ```shell | 
 | $ adb push build-android/iree/tools/iree-run-module /data/local/tmp/ | 
 | $ adb shell chmod +x /data/local/tmp/iree-run-module | 
 | $ adb push /tmp/simple-vmla.vmfb /data/local/tmp/ | 
 | ``` | 
 |  | 
 | Log into Android: | 
 |  | 
 | ```shell | 
 | $ adb shell | 
 |  | 
 | android $ cd /data/local/tmp/ | 
 | android $ ./iree-run-module -driver=vmla \ | 
 |           -input_file=simple-vmla.vmfb \ | 
 |           -entry_function=abs \ | 
 |           -inputs="i32=-5" | 
 |  | 
 | EXEC @abs | 
 | i32=5 | 
 | ``` | 
 |  | 
 | ### Vulkan HAL backend | 
 |  | 
 | Please make sure your Android device is Vulkan capable. Vulkan is supported on | 
 | Android since 7, but Android 10 is our primary target at the moment. | 
 |  | 
 | Translate a source MLIR into IREE module: | 
 |  | 
 | ```shell | 
 | # Assuming in IREE source root | 
 | $ build-android/host/bin/iree-translate \ | 
 |     -iree-mlir-to-vm-bytecode-module \ | 
 |     -iree-hal-target-backends=vulkan-spirv \ | 
 |     iree/tools/test/simple.mlir \ | 
 |     -o /tmp/simple-vulkan.vmfb | 
 | ``` | 
 |  | 
 | Then push the IREE runtime executable and module to the device: | 
 |  | 
 | ```shell | 
 | $ adb push build-android/iree/tools/iree-run-module /data/local/tmp/ | 
 | $ adb shell chmod +x /data/local/tmp/iree-run-module | 
 | $ adb push /tmp/simple-vulkan.vmfb /data/local/tmp/ | 
 | ``` | 
 |  | 
 | Log into Android: | 
 |  | 
 | ```shell | 
 | $ adb shell | 
 |  | 
 | android $ cd /data/local/tmp/ | 
 | android $ ./iree-run-module -driver=vulkan \ | 
 |           -input_file=simple-vulkan.vmfb \ | 
 |           -entry_function=abs \ | 
 |           -inputs="i32=-5" | 
 |  | 
 | EXEC @abs | 
 | i32=5 | 
 | ``` | 
 |  | 
 | #### Common issues | 
 |  | 
 | ##### Vulkan function `vkCreateInstance` not available | 
 |  | 
 | This can happen on Android devices with ARM Mali GPUs, where there is only one | 
 | monolithic driver (`/vendor/lib[64]/libGLES_mali.so`) and the vulkan vendor | 
 | driver (`/vendor/lib[64]/hw/vulkan.*.so`) is just a symlink to it. This causes | 
 | problems for Vulkan device enumeration under `/data/local/tmp/`. A known | 
 | workaround is to copy the `libGLES_mali.so` library under `/data/local/tmp/` and | 
 | rename it as `libvulkan.so` and then prefix `LD_LIBRARY_PATH=/data/local/tmp` | 
 | when invoking IREE executables. | 
 |  | 
 | ### Dylib LLVM AOT backend | 
 |  | 
 | To compile IREE module for the target Android device (assume Android 10 AArc64) | 
 | we need install the corresponding standalone toolchain and setting AOT linker | 
 | path environment variable: | 
 |  | 
 | ```shell | 
 | $ export ANDROID_ARM64_TOOLCHAIN=/path/to/install/the/toolchain | 
 | $ $ANDROID_NDK/build/tools/make-standalone-toolchain.sh --arch=arm64 --platform=android-29 \ | 
 |     --install-dir=$ANDROID_ARM64_TOOLCHAIN | 
 | $ export IREE_LLVMAOT_LINKER_PATH=$ANDROID_ARM64_TOOLCHAIN/aarch64-linux-android/bin/ld | 
 | ``` | 
 |  | 
 | Translate a source MLIR into an IREE module: | 
 |  | 
 | ```shell | 
 | # Assuming in IREE source root | 
 | $ build-android/host/bin/iree-translate \ | 
 |     -iree-mlir-to-vm-bytecode-module \ | 
 |     -iree-llvm-target-triple=aarch64-linux-android \ | 
 |     -iree-hal-target-backends=dylib-llvm-aot \ | 
 |     iree/tools/test/simple.mlir \ | 
 |     -o /tmp/simple-llvm_aot.vmfb | 
 | ``` | 
 |  | 
 | Then push the IREE runtime executable and module to the device: | 
 |  | 
 | ```shell | 
 | $ adb push build-android/iree/tools/iree-run-module /data/local/tmp/ | 
 | $ adb shell chmod +x /data/local/tmp/iree-run-module | 
 | $ adb push /tmp/simple-llvm_aot.vmfb /data/local/tmp/ | 
 | ``` | 
 |  | 
 | Log into Android: | 
 |  | 
 | ```shell | 
 | $ adb shell | 
 |  | 
 | android $ cd /data/local/tmp/ | 
 | android $ ./iree-run-module -driver=dylib \ | 
 |           -input_file=simple-llvm_aot.vmfb \ | 
 |           -entry_function=abs \ | 
 |           -inputs="i32=-5" | 
 |  | 
 | EXEC @abs | 
 | i32=5 | 
 | ``` |