From e6a107d2642aacdff221c707d4f06f4fe360d337 Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Sat, 16 Nov 2024 14:39:11 +0800 Subject: [PATCH] Use xcframework for Flutter iOS plugin. It supports both iPhones and iOS simulators. --- .github/workflows/release-dart-package.yaml | 7 +- build-ios-shared.sh | 146 +++++++++++++++++- flutter-examples/README.md | 10 +- flutter-examples/tts/lib/model.dart | 11 +- flutter/sherpa_onnx/lib/sherpa_onnx.dart | 10 +- .../ios/sherpa_onnx_ios.podspec | 3 +- new-release.sh | 1 + 7 files changed, 170 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release-dart-package.yaml b/.github/workflows/release-dart-package.yaml index f590403fe..cc830e2c2 100644 --- a/.github/workflows/release-dart-package.yaml +++ b/.github/workflows/release-dart-package.yaml @@ -481,11 +481,8 @@ jobs: - name: Copy pre-built libs shell: bash run: | - echo "----ios-arm64----" - cp -v build-ios-shared/ios-arm64/libsherpa-onnx-c-api.dylib flutter/sherpa_onnx_ios/ios/ - cp -v build-ios-shared/ios-onnxruntime/onnxruntime.xcframework/ios-arm64/onnxruntime.a flutter/sherpa_onnx_ios/ios/libonnxruntime.a - - ls -lh flutter/sherpa_onnx_ios/ios/libonnxruntime.a + echo "----ios arm64 and arm64_x64_simulator----" + cp -av build-ios-shared/sherpa_onnx.xcframework flutter/sherpa_onnx_ios/ios/ mv -v flutter/sherpa_onnx_ios /tmp/to_be_published diff --git a/build-ios-shared.sh b/build-ios-shared.sh index 2af1b36f0..3191289ab 100755 --- a/build-ios-shared.sh +++ b/build-ios-shared.sh @@ -76,6 +76,8 @@ if [[ ! -f build/simulator_x86_64/install/lib/libsherpa-onnx-c-api.dylib ]]; the -B build/simulator_x86_64 cmake --build build/simulator_x86_64 -j 4 --target install +else + echo "Skip building for simulator (x86_64)" fi echo "Building for simulator (arm64)" @@ -107,6 +109,8 @@ if [[ ! -f build/simulator_arm64/install/lib/libsherpa-onnx-c-api.dylib ]]; then -B build/simulator_arm64 cmake --build build/simulator_arm64 -j 4 --target install +else + echo "Skip building for simulator (arm64)" fi echo "Building for arm64" @@ -140,11 +144,149 @@ if [[ ! -f build/os64/install/lib/libsherpa-onnx-c-api.dylib ]]; then -B build/os64 cmake --build build/os64 -j 4 --target install +else + echo "Skip building for arm64" fi echo "Collect dynamic libraries " mkdir -p ios-arm64 ios-arm64-simulator ios-x86_64-simulator cp -v ./build/os64/install/lib/libsherpa-onnx-c-api.dylib ios-arm64/ -cp -v ./build/simulator_arm64/install/lib/libsherpa-onnx-c-api.dylib ios-arm64-simulator -cp -v .//build/simulator_x86_64/install/lib/libsherpa-onnx-c-api.dylib ios-x86_64-simulator +cp -v ./build/simulator_arm64/install/lib/libsherpa-onnx-c-api.dylib ios-arm64-simulator/ +cp -v .//build/simulator_x86_64/install/lib/libsherpa-onnx-c-api.dylib ios-x86_64-simulator/ + +# see https://github.com/k2-fsa/sherpa-onnx/issues/1172#issuecomment-2439662662 +rm -rf ios-arm64_x86_64-simulator +mkdir ios-arm64_x86_64-simulator + +lipo \ + -create \ + ios-arm64-simulator/libsherpa-onnx-c-api.dylib \ + ios-x86_64-simulator/libsherpa-onnx-c-api.dylib \ + -output \ + ios-arm64_x86_64-simulator/libsherpa-onnx-c-api.dylib + +pushd ios-arm64 +rm -rf sherpa_onnx.framework +mkdir sherpa_onnx.framework + +lipo \ + -create \ + libsherpa-onnx-c-api.dylib \ + -output \ + sherpa_onnx + +mv sherpa_onnx sherpa_onnx.framework/ +cd sherpa_onnx.framework + +install_name_tool \ + -change @rpath/libsherpa-onnx-c-api.dylib @rpath/sherpa_onnx.framework/sherpa_onnx \ + sherpa_onnx + +install_name_tool \ + -id "@rpath/sherpa_onnx.framework/sherpa_onnx" \ + sherpa_onnx + +chmod +x sherpa_onnx +popd + +pushd ios-arm64_x86_64-simulator +rm -rf sherpa_onnx.framework +mkdir sherpa_onnx.framework + +lipo \ + -create \ + libsherpa-onnx-c-api.dylib \ + -output \ + sherpa_onnx + +mv sherpa_onnx sherpa_onnx.framework/ +cd sherpa_onnx.framework +install_name_tool \ + -change @rpath/libsherpa-onnx-c-api.dylib @rpath/sherpa_onnx.framework/sherpa_onnx \ + sherpa_onnx + +install_name_tool \ + -id "@rpath/sherpa_onnx.framework/sherpa_onnx" \ + sherpa_onnx + +chmod +x sherpa_onnx +popd + +for d in ios-arm64_x86_64-simulator ios-arm64; do + dst=$d/sherpa_onnx.framework + + # The Info.plist is modified from + # https://github.com/Spicely/flutter_openim_sdk_ffi/blob/main/ios/openim_sdk_ffi.framework/Info.plist + cat >$dst/Info.plist < + + + + CFBundleName + sherpa_onnx + DTSDKName + iphoneos17.0 + DTXcode + 1501 + DTSDKBuild + 21A326 + CFBundleDevelopmentRegion + en + CFBundleVersion + 1 + BuildMachineOSBuild + 23B81 + DTPlatformName + iphoneos + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.10.30 + CFBundleSupportedPlatforms + + iPhoneOS + + CFBundleInfoDictionaryVersion + 6.0 + CFBundleExecutable + sherpa_onnx + DTCompiler + com.apple.compilers.llvm.clang.1_0 + UIRequiredDeviceCapabilities + + arm64 + + MinimumOSVersion + 12.0 + CFBundleIdentifier + com.k2fsa.sherpa.onnx + UIDeviceFamily + + 1 + 2 + + CFBundleSignature + ???? + DTPlatformVersion + 17.0 + DTXcodeBuild + 15A507 + DTPlatformBuild + 21A326 + + +EOF +done + +rm -rf sherpa_onnx.xcframework +xcodebuild -create-xcframework \ + -framework ios-arm64/sherpa_onnx.framework \ + -framework ios-arm64_x86_64-simulator/sherpa_onnx.framework \ + -output sherpa_onnx.xcframework + +cd sherpa_onnx.xcframework +echo "PWD: $PWD" +ls -lh +echo "---" +ls -lh */* diff --git a/flutter-examples/README.md b/flutter-examples/README.md index b7ed66715..3bb6b52c5 100644 --- a/flutter-examples/README.md +++ b/flutter-examples/README.md @@ -136,14 +136,16 @@ flutter create --platforms ios ./ Connect your iPhone to the computer, and run `flutter devices`, which will print: ```bash -Found 3 connected devices: - iPhone (mobile) • 00008030-001064212E85802E • ios • iOS 16.3 20D47 - macOS (desktop) • macos • darwin-x64 • macOS 13.1 22C65 darwin-x64 - Chrome (web) • chrome • web-javascript • Google Chrome 126.0.6478.127 +Found 4 connected devices: + iPhone 14 (mobile) • 634110C4-168D-408F-A938-D7FC62222579 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-2 (simulator) + iPhone (mobile) • 00008030-001064212E85802E • ios • iOS 16.3 20D47 + macOS (desktop) • macos • darwin-x64 • macOS 13.1 22C65 darwin-x64 + Chrome (web) • chrome • web-javascript • Google Chrome 126.0.6478.127 No wireless devices were found. Run "flutter emulators" to list and start any available device emulators. +(E.g., flutter emulators --launch ios) If you expected another device to be detected, please run "flutter doctor" to diagnose potential issues. You may also try increasing the time to wait for connected devices with the "--device-timeout" flag. Visit https://flutter.dev/setup/ for troubleshooting tips. diff --git a/flutter-examples/tts/lib/model.dart b/flutter-examples/tts/lib/model.dart index 7a53934cc..16ada98c3 100644 --- a/flutter-examples/tts/lib/model.dart +++ b/flutter-examples/tts/lib/model.dart @@ -79,16 +79,17 @@ Future createOfflineTts() async { // Example 7 // https://github.com/k2-fsa/sherpa-onnx/releases/tag/tts-models // https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/vits-melo-tts-zh_en.tar.bz2 - modelDir = 'vits-melo-tts-zh_en'; - modelName = 'model.onnx'; - lexicon = 'lexicon.txt'; - dictDir = 'vits-melo-tts-zh_en/dict'; + // modelDir = 'vits-melo-tts-zh_en'; + // modelName = 'model.onnx'; + // lexicon = 'lexicon.txt'; + // dictDir = 'vits-melo-tts-zh_en/dict'; // ============================================================ // Please don't change the remaining part of this function // ============================================================ if (modelName == '') { - throw Exception('You are supposed to select a model by changing the code before you run the app'); + throw Exception( + 'You are supposed to select a model by changing the code before you run the app'); } final Directory directory = await getApplicationDocumentsDirectory(); diff --git a/flutter/sherpa_onnx/lib/sherpa_onnx.dart b/flutter/sherpa_onnx/lib/sherpa_onnx.dart index 9fcd2872f..b9fb7dd53 100644 --- a/flutter/sherpa_onnx/lib/sherpa_onnx.dart +++ b/flutter/sherpa_onnx/lib/sherpa_onnx.dart @@ -25,7 +25,7 @@ String? _path; // https://github.com/flutter/codelabs/blob/main/ffigen_codelab/step_05/lib/ffigen_app.dart // https://api.flutter.dev/flutter/dart-io/Platform-class.html final DynamicLibrary _dylib = () { - if (Platform.isMacOS || Platform.isIOS) { + if (Platform.isMacOS) { if (_path == null) { return DynamicLibrary.open('libsherpa-onnx-c-api.dylib'); } else { @@ -33,6 +33,14 @@ final DynamicLibrary _dylib = () { } } + if (Platform.isIOS) { + if (_path == null) { + return DynamicLibrary.open('sherpa_onnx.framework/sherpa_onnx'); + } else { + return DynamicLibrary.open('$_path/sherpa_onnx.framework/sherpa_onnx'); + } + } + if (Platform.isAndroid || Platform.isLinux) { if (_path == null) { return DynamicLibrary.open('libsherpa-onnx-c-api.so'); diff --git a/flutter/sherpa_onnx_ios/ios/sherpa_onnx_ios.podspec b/flutter/sherpa_onnx_ios/ios/sherpa_onnx_ios.podspec index e0e0a9769..032ca5147 100644 --- a/flutter/sherpa_onnx_ios/ios/sherpa_onnx_ios.podspec +++ b/flutter/sherpa_onnx_ios/ios/sherpa_onnx_ios.podspec @@ -23,7 +23,8 @@ A new Flutter FFI plugin project. s.source = { :path => '.' } s.dependency 'Flutter' s.platform = :ios, '12.0' - s.ios.vendored_libraries = '*.dylib', '*.a' + s.preserve_paths = 'sherpa_onnx.xcframework/**/*' + s.vendored_frameworks = 'sherpa_onnx.xcframework' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { diff --git a/new-release.sh b/new-release.sh index 48095178e..c070fa78e 100755 --- a/new-release.sh +++ b/new-release.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash +sed -i.bak 's/1\.10\.29/1\.10\.30/g' ./build-ios-shared.sh find flutter -name *.yaml -type f -exec sed -i.bak 's/1\.10\.29/1\.10\.30/g' {} \; find dart-api-examples -name *.yaml -type f -exec sed -i.bak 's/1\.10\.29/1\.10\.30/g' {} \; find flutter-examples -name *.yaml -type f -exec sed -i.bak 's/1\.10\.29/1\.10\.30/g' {} \;