IVGCVSW-7202 Add Android NDK build targets to build-tool

* Changed build tool scripts to also target Android OS
* Updated Dockerfile to Ubuntu 20.04

Signed-off-by: John Mcloughlin <john.mcloughlin@arm.com>
Change-Id: I6905c205d8870e1628e4885743d9131cb1f11276
diff --git a/build-tool/docker/Dockerfile b/build-tool/docker/Dockerfile
index 2102054..a60a4d5 100644
--- a/build-tool/docker/Dockerfile
+++ b/build-tool/docker/Dockerfile
@@ -1,12 +1,12 @@
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
 # Default build type is 'production'. Use 'dev' if supplying custom Arm NN / ACL repos from host
 ARG BUILD_TYPE=production
 
-ARG UBUNTU_VERSION=18.04
+ARG UBUNTU_VERSION=20.04
 FROM ubuntu:${UBUNTU_VERSION} AS build-production
 
 ENV DEBIAN_FRONTEND noninteractive
diff --git a/build-tool/scripts/build-armnn.sh b/build-tool/scripts/build-armnn.sh
index 2751fc2..147aedf 100755
--- a/build-tool/scripts/build-armnn.sh
+++ b/build-tool/scripts/build-armnn.sh
@@ -42,6 +42,11 @@
       acl_arch="arch=arm64-v8a"
       ;;
 
+    "android64")
+      compile_flags+="$AARCH64_COMPILER_FLAGS"
+      acl_arch="arch=arm64-v8a"
+      ;;
+
     "x86_64")
       acl_arch="arch=x86_64"
       ;;
@@ -56,13 +61,23 @@
 
   mkdir -p "$ACL_BUILD_TARGET"
 
-  eval "$compile_flags" \
-  scons "$native_flag" \
+  if [ "$TARGET_ARCH" == "android64" ]; then
+    eval "$compile_flags" \
+    scons toolchain_prefix=llvm- \
+      compiler_prefix=aarch64-linux-android$ANDROID_API_VERSION- \
+      "$acl_arch" \
+      "$acl_params" \
+      "$extra_cxx_flags" \
+      os=android -j "$NUM_THREADS"
+  else
+    eval "$compile_flags" \
+    scons "$native_flag" \
         "$acl_arch" \
         "$acl_params" \
         build_dir="$ACL_BUILD_TARGET" \
         "$extra_cxx_flags" \
         -j "$NUM_THREADS"
+  fi
 
   echo -e "\n***** Built ACL for $TARGET_ARCH *****"
 
@@ -79,12 +94,25 @@
     build_type="Debug"
   fi
 
+  local cmake_flags=""
   local compile_flags=""
+  local android_cmake_args=""
 
   case "$TARGET_ARCH" in
     "aarch64")
       compile_flags+="$AARCH64_COMPILER_FLAGS"
       ;;
+    "android64")
+      compile_flags+="$ANDROID64_COMPILER_FLAGS"
+      cmake_flags+="CXXFLAGS='-fPIE -fPIC'"
+      android_cmake_args+="-DCMAKE_ANDROID_NDK=$NDK_SRC \
+                           -DNDK_VERSION=r$NDK_VERSION \
+                           -DCMAKE_SYSTEM_NAME=Android \
+                           -DCMAKE_SYSTEM_VERSION=$ANDROID_API_VERSION \
+                           -DCMAKE_ANDROID_ARCH_ABI=$ANDROID_ARM_ARCH \
+                           -DCMAKE_SYSROOT=$ANDROID64_x86_TOOLCHAIN/sysroot \
+                           -DCMAKE_EXE_LINKER_FLAGS='-pie -llog'"
+    ;;
   esac
 
   if [ "$flag_clean" -eq 1 ]; then
@@ -95,7 +123,8 @@
   echo -e "\n***** Building Arm NN for $TARGET_ARCH *****"
 
   eval "$compile_flags" \
-  cmake -DCMAKE_BUILD_TYPE="$build_type" \
+  cmake "$android_cmake_args" \
+        -DCMAKE_BUILD_TYPE="$build_type" \
         -DBUILD_CLASSIC_DELEGATE="$flag_tflite_classic_delegate" \
         -DBUILD_OPAQUE_DELEGATE="$flag_tflite_opaque_delegate" \
         -DBUILD_TF_LITE_PARSER="$flag_tflite_parser" \
@@ -107,14 +136,14 @@
         -DARMCOMPUTE_ROOT="$ACL_SRC" \
         -DARMCOMPUTE_BUILD_DIR="$ACL_BUILD_TARGET" \
         -DTENSORFLOW_ROOT="$TENSORFLOW_SRC" \
