blob: a7fd674bfa6ecd5efc6fa5a8eeb0ae20fb87555d [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"
Mike Kellyc1a1d0f2023-04-14 13:43:06 +010022 echo " -u Build tests and test applications <1 or 0> defaults to 1"
Mike Kelly6fe9ef92023-03-24 19:21:25 +000023 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 \
Mike Kellyc1a1d0f2023-04-14 13:43:06 +0100290 -DBUILD_TESTS=$BUILD_TESTS \
Mike Kelly6fe9ef92023-03-24 19:21:25 +0000291 -fexceptions"
292
293 if [[ $TFLITE_PARSER == 1 ]]; then
294 CMARGS="$CMARGS \
295 -DBUILD_TF_LITE_PARSER=1 \
296 -DTF_LITE_GENERATED_PATH=$WORKING_DIR/tflite-out/tensorflow/tensorflow/lite/schema \
297 -DTENSORFLOW_ROOT=$WORKING_DIR/tensorflow \
298 -DTFLITE_LIB_ROOT=$WORKING_DIR/tflite-out/android"
299 fi
300
301 if [[ $DELEGATE == 1 ]]; then
302 CMARGS="$CMARGS \
303 -DBUILD_ARMNN_TFLITE_DELEGATE=1 \
304 -DTENSORFLOW_ROOT=$WORKING_DIR/tensorflow \
305 -DTFLITE_LIB_ROOT=$WORKING_DIR/tflite-out/android \
306 -DTFLITE_ROOT_DIR=$WORKING_DIR/tensorflow/tensorflow/lite"
307 fi
308
309 if [[ $DYNAMIC_SAMPLE == 1 ]]; then
310 DYNAMIC_SAMPLE_PATH="/data/local/tmp/dynamic/sample"
311 CMARGS="$CMARGS \
312 -DDYNAMIC_BACKEND_PATHS=$DYNAMIC_SAMPLE_PATH \
313 -DSAMPLE_DYNAMIC_BACKEND=1"
314 fi
315 echo "args"
316 echo $CMARGS
317 CXX=aarch64-linux-android$ANDROID_API-clang++ \
318 CC=aarch64-linux-android$ANDROID_API-clang \
319 CXX_FLAGS="-fPIE -fPIC" \
320 $CMAKE $CMARGS ..
321 make -j16
322}
323
324function BuildStandaloneDynamicBackend {
325 echo "+++ Building Standalone Dynamic Sample Backend"
326 cd $WORKING_DIR/armnn/src/dynamic/sample
327 BUILD_DIR=build
328 rm -rf $BUILD_DIR
329 mkdir -p $BUILD_DIR
330 cd $BUILD_DIR
331 CXX=aarch64-linux-android$ANDROID_API-clang++ \
332 CC=aarch64-linux-android$ANDROID_API-clang \
333 CXX_FLAGS="-fPIE -fPIC" \
334 $CMAKE \
335 -DCMAKE_C_COMPILER_WORKS=TRUE \
336 -DCMAKE_CXX_COMPILER_WORKS=TRUE \
337 -DCMAKE_ANDROID_NDK=$NDK_DIR \
338 -DCMAKE_SYSTEM_NAME=Android \
339 -DCMAKE_SYSTEM_VERSION=$ANDROID_API \
340 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
341 -DCMAKE_SYSROOT=$WORKING_DIR/android-ndk-r25/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
342 -DCMAKE_CXX_FLAGS=--std=c++14 \
343 -DCMAKE_EXE_LINKER_FLAGS="-pie -llog" \
344 -DCMAKE_MODULE_LINKER_FLAGS="-llog" \
345 -DARMNN_PATH=$WORKING_DIR/armnn/build/libarmnn.so ..
346 make
347}
348
349# push sources to board
350function PushBuildSourcesToBoard {
351 echo "+++ Removing files and symbolic links from previous runs"
352 adb start-server
353 adb shell rm -rf /data/local/tmp/*
354 echo "+++ Pushing sources to board"
355 adb root
356 adb remount
357 sleep 10s
358 adb version
359 adb push libarmnn.so /data/local/tmp/
360 adb push libtimelineDecoder.so /data/local/tmp/
361 adb push libtimelineDecoderJson.so /data/local/tmp/
362 adb push GatordMock /data/local/tmp/
363 adb push libarmnnBasePipeServer.so /data/local/tmp/
364 adb push libarmnnTestUtils.so /data/local/tmp/
365 adb push UnitTests /data/local/tmp/
366 if [[ $DELEGATE == 1 ]]; then
367 adb push ${WORKING_DIR}/armnn/build/delegate/DelegateUnitTests /data/local/tmp/
368 adb push ${WORKING_DIR}/armnn/build/delegate/libarmnnDelegate.so /data/local/tmp/
369 fi
370 adb push $NDK_DIR/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so /data/local/tmp/
371 echo "+++ Pushing test files to board"
372 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testSharedObject
373 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/testSharedObject/* /data/local/tmp/src/backends/backendsCommon/test/testSharedObject/
374 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend
375 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/testDynamicBackend/* /data/local/tmp/src/backends/backendsCommon/test/testDynamicBackend/
376 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1
377 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath1/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath1/
378 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2
379 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
380 adb shell 'ln -s Arm_CpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1'
381 adb shell 'ln -s Arm_CpuAcc_backend.so.1 /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1.2'
382 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'
383 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_GpuAcc_backend.so /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/
384 adb shell 'ln -s nothing /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath2/Arm_no_backend.so'
385 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath3
386 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5
387 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath5/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath5/
388 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6
389 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath6/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath6/
390 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath7
391 adb shell mkdir -p /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9
392 adb push -p ${WORKING_DIR}/armnn/build/src/backends/backendsCommon/test/backendsTestPath9/* /data/local/tmp/src/backends/backendsCommon/test/backendsTestPath9/
393 adb shell mkdir -p /data/local/tmp/src/backends/dynamic/reference
394 adb push -p ${WORKING_DIR}/armnn/build/src/backends/dynamic/reference/Arm_CpuRef_backend.so /data/local/tmp/src/backends/dynamic/reference/
395 if [[ $DYNAMIC_SAMPLE == 1 ]]; then
396 adb shell mkdir -p /data/local/tmp/dynamic/sample/
397 adb push -p ${WORKING_DIR}/armnn/src/dynamic/sample/build/libArm_SampleDynamic_backend.so /data/local/tmp/dynamic/sample/
398 fi
399 echo "+++ Running UnitTests"
400 adb shell LD_LIBRARY_PATH=/data/local/tmp:/vendor/lib64:/vendor/lib64/egl /data/local/tmp/UnitTests ; printf $?
401 if [[ $DELEGATE == 1 ]]; then
402 adb shell LD_LIBRARY_PATH=/data/local/tmp:/vendor/lib64:/vendor/lib64/egl /data/local/tmp/DelegateUnitTests ; printf $?
403 fi
404}
405
406# Cleanup any previous runs, setup clean directories
407echo "+++ Creating $WORKING_DIR directory"
408mkdir -p $WORKING_DIR
409AssertZeroExitCode "Creating $WORKING_DIR directory failed"
410
411GetAndroidNDK
412if [[ $? != 0 ]] ; then
413 echo "Downloading Android NDK failed"
414 exit 1
415fi
416GetAndBuildFlatbuffers
417if [[ $? != 0 ]] ; then
418 echo "Building Flatbuffers failed"
419 exit 1
420fi
421if [[ $(lsb_release -rs) == "18.04" ]]; then
422 # We know this is necessary for 18.04 builds.
423 GetAndBuildCmake319
424 CMAKE=$WORKING_DIR/cmake/install/bin/cmake
425fi
426GetArmNN
427if [[ $? != 0 ]] ; then
428 echo "Cloning Arm NN failed"
429 exit 1
430fi
431# Build TFLite if the Delegate or Parser is required
432if [[ $DELEGATE == 1 || $TFLITE_PARSER ]]; then
433 GetAndBuildTFLite
434fi
435if [[ $? != 0 ]] ; then
436 echo "Building tflite failed"
437 exit 1
438fi
439GetAndBuildComputeLibrary
440if [[ $? != 0 ]] ; then
441 echo "Building ComputeLibrary failed"
442 exit 1
443fi
444BuildArmNN
445if [[ $? != 0 ]] ; then
446 echo "Building Arm NN failed"
447 exit 1
448fi
449if [[ $DYNAMIC_SAMPLE == 1 ]]; then
450 BuildStandaloneDynamicBackend
451fi
452if [[ $PUSH_TO_BOARD == 1 ]]; then
453 PushBuildSourcesToBoard
454fi
455if [[ "$R_new" -eq 0 ]]; then
456 echo "Success!"
457else
458 echo "Failed to run UnitTests"
459 exit 1
460fi