IVGCVSW-4451 Add QLstm NEON workload
[platform/upstream/armnn.git] / BuildGuideAndroidNDK.md
1 # How to use the Android NDK to build ArmNN
2
3 *  [Introduction](#introduction)
4 *  [Download the Android NDK and make a standalone toolchain](#downloadNDK)
5 *  [Build the Boost C++ libraries](#buildBoost)
6 *  [Build the Compute Library](#buildCL)
7 *  [Build Google's Protobuf library](#buildProtobuf)
8 *  [Download TensorFlow](#downloadTF)
9 *  [Build ArmNN](#buildArmNN)
10 *  [Run ArmNN UnitTests on an Android device](#runArmNNUnitTests)
11
12
13 #### <a name="introduction">Introduction</a>
14 These are step by step instructions for using the Android NDK to build ArmNN.
15 They have been tested on a clean install of Ubuntu 18.04, and should also work with other OS versions.
16 The instructions show how to build the ArmNN core library and the optional TensorFlow parser.
17 All downloaded or generated files will be saved inside the `~/armnn-devenv` directory.
18
19 #### <a name="downloadNDK">Download the Android NDK and make a standalone toolchain</a>
20
21 * Download the Android NDK from [the official website](https://developer.android.com/ndk/downloads/index.html):
22
23      ```bash
24      mkdir -p ~/armnn-devenv/toolchains
25      cd ~/armnn-devenv/toolchains
26      # For Mac OS, change the NDK download link accordingly.
27      wget https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip
28      unzip android-ndk-r20b-linux-x86_64.zip
29      export NDK=~/armnn-devenv/android-ndk-r20b
30      export NDK_TOOLCHAIN_ROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64
31      export PATH=$NDK_TOOLCHAIN_ROOT/bin/:$PATH
32      ```
33
34          You may want to append the above export variables commands to your `~/.bashrc` (or `~/.bash_profile` in Mac OS).
35
36 * With the android ndk-20b, you don't need to use the make_standalone_toolchain script to create a toolchain for a specific version of android. Android's current preference is for you to just specify the architecture and operating system while setting the compiler and just use the ndk directory.
37
38 #### <a name="buildBoost">Build the Boost C++ libraries</a>
39
40 * Download Boost version 1.64:
41
42    ```bash
43    mkdir ~/armnn-devenv/boost
44    cd ~/armnn-devenv/boost
45    wget https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.bz2
46    tar xvf boost_1_64_0.tar.bz2
47    ```
48
49 * Build:
50
51         (Requires gcc if not previously installed: `sudo apt install gcc`)
52         ```bash
53         echo "using clang : arm : aarch64-linux-android<Android_API>-clang++ ;" > $HOME/armnn-devenv/boost/user-config.jam
54         cd ~/armnn-devenv/boost/boost_1_64_0
55         ./bootstrap.sh --prefix=$HOME/armnn-devenv/boost/install
56         ./b2 install --user-config=$HOME/armnn-devenv/boost/user-config.jam \
57      toolset=clang-arm link=static cxxflags=-fPIC --with-filesystem \
58          --with-test --with-log --with-program_options -j16
59     ```
60  Note: You can specify the 'Android_API' version you want. For example, if your ANDROID_API is 27 then the compiler will be aarch64-linux-android27-clang++.
61
62 #### <a name="buildCL">Build the Compute Library</a>
63 * Clone the Compute Library:
64
65         (Requires Git if not previously installed: `sudo apt install git`)
66
67         ``` bash
68         cd ~/armnn-devenv
69         git clone https://github.com/ARM-software/ComputeLibrary.git
70         ```
71
72 * Build:
73
74         (Requires SCons if not previously installed: `sudo apt install scons`)
75         ```bash
76         cd ComputeLibrary
77         scons arch=arm64-v8a neon=1 opencl=1 embed_kernels=1 extra_cxx_flags="-fPIC" \
78          benchmark_tests=0 validation_tests=0 os=android -j16
79         ```
80
81 #### <a name="buildProtobuf">Build Google's Protobuf library</a>
82
83 * Clone protobuf:
84         ```bash
85         mkdir ~/armnn-devenv/google
86         cd ~/armnn-devenv/google
87         git clone https://github.com/google/protobuf.git
88         cd protobuf
89         git checkout -b v3.5.2 v3.5.2
90         ```
91
92 * Build a native (x86) version of the protobuf libraries and compiler (protoc):
93
94         (Requires cUrl, autoconf, llibtool, and other build dependencies if not previously installed: `sudo apt install curl autoconf libtool build-essential g++`)
95
96         ```bash
97         ./autogen.sh
98         mkdir x86_build
99         cd x86_build
100         ../configure --prefix=$HOME/armnn-devenv/google/x86_pb_install
101         make install -j16
102         cd ..
103         ```
104
105 * Build the arm64 version of the protobuf libraries:
106
107    ```bash
108         mkdir arm64_build
109         cd arm64_build
110         CC=aarch64-linux-android<Android_API>-clang \
111         CXX=aarch64-linux-android<Android_API>-clang++ \
112         CFLAGS="-fPIE -fPIC" \
113         LDFLAGS="-llog -lz -lc++_static" \
114        ../configure --host=aarch64-linux-android \
115        --prefix=$HOME/armnn-devenv/google/arm64_pb_install \
116        --enable-cross-compile \
117        --with-protoc=$HOME/armnn-devenv/google/x86_pb_install/bin/protoc
118         make install -j16
119         cd ..
120         ```
121
122 #### <a name="downloadTF">Download TensorFlow</a>
123 * Clone TensorFlow source code:
124
125         ```bash
126         cd ~/armnn-devenv/google/
127         git clone https://github.com/tensorflow/tensorflow.git
128         cd tensorflow/
129         git checkout 590d6eef7e91a6a7392c8ffffb7b58f2e0c8bc6b
130         ```
131
132         You need tensorflow/contrib/makefile/tf_proto_files.txt from TensorFlow to generate TensorFlow protobuf definitions. This file is not available in TensorFlow master branch.
133
134 #### <a name="buildArmNN">Build ArmNN</a>
135
136 * Clone ArmNN source code:
137
138         ```bash
139         cd ~/armnn-devenv/
140         git clone https://github.com/ARM-software/armnn.git
141         ```
142
143 * Generate TensorFlow protobuf definitions:
144
145         ```bash
146         cd ~/armnn-devenv/google/tensorflow
147         ~/armnn-devenv/armnn/scripts/generate_tensorflow_protobuf.sh \
148          $HOME/armnn-devenv/google/tf_pb $HOME/armnn-devenv/google/x86_pb_install
149         ```
150
151  * Build ArmNN:
152
153         (Requires CMake if not previously installed: `sudo apt install cmake`)
154
155         ```bash
156         mkdir ~/armnn-devenv/armnn/build
157         cd ~/armnn-devenv/armnn/build
158         CXX=aarch64-linux-android<Android_API>-clang++ \
159         CC=aarch64-linux-android<Android_API>-clang \
160         CXX_FLAGS="-fPIE -fPIC" \
161         cmake .. \
162         -DCMAKE_ANDROID_NDK=$NDK \
163         -DCMAKE_SYSTEM_NAME=Android \
164         -DCMAKE_SYSTEM_VERSION=<Android_API> \
165         -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
166         -DCMAKE_EXE_LINKER_FLAGS="-pie -llog -lz" \
167         -DARMCOMPUTE_ROOT=$HOME/armnn-devenv/ComputeLibrary/ \
168         -DARMCOMPUTE_BUILD_DIR=$HOME/armnn-devenv/ComputeLibrary/build \
169         -DBOOST_ROOT=$HOME/armnn-devenv/boost/install/ \
170         -DARMCOMPUTENEON=1 -DARMCOMPUTECL=1 -DARMNNREF=1 \
171         -DTF_GENERATED_SOURCES=$HOME/armnn-devenv/google/tf_pb/ -DBUILD_TF_PARSER=1 \
172         -DPROTOBUF_ROOT=$HOME/armnn-devenv/google/arm64_pb_install/
173         ```
174
175         To include standalone sample dynamic backend tests, add the argument to enable the tests and the dynamic backend path to the CMake command:
176
177     ```bash
178     -DSAMPLE_DYNAMIC_BACKEND=1 \
179     -DDYNAMIC_BACKEND_PATHS=$SAMPLE_DYNAMIC_BACKEND_PATH
180     ```
181     Where $SAMPLE_DYNAMIC_BACKEND_PATH is the path where libArm_SampleDynamic_backend.so library file is pushed
182
183  * Run the build
184     ```bash
185     make -j16
186     ```
187
188 #### <a name="buildStandaloneBackend">Build Standalone Sample Dynamic Backend</a>
189 * The sample dynamic backend is located in armnn/src/dynamic/sample
190     ```bash
191     mkdir build
192     cd build
193     ```
194
195 * Use CMake to configure the build environment, update the following script and run it from the armnn/src/dynamic/sample/build directory to set up the armNN build:
196     ```bash
197     #!/bin/bash
198     CXX=aarch64-linux-android<Android_API>-clang++ \
199     CC=aarch64-linux-android<Android_API>-clang \
200     CXX_FLAGS="-fPIE -fPIC" \
201     cmake \
202     -DCMAKE_SYSTEM_NAME=Android \
203     -DCMAKE_CXX_FLAGS=--std=c++14 \
204     -DCMAKE_EXE_LINKER_FLAGS="-pie -llog" \
205     -DCMAKE_MODULE_LINKER_FLAGS="-llog" \
206     -DBOOST_ROOT=$HOME/armnn-devenv/boost/install \
207     -DBoost_SYSTEM_LIBRARY=$HOME/armnn-devenv/boost/install/lib/libboost_system.a \
208     -DBoost_FILESYSTEM_LIBRARY=$HOME/armnn-devenv/boost/install/lib/libboost_filesystem.a \
209     -DARMNN_PATH=$HOME/armnn-devenv/armnn/build/libarmnn.so ..
210     ```
211
212 * Run the build
213     ```bash
214     make
215     ```
216
217 #### <a name="runArmNNUnitTests">Run the ArmNN unit tests on an Android device</a>
218
219
220 * Push the build results to an Android device and make symbolic links for shared libraries:
221   Currently adb version we have used for testing is 1.0.41.
222
223         ```bash
224         adb push libarmnnTfParser.so /data/local/tmp/
225         adb push libarmnn.so /data/local/tmp/
226         adb push libtimelineDecoder.so /data/local/tmp/
227         adb push UnitTests /data/local/tmp/
228         adb push $NDK/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so /data/local/tmp/
229         adb push $HOME/armnn-devenv/google/arm64_pb_install/lib/libprotobuf.so /data/local/tmp/libprotobuf.so.15.0.1
230         adb shell 'ln -s libprotobuf.so.15.0.1 /data/local/tmp/libprotobuf.so.15'
231         adb shell 'ln -s libprotobuf.so.15.0.1 /data/local/tmp/libprotobuf.so'
232         ```
233
234 * Push the files needed for the unit tests (they are a mix of files, directories and symbolic links):
235
236         ```bash
237         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testSharedObject
238         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/testSharedObject/* /data/local/tmp/src/backends/backendsCommon/test/testSharedObject/
239
240         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend
241         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/testDynamicBackend/* /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend/
242
243         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1
244         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath1/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1/
245
246         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2
247         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
248         adb shell ln -s Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1
249         adb shell ln -s Arm_CpuAcc_backend.so.1 /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1.2
250         adb shell ln -s Arm_CpuAcc_backend.so.1.2 /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1.2.3
251         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_GpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
252         adb shell ln -s nothing /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_no_backend.so
253
254         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath3
255
256         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5
257         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath5/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5/
258
259         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6
260         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath6/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6/
261
262         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath7
263
264         adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9
265         adb push -p ~/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath9/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9/
266
267         adb shell mkdir -p /data/local/tmp/src/backends/dynamic/reference
268         adb push -p ~/armnn-devenv/armnn/build/src/backends/dynamic/reference/Arm_CpuRef_backend.so /data/local/tmp/src/backends/dynamic/reference/
269         ```
270
271         If the standalone sample dynamic tests are enabled, also push libArm_SampleDynamic_backend.so library file to the folder specified as $SAMPLE_DYNAMIC_BACKEND_PATH when ArmNN is built.
272         This is the example when $SAMPLE_DYNAMIC_BACKEND_PATH is specified as /data/local/tmp/dynamic/sample/:
273
274         ```bash
275         adb shell mkdir -p /data/local/tmp/dynamic/sample/
276         adb push -p ${WORKING_DIR}/armnn/src/dynamic/sample/build/libArm_SampleDynamic_backend.so /data/local/tmp/dynamic/sample/
277         ```
278
279 * Run ArmNN unit tests:
280
281         ```bash
282         adb shell 'LD_LIBRARY_PATH=/data/local/tmp:/vendor/lib64:/vendor/lib64/egl /data/local/tmp/UnitTests'
283         ```
284
285         If libarmnnUtils.a is present in `~/armnn-devenv/armnn/build/` and the unit tests run without failure then the build was successful.