Selective build script for iOS
Usage: bash tensorflow/lite/experimental/ios/build_frameworks.sh \ --input_models=model1.tflite,model2.tflite \ --target_archs=armv7,arm64,x86_64 PiperOrigin-RevId: 348727288 Change-Id: I61559417880fa66265b5bbb286b0cab80f9f6387
This commit is contained in:
parent
9be3ad213b
commit
ccd1722630
212
tensorflow/lite/ios/build_frameworks.sh
Executable file
212
tensorflow/lite/ios/build_frameworks.sh
Executable file
@ -0,0 +1,212 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "${SCRIPT_DIR}/../../../" && pwd)"
|
||||
TMP_DIR="tensorflow/lite/ios/tmp"
|
||||
|
||||
function print_usage {
|
||||
echo "Usage:"
|
||||
echo " $(basename ${BASH_SOURCE}) \\"
|
||||
echo " --input_models=model1.tflite,model2.tflite \\"
|
||||
echo " --target_archs=x86_64,armv7,arm64"
|
||||
echo ""
|
||||
echo "Where: "
|
||||
echo " --input_models: Supported TFLite models."
|
||||
echo " --target_archs: Supported arches included in the frameworks."
|
||||
echo " Default: x86_64,armv7,arm64. i386 architecture is currently not"
|
||||
echo " supported."
|
||||
echo ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
# generate_list_field takes two positional arguments:
|
||||
# - Name of the field in the build rule.
|
||||
# - Comma-separated list of values of this field.
|
||||
# The function returns a string represents that field in the BUILD file. Ex:
|
||||
# 'name = ["value1", "value2"],'
|
||||
function generate_list_field {
|
||||
local name="$1"
|
||||
local list_string="$2"
|
||||
IFS=","
|
||||
read -ra list <<< "$list_string"
|
||||
|
||||
local message=("$name=[")
|
||||
for item in "${list[@]}"
|
||||
do
|
||||
message+=("\"$item\",")
|
||||
done
|
||||
message+=('],')
|
||||
printf '%s' "${message[@]}"
|
||||
}
|
||||
|
||||
function print_output {
|
||||
echo "Output can be found here:"
|
||||
for i in "$@"
|
||||
do
|
||||
# ls command returns failure if the file does not exist.
|
||||
ls -1a ${ROOT_DIR}/$i
|
||||
done
|
||||
}
|
||||
|
||||
function generate_tflite_framework {
|
||||
pushd ${TMP_DIR} > /dev/null
|
||||
# Generate the BUILD file.
|
||||
message=(
|
||||
'load("@build_bazel_rules_apple//apple:ios.bzl", "ios_static_framework")'
|
||||
'load("//tensorflow/lite:build_def.bzl", "tflite_custom_c_library")'
|
||||
'load("//tensorflow/lite/ios:ios.bzl", "TFL_MINIMUM_OS_VERSION")'
|
||||
'tflite_custom_c_library('
|
||||
' name = "custom_c_api",'
|
||||
' '"$(generate_list_field "models" "$MODEL_NAMES")"
|
||||
')'
|
||||
'ios_static_framework('
|
||||
' name = "TensorFlowLiteC_framework",'
|
||||
' hdrs = ['
|
||||
' "//tensorflow/lite/c:c_api_types.h",'
|
||||
' "//tensorflow/lite/ios:common.h",'
|
||||
' "//tensorflow/lite/ios:c_api.h",'
|
||||
' "//tensorflow/lite/ios:xnnpack_delegate.h",'
|
||||
' ],'
|
||||
' bundle_name = "TensorFlowLiteC",'
|
||||
' minimum_os_version = TFL_MINIMUM_OS_VERSION,'
|
||||
' deps = ['
|
||||
' ":custom_c_api",'
|
||||
' "//tensorflow/lite/delegates/xnnpack:xnnpack_delegate",'
|
||||
' ],'
|
||||
')'
|
||||
)
|
||||
printf '%s\n' "${message[@]}" >> BUILD
|
||||
|
||||
# Build the framework package.
|
||||
popd > /dev/null
|
||||
bazel build -c opt --config=ios --ios_multi_cpus=${TARGET_ARCHS} \
|
||||
//${TMP_DIR}:TensorFlowLiteC_framework
|
||||
|
||||
OUT_FILES="${OUT_FILES} bazel-bin/${TMP_DIR}/TensorFlowLiteC_framework.zip"
|
||||
}
|
||||
|
||||
function generate_flex_framework {
|
||||
pushd ${TMP_DIR}
|
||||
# Generating the BUILD file.
|
||||
message=(
|
||||
'load("//tensorflow/lite/delegates/flex:build_def.bzl", "tflite_flex_cc_library")'
|
||||
'tflite_flex_cc_library('
|
||||
' name = "custom_flex_delegate",'
|
||||
' '"$(generate_list_field "models" "$MODEL_NAMES")"
|
||||
')'
|
||||
'ios_static_framework('
|
||||
' name = "TensorFlowLiteSelectTfOps_framework",'
|
||||
' avoid_deps = ["//tensorflow/lite/c:common"],'
|
||||
' bundle_name = "TensorFlowLiteSelectTfOps",'
|
||||
' minimum_os_version = TFL_MINIMUM_OS_VERSION,'
|
||||
' deps = ['
|
||||
' ":custom_flex_delegate",'
|
||||
' ],'
|
||||
')'
|
||||
)
|
||||
printf '%s\n' "${message[@]}" >> BUILD
|
||||
popd
|
||||
|
||||
# Build the framework.
|
||||
bazel build -c opt --config=ios --ios_multi_cpus=${TARGET_ARCHS} \
|
||||
//${TMP_DIR}:TensorFlowLiteSelectTfOps_framework
|
||||
|
||||
OUT_FILES="${OUT_FILES} bazel-bin/${TMP_DIR}/TensorFlowLiteSelectTfOps_framework.zip"
|
||||
}
|
||||
|
||||
# Check command line flags.
|
||||
TARGET_ARCHS=x86_64,armv7,arm64
|
||||
|
||||
if [ "$#" -gt 2 ]; then
|
||||
echo "ERROR: Too many arguments."
|
||||
print_usage
|
||||
fi
|
||||
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
--input_models=*)
|
||||
FLAG_MODELS="${i#*=}"
|
||||
shift;;
|
||||
--target_archs=*)
|
||||
TARGET_ARCHS="${i#*=}"
|
||||
shift;;
|
||||
*)
|
||||
echo "ERROR: Unrecognized argument: ${i}"
|
||||
print_usage;;
|
||||
esac
|
||||
done
|
||||
|
||||
cd $ROOT_DIR
|
||||
|
||||
# Bazel v3.4 is required to build tensorflow python.
|
||||
if ! grep -q "3.4.0" ".bazelversion"; then
|
||||
mv .bazelversion .bazelversion_old
|
||||
echo "3.4.0" > .bazelversion
|
||||
fi
|
||||
|
||||
# Check if users already run configure
|
||||
if [ ! -f "$ROOT_DIR/.tf_configure.bazelrc" ]; then
|
||||
echo "ERROR: Please run ./configure first."
|
||||
exit 1
|
||||
else
|
||||
if ! grep -q "TF_CONFIGURE_IOS=\"1\"" "$ROOT_DIR/.tf_configure.bazelrc"; then
|
||||
echo "ERROR: Please run ./configure with iOS config."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prepare the tmp directory.
|
||||
rm -rf ${TMP_DIR} && mkdir -p ${TMP_DIR}
|
||||
|
||||
# Copy models to tmp directory.
|
||||
MODEL_NAMES=""
|
||||
IFS=","
|
||||
read -ra MODEL_PATHS <<< "${FLAG_MODELS}"
|
||||
for model in "${MODEL_PATHS[@]}"
|
||||
do
|
||||
cp ${model} ${TMP_DIR}
|
||||
if [ -z "$MODEL_NAMES" ]; then
|
||||
MODEL_NAMES="$(basename ${model})"
|
||||
else
|
||||
MODEL_NAMES="${MODEL_NAMES},$(basename ${model})"
|
||||
fi
|
||||
done
|
||||
|
||||
# Build the custom framework.
|
||||
generate_tflite_framework
|
||||
if [ -z ${FLAG_MODELS} ]; then
|
||||
print_output ${OUT_FILES}
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Build flex framework if one of the models contain flex ops.
|
||||
bazel build -c opt --config=monolithic //tensorflow/lite/tools:list_flex_ops_no_kernel_main
|
||||
bazel-bin/tensorflow/lite/tools/list_flex_ops_no_kernel_main --graphs=${FLAG_MODELS} > ${TMP_DIR}/ops_list.txt
|
||||
if [[ `cat ${TMP_DIR}/ops_list.txt` != "[]" ]]; then
|
||||
generate_flex_framework
|
||||
fi
|
||||
|
||||
# List the output files.
|
||||
if [ ! -f ".bazelversion_old" ]; then
|
||||
rm .bazelversion
|
||||
mv -f .bazelversion_old .bazelversion
|
||||
fi
|
||||
rm -rf ${TMP_DIR}
|
||||
print_output ${OUT_FILES}
|
Loading…
Reference in New Issue
Block a user