-        -DTF_LITE_SCHEMA_INCLUDE_PATH="$TFLITE_BUILD_ROOT" \
+        -DTFLITE_ROOT_DIR="$TFLITE_SRC" \
+        -DTF_LITE_GENERATED_PATH="$TFLITE_SRC"/schema \
+        -DTF_LITE_SCHEMA_INCLUDE_PATH="$TFLITE_SRC"/schema \
         -DTFLITE_LIB_ROOT="$TFLITE_BUILD_TARGET" \
         -DFLATBUFFERS_ROOT="$FLATBUFFERS_BUILD_TARGET" \
         -DFLATC_DIR="$FLATBUFFERS_BUILD_HOST" \
         -DONNX_GENERATED_SOURCES="$ONNX_BUILD_TARGET" \
-        -DPROTOBUF_ROOT="$PROTOBUF_BUILD_HOST" \
-        -DPROTOBUF_LIBRARY_DEBUG="$PROTOBUF_LIBRARY_TARGET" \
-        -DPROTOBUF_LIBRARY_RELEASE="$PROTOBUF_LIBRARY_TARGET" \
+        -DPROTOBUF_ROOT="$PROTOBUF_BUILD_TARGET" \
         "$armnn_cmake_args" \
         "$ARMNN_SRC"
 
@@ -124,9 +153,13 @@
   if [ "$flag_onnx_parser" -eq 1 ]; then
     cd "$ARMNN_BUILD_TARGET"
     rm -f libprotobuf.so libprotobuf.so.23 libprotobuf.so.23.0.0
-    cp "$PROTOBUF_LIBRARY_TARGET" .
-    ln -s libprotobuf.so.23.0.0 ./libprotobuf.so.23
-    ln -s libprotobuf.so.23.0.0 ./libprotobuf.so
+    if [ "$TARGET_ARCH" != "android64" ]; then
+      cp "$PROTOBUF_LIBRARY_TARGET" .
+      ln -s libprotobuf.so.23.0.0 ./libprotobuf.so.23
+      ln -s libprotobuf.so.23.0.0 ./libprotobuf.so
+    else
+      cp "$PROTOBUF_ANDROID_LIB_TARGET" .
+    fi
   fi
 
   # Copy Arm NN include directory into build output
@@ -205,7 +238,7 @@
     build the Arm NN ONNX parser component
   --all
     build all Arm NN components listed above
-  --target-arch=[aarch64|x86_64]
+  --target-arch=[aarch64|android64|x86_64]
     specify a target architecture (mandatory)
   --neon-backend
     build Arm NN with the NEON backend (CPU acceleration from ACL)
diff --git a/build-tool/scripts/common.sh b/build-tool/scripts/common.sh
index 6c1ce8a..421dc3d 100755
--- a/build-tool/scripts/common.sh
+++ b/build-tool/scripts/common.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -38,6 +38,17 @@
 
 AARCH64_COMPILER_FLAGS+="CC=/usr/bin/aarch64-linux-gnu-gcc CXX=/usr/bin/aarch64-linux-gnu-g++ "
 
+# NDK
+NDK_VERSION=25
+NDK_SRC="$SOURCE_DIR"/android-ndk-r"$NDK_VERSION"
+
+# ANDROID
+ANDROID_API_VERSION=30
+ANDROID_ARM_ARCH="arm64-v8a"
+ANDROID64_x86_TOOLCHAIN+="$NDK_SRC/toolchains/llvm/prebuilt/linux-x86_64"
+ANDROID64_COMPILER_FLAGS+="CC="$ANDROID64_x86_TOOLCHAIN"/bin/aarch64-linux-android"$ANDROID_API_VERSION"-clang \
+                           CXX="$ANDROID64_x86_TOOLCHAIN"/bin/aarch64-linux-android"$ANDROID_API_VERSION"-clang++ "
+
 # Flatbuffers
 FLATBUFFERS_VERSION=2.0.6
 FLATBUFFERS_SRC="$SOURCE_DIR"/flatbuffers-"$FLATBUFFERS_VERSION"
@@ -64,6 +75,7 @@
 PROTOCOL_COMPILER_HOST="$PROTOBUF_BUILD_HOST"/bin/protoc
 PROTOBUF_BUILD_TARGET="$PROTOBUF_BUILD_ROOT"/"$TARGET_ARCH"_build
 PROTOBUF_LIBRARY_TARGET="$PROTOBUF_BUILD_TARGET"/lib/libprotobuf.so.23.0.0
