IVGCVSW-8172 Add macOS support to build tool setup

  * Updates build rules for platform
  * Failing unit tests excluded (dynamic backends, profiling)
  * install-packages.sh generates manual setup information

Signed-off-by: Tracy Narine <tracy.narine@arm.com>
Change-Id: I2d3d434aa615a8796c0cb94cd5b9c35a5acfd148
diff --git a/build-tool/scripts/build-armnn.sh b/build-tool/scripts/build-armnn.sh
index 18e59e1..5bc8d69 100755
--- a/build-tool/scripts/build-armnn.sh
+++ b/build-tool/scripts/build-armnn.sh
@@ -17,12 +17,36 @@
 abs_btool_path=$(dirname "$abs_script_path")	# absolute path to build-tool directory
 abs_armnn_path=$(dirname "$abs_btool_path")	# absolute path to armnn directory
 
+# Figure out platform specific settings
+osname=$(uname)
+osgetopt=getopt
+os_darwin=0
+if [ "$osname" == "Darwin" ]; then
+  os_darwin=1
+  osgetoptsys="/opt/homebrew/opt/gnu-getopt/bin/getopt"
+  osgetopthome="$HOME/homebrew/opt/gnu-getopt/bin/getopt"
+  if [ -f "$osgetoptsys" ]; then
+    echo "gnu-getopt found at: $osgetoptsys"
+    osgetopt=$osgetoptsys
+  elif [ -f "$osgetopthome" ]; then
+    echo "gnu-getopt found at: $osgetopthome"
+    osgetopt=$osgetopthome
+  else
+    echo "Run $rel_path/install-packages.sh and follow the instructions to configure the environment for $osname"
+    exit 1
+  fi
+fi
+
 build_acl()
 {
   cd "$ACL_SRC"
 
   # $acl_scons_params are additional options provided by the user and will overwrite any previously defined args
-  local acl_params="neon=$flag_neon_backend opencl=$flag_cl_backend Werror=0 embed_kernels=1 examples=0 validation_tests=0 benchmark_tests=0 benchmark_examples=0 $acl_scons_params"
+  acl_extra=""
+  if [ "$os_darwin" -eq 1 ]; then
+    acl_extra="os=macos "
+  fi
+  local acl_params="$acl_extra neon=$flag_neon_backend opencl=$flag_cl_backend Werror=0 embed_kernels=1 examples=0 validation_tests=0 benchmark_tests=0 benchmark_examples=0 $acl_scons_params"
 
   if [ "$flag_debug" -eq 1 ]; then
     acl_params="$acl_params debug=1 asserts=1"
@@ -100,10 +124,16 @@
   local cmake_flags=""
   local compile_flags=""
   local android_cmake_args=""
+  local linker_cmake_args=""
+  local warn_flags=""
 
   case "$TARGET_ARCH" in
     "aarch64")
       compile_flags+="$AARCH64_COMPILER_FLAGS"
+      if [ "$os_darwin" -eq 1 ]; then
+        linker_cmake_args="-DCMAKE_SHARED_LINKER_FLAGS='-framework CoreFoundation -framework Foundation'"
+        warn_flags="-DCMAKE_CXX_FLAGS='-Wno-error=deprecated-declarations'"
+      fi
       ;;
     "android64")
       compile_flags+="$ANDROID64_COMPILER_FLAGS"
@@ -125,8 +155,17 @@
 
   echo -e "\n***** Building Arm NN for $TARGET_ARCH *****"
 
+  local flatbuffers_root="$FLATBUFFERS_BUILD_TARGET"
+  local protobuf_root="$PROTOBUF_BUILD_TARGET"
+  if [ "$os_darwin" -eq 1 ]; then
+    flatbuffers_root="$FLATBUFFERS_BUILD_HOST"
+    protobuf_root="$PROTOBUF_BUILD_HOST"
+  fi
+
   eval "$compile_flags" \
   cmake "$android_cmake_args" \
+        "$linker_cmake_args" \
+        "$warn_flags" \
         -DCMAKE_BUILD_TYPE="$build_type" \
         -DBUILD_CLASSIC_DELEGATE="$flag_tflite_classic_delegate" \
         -DBUILD_OPAQUE_DELEGATE="$flag_tflite_opaque_delegate" \
@@ -143,17 +182,21 @@
         -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" \
+        -DFLATBUFFERS_ROOT="$flatbuffers_root" \
         -DFLATC_DIR="$FLATBUFFERS_BUILD_HOST" \
         -DONNX_GENERATED_SOURCES="$ONNX_BUILD_TARGET" \
-        -DPROTOBUF_ROOT="$PROTOBUF_BUILD_TARGET" \
+        -DPROTOBUF_ROOT="$protobuf_root" \
         "$armnn_cmake_args" \
         "$ARMNN_SRC"
 
   make -j "$NUM_THREADS"
 
   # Copy protobuf library into Arm NN build directory, if ONNX Parser is enabled
