Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOS Failed to lookup symbol (dlsym(RTLD_DEFAULT, test_func): symbol not found) #897

Open
hustxiaoc opened this issue Apr 29, 2020 · 48 comments

Comments

@hustxiaoc
Copy link

It was ok in debug mode, but failed in release mode.

Failed to lookup symbol (dlsym(RTLD_DEFAULT, test_func): symbol not found)
#0      DynamicLibrary.lookup (dart:ffi-patch/ffi_dynamic_library_patch.dart:33)
@dcharkes
Copy link
Collaborator

@hustxiaoc Could you please provide more information? What version of Flutter are you using? And do you have a minimal reproduction?

@hustxiaoc
Copy link
Author

hustxiaoc commented Apr 29, 2020

Sure, I'll create a minimal demo project.
https://github.com/hustxiaoc/flutter_test_plugin

Flutter 1.18.0-6.0.pre • channel dev • https://github.com/flutter/flutter.git
Framework • revision 84c84fb249 (8 days ago) • 2020-04-20 21:35:01 -0400
Engine • revision 2bde4f0ae4
Tools • Dart 2.9.0 (build 2.9.0-1.0.dev a12c36dd97)

Thanks.

@hustxiaoc
Copy link
Author

Or you can just try this plugin, it has the same error. https://pub.dev/packages/dvote_native#-example-tab-

2020-04-30 14:08:52.473100+0800 Runner[75582:6665062] flutter: Invalid argument(s): Failed to lookup symbol (dlsym(RTLD_DEFAULT, generate_zk_proof): symbol not found)

@dcharkes
Copy link
Collaborator

Do the fixes mentioned dart-archive/ffi#39 (comment) work for you?

@vladimirdjokic76
Copy link

vladimirdjokic76 commented May 12, 2020

I am facing the exactly the same problem on IOS, but only in release mode and only with .DynamicLibrary.lookupFunction.
function DynamicLibrary.lookup works fine.

@vladimirdjokic76
Copy link

@hustxiaoc Did you manage to fix it ? Thanks!

@hustxiaoc
Copy link
Author

@vladimirdjokic76 It works fine in release mode after I rebuild the library, but the problem shows again in Archive mode.

@hustxiaoc
Copy link
Author

I'm going to use the old way, dart -> oc -> library.

@vladimirdjokic76
Copy link

Thanks @hustxiaoc 👍

@negator
Copy link

negator commented May 25, 2020

I ran into this issue recently as well, and was able to resolve it (after lots of trial/error). The long and the short of it is that Xcode performs aggressive dead code elimination, with no option for disabling it.

Following this medium article is necessary but not entirely sufficient. You must also ensure the functions are invoked from a place in code that cannot be removed via dead code analysis (e.g. at the end of the application:didFinishLaunchingWithOptions:).

Something like:

override func application(...) {
        ...
       dummyMethodToEnforceBundling()
       return super.application(...)
}

Not sure if the linker was updated after the writing of the article to be more aggressive.

Additionally I had to disable code optimization in the Swift Compiler:
Screen Shot 2020-05-25 at 12 24 42 PM

@hustxiaoc
Copy link
Author

@negator Great work , I'll try it.

@hustxiaoc
Copy link
Author

@negator I still got the issue after turning off Optimization

@negator
Copy link

negator commented Jun 3, 2020

@hustxiaoc looking at your test project it seems you are only calling the get_seed() function:

https://github.com/hustxiaoc/flutter_test_plugin/blob/b07a4315a85157c8331042168089906679f9498d/ios/Classes/SwiftVoltThresholdPlugin.swift#L15-L17

But I noticed many more functions in the header file.

In my project I have 3 functions, that I explicitly invoke in dummy functions. After disabling optimizations and creating an archive, I can see the functions in my archive using nm -g ....

nm -g ~/Library/Developer/Xcode/Archives/.../Runner.xcarchive/Products/Applications/Runner.app/Runner

I imagine the binary you would need to inspect would be something like:

nm -g ~/.../Runner.app/Frameworks/Volt.framework/Volt

Do you at least see the get_seed() function?

Edit: For cocoapods, you might need to disable whole-module-optimization. This SO answer seems to work: https://stackoverflow.com/questions/46722323/project-pods-turn-on-whole-module-optimization/48550610#48550610

@hustxiaoc
Copy link
Author

Will disable code optimization have a significant impact on the performance and app size?

@negator
Copy link

negator commented Jun 4, 2020

I don’t believe so, since flutter apps do not contain much swift code, but I’m not 100% sure.

@AnisovAleksey
Copy link

Disable optimizations not work because symbols are removed (or hidden) after export the archive. So main problem in the export. Issue with optimization you can fix by adding attributes to your function
extern "C" __attribute__((visibility("default"))) __attribute__((used))

extern "C" needed only in .cpp files

My current workaround: Build library as framework and I load it as DynamicLibrary.open("storage.framework/storage");
but here you have one disadvantage - all dependencies will be linked in runtime, so app size will grow

@embedur-sarathis
Copy link

I am also facing the same issue. works for debug mode, but the issues on the release mode

@awazgyawali
Copy link

Has anybody managed to fix this? Nothing seems to work. Extremely frustrating to see that it works on debug/release but on in the archive.

@hustxiaoc
Copy link
Author

hustxiaoc commented Jun 11, 2020

@awazgyawali You can try flutter channel for now, which is letting object c call that function instead of dart. it works for me.

@xuchaoqian
Copy link

xuchaoqian commented Jun 13, 2020

