ArmNN
 22.05.01
BuildGuideAndroidNDK.md
Go to the documentation of this file.
1 # How to use the Android NDK to build Arm NN
2 
3 - [Introduction](#introduction)
4 - [Download the Android NDK and make a standalone toolchain](#download-the-android-ndk-and-make-a-standalone-toolchain)
5 - [Install Cmake](#install-cmake)
6 - [Build Google's Protobuf library](#build-google-s-protobuf-library)
7 - [Build Flatbuffers](#build-flatbuffers)
8 - [Download Arm NN](#download-arm-nn)
9 - [Build Arm Compute Library](#build-arm-compute-library)
10 - [Build Arm NN](#build-arm-nn)
11 - [Build Standalone Sample Dynamic Backend](#build-standalone-sample-dynamic-backend)
12 - [Run the Arm NN unit tests on an Android device](#run-the-armnn-unit-tests-on-an-android-device)
13 
14 
15 ## Introduction
16 These are step by step instructions for using the Android NDK to build Arm NN.
17 They have been tested on a clean install of Ubuntu 18.04 and 20.04, and should also work with other OS versions.
18 The instructions show how to build the Arm NN core library.
19 Building protobuf is optional. We have given steps should the user wish to build it (i.e. as an Onnx dependency).
20 All downloaded or generated files will be saved inside the `$HOME/armnn-devenv` directory.
21 
22 ## Download the Android NDK and make a standalone toolchain
23 
24 * Download the Android NDK from [the official website](https://developer.android.com/ndk/downloads/index.html):
25  ```bash
26  mkdir -p $HOME/armnn-devenv/
27  cd $HOME/armnn-devenv/
28  # For Mac OS, change the NDK download link accordingly.
29  wget https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip
30  unzip android-ndk-r20b-linux-x86_64.zip
31  export NDK=$HOME/armnn-devenv/android-ndk-r20b
32  export NDK_TOOLCHAIN_ROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64
33  export PATH=$NDK_TOOLCHAIN_ROOT/bin/:$PATH
34 
35  # You may want to append the above export variables commands to your `~/.bashrc` (or `~/.bash_profile` in Mac OS).
36  ```
37 
38 * 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.
39 
40 ## Install Cmake
41 Cmake 3.19rc3 is required to build Arm NN.
42 
43 '''
44 cd $HOME/armnn-devenv
45 sudo apt-get install libssl-dev
46 wget https://github.com/Kitware/CMake/releases/download/v3.19.0-rc3/cmake-3.19.0-rc3.tar.gz
47 tar -zxvf cmake-3.19.0-rc3.tar.gz
48 cd cmake-3.19.0-rc3
49 ./bootstrap --prefix=$HOME/armnn-devenv/cmake/install
50 make all install
51 cd..
52 '''
53 
54 ## Build Google's Protobuf library (Optional)
55 
56 * Clone protobuf:
57  (Requires Git if not previously installed: `sudo apt install git`)
58 ```bash
59 mkdir $HOME/armnn-devenv/google
60 cd $HOME/armnn-devenv/google
61 git clone https://github.com/google/protobuf.git
62 cd protobuf
63 git checkout -b v3.12.0 v3.12.0
64 ```
65 
66 * Build a native (x86) version of the protobuf libraries and compiler (protoc):
67  (Requires cUrl, autoconf, llibtool, and other build dependencies if not previously installed: `sudo apt install curl autoconf libtool build-essential g++`)
68 ```bash
69 ./autogen.sh
70 mkdir x86_build
71 cd x86_build
72 ../configure --prefix=$HOME/armnn-devenv/google/x86_pb_install
73 make install -j16
74 cd ..
75 ```
76 
77 * Build the arm64 version of the protobuf libraries:
78 ```bash
79 mkdir arm64_build
80 cd arm64_build
81 CC=aarch64-linux-android<Android_API>-clang \
82 CXX=aarch64-linux-android<Android_API>-clang++ \
83 CFLAGS="-fPIE -fPIC" \
84  LDFLAGS="-llog -lz -lc++_static" \
85  ../configure --host=aarch64-linux-android \
86  --prefix=$HOME/armnn-devenv/google/arm64_pb_install \
87  --enable-cross-compile \
88  --with-protoc=$HOME/armnn-devenv/google/x86_pb_install/bin/protoc
89 make install -j16
90 cd ..
91 ```
92 
93 Note: The ANDROID_API variable should be set to the Android API version number you are using. E.g. "30" for Android R.
94 
95 ## Build Flatbuffers
96 
97 * Download Flatbuffers
98 ```bash
99 cd $HOME/armnn-devenv
100 wget -O flatbuffers-1.12.0.tar.gz https://github.com/google/flatbuffers/archive/v1.12.0.tar.gz
101 tar xf flatbuffers-1.12.0.tar.gz
102 ```
103 
104 * Build Flatbuffers
105 ```bash
106 cd flatbuffers-1.12.0
107 rm -f CMakeCache.txt
108 rm -rf build
109 mkdir build
110 cd build
111 CXXFLAGS="-fPIC" $CMAKE .. \
112  -DFLATBUFFERS_BUILD_FLATC=1 \
113  -DCMAKE_INSTALL_PREFIX:PATH=$WORKING_DIR/flatbuffers
114 
115 make all install
116 ```
117 Note: -fPIC is added to allow users to use the libraries in shared objects.
118 
119 ## Download Arm NN
120 * Clone Arm NN:
121  (Requires Git if not previously installed: `sudo apt install git`)
122 
123 ```bash
124 cd $HOME/armnn-devenv
125 git clone https://github.com/ARM-software/armnn.git
126 ```
127 
128 * Checkout Arm NN branch:
129 ```bash
130 cd armnn
131 git checkout <branch_name>
132 git pull
133 ```
134 
135 For example, if you want to check out the 21.11 release branch:
136 ```bash
137 git checkout branches/armnn_21_11
138 git pull
139 ```
140 
141 ## Build Arm Compute Library
142 * Clone Arm Compute Library:
143 
144 ```bash
145 cd $HOME/armnn-devenv
146 git clone https://github.com/ARM-software/ComputeLibrary.git
147 ```
148 * Checkout Arm Compute Library release tag:
149 ```bash
150 cd ComputeLibrary
151 git checkout <tag_name>
152 ```
153 For example, if you want to checkout the 21.11 release tag:
154 ```bash
155 git checkout v21.11
156 ```
157 
158 Arm NN and Arm Compute Library are developed closely together. If you would like to use a particular release of Arm NN you will need the same release tag of ACL too.
159 
160 Arm NN provides a script that downloads the version of Arm Compute Library that Arm NN was tested with:
161 ```bash
162 git checkout $(../armnn/scripts/get_compute_library.sh -p)
163 ```
164 * the Arm Compute Library:
165  (Requires SCons if not previously installed: `sudo apt install scons`)
166 ```bash
167 scons arch=arm64-v8a neon=1 opencl=1 embed_kernels=1 extra_cxx_flags="-fPIC" \
168  benchmark_tests=0 validation_tests=0 os=android -j16
169 ```
170 
171 ## Build Arm NN
172 
173 * Build Arm NN:
174  (Requires CMake if not previously installed: `sudo apt install cmake`)
175 ```bash
176 mkdir $HOME/armnn-devenv/armnn/build
177 cd $HOME/armnn-devenv/armnn/build
178 CXX=aarch64-linux-android<Android_API>-clang++ \
179 CC=aarch64-linux-android<Android_API>-clang \
180 CXX_FLAGS="-fPIE -fPIC" \
181 cmake .. \
182  -DCMAKE_ANDROID_NDK=$NDK \
183  -DCMAKE_SYSTEM_NAME=Android \
184  -DCMAKE_SYSTEM_VERSION=<Android_API> \
185  -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
186  -DCMAKE_EXE_LINKER_FLAGS="-pie -llog -lz" \
187  -DARMCOMPUTE_ROOT=$HOME/armnn-devenv/ComputeLibrary/ \
188  -DARMCOMPUTE_BUILD_DIR=$HOME/armnn-devenv/ComputeLibrary/build \
189  -DARMCOMPUTENEON=1 -DARMCOMPUTECL=1 -DARMNNREF=1 \
190  -DPROTOBUF_ROOT=$HOME/armnn-devenv/google/arm64_pb_install/
191  -DFLATBUFFERS_ROOT=$HOME/armnn-devenv/flatbuffers \
192  -DFLATC_DIR=$HOME/armnn-devenv/flatbuffers-1.12.0/build \
193 ```
194 
195 To include standalone sample dynamic backend tests, add the argument to enable the tests and the dynamic backend path to the CMake command:
196 
197 ```bash
198 -DSAMPLE_DYNAMIC_BACKEND=1 \
199 -DDYNAMIC_BACKEND_PATHS=$SAMPLE_DYNAMIC_BACKEND_PATH
200 # Where $SAMPLE_DYNAMIC_BACKEND_PATH is the path where libArm_SampleDynamic_backend.so library file is pushed
201 ```
202 
203  * Run the build
204 ```bash
205 make -j16
206 ```
207 
208 ## Build Standalone Sample Dynamic Backend
209 * The sample dynamic backend is located in armnn/src/dynamic/sample
210 ```bash
211 mkdir build
212 cd build
213 ```
214 
215 * 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 Arm NN build:
216 ```bash
217 #!/bin/bash
218 CXX=aarch64-linux-android<Android_API>-clang++ \
219 CC=aarch64-linux-android<Android_API>-clang \
220 CXX_FLAGS="-fPIE -fPIC" \
221 cmake \
222 -DCMAKE_C_COMPILER_WORKS=TRUE \
223 -DCMAKE_CXX_COMPILER_WORKS=TRUE \
224 -DCMAKE_ANDROID_NDK=$NDK \
225 -DCMAKE_SYSTEM_NAME=Android \
226 -DCMAKE_SYSTEM_VERSION=$ANDROID_API \
227 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
228 -DCMAKE_SYSROOT=$HOME/armnn-devenv/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
229 -DCMAKE_CXX_FLAGS=--std=c++14 \
230 -DCMAKE_EXE_LINKER_FLAGS="-pie -llog" \
231 -DCMAKE_MODULE_LINKER_FLAGS="-llog" \
232 -DARMNN_PATH=$HOME/armnn-devenv/armnn/build/libarmnn.so ..
233 ```
234 
235 * Run the build
236 ```bash
237 make
238 ```
239 
240 ## Run the Arm NN unit tests on an Android device
241 
242 
243 * Push the build results to an Android device and make symbolic links for shared libraries:
244  Currently adb version we have used for testing is 1.0.41.
245 ```bash
246 adb push libarmnn.so /data/local/tmp/
247  adb push libtimelineDecoder.so /data/local/tmp/
248 adb push UnitTests /data/local/tmp/
249 adb push $NDK/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so /data/local/tmp/
250 adb push $HOME/armnn-devenv/google/arm64_pb_install/lib/libprotobuf.so /data/local/tmp/libprotobuf.so.23.0.0
251 adb shell 'ln -s libprotobuf.so.23.0.0 /data/local/tmp/libprotobuf.so.23'
252 adb shell 'ln -s libprotobuf.so.23.0.0 /data/local/tmp/libprotobuf.so'
253 ```
254 
255 * Push the files needed for the unit tests (they are a mix of files, directories and symbolic links):
256 ```bash
257 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testSharedObject
258 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/testSharedObject/* /data/local/tmp/src/backends/backendsCommon/test/testSharedObject/
259 
260 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend
261 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/testDynamicBackend/* /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend/
262 
263 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1
264 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath1/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1/
265 
266 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2
267 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
268 adb shell ln -s Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1
269 adb shell ln -s Arm_CpuAcc_backend.so.1 /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1.2
270 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
271 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_GpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
272 adb shell ln -s nothing /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_no_backend.so
273 
274 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath3
275 
276 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5
277 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath5/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5/
278 
279 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6
280 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath6/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6/
281 
282 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath7
283 
284 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9
285 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/backendsCommon/test/backendsTestPath9/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9/
286 
287 adb shell mkdir -p /data/local/tmp/src/backends/dynamic/reference
288 adb push -p $HOME/armnn-devenv/armnn/build/src/backends/dynamic/reference/Arm_CpuRef_backend.so /data/local/tmp/src/backends/dynamic/reference/
289 
290 # 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 Arm NN is built.
291 # This is the example when $SAMPLE_DYNAMIC_BACKEND_PATH is specified as /data/local/tmp/dynamic/sample/:
292 
293 adb shell mkdir -p /data/local/tmp/dynamic/sample/
294 adb push -p $HOME/armnn-devenv/armnn/src/dynamic/sample/build/libArm_SampleDynamic_backend.so /data/local/tmp/dynamic/sample/
295 ```
296 
297 * Run Arm NN unit tests:
298 ```bash
299 adb shell 'LD_LIBRARY_PATH=/data/local/tmp:/vendor/lib64:/vendor/lib64/egl /data/local/tmp/UnitTests'
300 ```
301 If libarmnnUtils.a is present in `$HOME/armnn-devenv/armnn/build/` and the unit tests run without failure then the build was successful.