From d03c60dd7fa94f3df927c5c90db5a038412ef0b6 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 8 Nov 2023 04:53:31 +0700 Subject: [PATCH] ios : add support for Swift Package Manager (#1370) * Add support for Swift * Make it build in Xcode * Use the SPM package in the SwiftUI example app --- .gitignore | 5 + Package.swift | 77 +++++++++++++++ .../whisper.cpp.swift/LibWhisper.swift | 1 + .../WhisperCppDemo-Bridging-Header.h | 4 - .../whisper.swiftui.xcodeproj/project.pbxproj | 96 +++++-------------- spm-headers/ggml.h | 1 + spm-headers/whisper.h | 1 + 7 files changed, 109 insertions(+), 76 deletions(-) create mode 100644 Package.swift delete mode 100644 examples/whisper.swiftui/whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h create mode 120000 spm-headers/ggml.h create mode 120000 spm-headers/whisper.h diff --git a/.gitignore b/.gitignore index ab1fc2e3a77..d5c4b0caf48 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,11 @@ build-no-accel/ build-sanitize-addr/ build-sanitize-thread/ +# SPM +.build/ +.swiftpm +*.metallib + /main /stream /command diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000000..5022b413d1a --- /dev/null +++ b/Package.swift @@ -0,0 +1,77 @@ +// swift-tools-version:5.5 + +import PackageDescription + +#if arch(arm) || arch(arm64) +let platforms: [SupportedPlatform]? = [ + .macOS(.v12), + .iOS(.v14), + .watchOS(.v4), + .tvOS(.v14) +] +let exclude: [String] = [] +let resources: [Resource] = [ + .process("ggml-metal.metal") +] +let additionalSources: [String] = ["ggml-metal.m"] +let additionalSettings: [CSetting] = [ + .unsafeFlags(["-fno-objc-arc"]), + .define("GGML_USE_METAL") +] +#else +let platforms: [SupportedPlatform]? = nil +let exclude: [String] = ["ggml-metal.metal"] +let resources: [Resource] = [] +let additionalSources: [String] = [] +let additionalSettings: [CSetting] = [] +#endif + +let package = Package( + name: "whisper", + platforms: platforms, + products: [ + .library(name: "whisper", targets: ["whisper"]), + ], + targets: [ + .target( + name: "whisper", + path: ".", + exclude: exclude + [ + "bindings", + "cmake", + "coreml", + "examples", + "extra", + "models", + "samples", + "tests", + "CMakeLists.txt", + "ggml-cuda.cu", + "ggml-cuda.h", + "Makefile" + ], + sources: [ + "ggml.c", + "whisper.cpp", + "ggml-alloc.c", + "ggml-backend.c", + "ggml-quants.c" + ] + additionalSources, + resources: resources, + publicHeadersPath: "spm-headers", + cSettings: [ + .unsafeFlags(["-Wno-shorten-64-to-32", "-O3", "-DNDEBUG"]), + .define("GGML_USE_ACCELERATE") + // NOTE: NEW_LAPACK will required iOS version 16.4+ + // We should consider add this in the future when we drop support for iOS 14 + // (ref: ref: https://developer.apple.com/documentation/accelerate/1513264-cblas_sgemm?language=objc) + // .define("ACCELERATE_NEW_LAPACK"), + // .define("ACCELERATE_LAPACK_ILP64") + ] + additionalSettings, + linkerSettings: [ + .linkedFramework("Accelerate") + ] + ) + ], + cxxLanguageStandard: .cxx11 +) diff --git a/examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift b/examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift index 95e1aeefbc3..84559c9a0c6 100644 --- a/examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift +++ b/examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift @@ -1,4 +1,5 @@ import Foundation +import whisper enum WhisperError: Error { case couldNotInitializeContext diff --git a/examples/whisper.swiftui/whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h b/examples/whisper.swiftui/whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h deleted file mode 100644 index f5ed59c0fcf..00000000000 --- a/examples/whisper.swiftui/whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h +++ /dev/null @@ -1,4 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// -#import "whisper.h" diff --git a/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj b/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj index 605240da179..d5efc0f5e63 100644 --- a/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj +++ b/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj @@ -15,16 +15,9 @@ 0AAC5D9B29539CCF003032C3 /* WhisperCppDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5D9A29539CCF003032C3 /* WhisperCppDemoApp.swift */; }; 0AAC5D9D29539CCF003032C3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5D9C29539CCF003032C3 /* ContentView.swift */; }; 0AAC5D9F29539CD0003032C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AAC5D9E29539CD0003032C3 /* Assets.xcassets */; }; - 0AAC5DA329539CD0003032C3 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AAC5DA229539CD0003032C3 /* Preview Assets.xcassets */; }; - 0AAC5DCB29539EB1003032C3 /* whisper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DC729539EB0003032C3 /* whisper.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_METAL -Wno-shorten-64-to-32"; }; }; - 0AAC5DCC29539EB1003032C3 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DC929539EB0003032C3 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_METAL -Wno-shorten-64-to-32"; }; }; 0AAC5DCE2953A05C003032C3 /* WhisperState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DCD2953A05C003032C3 /* WhisperState.swift */; }; 0AAC5DD12953A394003032C3 /* LibWhisper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DD02953A394003032C3 /* LibWhisper.swift */; }; - 18ABE1522AF555FA0044A204 /* ggml-backend.c in Sources */ = {isa = PBXBuildFile; fileRef = 18ABE14C2AF555FA0044A204 /* ggml-backend.c */; }; - 18ABE1532AF555FA0044A204 /* ggml-quants.c in Sources */ = {isa = PBXBuildFile; fileRef = 18ABE1512AF555FA0044A204 /* ggml-quants.c */; }; - 18AED4812AB21F2B009D854F /* ggml-alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AED47F2AB21F2B009D854F /* ggml-alloc.c */; }; - 7FCB08262ACFA3A400AF3530 /* ggml-metal.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FCB08252ACFA3A400AF3530 /* ggml-metal.m */; settings = {COMPILER_FLAGS = "-framework Foundation -framework Metal -framework MetalKit -fno-objc-arc"; }; }; - 7FCB08282ACFA48500AF3530 /* ggml-metal.metal in Sources */ = {isa = PBXBuildFile; fileRef = 7FCB08272ACFA48500AF3530 /* ggml-metal.metal */; }; + E3F92DC52AFA8E3800A6A9D4 /* whisper in Frameworks */ = {isa = PBXBuildFile; productRef = E3F92DC42AFA8E3800A6A9D4 /* whisper */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -38,25 +31,9 @@ 0AAC5D9C29539CCF003032C3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 0AAC5D9E29539CD0003032C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 0AAC5DA029539CD0003032C3 /* WhisperCppDemo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WhisperCppDemo.entitlements; sourceTree = ""; }; - 0AAC5DA229539CD0003032C3 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; - 0AAC5DC629539EAF003032C3 /* WhisperCppDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WhisperCppDemo-Bridging-Header.h"; sourceTree = ""; }; - 0AAC5DC729539EB0003032C3 /* whisper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = whisper.cpp; sourceTree = ""; }; - 0AAC5DC829539EB0003032C3 /* whisper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = whisper.h; sourceTree = ""; }; - 0AAC5DC929539EB0003032C3 /* ggml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ggml.c; sourceTree = ""; }; - 0AAC5DCA29539EB0003032C3 /* ggml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ggml.h; sourceTree = ""; }; 0AAC5DCD2953A05C003032C3 /* WhisperState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhisperState.swift; sourceTree = ""; }; 0AAC5DD02953A394003032C3 /* LibWhisper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibWhisper.swift; sourceTree = ""; }; - 18ABE14C2AF555FA0044A204 /* ggml-backend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ggml-backend.c"; sourceTree = ""; }; - 18ABE14D2AF555FA0044A204 /* ggml-backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ggml-backend.h"; sourceTree = ""; }; - 18ABE14E2AF555FA0044A204 /* ggml-backend-impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ggml-backend-impl.h"; sourceTree = ""; }; - 18ABE14F2AF555FA0044A204 /* ggml-quants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ggml-quants.h"; sourceTree = ""; }; - 18ABE1502AF555FA0044A204 /* ggml-impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ggml-impl.h"; sourceTree = ""; }; - 18ABE1512AF555FA0044A204 /* ggml-quants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ggml-quants.c"; sourceTree = ""; }; - 18AED47F2AB21F2B009D854F /* ggml-alloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ggml-alloc.c"; sourceTree = ""; }; - 18AED4802AB21F2B009D854F /* ggml-alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ggml-alloc.h"; sourceTree = ""; }; - 7FCB081E2ACFA04400AF3530 /* ggml-metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ggml-metal.h"; sourceTree = ""; }; - 7FCB08252ACFA3A400AF3530 /* ggml-metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ggml-metal.m"; sourceTree = ""; }; - 7FCB08272ACFA48500AF3530 /* ggml-metal.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = "ggml-metal.metal"; sourceTree = ""; }; + E3F92DC22AFA8DD800A6A9D4 /* whisper.cpp */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = whisper.cpp; path = ../..; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,6 +41,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E3F92DC52AFA8E3800A6A9D4 /* whisper in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,11 +77,12 @@ 0AAC5D8E29539CCF003032C3 = { isa = PBXGroup; children = ( + E3F92DC22AFA8DD800A6A9D4 /* whisper.cpp */, 0A8E48FF2954B3F100704C1B /* README.md */, - 0AAC5DC529539E89003032C3 /* whisper.cpp */, 0AAC5DCF2953A36C003032C3 /* whisper.cpp.swift */, 0AAC5D9929539CCF003032C3 /* whisper.swiftui.demo */, 0AAC5D9829539CCF003032C3 /* Products */, + E3F92DC32AFA8E3800A6A9D4 /* Frameworks */, ); sourceTree = ""; }; @@ -128,42 +107,9 @@ path = whisper.swiftui.demo; sourceTree = ""; }; - 0AAC5DA129539CD0003032C3 /* Preview Content */ = { - isa = PBXGroup; - children = ( - 0AAC5DA229539CD0003032C3 /* Preview Assets.xcassets */, - ); - name = "Preview Content"; - path = "../Preview Content"; - sourceTree = ""; - }; - 0AAC5DC529539E89003032C3 /* whisper.cpp */ = { - isa = PBXGroup; - children = ( - 7FCB08272ACFA48500AF3530 /* ggml-metal.metal */, - 7FCB081E2ACFA04400AF3530 /* ggml-metal.h */, - 7FCB08252ACFA3A400AF3530 /* ggml-metal.m */, - 18ABE14E2AF555FA0044A204 /* ggml-backend-impl.h */, - 18ABE14C2AF555FA0044A204 /* ggml-backend.c */, - 18ABE14D2AF555FA0044A204 /* ggml-backend.h */, - 18ABE1502AF555FA0044A204 /* ggml-impl.h */, - 18ABE1512AF555FA0044A204 /* ggml-quants.c */, - 18ABE14F2AF555FA0044A204 /* ggml-quants.h */, - 18AED47F2AB21F2B009D854F /* ggml-alloc.c */, - 18AED4802AB21F2B009D854F /* ggml-alloc.h */, - 0AAC5DC929539EB0003032C3 /* ggml.c */, - 0AAC5DCA29539EB0003032C3 /* ggml.h */, - 0AAC5DC729539EB0003032C3 /* whisper.cpp */, - 0AAC5DC829539EB0003032C3 /* whisper.h */, - ); - name = whisper.cpp; - path = ../..; - sourceTree = ""; - }; 0AAC5DCF2953A36C003032C3 /* whisper.cpp.swift */ = { isa = PBXGroup; children = ( - 0AAC5DC629539EAF003032C3 /* WhisperCppDemo-Bridging-Header.h */, 0AAC5DD02953A394003032C3 /* LibWhisper.swift */, ); path = whisper.cpp.swift; @@ -182,11 +128,17 @@ children = ( 0AAC5D9E29539CD0003032C3 /* Assets.xcassets */, 0AAC5DA029539CD0003032C3 /* WhisperCppDemo.entitlements */, - 0AAC5DA129539CD0003032C3 /* Preview Content */, ); path = "Supporting files"; sourceTree = ""; }; + E3F92DC32AFA8E3800A6A9D4 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -203,6 +155,9 @@ dependencies = ( ); name = whisper.swiftui; + packageProductDependencies = ( + E3F92DC42AFA8E3800A6A9D4 /* whisper */, + ); productName = WhisperCppDemo; productReference = 0AAC5D9729539CCF003032C3 /* whisper.swiftui.app */; productType = "com.apple.product-type.application"; @@ -247,7 +202,6 @@ buildActionMask = 2147483647; files = ( 0AA751482953AC2E001EE061 /* samples in Resources */, - 0AAC5DA329539CD0003032C3 /* Preview Assets.xcassets in Resources */, 0A8E49002954B3F100704C1B /* README.md in Resources */, 0AA751492953AC2E001EE061 /* models in Resources */, 0AAC5D9F29539CD0003032C3 /* Assets.xcassets in Resources */, @@ -263,17 +217,10 @@ files = ( 0AAC5D9D29539CCF003032C3 /* ContentView.swift in Sources */, 0AAC5D9B29539CCF003032C3 /* WhisperCppDemoApp.swift in Sources */, - 0AAC5DCC29539EB1003032C3 /* ggml.c in Sources */, - 18ABE1532AF555FA0044A204 /* ggml-quants.c in Sources */, 0AAC5DCE2953A05C003032C3 /* WhisperState.swift in Sources */, - 7FCB08282ACFA48500AF3530 /* ggml-metal.metal in Sources */, 0AAC5DD12953A394003032C3 /* LibWhisper.swift in Sources */, 0AA7514C2953B569001EE061 /* RiffWaveUtils.swift in Sources */, - 0AAC5DCB29539EB1003032C3 /* whisper.cpp in Sources */, 0AA7514E2953D958001EE061 /* Recorder.swift in Sources */, - 7FCB08262ACFA3A400AF3530 /* ggml-metal.m in Sources */, - 18AED4812AB21F2B009D854F /* ggml-alloc.c in Sources */, - 18ABE1522AF555FA0044A204 /* ggml-backend.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -401,7 +348,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"whisper.swiftui.demo/Supporting files/Preview Content\""; - DEVELOPMENT_TEAM = P8JZH34X63; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -425,7 +372,6 @@ SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -442,7 +388,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"whisper.swiftui.demo/Supporting files/Preview Content\""; - DEVELOPMENT_TEAM = P8JZH34X63; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -471,7 +417,6 @@ SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -499,6 +444,13 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + E3F92DC42AFA8E3800A6A9D4 /* whisper */ = { + isa = XCSwiftPackageProductDependency; + productName = whisper; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 0AAC5D8F29539CCF003032C3 /* Project object */; } diff --git a/spm-headers/ggml.h b/spm-headers/ggml.h new file mode 120000 index 00000000000..39215298f98 --- /dev/null +++ b/spm-headers/ggml.h @@ -0,0 +1 @@ +../ggml.h \ No newline at end of file diff --git a/spm-headers/whisper.h b/spm-headers/whisper.h new file mode 120000 index 00000000000..f67137aa25a --- /dev/null +++ b/spm-headers/whisper.h @@ -0,0 +1 @@ +../whisper.h \ No newline at end of file