Skip to content

Commit

Permalink
PMNGIOS-675 [platform] Added scripts to build TensorFlowLiteC xcframe…
Browse files Browse the repository at this point in the history
…work
  • Loading branch information
acecilia authored Jun 3, 2021
1 parent 12d84aa commit 99cc470
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build_2_5_0:
Scripts/make_xcframework.sh build_2_5_0
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# TensorFlowLiteC binary

A repository to build and host prebuilt binaries of TensorFlowLiteC. Find the binaries in [the releases section of the repository](https://github.com/revolut-mobile/TensorFlowLiteC-binary/releases)
3 changes: 3 additions & 0 deletions TensorFlowLiteC.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"2.5.0": "https://github.com/revolut-mobile/TensorFlowLiteC-binary/releases/download/2.5.0/revolut-mobile/TensorFlowLiteC.xcframework.zip"
}
47 changes: 47 additions & 0 deletions patches/XNNPACK.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
diff --git a/BUILD.bazel b/BUILD.bazel
index dc228700..f6e6053a 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -7480,6 +7480,14 @@ config_setting(
},
)

+config_setting(
+ name = "ios_sim_arm64",
+ values = {
+ "apple_platform_type": "ios",
+ "cpu": "ios_sim_arm64",
+ },
+)
+
config_setting(
name = "ios_arm64e",
values = {
diff --git a/build_defs.bzl b/build_defs.bzl
index af543b93..ef99fc43 100644
--- a/build_defs.bzl
+++ b/build_defs.bzl
@@ -156,6 +156,7 @@ def xnnpack_cc_library(
":android_x86": x86_srcs,
":android_x86_64": x86_srcs,
":ios_armv7": aarch32_srcs,
+ ":ios_sim_arm64": aarch64_srcs,
":ios_arm64": aarch64_srcs,
":ios_arm64e": aarch64_srcs,
":ios_x86": x86_srcs,
@@ -191,6 +192,7 @@ def xnnpack_cc_library(
":android_x86": gcc_x86_copts,
":android_x86_64": gcc_x86_copts,
":ios_armv7": apple_aarch32_copts,
+ ":ios_sim_arm64": aarch64_copts,
":ios_arm64": aarch64_copts,
":ios_arm64e": aarch64_copts,
":ios_x86": gcc_x86_copts,
@@ -273,6 +275,7 @@ def xnnpack_aggregate_library(
":android_x86": x86_deps,
":android_x86_64": x86_deps,
":ios_armv7": aarch32_deps,
+ ":ios_sim_arm64": aarch64_deps,
":ios_arm64": aarch64_deps,
":ios_arm64e": aarch64_deps,
":ios_x86": x86_deps,
74 changes: 74 additions & 0 deletions patches/tensorflow.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
diff --git a/tensorflow/lite/kernels/internal/BUILD b/tensorflow/lite/kernels/internal/BUILD
index d1b0505de90..2432725beec 100644
--- a/tensorflow/lite/kernels/internal/BUILD
+++ b/tensorflow/lite/kernels/internal/BUILD
@@ -133,6 +133,13 @@ config_setting(
},
)

+config_setting(
+ name = "ios_sim_arm64",
+ values = {
+ "cpu": "ios_sim_arm64",
+ },
+)
+
config_setting(
name = "ios_arm64",
values = {
@@ -238,6 +245,7 @@ selects.config_setting_group(
":armhf",
":armv7a",
":ios_armv7",
+ ":ios_sim_arm64",
":ios_arm64",
":ios_arm64e",
":darwin_arm64",
diff --git a/tensorflow/workspace2.bzl b/tensorflow/workspace2.bzl
index efc50709b8f..c4dc2f65e2f 100644
--- a/tensorflow/workspace2.bzl
+++ b/tensorflow/workspace2.bzl
@@ -124,14 +124,9 @@ def _tf_repositories():
# b) get the sha256 hash of the commit by running:
# curl -L <url> | sha256sum
# and update the sha256 with the result.
- tf_http_archive(
+ native.local_repository(
name = "XNNPACK",
- sha256 = "95b778a920a1a79efdb11bf68dda9b4fd16779a1a0210438582e750f9bfb6351",
- strip_prefix = "XNNPACK-fb8d1f1b2bb2e32c141564528a39748c4631b453",
- urls = [
- "https://storage.googleapis.com/mirror.tensorflow.org/github.com/google/XNNPACK/archive/fb8d1f1b2bb2e32c141564528a39748c4631b453.zip",
- "https://github.com/google/XNNPACK/archive/fb8d1f1b2bb2e32c141564528a39748c4631b453.zip",
- ],
+ path = "../XNNPACK",
)

tf_http_archive(
diff --git a/third_party/cpuinfo/BUILD.bazel b/third_party/cpuinfo/BUILD.bazel
index 8e9239c0efb..72338d50ce1 100644
--- a/third_party/cpuinfo/BUILD.bazel
+++ b/third_party/cpuinfo/BUILD.bazel
@@ -115,6 +115,7 @@ cc_library(
":ios_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
":ios_x86": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
":ios_armv7": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
+ ":ios_sim_arm64": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
":ios_arm64": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
":ios_arm64e": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
":watchos_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
@@ -284,6 +285,14 @@ config_setting(
},
)

+config_setting(
+ name = "ios_sim_arm64",
+ values = {
+ "apple_platform_type": "ios",
+ "cpu": "ios_sim_arm64",
+ },
+)
+
config_setting(
name = "ios_arm64",
values = {
125 changes: 125 additions & 0 deletions scripts/make_xcframework.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/bin/zsh

set -euo pipefail

readonly WORK_DIR="$(pwd)"
readonly BUILD_DIR="${WORK_DIR}/build"
readonly TENSORFLOW_DIR="${BUILD_DIR}/tensorflow"
readonly XNNPACK_DIR="${BUILD_DIR}/XNNPACK"
readonly OUTPUT_DIR="${BUILD_DIR}/output"
readonly BAZEL_DIR="${BUILD_DIR}/bazel"
readonly PATCHED_BAZEL_BIN="${BAZEL_DIR}/bin/bazel"
readonly PATCHES_DIR="${WORK_DIR}/patches"
readonly TENSORFLOW_TARGET="TensorFlowLiteC_static_framework"

# Tensorflow does not support arm64 slices for the simulator yet. This patch is a workaround
# See: https://github.com/tensorflow/tensorflow/issues/47400
clone_and_patch_tensorflow() {
git clone --recurse-submodules --branch "v2.5.0" --depth 1 https://github.com/tensorflow/tensorflow.git "${TENSORFLOW_DIR}"
cd "${TENSORFLOW_DIR}"
git apply "${PATCHES_DIR}/tensorflow.patch"
}

# XNNPACK does not support arm64 slices for the simulator yet. This patch is a workaround
clone_and_patch_XNNPACK() {
git clone --recurse-submodules https://github.com/google/XNNPACK.git "${XNNPACK_DIR}"
cd "${XNNPACK_DIR}"
git checkout fb8d1f1b2bb2e32c141564528a39748c4631b453
git apply "${PATCHES_DIR}/XNNPACK.patch"
}

# Bazel does not support arm64 slices for the simulator yet. But there is a workaround
# See: https://github.com/bazelbuild/rules_apple/issues/980#issuecomment-738645357
download_patched_version_of_bazel() {
# Here we are using bazel 4.1.0 to build a patched version of bazel 3.7.2,
# so we can build the iOS arm64 simulator slice. We are patching version 3.7.2 because
# that is the version used by tensorflow 2.5.0
mkdir -p "${BAZEL_DIR}/4.1.0"
cd "${BAZEL_DIR}/4.1.0"
curl -O -L "https://github.com/bazelbuild/bazel/releases/download/4.1.0/bazel-4.1.0-darwin-x86_64"
mv bazel-4.1.0-darwin-x86_64 bazel
chmod +x bazel

cd "${BAZEL_DIR}"
git clone --branch "3.7.2" --depth 1 https://github.com/bazelbuild/bazel.git "3.7.2"
cd "3.7.2"
curl -O -L https://gist.githubusercontent.com/indragiek/e14162c0098d97ee976bceae9441f04d/raw/dba3a66a90d0a96d0dc6e236ab3fa1d41a2ce359/ios_sim_arm64.patch
git apply ios_sim_arm64.patch

# To install java11 on macos: brew install java11 https://mkyong.com/java/how-to-install-java-on-mac-osx/
# https://github.com/bazelbuild/bazel/issues/11399#issuecomment-628945756
# https://github.com/bazelbuild/rules_nodejs/issues/1301
export JAVA_HOME="/usr/local/opt/openjdk@11/libexec/openjdk.jdk/Contents/Home" && "${BAZEL_DIR}"/4.1.0/bazel build --incompatible_restrict_string_escapes=false -c opt //src:bazel
mkdir -p "$(dirname ${PATCHED_BAZEL_BIN})"
cp bazel-bin/src/bazel "${PATCHED_BAZEL_BIN}"
chmod +x "${PATCHED_BAZEL_BIN}"
}

build_xcframework() {
readonly SIM_ARM64_DIR="${BUILD_DIR}/iphonesimulator/ios_sim_arm64"
readonly SIM_x86_DIR="${BUILD_DIR}/iphonesimulator/ios_x86_64"

cd ${TENSORFLOW_DIR}

# See: https://github.com/tensorflow/tensorflow/issues/8527#issuecomment-289272898
export TF_CONFIGURE_IOS=1
# See: https://github.com/tensorflow/tensorflow/issues/8527#issuecomment-287923871
yes '' | ./configure || True

# Make arm64 simulator slice
${PATCHED_BAZEL_BIN} build --config=ios --cpu=ios_sim_arm64 -c opt tensorflow/lite/ios:${TENSORFLOW_TARGET}
mkdir -p "${SIM_ARM64_DIR}" && unzip bazel-bin/tensorflow/lite/ios/${TENSORFLOW_TARGET}.zip -d "${SIM_ARM64_DIR}"

# Make x86_64 simulator slice
bazelisk build --config=ios --cpu=ios_x86_64 -c opt tensorflow/lite/ios:${TENSORFLOW_TARGET}
mkdir -p "${SIM_x86_DIR}" && unzip bazel-bin/tensorflow/lite/ios/${TENSORFLOW_TARGET}.zip -d "${SIM_x86_DIR}"

# Merge both arm64 and x86_64 simulator slices into a fat framework
merge_framework_slices_into_fat_framework \
"TensorFlowLiteC" \
"${SIM_ARM64_DIR}/TensorFlowLiteC.framework" \
"${SIM_x86_DIR}/TensorFlowLiteC.framework" \
"${BUILD_DIR}/iphonesimulator"

# Make ios slices
bazelisk build --config=ios --ios_multi_cpus=armv7,arm64 -c opt tensorflow/lite/ios:${TENSORFLOW_TARGET}
unzip bazel-bin/tensorflow/lite/ios/${TENSORFLOW_TARGET}.zip -d "${BUILD_DIR}/iphoneos"

# Create the xcframework
xcrun xcodebuild -quiet -create-xcframework \
-framework "${BUILD_DIR}/iphoneos/TensorFlowLiteC.framework" \
-framework "${BUILD_DIR}/iphonesimulator/TensorFlowLiteC.framework" \
-output "${OUTPUT_DIR}/TensorFlowLiteC.xcframework"
}

# Merge two framework slices into one fat framework
# Based on https://gist.github.com/sundeepgupta/3ad9c6106e2cd9f51c68cf9f475191fa
merge_framework_slices_into_fat_framework() {
readonly NAME="${1}"
readonly FRAMEWORK_1="${2}"
readonly FRAMEWORK_2="${3}"
readonly DESTINATION="${4}"

# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
cp -R "${FRAMEWORK_1}" "${DESTINATION}/"

# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory
SIMULATOR_SWIFT_MODULES_DIR="${FRAMEWORK_2}/Modules/${NAME}.swiftmodule/."
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${DESTINATION}/${NAME}.framework/Modules/${NAME}.swiftmodule"
fi

# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${DESTINATION}/${NAME}.framework/${NAME}" "${FRAMEWORK_1}/${NAME}" "${FRAMEWORK_2}/${NAME}"
}

build_2_5_0() {
clone_and_patch_tensorflow
clone_and_patch_XNNPACK
download_patched_version_of_bazel
build_xcframework
}

rm -rf "${BUILD_DIR}"
mkdir "${BUILD_DIR}"
"$@"

0 comments on commit 99cc470

Please sign in to comment.