-  if [ "$flag_onnx_parser" -eq 1 ]; then
+  if [ "$flag_onnx_parser" -eq 1 ] && [ "$os_darwin" -eq 1 ]; then
+    cd "$ARMNN_BUILD_TARGET"
+    rm -f libprotobuf.dylib libprotobuf.23.dylib
+    cp "$PROTOBUF_LIBRARY_TARGET" .
+  elif [ "$flag_onnx_parser" -eq 1 ]; then
     cd "$ARMNN_BUILD_TARGET"
     rm -f libprotobuf.so libprotobuf.so.23 libprotobuf.so.23.0.0
     if [ "$TARGET_ARCH" != "android64" ]; then
@@ -228,7 +271,12 @@
   acl_tag="$(echo "$armnn_branch" | tr '\n' ' ' | sed -e 's/[^0-9]/ /g' -e 's/^ *//g' -e 's/ *$//g' | tr -s ' ' | sed 's/ /./g')"
 
   cd "$ACL_SRC"
-  git checkout v"$acl_tag"
+  if [ "$acl_tag" == "" ]; then
+    # Take the latest
+    git checkout main
+  else
+    git checkout v"$acl_tag"
+  fi
 
   echo -e "\n***** ACL Downloaded: $acl_tag *****"
 }
@@ -324,7 +372,7 @@
   exit 1
 fi
 
