Skip to content

[WIP] Compile plugins as .aars, not subprojects - #29460

Closed
mklim wants to merge 1 commit into
flutter:masterfrom
mklim:plugin_aar_wip
Closed

mklim wants to merge 1 commit into
flutter:masterfrom
mklim:plugin_aar_wip

Conversation

@mklim

@mklim mklim commented Mar 15, 2019

Copy link
Copy Markdown
Contributor

Description

This is a very rough proof of concept. It functions on simple app cases
given manual tweaking.

It basically works by adding extra logic to gradle.dart before the APK
of an app is compiled.

  • Gets a flat list of all transitive Flutter plugin dependencies.
  • Runs an init-script on each one to add the local flutter-jar as a
    compileOnly dependency to it.
  • Compiles each dependency as an AAR.
  • Uses the plugin AARs as dependencies for compiling the APK in the
    flutter.gradle plugin.

There's two big blockers on this still that I'm currently aware of.

  1. This requires apps to manually remove the subprojects declarations
    from android/build.gradle and the plugins.each loop from
    android/settings.gradle. It's both breaking and requiring manual
    intervention on the app side to work.
  2. Transitive gradle dependencies within our Flutter plugins cause
    crashes at runtime, since the inner deps aren't being included in the
    aar. To see a failing case, use this code with a sample app requiring
    firebase_auth. At runtime it will crash because the firebase
    library isn't found.

Related Issues

#29328

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes tests for all changed/updated/fixed behaviors (See Test Coverage).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

(This is a WIP. It shouldn't be merged until there's tests, it's no longer a breaking change, etc.)

This is a very rough proof of concept. It functions on simple app cases
given manual tweaking.

It basically works by adding extra logic to `gradle.dart` before the APK
of an app is compiled.

- Get a flat list of all transitive Flutter plugin dependencies.
- Run an `init-script` on each one to add the local `flutter-jar` as a
  `compileOnly` dependency to it.
- Compile each dependency as an AAR.
- Use the plugin AARs as dependencies for compiling the APK in the
  `flutter.gradle` plugin.

There's two big blockers on this still that I'm currently aware of.

1. This requires apps to manually remove the `subprojects` declarations
   from `android/build.gradle` and the `plugins.each` loop from
   `android/settings.gradle`. It's both breaking and requiring manual
   intervention on the app side to work.
2. Transitive gradle dependencies within our Flutter plugins cause
   crashes at runtime, since the inner deps aren't being included in the
   aar. To see a failing case, use this code with a sample app requiring
   `firebase_auth`. At runtime it will crash because the firebase
   library isn't found.
} else {
project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
// TODO(mklim): This replacement currently requires apps to remove their
// `subproject {}` declarations or else break. If we're going to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do that programatically in gradle.dart?

// instead.
plugins.each { name, path ->
def String artifactDir = Paths.get(path, 'android', 'build', 'outputs', 'aar').toString();
def Set<File> aars = project.fileTree(dir: artifactDir, include: '*.aar').getFiles();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about just compile project.fileTree(dir: artifactDir, include: '*.aar')?

And is compile right here or api?


// TODO(mklim): Fix the obvious bugs.
// - Do we need logic for passing along build architecture, local engine, etc?
// - Make this smart enough to not rebuild the plugin every time?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't gradle take care of that?

I'd time how long that takes, and if it's more than a few ms then we should just be able to check for the build output ourselves.

}

// TODO(mklim): Fix the obvious bugs.
// - Do we need logic for passing along build architecture, local engine, etc?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we really should support that.

That said, I'm not sure the plugins actually need libflutter.so - while it's probably possible for some plugin to try to use JNI on that, I think it's probably very uncommon and we're safer to break that (totally a gut sense though, I have no hard data). This is where it'd be nice to just have a set of interfaces the engine exposes in a lighter weight JAR that plugins could use.

bool isBuildingBundle,
) async {
// TODO(mklim): This is breaking, should fix the incompatibility or only case
// into this for migrated apps (_buildGradleProjectV3)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we probably want this to be considered a new type of project, and we should offer some kind of auto-migration for it (e.g. removing any flutter/plugin related subproject nodes).

@dnfield

dnfield commented Mar 18, 2019 •

Copy link
Copy Markdown
Contributor

I suspect we should look to update the logic that adds new plugin projects to the main project so it no longer does that. I just remembered that's done by directly reading the .flutter-plugins file from the Gradle script.

/cc @jonahwilliams @amirh @matthew-carroll

@goderbauer goderbauer added the tool Affects the "flutter" command-line tool. See also t: labels. label Mar 18, 2019
@dnfield dnfield mentioned this pull request Mar 23, 2019
7 of 10 tasks
@dnfield

dnfield commented Mar 23, 2019

Copy link
Copy Markdown
Contributor

This work is being continued in #29849

@dnfield dnfield closed this Mar 23, 2019
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Aug 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants