diff --git a/.bazelrc b/.bazelrc index 724dd23fd..44bc3d0a1 100644 --- a/.bazelrc +++ b/.bazelrc @@ -87,6 +87,9 @@ build:ios_fat --config=ios build:ios_fat --ios_multi_cpus=armv7,arm64 build:ios_fat --watchos_cpus=armv7k +build:ios_sim_fat --config=ios +build:ios_sim_fat --ios_multi_cpus=x86_64,sim_arm64 + build:darwin_x86_64 --apple_platform_type=macos build:darwin_x86_64 --macos_minimum_os=10.12 build:darwin_x86_64 --cpu=darwin_x86_64 diff --git a/mediapipe/framework/tool/ios.bzl b/mediapipe/framework/tool/ios.bzl new file mode 100644 index 000000000..c97b092e1 --- /dev/null +++ b/mediapipe/framework/tool/ios.bzl @@ -0,0 +1,53 @@ +# Copyright 2023 The MediaPipe Authors. +# +# 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. + +"""MediaPipe Task Library Helper Rules for iOS""" + +MPP_TASK_MINIMUM_OS_VERSION = "11.0" + +# When the static framework is built with bazel, the all header files are moved +# to the "Headers" directory with no header path prefixes. This auxiliary rule +# is used for stripping the path prefix to the C/iOS API header files included by +# other C/iOS API header files. +# In case of C header files, includes start with a keyword of "#include'. +# Imports in iOS header files start with a keyword of '#import'. +def strip_api_include_path_prefix(name, hdr_labels, prefix = ""): + """Create modified header files with the import path stripped out. + + Args: + name: The name to be used as a prefix to the generated genrules. + hdr_labels: List of header labels to strip out the include path. Each + label must end with a colon followed by the header file name. + prefix: Optional prefix path to prepend to the header inclusion path. + """ + for hdr_label in hdr_labels: + hdr_filename = hdr_label.split(":")[-1] + + # The last path component of iOS header files is sources/some_file.h + # Hence it wiill contain a '/'. So the string can be split at '/' to get + # the header file name. + if "/" in hdr_filename: + hdr_filename = hdr_filename.split("/")[-1] + + hdr_basename = hdr_filename.split(".")[0] + native.genrule( + name = "{}_{}".format(name, hdr_basename), + srcs = [hdr_label], + outs = [hdr_filename], + cmd = """ + sed 's|#\\([a-z]*\\) ".*/\\([^/]\\{{1,\\}}\\.h\\)"|#\\1 "{}\\2"|'\ + "$(location {})"\ + > "$@" + """.format(prefix, hdr_label), + ) diff --git a/mediapipe/tasks/ios/BUILD b/mediapipe/tasks/ios/BUILD new file mode 100644 index 000000000..c839acd84 --- /dev/null +++ b/mediapipe/tasks/ios/BUILD @@ -0,0 +1,213 @@ +# Copyright 2023 The MediaPipe 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. + +load( + "//mediapipe/framework/tool:ios.bzl", + "MPP_TASK_MINIMUM_OS_VERSION", + "strip_api_include_path_prefix", +) +load("@build_bazel_rules_apple//apple:apple.bzl", "apple_static_xcframework") +load("@build_bazel_rules_apple//apple:apple_static_library.bzl", "apple_static_library") + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +# List of targets to be added in avoid_deps of ":MediaPipeTasksVision_framework" +# and ":MediaPipeTasksText_framework". +# The transitive closure of the following targets are used for building the +# frameworks but are avoided from the framework binaries to avoid duplicate symbols +# error when included in an xcode project: +# 1. iOS classes shared amongst the various vision and text tasks. These classes +# will be built with ":MediaPipeTasksCommon_framework" +# 2. Task graphs. These will be built with ":MediaPipeTaskGraphs_library". +# 3. gpu targets which will be built with the ":MediaPipeTaskGraphs_library". +OBJC_COMMON_DEPS = [ + "//mediapipe/tasks/ios/core:MPPBaseOptions", + "//mediapipe/tasks/ios/core:MPPTaskInfo", + "//mediapipe/tasks/ios/core:MPPTaskOptions", + "//mediapipe/tasks/ios/core:MPPTaskResult", + "//mediapipe/tasks/ios/core:MPPTaskRunner", + "//mediapipe/tasks/ios/components/containers:MPPClassificationResult", + "//mediapipe/tasks/ios/components/containers:MPPCategory", + "//mediapipe/tasks/ios/common/utils:MPPCommonUtils", + "//mediapipe/tasks/cc/vision/image_classifier:image_classifier_graph", + "//mediapipe/tasks/cc/vision/object_detector:object_detector_graph", + "//mediapipe/tasks/cc/text/text_classifier:text_classifier_graph", + "//mediapipe/tasks/cc/text/text_embedder:text_embedder_graph", + "//mediapipe/gpu:metal_shared_resources", +] + +strip_api_include_path_prefix( + name = "strip_api_include_path", + hdr_labels = [ + "//mediapipe/tasks/ios/common:sources/MPPCommon.h", + "//mediapipe/tasks/ios/components/containers:sources/MPPCategory.h", + "//mediapipe/tasks/ios/components/containers:sources/MPPClassificationResult.h", + "//mediapipe/tasks/ios/components/containers:sources/MPPEmbedding.h", + "//mediapipe/tasks/ios/components/containers:sources/MPPEmbeddingResult.h", + "//mediapipe/tasks/ios/components/containers:sources/MPPDetection.h", + "//mediapipe/tasks/ios/core:sources/MPPBaseOptions.h", + "//mediapipe/tasks/ios/core:sources/MPPTaskOptions.h", + "//mediapipe/tasks/ios/core:sources/MPPTaskResult.h", + "//mediapipe/tasks/ios/text/text_classifier:sources/MPPTextClassifier.h", + "//mediapipe/tasks/ios/text/text_classifier:sources/MPPTextClassifierOptions.h", + "//mediapipe/tasks/ios/text/text_classifier:sources/MPPTextClassifierResult.h", + "//mediapipe/tasks/ios/text/text_embedder:sources/MPPTextEmbedder.h", + "//mediapipe/tasks/ios/text/text_embedder:sources/MPPTextEmbedderOptions.h", + "//mediapipe/tasks/ios/text/text_embedder:sources/MPPTextEmbedderResult.h", + "//mediapipe/tasks/ios/vision/core:sources/MPPRunningMode.h", + "//mediapipe/tasks/ios/vision/core:sources/MPPImage.h", + "//mediapipe/tasks/ios/vision/image_classifier:sources/MPPImageClassifier.h", + "//mediapipe/tasks/ios/vision/image_classifier:sources/MPPImageClassifierOptions.h", + "//mediapipe/tasks/ios/vision/image_classifier:sources/MPPImageClassifierResult.h", + "//mediapipe/tasks/ios/vision/object_detector:sources/MPPObjectDetector.h", + "//mediapipe/tasks/ios/vision/object_detector:sources/MPPObjectDetectorOptions.h", + "//mediapipe/tasks/ios/vision/object_detector:sources/MPPObjectDetectionResult.h", + ], +) + +apple_static_xcframework( + name = "MediaPipeTasksText_framework", + # Avoid dependencies of ":MediaPipeTasksCommon_framework" and + # ":MediaPipeTaskGraphs_library in order to prevent duplicate symbols error + # when the frameworks are imported in iOS projects. + avoid_deps = OBJC_COMMON_DEPS, + bundle_name = "MediaPipeTasksText", + ios = { + "simulator": [ + "arm64", + "x86_64", + ], + "device": ["arm64"], + }, + minimum_os_versions = { + "ios": MPP_TASK_MINIMUM_OS_VERSION, + }, + public_hdrs = [ + ":MPPBaseOptions.h", + ":MPPCategory.h", + ":MPPClassificationResult.h", + ":MPPEmbedding.h", + ":MPPEmbeddingResult.h", + ":MPPCommon.h", + ":MPPTaskOptions.h", + ":MPPTaskResult.h", + ":MPPTextClassifier.h", + ":MPPTextClassifierOptions.h", + ":MPPTextClassifierResult.h", + ":MPPTextEmbedder.h", + ":MPPTextEmbedderOptions.h", + ":MPPTextEmbedderResult.h", + ], + deps = [ + "//mediapipe/tasks/ios/text/text_classifier:MPPTextClassifier", + "//mediapipe/tasks/ios/text/text_embedder:MPPTextEmbedder", + ], +) + +apple_static_xcframework( + name = "MediaPipeTasksVision_framework", + # Avoids dependencies of ":MediaPipeTasksCommon_framework" and + # ":MediaPipeTaskGraphs_library in order to prevent duplicate symbols error + # when the frameworks are imported in iOS projects. + # Also avoids opencv since it will be built with + # ":MediaPipeTaskGraphs_library". + avoid_deps = OBJC_COMMON_DEPS + [ + "@ios_opencv//:OpencvFramework", + ], + bundle_name = "MediaPipeTasksVision", + ios = { + "simulator": [ + "arm64", + "x86_64", + ], + "device": ["arm64"], + }, + minimum_os_versions = { + "ios": MPP_TASK_MINIMUM_OS_VERSION, + }, + public_hdrs = [ + ":MPPBaseOptions.h", + ":MPPCategory.h", + ":MPPClassificationResult.h", + ":MPPDetection.h", + ":MPPCommon.h", + ":MPPTaskOptions.h", + ":MPPTaskResult.h", + ":MPPImage.h", + ":MPPRunningMode.h", + ":MPPImageClassifier.h", + ":MPPImageClassifierOptions.h", + ":MPPImageClassifierResult.h", + ":MPPObjectDetector.h", + ":MPPObjectDetectorOptions.h", + ":MPPObjectDetectionResult.h", + ], + deps = [ + "//mediapipe/tasks/ios/vision/image_classifier:MPPImageClassifier", + "//mediapipe/tasks/ios/vision/object_detector:MPPObjectDetector", + ], +) + +apple_static_library( + name = "MediaPipeTaskGraphs_library", + # There is no way to turn off zlib dependency in custom opencv builds. + # Hence zlib is avoided to prevent duplicate symbols because of conflicts + # between opencv's zlib and "@zlib//:zlib" + avoid_deps = [ + "@zlib//:zlib", + ], + minimum_os_version = MPP_TASK_MINIMUM_OS_VERSION, + platform_type = "ios", + deps = [ + "//mediapipe/tasks/cc/text/text_classifier:text_classifier_graph", + "//mediapipe/tasks/cc/text/text_embedder:text_embedder_graph", + "//mediapipe/tasks/cc/vision/image_classifier:image_classifier_graph", + "//mediapipe/tasks/cc/vision/object_detector:object_detector_graph", + "@ios_opencv//:OpencvFramework", + "@org_tensorflow//third_party/icu/data:conversion_data", + ], +) + +apple_static_xcframework( + name = "MediaPipeTasksCommon_framework", + # avoids gpu targets since they will be built with + # ":MediaPipeTaskGraphs_library". Otherwise it will result in + # duplicate symbols error when the frameworks are imported in iOS. + avoid_deps = [ + "//mediapipe/gpu:metal_shared_resources", + ], + bundle_name = "MediaPipeTasksCommon", + ios = { + "simulator": [ + "arm64", + "x86_64", + ], + "device": ["arm64"], + }, + minimum_os_versions = { + "ios": MPP_TASK_MINIMUM_OS_VERSION, + }, + deps = [ + "//mediapipe/tasks/ios/common/utils:MPPCommonUtils", + "//mediapipe/tasks/ios/components/containers:MPPCategory", + "//mediapipe/tasks/ios/components/containers:MPPClassificationResult", + "//mediapipe/tasks/ios/core:MPPBaseOptions", + "//mediapipe/tasks/ios/core:MPPTaskInfo", + "//mediapipe/tasks/ios/core:MPPTaskOptions", + "//mediapipe/tasks/ios/core:MPPTaskResult", + "//mediapipe/tasks/ios/core:MPPTaskRunner", + ], +) diff --git a/mediapipe/tasks/ios/MediaPipeTasksCommon.podspec.template b/mediapipe/tasks/ios/MediaPipeTasksCommon.podspec.template new file mode 100644 index 000000000..de9a3fa26 --- /dev/null +++ b/mediapipe/tasks/ios/MediaPipeTasksCommon.podspec.template @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.name = 'MediaPipeTasksCommon' + s.version = '${MPP_BUILD_VERSION}' + s.authors = 'Google Inc.' + s.license = { :type => 'Apache',:file => "LICENSE" } + s.homepage = 'https://github.com/google/mediapipe' + s.source = { :http => '${MPP_DOWNLOAD_URL}' } + s.summary = 'MediaPipe Task Library - Text' + s.description = 'The Natural Language APIs of the MediaPipe Task Library' + + s.ios.deployment_target = '11.0' + + s.module_name = 'MediaPipeTasksCommon' + s.static_framework = true + s.user_target_xcconfig = { + 'OTHER_LDFLAGS[sdk=iphonesimulator*]' => '$(inherited) -force_load "${PODS_ROOT}/MediaPipeTasksCommon/frameworks/graph_libraries/libMediaPipeTasksCommon_simulator_graph.a"', + 'OTHER_LDFLAGS[sdk=iphoneos*]' => '$(inherited) -force_load "$(PODS_ROOT)/MediaPipeTasksCommon/frameworks/graph_libraries/libMediaPipeTasksCommon_device_graph.a"', + } + s.frameworks = 'Accelerate', 'CoreMedia', 'AssetsLibrary', 'CoreFoundation', 'CoreGraphics', 'CoreImage', 'QuartzCore', 'AVFoundation', 'CoreVideo' + s.preserve_paths ='frameworks/graph_libraries/*.a' + s.library = 'c++' + s.vendored_frameworks = 'frameworks/MediaPipeTasksCommon.xcframework' +end diff --git a/mediapipe/tasks/ios/MediaPipeTasksText.podspec.template b/mediapipe/tasks/ios/MediaPipeTasksText.podspec.template new file mode 100644 index 000000000..144d36f88 --- /dev/null +++ b/mediapipe/tasks/ios/MediaPipeTasksText.podspec.template @@ -0,0 +1,18 @@ +Pod::Spec.new do |s| + s.name = 'MediaPipeTasksText' + s.version = '${MPP_BUILD_VERSION}' + s.authors = 'Google Inc.' + s.license = { :type => 'Apache',:file => "LICENSE" } + s.homepage = 'https://github.com/google/mediapipe' + s.source = { :http => '${MPP_DOWNLOAD_URL}' } + s.summary = 'MediaPipe Task Library - Text' + s.description = 'The Natural Language APIs of the MediaPipe Task Library' + + s.ios.deployment_target = '11.0' + + s.module_name = 'MediaPipeTasksText' + s.static_framework = true + s.dependency 'MediaPipeTasksCommon' + s.library = 'c++' + s.vendored_frameworks = 'frameworks/MediaPipeTasksText.xcframework' +end diff --git a/mediapipe/tasks/ios/MediaPipeTasksVision.podspec.template b/mediapipe/tasks/ios/MediaPipeTasksVision.podspec.template new file mode 100644 index 000000000..373c1768b --- /dev/null +++ b/mediapipe/tasks/ios/MediaPipeTasksVision.podspec.template @@ -0,0 +1,18 @@ +Pod::Spec.new do |s| + s.name = 'MediaPipeTasksVision' + s.version = '${MPP_BUILD_VERSION}' + s.authors = 'Google Inc.' + s.license = { :type => 'Apache',:file => "LICENSE" } + s.homepage = 'https://github.com/google/mediapipe' + s.source = { :http => '${MPP_DOWNLOAD_URL}' } + s.summary = 'MediaPipe Task Library - Vision' + s.description = 'The Vision APIs of the MediaPipe Task Library' + + s.ios.deployment_target = '11.0' + + s.module_name = 'MediaPipeTasksVision' + s.static_framework = true + s.dependency 'MediaPipeTasksCommon' + s.library = 'c++' + s.vendored_frameworks = 'frameworks/MediaPipeTasksVision.xcframework' +end diff --git a/mediapipe/tasks/ios/build_ios_framework.sh b/mediapipe/tasks/ios/build_ios_framework.sh new file mode 100755 index 000000000..bb2fafc1f --- /dev/null +++ b/mediapipe/tasks/ios/build_ios_framework.sh @@ -0,0 +1,211 @@ +#!/usr/bin/env bash +# Copyright 2023 The MediaPipe 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 the following variables as appropriate. +# * BAZEL: path to bazel. defaults to the first one available in PATH +# * FRAMEWORK_NAME: name of the iOS framework to be built. Currently the +# * accepted values are MediaPipeTasksCommon, MediaPipeTasksText, MediaPipeTasksVision. +# * MPP_BUILD_VERSION: to specify the release version. defaults to 0.0.1-dev +# * IS_RELEASE_BUILD: set as true if this build should be a release build +# * ARCHIVE_FRAMEWORK: set as true if the framework should be archived +# * DEST_DIR: destination directory to which the framework will be copied. + +set -ex + +if [[ "$(uname)" != "Darwin" ]]; then + echo "This build script only works on macOS." + exit 1 +fi + +BAZEL="${BAZEL:-$(which bazel)}" +MPP_BUILD_VERSION=${MPP_BUILD_VERSION:-0.0.1-dev} +MPP_ROOT_DIR=$(git rev-parse --show-toplevel) +ARCHIVE_FRAMEWORK=${ARCHIVE_FRAMEWORK:-true} +IS_RELEASE_BUILD=${IS_RELEASE_BUILD:-false} +DEST_DIR=${DEST_DIR:-$HOME} + +echo "Destination" +echo "${DEST_DIR}" + +if [[ ! -x "${BAZEL}" ]]; then + echo "bazel executable is not found." + exit 1 +fi + +if [ -z ${FRAMEWORK_NAME+x} ]; then + echo "Name of the iOS framework, which is to be built, must be set." + exit 1 +fi + +case $FRAMEWORK_NAME in + "MediaPipeTasksCommon") + ;; + "MediaPipeTasksVision") + ;; + "MediaPipeTasksText") + ;; + *) + echo "Wrong framework name. The following framework names are allowed: MediaPipeTasksText, MediaPipeTasksVision, MediaPipeTasksCommon" + exit 1 + ;; +esac + +if [[ -z "${DEST_DIR+x}" || "${DEST_DIR}" == ${MPP_ROOT_DIR}* ]]; then + echo "DEST_DIR variable must be set and not be under the repository root." + exit 1 +fi + +# This function takes one bazel target label as an argument, and prints +# the path of the first output file of the specified target. +function get_output_file_path { + local STARLARK_OUTPUT_TMPDIR="$(mktemp -d)" + + local STARLARK_FILE="${STARLARK_OUTPUT_TMPDIR}/print_output_file.starlark" + cat > "${STARLARK_FILE}" << EOF +def format(target): + return target.files.to_list()[0].path +EOF + + local OUTPUT_PATH=$(bazel cquery $1 --output=starlark --starlark:file="${STARLARK_FILE}" 2> /dev/null) + + rm -rf "${STARLARK_OUTPUT_TMPDIR}" + + echo ${OUTPUT_PATH} +} + +# This function builds a target using the command passed in as argument and +# uses cquery to find the path to the output of the target. +function build_target { + # Build using the command passed as argument. + "${BAZEL}" build $1 + + # Get the path to the output file of the target. + local OUTPUT_PATH=$(get_output_file_path "$1") + + echo ${OUTPUT_PATH} +} + +# This function builds 3 the xcframework and associated graph libraries if any +# for a given framework name. +function build_ios_frameworks_and_libraries { + local TARGET_PREFIX="//mediapipe/tasks/ios" + FULL_FRAMEWORK_TARGET="${TARGET_PREFIX}:${FRAMEWORK_NAME}_framework" + FULL_GRAPH_LIBRARY_TARGET="${TARGET_PREFIX}:${FRAMEWORK_NAME}_GraphLibrary" + + # .bazelrc sets --apple_generate_dsym=true by default which bloats the libraries to sizes of + # the order of GBs. All iOS framework and library build commands for distribution via + # CocoaPods must set --apple_generate_dsym=false inorder to shave down the binary size to + # the order of a few MBs. + + # Build Task Library xcframework. + local FRAMEWORK_CQUERY_COMMAND="-c opt --apple_generate_dsym=false ${FULL_FRAMEWORK_TARGET}" + IOS_FRAMEWORK_PATH="$(build_target "${FRAMEWORK_CQUERY_COMMAND}")" + + # `MediaPipeTasksCommon` pods must also include the task graph libraries which + # are to be force loaded. Hence the graph libraies are only built if the framework + # name is `MediaPipeTasksCommon`.` + case $FRAMEWORK_NAME in + "MediaPipeTasksCommon") + local IOS_SIM_FAT_LIBRARY_CQUERY_COMMAND="-c opt --config=ios_sim_fat --apple_generate_dsym=false //mediapipe/tasks/ios:MediaPipeTaskGraphs_library" + IOS_GRAPHS_SIMULATOR_LIBRARY_PATH="$(build_target "${IOS_SIM_FAT_LIBRARY_CQUERY_COMMAND}")" + + # Build static library for iOS devices with arch ios_arm64. We don't need to build for armv7 since + # our deployment target is iOS 11.0. iOS 11.0 and upwards is not supported by old armv7 devices. + local IOS_DEVICE_LIBRARY_CQUERY_COMMAND="-c opt --config=ios_arm64 --apple_generate_dsym=false //mediapipe/tasks/ios:MediaPipeTaskGraphs_library" + IOS_GRAPHS_DEVICE_LIBRARY_PATH="$(build_target "${IOS_DEVICE_LIBRARY_CQUERY_COMMAND}")" + ;; + *) + ;; + esac +} + +function create_framework_archive { + # Change to the Bazel iOS output directory. + pushd "${BAZEL_IOS_OUTDIR}" + + # Create the temporary directory for the given framework. + local ARCHIVE_NAME="${FRAMEWORK_NAME}-${MPP_BUILD_VERSION}" + local MPP_TMPDIR="$(mktemp -d)" + + # Copy the license file to MPP_TMPDIR + cp "LICENSE" ${MPP_TMPDIR} + + # Unzip the iOS framework zip generated by bazel to MPP_TMPDIR + local FRAMEWORKS_DIR="${MPP_TMPDIR}/frameworks" + + echo ${IOS_FRAMEWORK_PATH} + unzip "${IOS_FRAMEWORK_PATH}" -d "${FRAMEWORKS_DIR}" + + # If the framwork being built is `MediaPipeTasksCommon`, the built graph + # libraries should be copied to the output directory which is to be archived. + case $FRAMEWORK_NAME in + "MediaPipeTasksCommon") + local GRAPH_LIBRARIES_DIR="graph_libraries" + # Create the parent folder which will hold the graph libraries of all architectures. + mkdir -p "${FRAMEWORKS_DIR}/${GRAPH_LIBRARIES_DIR}" + + local SIMULATOR_GRAPH_LIBRARY_PATH="${FRAMEWORKS_DIR}/${GRAPH_LIBRARIES_DIR}/lib${FRAMEWORK_NAME}_simulator_graph.a" + + # Copy ios simulator fat library into a separate directory. + echo ${IOS_GRAPHS_SIMULATOR_LIBRARY_PATH} + cp "${IOS_GRAPHS_SIMULATOR_LIBRARY_PATH}" "${SIMULATOR_GRAPH_LIBRARY_PATH}" + + local IOS_DEVICE_GRAPH_LIBRARY_PATH="${FRAMEWORKS_DIR}/${GRAPH_LIBRARIES_DIR}/lib${FRAMEWORK_NAME}_device_graph.a" + + # Copy ios device library into a separate directory. + echo ${IOS_GRAPHS_DEVICE_LIBRARY_PATH} + cp "${IOS_GRAPHS_DEVICE_LIBRARY_PATH}" "${IOS_DEVICE_GRAPH_LIBRARY_PATH}" + ;; + *) + ;; + esac + + #----- (3) Move the framework to the destination ----- + if [[ "${ARCHIVE_FRAMEWORK}" == true ]]; then + local TARGET_DIR="$(realpath "${FRAMEWORK_NAME}")" + + # Create the framework archive directory. + + local FRAMEWORK_ARCHIVE_DIR + if [[ "${IS_RELEASE_BUILD}" == true ]]; then + # Get the first 16 bytes of the sha256 checksum of the root directory. + local SHA256_CHECKSUM=$(find "${MPP_TMPDIR}" -type f -print0 | xargs -0 shasum -a 256 | sort | shasum -a 256 | cut -c1-16) + FRAMEWORK_ARCHIVE_DIR="${TARGET_DIR}/${MPP_BUILD_VERSION}/${SHA256_CHECKSUM}" + else + FRAMEWORK_ARCHIVE_DIR="${TARGET_DIR}/${MPP_BUILD_VERSION}" + fi + mkdir -p "${FRAMEWORK_ARCHIVE_DIR}" + + # Zip up the framework and move to the archive directory. + pushd "${MPP_TMPDIR}" + local MPP_ARCHIVE_FILE="${ARCHIVE_NAME}.tar.gz" + tar -cvzf "${MPP_ARCHIVE_FILE}" . + mv "${MPP_ARCHIVE_FILE}" "${FRAMEWORK_ARCHIVE_DIR}" + popd + + # Move the target directory to the Kokoro artifacts directory. + mv "${TARGET_DIR}" "$(realpath "${DEST_DIR}")"/ + else + rsync -r "${MPP_TMPDIR}/" "$(realpath "${DEST_DIR}")/" + fi + + # Clean up the temporary directory for the framework. + rm -rf "${MPP_TMPDIR}" + echo ${MPP_TMPDIR} +} + +cd "${MPP_ROOT_DIR}" +build_ios_frameworks_and_libraries +create_framework_archive diff --git a/mediapipe/tasks/ios/ios.bzl b/mediapipe/tasks/ios/ios.bzl deleted file mode 100644 index 8fe2a24a1..000000000 --- a/mediapipe/tasks/ios/ios.bzl +++ /dev/null @@ -1,3 +0,0 @@ -"""MediaPipe Task Library Helper Rules for iOS""" - -MPP_TASK_MINIMUM_OS_VERSION = "11.0" diff --git a/mediapipe/tasks/ios/test/text/text_classifier/BUILD b/mediapipe/tasks/ios/test/text/text_classifier/BUILD index 3b533646e..b770b7127 100644 --- a/mediapipe/tasks/ios/test/text/text_classifier/BUILD +++ b/mediapipe/tasks/ios/test/text/text_classifier/BUILD @@ -7,7 +7,7 @@ load( "swift_library", ) load( - "//mediapipe/tasks:ios/ios.bzl", + "//mediapipe/framework/tool:ios.bzl", "MPP_TASK_MINIMUM_OS_VERSION", ) load( diff --git a/mediapipe/tasks/ios/test/text/text_embedder/BUILD b/mediapipe/tasks/ios/test/text/text_embedder/BUILD index 387db3574..3d8825440 100644 --- a/mediapipe/tasks/ios/test/text/text_embedder/BUILD +++ b/mediapipe/tasks/ios/test/text/text_embedder/BUILD @@ -7,7 +7,7 @@ load( "swift_library", ) load( - "//mediapipe/tasks:ios/ios.bzl", + "//mediapipe/framework/tool:ios.bzl", "MPP_TASK_MINIMUM_OS_VERSION", ) load( diff --git a/mediapipe/tasks/ios/test/vision/core/BUILD b/mediapipe/tasks/ios/test/vision/core/BUILD index 92954d065..5932968e5 100644 --- a/mediapipe/tasks/ios/test/vision/core/BUILD +++ b/mediapipe/tasks/ios/test/vision/core/BUILD @@ -3,7 +3,7 @@ load( "ios_unit_test", ) load( - "//mediapipe/tasks:ios/ios.bzl", + "//mediapipe/framework/tool:ios.bzl", "MPP_TASK_MINIMUM_OS_VERSION", ) load( diff --git a/mediapipe/tasks/ios/test/vision/image_classifier/BUILD b/mediapipe/tasks/ios/test/vision/image_classifier/BUILD index c274e6e2e..b84fb6a7e 100644 --- a/mediapipe/tasks/ios/test/vision/image_classifier/BUILD +++ b/mediapipe/tasks/ios/test/vision/image_classifier/BUILD @@ -1,6 +1,6 @@ load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test") load( - "//mediapipe/tasks:ios/ios.bzl", + "//mediapipe/framework/tool:ios.bzl", "MPP_TASK_MINIMUM_OS_VERSION", ) load(