-args=$(getopt -ohx -l tflite-classic-delegate,tflite-opaque-delegate,tflite-parser,onnx-parser,all,target-arch:,neon-backend,cl-backend,ref-backend,clean,debug,armnn-cmake-args:,acl-scons-params:,num-threads:,symlink-armnn,help -n "$name"   -- "$@")
+args=$($osgetopt -ohx -l tflite-classic-delegate,tflite-opaque-delegate,tflite-parser,onnx-parser,all,target-arch:,neon-backend,cl-backend,ref-backend,clean,debug,armnn-cmake-args:,acl-scons-params:,num-threads:,symlink-armnn,help -n "$name"   -- "$@")
 eval set -- "$args"
 while [ $# -gt 0 ]; do
   if [ -n "${opt_prev:-}" ]; then
diff --git a/build-tool/scripts/common.sh b/build-tool/scripts/common.sh
index e68de99..0c34c7e 100755
--- a/build-tool/scripts/common.sh
+++ b/build-tool/scripts/common.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2024 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -34,9 +34,16 @@
 NATIVE_BUILD=0
 if [ "$TARGET_ARCH" == "$HOST_ARCH" ]; then
   NATIVE_BUILD=1
+elif [ "$TARGET_ARCH" == "aarch64" ]; then
+  if [ "$HOST_ARCH" == "arm64" ]; then
+    NATIVE_BUILD=1
+  fi
 fi
 
 AARCH64_COMPILER_FLAGS+="CC=/usr/bin/aarch64-linux-gnu-gcc CXX=/usr/bin/aarch64-linux-gnu-g++ "
+if [ "$HOST_ARCH" == "arm64" ]; then
+  AARCH64_COMPILER_FLAGS+="CC=/usr/bin/clang CXX=/usr/bin/clang++ "
+fi
 
 # NDK
 NDK_VERSION=26b
@@ -74,7 +81,11 @@
 PROTOBUF_BUILD_HOST="$PROTOBUF_BUILD_ROOT"/"$HOST_ARCH"_build
 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
+if [ "$osname" == "Darwin" ]; then
+  PROTOBUF_LIBRARY_TARGET="$PROTOBUF_BUILD_HOST"/lib/libprotobuf.dylib
+else
+  PROTOBUF_LIBRARY_TARGET="$PROTOBUF_BUILD_TARGET"/lib/libprotobuf.so.23.0.0
+fi
 PROTOBUF_ANDROID_LIB_TARGET="$PROTOBUF_BUILD_TARGET"/lib/libprotobuf.so
 
 # ONNX
diff --git a/build-tool/scripts/install-packages.sh b/build-tool/scripts/install-packages.sh
index 1a238b6..4a461a0 100755
--- a/build-tool/scripts/install-packages.sh
+++ b/build-tool/scripts/install-packages.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022, 2024 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -91,6 +91,25 @@
   rm -rf /var/lib/apt/lists/*
 }
 
+usage_darwin()
+{
+  cat <<EOF
+The $osname platform requires manual setup:
+0) Install the command line developer tools (at a minimum)
+1) Install homebrew and then run the following in a terminal:
+   1) brew install cmake
+   2) brew install scons
+   3) brew install gnu-getopt
+   4) brew install wget
+EOF
+}
+
+osname=$(uname)
+if [ "$osname" == "Darwin" ]; then
+  usage_darwin
+  exit 1
+fi
+
 name=$(basename "$0")
 
 if [ ! "$(id -u)" -eq 0 ]; then
diff --git a/build-tool/scripts/setup-armnn.sh b/build-tool/scripts/setup-armnn.sh
index 6b87d6f..a445356 100755
--- a/build-tool/scripts/setup-armnn.sh
+++ b/build-tool/scripts/setup-armnn.sh
@@ -13,6 +13,26 @@
 
 rel_path=$(dirname "$0") # relative path from where script is executed to script location
 
+# Figure out platform specific settings
+osname=$(uname)
+osgetopt=getopt
+os_darwin=0
+if [ "$osname" == "Darwin" ]; then
+  os_darwin=1
+  osgetoptsys="/opt/homebrew/opt/gnu-getopt/bin/getopt"
+  osgetopthome="$HOME/homebrew/opt/gnu-getopt/bin/getopt"
+  if [ -f "$osgetoptsys" ]; then
+    echo "gnu-getopt found at: $osgetoptsys"
+    osgetopt=$osgetoptsys
+  elif [ -f "$osgetopthome" ]; then
+    echo "gnu-getopt found at: $osgetopthome"
+    osgetopt=$osgetopthome
+  else
+    echo "Run $rel_path/install-packages.sh and follow the instructions to configure the environment for $osname"
+    exit 1
+  fi
+fi
+
 # Download an archive using wget and extract using tar
 # Takes three arguments:
 # 1. Name of dependency being downloaded e.g. Flatbuffers
@@ -138,6 +158,9 @@
     target_arch="$HOST_ARCH"
     mkdir -p "$FLATBUFFERS_BUILD_HOST"
     build_dir="$FLATBUFFERS_BUILD_HOST"
+    if [ "$os_darwin" -eq 1 ]; then
+      cmake_flags+="$AARCH64_COMPILER_FLAGS"
+    fi
   fi
 
   echo -e "\n***** Building flatbuffers for $target_arch *****"
@@ -184,6 +207,14 @@
   echo -e "\n***** TensorFlow downloaded *****"
 }
 
+build_tflite_cpuinfo()
+{
+  cd "$TFLITE_BUILD_TARGET"/cpuinfo
+  cmake .
+  make
+  cp *.a ../_deps/cpuinfo-build
+}
+
 build_tflite()
 {
   mkdir -p "$TFLITE_BUILD_TARGET"
@@ -194,9 +225,13 @@
 
   case "$TARGET_ARCH" in
     "aarch64")
+      cmake_system="Linux"
+      if [ "$os_darwin" -eq 1 ]; then
+        cmake_system="Darwin"
+      fi
       cmake_flags+="$AARCH64_COMPILER_FLAGS"
       target_arch_cmd="-DCMAKE_SYSTEM_PROCESSOR=aarch64 \
-                       -DCMAKE_SYSTEM_NAME=Linux "
+                       -DCMAKE_SYSTEM_NAME=$cmake_system "
 
       if [ "$NATIVE_BUILD" -eq 0 ]; then
         cmake_flags+="ARMCC_FLAGS='-funsafe-math-optimizations' "
@@ -226,6 +261,11 @@
         "$TFLITE_SRC"
   cmake --build . -j "$NUM_THREADS"
 
+  if [ "$os_darwin" -eq 1 ]; then
+    # Workaround undefined link error for this platform
+    build_tflite_cpuinfo
+  fi
+
   echo -e "\n***** Built TF Lite for $TARGET_ARCH *****"
 }
 
@@ -324,7 +364,7 @@
   exit 1
 fi
 
-args=$(getopt -ohx -l tflite-classic-delegate,tflite-opaque-delegate,tflite-parser,onnx-parser,all,target-arch:,num-threads:,help -n "$name"   -- "$@")
+args=$($osgetopt -ohx -l tflite-classic-delegate,tflite-opaque-delegate,tflite-parser,onnx-parser,all,target-arch:,num-threads:,help -n "$name"   -- "$@")
 eval set -- "$args"
 while [ $# -gt 0 ]; do
   if [ -n "${opt_prev:-}" ]; then
diff --git a/build-tool/scripts/validation.sh b/build-tool/scripts/validation.sh
index 1d7af76..a18908e 100755
--- a/build-tool/scripts/validation.sh
+++ b/build-tool/scripts/validation.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2024 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -16,12 +16,12 @@
 
 # Host and target architecture validation
 if [ "$target_arch" == "" ]; then
-  echo "$name: --target-arch is not set. Example usage: --target-arch=aarch64"
+  echo "$name: --target_arch is not set. Example usage: --target_arch=aarch64"
   exit 1
 fi
 
 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"
+  echo "$name: --target_arch is not valid. Valid options are: aarch64, android64, x86_64"
   exit 1
 fi