Skip to content

Implement dartPluginClass support for plugins #52267

Description

@stuartmorgan-g

The federated plugin design describes having a dartPluginClass for each platform, allowing the registration of Dart plugin implementation details on a per-platform basis. Currently actually doing that is only possible on Web (AFAICT).

This is currently blocking implementation of path_provider and shared_preferences on Linux, where there's no need to use anything but pure Dart, because there's no way to bind the implementation to the interface package. (This is would also be very useful in conjunction with FFI; e.g., the Windows path_provider implementation could easily be Dart + FFI to a couple of system calls, significantly reducing the amount of code involved.)

Greg and I looked at this a little bit at the end of last week. Adding the auto-generation of a Dart registrant is simple, but we got stuck on actually injecting the call to that registrant in a way that doesn't break existing functionality (in particular, passing an arbitrary start point to the embedder API). I'm not sure if there was already a plan/design in place to address that.

/cc @amirh

Activity

  1. added
    toolAffects the "flutter" command-line tool. See also t: labels.
    platform-macosBuilding on or for macOS specifically
    platform-windowsBuilding on or for Windows specifically
    p: toolingAffects the flutter_plugin_tools package
    platform-linuxBuilding on or for Linux specifically
    on Mar 9, 2020
  2. stuartmorgan-g commented on Mar 9, 2020

    @stuartmorgan-g
    ContributorAuthor

    /cc @gspencergoog as well.

    (I've added the desktop platform labels because I know we'll want it there, but presumably we'll want this on iOS and Android too).

  3. amirh commented on Mar 9, 2020

    @amirh
    Contributor

    I was discussing this with @jonahwilliams awhile ago, one alternative we were considering was to generate a main function that wraps the app's main (and also invokes plugin activation), and use the generated main as the entry point.

    Also note that there's some more discussion on how to bake this codegen in the tool in this follow-up doc.

    One thing I'd like to bring up for consideration again (tomorrow's meeting is a good chance) is whether to trade ease of use of unendorsed plugins with infra simplicity (by making it the app-facing package's responsibility to activate endorsed implementations).

  4. stuartmorgan-g commented on Mar 9, 2020

    @stuartmorgan-g
    ContributorAuthor

    one alternative we were considering was to generate a main function that wraps the app's main (and also invokes plugin activation), and use the generated main as the entry point.

    How? I considered that, but couldn't see how that would work in practice. Taking macOS as a concrete example, if my native code passes any non-default entryPoint when starting the engine how would we wrap it? The generated Dart wrapper needs to know what entry point to call into, but the tooling doesn't know what the native code is going to pass.

  5. amirh commented on Mar 10, 2020

    @amirh
    Contributor

    I didn't realize we let embeddings set the entry point. 🤔
    @jonahwilliams are we doing something like that for web? do we allow a custom entry point there?

    I guess if we want to keep going up this mountain we may propose VM support for an additional entry point. Though I'd really love a simpler solution.

    [Just brainstorming] I'm not familiar with the VM bindings, do you know if it's possible for the engine to initiate invocation of a Dart method after runnning the initial entry point? (if that is possible I can imagine us adding code in widgets binding initialization to wait for the engine to indicate that plugins have been activated, and the engine will indicate that after invoking the generated registrant)

  6. jonahwilliams commented on Mar 10, 2020

    @jonahwilliams
    Contributor

    are we doing something like that for web

    No, the web doesn't really have an embedding so its not configurable.

  7. stuartmorgan-g commented on Mar 10, 2020

    @stuartmorgan-g
    ContributorAuthor

    @chinmaygarde and/or @jason-simmons Do you know offhand the answer to the question above about whether we are able to invoke arbitrary Dart code from the embedding? I.e., could the native embedding code start up the engine, then immediately call some known function?

  8. removed
    p: toolingAffects the flutter_plugin_tools package
    on Apr 28, 2020
  9. stuartmorgan-g commented on Jun 4, 2020

    @stuartmorgan-g
    ContributorAuthor

    there's no way to bind the implementation to the interface package

    Capturing from various discussions, the short-term solution to this problem is to directly register the dart-only implementation from the front-end package (example).

    This has the downside that it requires an override option for registering a different implementation, meaning that for instance tests that want to use a mock must explicitly disable the platform registration (example).

  10. 62 remaining items

  11. stuartmorgan-g commented on Apr 23, 2021

    @stuartmorgan-g
    ContributorAuthor

    Leaving open for mobile.

  12. xster commented on Sep 16, 2021

    @xster
    Member

    Since there weren't much additional discussions after the register plugin entrypoint wrapping the real entrypoint proposal, I'm assuming that's rough direction? Is there a doc with more details on the proposal?

    It's not too clear to me who calls that entrypoint. The embedding has ways of specifying an entrypoint when running the engine so it's a runtime problem rather than a compile time problem. How do we, at that point, switch out the real entrypoint the user called and wrap this plugin registration call around it?

  13. stuartmorgan-g commented on Sep 17, 2021

    @stuartmorgan-g
    ContributorAuthor

    Is there a doc with more details on the proposal?

    @blasten Is there a doc for what you implemented?

    It's not too clear to me who calls that entrypoint. The embedding has ways of specifying an entrypoint when running the engine so it's a runtime problem rather than a compile time problem. How do we, at that point, switch out the real entrypoint the user called and wrap this plugin registration call around it?

    I wasn't involved in the reviews; I assumed that problem had been resolved since it was explicitly discussed several times above. As I've tried to extend it to mobile though, and found that it breaks flutter test, it seems to me like that may not actually be the case.

  14. blasten commented on Sep 17, 2021

    @blasten

    There's no doc about the implementation by itself, but I can summarize it:

    The engine (C++) calls the Dart plugin registrant: https://github.com/flutter/flutter/pull/87991/files#diff-68361f6fc9aafa5fa7de042eec4603dd4f321eb783a00edd57780ef78c1094bbR709. The only requirement is to define a top-level _PluginRegistrant class with a static method register(). Each should have @pragma('vm:entry-point').

    Wrapping main.dart was required because the Dart compiler had no other way to import a generated file from an arbitrary package that isn't imported by the app's dependency tree.

    flutter test should work fine. @stuartmorgan please file an issue with repro steps if that isn't the case. flutter test should set the set dart entrypoint anyways.

    I'm aware that the Android embedding allows to use an arbitrary entrypoint string. I think this is supported, although not tested. Since the engine only expects _PluginRegistrant; it doesn't really matter if it's defined in main.dart or foo.dart, it only matters that it's defined. @xster

  15. stuartmorgan-g commented on Sep 17, 2021

    @stuartmorgan-g
    ContributorAuthor

    flutter test should work fine. @stuartmorgan please file an issue with repro steps if that isn't the case.

    It doesn't, as I said here: #87991 (comment). See also #88632 and #88794

  16. blasten commented on Sep 17, 2021

    @blasten

    I see, sorry.

    The fix seems to be to regenerate the generated entrypoint here using generateMainDartWithPluginRegistrant.

    I thought flutter test used the build system used elsewhere, but it doesn't seem like.

  17. stuartmorgan-g commented on Sep 17, 2021

    @stuartmorgan-g
    ContributorAuthor

    The fix seems to be to regenerate the generated entrypoint here using generateMainDartWithPluginRegistrant.

    Thanks, I'll take a look at that. I hadn't had time yet to try to trace through everything to figure out where flutter test builds were happening.

    The part that I'm still confused about though is: why is flutter test capable of overriding the original main, but not of overriding the wrapper main in generated_main.dart? Shouldn't that work the same way it used to? (And what is that way?)

  18. stuartmorgan-g commented on Sep 17, 2021

    @stuartmorgan-g
    ContributorAuthor

    That does appear to work, but I'd like to make sure I understand
    a) why we need it, and
    b) if we should be generating generated_main.dart somewhere else, because having it be a persistent file that points to a temp file that doesn't outlive the flutter test run seems very questionable.

  19. blasten commented on Sep 17, 2021

    @blasten

    Discussed offline. The fix is #90288

  20. github-actions commented on Oct 16, 2021

    @github-actions

    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 -v and a minimal reproduction of the issue.

  21. locked as resolved and limited conversation to collaborators on Oct 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

P1High-priority issues at the top of the work lista: desktopRunning on desktopcustomer: googleVarious Google teamsplatform-androidAndroid applications specificallyplatform-iosiOS applications specificallyplatform-linuxBuilding on or for Linux specificallyplatform-macosBuilding on or for macOS specificallyplatform-windowsBuilding on or for Windows specificallytoolAffects the "flutter" command-line tool. See also t: labels.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions