1#!/bin/bash 2############################################################################## 3# Example command to build the android target. 4############################################################################## 5# 6# This script shows how one can build a Caffe2 binary for the Android platform 7# using android-cmake. A few notes: 8# 9# (1) This build also does a host build for protobuf. You will need autoconf 10# to carry out this. If autoconf is not possible, you will need to provide 11# a pre-built protoc binary that is the same version as the protobuf 12# version under third_party. 13# If you are building on Mac, you might need to install autotool and 14# libtool. The easiest way is via homebrew: 15# brew install automake 16# brew install libtool 17# (2) You will need to have android ndk installed. The current script assumes 18# that you set ANDROID_NDK to the location of ndk. 19# (3) The toolchain and the build target platform can be specified with the 20# cmake arguments below. For more details, check out android-cmake's doc. 21 22set -e 23 24# Android specific flags 25if [ -z "$ANDROID_ABI" ]; then 26 ANDROID_ABI="armeabi-v7a with NEON" 27fi 28ANDROID_NATIVE_API_LEVEL="21" 29echo "Build with ANDROID_ABI[$ANDROID_ABI], ANDROID_NATIVE_API_LEVEL[$ANDROID_NATIVE_API_LEVEL]" 30 31CAFFE2_ROOT="$( cd "$(dirname "$0")"/.. ; pwd -P)" 32if [ -z "$ANDROID_NDK" ]; then 33 echo "ANDROID_NDK not set; please set it to the Android NDK directory" 34 exit 1 35fi 36 37if [ ! -d "$ANDROID_NDK" ]; then 38 echo "ANDROID_NDK not a directory; did you install it under $ANDROID_NDK?" 39 exit 1 40fi 41 42if [ -z "$PYTHON" ]; then 43 PYTHON=python 44 PYTHON_VERSION_MAJOR=$($PYTHON -c 'import sys; print(sys.version_info[0])') 45 if [ "${PYTHON_VERSION_MAJOR}" -le 2 ]; then 46 echo "Default python executable is Python-2, trying to use python3 alias" 47 PYTHON=python3 48 fi 49fi 50 51ANDROID_NDK_PROPERTIES="$ANDROID_NDK/source.properties" 52[ -f "$ANDROID_NDK_PROPERTIES" ] && ANDROID_NDK_VERSION=$(sed -n 's/^Pkg.Revision[^=]*= *\([0-9]*\)\..*$/\1/p' "$ANDROID_NDK_PROPERTIES") 53 54echo "Bash: $(/bin/bash --version | head -1)" 55echo "Python: $($PYTHON -c 'import sys; print(sys.version)')" 56echo "Caffe2 path: $CAFFE2_ROOT" 57echo "Using Android NDK at $ANDROID_NDK" 58echo "Android NDK version: $ANDROID_NDK_VERSION" 59 60CMAKE_ARGS=() 61 62# Build PyTorch mobile 63CMAKE_ARGS+=("-DCMAKE_PREFIX_PATH=$($PYTHON -c 'import sysconfig; print(sysconfig.get_path("purelib"))')") 64CMAKE_ARGS+=("-DPython_EXECUTABLE=$($PYTHON -c 'import sys; print(sys.executable)')") 65CMAKE_ARGS+=("-DBUILD_CUSTOM_PROTOBUF=OFF") 66 67# custom build with selected ops 68if [ -n "${SELECTED_OP_LIST}" ]; then 69 SELECTED_OP_LIST="$(cd $(dirname $SELECTED_OP_LIST); pwd -P)/$(basename $SELECTED_OP_LIST)" 70 echo "Choose SELECTED_OP_LIST file: $SELECTED_OP_LIST" 71 if [ ! -r ${SELECTED_OP_LIST} ]; then 72 echo "Error: SELECTED_OP_LIST file ${SELECTED_OP_LIST} not found." 73 exit 1 74 fi 75 CMAKE_ARGS+=("-DSELECTED_OP_LIST=${SELECTED_OP_LIST}") 76fi 77 78# If Ninja is installed, prefer it to Make 79if [ -x "$(command -v ninja)" ]; then 80 CMAKE_ARGS+=("-GNinja") 81fi 82 83# Use android-cmake to build Android project from CMake. 84CMAKE_ARGS+=("-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake") 85 86if [ -z "$BUILD_MOBILE_BENCHMARK" ]; then 87 BUILD_MOBILE_BENCHMARK=0 88fi 89 90if [ -z "$BUILD_MOBILE_TEST" ]; then 91 BUILD_MOBILE_TEST=0 92fi 93# Don't build artifacts we don't need 94CMAKE_ARGS+=("-DBUILD_TEST=OFF") 95CMAKE_ARGS+=("-DBUILD_BINARY=OFF") 96 97# If there exists env variable and it equals to 0, build full jit interpreter. 98# Default behavior is to build lite interpreter 99# cmd: BUILD_LITE_INTERPRETER=0 ./scripts/build_android.sh 100if [ "${BUILD_LITE_INTERPRETER}" == 0 ]; then 101 CMAKE_ARGS+=("-DBUILD_LITE_INTERPRETER=OFF") 102else 103 CMAKE_ARGS+=("-DBUILD_LITE_INTERPRETER=ON") 104fi 105if [ "${TRACING_BASED}" == 1 ]; then 106 CMAKE_ARGS+=("-DTRACING_BASED=ON") 107else 108 CMAKE_ARGS+=("-DTRACING_BASED=OFF") 109fi 110if [ "${USE_LIGHTWEIGHT_DISPATCH}" == 1 ]; then 111 CMAKE_ARGS+=("-DUSE_LIGHTWEIGHT_DISPATCH=ON") 112 CMAKE_ARGS+=("-DSTATIC_DISPATCH_BACKEND=CPU") 113else 114 CMAKE_ARGS+=("-DUSE_LIGHTWEIGHT_DISPATCH=OFF") 115fi 116 117CMAKE_ARGS+=("-DBUILD_MOBILE_BENCHMARK=$BUILD_MOBILE_BENCHMARK") 118CMAKE_ARGS+=("-DBUILD_MOBILE_TEST=$BUILD_MOBILE_TEST") 119CMAKE_ARGS+=("-DBUILD_PYTHON=OFF") 120CMAKE_ARGS+=("-DBUILD_SHARED_LIBS=OFF") 121if (( "${ANDROID_NDK_VERSION:-0}" < 18 )); then 122 CMAKE_ARGS+=("-DANDROID_TOOLCHAIN=gcc") 123else 124 CMAKE_ARGS+=("-DANDROID_TOOLCHAIN=clang") 125fi 126# Disable unused dependencies 127CMAKE_ARGS+=("-DUSE_CUDA=OFF") 128CMAKE_ARGS+=("-DUSE_ITT=OFF") 129CMAKE_ARGS+=("-DUSE_GFLAGS=OFF") 130CMAKE_ARGS+=("-DUSE_OPENCV=OFF") 131CMAKE_ARGS+=("-DUSE_MPI=OFF") 132CMAKE_ARGS+=("-DUSE_OPENMP=OFF") 133# Only toggle if VERBOSE=1 134if [ "${VERBOSE:-}" == '1' ]; then 135 CMAKE_ARGS+=("-DCMAKE_VERBOSE_MAKEFILE=1") 136fi 137 138# Android specific flags 139CMAKE_ARGS+=("-DANDROID_NDK=$ANDROID_NDK") 140CMAKE_ARGS+=("-DANDROID_ABI=$ANDROID_ABI") 141CMAKE_ARGS+=("-DANDROID_NATIVE_API_LEVEL=$ANDROID_NATIVE_API_LEVEL") 142CMAKE_ARGS+=("-DANDROID_CPP_FEATURES=rtti exceptions") 143if [ "${ANDROID_STL_SHARED:-}" == '1' ]; then 144 CMAKE_ARGS+=("-DANDROID_STL=c++_shared") 145fi 146if [ "${ANDROID_DEBUG_SYMBOLS:-}" == '1' ]; then 147 CMAKE_ARGS+=("-DANDROID_DEBUG_SYMBOLS=1") 148fi 149 150if [ -n "${USE_VULKAN}" ]; then 151 CMAKE_ARGS+=("-DUSE_VULKAN=ON") 152 if [ -n "${USE_VULKAN_FP16_INFERENCE}" ]; then 153 CMAKE_ARGS+=("-DUSE_VULKAN_FP16_INFERENCE=ON") 154 fi 155 if [ -n "${USE_VULKAN_RELAXED_PRECISION}" ]; then 156 CMAKE_ARGS+=("-DUSE_VULKAN_RELAXED_PRECISION=ON") 157 fi 158fi 159 160# Use-specified CMake arguments go last to allow overridding defaults 161CMAKE_ARGS+=($@) 162 163# Patch pocketfft (as Android does not have aligned_alloc even if compiled with c++17 164if [ -f third_party/pocketfft/pocketfft_hdronly.h ]; then 165 sed -i -e "s/__cplusplus >= 201703L/0/" third_party/pocketfft/pocketfft_hdronly.h 166fi 167 168# Now, actually build the Android target. 169BUILD_ROOT=${BUILD_ROOT:-"$CAFFE2_ROOT/build_android"} 170INSTALL_PREFIX=${BUILD_ROOT}/install 171mkdir -p $BUILD_ROOT 172cd $BUILD_ROOT 173cmake "$CAFFE2_ROOT" \ 174 -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX \ 175 -DCMAKE_BUILD_TYPE=Release \ 176 "${CMAKE_ARGS[@]}" 177 178# Cross-platform parallel build 179if [ -z "$MAX_JOBS" ]; then 180 if [ "$(uname)" == 'Darwin' ]; then 181 MAX_JOBS=$(sysctl -n hw.ncpu) 182 else 183 MAX_JOBS=$(nproc) 184 fi 185fi 186 187echo "Will install headers and libs to $INSTALL_PREFIX for further Android project usage." 188cmake --build . --target install -- "-j${MAX_JOBS}" 189echo "Installation completed, now you can copy the headers/libs from $INSTALL_PREFIX to your Android project directory." 190