blob: 4d9689e6a09cbc29c1adbb4651d27bbb068c47cd [file] [log] [blame]
Mike Kelly6fe9ef92023-03-24 19:21:25 +00001#!/bin/bash
2#
3# Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
4#
5# SPDX-License-Identifier: MIT
6#
7
8function Usage() {
9 echo "This script builds Arm NN for Android using the Android NDK. The script builds"
10 echo "the Arm NN core library and its dependencies."
11 echo ""
12 echo "Usage: $CMD [options]"
13 echo "Options:"
14 echo " -l Use this copy of Arm NN and ComputeLibrary instead of cloning new copies"
15 echo " <1 or 0> defaults to 1"
16 echo " -a Override Arm NN branch (defaults to latest release branches/armnn_23_02)"
17 echo " -b Override ACL branch (defaults to latest release v23.02)"
18 echo " -A Android API level defaults to 30"
19 echo " -n Neon (CpuAcc backend) enabled <1 or 0> defaults to 1"
20 echo " -g CL (GpuAcc backend) enabled <1 or 0> defaults to 1"
21 echo " -r Reference (CpuRef backend) enabled <1 or 0> defaults to 1"
22 echo " -u Build unit tests <1 or 0> defaults to 1"
23 echo " -d TfLite Delegate enabled <1 or 0> defaults to 1"
24 echo " -p TfLite Parser enabled <1 or 0> defaults to 1"
25 echo " -s Dynamic Sample enabled <1 or 0> defaults to 0"
26 echo " -i Installation directory defaults to ~/armnn-devenv"
27 echo " -t Push to board and run tests <1 or 0> defaults to 0"
28
29 exit 1
30}
31
32function AssertZeroExitCode {
33 EXITCODE=$?
34 if [[ $EXITCODE -ne 0 ]]; then
35 echo -e "Previous command exited with code $EXITCODE"
36 exit 1
37 fi
38}
39
40THIS_FILE=$(readlink -f "$0")
41BASE_DIR=$(dirname "$THIS_FILE")
42
43# Set variables and working directory
44CREATE_LINKS=1
45ARMNN_BRANCH=branches/armnn_23_02
46ACL_BRANCH=v23.02
47ACL_NEON=1
48ACL_CL=1
49REFERENCE=1
50BUILD_TESTS=1
51DELEGATE=1
52TFLITE_PARSER=1
53DYNAMIC_SAMPLE=0
54CMAKE=$(which cmake)
55WORKING_DIR=$HOME/armnn-devenv
56
57ANDROID_API=30
58PUSH_TO_BOARD=0
59
60# Parse the command line arguments to get build type
61while getopts "hl:a:c:A:n:g:r:u:d:p:s:i:t:" opt; do
62 ((OPTION_COUNTER+=1))
63 case "$opt" in
64 h|\?) Usage;;
65 l) CREATE_LINKS=$OPTARG;;
66 a) ARMNN_BRANCH=$OPTARG;;
67 c) ACL_BRANCH=$OPTARG;;
68 A) ANDROID_API=$OPTARG;;
69 n) ACL_NEON=$OPTARG;;
70 g) ACL_CL=$OPTARG;;
71 r) REFERENCE=$OPTARG;;
72 u) BUILD_TESTS=$OPTARG;;
73 d) DELEGATE=$OPTARG;;
74 p) TFLITE_PARSER=$OPTARG;;
75 s) DYNAMIC_SAMPLE=$OPTARG;;
76 i) WORKING_DIR=$OPTARG;;
77 t) PUSH_TO_BOARD=$OPTARG;;
78 esac
79done
80shift $((OPTIND - 1))
81
82export NDK_DIR=$WORKING_DIR/android-ndk-r25
83export NDK_TOOLCHAIN_ROOT=$NDK_DIR/toolchains/llvm/prebuilt/linux-x86_64
84export PATH=$NDK_TOOLCHAIN_ROOT/bin/:$PATH
85
86pushd $WORKING_DIR
87
88function GetAndroidNDK {
89 cd $WORKING_DIR
90 if [[ ! -d android-ndk-r25 ]]; then
91 echo "+++ Getting Android NDK"
92 wget https://dl.google.com/android/repository/android-ndk-r25-linux.zip
93 unzip android-ndk-r25-linux.zip
94 fi
95}
96
97function GetAndBuildCmake319 {
98 echo "+++ Building Cmake 3.19rc3"
99 cd $WORKING_DIR
100 sudo apt-get install libssl-dev
101 wget https://github.com/Kitware/CMake/releases/download/v3.19.0-rc3/cmake-3.19.0-rc3.tar.gz
102 tar -zxf cmake-3.19.0-rc3.tar.gz
103 pushd cmake-3.19.0-rc3
104 ./bootstrap --prefix=$WORKING_DIR/cmake/install
105 make all install
106 popd
107}
108
109function GetAndBuildFlatbuffers {
110 cd $WORKING_DIR
111
112 if [[ ! -d flatbuffers-2.0.6 ]]; then
113 echo "+++ Getting Flatbuffers"
114 wget https://github.com/google/flatbuffers/archive/v2.0.6.tar.gz
115 tar xf v2.0.6.tar.gz
116 fi
117 #Build FlatBuffers
118 echo "+++ Building x86 Flatbuffers library"
119 cd $WORKING_DIR/flatbuffers-2.0.6
120
121 rm -f CMakeCache.txt
122
123 rm -rf build-x86
124 mkdir build-x86
125 cd build-x86
126
127 rm -rf $WORKING_DIR/flatbuffers-x86
128 mkdir $WORKING_DIR/flatbuffers-x86
129
130 CXXFLAGS="-fPIC" $CMAKE .. \
131 -DFLATBUFFERS_BUILD_FLATC=1 \
132 -DCMAKE_INSTALL_PREFIX:PATH=$WORKING_DIR/flatbuffers-x86
133
134 make all install -j16
135
136 echo "+++ Building Android Flatbuffers library"
137 cd $WORKING_DIR/flatbuffers-2.0.6
138
139 rm -f CMakeCache.txt
140
141 rm -rf build-android
142 mkdir build-android
143 cd build-android
144
145 rm -rf $WORKING_DIR/flatbuffers-android
146 mkdir $WORKING_DIR/flatbuffers-android
147
148 CC=/usr/bin/aarch64-linux-gnu-gcc CXX=/usr/bin/aarch64-linux-gnu-g++ \
149 CXXFLAGS="-fPIC" $CMAKE .. \
150 -DCMAKE_ANDROID_NDK=$NDK_DIR \
151 -DCMAKE_SYSTEM_NAME=Android \
152 -DCMAKE_SYSTEM_VERSION=$ANDROID_API \
153 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
154 -DCMAKE_CXX_FLAGS=--std=c++14 \
155 -DFLATBUFFERS_BUILD_FLATC=OFF \
156 -DCMAKE_BUILD_TYPE=Release \
157 -DFLATBUFFERS_BUILD_TESTS=OFF \
158 -DCMAKE_INSTALL_PREFIX=$WORKING_DIR/flatbuffers-android
159
160 make all install -j16
161}
162
163function GetArmNN {
164 cd $WORKING_DIR
165
166 if [[ ! -d armnn ]]; then
167 if [[ $CREATE_LINKS = 1 && -d $BASE_DIR/../../armnn ]]; then
168 echo "+++ Linking Arm NN"
169 ln -s $BASE_DIR/../../armnn $WORKING_DIR/armnn
170 else
171 echo "+++ Cloning Arm NN"
172 git clone https://review.mlplatform.org/ml/armnn.git armnn
173 cd armnn
174
175 git checkout $ARMNN_BRANCH
176 git log -1
177 fi
178 fi
179}
180
181function GetAndBuildComputeLibrary {
182 cd $WORKING_DIR
183
184 if [[ ! -d ComputeLibrary ]]; then
185 if [[ $CREATE_LINKS = 1 ]]; then
186 if [[ -d $BASE_DIR/../../ComputeLibrary ]]; then
187 echo "+++ Linking ComputeLibrary"
188 ln -s $BASE_DIR/../../ComputeLibrary $WORKING_DIR/ComputeLibrary
189 else
190 echo "+++ Cloning ComputeLibrary"
191 git clone https://review.mlplatform.org/ml/ComputeLibrary.git ComputeLibrary
192 cd ComputeLibrary
193 git checkout $($BASE_DIR/../../armnn/scripts/get_compute_library.sh -p)
194 git log -1
195 fi
196 else
197 echo "+++ Cloning ComputeLibrary"
198
199 git clone https://review.mlplatform.org/ml/ComputeLibrary.git ComputeLibrary
200 cd ComputeLibrary
201 git checkout $ACL_BRANCH
202 git log -1
203 fi
204 fi
205 cd $WORKING_DIR/ComputeLibrary
206
207 echo "+++ Building Compute Library"
208 scons toolchain_prefix=llvm- compiler_prefix=aarch64-linux-android$ANDROID_API- arch=arm64-v8a neon=$ACL_NEON opencl=$ACL_CL embed_kernels=$ACL_CL extra_cxx_flags="-fPIC" \
209 benchmark_tests=0 validation_tests=0 os=android -j16
210}
211
212function GetAndBuildTFLite {
213 TENSORFLOW_REVISION="tags/v2.10.0" # Release 2.10.0 tag
214 TFLITE_ROOT_DIR=${WORKING_DIR}/tensorflow/tensorflow/lite
215
216 cd $WORKING_DIR
217
218 if [[ ! -d tensorflow ]]; then
219 if [[ -d $BASE_DIR/../../armnn ]]; then
220 TENSORFLOW_REVISION=$($BASE_DIR/../../armnn/scripts/get_tensorflow.sh -p)
221 fi
222 echo "+++ Cloning TensorFlow"
223 git clone https://github.com/tensorflow/tensorflow.git
224 AssertZeroExitCode "Cloning TensorFlow failed"
225
226 cd tensorflow
227
228 echo "Checking out ${TENSORFLOW_REVISION}"
229 git fetch && git checkout $TENSORFLOW_REVISION
230
231 cd $WORKING_DIR
232 fi
233
234 CMARGS="-DTFLITE_ENABLE_XNNPACK=OFF"
235
236 # Two different naming conventions; one for build and the other for CC_OPT_FLAGS
237 ANDROID_ARM_ARCH="arm64-v8a"
238
239 mkdir -p tflite-out/android
240 cd tflite-out/android
241
242 echo "*** Configure and Cross-Compile TfLite for ${TARGET_MACHINE} with architecture ${ANDROID_ARM_ARCH}"
243 echo "*** Outputting files to ${TFLITE_OUTPUT_DIR}/${TARGET_MACHINE}"
244
245 CMARGS="$CMARGS -DCMAKE_TOOLCHAIN_FILE=$NDK_DIR/build/cmake/android.toolchain.cmake \
246 -DANDROID_ABI=$ANDROID_ARM_ARCH \
247 -DANDROID_PLATFORM=$ANDROID_API" \
248
249 $CMAKE $CMARGS $TFLITE_ROOT_DIR
250 AssertZeroExitCode "Failed to configure Tensorflow Lite from source"
251
252 cd $WORKING_DIR
253
254 $CMAKE --build tflite-out/android -j 16
255 AssertZeroExitCode "Failed to build Tensorflow Lite from source"
256
257 mkdir -p $WORKING_DIR/tflite-out/tensorflow/tensorflow/lite/schema
258
259 SCHEMA_LOCATION=$WORKING_DIR/tensorflow/tensorflow/lite/schema/schema.fbs
260
261 cp $SCHEMA_LOCATION $WORKING_DIR/tflite-out/tensorflow/tensorflow/lite/schema
262
263 cd $WORKING_DIR/tflite-out/tensorflow/tensorflow/lite/schema
264 $WORKING_DIR/flatbuffers-x86/bin/flatc -c --gen-object-api --reflect-types --reflect-names schema.fbs
265 AssertZeroExitCode "Failed to generate C++ schema from $SCHEMA_LOCATION"
266}
267
268function BuildArmNN {
269 echo "+++ Building Arm NN"
270
271 rm -rf $WORKING_DIR/armnn/build
272
273 mkdir $WORKING_DIR/armnn/build
274 cd $WORKING_DIR/armnn/build
275
276 CMARGS="-DCMAKE_BUILD_TYPE=Release \
277 -DCMAKE_ANDROID_NDK=$NDK_DIR \
278 -DNDK_VERSION=r25 \
279 -DCMAKE_SYSTEM_NAME=Android \
280 -DCMAKE_SYSTEM_VERSION=$ANDROID_API \
281 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
282 -DCMAKE_SYSROOT=$WORKING_DIR/android-ndk-r25/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
283 -DARMCOMPUTE_ROOT=$WORKING_DIR/ComputeLibrary \
284 -DARMCOMPUTE_BUILD_DIR=$WORKING_DIR/ComputeLibrary/build \
285 -DARMCOMPUTENEON=$ACL_NEON -DARMCOMPUTECL=$ACL_CL -DARMNNREF=$REFERENCE \
286 -DFLATBUFFERS_INCLUDE_PATH=$WORKING_DIR/flatbuffers-x86/include \
287 -DFLATBUFFERS_ROOT=$WORKING_DIR/flatbuffers-android \
288 -DFLATC_DIR=$WORKING_DIR/flatbuffers-x86 \
289 -DBUILD_UNIT_TESTS=$BUILD_TESTS \
290 -fexceptions"
291
292 if [[ $TFLITE_PARSER == 1 ]]; then
293 CMARGS="$CMARGS \
294 -DBUILD_TF_LITE_PARSER=1 \
295 -DTF_LITE_GENERATED_PATH=$WORKING_DIR/tflite-out/tensorflow/tensorflow/lite/schema \
296 -DTENSORFLOW_ROOT=$WORKING_DIR/tensorflow \
297 -DTFLITE_LIB_ROOT=$WORKING_DIR/tflite-out/android"
298 fi
299
300 if [[ $DELEGATE == 1 ]]; then
301 CMARGS="$CMARGS \
302 -DBUILD_ARMNN_TFLITE_DELEGATE=1 \
303 -DTENSORFLOW_ROOT=$WORKING_DIR/tensorflow \
304 -DTFLITE_LIB_ROOT=$WORKING_DIR/tflite-out/android \
305 -DTFLITE_ROOT_DIR=$WORKING_DIR/tensorflow/tensorflow/lite"
306 fi
307
308 if [[ $DYNAMIC_SAMPLE == 1 ]]; then
309 DYNAMIC_SAMPLE_PATH="/data/local/tmp/dynamic/sample"
310 CMARGS="$CMARGS \
311 -DDYNAMIC_BACKEND_PATHS=$DYNAMIC_SAMPLE_PATH \
312 -DSAMPLE_DYNAMIC_BACKEND=1"
313 fi
314 echo "args"
315 echo $CMARGS
316 CXX=aarch64-linux-android$ANDROID_API-clang++ \
317 CC=aarch64-linux-android$ANDROID_API-clang \
318 CXX_FLAGS="-fPIE -fPIC" \
319 $CMAKE $CMARGS ..
320 make -j16
321}
322
323function BuildStandaloneDynamicBackend {
324 echo "+++ Building Standalone Dynamic Sample Backend"
325 cd $WORKING_DIR/armnn/src/dynamic/sample
326 BUILD_DIR=build
327 rm -rf $BUILD_DIR
328 mkdir -p $BUILD_DIR
329 cd $BUILD_DIR
330 CXX=aarch64-linux-android$ANDROID_API-clang++ \
331 CC=aarch64-linux-android$ANDROID_API-clang \
332 CXX_FLAGS="-fPIE -fPIC" \
333 $CMAKE \
334 -DCMAKE_C_COMPILER_WORKS=TRUE \
335 -DCMAKE_CXX_COMPILER_WORKS=TRUE \
336 -DCMAKE_ANDROID_NDK=$NDK_DIR \
337 -DCMAKE_SYSTEM_NAME=Android \
338 -DCMAKE_SYSTEM_VERSION=$ANDROID_API \
339 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
340 -DCMAKE_SYSROOT=$WORKING_DIR/android-ndk-r25/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
341 -DCMAKE_CXX_FLAGS=--std=c++14 \
342 -DCMAKE_EXE_LINKER_FLAGS="-pie -llog" \
343 -DCMAKE_MODULE_LINKER_FLAGS="-llog" \
344 -DARMNN_PATH=$WORKING_DIR/armnn/build/libarmnn.so ..
345 make
346}
347
348# push sources to board
349function PushBuildSourcesToBoard {
350 echo "+++ Removing files and symbolic links from previous runs"
351 adb start-server
352 adb shell rm -rf /data/local/tmp/*
353 echo "+++ Pushing sources to board"
354 adb root
355 adb remount
356 sleep 10s
357 adb version
358 adb push libarmnn.so /data/local/tmp/
359 adb push libtimelineDecoder.so /data/local/tmp/
360 adb push libtimelineDecoderJson.so /data/local/tmp/
361 adb push GatordMock /data/local/tmp/
362 adb push libarmnnBasePipeServer.so /data/local/tmp/
363 adb push libarmnnTestUtils.so /data/local/tmp/
364 adb push UnitTests /data/local/tmp/
365 if [[ $DELEGATE == 1 ]]; then
366 adb push ${WORKING_DIR}/armnn/build/delegate/DelegateUnitTests /data/local/tmp/
367 adb push ${WORKING_DIR}/armnn/build/delegate/libarmnnDelegate.so /data/local/tmp/
368 fi
369 adb push $NDK_DIR/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so /data/local/tmp/
370 echo "+++ Pushing test files to board"
371 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testSharedObject
372 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/testSharedObject/* /data/local/tmp/src/backends/backendsCommon/test/testSharedObject/
373 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend
374 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/testDynamicBackend/* /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend/
375 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1
376 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath1/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1/
377 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2
378 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
379 adb shell 'ln -s Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1'
380 adb shell 'ln -s Arm_CpuAcc_backend.so.1 /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1.2'
381 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'
382 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_GpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
383 adb shell 'ln -s nothing /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_no_backend.so'
384 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath3
385 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5
386 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath5/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5/
387 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6
388 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath6/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6/
389 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath7
390 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9
391 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath9/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9/
392 adb shell mkdir -p /data/local/tmp/src/backends/dynamic/reference
393 adb push -p ${WORKING_DIR}/armnn/build/src/backends/dynamic/reference/Arm_CpuRef_backend.so /data/local/tmp/src/backends/dynamic/reference/
394 if [[ $DYNAMIC_SAMPLE == 1 ]]; then
395 adb shell mkdir -p /data/local/tmp/dynamic/sample/
396 adb push -p ${WORKING_DIR}/armnn/src/dynamic/sample/build/libArm_SampleDynamic_backend.so /data/local/tmp/dynamic/sample/
397 fi
398 echo "+++ Running UnitTests"
399 adb shell LD_LIBRARY_PATH=/data/local/tmp:/vendor/lib64:/vendor/lib64/egl /data/local/tmp/UnitTests ; printf $?
400 if [[ $DELEGATE == 1 ]]; then
401 adb shell LD_LIBRARY_PATH=/data/local/tmp:/vendor/lib64:/vendor/lib64/egl /data/local/tmp/DelegateUnitTests ; printf $?
402 fi
403}
404
405# Cleanup any previous runs, setup clean directories
406echo "+++ Creating $WORKING_DIR directory"
407mkdir -p $WORKING_DIR
408AssertZeroExitCode "Creating $WORKING_DIR directory failed"
409
410GetAndroidNDK
411if [[ $? != 0 ]] ; then
412 echo "Downloading Android NDK failed"
413 exit 1
414fi
415GetAndBuildFlatbuffers
416if [[ $? != 0 ]] ; then
417 echo "Building Flatbuffers failed"
418 exit 1
419fi
420if [[ $(lsb_release -rs) == "18.04" ]]; then
421 # We know this is necessary for 18.04 builds.
422 GetAndBuildCmake319
423 CMAKE=$WORKING_DIR/cmake/install/bin/cmake
424fi
425GetArmNN
426if [[ $? != 0 ]] ; then
427 echo "Cloning Arm NN failed"
428 exit 1
429fi
430# Build TFLite if the Delegate or Parser is required
431if [[ $DELEGATE == 1 || $TFLITE_PARSER ]]; then
432 GetAndBuildTFLite
433fi
434if [[ $? != 0 ]] ; then
435 echo "Building tflite failed"
436 exit 1
437fi
438GetAndBuildComputeLibrary
439if [[ $? != 0 ]] ; then
440 echo "Building ComputeLibrary failed"
441 exit 1
442fi
443BuildArmNN
444if [[ $? != 0 ]] ; then
445 echo "Building Arm NN failed"
446 exit 1
447fi
448if [[ $DYNAMIC_SAMPLE == 1 ]]; then
449 BuildStandaloneDynamicBackend
450fi
451if [[ $PUSH_TO_BOARD == 1 ]]; then
452 PushBuildSourcesToBoard
453fi
454if [[ "$R_new" -eq 0 ]]; then
455 echo "Success!"
456else
457 echo "Failed to run UnitTests"
458 exit 1
459fi