Repository navigation
Consider using cocoapod's static_framework for flutter plugins that require static libraries #15031
Description
Currently, developing a flutter project that includes swift can be a bit of a pain when including various plugins - in particular Firebase messaging is the one I've had trouble with.
This is more or less the structure of (the iOS part) of my app:
App
↳ swift source
↳ firebase messaging
↳ objc source
↳ various static libraries included in sub-pods etc
↳ Qr code plugin
↳ objc source (originally swift but had issues with that)
↳ Google MobileVision (objc source)
↳ various static libraries included as sub-pods etc
↳ Swift plugin(s) (source, no libraries)
↳ Objc plugin(s) (source, no libraries)
Because of my usage of swift, use_frameworks! is set in my Podfile.
What's happening when I build currently is that the various libraries are each being build as dynamic frameworks i.e. Firebase, qr code pluign, swift plugin(s), objc plugin(s). Then it appears that the static libraries are being linked properly when running on the device, but when I do an achive build, upload to testflight, and run on the device it fails to run. As far as I can tell, the static libraries are being linked into the main app rather than the dynamic libraries where they're required (i.e. firebase), although I may be misdiagnosing that as I'm not an expert by any means.
I do have an example project but the issue is that to actually reproduce the issue you have to archive it, upload to app store, and use testflight etc to run it; I sometimes saw issues with release builds after running flutter build ios --release but not always for some reason.
This is the error though, although not all that detailed as it's hard to debug an app from testflight:
Termination Description: DYLD, Symbol not found: _OBJC_CLASS_$_FIRApp | Referenced from: /private/var/containers/Bundle/Application/A9C35A12-B9A3-4F0C-A508-C0554CA2843A/Runner.app/Frameworks/firebase_messaging.framework/firebase_messaging | Expected in: flat namespace | in /private/var/containers/Bundle/Application/A9C35A12-B9A3-4F0C-A508-C0554CA2843A/Runner.app/Frameworks/firebase_messaging.framework/firebase_messaging
What I'd like to propose is some way of forcing cocoapods to do what is needed (i.e. link the libraries into the right place). I tried various things including manually specifying the name of the dependency libraries in the podspec of the framework including them, which did link them into the dynamic framework but then resulted in duplicate definitions of classes and all sorts of other fun issues. I'm sure it's possible but that I just couldn't figure it out.
However, cocoapods does have a relatively new option introduced in 1.4.0 - static_framework. To use it, you simply specify static_framework = true in the podspec of the framework which includes a static library, and the framework will compile statically including the dependent libraries (it should also theoretically remove the requirement for the `s.pod_target_xcconfig = { 'FRAMEWORK_SEARCH_PATHS .... OTHER_LDFLAGS ...' currently in firebase_messaging.podspec (and I assume the other plugins as well).
There are a couple of caveats to this - the first being that CocoaPods currently has a bug that means public_headers which are symlinked from outside the project (as flutter has recently started doing) get included as Project Headers instead of Public Headers at least for when static_framework is used (it might pop up other places too). I've submitted a PR to cocoapods to resolve that but still need to write some unit tests for them (yay, I get to learn more ruby 😒) (edit: it has now been accepted into master but no idea about release date). Also, FYI - the trunk of cocoapods seems to not work with flutter (I don't currently have time to track down why not) so the next release that includes this fix could theoretically fail on that. It will also require people to update to cocoapods 1.4.0 if they haven't already.
Sorry for the long-windedness, but I think this is something worth considering especially now that more developers will hopefully be coming on board since the beta release - and I'd bet that a lot of them will want to use both swift and the various plugins flutter provides for firebase etc.
Activity
mit-mit commentedon Mar 1, 2018
cc @szakarias @mravn-google
wkethman commentedon Apr 10, 2018
Having same issue it appears, happy to help if I can
Were you able to solve?
mravn-google commentedon Apr 10, 2018
@rmtmckenzie Thanks for taking the time to write this up. Cocoapods 1.5.0 is out, so our focus is to make sure Flutter project templates work with that. We do have the option to require a particular version of Cocoapods, as part of the
flutter doctorchecks, if necessary.It is possible that 1.5.1 is needed (cf. CocoaPods/CocoaPods#7601).
@rmtmckenzie @wkethman If anybody has a combination of Flutter plugin's
.podspecand Flutter project'sPodfilethat works with static libs and Swift, we'd very much like to see them.wkethman commentedon Apr 10, 2018
Unfortunately, I do not have a combination that works, just for reference, below is the crash log from Apple for the issue and again this canNOT be reproduced by running in debug locally - the application for iOS works as expected under that scenario.
wkethman commentedon Apr 10, 2018
I have also tried updated cocoapods and had other failures crop up on build so backed down since I am issuing updates on the Android side of the house
wkethman commentedon Apr 10, 2018
I went ahead and updated Cocoapods to 1.5.0 (then deleted ios/pods and Podfile.lock and rebuilt with pods install) and here is the error:
In file included from /Users/wkethman/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.4.1/ios/Classes/SharedPreferencesPlugin.m:5:
/Users/wkethman/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.4.1/ios/Classes/SharedPreferencesPlugin.h:5:9: fatal error: 'Flutter/Flutter.h' file not found
#import <Flutter/Flutter.h>
^~~~~~~~~~~~~~~~~~~
1 error generated.
When I downgrade back to Cocoapods 1.4 this error goes away and the application builds and functions appropriately for iOS. I did just notice this error when running the application this time around:
The default Firebase app has not yet been configured. Add
[FIRApp configure];(FirebaseApp.configure()in Swift) to your application initialization. Read more: https://goo.gl/ctyzm8.This does not cause the application to fail, nor does it impact functionality.
Hope this helps.
rmtmckenzie commentedon Apr 10, 2018
I have this all working in my local environment, but I've done something a bit funky just to get it to work. I added this fix to solve the problem that I was having, but I did at the time notice that the time that something else in their master broke the build in the way described by @wkethman -
Flutter/flutter.h not found(I did mention that in the FYI in the second to last paragraph of my original post but that was a big block of text). As I have been (and am still to some degree) in a time crunch, I didn't ultimately track it down and am instead just using cocoapods 1.4 with the particular fix added =/ .So if you're trying to test this with cocoapods 1.5 the new issue will probably need resolving, and if you're testing with 1.4 you'll run into the same issue I did. I've pushed the branch I'm using to github so you can test it out if that would be helpful (which does work with use_frameworks! and static_framework: https://github.com/rmtmckenzie/cocoapods/tree/symlink-1.4.
Podfile (with a couple of lines removed that are just internal to my project)
And one of the static pods (from here). The GoogeMobileVision/BarcodeDetector dependency was the issue as it includes a static library.
And the modifications I had done to firebase_messaging's podspec locally before the various workarounds were implemented (I can't find the exact commit any more but it basically force-added the header files) - after the workaround was implemented I was able to go back to using firebase from pub without anything special.
mravn-google commentedon Apr 10, 2018
@rmtmckenzie Thanks a lot. With Flutter master, Cocoapods 1.5.0, and a
-i swiftFlutter project, it works for mes.static_framework = truein the podspec of the included plugin (firebase_messaging)FRAMEWORK_SEARCH_PATHS/OTHER_LDFLAGSworkaround in the plugin's podspecverify_no_static_framework_transitive_dependenciesworkaround in the project'sPodfilefile.settings = { 'ATTRIBUTES' => ['Public'] }workaround in the project'sPodfileIt would be great to get rid of all these workarounds.
wkethman commentedon Apr 10, 2018
Wow - so unfortunately I am just a surgical resident and coding is a hobby
These workarounds are just too complicated for me to implement - anyone willing to jump on the phone or provide more explicit steps (I know they may seem quite explicit for all of you)?
Otherwise I might just have to wait.
I am using Cocoapods 1.4.0, Firestore 0.5.0
Flutter (Channel master, v0.2.11-pre.7, on Mac OS X 10.13.4 17E199, locale en-US)
• Flutter version 0.2.11-pre.7 at /Users/wkethman/flutter
• Framework revision da4e06b (24 hours ago), 2018-04-10 01:02:24 +0300
• Engine revision d2b69fe
• Dart version 2.0.0-dev.46.0.flutter-09e1766e6c
[✓] Android toolchain - develop for Android devices (Android SDK 26.0.2)
• Android SDK at /Users/wkethman/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-27, build-tools 26.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
• All Android licenses accepted.
[✓] iOS toolchain - develop for iOS devices (Xcode 9.3)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 9.3, Build version 9E145
• ios-deploy 1.9.2
• CocoaPods version 1.4.0
[✓] Android Studio (version 3.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 23.1.2
• Dart plugin version 173.4700
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
mravn-google commentedon Apr 10, 2018
@wkethman You should upgrade Cocoapods to 1.5.0, then wait for flutter-team-archive/plugins#483 to land.
wkethman commentedon Apr 10, 2018
Ok thank you @mravn-google, I will wait to upgrade until the fix lands (any timing on that?)
rmtmckenzie commentedon Apr 11, 2018
Sorry @wkethman - what I was explaining was more to help out the flutter team on fixing the issue than to help someone else get going with it =\ although it was quite a pain for me to figure out the first time so don't feel too bad!
If you can't wait for the fix (although I don't imagine it will actually be all that long until they do get it into master + alpha plugins at least), the workaround is actually simpler than my rambles made it sound.
The first step is to fix the cocoapods bug. I could give you a patch file but it's almost easier to make changes to the cocoapods 1.4 ruby files directly - if you can find where it's installed, all you have to do is find
<cocoapods install directory>/lib/cocoapods/sandbox/path_list.rb(which will depend on how you installed it) and make this change:And the second step is to comment out the workaround in any podspec that depends on a static library, and instead add
s.static_framework=trueas I did in firebase_messaging's podspec in the last codeblock in my last comment. The way I did this is to clone the repositories directly for any relevant dependencies, specify the path to them in the pubspec'sdependency_overridessection, and make the changes there.But hopefully it won't come to that as the flutter team tends to be very responsive to things like this. I'm always amazed how fast stuff gets fixed compared to other frameworks I've used =)
wkethman commentedon Apr 12, 2018
Thank you for trying to help me - I will just wait for the updates to post
Just glad I could help get this figured out
mravn-google commentedon Apr 12, 2018
Fixes have landed on Flutter master and flutter/plugins repo, see #16036 (comment)
wkethman commentedon Apr 13, 2018
Just as an update @mravn-google and for anyone else having this issue:
flutter doctor -v
[✓] Flutter (Channel master, v0.2.12-pre.27, on Mac OS X 10.13.4 17E199, locale en-US)
• Flutter version 0.2.12-pre.27 at /Users/wkethman/flutter
• Framework revision e0cd42e (66 minutes ago), 2018-04-12 16:28:01 -0700
• Engine revision 76cb311
• Dart version 2.0.0-dev.47.0.flutter-f76dad0adc
[✓] Android toolchain - develop for Android devices (Android SDK 26.0.2)
• Android SDK at /Users/wkethman/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-27, build-tools 26.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
• All Android licenses accepted.
[✓] iOS toolchain - develop for iOS devices (Xcode 9.3)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 9.3, Build version 9E145
• ios-deploy 1.9.2
• CocoaPods version 1.5.0
[✓] Android Studio (version 3.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 23.2.2
• Dart plugin version 173.4700
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
I followed these instructions:
Application ran without errors for iOS (and for Android although this was never an issue) - which was previously an issue with Cocoapods 1.5.0
Uploading to iOS now so will let you know if this fixed the greater problem (hoping Cocoapods 1.5.0 is the trick)...will update shortly
Update
It worked on Testflight! Stay tuned
Update
It worked after deployment to iOS store - thank you everyone for your help!
mravn-google commentedon Apr 13, 2018
Thanks a lot, @wkethman. This is very helpful!
longhoang2984 commentedon Aug 23, 2018
dose not work for me 😶
rmtmckenzie commentedon Aug 23, 2018
@longhoang2984 What doesn't work for you, what version of flutter are you using, and what are you trying to do? In any case, this bug has since been fixed and if you've having a problem related to static frameworks you're probably better off opening a new bug rather than commenting on one that has been closed for several months.
github-actions commentedon Aug 15, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.