Skip to content

[flutter_tools] support build-time plugins #112727

Description

@gaaclarke

Flutter has a defined interface for creating runtime plugins, we should also design a plugin interface that can be executed at build-time. These plugins would live on pub.dev and runtime plugins could have have dependencies on them.

We've talked about this in the past with respect to code generation. This proposal provides more generic hooks for Dart compilation or native compilation (linking in particular). And proposes they present themselves as packages in pub.dev.

Example Build-time plugins

  1. Pigeon - The code generator for Flutter interop. Right now you have to use it externally to generate the code, this could be integrated as a build-time plugin.
  2. Rust language support for plugins - This could install extra project templates and when executing build it can look for the presence of "rustc" and execute rust compilation, generating a library that can be linked in during the rest of the compilation.

Requirements

  1. Provide a location and scheme where generated / downloaded files can be cached
  2. Able to generate Dart code into the cache
  3. Adjust Dart package resolution so generated code can be imported
  4. Ability to generate native libraries in the cache
  5. Ability to adjust the linker flags in the project so linker can find those libraries
  6. The plugin should be sandboxed to only operate on specific inputs and outputs. The concern being that it could overcomplicate builds and the plugins could collide with one another.

Bonus objectives

  1. Plugins can add new templates to the command-line tool
  2. Plugins can add new flags to the the command-line tool