+PROTOBUF_ANDROID_LIB_TARGET="$PROTOBUF_BUILD_TARGET"/lib/libprotobuf.so
 
 # ONNX
 ONNX_VERSION=1.6.0
diff --git a/build-tool/scripts/setup-armnn.sh b/build-tool/scripts/setup-armnn.sh
index 156bb2f..db2ef2a 100755
--- a/build-tool/scripts/setup-armnn.sh
+++ b/build-tool/scripts/setup-armnn.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -34,6 +34,18 @@
   echo -e "\n***** $1 downloaded *****"
 }
 
+download_androidndk()
+{
+  cd "$SOURCE_DIR"
+  echo -e "\n***** Downloading Android NDK *****\n"
+  wget https://dl.google.com/android/repository/android-ndk-r25-linux.zip
+  echo -e "\n***** Extracting archive *****"
+  unzip android-ndk-r25-linux.zip
+  echo -e "\n***** Removing archive *****"
+  rm android-ndk-r25-linux.zip
+  echo -e "\n***** Android NDK downloaded *****"
+}
+
 download_protobuf()
 {
   download_and_extract \
@@ -57,6 +69,10 @@
       cmake_flags+="$AARCH64_COMPILER_FLAGS"
       additional_cmds+="--host=aarch64-linux "
     fi
+    if [ "$TARGET_ARCH" == "android64" ]; then
+      additional_cmds+="--host=aarch64-linux-android "
+      cmake_flags+="$ANDROID64_COMPILER_FLAGS"
+    fi
   else
     target_arch="$HOST_ARCH"
     mkdir -p "$PROTOBUF_BUILD_HOST"
@@ -70,9 +86,26 @@
   # Cleanup any previous cmake files, except actual builds which we keep
   find . -mindepth 1 -name "*_build" -prune -o -exec rm -rf {} +
 
-  eval "$cmake_flags" \
-  "$PROTOBUF_SRC"/configure --prefix="$build_dir" "$additional_cmds"
-  make install -j "$NUM_THREADS"
+  if [ "$native_build" -eq 0 ] && [ "$TARGET_ARCH" == "android64" ]; then
+      eval "$cmake_flags"
+      cmake -DCMAKE_ANDROID_NDK="$NDK_SRC"  \
+            -DCMAKE_SYSTEM_NAME=Android \
+            -DCMAKE_SYSTEM_VERSION="$ANDROID_API_VERSION" \
+            -DCMAKE_ANDROID_ARCH_ABI="$ANDROID_ARM_ARCH" \
+            -DCMAKE_CXX_FLAGS=--std=c++14 \
+            -Dprotobuf_BUILD_TESTS=OFF \
+            -Dprotobuf_BUILD_SHARED_LIBS=ON \
+            -Dprotobuf_WITH_ZLIB=OFF \
+            -DCMAKE_BUILD_TYPE=Release \
+            $PROTOBUF_SRC/cmake/
+      make libprotobuf -j "$NUM_THREADS"
+      cmake -DCMAKE_INSTALL_PREFIX=$PROTOBUF_BUILD_TARGET -DCOMPONENT=libprotobuf -P cmake_install.cmake
+      cmake -DCMAKE_INSTALL_PREFIX=$PROTOBUF_BUILD_TARGET -DCOMPONENT=protobuf-headers -P cmake_install.cmake
+  else
+      eval "$cmake_flags" \
+      "$PROTOBUF_SRC"/configure --prefix="$build_dir" "$additional_cmds"
+      make install -j "$NUM_THREADS"
+  fi
 
   echo -e "\n***** Protobuf built for $target_arch ***** "
 }
@@ -95,7 +128,7 @@
 
   if [ "$native_build" -eq 0 ]; then
     mkdir -p "$FLATBUFFERS_BUILD_TARGET"
-    if [ "$TARGET_ARCH" == "aarch64" ]; then
+    if [ "$TARGET_ARCH" == "aarch64" ] || [ "$TARGET_ARCH" == "android64" ]; then
       cmake_flags+="$AARCH64_COMPILER_FLAGS"
     fi
   else
@@ -112,11 +145,25 @@
   # Cleanup any previous cmake files, except actual builds which we keep
   find . -mindepth 1 -name "*_build" -prune -o -exec rm -rf {} +
 
