Unverified Commit 4566b340 authored by Dan Field's avatar Dan Field Committed by GitHub

Do not validate the Android SDK when building an appbundle (#41946)

parent 3af16678
...@@ -9,7 +9,6 @@ import 'package:meta/meta.dart'; ...@@ -9,7 +9,6 @@ import 'package:meta/meta.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../globals.dart';
import '../project.dart'; import '../project.dart';
import 'android_sdk.dart'; import 'android_sdk.dart';
...@@ -58,9 +57,9 @@ class _AndroidBuilderImpl extends AndroidBuilder { ...@@ -58,9 +57,9 @@ class _AndroidBuilderImpl extends AndroidBuilder {
if (!project.android.isUsingGradle) { if (!project.android.isUsingGradle) {
throwToolExit( throwToolExit(
'The build process for Android has changed, and the current project configuration ' 'The build process for Android has changed, and the current project configuration '
'is no longer valid. Please consult\n\n' 'is no longer valid. Please consult\n\n'
' https://github.com/flutter/flutter/wiki/Upgrading-Flutter-projects-to-build-with-gradle\n\n' ' https://github.com/flutter/flutter/wiki/Upgrading-Flutter-projects-to-build-with-gradle\n\n'
'for details on how to upgrade the project.' 'for details on how to upgrade the project.'
); );
} }
if (!project.manifest.isModule && !project.manifest.isPlugin) { if (!project.manifest.isModule && !project.manifest.isPlugin) {
...@@ -70,13 +69,16 @@ class _AndroidBuilderImpl extends AndroidBuilder { ...@@ -70,13 +69,16 @@ class _AndroidBuilderImpl extends AndroidBuilder {
if (androidSdk == null) { if (androidSdk == null) {
throwToolExit('No Android SDK found. Try setting the `ANDROID_SDK_ROOT` environment variable.'); throwToolExit('No Android SDK found. Try setting the `ANDROID_SDK_ROOT` environment variable.');
} }
await buildGradleAar( try {
project: project, await buildGradleAar(
androidBuildInfo: androidBuildInfo, project: project,
target: target, androidBuildInfo: androidBuildInfo,
outputDir: outputDir, target: target,
); outputDir: outputDir,
androidSdk.reinitialize(); );
} finally {
androidSdk.reinitialize();
}
} }
/// Builds the APK. /// Builds the APK.
...@@ -89,22 +91,25 @@ class _AndroidBuilderImpl extends AndroidBuilder { ...@@ -89,22 +91,25 @@ class _AndroidBuilderImpl extends AndroidBuilder {
if (!project.android.isUsingGradle) { if (!project.android.isUsingGradle) {
throwToolExit( throwToolExit(
'The build process for Android has changed, and the current project configuration ' 'The build process for Android has changed, and the current project configuration '
'is no longer valid. Please consult\n\n' 'is no longer valid. Please consult\n\n'
' https://github.com/flutter/flutter/wiki/Upgrading-Flutter-projects-to-build-with-gradle\n\n' ' https://github.com/flutter/flutter/wiki/Upgrading-Flutter-projects-to-build-with-gradle\n\n'
'for details on how to upgrade the project.' 'for details on how to upgrade the project.'
); );
} }
// Validate that we can find an android sdk. // Validate that we can find an android sdk.
if (androidSdk == null) { if (androidSdk == null) {
throwToolExit('No Android SDK found. Try setting the ANDROID_SDK_ROOT environment variable.'); throwToolExit('No Android SDK found. Try setting the ANDROID_SDK_ROOT environment variable.');
} }
await buildGradleProject( try {
project: project, await buildGradleProject(
androidBuildInfo: androidBuildInfo, project: project,
target: target, androidBuildInfo: androidBuildInfo,
isBuildingBundle: false, target: target,
); isBuildingBundle: false,
androidSdk.reinitialize(); );
} finally {
androidSdk.reinitialize();
}
} }
/// Builds the App Bundle. /// Builds the App Bundle.
...@@ -126,19 +131,17 @@ class _AndroidBuilderImpl extends AndroidBuilder { ...@@ -126,19 +131,17 @@ class _AndroidBuilderImpl extends AndroidBuilder {
if (androidSdk == null) { if (androidSdk == null) {
throwToolExit('No Android SDK found. Try setting the ANDROID_HOME environment variable.'); throwToolExit('No Android SDK found. Try setting the ANDROID_HOME environment variable.');
} }
final List<String> validationResult = androidSdk.validateSdkWellFormed();
if (validationResult.isNotEmpty) { try {
for (String message in validationResult) { await buildGradleProject(
printError(message, wrap: false); project: project,
} androidBuildInfo: androidBuildInfo,
throwToolExit('Try re-installing or updating your Android SDK.'); target: target,
isBuildingBundle: true,
);
} finally {
androidSdk.reinitialize();
} }
return buildGradleProject(
project: project,
androidBuildInfo: androidBuildInfo,
target: target,
isBuildingBundle: true,
);
} }
} }
......
...@@ -820,9 +820,8 @@ Future<void> _buildGradleProjectV2( ...@@ -820,9 +820,8 @@ Future<void> _buildGradleProjectV2(
workingDirectory: flutterProject.android.hostAppGradleRoot.path, workingDirectory: flutterProject.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: gradleEnv, environment: gradleEnv,
// TODO(mklim): if AndroidX warnings are no longer required, this // TODO(mklim): if AndroidX warnings are no longer required, we can remove
// mapFunction and all its associated variabled can be replaced with just // them from this map function.
// `filter: ndkMessagefilter`.
mapFunction: (String line) { mapFunction: (String line) {
final bool isAndroidXPluginWarning = androidXPluginWarningRegex.hasMatch(line); final bool isAndroidXPluginWarning = androidXPluginWarningRegex.hasMatch(line);
if (!isAndroidXPluginWarning && androidXFailureRegex.hasMatch(line)) { if (!isAndroidXPluginWarning && androidXFailureRegex.hasMatch(line)) {
......
...@@ -2,15 +2,24 @@ ...@@ -2,15 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Process, ProcessResult;
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_builder.dart'; import 'package:flutter_tools/src/android/android_builder.dart';
import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/android/gradle.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build_aar.dart'; import 'package:flutter_tools/src/commands/build_aar.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
import '../../src/mocks.dart';
void main() { void main() {
Cache.disableLocking(); Cache.disableLocking();
...@@ -74,4 +83,100 @@ void main() { ...@@ -74,4 +83,100 @@ void main() {
AndroidBuilder: () => FakeAndroidBuilder(), AndroidBuilder: () => FakeAndroidBuilder(),
}, timeout: allowForCreateFlutterProject); }, timeout: allowForCreateFlutterProject);
}); });
group('Gradle', () {
ProcessManager mockProcessManager;
Directory tempDir;
AndroidSdk mockAndroidSdk;
Usage mockUsage;
FileSystem memoryFileSystem;
setUp(() {
mockUsage = MockUsage();
when(mockUsage.isFirstRun).thenReturn(true);
memoryFileSystem = MemoryFileSystem();
tempDir = memoryFileSystem.systemTempDirectory.createTempSync('flutter_tools_packages_test.');
memoryFileSystem.currentDirectory = tempDir;
mockProcessManager = MockProcessManager();
when(mockProcessManager.run(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(0, 0, 'assembleRelease', '')));
// Fallback with error.
final Process process = createMockProcess(exitCode: 1);
when(mockProcessManager.start(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenAnswer((_) => Future<Process>.value(process));
when(mockProcessManager.canRun(any)).thenReturn(false);
mockAndroidSdk = MockAndroidSdk();
when(mockAndroidSdk.directory).thenReturn('irrelevant');
});
group('AndroidSdk', () {
testUsingContext('validateSdkWellFormed() not called, sdk reinitialized', () async {
final Directory gradleCacheDir = memoryFileSystem.directory('/flutter_root/bin/cache/artifacts/gradle_wrapper')..createSync(recursive: true);
gradleCacheDir.childFile(platform.isWindows ? 'gradlew.bat' : 'gradlew').createSync();
tempDir.childFile('pubspec.yaml')
..createSync(recursive: true)
..writeAsStringSync('''name: test
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
plugin:
androidPackage: com.example.blah
pluginClass: BlahPlugin
''');
tempDir.childFile('.packages').createSync(recursive: true);
final Directory androidDir = tempDir.childDirectory('android');
androidDir.childFile('build.gradle').createSync(recursive: true);
androidDir.childFile('gradle.properties').createSync(recursive: true);
androidDir.childDirectory('gradle').childDirectory('wrapper').childFile('gradle-wrapper.properties').createSync(recursive: true);
tempDir.childDirectory('build').childDirectory('outputs').childDirectory('repo').createSync(recursive: true);
tempDir.childDirectory('lib').childFile('main.dart').createSync(recursive: true);
await runBuildAarCommand(tempDir.path);
verifyNever(mockAndroidSdk.validateSdkWellFormed());
verify(mockAndroidSdk.reinitialize()).called(1);
},
overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
FileSystem: () => memoryFileSystem,
});
});
});
} }
Future<BuildAarCommand> runBuildAarCommand(
String target, {
List<String> arguments,
}) async {
final BuildAarCommand command = BuildAarCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[
'aar',
'--no-pub',
'--flutter-root=/flutter_root',
...?arguments,
fs.path.join(target, 'lib', 'main.dart'),
]);
return command;
}
class MockAndroidSdk extends Mock implements AndroidSdk {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {}
class MockUsage extends Mock implements Usage {}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:io'; import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_builder.dart'; import 'package:flutter_tools/src/android/android_builder.dart';
import 'package:flutter_tools/src/android/android_sdk.dart'; import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/android/gradle.dart'; import 'package:flutter_tools/src/android/gradle.dart';
...@@ -137,6 +138,62 @@ void main() { ...@@ -137,6 +138,62 @@ void main() {
tryToDelete(tempDir); tryToDelete(tempDir);
}); });
group('AndroidSdk', () {
FileSystem memoryFileSystem;
setUp(() {
memoryFileSystem = MemoryFileSystem();
tempDir = memoryFileSystem.systemTempDirectory.createTempSync('flutter_tools_packages_test.');
memoryFileSystem.currentDirectory = tempDir;
gradlew = memoryFileSystem.path.join(tempDir.path, 'flutter_project', 'android',
platform.isWindows ? 'gradlew.bat' : 'gradlew');
});
testUsingContext('validateSdkWellFormed() not called, sdk reinitialized', () async {
final Directory gradleCacheDir = memoryFileSystem.directory('/flutter_root/bin/cache/artifacts/gradle_wrapper')..createSync(recursive: true);
gradleCacheDir.childFile(platform.isWindows ? 'gradlew.bat' : 'gradlew').createSync();
tempDir.childFile('pubspec.yaml')
..createSync(recursive: true)
..writeAsStringSync('''name: test
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
''');
tempDir.childFile('.packages').createSync(recursive: true);
final Directory androidDir = tempDir.childDirectory('android');
androidDir.childFile('build.gradle').createSync(recursive: true);
androidDir.childFile('gradle.properties').createSync(recursive: true);
androidDir.childDirectory('gradle').childDirectory('wrapper').childFile('gradle-wrapper.properties').createSync(recursive: true);
tempDir.childDirectory('build').childDirectory('outputs').childDirectory('repo').createSync(recursive: true);
tempDir.childDirectory('lib').childFile('main.dart').createSync(recursive: true);
when(mockProcessManager.run(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(0, 0, 'any', '')));
await expectLater(
runBuildApkCommand(tempDir.path, arguments: <String>['--no-pub', '--flutter-root=/flutter_root']),
throwsToolExit(message: 'Gradle build failed: 1'),
);
verifyNever(mockAndroidSdk.validateSdkWellFormed());
verify(mockAndroidSdk.reinitialize()).called(1);
},
overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
FileSystem: () => memoryFileSystem,
});
});
testUsingContext('shrinking is enabled by default on release mode', () async { testUsingContext('shrinking is enabled by default on release mode', () async {
final String projectPath = await createProject(tempDir, final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']); arguments: <String>['--no-pub', '--template=app']);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:io'; import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_builder.dart'; import 'package:flutter_tools/src/android/android_builder.dart';
import 'package:flutter_tools/src/android/android_sdk.dart'; import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/android/gradle.dart'; import 'package:flutter_tools/src/android/gradle.dart';
...@@ -122,6 +123,64 @@ void main() { ...@@ -122,6 +123,64 @@ void main() {
tryToDelete(tempDir); tryToDelete(tempDir);
}); });
group('AndroidSdk', () {
FileSystem memoryFileSystem;
setUp(() {
memoryFileSystem = MemoryFileSystem();
tempDir = memoryFileSystem.systemTempDirectory.createTempSync('flutter_tools_packages_test.');
memoryFileSystem.currentDirectory = tempDir;
gradlew = memoryFileSystem.path.join(tempDir.path, 'flutter_project', 'android',
platform.isWindows ? 'gradlew.bat' : 'gradlew');
});
testUsingContext('validateSdkWellFormed() not called, sdk reinitialized', () async {
final Directory gradleCacheDir = memoryFileSystem.directory('/flutter_root/bin/cache/artifacts/gradle_wrapper')..createSync(recursive: true);
gradleCacheDir.childFile(platform.isWindows ? 'gradlew.bat' : 'gradlew').createSync();
tempDir.childFile('pubspec.yaml')
..createSync(recursive: true)
..writeAsStringSync('''name: test
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
''');
tempDir.childFile('.packages').createSync(recursive: true);
final Directory androidDir = tempDir.childDirectory('android');
androidDir.childFile('build.gradle').createSync(recursive: true);
androidDir.childFile('gradle.properties').createSync(recursive: true);
androidDir.childDirectory('gradle').childDirectory('wrapper').childFile('gradle-wrapper.properties').createSync(recursive: true);
tempDir.childDirectory('build').childDirectory('outputs').childDirectory('repo').createSync(recursive: true);
tempDir.childDirectory('lib').childFile('main.dart').createSync(recursive: true);
when(mockProcessManager.run(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(0, 0, 'any', '')));
await expectLater(
runBuildAppBundleCommand(tempDir.path, arguments: <String>['--no-pub', '--flutter-root=/flutter_root']),
throwsToolExit(message: 'Gradle build failed: 1'),
);
verifyNever(mockAndroidSdk.validateSdkWellFormed());
verify(mockAndroidSdk.reinitialize()).called(1);
},
overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
FileSystem: () => memoryFileSystem,
});
});
testUsingContext('shrinking is enabled by default on release mode', () async { testUsingContext('shrinking is enabled by default on release mode', () async {
final String projectPath = await createProject( final String projectPath = await createProject(
tempDir, tempDir,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment