Enable the resource shrinker (#40610)
diff --git a/dev/bots/test.dart b/dev/bots/test.dart index eb03075..823956f 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart
@@ -1018,6 +1018,7 @@ if (subShard == 'gradle1') { await _runDevicelabTest('gradle_plugin_light_apk_test', env: env); await _runDevicelabTest('gradle_plugin_fat_apk_test', env: env); + await _runDevicelabTest('gradle_r8_test', env: env); } if (subShard == 'gradle2') { await _runDevicelabTest('gradle_plugin_bundle_test', env: env);
diff --git a/dev/devicelab/bin/tasks/gradle_r8_test.dart b/dev/devicelab/bin/tasks/gradle_r8_test.dart new file mode 100644 index 0000000..49017e7 --- /dev/null +++ b/dev/devicelab/bin/tasks/gradle_r8_test.dart
@@ -0,0 +1,77 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter_devicelab/framework/framework.dart'; +import 'package:flutter_devicelab/framework/utils.dart'; +import 'package:path/path.dart' as path; + +/// Tests that flutter build apk uses R8 by default by adding an +/// invalid proguard rule and evaluating the error message. +Future<void> main() async { + await task(() async { + + section('Find Java'); + + final String javaHome = await findJavaHome(); + if (javaHome == null) + return TaskResult.failure('Could not find Java'); + print('\nUsing JAVA_HOME=$javaHome'); + + section('Create Flutter app project'); + + final Directory tempDir = Directory.systemTemp.createTempSync('flutter_module_test.'); + final Directory projectDir = Directory(path.join(tempDir.path, 'hello')); + try { + await inDirectory(tempDir, () async { + await flutter( + 'create', + options: <String>[ + '--org', 'io.flutter.devicelab', + 'hello', + ], + ); + }); + + section('Add incorrect proguard rules'); + + final File proguardRules = File(path.join( + projectDir.path, + 'android', + 'app', + 'proguard-rules.pro', + )); + proguardRules.writeAsStringSync('invalidRule', flush: true); + + section('Build release APK'); + + final StringBuffer stderr = StringBuffer(); + + await inDirectory(projectDir, () async { + await evalFlutter( + 'build', + options: <String>[ + 'apk', + '--target-platform', 'android-arm', + '--verbose', + ], + canFail: true, + stderr: stderr, + ); + }); + + if (!stderr.toString().contains('com.android.tools.r8.CompilationFailedException')) { + return TaskResult.failure('Expected com.android.tools.r8.CompilationFailedException in stderr.'); + } + + return TaskResult.success(null); + } catch (e) { + return TaskResult.failure(e.toString()); + } finally { + rmTree(tempDir); + } + }); +}
diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle index 4d65284..c3328d7 100644 --- a/packages/flutter_tools/gradle/flutter.gradle +++ b/packages/flutter_tools/gradle/flutter.gradle
@@ -154,7 +154,7 @@ } } - if (shouldUseProguard(project)) { + if (shouldShrinkResources(project)) { String flutterProguardRules = Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "flutter_proguard_rules.pro") project.android.buildTypes { @@ -164,7 +164,8 @@ minifyEnabled true // Enables resource shrinking, which is performed by the // Android Gradle plugin. - shrinkResources true + // NOTE: The resource shrinker can't be used for libraries. + shrinkResources isBuiltAsApp(project) // Fallback to `android/app/proguard-rules.pro`. // This way, custom Proguard rules can be configured as needed. proguardFiles project.android.getDefaultProguardFile("proguard-android.txt"), flutterProguardRules, "proguard-rules.pro" @@ -393,13 +394,19 @@ return false } - private static Boolean shouldUseProguard(Project project) { - if (project.hasProperty('proguard')) { - return project.property('proguard').toBoolean() + private static Boolean shouldShrinkResources(Project project) { + if (project.hasProperty("shrink")) { + return project.property("shrink").toBoolean() } return false } + private static Boolean isBuiltAsApp(Project project) { + // Projects are built as applications when the they use the `com.android.application` + // plugin. + return project.plugins.hasPlugin("com.android.application"); + } + private static Boolean buildPluginAsAar() { return System.getProperty('build-plugins-as-aars') == 'true' }