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

Refactor gradle.dart #43479

Merged
merged 2 commits into from Oct 31, 2019
Merged

Refactor gradle.dart #43479

merged 2 commits into from Oct 31, 2019

Conversation

blasten
Copy link

@blasten blasten commented Oct 25, 2019

This PR refactors gradle.dart.

Here's the summary of the two main changes:

First, running flutter build apk/appbundle/aar involves 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 of stdout is 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 --flavor flag. 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.

@fluttergithubbot fluttergithubbot added the tool Affects the "flutter" command-line tool. See also t: labels. label Oct 25, 2019
packages/flutter_tools/lib/src/android/gradle.dart Outdated Show resolved Hide resolved
packages/flutter_tools/lib/src/android/gradle.dart Outdated Show resolved Hide resolved
packages/flutter_tools/lib/src/android/gradle.dart Outdated Show resolved Hide resolved
packages/flutter_tools/lib/src/android/gradle.dart Outdated Show resolved Hide resolved
packages/flutter_tools/lib/src/android/gradle.dart Outdated Show resolved Hide resolved
packages/flutter_tools/lib/src/android/gradle_utils.dart Outdated Show resolved Hide resolved
packages/flutter_tools/lib/src/android/gradle_errors.dart Outdated Show resolved Hide resolved
// currently impossible as the test is not hermetic. Luckily, our bots don't have Android
// SDKs yet so androidSdk should be null by default.
//
// This test is written to fail if our bots get Android SDKs in the future: shouldBeToolExit
Copy link
Member

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?

Copy link
Author

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.


/// Warning mark to use in stdout or stderr.
String get warningMark {
return terminal.bolden(terminal.color('[!]', TerminalColor.red));
Copy link
Contributor

Choose a reason for hiding this comment

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

How about ⚠ ?

Copy link
Author

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.

@@ -6,11 +6,11 @@ import 'dart:async';

Copy link
Contributor

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

Copy link
Author

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.

}
// Don't log analytics for downstream Flutter commands.
// e.g. `flutter build bundle`.
env['FLUTTER_SUPPRESS_ANALYTICS'] = 'true';
Copy link
Contributor

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.

Copy link
Author

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.

throwToolExit('Unable to locate gradlew script');
return null;
}
}
Copy link
Contributor

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?)

Copy link
Author

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

@Hixie
Copy link
Contributor

Hixie commented Oct 29, 2019

LGTM modulo my barrel of nits.

@blasten blasten force-pushed the faster_android_build branch 3 times, most recently from 6fe8aaf to 16246b4 Compare October 30, 2019 02:22
@blasten
Copy link
Author

blasten commented Oct 31, 2019

PTAL @zanderso

Copy link
Member

@zanderso zanderso left a comment

Choose a reason for hiding this comment

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

lgtm

@blasten blasten merged commit 175b372 into flutter:master Oct 31, 2019
@blasten blasten deleted the faster_android_build branch October 31, 2019 20:19
break;
}
}
// Pipe stdout/sterr from Gradle.
Copy link
Member

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';
Copy link
Member

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.');
Copy link
Member

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();
Copy link
Member

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();
Copy link
Member

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) {
Copy link
Member

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.');
Copy link
Member

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) {
Copy link
Member

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.

@@ -686,41 +533,24 @@ Future<void> buildGradleAar({
if (result.exitCode != 0) {
printStatus(result.stdout, wrap: false);
printError(result.stderr, wrap: false);
throwToolExit('Gradle task $aarTask failed with exit code $exitCode.', exitCode: exitCode);
throwToolExit(
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a BuildEvent?

if (!repoDirectory.existsSync()) {
printStatus(result.stdout, wrap: false);
printError(result.stderr, wrap: false);
throwToolExit('Gradle task $aarTask failed to produce $repoDirectory.', exitCode: exitCode);
throwToolExit(
Copy link
Member

Choose a reason for hiding this comment

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

ditto.

Inconnu08 pushed a commit to Inconnu08/flutter that referenced this pull request Nov 26, 2019
dotdoom added a commit to dotdoom/fastlane-plugin-flutter that referenced this pull request Nov 27, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 3, 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.

None yet

5 participants