-  eval "$cmake_flags" \
-  cmake -DFLATBUFFERS_BUILD_FLATC="$native_build" \
-        -DCMAKE_INSTALL_PREFIX:PATH="$build_dir" \
-        -DFLATBUFFERS_BUILD_TESTS=0 \
-	      "$FLATBUFFERS_SRC"
+  if [ "$native_build" -eq 0 ] && [ "$TARGET_ARCH" == "android64" ]; then
+    eval "$cmake_flags" \
+    cmake -DCMAKE_ANDROID_NDK="$NDK_SRC" \
+          -DCMAKE_SYSTEM_NAME=Android \
+          -DCMAKE_SYSTEM_VERSION="$ANDROID_API_VERSION" \
+          -DCMAKE_ANDROID_ARCH_ABI="$ANDROID_ARM_ARCH" \
+          -DCMAKE_CXX_FLAGS=--std=c++14 \
+          -DFLATBUFFERS_BUILD_FLATC=0 \
+          -DCMAKE_INSTALL_PREFIX:PATH="$build_dir" \
+          -DCMAKE_BUILD_TYPE=Release \
+          -DFLATBUFFERS_BUILD_TESTS=0 \
+          "$FLATBUFFERS_SRC"
+  else
+    eval "$cmake_flags" \
+    cmake -DFLATBUFFERS_BUILD_FLATC="$native_build" \
+          -DCMAKE_INSTALL_PREFIX:PATH="$build_dir" \
+          -DFLATBUFFERS_BUILD_TESTS=0 \
+          "$FLATBUFFERS_SRC"
+  fi
   make all install -j "$NUM_THREADS"
 
   echo -e "\n***** Built flatbuffers for $target_arch *****"
@@ -152,6 +199,14 @@
         cmake_flags+="ARMCC_FLAGS='-funsafe-math-optimizations' "
       fi
       ;;
+    "android64")
+      cmake_flags+="$AARCH64_COMPILER_FLAGS"
+      if [ "$NATIVE_BUILD" -eq 0 ]; then
+        target_arch_cmd="-DCMAKE_TOOLCHAIN_FILE=$NDK_SRC/build/cmake/android.toolchain.cmake \
+                         -DANDROID_ABI=$ANDROID_ARM_ARCH \
+                         -DANDROID_PLATFORM=$ANDROID_API_VERSION"
+      fi
+      ;;
   esac
 
   echo -e "\n***** Building TF Lite for $TARGET_ARCH *****"
@@ -225,7 +280,7 @@
     setup dependencies for the Arm NN ONNX parser
   --all
     setup dependencies for all Arm NN components listed above
-  --target-arch=[aarch64|x86_64]
+  --target-arch=[aarch64|android64|x86_64]
     specify a target architecture (mandatory)
   --num-threads=<INTEGER>
     specify number of threads/cores to build dependencies with (optional: defaults to number of online CPU cores on host)
@@ -358,6 +413,10 @@
 mkdir -p "$SOURCE_DIR"
 mkdir -p "$BUILD_DIR"
 
+if [ "$TARGET_ARCH" == "android64" ]; then
+  download_androidndk
+fi
+
 if [ "$flag_tflite_classic_delegate" -eq 1 ] || [ "$flag_tflite_opaque_delegate" -eq 1 ] ||  [ "$flag_tflite_parser" -eq 1 ]; then
   download_flatbuffers
 
diff --git a/build-tool/scripts/validation.sh b/build-tool/scripts/validation.sh
index 48b2372..1d7af76 100755
--- a/build-tool/scripts/validation.sh
+++ b/build-tool/scripts/validation.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -20,8 +20,8 @@
   exit 1
 fi
 
-if [ "$target_arch" != "aarch64" ] && [ "$target_arch" != "x86_64" ]; then
-  echo "$name: --target-arch is not valid. Valid options are: aarch64, x86_64"
+if [ "$target_arch" != "aarch64" ] && [ "$target_arch" != "android64" ] && [ "$target_arch" != "x86_64" ]; then
+  echo "$name: --target-arch is not valid. Valid options are: aarch64, android64, x86_64"
   exit 1
 fi
 
@@ -32,6 +32,13 @@
   fi
 fi
 
+if [ "$target_arch" == "android64" ]; then
+  if [ "$HOST_ARCH" != "x86_64" ]; then
+    echo "$name: --target_arch android64 is only supported when host is x86_64"
+    exit 1
+  fi
+fi
+
 # Validation of chosen Arm NN dependencies
 if [ "$flag_tflite_classic_delegate" -eq 0 ] && [ "$flag_tflite_opaque_delegate" -eq 0 ] && [ "$flag_tflite_parser" -eq 0 ] && [ "$flag_onnx_parser" -eq 0 ]; then
   echo "$name: at least one of flags --tflite-classic-delegate, --tflite-opaque-delegate, --tflite-parser or --onnx-parser must be set (or --all)."