| #!/bin/bash |
| # Copyright 2020 The IREE Authors |
| # |
| # Licensed under the Apache License v2.0 with LLVM Exceptions. |
| # See https://llvm.org/LICENSE.txt for license information. |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| |
| set -e |
| |
| ######################### |
| # Script input parameters |
| ######################### |
| |
| echo "=== A script for building iree-run-module apk ===" |
| echo "This script wraps iree-run-module together with a" |
| echo "specific IREE VM module and invocation information." |
| echo "" |
| echo "At a minimum, it expects the following env vars:" |
| echo "* ANDROID_SDK_ROOT" |
| echo "* ANDROID_NDK_ROOT" |
| echo "* ANDROID_SDK_BUILD_TOOLS_VERSION" |
| echo "See the script for details and more controls." |
| echo "===-------------------------------------------===" |
| echo "" |
| |
| print_usage_and_exit() { |
| echo "Usage: $0 <artifact-directory> " |
| echo " --driver <driver>" |
| echo " --module_file <input-module-file> " |
| echo " --entry_function <entry-function> " |
| echo " --function_inputs_file <input-buffer-file> " |
| exit 1 |
| } |
| |
| while (( "$#" )); do |
| case "$1" in |
| --driver) |
| if [[ -n "$2" ]] && [[ ${2:0:1} != "-" ]]; then |
| IREE_DRIVER=$2 |
| shift 2 |
| else |
| echo "Error: missing argument for $1" >&2 |
| print_usage_and_exit |
| fi |
| ;; |
| --module_file) |
| if [[ -n "$2" ]] && [[ ${2:0:1} != "-" ]]; then |
| IREE_INPUT_MODULE_FILE=$(readlink -f $2) |
| shift 2 |
| else |
| echo "Error: missing argument for $1" >&2 |
| print_usage_and_exit |
| fi |
| ;; |
| --entry_function) |
| if [[ -n "$2" ]] && [[ ${2:0:1} != "-" ]]; then |
| IREE_ENTRY_FUNCTION=$2 |
| shift 2 |
| else |
| echo "Error: missing argument for $1" >&2 |
| print_usage_and_exit |
| fi |
| ;; |
| --function_inputs_file) |
| if [[ -n "$2" ]] && [[ ${2:0:1} != "-" ]]; then |
| IREE_INPUT_BUFFER_FILE=$(readlink -f $2) |
| shift 2 |
| else |
| echo "Error: missing argument for $1" >&2 |
| print_usage_and_exit |
| fi |
| ;; |
| -*|--*=) # Unsupported flags |
| echo "Error: Unsupported flag $1" >&2 |
| exit 1 |
| ;; |
| *) # Positional arguments |
| if [[ -z "${IREE_ARTIFACT_ROOT+x}" ]]; then |
| IREE_ARTIFACT_ROOT=$(readlink -f $1) |
| else |
| echo "Error: <artifact-directory> already set to ${IREE_ARTIFACT_ROOT}" >&2 |
| print_usage_and_exit |
| fi |
| shift |
| ;; |
| esac |
| done |
| |
| if [[ -z "${IREE_ARTIFACT_ROOT}" ]] || [[ -z "${IREE_INPUT_MODULE_FILE}" ]] || \ |
| [[ -z "${IREE_ENTRY_FUNCTION}" ]] || [[ -z "${IREE_INPUT_BUFFER_FILE}" ]] || \ |
| [[ -z "${IREE_DRIVER}" ]]; then |
| echo "Error: missing necessary parameters" >&2 |
| print_usage_and_exit |
| fi |
| |
| ################################# |
| # IREE Android app configurations |
| ################################# |
| |
| # The final Android APK name; default to "iree-run-module.apk". |
| IREE_APK_NAME="${IREE_APK_NAME:-iree-run-module}" |
| # The CMAKE build type for compiling IREE. default to Release. |
| IREE_BUILD_TYPE="${IREE_BUILD_TYPE:-Release}" |
| # The target Android API level; default to Android 10 (API level 29). |
| IREE_ANDROID_API_LEVEL="${IREE_ANDROID_API_LEVEL:-29}" |
| # The target Android platform ABI; default to arm64-v8a. |
| IREE_ANDROID_ABI="${IREE_ANDROID_ABI:-arm64-v8a}" |
| |
| ################################ |
| # Android SDK/NDK configurations |
| ################################ |
| |
| # Android SDK root; must be provided as environment variable. |
| # By default Android Studio uses |
| # * $HOME/Android/Sdk for Linux. |
| # * $HOME/Library/Android/sdk for macOS. |
| # * $%LOCALAPPDATA%\Android\sdk for Windows. |
| ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:?environment variable not set}" |
| # Android NDK root; must be provided as environment variable. |
| ANDROID_NDK_ROOT="${ANDROID_NDK_ROOT:?environment variable not set}" |
| # Android SDK build tools version; must be provided as environment variable. |
| ANDROID_SDK_BUILD_TOOLS_VERSION="${ANDROID_SDK_BUILD_TOOLS_VERSION?environment variable not set}" |
| # Key store for signing apk files; default to Android debug keystore created |
| # by Android Studio. |
| ANDROID_KEYSTORE="${ANDROID_KEYSTORE:-${HOME}/.android/debug.keystore}" |
| |
| ###################### |
| # IREE build toolchain |
| ###################### |
| |
| CMAKE_BIN="${CMAKE_BIN:-$(which cmake)}" |
| NINJA_BIN="${NINJA_BIN:-$(which ninja)}" |
| CC_BIN="${CC_BIN:-$(which clang)}" |
| CXX_BIN="${CXX_BIN:-$(which clang++)}" |
| JAVAC_BIN="${JAVAC_BIN:-$(which javac)}" |
| |
| ################################## |
| # IREE source/artifact directories |
| ################################## |
| |
| # IREE project source root. |
| IREE_SOURCE_ROOT="$(git rev-parse --show-toplevel)" |
| # iree-run-module Android app source root. |
| IREE_NATIVE_APP_SOURCE_ROOT="${IREE_SOURCE_ROOT?}/tools/android/run_module_app" |
| |
| # Directory for IREE native code intermediate intermediate artifacts. |
| IREE_NATIVE_LIB_BUILD_DIR="${IREE_ARTIFACT_ROOT?}/iree/${IREE_BUILD_TYPE?}" |
| # Directory for holding APK parts. |
| IREE_APK_PARTS_DIR="${IREE_ARTIFACT_ROOT?}/parts" |
| # Directory for IREE native libraries. |
| IREE_NATIVE_LIB_DIR="${IREE_APK_PARTS_DIR?}/libs/lib/${IREE_ANDROID_ABI?}" |
| # Directory for Android app assets. |
| IREE_ASSET_DIR="${IREE_APK_PARTS_DIR?}/assets" |
| # Directory for Android app R.class. |
| IREE_RESOURCE_GEN_DIR="${IREE_APK_PARTS_DIR?}/rclass" |
| |
| ######################### |
| # Android build toolchain |
| ######################### |
| |
| ANDROID_SDK_BUILD_TOOLS_DIR="${ANDROID_SDK_ROOT?}/build-tools/${ANDROID_SDK_BUILD_TOOLS_VERSION?}" |
| ANDROID_SDK_PLATFORMS_DIR="${ANDROID_SDK_ROOT?}/platforms/android-${IREE_ANDROID_API_LEVEL?}" |
| |
| AAPT_BIN="${ANDROID_SDK_BUILD_TOOLS_DIR?}/aapt" |
| DX_BIN="${ANDROID_SDK_BUILD_TOOLS_DIR?}/dx" |
| ZIPALIGN_BIN="${ANDROID_SDK_BUILD_TOOLS_DIR?}/zipalign" |
| APKSIGNER_BIN="${ANDROID_SDK_BUILD_TOOLS_DIR?}/apksigner" |
| |
| AAPT_ADD="${AAPT_BIN?} add" |
| # Link in the Android framework classes and disable compression for IREE |
| # bytecode modules. This allows us to mmap the file directly. |
| AAPT_PACK="${AAPT_BIN?} package -f -I ${ANDROID_SDK_PLATFORMS_DIR?}/android.jar -0 vmfb" |
| DX="${DX_BIN?} --dex" |
| ZIPALIGN="${ZIPALIGN_BIN?} -f -p 4" |
| APKSIGN="${APKSIGNER_BIN?} sign" |
| JAVAC="${JAVAC_BIN?} -classpath ${ANDROID_SDK_PLATFORMS_DIR?}/android.jar -sourcepath ${IREE_RESOURCE_GEN_DIR?} -d ${IREE_APK_PARTS_DIR?}" |
| |
| ############################# |
| # Build IREE native libraries |
| ############################# |
| |
| mkdir -p "${IREE_NATIVE_LIB_BUILD_DIR?}" |
| |
| echo ">>> Building IREE native libraries <<<" |
| |
| IREE_NATIVE_LIB_NAME=iree_tools_android_run_module_app_iree_run_module_app |
| |
| pushd "${IREE_NATIVE_LIB_BUILD_DIR?}" |
| "${CMAKE_BIN?}" "${IREE_SOURCE_ROOT?}" -G Ninja \ |
| -DCMAKE_BUILD_TYPE="${IREE_BUILD_TYPE?}" \ |
| -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT?}/build/cmake/android.toolchain.cmake" \ |
| -DANDROID_ABI="${IREE_ANDROID_ABI?}" \ |
| -DANDROID_PLATFORM="android-${IREE_ANDROID_API_LEVEL?}" \ |
| -DIREE_HOST_C_COMPILER="${CC_BIN?}" \ |
| -DIREE_HOST_CXX_COMPILER="${CXX_BIN?}" \ |
| -DIREE_BUILD_COMPILER=OFF \ |
| -DIREE_BUILD_TESTS=OFF \ |
| -DIREE_BUILD_SAMPLES=OFF |
| "${NINJA_BIN?}" "${IREE_NATIVE_LIB_NAME?}" |
| popd |
| |
| ##################### |
| # Package Android app |
| ##################### |
| |
| # Clean artifacts from previous runs. |
| rm -rf "${IREE_ARTIFACT_ROOT?}/${IREE_APK_NAME?}.apk" "${IREE_APK_PARTS_DIR?}" |
| |
| echo ">>> Generating AndroidManifest.xml <<<" |
| |
| # Create an AndroidManifest.xml with proper target SDK version. |
| mkdir -p "${IREE_APK_PARTS_DIR?}" |
| IREE_ANDROID_API_LEVEL="${IREE_ANDROID_API_LEVEL?}" envsubst \ |
| < "${IREE_NATIVE_APP_SOURCE_ROOT?}/AndroidManifest.xml.template" \ |
| > "${IREE_APK_PARTS_DIR?}/AndroidManifest.xml" |
| |
| echo ">>> Preparing shared libraries and vm module information <<<" |
| |
| # Find the compiled iree_run_module_app shared library and symlink it to a |
| # known location for packaging. |
| mkdir -p "${IREE_NATIVE_LIB_DIR?}" |
| IREE_NATIVE_LIB=$(find ${IREE_NATIVE_LIB_BUILD_DIR?} -name "lib${IREE_NATIVE_LIB_NAME?}.so") |
| # Note: the target link name must match with |
| # run_module_app/AndroidManifest.xml.template. |
| ln -sf "${IREE_NATIVE_LIB?}" "${IREE_NATIVE_LIB_DIR?}/libiree_run_module_app.so" |
| |
| # Copy the VM FlatBuffer and iree-run-module invocation related information |
| # over as assets. |
| mkdir -p "${IREE_ASSET_DIR?}" |
| # Note: the following files must match with run_module_app/src/main.cc. |
| cp "${IREE_INPUT_MODULE_FILE?}" "${IREE_ASSET_DIR?}/module.vmfb" |
| cp "${IREE_INPUT_BUFFER_FILE?}" "${IREE_ASSET_DIR?}/inputs.txt" |
| echo -n "${IREE_ENTRY_FUNCTION?}" > "${IREE_ASSET_DIR?}/entry_function.txt" |
| echo -n "${IREE_DRIVER?}" > "${IREE_ASSET_DIR?}/driver.txt" |
| |
| echo ">>> Compiling app resources <<<" |
| |
| # Generate the R.java for resources. |
| mkdir -p "${IREE_RESOURCE_GEN_DIR?}" |
| ${AAPT_PACK?} --non-constant-id -m \ |
| -M "${IREE_APK_PARTS_DIR?}/AndroidManifest.xml" \ |
| -S "${IREE_NATIVE_APP_SOURCE_ROOT?}/res" \ |
| -J "${IREE_RESOURCE_GEN_DIR?}" \ |
| --generate-dependencies |
| |
| # Compile the R.java and create classes.dex out of it for Android. |
| echo "Using javac: '${JAVAC_BIN?}'" |
| ${JAVAC?} "${IREE_RESOURCE_GEN_DIR?}"/com/google/iree/run_module/*.java |
| ${DX?} --output="${IREE_APK_PARTS_DIR?}/classes.dex" "${IREE_APK_PARTS_DIR?}" |
| |
| echo ">>> Packaging apk file <<<" |
| |
| # Package assets and shared libraries into an apk file. |
| ${AAPT_PACK?} -m \ |
| -M "${IREE_APK_PARTS_DIR?}/AndroidManifest.xml" \ |
| -S "${IREE_NATIVE_APP_SOURCE_ROOT?}/res" \ |
| -A "${IREE_APK_PARTS_DIR?}/assets" \ |
| -F "${IREE_APK_PARTS_DIR?}/${IREE_APK_NAME?}.unaligned.apk" \ |
| --shared-lib "${IREE_APK_PARTS_DIR?}/libs" |
| |
| pushd "${IREE_APK_PARTS_DIR?}" |
| # Also package the resources into the apk file. |
| ${AAPT_ADD?} "${IREE_APK_NAME?}.unaligned.apk" classes.dex |
| echo ">>> Aligning apk file <<<" |
| ${ZIPALIGN?} "${IREE_APK_NAME?}.unaligned.apk" "${IREE_APK_NAME?}.apk" |
| echo ">>> Signing apk file <<<" |
| echo "NOTE: if you are using the Android Studio's debug keystore, the password is 'android'." |
| ${APKSIGN?} --ks "${ANDROID_KEYSTORE?}" --min-sdk-version 28 "${IREE_APK_NAME?}.apk" |
| mv "${IREE_APK_NAME?}.apk" "${IREE_ARTIFACT_ROOT?}" |
| popd |
| |
| echo ">>> Done: '${IREE_ARTIFACT_ROOT?}/${IREE_APK_NAME?}.apk' <<<" |