I figured out a workaround, inspired by the article refered by @dcharkes: using-ffi-on-flutter-plugins-to-run-native-rust-code

  1. Make a fat static c++ lib: xyz.a. // It's easy to do this with ios-cmake

  2. Declare c-compatible function signatures in XxxPlugin.h, and use them in SwiftXxxPlugin.swift by a dummy method.

  3. Copy xyz.a to ios directory alongside with xxx.podspec.

  4. Add the following lines to xxx.podspec:

  s.public_header_files = 'Classes/**/*.h'
  s.vendored_libraries = "xyz.a"
  s.pod_target_xcconfig = { 
    #...other settings...
    'OTHER_LDFLAGS' => '-lxyz'
  }
  1. cd Podfile directroy, then run pod install.

@AnisovAleksey
Copy link

@xuchaoqian is this working for you? did you tested it in the Test Flight?

@xuchaoqian
Copy link

@AnisovAleksey

It works on the real phone and the simulator. Not test it in the Test Flight yet.

BTW., I edited my earlier comment to add step 2.

@vladimirdjokic76
Copy link

vladimirdjokic76 commented Jun 17, 2020 via email

@xuchaoqian
Copy link

xuchaoqian commented Jun 19, 2020

@AnisovAleksey
It works in debug, release, archive modes.

@dcharkes
But I found a very weird thing. Every mode works fine if the plugin language is built in swfit, BUT it only works in debug mode after switching the plugin language to objective-c, and throw error: failed to lookup symbol. It seems that the archived IPA doesn't bundle the xxx.framework file for objective-c plugin.

@xuchaoqian
Copy link

@AnisovAleksey

I have tested my app in TestFlight. It works fine.

@shawnclovie
Copy link

@vladimirdjokic76
It works for me - app project dependence git repo that contains C static lib.
C Function that called with dart:ffi was be stripped.

@bitsydarel
Copy link

With latest flutter, was adding a universal static library but dart can't see it but iOS can see the symbol.

Followed all the directive from https://flutter.dev/docs/development/platform-integration/c-interop#ios-symbols-stripped

@bitsydarel
Copy link

Header and universal static library are added

Capture d’écran 2021-05-20 à 16 46 15

@bitsydarel
Copy link

Strip style set to non-global

Capture d’écran 2021-05-20 à 16 47 29

@bitsydarel
Copy link

Even added the attribute about visibility

Capture d’écran 2021-05-20 à 16 48 42

@bitsydarel
Copy link

It's not working even debug build on simulator

Capture d’écran 2021-05-20 à 16 51 06

@bitsydarel
Copy link

Even the iOS swift app delegate can see and run it without problem

Capture d’écran 2021-05-20 à 17 07 34

@bitsydarel
Copy link

bitsydarel commented May 20, 2021

the universal static library support all the cpu

Capture d’écran 2021-05-20 à 17 09 18

@bitsydarel
Copy link

even create a test c file
Capture d’écran 2021-05-20 à 17 29 58

added pseudo code that internally call the library function

Capture d’écran 2021-05-20 à 17 31 21

Capture d’écran 2021-05-20 à 17 31 44

Capture d’écran 2021-05-20 à 17 35 53

The number "3" is successfully printed in the console so the FPDF_DestroyLibrary symbol is definetly not stripped.
Capture d’écran 2021-05-20 à 17 35 15

But still dart can't see it...

Capture d’écran 2021-05-20 à 17 36 37

@bitsydarel
Copy link

@dcharkes should i file another bug or the provided Information are enough ?

@ghost
Copy link

ghost commented Jul 4, 2021

Hi @bitsydarel, I'm also trying to get libpdfium to work on iOS and facing the same problem. Did you get it to run?

@buehler
Copy link

buehler commented Oct 22, 2021

@RalphBergmannKMB Did you manage to run libpdfium.a in a flutter ios / macos project? I'm currently having the same issues :-(

@ghost
Copy link

ghost commented Oct 22, 2021

@buehler yes, but the iOS part was hard. I'm currently on holiday on Crete and can't help you more, but my plan is to release a Flutter plugin for PDFium.

In the end, I created my own version of this *.a file for iOS.

@buehler
Copy link

buehler commented Oct 22, 2021

Hey @RalphBergmannKMB thanks for the answer, I just had a breakthrough! I'm currently writing a plugin for PDFium in flutter since we need it for a project at our company.

I'll keep you posted.

@buehler
Copy link

buehler commented Oct 22, 2021

Hey @RalphBergmannKMB

I managed to run it on all platforms. MacOS and iOS need help (from c++) to export the symbols.

If you're interested, the plugin is in an alpha (non-published on pub.dev) state on https://github.com/smartive/flutter_pdfium.

We will improve the functionality as we develop the project and then we're going to publish it on pub.dev.

@ghost
Copy link

ghost commented Oct 22, 2021

I did it in a different way.

I used the code from https://github.com/paulo-coutinho/pdfium-lib but changed the way the *.a file is generated for iOS (I can't remember exactly, just wait until I'm back home).

Then I added those *.a and all the *.h files to the XCode project. And called a function from each *.h file, otherwise, XCode will remove the file.

Finally, I generated the mappings for Dart (https://pub.dev/packages/ffigen) and everything was ready.

I also tried to generate a Framework, but failed with singing issues :(

@ghost
Copy link

ghost commented Oct 22, 2021

But the result is absolutely amazing. We use PDFium to render PDF pages as bitmaps and display them in a Flutter app on Android and iOS. The UI doesn't freeze or something like that when you scroll from one page to another. It's super fast.

@pedromassango
Copy link

HI All, This is my solution, it also works in Test Flight... Select Target Runner -> Build Settings -> Strip Style -> change from "All Symbols" to "Non-Global Symbols" this is the app :) Screenshot 2020-06-17 at 20 43 52

This saved my week ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests