From 32b6067a0116bc5cdf2a24a079295c7d83f4b2f9 Mon Sep 17 00:00:00 2001 From: CatalinVoss Date: Mon, 23 Nov 2020 18:32:18 -0800 Subject: [PATCH] Enable static build of DeepSpeech iOS framework Set up additional `deepspeech_ios` target with static build steps Xcode config: lock swift version at 5.0, bundle framework rather than dynamic lib, never strip swift symbols, add framework search paths, and bring in lstdc++ Runtime schema config: disable the main thread checker as this causes trouble with the static build Update model versions to 0.9.1 Remove libdeepspeech.so from example app bundling steps Swift lib embed settings that are somehow essential Attempt to adjust taskcluster build steps Add a basic podspec Add framework to gitignore Fix podspec version code Attempt to fix taskcluster unzip step Switch deepspeech targets for iOS build Try doing this unzip in one step Remove packaging steps for unneeded stuff because libdeepspeech.so is no longer a thing here. I suppose we could add a step to package the iOS static lib instead. Fix podspec version Set up podspec relative assuming a clone from the repo root Remove space in iOS package step Fix buildfile nit Link stdc++ in explicitly with iOS build only Revert "Remove space in iOS package step" This reverts commit 3e1922ea370c110f9854ae7e97101f2ea00f55c6. --- .gitignore | 1 + native_client/BUILD | 18 ++++++++++++-- native_client/swift/deepspeech-ios.podspec | 19 +++++++++++++++ .../deepspeech_ios.xcodeproj/project.pbxproj | 24 +++++++++++++++---- .../xcschemes/deepspeech_ios.xcscheme | 1 + .../project.pbxproj | 4 ---- .../SpeechRecognitionImpl.swift | 4 ++-- taskcluster/ios-build.sh | 2 +- taskcluster/ios-package.sh | 4 ---- taskcluster/tc-build-utils.sh | 2 +- 10 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 native_client/swift/deepspeech-ios.podspec diff --git a/.gitignore b/.gitignore index eab56fe6..b4646cda 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ doc/xml-c doc/xml-java doc/xml-dotnet convert_graphdef_memmapped_format +native_client/swift/deepspeech_ios.framework/deepspeech_ios diff --git a/native_client/BUILD b/native_client/BUILD index 9119f392..c98d86a3 100644 --- a/native_client/BUILD +++ b/native_client/BUILD @@ -3,6 +3,7 @@ load("@org_tensorflow//tensorflow:tensorflow.bzl", "tf_cc_shared_object") load("@local_config_cuda//cuda:build_defs.bzl", "if_cuda") load("@com_github_nelhage_rules_boost//:boost/boost.bzl", "boost_deps") +load("@build_bazel_rules_apple//apple:ios.bzl", "ios_static_framework") load( "@org_tensorflow//tensorflow/lite:build_def.bzl", @@ -110,8 +111,8 @@ cc_library( ], ) -tf_cc_shared_object( - name = "libdeepspeech.so", +cc_library( + name = "deepspeech_bundle", srcs = [ "deepspeech.cc", "deepspeech.h", @@ -203,6 +204,19 @@ tf_cc_shared_object( ]) + [":decoder"], ) +tf_cc_shared_object( + name = "libdeepspeech.so", + deps = [":deepspeech_bundle"], +) + +ios_static_framework( + name = "deepspeech_ios", + deps = [":deepspeech_bundle"], + families = ["iphone", "ipad"], + minimum_os_version = "9.0", + linkopts = ["-lstdc++"], +) + genrule( name = "libdeepspeech_so_dsym", srcs = [":libdeepspeech.so"], diff --git a/native_client/swift/deepspeech-ios.podspec b/native_client/swift/deepspeech-ios.podspec new file mode 100644 index 00000000..d56d806a --- /dev/null +++ b/native_client/swift/deepspeech-ios.podspec @@ -0,0 +1,19 @@ +# Pull in version from outside +version = File.read(File.join(__dir__, "../../training/deepspeech_training/VERSION")).split("\n")[0] + +Pod::Spec.new do |s| + s.name = "deepspeech-ios" + s.version = version + s.summary = "DeepSpeech" + s.homepage = "https://github.com/mozilla/DeepSpeech" + s.license = "Mozilla Public License 2.0" + s.authors = "Mozilla et al." + + s.platforms = { :ios => "9.0" } + s.source = { :git => "https://github.com/mozilla/DeepSpeech.git", :tag => "v#{s.version}" } + + # Assuming taskcluster build location. Depending on your Xcode setup, this might be in + # build/Release-iphoneos/deepspeech_ios.framework instead. + s.vendored_frameworks = "native_client/swift/DerivedData/Build/Products/Release-iphoneos/deepspeech_ios.framework" + s.source_files = "native_client/swift/deepspeech_ios/**/*.{h,m,mm,swift}" +end diff --git a/native_client/swift/deepspeech_ios.xcodeproj/project.pbxproj b/native_client/swift/deepspeech_ios.xcodeproj/project.pbxproj index 59927e9e..d400f591 100644 --- a/native_client/swift/deepspeech_ios.xcodeproj/project.pbxproj +++ b/native_client/swift/deepspeech_ios.xcodeproj/project.pbxproj @@ -11,7 +11,7 @@ 505B137224960D550007DADA /* deepspeech_ios.h in Headers */ = {isa = PBXBuildFile; fileRef = 505B136424960D550007DADA /* deepspeech_ios.h */; settings = {ATTRIBUTES = (Public, ); }; }; 505B137D24961AF20007DADA /* deepspeech.h in Headers */ = {isa = PBXBuildFile; fileRef = 505B137C24961AF20007DADA /* deepspeech.h */; settings = {ATTRIBUTES = (Private, ); }; }; 505B137F24961BA70007DADA /* DeepSpeech.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505B137E24961BA70007DADA /* DeepSpeech.swift */; }; - 507CD39B24B61FA100409BBB /* libdeepspeech.so in Frameworks */ = {isa = PBXBuildFile; fileRef = 507CD39A24B61FA100409BBB /* libdeepspeech.so */; }; + AD2FD0F925678F8800314F2E /* deepspeech_ios.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD2FD0F825678F8800314F2E /* deepspeech_ios.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -45,7 +45,7 @@ 505B137B249619C90007DADA /* deepspeech_ios.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = deepspeech_ios.modulemap; sourceTree = ""; }; 505B137C24961AF20007DADA /* deepspeech.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = deepspeech.h; path = ../../deepspeech.h; sourceTree = ""; }; 505B137E24961BA70007DADA /* DeepSpeech.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepSpeech.swift; sourceTree = ""; }; - 507CD39A24B61FA100409BBB /* libdeepspeech.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libdeepspeech.so; sourceTree = ""; }; + AD2FD0F825678F8800314F2E /* deepspeech_ios.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = deepspeech_ios.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -53,7 +53,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 507CD39B24B61FA100409BBB /* libdeepspeech.so in Frameworks */, + AD2FD0F925678F8800314F2E /* deepspeech_ios.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -101,7 +101,7 @@ 505B1380249620C60007DADA /* Frameworks */ = { isa = PBXGroup; children = ( - 507CD39A24B61FA100409BBB /* libdeepspeech.so */, + AD2FD0F825678F8800314F2E /* deepspeech_ios.framework */, ); name = Frameworks; sourceTree = ""; @@ -243,6 +243,7 @@ 505B137324960D550007DADA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -296,8 +297,10 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + STRIP_SWIFT_SYMBOLS = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -306,6 +309,7 @@ 505B137424960D550007DADA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -352,8 +356,10 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; + STRIP_SWIFT_SYMBOLS = NO; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -372,6 +378,10 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); INFOPLIST_FILE = deepspeech_ios/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( @@ -386,6 +396,7 @@ ); MODULEMAP_FILE = deepspeech_ios/deepspeech_ios.modulemap; PRODUCT_BUNDLE_IDENTIFIER = "org.mozilla.deepspeech-ios"; + OTHER_LDFLAGS = "-lstdc++"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -406,6 +417,10 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); INFOPLIST_FILE = deepspeech_ios/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( @@ -420,6 +435,7 @@ ); MODULEMAP_FILE = deepspeech_ios/deepspeech_ios.modulemap; PRODUCT_BUNDLE_IDENTIFIER = "org.mozilla.deepspeech-ios"; + OTHER_LDFLAGS = "-lstdc++"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; diff --git a/native_client/swift/deepspeech_ios.xcodeproj/xcshareddata/xcschemes/deepspeech_ios.xcscheme b/native_client/swift/deepspeech_ios.xcodeproj/xcshareddata/xcschemes/deepspeech_ios.xcscheme index b3ba3705..b0b1b83f 100644 --- a/native_client/swift/deepspeech_ios.xcodeproj/xcshareddata/xcschemes/deepspeech_ios.xcscheme +++ b/native_client/swift/deepspeech_ios.xcodeproj/xcshareddata/xcschemes/deepspeech_ios.xcscheme @@ -44,6 +44,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + disableMainThreadChecker = "YES" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/native_client/swift/deepspeech_ios_test.xcodeproj/project.pbxproj b/native_client/swift/deepspeech_ios_test.xcodeproj/project.pbxproj index a57f983c..ea1c51f9 100644 --- a/native_client/swift/deepspeech_ios_test.xcodeproj/project.pbxproj +++ b/native_client/swift/deepspeech_ios_test.xcodeproj/project.pbxproj @@ -11,8 +11,6 @@ 504EC34424CF4EFD0073C22E /* AudioContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC34224CF4EFD0073C22E /* AudioContext.swift */; }; 504EC34524CF4F4F0073C22E /* deepspeech_ios.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 507CD3A024B61FE400409BBB /* deepspeech_ios.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 507CD3A124B61FE400409BBB /* deepspeech_ios.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 507CD3A024B61FE400409BBB /* deepspeech_ios.framework */; }; - 507CD3A324B61FEB00409BBB /* libdeepspeech.so in Frameworks */ = {isa = PBXBuildFile; fileRef = 507CD3A224B61FEA00409BBB /* libdeepspeech.so */; }; - 507CD3A424B61FFC00409BBB /* libdeepspeech.so in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 507CD3A224B61FEA00409BBB /* libdeepspeech.so */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 50F787F32497683900D52237 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50F787F22497683900D52237 /* AppDelegate.swift */; }; 50F787F52497683900D52237 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50F787F42497683900D52237 /* SceneDelegate.swift */; }; 50F787F72497683900D52237 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50F787F62497683900D52237 /* ContentView.swift */; }; @@ -48,7 +46,6 @@ dstSubfolderSpec = 10; files = ( 504EC34524CF4F4F0073C22E /* deepspeech_ios.framework in Embed Frameworks */, - 507CD3A424B61FFC00409BBB /* libdeepspeech.so in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -81,7 +78,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 507CD3A324B61FEB00409BBB /* libdeepspeech.so in Frameworks */, 507CD3A124B61FE400409BBB /* deepspeech_ios.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/native_client/swift/deepspeech_ios_test/SpeechRecognitionImpl.swift b/native_client/swift/deepspeech_ios_test/SpeechRecognitionImpl.swift index b3a4ac9b..35dfe0a6 100644 --- a/native_client/swift/deepspeech_ios_test/SpeechRecognitionImpl.swift +++ b/native_client/swift/deepspeech_ios_test/SpeechRecognitionImpl.swift @@ -26,8 +26,8 @@ class SpeechRecognitionImpl : NSObject, AVCaptureAudioDataOutputSampleBufferDele private var audioData = Data() override init() { - let modelPath = Bundle.main.path(forResource: "deepspeech-0.7.4-models", ofType: "tflite")! - let scorerPath = Bundle.main.path(forResource: "deepspeech-0.7.4-models", ofType: "scorer")! + let modelPath = Bundle.main.path(forResource: "deepspeech-0.9.1-models", ofType: "tflite")! + let scorerPath = Bundle.main.path(forResource: "deepspeech-0.9.1-models", ofType: "scorer")! model = try! DeepSpeechModel(modelPath: modelPath) try! model.enableExternalScorer(scorerPath: scorerPath) diff --git a/taskcluster/ios-build.sh b/taskcluster/ios-build.sh index 282f8c32..38ace090 100755 --- a/taskcluster/ios-build.sh +++ b/taskcluster/ios-build.sh @@ -9,7 +9,7 @@ source $(dirname "$0")/tc-tests-utils.sh source $(dirname "$0")/tf_tc-vars.sh BAZEL_TARGETS=" -//native_client:libdeepspeech.so +//native_client:deepspeech_ios " if [ "${arch}" = "--arm64" ]; then diff --git a/taskcluster/ios-package.sh b/taskcluster/ios-package.sh index 16cc9f96..9c688a65 100755 --- a/taskcluster/ios-package.sh +++ b/taskcluster/ios-package.sh @@ -10,10 +10,6 @@ mkdir -p ${TASKCLUSTER_ARTIFACTS} || true cp ${DS_ROOT_TASK}/DeepSpeech/ds/tensorflow/bazel*.log ${TASKCLUSTER_ARTIFACTS}/ -package_native_client "native_client.tar.xz" - -package_libdeepspeech_as_zip "libdeepspeech.zip" - case $arch in "--x86_64") release_folder="Release-iphonesimulator" diff --git a/taskcluster/tc-build-utils.sh b/taskcluster/tc-build-utils.sh index b1077ada..e823175c 100755 --- a/taskcluster/tc-build-utils.sh +++ b/taskcluster/tc-build-utils.sh @@ -340,7 +340,7 @@ do_nuget_build() do_deepspeech_ios_framework_build() { arch=$1 - cp ${DS_TFDIR}/bazel-bin/native_client/libdeepspeech.so ${DS_DSDIR}/native_client/swift/libdeepspeech.so + unzip ${DS_TFDIR}/bazel-bin/native_client/deepspeech_ios.zip -d ${DS_DSDIR}/native_client/swift cd ${DS_DSDIR}/native_client/swift case $arch in "--x86_64")