• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15# ==============================================================================
16
17set -e
18
19SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
20ROOT_DIR="$(cd "${SCRIPT_DIR}/../../../" && pwd)"
21TMP_DIR="tensorflow/lite/ios/tmp"
22
23function print_usage {
24  echo "Usage:"
25  echo "  $(basename ${BASH_SOURCE}) \\"
26  echo "    --input_models=model1.tflite,model2.tflite \\"
27  echo "    --target_archs=x86_64,armv7,arm64"
28  echo ""
29  echo "Where: "
30  echo "  --input_models: Supported TFLite models."
31  echo "  --target_archs: Supported arches included in the frameworks."
32  echo "      Default: x86_64,armv7,arm64. i386 architecture is currently not"
33  echo "      supported."
34  echo ""
35  exit 1
36}
37
38# generate_list_field takes two positional arguments:
39# - Name of the field in the build rule.
40# - Comma-separated list of values of this field.
41# The function returns a string represents that field in the BUILD file. Ex:
42# 'name = ["value1", "value2"],'
43function generate_list_field {
44  local name="$1"
45  local list_string="$2"
46  IFS=","
47  read -ra list <<< "$list_string"
48
49  local message=("$name=[")
50  for item in "${list[@]}"
51  do
52    message+=("\"$item\",")
53  done
54  message+=('],')
55  printf '%s' "${message[@]}"
56}
57
58function print_output {
59  echo "Output can be found here:"
60  for i in "$@"
61  do
62    # ls command returns failure if the file does not exist.
63    ls -1a ${ROOT_DIR}/$i
64  done
65}
66
67function generate_tflite_framework {
68  pushd ${TMP_DIR} > /dev/null
69  # Generate the BUILD file.
70  message=(
71    'load("@build_bazel_rules_apple//apple:ios.bzl", "ios_static_framework")'
72    'load("//tensorflow/lite:build_def.bzl", "tflite_custom_c_library")'
73    'load("//tensorflow/lite/ios:ios.bzl", "TFL_MINIMUM_OS_VERSION")'
74    'tflite_custom_c_library('
75    '    name = "custom_c_api",'
76    '    '"$(generate_list_field "models" "$MODEL_NAMES")"
77    ')'
78    'ios_static_framework('
79    '    name = "TensorFlowLiteC_framework",'
80    '    hdrs = ['
81    '        "//tensorflow/lite/c:c_api_types.h",'
82    '        "//tensorflow/lite/ios:common.h",'
83    '        "//tensorflow/lite/ios:c_api.h",'
84    '        "//tensorflow/lite/ios:xnnpack_delegate.h",'
85    '    ],'
86    '    bundle_name = "TensorFlowLiteC",'
87    '    minimum_os_version = TFL_MINIMUM_OS_VERSION,'
88    '    deps = ['
89    '        ":custom_c_api",'
90    '        "//tensorflow/lite/delegates/xnnpack:xnnpack_delegate",'
91    '    ],'
92    ')'
93  )
94  printf '%s\n' "${message[@]}" >> BUILD
95
96  # Build the framework package.
97  popd > /dev/null
98  bazel build -c opt --config=ios --ios_multi_cpus=${TARGET_ARCHS}  \
99    //${TMP_DIR}:TensorFlowLiteC_framework
100
101  OUT_FILES="${OUT_FILES} bazel-bin/${TMP_DIR}/TensorFlowLiteC_framework.zip"
102}
103
104function generate_flex_framework {
105  pushd ${TMP_DIR}
106  # Generating the BUILD file.
107  message=(
108    'load("//tensorflow/lite/delegates/flex:build_def.bzl", "tflite_flex_cc_library")'
109    'tflite_flex_cc_library('
110    '   name = "custom_flex_delegate",'
111    '    '"$(generate_list_field "models" "$MODEL_NAMES")"
112    ')'
113    'ios_static_framework('
114    '    name = "TensorFlowLiteSelectTfOps_framework",'
115    '    avoid_deps = ["//tensorflow/lite/c:common"],'
116    '    bundle_name = "TensorFlowLiteSelectTfOps",'
117    '    minimum_os_version = TFL_MINIMUM_OS_VERSION,'
118    '    deps = ['
119    '        ":custom_flex_delegate",'
120    '    ],'
121    ')'
122  )
123  printf '%s\n' "${message[@]}" >> BUILD
124  popd
125
126  # Build the framework.
127  bazel build -c opt --config=ios --ios_multi_cpus=${TARGET_ARCHS} \
128    //${TMP_DIR}:TensorFlowLiteSelectTfOps_framework
129
130  OUT_FILES="${OUT_FILES} bazel-bin/${TMP_DIR}/TensorFlowLiteSelectTfOps_framework.zip"
131}
132
133# Check command line flags.
134TARGET_ARCHS=x86_64,armv7,arm64
135
136if [ "$#" -gt 2 ]; then
137  echo "ERROR: Too many arguments."
138  print_usage
139fi
140
141for i in "$@"
142do
143case $i in
144    --input_models=*)
145      FLAG_MODELS="${i#*=}"
146      shift;;
147    --target_archs=*)
148      TARGET_ARCHS="${i#*=}"
149      shift;;
150    *)
151      echo "ERROR: Unrecognized argument: ${i}"
152      print_usage;;
153esac
154done
155
156cd $ROOT_DIR
157
158# Bazel v3.4 is required to build tensorflow python.
159if ! grep -q "3.4.0" ".bazelversion"; then
160  mv .bazelversion .bazelversion_old
161  echo "3.4.0" > .bazelversion
162fi
163
164# Check if users already run configure
165if [ ! -f "$ROOT_DIR/.tf_configure.bazelrc" ]; then
166  echo "ERROR: Please run ./configure first."
167  exit 1
168else
169  if ! grep -q "TF_CONFIGURE_IOS=\"1\"" "$ROOT_DIR/.tf_configure.bazelrc"; then
170    echo "ERROR: Please run ./configure with iOS config."
171    exit 1
172  fi
173fi
174
175# Prepare the tmp directory.
176rm -rf ${TMP_DIR} && mkdir -p ${TMP_DIR}
177
178# Copy models to tmp directory.
179MODEL_NAMES=""
180IFS=","
181read -ra MODEL_PATHS <<< "${FLAG_MODELS}"
182for model in "${MODEL_PATHS[@]}"
183do
184  cp ${model} ${TMP_DIR}
185  if [ -z "$MODEL_NAMES" ]; then
186    MODEL_NAMES="$(basename ${model})"
187  else
188    MODEL_NAMES="${MODEL_NAMES},$(basename ${model})"
189  fi
190done
191
192# Build the custom framework.
193generate_tflite_framework
194if [ -z ${FLAG_MODELS} ]; then
195  print_output ${OUT_FILES}
196  exit 0
197fi
198
199# Build flex framework if one of the models contain flex ops.
200bazel build -c opt --config=monolithic //tensorflow/lite/tools:list_flex_ops_no_kernel_main
201bazel-bin/tensorflow/lite/tools/list_flex_ops_no_kernel_main --graphs=${FLAG_MODELS} > ${TMP_DIR}/ops_list.txt
202if [[ `cat ${TMP_DIR}/ops_list.txt` != "[]" ]]; then
203  generate_flex_framework
204fi
205
206# List the output files.
207if [ ! -f ".bazelversion_old" ]; then
208  rm .bazelversion
209  mv -f .bazelversion_old .bazelversion
210fi
211rm -rf ${TMP_DIR}
212print_output ${OUT_FILES}
213