-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Refactor gradle.dart #43479
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
Refactor gradle.dart #43479
Conversation
41da3d2 to
90c55fe
Compare
packages/flutter_tools/test/general.shard/android/gradle_errors_test.dart
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the status of this part of the comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test was moved to gradle_utils_test.dart and it now checks for the exact exception message.
packages/flutter_tools/test/general.shard/android/gradle_test.dart
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about ⚠ ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried. Unfortunately, it doesn't render on PowerShell/cmd.exe. We could detect that or leave as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like AndroidBuilder is mostly just a trivial wrapper around buildGradleAar and buildGradleApp now. Can we remove the entire file? (Maybe in a follow-up PR.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. I filed #43863. Originally this was needed to test the build commands because the current build process is messy and requires mocking too many files/process calls, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be cleaner if flutter was always called with an argument that did that, rather than relying on the environment variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. When the tool calls Gradle, it doesn't log analytics. However, in add2app scenarios, when a developer calls Gradle directly (from Android Studio, for example), it's preferred to log the calls to the tool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should much of the contents of gradle.dart also be in a GradeUtils-like class? (maybe GradleUtils itself?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. I added this as TODO
6fe8aaf to
16246b4
Compare
16246b4 to
a86a1fd
Compare
82b4f15 to
abe34e2
Compare
|
PTAL @zanderso |
abe34e2 to
f67a150
Compare
zanderso
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
| break; | ||
| } | ||
| } | ||
| // Pipe stdout/sterr from Gradle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: sterr -> stderr.
| } else { | ||
| settings.values[key] = value; | ||
| if (retries >= 1) { | ||
| final String successEventLabel = 'gradle--${detectedGradleError.eventLabel}-success'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: is there an extra '-' here?
| if (isBuildingBundle) { | ||
| final File bundleFile = findBundleFile(project, buildInfo); | ||
| if (bundleFile == null) { | ||
| throwToolExit('Gradle build failed to produce an Android bundle package.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to supply some advice here? Like, "Try again." or "Look up in the logs for your error message from the Java build." etc.
| } | ||
| } | ||
| changed = true; | ||
| BuildEvent('gradle--${detectedGradleError.eventLabel}-failure').send(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an extra '-' here?
| } | ||
| } | ||
| changed = true; | ||
| BuildEvent('gradle--${detectedGradleError.eventLabel}-failure').send(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could include the exit code in one of the other fields of the event if that would be useful.
| } | ||
| if (isBuildingBundle) { | ||
| final File bundleFile = findBundleFile(project, buildInfo); | ||
| if (bundleFile == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a BuildEvent for this be useful?
| // Gradle produced an APK. | ||
| final Iterable<File> apkFiles = findApkFiles(project, androidBuildInfo); | ||
| if (apkFiles.isEmpty) { | ||
| throwToolExit('Gradle build failed to produce an Android package.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question about the error message.
| settings.writeContents(localProperties); | ||
| // Gradle produced an APK. | ||
| final Iterable<File> apkFiles = findApkFiles(project, androidBuildInfo); | ||
| if (apkFiles.isEmpty) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question about a BuildEvent.
| printStatus(result.stdout, wrap: false); | ||
| printError(result.stderr, wrap: false); | ||
| throwToolExit('Gradle task $aarTask failed with exit code $exitCode.', exitCode: exitCode); | ||
| throwToolExit( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a BuildEvent?
| printStatus(result.stdout, wrap: false); | ||
| printError(result.stderr, wrap: false); | ||
| throwToolExit('Gradle task $aarTask failed to produce $repoDirectory.', exitCode: exitCode); | ||
| throwToolExit( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto.
Follow-up on flutter/flutter#43479.
This PR refactors
gradle.dart.Here's the summary of the two main changes:
First, running
flutter build apk/appbundle/aarinvolves 3 calls to Gradle. One to get the version, one to get the list of flavors and finally the last call to build the target artifacts. These calls add about 2s overhead to the build calls, but most importantly add complexity to the code. e.g. Caching ofstdoutis required, so tests don't time out.I'm essentially getting rid of that. Once this PR is merged, we will call Gradle only once to build the artifacts. We will only get the list of flavor if Gradle failed due to an undefined flavor set via the tool's
--flavorflag. This is the only use case for getting the list of flavors from Gradle.Second, we have logic to detect common Gradles errors that attempts to guide the user toward completing the journey. This logic is all over the place. Some code checks if an error is triggered when checking the Gradle version. Other code checks if an error is triggered when building the artifact.
I don't think this is necessary since these errors occur not matter when the call to Gradle is made. As a result, I organized these logic around a new data structured called
GradleBuildError, which makes it easier to add new error handler in the near future.