Non-goals

  1. Supporting languages with runtimes (go, c#, etc.) - The concern being a proliferation of runtime costs that collide and bog down the system.

Activity

  1. added
    toolAffects the "flutter" command-line tool. See also t: labels.
    c: proposalA detailed proposal for a change to Flutter
    on Sep 30, 2022
  2. stuartmorgan-g commented on Sep 30, 2022

    @stuartmorgan-g
    Contributor

    And proposes they present themselves as plugins.

    I'm not sure what this means; Flutter plugins are Dart packages that include native code that's built into the application. What you are proposing doesn't have that, so they aren't Flutter plugins. (They are also tool-install-level, not project-level, which is also a critical difference.) What does "present themselves as plugins" actually mean?

    (As I said in the other issue, I really think it would be helpful to pick a different term to use for this proposal. Using the same word for a totally unrelated concept as what we currently use it for within Flutter seems needlessly confusing to me. There are other terms, like "extension", that don't have the same established meaning within the Flutter domain.)

  3. gaaclarke commented on Sep 30, 2022

    @gaaclarke
    MemberAuthor

    Yea I'm open to alternative names. What I meant and what is important is:

    1. They are available on pub.dev
    2. They can be added in a pubspec.yaml as a dev_dependency of any flutter module.
  4. stuartmorgan-g commented on Sep 30, 2022

    @stuartmorgan-g
    Contributor

    It sounds like you meant "presents as a package" then.

  5. changed the title [-]Design a plugin interface for tool[/-] [+]Design a plugin interface for `tool`[/+] on Sep 30, 2022
  6. gaaclarke commented on Oct 1, 2022

    @gaaclarke
    MemberAuthor

    @stuartmorgan as per our discussion the other day I think you make a convincing argument against making it easier to support any language with runtime costs. I've added it a non-goal to the description. When the design in more detailed we can consider if it is something worth actively blocking (ex blocking libraries with the symbols to fork or create threads?).

  7. dcharkes commented on Oct 2, 2022

    @dcharkes
    Contributor

    cc @jonasfj on our idea of having Rust as a build_dependency: for Dart standalone packages that want to use the rust compiler in a build step.

    Ability to generate native libraries in the cache

    @jonasfj and I have been debating whether native tools (downloaded or locally built) should live in pub cache or in the .dart_tool of the root package.

    Which native artifact you end up with, could depend on package resolution. And a native-tool-package might get a different downloaded/built artifact if one if its dependencies gets resolved to a different version. However, this means the rust compiler would be downloaded for every project it is transitively used, which is undesirable.

    The alternative is that we mandate that native tools should not depend on any of the dependencies that their enclosing package lists. Then the rust compiler can live in the pub cache. (We would still get multiple versions of the rust_compiler package in the cache over time, so we probably also need to think about purging the pub cache.)

  8. gaaclarke commented on Oct 3, 2022

    @gaaclarke
    MemberAuthor

    on our idea of having Rust as a build_dependency: for Dart standalone packages that want to use the rust compiler in a build step.

    @dcharkes Is Dart planning on adding build_dependencies? Are you using Rust as the example to decide how that will work wrt caching artifacts?

    So, one thing I learned while doing my projects in Rust is that some packages have options that determine how they operate. For example, the sdl2 package has a feature that allows you to determine if the library for sdl2 is "bundled" or not. If you set it to true, it will download (and build?) the appropriate library for you into the cache, otherwise it will be up to you to provide the binary for sdl2. If we had a similar mechanism we could specify if we wanted to use the rustc on "$PATH" or download it.

    For what it's worth, here's how it would look in a Rust package:

    [dependencies.sdl2]
    version = "0.35"
    features = ["bundled"]
  9. gaaclarke commented on Oct 3, 2022

    @gaaclarke
    MemberAuthor

    By happenstance I was playing around with Rust this weekend and I saw that they've already implemented a similar feature to this for their package manager. Here's some notes about what they are doing:

    Cargo (Rust's package manager) has 3 classes of dependencies: dependencies, dev-dependencies, build-dependencies. The first 2 classes operate like Dart's, but the 3rd class , build-dependencies, don't exist in Dart and add packages that can modify the build process ( documentation ).

    Here is an example build-dependencies crate that does code generation for binding Rust and C++: cxx-build. It is a direct comparison to our Pigeon use-case.

    Also, related to the idea that a package could add command-line arguments to the flutter tool, Cargo has that ability too. Here is a package that adds a new command to Cargo, cargo-llvm-cov. In fact, all commands that cargo implements appear to be packages. The equivalent for Flutter would be if the flutter tool was modular and ever command (flutter build, flutter run, etc) was its own module.

  10. added
    P3Issues that are less important to the Flutter project
    triaged-toolTriaged by Flutter Tool team
    on Jul 18, 2023
  11. changed the title [-]Design a plugin interface for `tool`[/-] [+][flutter_tools] support build-time plugins[/+] on Jul 21, 2023
  12. Dynesshely commented on Jan 23, 2024

    @Dynesshely

    I expect this feature too.

    This feature means that developers can combine more actions with flutter build process such as changing version number before building.

  13. gaaclarke commented on Jan 23, 2024

    @gaaclarke
    MemberAuthor

    Another use case for this is the flutter engine team would like to have tools for engine development that we don't want to introduce to the mainline tool. For example, a command-line flag for forcing opengles rendering in impeller.

  14. matanlurey commented on Jul 11, 2025

    @matanlurey
    Contributor

    We don't plan to support something like this, though the upcoming Dart native assets/builders might help.

  15. gaaclarke commented on Jul 11, 2025

    @gaaclarke
    MemberAuthor

    We don't plan to support something like this

    @matanlurey The reason why we don't plan to support it is important to resolving this issue. If we don't have the bandwidth to support it, as an open source product I think it's valuable to still document the proposal and continue to be a place to guide discussion on it. We are potentially one customer away from having this feature. Closing the issue will cause the discussion to be locked.

    If we don't think the proposal has value, I would argue we know it does because the feature exists in other ecosystems and there are good concrete examples of it. If we think the proposal is antithetical to Flutter's design, it would be important to document that for design iteration or guiding future proposals.

    though the upcoming Dart native assets/builders might help

    Neither of those solve the needs listed in the description. I think builders could be part of the solution if it was better integrated into the flutter tooling.

  16. matanlurey commented on Jul 11, 2025

    @matanlurey
    Contributor

    Right, but the tools team isn't doing it, and it isn't prioritized elsewhere. Keeping this issue open indefinitely so that we continue to not do it is not helpful.

  17. gaaclarke commented on Jul 11, 2025

    @gaaclarke
    MemberAuthor

    Right, but the tools team isn't doing it, and it isn't prioritized elsewhere. Keeping this issue open indefinitely so that we continue to not do it is not helpful.

    Since this is an open source product, I would think having open issues that the core team isn't addressing is actually helpful. Contributors can't easily work on things that are actively being addressed. We can chat about it as a team at the next sync to figure out what's most helpful in this case.

  18. matanlurey commented on Jul 11, 2025

    @matanlurey
    Contributor

    We wouldn't accept a contributor proposal for this, it's a large complicated feature.

  19. dcharkes commented on Jul 14, 2025

    @dcharkes
    Contributor

    The use cases are described somewhat sparsely, so I'm not sure if I fully grasp them and the things we're working on would cover them.

    1. Pigeon - The code generator for Flutter interop. Right now you have to use it externally to generate the code, this could be integrated as a build-time plugin.

    We are considering adding a generic way to run code generators in Dart. Tracking bug:

    2. Rust language support for plugins - This could install extra project templates and when executing build it can look for the presence of "rustc" and execute rust compilation, generating a library that can be linked in during the rest of the compilation.

    The build hooks system enables bundling and bundling Rust libraries. Tracking bug:

    However, we do not have a Rust (or C) plugin interface for Flutter, so you cannot interact with the Flutter Plugin API.

    They can be added in a pubspec.yaml as a dev_dependency of any flutter module.

    Code generators can be dev dependencies provided the generated code is checked in.

    Code that produces binaries that are bundled/linked in the final application should not be dev dependencies. Assuming you have Dart code which interacts with your native code, you'd want to avoid version skew between the two.

    Is Dart planning on adding build_dependencies?

    Right now we're using normal dependencies to avoid version skew. However, if we have conflicting version constraints between a build-time dependency and a run-time dependency, we might want to go this direction. Tracking bug:

    If any of your use cases are covered by the above mentioned tracking bugs, please document your use case in the relevant bug.

  20. gaaclarke commented on Jul 14, 2025

    @gaaclarke
    MemberAuthor

    @dcharkes what do you mean by "Code generators can be dev dependencies provided the generated code is checked in."?

    The idea is that if a project wanted to to have pigeon code generation it would add a dev_dependency on pigeon. The generated code wouldn't necessarily need to be checked in since it can be regenerated.

  21. dcharkes commented on Jul 14, 2025

    @dcharkes
    Contributor

    @dcharkes what do you mean by "Code generators can be dev dependencies provided the generated code is checked in."?

    The idea is that if a project wanted to to have pigeon code generation it would add a dev_dependency on pigeon. The generated code wouldn't necessarily need to be checked in since it can be regenerated.

    It can only be a dev dependency if users of the package will never have to run code generation. Code generators might have external dependencies, and the generated code might not have those dependencies. (E.g. libclang to generate bindings for a dylib, but the generated code can just use dart:ffi to call functions.) So, the package developers need to run the code generators, and the package users don't.

    (An alternative design is to not check the code in. Then the dependencies must be normal dependencies or build dependencies. Otherwise the users of your package don't have the source of the generator after pub get. But, I believe checking in generated code is a better workflow after our experience with FFIgen and JNIgen in the last couple of years.)

  22. gaaclarke commented on Jul 14, 2025

    @gaaclarke
    MemberAuthor

    @dcharkes, I think I see. In that case we need a build_dependencies instead. Any dependencies of build_dependencies effectively becomes a build_dependencies. I was hoping we could avoid the 3rd designation. I think this is the path that Rust took too.

  23. github-actions commented on Jul 28, 2025

    @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.

  24. locked as resolved and limited conversation to collaborators on Jul 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projectc: proposalA detailed proposal for a change to Flutterteam-toolOwned by Flutter Tool teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-toolTriaged by Flutter Tool team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions