mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Enable R8 (#40453)
This commit is contained in:
parent
e3c4609a5e
commit
2c857b9370
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1,3 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableR8=true
|
||||
|
@ -1,3 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableR8=true
|
||||
|
@ -1,3 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1,2 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1,2 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableR8=true
|
||||
|
@ -159,8 +159,12 @@ class FlutterPlugin implements Plugin<Project> {
|
||||
"gradle", "flutter_proguard_rules.pro")
|
||||
project.android.buildTypes {
|
||||
release {
|
||||
// Enables code shrinking, obfuscation, and optimization for only
|
||||
// your project's release build type.
|
||||
minifyEnabled true
|
||||
useProguard true
|
||||
// Enables resource shrinking, which is performed by the
|
||||
// Android Gradle plugin.
|
||||
shrinkResources true
|
||||
// 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"
|
||||
|
@ -306,6 +306,10 @@ Future<String> _initializeGradle(FlutterProject project) async {
|
||||
final Status status = logger.startProgress('Initializing gradle...',
|
||||
timeout: timeoutConfiguration.slowOperation);
|
||||
|
||||
|
||||
// Update the project if needed.
|
||||
// TODO(egarciad): https://github.com/flutter/flutter/issues/40460.
|
||||
migrateToR8(android);
|
||||
injectGradleWrapperIfNeeded(android);
|
||||
|
||||
final String gradle = _locateGradlewExecutable(android);
|
||||
@ -335,6 +339,31 @@ Future<String> _initializeGradle(FlutterProject project) async {
|
||||
return gradle;
|
||||
}
|
||||
|
||||
/// Migrates the Android's [directory] to R8.
|
||||
/// https://developer.android.com/studio/build/shrink-code
|
||||
@visibleForTesting
|
||||
void migrateToR8(Directory directory) {
|
||||
final File gradleProperties = directory.childFile('gradle.properties');
|
||||
if (!gradleProperties.existsSync()) {
|
||||
throwToolExit('Expected file ${gradleProperties.path}.');
|
||||
}
|
||||
final String propertiesContent = gradleProperties.readAsStringSync();
|
||||
if (propertiesContent.contains('android.enableR8')) {
|
||||
printTrace('gradle.properties already sets `android.enableR8`');
|
||||
return;
|
||||
}
|
||||
printTrace('set `android.enableR8=true` in gradle.properties');
|
||||
try {
|
||||
gradleProperties
|
||||
.writeAsStringSync('android.enableR8=true\n', mode: FileMode.append);
|
||||
} on FileSystemException {
|
||||
throwToolExit(
|
||||
'The tool failed to add `android.enableR8=true` to ${gradleProperties.path}. '
|
||||
'Please update the file manually and try this command again.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Injects the Gradle wrapper files if any of these files don't exist in [directory].
|
||||
void injectGradleWrapperIfNeeded(Directory directory) {
|
||||
copyDirectorySync(
|
||||
@ -754,8 +783,8 @@ Future<void> _buildGradleProjectV2(
|
||||
if (androidBuildInfo.splitPerAbi) {
|
||||
command.add('-Psplit-per-abi=true');
|
||||
}
|
||||
if (androidBuildInfo.proguard) {
|
||||
command.add('-Pproguard=true');
|
||||
if (androidBuildInfo.shrink) {
|
||||
command.add('-Pshrink=true');
|
||||
}
|
||||
if (androidBuildInfo.targetArchs.isNotEmpty) {
|
||||
final String targetPlatforms = androidBuildInfo.targetArchs
|
||||
@ -772,7 +801,7 @@ Future<void> _buildGradleProjectV2(
|
||||
}
|
||||
command.add(assembleTask);
|
||||
bool potentialAndroidXFailure = false;
|
||||
bool potentialProguardFailure = false;
|
||||
bool potentialR8Failure = false;
|
||||
final Stopwatch sw = Stopwatch()..start();
|
||||
int exitCode = 1;
|
||||
try {
|
||||
@ -789,10 +818,10 @@ Future<void> _buildGradleProjectV2(
|
||||
if (!isAndroidXPluginWarning && androidXFailureRegex.hasMatch(line)) {
|
||||
potentialAndroidXFailure = true;
|
||||
}
|
||||
// Proguard errors include this url.
|
||||
if (!potentialProguardFailure && androidBuildInfo.proguard &&
|
||||
line.contains('http://proguard.sourceforge.net')) {
|
||||
potentialProguardFailure = true;
|
||||
// R8 errors include references to this package.
|
||||
if (!potentialR8Failure && androidBuildInfo.shrink &&
|
||||
line.contains('com.android.tools.r8')) {
|
||||
potentialR8Failure = true;
|
||||
}
|
||||
// Always print the full line in verbose mode.
|
||||
if (logger.isVerbose) {
|
||||
@ -808,12 +837,12 @@ Future<void> _buildGradleProjectV2(
|
||||
}
|
||||
|
||||
if (exitCode != 0) {
|
||||
if (potentialProguardFailure) {
|
||||
if (potentialR8Failure) {
|
||||
final String exclamationMark = terminal.color('[!]', TerminalColor.red);
|
||||
printStatus('$exclamationMark Proguard may have failed to optimize the Java bytecode.', emphasis: true);
|
||||
printStatus('To disable proguard, pass the `--no-proguard` flag to this command.', indent: 4);
|
||||
printStatus('To learn more about Proguard, see: https://flutter.dev/docs/deployment/android#enabling-proguard', indent: 4);
|
||||
BuildEvent('proguard-failure').send();
|
||||
printStatus('$exclamationMark The shrinker may have failed to optimize the Java bytecode.', emphasis: true);
|
||||
printStatus('To disable the shrinker, pass the `--no-shrink` flag to this command.', indent: 4);
|
||||
printStatus('To learn more, see: https://developer.android.com/studio/build/shrink-code', indent: 4);
|
||||
BuildEvent('r8-failure').send();
|
||||
} else if (potentialAndroidXFailure) {
|
||||
printStatus('AndroidX incompatibilities may have caused this build to fail. See https://goo.gl/CP92wY.');
|
||||
BuildEvent('android-x-failure').send();
|
||||
|
@ -92,7 +92,7 @@ class AndroidBuildInfo {
|
||||
AndroidArch.arm64_v8a,
|
||||
],
|
||||
this.splitPerAbi = false,
|
||||
this.proguard = false,
|
||||
this.shrink = false,
|
||||
});
|
||||
|
||||
// The build info containing the mode and flavor.
|
||||
@ -105,8 +105,8 @@ class AndroidBuildInfo {
|
||||
/// will be produced.
|
||||
final bool splitPerAbi;
|
||||
|
||||
/// Whether to enable Proguard on release mode.
|
||||
final bool proguard;
|
||||
/// Whether to enable code shrinking on release mode.
|
||||
final bool shrink;
|
||||
|
||||
/// The target platforms for the build.
|
||||
final Iterable<AndroidArch> targetArchs;
|
||||
|
@ -21,6 +21,7 @@ class BuildApkCommand extends BuildSubCommand {
|
||||
usesPubOption();
|
||||
usesBuildNumberOption();
|
||||
usesBuildNameOption();
|
||||
addShrinkingFlag();
|
||||
|
||||
argParser
|
||||
..addFlag('split-per-abi',
|
||||
@ -28,12 +29,6 @@ class BuildApkCommand extends BuildSubCommand {
|
||||
help: 'Whether to split the APKs per ABIs. '
|
||||
'To learn more, see: https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split',
|
||||
)
|
||||
..addFlag('proguard',
|
||||
negatable: true,
|
||||
defaultsTo: false,
|
||||
help: 'Whether to enable Proguard on release mode. '
|
||||
'To learn more, see: https://flutter.dev/docs/deployment/android#enabling-proguard',
|
||||
)
|
||||
..addMultiOption('target-platform',
|
||||
splitCommas: true,
|
||||
defaultsTo: <String>['android-arm', 'android-arm64'],
|
||||
@ -83,10 +78,11 @@ class BuildApkCommand extends BuildSubCommand {
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
final BuildInfo buildInfo = getBuildInfo();
|
||||
final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(buildInfo,
|
||||
final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(
|
||||
buildInfo,
|
||||
splitPerAbi: argResults['split-per-abi'],
|
||||
targetArchs: argResults['target-platform'].map<AndroidArch>(getAndroidArchForName),
|
||||
proguard: argResults['proguard'],
|
||||
shrink: argResults['shrink'],
|
||||
);
|
||||
|
||||
if (buildInfo.isRelease && !androidBuildInfo.splitPerAbi && androidBuildInfo.targetArchs.length > 1) {
|
||||
|
@ -19,15 +19,10 @@ class BuildAppBundleCommand extends BuildSubCommand {
|
||||
usesPubOption();
|
||||
usesBuildNumberOption();
|
||||
usesBuildNameOption();
|
||||
addShrinkingFlag();
|
||||
|
||||
argParser
|
||||
..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp)
|
||||
..addFlag('proguard',
|
||||
negatable: true,
|
||||
defaultsTo: false,
|
||||
help: 'Whether to enable Proguard on release mode. '
|
||||
'To learn more, see: https://flutter.dev/docs/deployment/android#enabling-proguard',
|
||||
)
|
||||
..addMultiOption('target-platform',
|
||||
splitCommas: true,
|
||||
defaultsTo: <String>['android-arm', 'android-arm64'],
|
||||
@ -70,7 +65,7 @@ class BuildAppBundleCommand extends BuildSubCommand {
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(getBuildInfo(),
|
||||
targetArchs: argResults['target-platform'].map<AndroidArch>(getAndroidArchForName),
|
||||
proguard: argResults['proguard'],
|
||||
shrink: argResults['shrink'],
|
||||
);
|
||||
await androidBuilder.buildAab(
|
||||
project: FlutterProject.current(),
|
||||
|
@ -277,6 +277,19 @@ abstract class FlutterCommand extends Command<void> {
|
||||
help: 'Build a release version of your app${defaultToRelease ? ' (default mode)' : ''}.');
|
||||
}
|
||||
|
||||
void addShrinkingFlag() {
|
||||
argParser.addFlag('shrink',
|
||||
negatable: true,
|
||||
defaultsTo: true,
|
||||
help: 'Whether to enable code shrinking on release mode.'
|
||||
'When enabling shrinking, you also benefit from obfuscation, '
|
||||
'which shortens the names of your app’s classes and members, '
|
||||
'and optimization, which applies more aggressive strategies to '
|
||||
'further reduce the size of your app.'
|
||||
'To learn more, see: https://developer.android.com/studio/build/shrink-code'
|
||||
);
|
||||
}
|
||||
|
||||
void usesFuchsiaOptions({ bool hide = false }) {
|
||||
argParser.addOption(
|
||||
'target-model',
|
||||
|
@ -1,5 +1,5 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
||||
android.enableR8=true
|
||||
{{#androidX}}
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
@ -1,5 +1,5 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
||||
android.enableR8=true
|
||||
{{#androidX}}
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
@ -1,5 +1,5 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
||||
android.enableR8=true
|
||||
{{#androidX}}
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
@ -3,7 +3,6 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_sdk.dart';
|
||||
@ -13,6 +12,7 @@ import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/os.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
@ -867,6 +867,13 @@ flutter:
|
||||
gradleWrapperDirectory
|
||||
.childFile(gradleBinary)
|
||||
.writeAsStringSync('irrelevant');
|
||||
fs.currentDirectory
|
||||
.childDirectory('android')
|
||||
.createSync();
|
||||
fs.currentDirectory
|
||||
.childDirectory('android')
|
||||
.childFile('gradle.properties')
|
||||
.writeAsStringSync('irrelevant');
|
||||
gradleWrapperDirectory
|
||||
.childDirectory('gradle')
|
||||
.childDirectory('wrapper')
|
||||
@ -1072,6 +1079,82 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
|
||||
});
|
||||
});
|
||||
|
||||
group('migrateToR8', () {
|
||||
MemoryFileSystem memoryFileSystem;
|
||||
|
||||
setUp(() {
|
||||
memoryFileSystem = MemoryFileSystem();
|
||||
});
|
||||
|
||||
testUsingContext('throws ToolExit if gradle.properties doesn\'t exist', () {
|
||||
final Directory sampleAppAndroid = fs.directory('/sample-app/android');
|
||||
sampleAppAndroid.createSync(recursive: true);
|
||||
|
||||
expect(() {
|
||||
migrateToR8(sampleAppAndroid);
|
||||
}, throwsToolExit(message: 'Expected file ${sampleAppAndroid.path}'));
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
});
|
||||
|
||||
testUsingContext('throws ToolExit if it cannot write gradle.properties', () {
|
||||
final MockDirectory sampleAppAndroid = MockDirectory();
|
||||
final MockFile gradleProperties = MockFile();
|
||||
|
||||
when(gradleProperties.path).thenReturn('foo/gradle.properties');
|
||||
when(gradleProperties.existsSync()).thenReturn(true);
|
||||
when(gradleProperties.readAsStringSync()).thenReturn('');
|
||||
when(gradleProperties.writeAsStringSync('android.enableR8=true\n', mode: FileMode.append))
|
||||
.thenThrow(const FileSystemException());
|
||||
|
||||
when(sampleAppAndroid.childFile('gradle.properties'))
|
||||
.thenReturn(gradleProperties);
|
||||
|
||||
expect(() {
|
||||
migrateToR8(sampleAppAndroid);
|
||||
},
|
||||
throwsToolExit(message:
|
||||
'The tool failed to add `android.enableR8=true` to foo/gradle.properties. '
|
||||
'Please update the file manually and try this command again.'));
|
||||
});
|
||||
|
||||
testUsingContext('does not update gradle.properties if it already uses R8', () {
|
||||
final Directory sampleAppAndroid = fs.directory('/sample-app/android');
|
||||
sampleAppAndroid.createSync(recursive: true);
|
||||
sampleAppAndroid.childFile('gradle.properties')
|
||||
.writeAsStringSync('android.enableR8=true');
|
||||
|
||||
migrateToR8(sampleAppAndroid);
|
||||
|
||||
expect(testLogger.traceText,
|
||||
contains('gradle.properties already sets `android.enableR8`'));
|
||||
expect(sampleAppAndroid.childFile('gradle.properties').readAsStringSync(),
|
||||
equals('android.enableR8=true'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
});
|
||||
|
||||
testUsingContext('sets android.enableR8=true', () {
|
||||
final Directory sampleAppAndroid = fs.directory('/sample-app/android');
|
||||
sampleAppAndroid.createSync(recursive: true);
|
||||
sampleAppAndroid.childFile('gradle.properties')
|
||||
.writeAsStringSync('org.gradle.jvmargs=-Xmx1536M\n');
|
||||
|
||||
migrateToR8(sampleAppAndroid);
|
||||
|
||||
expect(testLogger.traceText, contains('set `android.enableR8=true` in gradle.properties'));
|
||||
expect(sampleAppAndroid.childFile('gradle.properties').readAsStringSync(),
|
||||
equals(
|
||||
'org.gradle.jvmargs=-Xmx1536M\n'
|
||||
'android.enableR8=true\n'
|
||||
)
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
});
|
||||
});
|
||||
|
||||
group('gradle build', () {
|
||||
MockAndroidSdk mockAndroidSdk;
|
||||
MockAndroidStudio mockAndroidStudio;
|
||||
@ -1136,6 +1219,9 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
|
||||
final File gradlew = fs.file('path/to/project/.android/gradlew');
|
||||
gradlew.createSync(recursive: true);
|
||||
|
||||
fs.file('path/to/project/.android/gradle.properties')
|
||||
.writeAsStringSync('irrelevant');
|
||||
|
||||
when(mockProcessManager.run(
|
||||
<String> ['/path/to/project/.android/gradlew', '-v'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
@ -1198,9 +1284,11 @@ Platform fakePlatform(String name) {
|
||||
return FakePlatform.fromPlatform(const LocalPlatform())..operatingSystem = name;
|
||||
}
|
||||
|
||||
class MockAndroidStudio extends Mock implements AndroidStudio {}
|
||||
class MockDirectory extends Mock implements Directory {}
|
||||
class MockFile extends Mock implements File {}
|
||||
class MockGradleProject extends Mock implements GradleProject {}
|
||||
class MockLocalEngineArtifacts extends Mock implements LocalEngineArtifacts {}
|
||||
class MockProcessManager extends Mock implements ProcessManager {}
|
||||
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
|
||||
class MockGradleProject extends Mock implements GradleProject {}
|
||||
class MockitoAndroidSdk extends Mock implements AndroidSdk {}
|
||||
class MockAndroidStudio extends Mock implements AndroidStudio {}
|
||||
|
@ -103,6 +103,10 @@ void main() {
|
||||
platform.isWindows ? 'gradlew.bat' : 'gradlew',
|
||||
)..createSync(recursive: true);
|
||||
|
||||
project.android.hostAppGradleRoot
|
||||
.childFile('gradle.properties')
|
||||
.writeAsStringSync('irrelevant');
|
||||
|
||||
final Directory gradleWrapperDir = fs.systemTempDirectory.createTempSync('gradle_wrapper.');
|
||||
when(mockCache.getArtifactDirectory('gradle_wrapper')).thenReturn(gradleWrapperDir);
|
||||
|
||||
|
@ -137,7 +137,7 @@ void main() {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
testUsingContext('proguard is enabled by default on release mode', () async {
|
||||
testUsingContext('shrinking is enabled by default on release mode', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
arguments: <String>['--no-pub', '--template=app']);
|
||||
|
||||
@ -151,7 +151,7 @@ void main() {
|
||||
'-q',
|
||||
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Ptrack-widget-creation=false',
|
||||
'-Pproguard=true',
|
||||
'-Pshrink=true',
|
||||
'-Ptarget-platform=android-arm,android-arm64',
|
||||
'assembleRelease',
|
||||
],
|
||||
@ -165,17 +165,16 @@ void main() {
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
},
|
||||
skip: true,
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('proguard is disabled when --no-proguard is passed', () async {
|
||||
testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
arguments: <String>['--no-pub', '--template=app']);
|
||||
|
||||
await expectLater(() async {
|
||||
await runBuildApkCommand(
|
||||
projectPath,
|
||||
arguments: <String>['--no-proguard'],
|
||||
arguments: <String>['--no-shrink'],
|
||||
);
|
||||
}, throwsToolExit(message: 'Gradle task assembleRelease failed with exit code 1'));
|
||||
|
||||
@ -198,10 +197,9 @@ void main() {
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
},
|
||||
skip: true,
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('guides the user when proguard fails', () async {
|
||||
testUsingContext('guides the user when the shrinker fails', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
arguments: <String>['--no-pub', '--template=app']);
|
||||
|
||||
@ -211,22 +209,20 @@ void main() {
|
||||
'-q',
|
||||
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Ptrack-widget-creation=false',
|
||||
'-Pproguard=true',
|
||||
'-Pshrink=true',
|
||||
'-Ptarget-platform=android-arm,android-arm64',
|
||||
'assembleRelease',
|
||||
],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenAnswer((_) {
|
||||
const String proguardStdoutWarning =
|
||||
'Warning: there were 6 unresolved references to program class members.'
|
||||
'Your input classes appear to be inconsistent.'
|
||||
'You may need to recompile the code.'
|
||||
'(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)';
|
||||
const String r8StdoutWarning =
|
||||
'Execution failed for task \':app:transformClassesAndResourcesWithR8ForStageInternal\'.'
|
||||
'> com.android.tools.r8.CompilationFailedException: Compilation failed to complete';
|
||||
return Future<Process>.value(
|
||||
createMockProcess(
|
||||
exitCode: 1,
|
||||
stdout: proguardStdoutWarning,
|
||||
stdout: r8StdoutWarning,
|
||||
)
|
||||
);
|
||||
});
|
||||
@ -238,15 +234,15 @@ void main() {
|
||||
}, throwsToolExit(message: 'Gradle task assembleRelease failed with exit code 1'));
|
||||
|
||||
expect(testLogger.statusText,
|
||||
contains('Proguard may have failed to optimize the Java bytecode.'));
|
||||
contains('The shrinker may have failed to optimize the Java bytecode.'));
|
||||
expect(testLogger.statusText,
|
||||
contains('To disable proguard, pass the `--no-proguard` flag to this command.'));
|
||||
contains('To disable the shrinker, pass the `--no-shrink` flag to this command.'));
|
||||
expect(testLogger.statusText,
|
||||
contains('To learn more about Proguard, see: https://flutter.dev/docs/deployment/android#enabling-proguard'));
|
||||
contains('To learn more, see: https://developer.android.com/studio/build/shrink-code'));
|
||||
|
||||
verify(mockUsage.sendEvent(
|
||||
'build-apk',
|
||||
'proguard-failure',
|
||||
'r8-failure',
|
||||
parameters: anyNamed('parameters'),
|
||||
)).called(1);
|
||||
},
|
||||
@ -257,7 +253,6 @@ void main() {
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
},
|
||||
skip: true,
|
||||
timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ void main() {
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
|
||||
group('Flags', () {
|
||||
group('Gradle', () {
|
||||
Directory tempDir;
|
||||
ProcessManager mockProcessManager;
|
||||
MockAndroidSdk mockAndroidSdk;
|
||||
@ -122,7 +122,7 @@ void main() {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
testUsingContext('proguard is enabled by default on release mode', () async {
|
||||
testUsingContext('shrinking is enabled by default on release mode', () async {
|
||||
final String projectPath = await createProject(
|
||||
tempDir,
|
||||
arguments: <String>['--no-pub', '--template=app'],
|
||||
@ -138,7 +138,7 @@ void main() {
|
||||
'-q',
|
||||
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Ptrack-widget-creation=false',
|
||||
'-Pproguard=true',
|
||||
'-Pshrink=true',
|
||||
'-Ptarget-platform=android-arm,android-arm64',
|
||||
'bundleRelease',
|
||||
],
|
||||
@ -152,10 +152,9 @@ void main() {
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
},
|
||||
skip: true,
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('proguard is disabled when --no-proguard is passed', () async {
|
||||
testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
|
||||
final String projectPath = await createProject(
|
||||
tempDir,
|
||||
arguments: <String>['--no-pub', '--template=app'],
|
||||
@ -164,7 +163,7 @@ void main() {
|
||||
await expectLater(() async {
|
||||
await runBuildAppBundleCommand(
|
||||
projectPath,
|
||||
arguments: <String>['--no-proguard'],
|
||||
arguments: <String>['--no-shrink'],
|
||||
);
|
||||
}, throwsToolExit(message: 'Gradle task bundleRelease failed with exit code 1'));
|
||||
|
||||
@ -187,10 +186,9 @@ void main() {
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
},
|
||||
skip: true,
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('guides the user when proguard fails', () async {
|
||||
testUsingContext('guides the user when the shrinker fails', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
arguments: <String>['--no-pub', '--template=app']);
|
||||
|
||||
@ -200,22 +198,20 @@ void main() {
|
||||
'-q',
|
||||
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Ptrack-widget-creation=false',
|
||||
'-Pproguard=true',
|
||||
'-Pshrink=true',
|
||||
'-Ptarget-platform=android-arm,android-arm64',
|
||||
'bundleRelease',
|
||||
],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenAnswer((_) {
|
||||
const String proguardStdoutWarning =
|
||||
'Warning: there were 6 unresolved references to program class members.'
|
||||
'Your input classes appear to be inconsistent.'
|
||||
'You may need to recompile the code.'
|
||||
'(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)';
|
||||
const String r8StdoutWarning =
|
||||
'Execution failed for task \':app:transformClassesAndResourcesWithR8ForStageInternal\'.'
|
||||
'> com.android.tools.r8.CompilationFailedException: Compilation failed to complete';
|
||||
return Future<Process>.value(
|
||||
createMockProcess(
|
||||
exitCode: 1,
|
||||
stdout: proguardStdoutWarning,
|
||||
stdout: r8StdoutWarning,
|
||||
)
|
||||
);
|
||||
});
|
||||
@ -227,15 +223,15 @@ void main() {
|
||||
}, throwsToolExit(message: 'Gradle task bundleRelease failed with exit code 1'));
|
||||
|
||||
expect(testLogger.statusText,
|
||||
contains('Proguard may have failed to optimize the Java bytecode.'));
|
||||
contains('The shrinker may have failed to optimize the Java bytecode.'));
|
||||
expect(testLogger.statusText,
|
||||
contains('To disable proguard, pass the `--no-proguard` flag to this command.'));
|
||||
contains('To disable the shrinker, pass the `--no-shrink` flag to this command.'));
|
||||
expect(testLogger.statusText,
|
||||
contains('To learn more about Proguard, see: https://flutter.dev/docs/deployment/android#enabling-proguard'));
|
||||
contains('To learn more, see: https://developer.android.com/studio/build/shrink-code'));
|
||||
|
||||
verify(mockUsage.sendEvent(
|
||||
'build-appbundle',
|
||||
'proguard-failure',
|
||||
'r8-failure',
|
||||
parameters: anyNamed('parameters'),
|
||||
)).called(1);
|
||||
},
|
||||
@ -246,7 +242,6 @@ void main() {
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
},
|
||||
skip: true,
|
||||
timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user