From aabdf525583fb708c956a439c33edde40036f683 Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Mon, 22 Jul 2019 22:07:59 -0700 Subject: [PATCH] Revert "Add flutter build aar (#35217)" (#36731) This reverts commit 11460b83785b6b6a81a5e751403442c518b5d7ed. --- dev/bots/test.dart | 5 - .../bin/tasks/build_aar_module_test.dart | 219 ---------- .../bin/tasks/build_aar_plugin_test.dart | 138 ------- .../bin/tasks/gradle_jetifier_test.dart | 138 ------- .../tasks/gradle_migrate_settings_test.dart | 180 --------- .../gradle_plugin_dependencies_test.dart | 147 ------- dev/devicelab/bin/tasks/module_test.dart | 2 +- dev/devicelab/bin/tasks/module_test_ios.dart | 2 +- dev/devicelab/lib/framework/apk_utils.dart | 87 ---- dev/devicelab/lib/framework/utils.dart | 19 +- .../gradle/aar_init_script.gradle | 128 ------ .../gradle/deprecated_settings.gradle | 31 -- packages/flutter_tools/gradle/flutter.gradle | 313 +++------------ .../manual_migration_settings.gradle.md | 19 - .../gradle/settings_aar.gradle.tmpl | 1 - .../flutter_tools/lib/src/android/aar.dart | 62 --- .../flutter_tools/lib/src/android/gradle.dart | 374 +++--------------- .../flutter_tools/lib/src/commands/build.dart | 2 - .../lib/src/commands/build_aar.dart | 94 ----- packages/flutter_tools/lib/src/features.dart | 18 - packages/flutter_tools/lib/src/project.dart | 4 + .../lib/src/reporting/usage.dart | 5 +- .../library/Flutter.tmpl/build.gradle.tmpl | 3 - .../library/include_flutter.groovy.copy.tmpl | 33 +- .../android-java.tmpl/build.gradle.tmpl | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 5 - .../general.shard/android/gradle_test.dart | 172 +------- .../commands/build_aar_test.dart | 87 ---- .../test/general.shard/features_test.dart | 15 - packages/flutter_tools/test/src/testbed.dart | 4 - 30 files changed, 147 insertions(+), 2162 deletions(-) delete mode 100644 dev/devicelab/bin/tasks/build_aar_module_test.dart delete mode 100644 dev/devicelab/bin/tasks/build_aar_plugin_test.dart delete mode 100644 dev/devicelab/bin/tasks/gradle_jetifier_test.dart delete mode 100644 dev/devicelab/bin/tasks/gradle_migrate_settings_test.dart delete mode 100644 dev/devicelab/bin/tasks/gradle_plugin_dependencies_test.dart delete mode 100644 packages/flutter_tools/gradle/aar_init_script.gradle delete mode 100644 packages/flutter_tools/gradle/deprecated_settings.gradle delete mode 100644 packages/flutter_tools/gradle/manual_migration_settings.gradle.md delete mode 100644 packages/flutter_tools/gradle/settings_aar.gradle.tmpl delete mode 100644 packages/flutter_tools/lib/src/android/aar.dart delete mode 100644 packages/flutter_tools/lib/src/commands/build_aar.dart delete mode 100644 packages/flutter_tools/templates/plugin/android.tmpl/gradle/wrapper/gradle-wrapper.properties delete mode 100644 packages/flutter_tools/test/general.shard/commands/build_aar_test.dart diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 4ebcfc32e0c2f..48be0bb022eec 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -961,14 +961,9 @@ Future _androidGradleTests(String subShard) async { if (subShard == 'gradle1') { await _runDevicelabTest('gradle_plugin_light_apk_test', env: env); await _runDevicelabTest('gradle_plugin_fat_apk_test', env: env); - await _runDevicelabTest('gradle_jetifier_test', env: env); - await _runDevicelabTest('gradle_plugin_dependencies_test', env: env); - await _runDevicelabTest('gradle_migrate_settings_test', env: env); } if (subShard == 'gradle2') { await _runDevicelabTest('gradle_plugin_bundle_test', env: env); await _runDevicelabTest('module_test', env: env); - await _runDevicelabTest('build_aar_plugin_test', env: env); - await _runDevicelabTest('build_aar_module_test', env: env); } } diff --git a/dev/devicelab/bin/tasks/build_aar_module_test.dart b/dev/devicelab/bin/tasks/build_aar_module_test.dart deleted file mode 100644 index be55a15b7ac94..0000000000000 --- a/dev/devicelab/bin/tasks/build_aar_module_test.dart +++ /dev/null @@ -1,219 +0,0 @@ -// 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; - -final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew'; -final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew'; - -/// Tests that AARs can be built on module projects. -Future 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 module 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: ['--org', 'io.flutter.devicelab', '--template', 'module', 'hello'], - ); - }); - - section('Add plugins'); - - final File pubspec = File(path.join(projectDir.path, 'pubspec.yaml')); - String content = pubspec.readAsStringSync(); - content = content.replaceFirst( - '\ndependencies:\n', - '\ndependencies:\n device_info:\n package_info:\n', - ); - pubspec.writeAsStringSync(content, flush: true); - await inDirectory(projectDir, () async { - await flutter( - 'packages', - options: ['get'], - ); - }); - - section('Build release AAR'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: ['aar', '--verbose'], - ); - }); - - final String repoPath = path.join( - projectDir.path, - 'build', - 'host', - 'outputs', - 'repo', - ); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'flutter_release', - '1.0', - 'flutter_release-1.0.aar', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'flutter_release', - '1.0', - 'flutter_release-1.0.pom', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'deviceinfo', - 'device_info_release', - '1.0', - 'device_info_release-1.0.aar', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'deviceinfo', - 'device_info_release', - '1.0', - 'device_info_release-1.0.pom', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'packageinfo', - 'package_info_release', - '1.0', - 'package_info_release-1.0.aar', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'packageinfo', - 'package_info_release', - '1.0', - 'package_info_release-1.0.pom', - )); - - section('Build debug AAR'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: ['aar', '--verbose', '--debug'], - ); - }); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'flutter_release', - '1.0', - 'flutter_release-1.0.aar', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'flutter_debug', - '1.0', - 'flutter_debug-1.0.pom', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'deviceinfo', - 'device_info_debug', - '1.0', - 'device_info_debug-1.0.aar', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'deviceinfo', - 'device_info_debug', - '1.0', - 'device_info_debug-1.0.pom', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'packageinfo', - 'package_info_debug', - '1.0', - 'package_info_debug-1.0.aar', - )); - - checkFileExists(path.join( - repoPath, - 'io', - 'flutter', - 'plugins', - 'packageinfo', - 'package_info_debug', - '1.0', - 'package_info_debug-1.0.pom', - )); - - return TaskResult.success(null); - } catch (e) { - return TaskResult.failure(e.toString()); - } finally { - rmTree(tempDir); - } - }); -} diff --git a/dev/devicelab/bin/tasks/build_aar_plugin_test.dart b/dev/devicelab/bin/tasks/build_aar_plugin_test.dart deleted file mode 100644 index 70738106ded16..0000000000000 --- a/dev/devicelab/bin/tasks/build_aar_plugin_test.dart +++ /dev/null @@ -1,138 +0,0 @@ -// 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; - -final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew'; -final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew'; - -/// Tests that AARs can be built on plugin projects. -Future 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 plugin 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: [ - '--org', 'io.flutter.devicelab', - '--template', 'plugin', - 'hello', - ], - ); - }); - - section('Build release AAR'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: ['aar', '--verbose'], - ); - }); - - final String repoPath = path.join( - projectDir.path, - 'build', - 'outputs', - 'repo', - ); - - final File releaseAar = File(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'hello_release', - '1.0', - 'hello_release-1.0.aar', - )); - - if (!exists(releaseAar)) { - return TaskResult.failure('Failed to build the release AAR file.'); - } - - final File releasePom = File(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'hello_release', - '1.0', - 'hello_release-1.0.pom', - )); - - if (!exists(releasePom)) { - return TaskResult.failure('Failed to build the release POM file.'); - } - - section('Build debug AAR'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: [ - 'aar', - '--verbose', - '--debug', - ], - ); - }); - - final File debugAar = File(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'hello_debug', - '1.0', - 'hello_debug-1.0.aar', - )); - - if (!exists(debugAar)) { - return TaskResult.failure('Failed to build the debug AAR file.'); - } - - final File debugPom = File(path.join( - repoPath, - 'io', - 'flutter', - 'devicelab', - 'hello', - 'hello_debug', - '1.0', - 'hello_debug-1.0.pom', - )); - - if (!exists(debugPom)) { - return TaskResult.failure('Failed to build the debug POM file.'); - } - - return TaskResult.success(null); - } catch (e) { - return TaskResult.failure(e.toString()); - } finally { - rmTree(tempDir); - } - }); -} diff --git a/dev/devicelab/bin/tasks/gradle_jetifier_test.dart b/dev/devicelab/bin/tasks/gradle_jetifier_test.dart deleted file mode 100644 index bbabfc2e8b11e..0000000000000 --- a/dev/devicelab/bin/tasks/gradle_jetifier_test.dart +++ /dev/null @@ -1,138 +0,0 @@ -// 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/apk_utils.dart'; -import 'package:flutter_devicelab/framework/framework.dart'; -import 'package:flutter_devicelab/framework/utils.dart'; -import 'package:path/path.dart' as path; - -final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew'; -final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew'; - -/// Tests that Jetifier can translate plugins that use support libraries. -Future 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 AndroidX 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: [ - '--org', 'io.flutter.devicelab', - '--androidx', - 'hello', - ], - ); - }); - - section('Add plugin that uses support libraries'); - - final File pubspec = File(path.join(projectDir.path, 'pubspec.yaml')); - String content = pubspec.readAsStringSync(); - content = content.replaceFirst( - '\ndependencies:\n', - '\ndependencies:\n firebase_auth: 0.7.0\n', - ); - pubspec.writeAsStringSync(content, flush: true); - await inDirectory(projectDir, () async { - await flutter( - 'packages', - options: ['get'], - ); - }); - - section('Build release APK'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: [ - 'apk', - '--target-platform', 'android-arm', - '--verbose', - ], - ); - }); - - final File releaseApk = File(path.join( - projectDir.path, - 'build', - 'app', - 'outputs', - 'apk', - 'release', - 'app-release.apk', - )); - - if (!exists(releaseApk)) { - return TaskResult.failure('Failed to build release APK.'); - } - - checkApkContainsClasses(releaseApk, [ - // The plugin class defined by `firebase_auth`. - 'io.flutter.plugins.firebaseauth.FirebaseAuthPlugin', - // Used by `firebase_auth`. - 'com.google.firebase.FirebaseApp', - // Base class for activities that enables composition of higher level components. - 'androidx.core.app.ComponentActivity', - ]); - - section('Build debug APK'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: [ - 'apk', - '--target-platform', 'android-arm', - '--debug', '--verbose', - ], - ); - }); - - final File debugApk = File(path.join( - projectDir.path, - 'build', - 'app', - 'outputs', - 'apk', - 'debug', - 'app-debug.apk', - )); - - if (!exists(debugApk)) { - return TaskResult.failure('Failed to build debug APK.'); - } - - checkApkContainsClasses(debugApk, [ - // The plugin class defined by `firebase_auth`. - 'io.flutter.plugins.firebaseauth.FirebaseAuthPlugin', - // Used by `firebase_auth`. - 'com.google.firebase.FirebaseApp', - // Base class for activities that enables composition of higher level components. - 'androidx.core.app.ComponentActivity', - ]); - - return TaskResult.success(null); - } catch (e) { - return TaskResult.failure(e.toString()); - } finally { - rmTree(tempDir); - } - }); -} diff --git a/dev/devicelab/bin/tasks/gradle_migrate_settings_test.dart b/dev/devicelab/bin/tasks/gradle_migrate_settings_test.dart deleted file mode 100644 index 72a1708ad2fcf..0000000000000 --- a/dev/devicelab/bin/tasks/gradle_migrate_settings_test.dart +++ /dev/null @@ -1,180 +0,0 @@ -// 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; - -final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew'; -final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew'; - -/// Tests that [settings_aar.gradle] is created when possible. -Future 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 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: ['hello'], - ); - }); - - section('Override settings.gradle V1'); - - final String relativeNewSettingsGradle = path.join('android', 'settings_aar.gradle'); - - section('Build APK'); - - String stdout; - await inDirectory(projectDir, () async { - stdout = await evalFlutter( - 'build', - options: [ - 'apk', - '--flavor', 'does-not-exist', - ], - canFail: true, // The flavor doesn't exist. - ); - }); - - const String newFileContent = 'include \':app\''; - - final File settingsGradle = File(path.join(projectDir.path, 'android', 'settings.gradle')); - final File newSettingsGradle = File(path.join(projectDir.path, 'android', 'settings_aar.gradle')); - - if (!newSettingsGradle.existsSync()) { - return TaskResult.failure('Expected file: `${newSettingsGradle.path}`.'); - } - - if (newSettingsGradle.readAsStringSync().trim() != newFileContent) { - return TaskResult.failure('Expected to create `${newSettingsGradle.path}` V1.'); - } - - if (!stdout.contains('Creating `$relativeNewSettingsGradle`') || - !stdout.contains('`$relativeNewSettingsGradle` created successfully')) { - return TaskResult.failure('Expected update message in stdout.'); - } - - section('Override settings.gradle V2'); - - const String deprecatedFileContentV2 = ''' -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withInputStream { stream -> plugins.load(stream) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":\$name" - project(":\$name").projectDir = pluginDirectory -} -'''; - settingsGradle.writeAsStringSync(deprecatedFileContentV2, flush: true); - newSettingsGradle.deleteSync(); - - section('Build APK'); - - await inDirectory(projectDir, () async { - stdout = await evalFlutter( - 'build', - options: [ - 'apk', - '--flavor', 'does-not-exist', - ], - canFail: true, // The flavor doesn't exist. - ); - }); - - if (newSettingsGradle.readAsStringSync().trim() != newFileContent) { - return TaskResult.failure('Expected to create `${newSettingsGradle.path}` V2.'); - } - - if (!stdout.contains('Creating `$relativeNewSettingsGradle`') || - !stdout.contains('`$relativeNewSettingsGradle` created successfully')) { - return TaskResult.failure('Expected update message in stdout.'); - } - - section('Override settings.gradle with custom logic'); - - const String customDeprecatedFileContent = ''' -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withInputStream { stream -> plugins.load(stream) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":\$name" - project(":\$name").projectDir = pluginDirectory -} -// some custom logic -'''; - settingsGradle.writeAsStringSync(customDeprecatedFileContent, flush: true); - newSettingsGradle.deleteSync(); - - section('Build APK'); - - final StringBuffer stderr = StringBuffer(); - await inDirectory(projectDir, () async { - stdout = await evalFlutter( - 'build', - options: [ - 'apk', - '--flavor', 'does-not-exist', - ], - canFail: true, // The flavor doesn't exist. - stderr: stderr, - ); - }); - - if (newSettingsGradle.existsSync()) { - return TaskResult.failure('Unexpected file: `${newSettingsGradle.path}`.'); - } - - if (!stdout.contains('Creating `$relativeNewSettingsGradle`')) { - return TaskResult.failure('Expected update message in stdout.'); - } - - if (stdout.contains('`$relativeNewSettingsGradle` created successfully')) { - return TaskResult.failure('Unexpected message in stdout.'); - } - - if (!stderr.toString().contains('Flutter tried to create the file ' - '`$relativeNewSettingsGradle`, but failed.')) { - return TaskResult.failure('Expected failure message in stdout.'); - } - - return TaskResult.success(null); - } catch (e) { - return TaskResult.failure(e.toString()); - } finally { - rmTree(tempDir); - } - }); -} diff --git a/dev/devicelab/bin/tasks/gradle_plugin_dependencies_test.dart b/dev/devicelab/bin/tasks/gradle_plugin_dependencies_test.dart deleted file mode 100644 index 2525bdfa1a6ff..0000000000000 --- a/dev/devicelab/bin/tasks/gradle_plugin_dependencies_test.dart +++ /dev/null @@ -1,147 +0,0 @@ -// 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/apk_utils.dart'; -import 'package:flutter_devicelab/framework/framework.dart'; -import 'package:flutter_devicelab/framework/utils.dart'; -import 'package:path/path.dart' as path; - -final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew'; -final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew'; - -/// Tests that projects can include plugins that have a transtive dependency in common. -/// For more info see: https://github.com/flutter/flutter/issues/27254. -Future 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 AndroidX 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: [ - '--org', 'io.flutter.devicelab', - '--androidx', - 'hello', - ], - ); - }); - - section('Add plugin that have conflicting dependencies'); - - final File pubspec = File(path.join(projectDir.path, 'pubspec.yaml')); - String content = pubspec.readAsStringSync(); - - // `flutter_local_notifications` uses `androidx.core:core:1.0.1` - // `firebase_core` and `firebase_messaging` use `androidx.core:core:1.0.0`. - content = content.replaceFirst( - '\ndependencies:\n', - '\ndependencies:\n flutter_local_notifications: 0.7.1+3\n firebase_core:\n firebase_messaging:\n', - ); - pubspec.writeAsStringSync(content, flush: true); - await inDirectory(projectDir, () async { - await flutter( - 'packages', - options: ['get'], - ); - }); - - section('Build release APK'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: [ - 'apk', - '--target-platform', 'android-arm', - '--verbose', - ], - ); - }); - - final File releaseApk = File(path.join( - projectDir.path, - 'build', - 'app', - 'outputs', - 'apk', - 'release', - 'app-release.apk', - )); - - if (!exists(releaseApk)) { - return TaskResult.failure('Failed to build release APK.'); - } - - checkApkContainsClasses(releaseApk, [ - // Used by `flutter_local_notifications`. - 'com.google.gson.Gson', - // Used by `firebase_core` and `firebase_messaging`. - 'com.google.firebase.FirebaseApp', - // Used by `firebase_core`. - 'com.google.firebase.FirebaseOptions', - // Used by `firebase_messaging`. - 'com.google.firebase.messaging.FirebaseMessaging', - ]); - - section('Build debug APK'); - - await inDirectory(projectDir, () async { - await flutter( - 'build', - options: [ - 'apk', - '--target-platform', 'android-arm', - '--debug', - '--verbose', - ], - ); - }); - - final File debugApk = File(path.join( - projectDir.path, - 'build', - 'app', - 'outputs', - 'apk', - 'debug', - 'app-debug.apk', - )); - - if (!exists(debugApk)) { - return TaskResult.failure('Failed to build debug APK.'); - } - - checkApkContainsClasses(debugApk, [ - // Used by `flutter_local_notifications`. - 'com.google.gson.Gson', - // Used by `firebase_core` and `firebase_messaging`. - 'com.google.firebase.FirebaseApp', - // Used by `firebase_core`. - 'com.google.firebase.FirebaseOptions', - // Used by `firebase_messaging`. - 'com.google.firebase.messaging.FirebaseMessaging', - ]); - - return TaskResult.success(null); - } catch (e) { - return TaskResult.failure(e.toString()); - } finally { - rmTree(tempDir); - } - }); -} diff --git a/dev/devicelab/bin/tasks/module_test.dart b/dev/devicelab/bin/tasks/module_test.dart index 0bdcdb044e2d3..1b6e8919c56cd 100644 --- a/dev/devicelab/bin/tasks/module_test.dart +++ b/dev/devicelab/bin/tasks/module_test.dart @@ -42,7 +42,7 @@ Future main() async { String content = await pubspec.readAsString(); content = content.replaceFirst( '\ndependencies:\n', - '\ndependencies:\n device_info:\n package_info:\n', + '\ndependencies:\n battery:\n package_info:\n', ); await pubspec.writeAsString(content, flush: true); await inDirectory(projectDir, () async { diff --git a/dev/devicelab/bin/tasks/module_test_ios.dart b/dev/devicelab/bin/tasks/module_test_ios.dart index f578754820210..ec71e03c7be60 100644 --- a/dev/devicelab/bin/tasks/module_test_ios.dart +++ b/dev/devicelab/bin/tasks/module_test_ios.dart @@ -143,7 +143,7 @@ Future main() async { String content = await pubspec.readAsString(); content = content.replaceFirst( '\ndependencies:\n', - '\ndependencies:\n device_info:\n package_info:\n', + '\ndependencies:\n battery:\n package_info:\n', ); await pubspec.writeAsString(content, flush: true); await inDirectory(projectDir, () async { diff --git a/dev/devicelab/lib/framework/apk_utils.dart b/dev/devicelab/lib/framework/apk_utils.dart index 0c42b2652899b..0dc28b92e2e98 100644 --- a/dev/devicelab/lib/framework/apk_utils.dart +++ b/dev/devicelab/lib/framework/apk_utils.dart @@ -83,93 +83,6 @@ bool hasMultipleOccurrences(String text, Pattern pattern) { return text.indexOf(pattern) != text.lastIndexOf(pattern); } -/// Utility class to analyze the content inside an APK using dexdump, -/// which is provided by the Android SDK. -/// https://android.googlesource.com/platform/art/+/master/dexdump/dexdump.cc -class ApkExtractor { - ApkExtractor(this.apkFile); - - /// The APK. - final File apkFile; - - bool _extracted = false; - - Directory _outputDir; - - Future _extractApk() async { - if (_extracted) { - return; - } - _outputDir = apkFile.parent.createTempSync('apk'); - if (Platform.isWindows) { - await eval('7za', ['x', apkFile.path], workingDirectory: _outputDir.path); - } else { - await eval('unzip', [apkFile.path], workingDirectory: _outputDir.path); - } - _extracted = true; - } - - /// Returns the full path to the [dexdump] tool. - Future _findDexDump() async { - final String androidHome = Platform.environment['ANDROID_HOME'] ?? - Platform.environment['ANDROID_SDK_ROOT']; - - if (androidHome == null || androidHome.isEmpty) { - throw Exception('Unset env flag: `ANDROID_HOME` or `ANDROID_SDK_ROOT`.'); - } - String dexdumps; - if (Platform.isWindows) { - dexdumps = await eval('dir', ['/s/b', 'dexdump.exe'], - workingDirectory: androidHome); - } else { - dexdumps = await eval('find', [androidHome, '-name', 'dexdump']); - } - if (dexdumps.isEmpty) { - throw Exception('Couldn\'t find a dexdump executable.'); - } - return dexdumps.split('\n').first; - } - - // Removes any temporary directory. - void dispose() { - if (!_extracted) { - return; - } - rmTree(_outputDir); - _extracted = true; - } - - /// Returns true if the APK contains a given class. - Future containsClass(String className) async { - await _extractApk(); - - final String dexDump = await _findDexDump(); - final String classesDex = path.join(_outputDir.path, 'classes.dex'); - - if (!File(classesDex).existsSync()) { - throw Exception('Couldn\'t find classes.dex in the APK.'); - } - final String classDescriptors = await eval(dexDump, - [classesDex], printStdout: false); - - if (classDescriptors.isEmpty) { - throw Exception('No descriptors found in classes.dex.'); - } - return classDescriptors.contains(className.replaceAll('.', '/')); - } -} - - /// Checks that the classes are contained in the APK, throws otherwise. -Future checkApkContainsClasses(File apk, List classes) async { - final ApkExtractor extractor = ApkExtractor(apk); - for (String className in classes) { - if (!(await extractor.containsClass(className))) { - throw Exception('APK doesn\'t contain class `$className`.'); - } - } - extractor.dispose(); -} - class FlutterProject { FlutterProject(this.parent, this.name); diff --git a/dev/devicelab/lib/framework/utils.dart b/dev/devicelab/lib/framework/utils.dart index 4cb5ed7fb5793..68ef7987abd3b 100644 --- a/dev/devicelab/lib/framework/utils.dart +++ b/dev/devicelab/lib/framework/utils.dart @@ -303,7 +303,7 @@ Future exec( /// Executes a command and returns its standard output as a String. /// -/// For logging purposes, the command's output is also printed out by default. +/// For logging purposes, the command's output is also printed out. Future eval( String executable, List arguments, { @@ -311,8 +311,6 @@ Future eval( bool canFail = false, // as in, whether failures are ok. False means that they are fatal. String workingDirectory, StringBuffer stderr, // if not null, the stderr will be written here - bool printStdout = true, - bool printStderr = true, }) async { final Process process = await startProcess(executable, arguments, environment: environment, workingDirectory: workingDirectory); @@ -323,18 +321,14 @@ Future eval( .transform(utf8.decoder) .transform(const LineSplitter()) .listen((String line) { - if (printStdout) { - print('stdout: $line'); - } + print('stdout: $line'); output.writeln(line); }, onDone: () { stdoutDone.complete(); }); process.stderr .transform(utf8.decoder) .transform(const LineSplitter()) .listen((String line) { - if (printStderr) { - print('stderr: $line'); - } + print('stderr: $line'); stderr?.writeln(line); }, onDone: () { stderrDone.complete(); }); @@ -625,10 +619,3 @@ void setLocalEngineOptionIfNecessary(List options, [String flavor]) { options.add('--local-engine=${osNames[deviceOperatingSystem]}_$flavor'); } } - -/// Checks that the file exists, otherwise throws a [FileSystemException]. -void checkFileExists(String file) { - if (!exists(File(file))) { - throw FileSystemException('Expected file to exit.', file); - } -} diff --git a/packages/flutter_tools/gradle/aar_init_script.gradle b/packages/flutter_tools/gradle/aar_init_script.gradle deleted file mode 100644 index 1285c58819078..0000000000000 --- a/packages/flutter_tools/gradle/aar_init_script.gradle +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 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. -// -// This script is used to initialize the build in a module or plugin project. -// During this phase, the script applies the Maven plugin and configures the -// destination of the local repository. -// The local repository will contain the AAR and POM files. - -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.maven.MavenDeployer -import org.gradle.api.plugins.MavenPlugin -import org.gradle.api.tasks.Upload - -void configureProject(Project project, File outputDir) { - if (!project.hasProperty("android")) { - throw new GradleException("Android property not found.") - } - if (!project.android.hasProperty("libraryVariants")) { - throw new GradleException("Can't generate AAR on a non Android library project."); - } - - project.apply plugin: "maven" - - project.android.libraryVariants.all { variant -> - addAarTask(project, variant) - } - // Snapshot versions include the timestamp in the artifact name. - // Therefore, remove the snapshot part, so new runs of `flutter build aar` overrides existing artifacts. - // This version isn't relevant in Flutter since the pub version is used - // to resolve dependencies. - project.version = project.version.replace("-SNAPSHOT", "") - - project.uploadArchives { - repositories { - mavenDeployer { - repository(url: "file://${outputDir}/outputs/repo") - } - } - } - // Check if the project uses the Flutter plugin (defined in flutter.gradle). - Boolean usesFlutterPlugin = project.plugins.find { it.class.name == "FlutterPlugin" } != null - if (!usesFlutterPlugin) { - // Plugins don't include their dependencies under the assumption that the parent project adds them. - if (project.properties['android.useAndroidX']) { - project.dependencies { - compileOnly "androidx.annotation:annotation:+" - } - } else { - project.dependencies { - compileOnly "com.android.support:support-annotations:+" - } - } - project.dependencies { - // The Flutter plugin already adds `flutter.jar`. - compileOnly project.files("${getFlutterRoot(project)}/bin/cache/artifacts/engine/android-arm-release/flutter.jar") - } - } -} - -String getFlutterRoot(Project project) { - if (!project.hasProperty("flutter-root")) { - throw new GradleException("The `-Pflutter-root` flag must be specified.") - } - return project.property("flutter-root") -} - -void addAarTask(Project project, variant) { - String variantName = variant.name.capitalize() - String taskName = "assembleAar${variantName}" - project.tasks.create(name: taskName) { - // This check is required to be able to configure the archives before `uploadArchives` runs. - if (!project.gradle.startParameter.taskNames.contains(taskName)) { - return - } - // NOTE(blasten): `android.defaultPublishConfig` must equal the variant name to build. - // Where variant name is ``. However, it's too late to configure - // `defaultPublishConfig` at this point. Therefore, the code below ensures that the - // default build config uses the artifacts produced for the specific build variant. - Task bundle = project.tasks.findByName("bundle${variantName}Aar") // gradle:3.2.0 - if (bundle == null) { - bundle = project.tasks.findByName("bundle${variantName}") // gradle:3.1.0 - } - if (bundle == null) { - throw new GradleException("Can't generate AAR for variant ${variantName}."); - } - project.uploadArchives.repositories.mavenDeployer { - pom { - artifactId = "${project.name}_${variant.name.toLowerCase()}" - } - } - // Clear the current archives since the current one is assigned based on - // `android.defaultPublishConfig` which defaults to `release`. - project.configurations["archives"].artifacts.clear() - // Add the artifact that will be published. - project.artifacts.add("archives", bundle) - // Generate the Maven artifacts. - finalizedBy "uploadArchives" - } -} - -projectsEvaluated { - if (rootProject.property("is-plugin").toBoolean()) { - if (rootProject.hasProperty("output-dir")) { - rootProject.buildDir = rootProject.property("output-dir") - } else { - rootProject.buildDir = "../build"; - } - // In plugin projects, the Android library is the root project. - configureProject(rootProject, rootProject.buildDir) - return - } - // In module projects, the Android library project is the `:flutter` subproject. - Project androidLibrarySubproject = rootProject.subprojects.find { it.name == "flutter" } - // In module projects, the `buildDir` is defined in the `:app` subproject. - Project appSubproject = rootProject.subprojects.find { it.name == "app" } - - assert appSubproject != null - assert androidLibrarySubproject != null - - if (appSubproject.hasProperty("output-dir")) { - appSubproject.buildDir = appSubproject.property("output-dir") - } else { - appSubproject.buildDir = "../build/host" - } - configureProject(androidLibrarySubproject, appSubproject.buildDir) -} diff --git a/packages/flutter_tools/gradle/deprecated_settings.gradle b/packages/flutter_tools/gradle/deprecated_settings.gradle deleted file mode 100644 index 98e3600b90e31..0000000000000 --- a/packages/flutter_tools/gradle/deprecated_settings.gradle +++ /dev/null @@ -1,31 +0,0 @@ -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} -;EOF -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withInputStream { stream -> plugins.load(stream) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle index 50f40281b29c9..52317dc907243 100644 --- a/packages/flutter_tools/gradle/flutter.gradle +++ b/packages/flutter_tools/gradle/flutter.gradle @@ -1,13 +1,8 @@ -// Copyright 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 static groovy.io.FileType.FILES +import java.nio.file.Path +import java.nio.file.Paths import com.android.builder.model.AndroidProject import com.android.build.OutputFile -import java.nio.file.Path -import java.nio.file.Paths import org.apache.tools.ant.taskdefs.condition.Os import org.gradle.api.DefaultTask import org.gradle.api.GradleException @@ -96,7 +91,7 @@ class FlutterPlugin implements Plugin { @Override void apply(Project project) { project.extensions.create("flutter", FlutterExtension) - project.afterEvaluate this.&addFlutterTasks + project.afterEvaluate this.&addFlutterTask // By default, assembling APKs generates fat APKs if multiple platforms are passed. // Configuring split per ABI allows to generate separate APKs for each abi. @@ -208,116 +203,40 @@ class FlutterPlugin implements Plugin { }) } } - } - - /** - * Returns the directory where the plugins are built. - */ - private File getPluginBuildDir(Project project) { - // Module projects specify this flag to include plugins in the same repo as the module project. - if (project.ext.has("pluginBuildDir")) { - return project.ext.get("pluginBuildDir") - } - return project.buildDir - } - private Properties getPluginList(Project project) { File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins') - return readPropertiesIfExist(pluginsFile) - } - - private void addPluginTasks(Project project) { - Properties plugins = getPluginList(project) - project.android.buildTypes.each { buildType -> - plugins.each { name, path -> - String buildModeValue = buildType.debuggable ? "debug" : "release" - List taskNameParts = ["build", "plugin", buildModeValue] - taskNameParts.addAll(name.split("_")) - String taskName = toCammelCase(taskNameParts) - // Build types can be extended. For example, a build type can extend the `debug` mode. - // In such cases, prevent creating the same task. - if (project.tasks.findByName(taskName) == null) { - project.tasks.create(name: taskName, type: FlutterPluginTask) { - flutterExecutable this.flutterExecutable - buildMode buildModeValue - verbose isVerbose(project) - pluginDir project.file(path) - sourceDir project.file(project.flutter.source) - intermediateDir getPluginBuildDir(project) + Properties plugins = readPropertiesIfExist(pluginsFile) + + plugins.each { name, _ -> + def pluginProject = project.rootProject.findProject(":$name") + if (pluginProject != null) { + project.dependencies { + if (project.getConfigurations().findByName("implementation")) { + implementation pluginProject + } else { + compile pluginProject } } - } - } - } - - private void buildPlugins(Project project, Set buildTypes) { - List projects = [project] - // Module projects set the `hostProjects` extra property in `include_flutter.groovy`. - // This is required to set the local repository in each host app project. - if (project.ext.has("hostProjects")) { - projects.addAll(project.ext.get("hostProjects")) - } - projects.each { hostProject -> - hostProject.repositories { - maven { - url "${getPluginBuildDir(project)}/outputs/repo" - } - } - } - buildTypes.each { buildType -> - project.tasks.withType(FlutterPluginTask).all { pluginTask -> - String buildMode = buildType.debuggable ? "debug" : "release" - if (pluginTask.buildMode != buildMode) { - return - } - pluginTask.execute() - pluginTask.intermediateDir.eachFileRecurse(FILES) { file -> - if (file.name != "maven-metadata.xml") { - return + pluginProject.afterEvaluate { + pluginProject.android.buildTypes { + profile { + initWith debug + } } - def mavenMetadata = new XmlParser().parse(file) - String groupId = mavenMetadata.groupId.text() - String artifactId = mavenMetadata.artifactId.text() - if (!artifactId.endsWith(buildMode)) { - return + pluginProject.android.buildTypes.each { + def buildMode = buildModeFor(it) + addFlutterJarCompileOnlyDependency(pluginProject, it.name, project.files( flutterJar ?: baseJar[buildMode] )) + } + pluginProject.android.buildTypes.whenObjectAdded { + def buildMode = buildModeFor(it) + addFlutterJarCompileOnlyDependency(pluginProject, it.name, project.files( flutterJar ?: baseJar[buildMode] )) } - // Add the plugin dependency based on the Maven metadata. - addApiDependencies(project, buildType.name, "$groupId:$artifactId:+@aar", { - transitive = true - }) - } - } - } - } - - /** - * Returns a set with the build type names that apply to the given list of tasks - * required to configure the plugin dependencies. - */ - private Set getBuildTypesForTasks(Project project, List tasksToExecute) { - Set buildTypes = [] - tasksToExecute.each { task -> - project.android.buildTypes.each { buildType -> - if (task == "androidDependencies" || task.endsWith("dependencies")) { - // The tasks to query the dependencies includes all the build types. - buildTypes.add(buildType) - } else if (task.endsWith("assemble")) { - // The `assemble` task includes all the build types. - buildTypes.add(buildType) - } else if (task.endsWith(buildType.name.capitalize())) { - buildTypes.add(buildType) } + } else { + project.logger.error("Plugin project :$name not found. Please update settings.gradle.") } } - return buildTypes - } - - private static String toCammelCase(List parts) { - if (parts.empty) { - return "" - } - return "${parts[0]}${parts[1..-1].collect { it.capitalize() }.join('')}" } private String resolveProperty(Project project, String name, String defaultValue) { @@ -368,17 +287,6 @@ class FlutterPlugin implements Plugin { return project.hasProperty('localEngineOut') } - private static Boolean isVerbose(Project project) { - if (project.hasProperty('verbose')) { - return project.property('verbose').toBoolean() - } - return false - } - - private static Boolean buildPluginAsAar() { - return System.getProperty('build-plugins-as-aars') == 'true' - } - /** * Returns the platform that is used to extract the `libflutter.so` and the .class files. * @@ -396,24 +304,30 @@ class FlutterPlugin implements Plugin { if (project.state.failure) { return } - String configuration; - if (project.getConfigurations().findByName("compileOnly")) { - configuration = "${variantName}CompileOnly"; - } else { - configuration = "${variantName}Provided"; + + project.dependencies { + String configuration; + if (project.getConfigurations().findByName("compileOnly")) { + configuration = "${variantName}CompileOnly"; + } else { + configuration = "${variantName}Provided"; + } + + add(configuration, files) } - project.dependencies.add(configuration, files) } - private static void addApiDependencies(Project project, String variantName, Object dependency, Closure config = null) { - String configuration; - // `compile` dependencies are now `api` dependencies. - if (project.getConfigurations().findByName("api")) { - configuration = "${variantName}Api"; - } else { - configuration = "${variantName}Compile"; + private static void addApiDependencies(Project project, String variantName, FileCollection files) { + project.dependencies { + String configuration; + // `compile` dependencies are now `api` dependencies. + if (project.getConfigurations().findByName("api")) { + configuration = "${variantName}Api"; + } else { + configuration = "${variantName}Compile"; + } + add(configuration, files) } - project.dependencies.add(configuration, dependency, config) } /** @@ -441,13 +355,14 @@ class FlutterPlugin implements Plugin { return "${targetArch}-release" } - private void addFlutterTasks(Project project) { + private void addFlutterTask(Project project) { if (project.state.failure) { return } if (project.flutter.source == null) { throw new GradleException("Must provide Flutter source directory") } + String target = project.flutter.target if (target == null) { target = 'lib/main.dart' @@ -456,6 +371,10 @@ class FlutterPlugin implements Plugin { target = project.property('target') } + Boolean verboseValue = null + if (project.hasProperty('verbose')) { + verboseValue = project.property('verbose').toBoolean() + } String[] fileSystemRootsValue = null if (project.hasProperty('filesystem-roots')) { fileSystemRootsValue = project.property('filesystem-roots').split('\\|') @@ -521,9 +440,10 @@ class FlutterPlugin implements Plugin { } } - def compileTasks = targetPlatforms.collect { targetArch -> + def flutterTasks = [] + targetPlatforms.each { targetArch -> String abiValue = PLATFORM_ARCH_MAP[targetArch] - String taskName = toCammelCase(["compile", FLUTTER_BUILD_PREFIX, variant.name, targetArch.replace('android-', '')]) + String taskName = "compile${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}${targetArch.replace('android-', '').capitalize()}" FlutterTask compileTask = project.tasks.create(name: taskName, type: FlutterTask) { flutterRoot this.flutterRoot flutterExecutable this.flutterExecutable @@ -532,7 +452,7 @@ class FlutterPlugin implements Plugin { localEngineSrcPath this.localEngineSrcPath abi abiValue targetPath target - verbose isVerbose(project) + verbose verboseValue fileSystemRoots fileSystemRootsValue fileSystemScheme fileSystemSchemeValue trackWidgetCreation trackWidgetCreationValue @@ -546,8 +466,8 @@ class FlutterPlugin implements Plugin { extraFrontEndOptions extraFrontEndOptionsValue extraGenSnapshotOptions extraGenSnapshotOptionsValue } + flutterTasks.add(compileTask) } - def libJar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/libs.jar") def libFlutterPlatforms = targetPlatforms.collect() // x86/x86_64 native library used for debugging only, for now. @@ -576,13 +496,13 @@ class FlutterPlugin implements Plugin { include 'lib/**' } } - dependsOn compileTasks + dependsOn flutterTasks // Add the ELF library. - compileTasks.each { compileTask -> - from(compileTask.intermediateDir) { + flutterTasks.each { flutterTask -> + from(flutterTask.intermediateDir) { include '*.so' rename { String filename -> - return "lib/${compileTask.abi}/lib${filename}" + return "lib/${flutterTask.abi}/lib${filename}" } } } @@ -596,7 +516,7 @@ class FlutterPlugin implements Plugin { Task packageAssets = project.tasks.findByPath(":flutter:package${variant.name.capitalize()}Assets") Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets") Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) { - dependsOn compileTasks + dependsOn flutterTasks if (packageAssets && cleanPackageAssets) { dependsOn packageAssets dependsOn cleanPackageAssets @@ -607,7 +527,7 @@ class FlutterPlugin implements Plugin { variant.mergeAssets.mustRunAfter("clean${variant.mergeAssets.name.capitalize()}") into variant.mergeAssets.outputDir } - compileTasks.each { flutterTask -> + flutterTasks.each { flutterTask -> with flutterTask.assets } } @@ -630,62 +550,12 @@ class FlutterPlugin implements Plugin { processResources.dependsOn(copyFlutterAssetsTask) } } + if (project.android.hasProperty("applicationVariants")) { project.android.applicationVariants.all addFlutterDeps } else { project.android.libraryVariants.all addFlutterDeps } - - if (buildPluginAsAar()) { - addPluginTasks(project) - - List tasksToExecute = project.gradle.startParameter.taskNames - Set buildTypes = getBuildTypesForTasks(project, tasksToExecute) - if (tasksToExecute.contains("clean")) { - // Because the plugins are built during configuration, the task "clean" - // cannot run in conjunction with an assembly task. - if (!buildTypes.empty) { - throw new GradleException("Can't run the clean task along with other assemble tasks") - } - } - // Build plugins when a task "assembly*" will be called later. - if (!buildTypes.empty) { - // Build the plugin during configuration. - // This is required when Jetifier is enabled, otherwise the implementation dependency - // cannot be added. - buildPlugins(project, buildTypes) - } - } else { - getPluginList(project).each { name, _ -> - def pluginProject = project.rootProject.findProject(":$name") - if (pluginProject != null) { - project.dependencies { - if (project.getConfigurations().findByName("implementation")) { - implementation pluginProject - } else { - compile pluginProject - } - } - pluginProject.afterEvaluate { - pluginProject.android.buildTypes { - profile { - initWith debug - } - } - pluginProject.android.buildTypes.each { - def buildMode = buildModeFor(it) - addFlutterJarCompileOnlyDependency(pluginProject, it.name, project.files( flutterJar ?: baseJar[buildMode] )) - } - pluginProject.android.buildTypes.whenObjectAdded { - def buildMode = buildModeFor(it) - addFlutterJarCompileOnlyDependency(pluginProject, it.name, project.files( flutterJar ?: baseJar[buildMode] )) - } - } - } else { - project.logger.error("Plugin project :$name not found. Please update settings.gradle.") - } - } - } } } @@ -914,59 +784,6 @@ class FlutterTask extends BaseFlutterTask { } } -class FlutterPluginTask extends DefaultTask { - File flutterExecutable - @Optional @Input - Boolean verbose - @Input - String buildMode - @Input - File pluginDir - @Input - File intermediateDir - File sourceDir - - @InputFiles - FileCollection getSourceFiles() { - return project.fileTree( - dir: sourceDir, - exclude: ["android", "ios"], - include: ["pubspec.yaml"] - ) - } - - @OutputDirectory - File getOutputDirectory() { - return intermediateDir - } - - @TaskAction - void build() { - intermediateDir.mkdirs() - project.exec { - executable flutterExecutable.absolutePath - workingDir pluginDir - args "build", "aar" - args "--quiet" - args "--suppress-analytics" - args "--output-dir", "${intermediateDir}" - switch (buildMode) { - case 'release': - args "--release" - break - case 'debug': - args "--debug" - break - default: - assert false - } - if (verbose) { - args "--verbose" - } - } - } -} - gradle.useLogger(new FlutterEventLogger()) class FlutterEventLogger extends BuildAdapter implements TaskExecutionListener { diff --git a/packages/flutter_tools/gradle/manual_migration_settings.gradle.md b/packages/flutter_tools/gradle/manual_migration_settings.gradle.md deleted file mode 100644 index f899531917bff..0000000000000 --- a/packages/flutter_tools/gradle/manual_migration_settings.gradle.md +++ /dev/null @@ -1,19 +0,0 @@ -To manually update `settings.gradle`, follow these steps: - - 1. Copy `settings.gradle` as `settings_aar.gradle` - 2. Remove the following code from `settings_aar.gradle`: - - def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - - def plugins = new Properties() - def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') - if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } - } - - plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory - } - diff --git a/packages/flutter_tools/gradle/settings_aar.gradle.tmpl b/packages/flutter_tools/gradle/settings_aar.gradle.tmpl deleted file mode 100644 index e7b4def49cb53..0000000000000 --- a/packages/flutter_tools/gradle/settings_aar.gradle.tmpl +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/packages/flutter_tools/lib/src/android/aar.dart b/packages/flutter_tools/lib/src/android/aar.dart deleted file mode 100644 index f619f775e0f0f..0000000000000 --- a/packages/flutter_tools/lib/src/android/aar.dart +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 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 'package:meta/meta.dart'; - -import '../base/common.dart'; -import '../build_info.dart'; -import '../project.dart'; - -import 'android_sdk.dart'; -import 'gradle.dart'; - -/// Provides a method to build a module or plugin as AAR. -abstract class AarBuilder { - /// Builds the AAR artifacts. - Future build({ - @required FlutterProject project, - @required AndroidBuildInfo androidBuildInfo, - @required String target, - @required String outputDir, - }); -} - -/// Default implementation of [AarBuilder]. -class AarBuilderImpl extends AarBuilder { - AarBuilderImpl(); - - /// Builds the AAR and POM files for the current Flutter module or plugin. - @override - Future build({ - @required FlutterProject project, - @required AndroidBuildInfo androidBuildInfo, - @required String target, - @required String outputDir, - }) async { - if (!project.android.isUsingGradle) { - throwToolExit( - 'The build process for Android has changed, and the current project configuration\n' - 'is no longer valid. Please consult\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.' - ); - } - if (!project.manifest.isModule && !project.manifest.isPlugin) { - throwToolExit('AARs can only be built for plugin or module projects.'); - } - // Validate that we can find an Android SDK. - if (androidSdk == null) { - throwToolExit('No Android SDK found. Try setting the `ANDROID_SDK_ROOT` environment variable.'); - } - await buildGradleAar( - project: project, - androidBuildInfo: androidBuildInfo, - target: target, - outputDir: outputDir, - ); - androidSdk.reinitialize(); - } -} diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart index 7d4aa9eb3181f..bf0ad9afbba6c 100644 --- a/packages/flutter_tools/lib/src/android/gradle.dart +++ b/packages/flutter_tools/lib/src/android/gradle.dart @@ -17,10 +17,8 @@ import '../base/platform.dart'; import '../base/process.dart'; import '../base/terminal.dart'; import '../base/utils.dart'; -import '../base/version.dart'; import '../build_info.dart'; import '../cache.dart'; -import '../features.dart'; import '../flutter_manifest.dart'; import '../globals.dart'; import '../project.dart'; @@ -29,10 +27,10 @@ import '../runner/flutter_command.dart'; import 'android_sdk.dart'; import 'android_studio.dart'; +const String gradleVersion = '4.10.2'; final RegExp _assembleTaskPattern = RegExp(r'assemble(\S+)'); -GradleProject _cachedGradleAppProject; -GradleProject _cachedGradleLibraryProject; +GradleProject _cachedGradleProject; String _cachedGradleExecutable; enum FlutterPluginVersion { @@ -104,19 +102,14 @@ Future getGradleAppOut(AndroidProject androidProject) async { case FlutterPluginVersion.managed: // Fall through. The managed plugin matches plugin v2 for now. case FlutterPluginVersion.v2: - return fs.file((await _gradleAppProject()).apkDirectory.childFile('app.apk')); + return fs.file((await _gradleProject()).apkDirectory.childFile('app.apk')); } return null; } -Future _gradleAppProject() async { - _cachedGradleAppProject ??= await _readGradleProject(isLibrary: false); - return _cachedGradleAppProject; -} - -Future _gradleLibraryProject() async { - _cachedGradleLibraryProject ??= await _readGradleProject(isLibrary: true); - return _cachedGradleLibraryProject; +Future _gradleProject() async { + _cachedGradleProject ??= await _readGradleProject(); + return _cachedGradleProject; } /// Runs `gradlew dependencies`, ensuring that dependencies are resolved and @@ -134,98 +127,32 @@ Future checkGradleDependencies() async { progress.stop(); } -/// Tries to create `settings_aar.gradle` in an app project by removing the subprojects -/// from the existing `settings.gradle` file. This operation will fail if the existing -/// `settings.gradle` file has local edits. -void createSettingsAarGradle(Directory androidDirectory) { - final File newSettingsFile = androidDirectory.childFile('settings_aar.gradle'); - if (newSettingsFile.existsSync()) { - return; - } - final File currentSettingsFile = androidDirectory.childFile('settings.gradle'); - if (!currentSettingsFile.existsSync()) { - return; - } - final String currentFileContent = currentSettingsFile.readAsStringSync(); - - final String newSettingsRelativeFile = fs.path.relative(newSettingsFile.path); - final Status status = logger.startProgress('✏️ Creating `$newSettingsRelativeFile`...', - timeout: timeoutConfiguration.fastOperation); - - final String flutterRoot = fs.path.absolute(Cache.flutterRoot); - final File deprecatedFile = fs.file(fs.path.join(flutterRoot, 'packages','flutter_tools', - 'gradle', 'deprecated_settings.gradle')); - assert(deprecatedFile.existsSync()); - // Get the `settings.gradle` content variants that should be patched. - final List deprecatedFilesContent = deprecatedFile.readAsStringSync().split(';EOF'); - bool exactMatch = false; - for (String deprecatedFileContent in deprecatedFilesContent) { - if (currentFileContent.trim() == deprecatedFileContent.trim()) { - exactMatch = true; - break; - } - } - if (!exactMatch) { - status.cancel(); - printError('*******************************************************************************************'); - printError('Flutter tried to create the file `$newSettingsRelativeFile`, but failed.'); - // Print how to manually update the file. - printError(fs.file(fs.path.join(flutterRoot, 'packages','flutter_tools', - 'gradle', 'manual_migration_settings.gradle.md')).readAsStringSync()); - printError('*******************************************************************************************'); - throwToolExit('Please create the file and run this command again.'); - } - // Copy the new file. - final String settingsAarContent = fs.file(fs.path.join(flutterRoot, 'packages','flutter_tools', - 'gradle', 'settings_aar.gradle.tmpl')).readAsStringSync(); - newSettingsFile.writeAsStringSync(settingsAarContent); - status.stop(); - printStatus('✅ `$newSettingsRelativeFile` created successfully.'); -} - // Note: Dependencies are resolved and possibly downloaded as a side-effect // of calculating the app properties using Gradle. This may take minutes. -Future _readGradleProject({bool isLibrary = false}) async { +Future _readGradleProject() async { final FlutterProject flutterProject = FlutterProject.current(); final String gradle = await _ensureGradle(flutterProject); updateLocalProperties(project: flutterProject); - - final FlutterManifest manifest = flutterProject.manifest; - final Directory hostAppGradleRoot = flutterProject.android.hostAppGradleRoot; - - if (featureFlags.isPluginAsAarEnabled && - !manifest.isPlugin && !manifest.isModule) { - createSettingsAarGradle(hostAppGradleRoot); - } - if (manifest.isPlugin) { - assert(isLibrary); - return GradleProject( - ['debug', 'profile', 'release'], - [], // Plugins don't have flavors. - flutterProject.directory.childDirectory('build').path, - ); - } final Status status = logger.startProgress('Resolving dependencies...', timeout: timeoutConfiguration.slowOperation); GradleProject project; - // Get the properties and tasks from Gradle, so we can determinate the `buildDir`, - // flavors and build types defined in the project. If gradle fails, then check if the failure is due to t try { final RunResult propertiesRunResult = await runCheckedAsync( - [gradle, isLibrary ? 'properties' : 'app:properties'], - workingDirectory: hostAppGradleRoot.path, + [gradle, 'app:properties'], + workingDirectory: flutterProject.android.hostAppGradleRoot.path, environment: _gradleEnv, ); final RunResult tasksRunResult = await runCheckedAsync( - [gradle, isLibrary ? 'tasks': 'app:tasks', '--all', '--console=auto'], - workingDirectory: hostAppGradleRoot.path, + [gradle, 'app:tasks', '--all', '--console=auto'], + workingDirectory: flutterProject.android.hostAppGradleRoot.path, environment: _gradleEnv, ); project = GradleProject.fromAppProperties(propertiesRunResult.stdout, tasksRunResult.stdout); } catch (exception) { if (getFlutterPluginVersion(flutterProject.android) == FlutterPluginVersion.managed) { status.cancel(); - // Handle known exceptions. - throwToolExitIfLicenseNotAccepted(exception); + // Handle known exceptions. This will exit if handled. + handleKnownGradleExceptions(exception.toString()); + // Print a general Gradle error and exit. printError('* Error running Gradle:\n$exception\n'); throwToolExit('Please review your Gradle project setup in the android/ folder.'); @@ -233,23 +160,23 @@ Future _readGradleProject({bool isLibrary = false}) async { // Fall back to the default project = GradleProject( ['debug', 'profile', 'release'], - [], - fs.path.join(flutterProject.android.hostAppGradleRoot.path, 'app', 'build') + [], flutterProject.android.gradleAppOutV1Directory, + flutterProject.android.gradleAppBundleOutV1Directory, ); } status.stop(); return project; } -/// Handle Gradle error thrown when Gradle needs to download additional -/// Android SDK components (e.g. Platform Tools), and the license -/// for that component has not been accepted. -void throwToolExitIfLicenseNotAccepted(Exception exception) { - const String licenseNotAcceptedMatcher = +void handleKnownGradleExceptions(String exceptionString) { + // Handle Gradle error thrown when Gradle needs to download additional + // Android SDK components (e.g. Platform Tools), and the license + // for that component has not been accepted. + const String matcher = r'You have not accepted the license agreements of the following SDK components:' r'\s*\[(.+)\]'; - final RegExp licenseFailure = RegExp(licenseNotAcceptedMatcher, multiLine: true); - final Match licenseMatch = licenseFailure.firstMatch(exception.toString()); + final RegExp licenseFailure = RegExp(matcher, multiLine: true); + final Match licenseMatch = licenseFailure.firstMatch(exceptionString); if (licenseMatch != null) { final String missingLicenses = licenseMatch.group(1); final String errorMessage = @@ -306,7 +233,6 @@ void injectGradleWrapper(Directory directory) { _locateGradlewExecutable(directory); final File propertiesFile = directory.childFile(fs.path.join('gradle', 'wrapper', 'gradle-wrapper.properties')); if (!propertiesFile.existsSync()) { - final String gradleVersion = getGradleVersionForAndroidPlugin(directory); propertiesFile.writeAsStringSync(''' distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists @@ -318,78 +244,6 @@ distributionUrl=https\\://services.gradle.org/distributions/gradle-$gradleVersio } } -/// Returns true if [targetVersion] is within the range [min] and [max] inclusive. -bool _isWithinVersionRange(String targetVersion, {String min, String max}) { - final Version parsedTargetVersion = Version.parse(targetVersion); - return parsedTargetVersion >= Version.parse(min) && - parsedTargetVersion <= Version.parse(max); -} - -const String defaultGradleVersion = '4.10.2'; - -/// Returns the Gradle version that is required by the given Android Gradle plugin version -/// by picking the largest compatible version from -/// https://developer.android.com/studio/releases/gradle-plugin#updating-gradle -String getGradleVersionFor(String androidPluginVersion) { - if (_isWithinVersionRange(androidPluginVersion, min: '1.0.0', max: '1.1.3')) { - return '2.3'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '1.2.0', max: '1.3.1')) { - return '2.9'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '1.5.0', max: '1.5.0')) { - return '2.2.1'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '2.0.0', max: '2.1.2')) { - return '2.13'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '2.1.3', max: '2.2.3')) { - return '2.14.1'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '2.3.0', max: '2.9.9')) { - return '3.3'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '3.0.0', max: '3.0.9')) { - return '4.1'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '3.1.0', max: '3.1.9')) { - return '4.4'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '3.2.0', max: '3.2.1')) { - return '4.6'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '3.3.0', max: '3.3.2')) { - return '4.10.2'; - } - if (_isWithinVersionRange(androidPluginVersion, min: '3.4.0', max: '3.5.0')) { - return '5.1.1'; - } - throwToolExit('Unsuported Android Plugin version: $androidPluginVersion.'); - return ''; -} - -final RegExp _androidPluginRegExp = RegExp('com\.android\.tools\.build\:gradle\:(\\d+\.\\d+\.\\d+\)'); - -/// Returns the Gradle version that the current Android plugin depends on when found, -/// otherwise it returns a default version. -/// -/// The Android plugin version is specified in the [build.gradle] file within -/// the project's Android directory. -String getGradleVersionForAndroidPlugin(Directory directory) { - final File buildFile = directory.childFile('build.gradle'); - if (!buildFile.existsSync()) { - return defaultGradleVersion; - } - final String buildFileContent = buildFile.readAsStringSync(); - final Iterable pluginMatches = _androidPluginRegExp.allMatches(buildFileContent); - - if (pluginMatches.isEmpty) { - return defaultGradleVersion; - } - final String androidPluginVersion = pluginMatches.first.group(1); - return getGradleVersionFor(androidPluginVersion); -} - /// Overwrite local.properties in the specified Flutter project's Android /// sub-project, if needed. /// @@ -493,95 +347,6 @@ Future buildGradleProject({ } } -Future buildGradleAar({ - @required FlutterProject project, - @required AndroidBuildInfo androidBuildInfo, - @required String target, - @required String outputDir, -}) async { - final FlutterManifest manifest = project.manifest; - - GradleProject gradleProject; - if (manifest.isModule) { - gradleProject = await _gradleAppProject(); - } else if (manifest.isPlugin) { - gradleProject = await _gradleLibraryProject(); - } else { - throwToolExit('AARs can only be built for plugin or module projects.'); - } - - if (outputDir != null && outputDir.isNotEmpty) { - gradleProject.buildDirectory = outputDir; - } - - final String aarTask = gradleProject.aarTaskFor(androidBuildInfo.buildInfo); - if (aarTask == null) { - printUndefinedTask(gradleProject, androidBuildInfo.buildInfo); - throwToolExit('Gradle build aborted.'); - } - final Status status = logger.startProgress( - 'Running Gradle task \'$aarTask\'...', - timeout: timeoutConfiguration.slowOperation, - multilineOutput: true, - ); - - final String gradle = await _ensureGradle(project); - final String gradlePath = fs.file(gradle).absolute.path; - final String flutterRoot = fs.path.absolute(Cache.flutterRoot); - final String initScript = fs.path.join(flutterRoot, 'packages','flutter_tools', 'gradle', 'aar_init_script.gradle'); - final List command = [ - gradlePath, - '-I=$initScript', - '-Pflutter-root=$flutterRoot', - '-Poutput-dir=${gradleProject.buildDirectory}', - '-Pis-plugin=${manifest.isPlugin}', - '-Dbuild-plugins-as-aars=true', - ]; - - if (target != null && target.isNotEmpty) { - command.add('-Ptarget=$target'); - } - - if (androidBuildInfo.targetArchs.isNotEmpty) { - final String targetPlatforms = androidBuildInfo.targetArchs - .map(getPlatformNameForAndroidArch).join(','); - command.add('-Ptarget-platform=$targetPlatforms'); - } - command.add(aarTask); - - final Stopwatch sw = Stopwatch()..start(); - int exitCode = 1; - - try { - exitCode = await runCommandAndStreamOutput( - command, - workingDirectory: project.android.hostAppGradleRoot.path, - allowReentrantFlutter: true, - environment: _gradleEnv, - mapFunction: (String line) { - // Always print the full line in verbose mode. - if (logger.isVerbose) { - return line; - } - return null; - }, - ); - } finally { - status.stop(); - } - flutterUsage.sendTiming('build', 'gradle-aar', Duration(milliseconds: sw.elapsedMilliseconds)); - - if (exitCode != 0) { - throwToolExit('Gradle task $aarTask failed with exit code $exitCode', exitCode: exitCode); - } - - final Directory repoDirectory = gradleProject.repoDirectory; - if (!repoDirectory.existsSync()) { - throwToolExit('Gradle task $aarTask failed to produce $repoDirectory', exitCode: exitCode); - } - printStatus('Built ${fs.path.relative(repoDirectory.path)}.', color: TerminalColor.green); -} - Future _buildGradleProjectV1(FlutterProject project, String gradle) async { // Run 'gradlew build'. final Status status = logger.startProgress( @@ -624,22 +389,6 @@ String _calculateSha(File file) { return sha; } -void printUndefinedTask(GradleProject project, BuildInfo buildInfo) { - printError(''); - printError('The Gradle project does not define a task suitable for the requested build.'); - if (!project.buildTypes.contains(buildInfo.modeName)) { - printError('Review the android/app/build.gradle file and ensure it defines a ${buildInfo.modeName} build type.'); - return; - } - if (project.productFlavors.isEmpty) { - printError('The android/app/build.gradle file does not define any custom product flavors.'); - printError('You cannot use the --flavor option.'); - } else { - printError('The android/app/build.gradle file defines product flavors: ${project.productFlavors.join(', ')}'); - printError('You must specify a --flavor option to select one of them.'); - } -} - Future _buildGradleProjectV2( FlutterProject flutterProject, String gradle, @@ -647,7 +396,7 @@ Future _buildGradleProjectV2( String target, bool isBuildingBundle, ) async { - final GradleProject project = await _gradleAppProject(); + final GradleProject project = await _gradleProject(); final BuildInfo buildInfo = androidBuildInfo.buildInfo; String assembleTask; @@ -657,9 +406,22 @@ Future _buildGradleProjectV2( } else { assembleTask = project.assembleTaskFor(buildInfo); } + if (assembleTask == null) { - printUndefinedTask(project, buildInfo); - throwToolExit('Gradle build aborted.'); + printError(''); + printError('The Gradle project does not define a task suitable for the requested build.'); + if (!project.buildTypes.contains(buildInfo.modeName)) { + printError('Review the android/app/build.gradle file and ensure it defines a ${buildInfo.modeName} build type.'); + } else { + if (project.productFlavors.isEmpty) { + printError('The android/app/build.gradle file does not define any custom product flavors.'); + printError('You cannot use the --flavor option.'); + } else { + printError('The android/app/build.gradle file defines product flavors: ${project.productFlavors.join(', ')}'); + printError('You must specify a --flavor option to select one of them.'); + } + throwToolExit('Gradle build aborted.'); + } } final Status status = logger.startProgress( 'Running Gradle task \'$assembleTask\'...', @@ -698,14 +460,6 @@ Future _buildGradleProjectV2( .map(getPlatformNameForAndroidArch).join(','); command.add('-Ptarget-platform=$targetPlatforms'); } - if (featureFlags.isPluginAsAarEnabled) { - // Pass a system flag instead of a project flag, so this flag can be - // read from include_flutter.groovy. - command.add('-Dbuild-plugins-as-aars=true'); - if (!flutterProject.manifest.isModule) { - command.add('--settings-file=settings_aar.gradle'); - } - } command.add(assembleTask); bool potentialAndroidXFailure = false; final Stopwatch sw = Stopwatch()..start(); @@ -850,6 +604,7 @@ Map get _gradleEnv { // Use java bundled with Android Studio. env['JAVA_HOME'] = javaPath; } + // Don't log analytics for downstream Flutter commands. // e.g. `flutter build bundle`. env['FLUTTER_SUPPRESS_ANALYTICS'] = 'true'; @@ -857,15 +612,11 @@ Map get _gradleEnv { } class GradleProject { - GradleProject( - this.buildTypes, - this.productFlavors, - this.buildDirectory, - ); + GradleProject(this.buildTypes, this.productFlavors, this.apkDirectory, this.bundleDirectory); factory GradleProject.fromAppProperties(String properties, String tasks) { // Extract build directory. - final String buildDirectory = properties + final String buildDir = properties .split('\n') .firstWhere((String s) => s.startsWith('buildDir: ')) .substring('buildDir: '.length) @@ -897,36 +648,17 @@ class GradleProject { if (productFlavors.isEmpty) buildTypes.addAll(variants); return GradleProject( - buildTypes.toList(), - productFlavors.toList(), - buildDirectory, - ); + buildTypes.toList(), + productFlavors.toList(), + fs.directory(fs.path.join(buildDir, 'outputs', 'apk')), + fs.directory(fs.path.join(buildDir, 'outputs', 'bundle')), + ); } - /// The build types such as [release] or [debug]. final List buildTypes; - - /// The product flavors defined in build.gradle. final List productFlavors; - - /// The build directory. This is typically build/. - String buildDirectory; - - /// The directory where the APK artifact is generated. - Directory get apkDirectory { - return fs.directory(fs.path.join(buildDirectory, 'outputs', 'apk')); - } - - /// The directory where the app bundle artifact is generated. - Directory get bundleDirectory { - return fs.directory(fs.path.join(buildDirectory, 'outputs', 'bundle')); - } - - /// The directory where the repo is generated. - /// Only applicable to AARs. - Directory get repoDirectory { - return fs.directory(fs.path.join(buildDirectory, 'outputs', 'repo')); - } + final Directory apkDirectory; + final Directory bundleDirectory; String _buildTypeFor(BuildInfo buildInfo) { final String modeName = camelCase(buildInfo.modeName); @@ -976,14 +708,6 @@ class GradleProject { return 'bundle${toTitleCase(productFlavor)}${toTitleCase(buildType)}'; } - String aarTaskFor(BuildInfo buildInfo) { - final String buildType = _buildTypeFor(buildInfo); - final String productFlavor = _productFlavorFor(buildInfo); - if (buildType == null || productFlavor == null) - return null; - return 'assembleAar${toTitleCase(productFlavor)}${toTitleCase(buildType)}'; - } - String bundleFileFor(BuildInfo buildInfo) { // For app bundle all bundle names are called as app.aab. Product flavors // & build types are differentiated as folders, where the aab will be added. diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart index a4439809a1547..1691b57bfc770 100644 --- a/packages/flutter_tools/lib/src/commands/build.dart +++ b/packages/flutter_tools/lib/src/commands/build.dart @@ -9,7 +9,6 @@ import '../commands/build_macos.dart'; import '../commands/build_windows.dart'; import '../runner/flutter_command.dart'; -import 'build_aar.dart'; import 'build_aot.dart'; import 'build_apk.dart'; import 'build_appbundle.dart'; @@ -20,7 +19,6 @@ import 'build_web.dart'; class BuildCommand extends FlutterCommand { BuildCommand({bool verboseHelp = false}) { - addSubcommand(BuildAarCommand(verboseHelp: verboseHelp)); addSubcommand(BuildApkCommand(verboseHelp: verboseHelp)); addSubcommand(BuildAppBundleCommand(verboseHelp: verboseHelp)); addSubcommand(BuildAotCommand()); diff --git a/packages/flutter_tools/lib/src/commands/build_aar.dart b/packages/flutter_tools/lib/src/commands/build_aar.dart deleted file mode 100644 index e40f522c7e6cb..0000000000000 --- a/packages/flutter_tools/lib/src/commands/build_aar.dart +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 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 '../android/aar.dart'; -import '../base/context.dart'; -import '../base/os.dart'; -import '../build_info.dart'; -import '../project.dart'; -import '../reporting/usage.dart'; -import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult; -import 'build.dart'; - -/// The AAR builder in the current context. -AarBuilder get aarBuilder => context.get() ?? AarBuilderImpl(); - -class BuildAarCommand extends BuildSubCommand { - BuildAarCommand({bool verboseHelp = false}) { - addBuildModeFlags(verboseHelp: verboseHelp); - usesFlavorOption(); - usesPubOption(); - argParser - ..addMultiOption('target-platform', - splitCommas: true, - defaultsTo: ['android-arm', 'android-arm64'], - allowed: ['android-arm', 'android-arm64', 'android-x86', 'android-x64'], - help: 'The target platform for which the project is compiled.', - ) - ..addOption('output-dir', - help: 'The absolute path to the directory where the repository is generated.' - 'By default, this is \'android/build\'. ', - ); - } - - @override - final String name = 'aar'; - - @override - Future> get usageValues async { - final Map usage = {}; - final FlutterProject futterProject = _getProject(); - if (futterProject == null) { - return usage; - } - if (futterProject.manifest.isModule) { - usage[kCommandBuildAarProjectType] = 'module'; - } else if (futterProject.manifest.isPlugin) { - usage[kCommandBuildAarProjectType] = 'plugin'; - } else { - usage[kCommandBuildAarProjectType] = 'app'; - } - usage[kCommandBuildAarTargetPlatform] = - (argResults['target-platform'] as List).join(','); - return usage; - } - - @override - Future> get requiredArtifacts async => const { - DevelopmentArtifact.universal, - DevelopmentArtifact.android, - }; - - @override - final String description = 'Build a repository containing an AAR and a POM file.\n\n' - 'The POM file is used to include the dependencies that the AAR was compiled against.\n\n' - 'To learn more about how to use these artifacts, see ' - 'https://docs.gradle.org/current/userguide/repository_types.html#sub:maven_local'; - - @override - Future runCommand() async { - final BuildInfo buildInfo = getBuildInfo(); - final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(buildInfo, - targetArchs: argResults['target-platform'].map(getAndroidArchForName)); - - await aarBuilder.build( - project: _getProject(), - target: '', // Not needed because this command only builds Android's code. - androidBuildInfo: androidBuildInfo, - outputDir: argResults['output-dir'], - ); - return null; - } - - /// Returns the [FlutterProject] which is determinated from the remaining command-line - /// argument if any or the current working directory. - FlutterProject _getProject() { - if (argResults.rest.isEmpty) { - return FlutterProject.current(); - } - return FlutterProject.fromPath(findProjectRoot(argResults.rest.first)); - } -} diff --git a/packages/flutter_tools/lib/src/features.dart b/packages/flutter_tools/lib/src/features.dart index c56c77d89eeb1..69157a8dac286 100644 --- a/packages/flutter_tools/lib/src/features.dart +++ b/packages/flutter_tools/lib/src/features.dart @@ -36,9 +36,6 @@ class FeatureFlags { /// Whether flutter desktop for Windows is enabled. bool get isWindowsEnabled => _isEnabled(flutterWindowsDesktopFeature); - /// Whether plugins are built as AARs in app projects. - bool get isPluginAsAarEnabled => _isEnabled(flutterBuildPluginAsAarFeature); - // Calculate whether a particular feature is enabled for the current channel. static bool _isEnabled(Feature feature) { final String currentChannel = FlutterVersion.instance.channel; @@ -68,7 +65,6 @@ const List allFeatures = [ flutterLinuxDesktopFeature, flutterMacOSDesktopFeature, flutterWindowsDesktopFeature, - flutterBuildPluginAsAarFeature, ]; /// The [Feature] for flutter web. @@ -119,20 +115,6 @@ const Feature flutterWindowsDesktopFeature = Feature( ), ); -/// The [Feature] for building plugins as AARs in an app project. -const Feature flutterBuildPluginAsAarFeature = Feature( - name: 'Build plugins independently as AARs in app projects', - configSetting: 'enable-build-plugin-as-aar', - master: FeatureChannelSetting( - available: true, - enabledByDefault: true, - ), - dev: FeatureChannelSetting( - available: true, - enabledByDefault: false, - ), -); - /// A [Feature] is a process for conditionally enabling tool features. /// /// All settings are optional, and if not provided will generally default to diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart index ece08466c5a78..95b526ef908ee 100644 --- a/packages/flutter_tools/lib/src/project.dart +++ b/packages/flutter_tools/lib/src/project.dart @@ -510,6 +510,10 @@ class AndroidProject { return fs.directory(fs.path.join(hostAppGradleRoot.path, 'app', 'build', 'outputs', 'apk')); } + Directory get gradleAppBundleOutV1Directory { + return fs.directory(fs.path.join(hostAppGradleRoot.path, 'app', 'build', 'outputs', 'bundle')); + } + /// Whether the current flutter project has an Android sub-project. bool existsSync() { return parent.isModule || _editableHostAppDirectory.existsSync(); diff --git a/packages/flutter_tools/lib/src/reporting/usage.dart b/packages/flutter_tools/lib/src/reporting/usage.dart index 5a596d3b79a09..ea2c739958592 100644 --- a/packages/flutter_tools/lib/src/reporting/usage.dart +++ b/packages/flutter_tools/lib/src/reporting/usage.dart @@ -57,16 +57,13 @@ const String kCommandBuildBundleIsModule = 'cd25'; const String kCommandResult = 'cd26'; const String kCommandHasTerminal = 'cd31'; -const String kCommandBuildAarTargetPlatform = 'cd34'; -const String kCommandBuildAarProjectType = 'cd35'; - const String reloadExceptionTargetPlatform = 'cd27'; const String reloadExceptionSdkName = 'cd28'; const String reloadExceptionEmulator = 'cd29'; const String reloadExceptionFullRestart = 'cd30'; const String enabledFlutterFeatures = 'cd32'; -// Next ID: cd36 +// Next ID: cd34 Usage get flutterUsage => Usage.instance; diff --git a/packages/flutter_tools/templates/module/android/library/Flutter.tmpl/build.gradle.tmpl b/packages/flutter_tools/templates/module/android/library/Flutter.tmpl/build.gradle.tmpl index 0a8051b1d155d..e08734edae9cc 100644 --- a/packages/flutter_tools/templates/module/android/library/Flutter.tmpl/build.gradle.tmpl +++ b/packages/flutter_tools/templates/module/android/library/Flutter.tmpl/build.gradle.tmpl @@ -26,9 +26,6 @@ if (flutterVersionName == null) { apply plugin: 'com.android.library' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" -group '{{androidIdentifier}}' -version '1.0' - android { compileSdkVersion 28 diff --git a/packages/flutter_tools/templates/module/android/library/include_flutter.groovy.copy.tmpl b/packages/flutter_tools/templates/module/android/library/include_flutter.groovy.copy.tmpl index 7be7efbaf8a7e..c6939be730569 100644 --- a/packages/flutter_tools/templates/module/android/library/include_flutter.groovy.copy.tmpl +++ b/packages/flutter_tools/templates/module/android/library/include_flutter.groovy.copy.tmpl @@ -6,37 +6,24 @@ def flutterProjectRoot = new File(scriptFile).parentFile.parentFile gradle.include ':flutter' gradle.project(':flutter').projectDir = new File(flutterProjectRoot, '.android/Flutter') -if (System.getProperty('build-plugins-as-aars') != 'true') { - def plugins = new Properties() - def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins') - if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } - } +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} - plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile() - gradle.include ":$name" - gradle.project(":$name").projectDir = pluginDirectory - } +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile() + gradle.include ":$name" + gradle.project(":$name").projectDir = pluginDirectory } + gradle.getGradle().projectsLoaded { g -> g.rootProject.beforeEvaluate { p -> _mainModuleName = binding.variables['mainModuleName'] if (_mainModuleName != null && !_mainModuleName.empty) { p.ext.mainModuleName = _mainModuleName } - def subprojects = [] - def flutterProject - p.subprojects { sp -> - if (sp.name == 'flutter') { - flutterProject = sp - } else { - subprojects.add(sp) - } - } - assert flutterProject != null - flutterProject.ext.hostProjects = subprojects - flutterProject.ext.pluginBuildDir = new File(flutterProjectRoot, 'build/host') } g.rootProject.afterEvaluate { p -> p.subprojects { sp -> diff --git a/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl b/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl index c16a39446fbe5..20d1a386e08cf 100644 --- a/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl +++ b/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl @@ -1,5 +1,5 @@ group '{{androidIdentifier}}' -version '1.0' +version '1.0-SNAPSHOT' buildscript { repositories { diff --git a/packages/flutter_tools/templates/plugin/android.tmpl/gradle/wrapper/gradle-wrapper.properties b/packages/flutter_tools/templates/plugin/android.tmpl/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 019065d1d650c..0000000000000 --- a/packages/flutter_tools/templates/plugin/android.tmpl/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/packages/flutter_tools/test/general.shard/android/gradle_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_test.dart index 80f203134d46d..b09f73ffc7a60 100644 --- a/packages/flutter_tools/test/general.shard/android/gradle_test.dart +++ b/packages/flutter_tools/test/general.shard/android/gradle_test.dart @@ -6,9 +6,7 @@ import 'dart:async'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/android/gradle.dart'; -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/build_info.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -170,20 +168,20 @@ someOtherTask expect(project.productFlavors, ['free', 'paid']); }); test('should provide apk file name for default build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.apkFilesFor(const AndroidBuildInfo(BuildInfo.debug)).first, 'app-debug.apk'); expect(project.apkFilesFor(const AndroidBuildInfo(BuildInfo.profile)).first, 'app-profile.apk'); expect(project.apkFilesFor(const AndroidBuildInfo(BuildInfo.release)).first, 'app-release.apk'); expect(project.apkFilesFor(const AndroidBuildInfo(BuildInfo(BuildMode.release, 'unknown'))).isEmpty, isTrue); }); test('should provide apk file name for flavored build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.apkFilesFor(const AndroidBuildInfo(BuildInfo(BuildMode.debug, 'free'))).first, 'app-free-debug.apk'); expect(project.apkFilesFor(const AndroidBuildInfo(BuildInfo(BuildMode.release, 'paid'))).first, 'app-paid-release.apk'); expect(project.apkFilesFor(const AndroidBuildInfo(BuildInfo(BuildMode.release, 'unknown'))).isEmpty, isTrue); }); test('should provide apks for default build types and each ABI', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.apkFilesFor( const AndroidBuildInfo( BuildInfo.debug, @@ -226,7 +224,7 @@ someOtherTask ).isEmpty, isTrue); }); test('should provide apks for each ABI and flavored build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.apkFilesFor( const AndroidBuildInfo( BuildInfo(BuildMode.debug, 'free'), @@ -269,154 +267,54 @@ someOtherTask ).isEmpty, isTrue); }); test('should provide bundle file name for default build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.bundleFileFor(BuildInfo.debug), 'app.aab'); expect(project.bundleFileFor(BuildInfo.profile), 'app.aab'); expect(project.bundleFileFor(BuildInfo.release), 'app.aab'); expect(project.bundleFileFor(const BuildInfo(BuildMode.release, 'unknown')), 'app.aab'); }); test('should provide bundle file name for flavored build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.bundleFileFor(const BuildInfo(BuildMode.debug, 'free')), 'app.aab'); expect(project.bundleFileFor(const BuildInfo(BuildMode.release, 'paid')), 'app.aab'); expect(project.bundleFileFor(const BuildInfo(BuildMode.release, 'unknown')), 'app.aab'); }); test('should provide assemble task name for default build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.assembleTaskFor(BuildInfo.debug), 'assembleDebug'); expect(project.assembleTaskFor(BuildInfo.profile), 'assembleProfile'); expect(project.assembleTaskFor(BuildInfo.release), 'assembleRelease'); expect(project.assembleTaskFor(const BuildInfo(BuildMode.release, 'unknown')), isNull); }); test('should provide assemble task name for flavored build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.assembleTaskFor(const BuildInfo(BuildMode.debug, 'free')), 'assembleFreeDebug'); expect(project.assembleTaskFor(const BuildInfo(BuildMode.release, 'paid')), 'assemblePaidRelease'); expect(project.assembleTaskFor(const BuildInfo(BuildMode.release, 'unknown')), isNull); }); test('should respect format of the flavored build types', () { - final GradleProject project = GradleProject(['debug'], ['randomFlavor'], '/some/dir'); + final GradleProject project = GradleProject(['debug'], ['randomFlavor'], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.assembleTaskFor(const BuildInfo(BuildMode.debug, 'randomFlavor')), 'assembleRandomFlavorDebug'); }); test('bundle should provide assemble task name for default build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], [], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.bundleTaskFor(BuildInfo.debug), 'bundleDebug'); expect(project.bundleTaskFor(BuildInfo.profile), 'bundleProfile'); expect(project.bundleTaskFor(BuildInfo.release), 'bundleRelease'); expect(project.bundleTaskFor(const BuildInfo(BuildMode.release, 'unknown')), isNull); }); test('bundle should provide assemble task name for flavored build types', () { - final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], '/some/dir'); + final GradleProject project = GradleProject(['debug', 'profile', 'release'], ['free', 'paid'], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.bundleTaskFor(const BuildInfo(BuildMode.debug, 'free')), 'bundleFreeDebug'); expect(project.bundleTaskFor(const BuildInfo(BuildMode.release, 'paid')), 'bundlePaidRelease'); expect(project.bundleTaskFor(const BuildInfo(BuildMode.release, 'unknown')), isNull); }); test('bundle should respect format of the flavored build types', () { - final GradleProject project = GradleProject(['debug'], ['randomFlavor'], '/some/dir'); + final GradleProject project = GradleProject(['debug'], ['randomFlavor'], fs.directory('/some/dir'),fs.directory('/some/dir')); expect(project.bundleTaskFor(const BuildInfo(BuildMode.debug, 'randomFlavor')), 'bundleRandomFlavorDebug'); }); }); - group('Config files', () { - BufferLogger mockLogger; - Directory tempDir; - - setUp(() { - mockLogger = BufferLogger(); - tempDir = fs.systemTempDirectory.createTempSync('settings_aar_test.'); - - }); - - testUsingContext('create settings_aar.gradle', () { - const String deprecatedFile = ''' -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":\$name" - project(":\$name").projectDir = pluginDirectory -} -'''; - - const String settingsAarFile = ''' -include ':app' -'''; - - tempDir.childFile('settings.gradle').writeAsStringSync(deprecatedFile); - - final String toolGradlePath = fs.path.join( - fs.path.absolute(Cache.flutterRoot), - 'packages', - 'flutter_tools', - 'gradle'); - fs.directory(toolGradlePath).createSync(recursive: true); - fs.file(fs.path.join(toolGradlePath, 'deprecated_settings.gradle')) - .writeAsStringSync(deprecatedFile); - - fs.file(fs.path.join(toolGradlePath, 'settings_aar.gradle.tmpl')) - .writeAsStringSync(settingsAarFile); - - createSettingsAarGradle(tempDir); - - expect(mockLogger.statusText, contains('created successfully')); - expect(tempDir.childFile('settings_aar.gradle').existsSync(), isTrue); - - }, overrides: { - FileSystem: () => MemoryFileSystem(), - Logger: () => mockLogger, - }); - }); - - group('Undefined task', () { - BufferLogger mockLogger; - - setUp(() { - mockLogger = BufferLogger(); - }); - - testUsingContext('print undefined build type', () { - final GradleProject project = GradleProject(['debug', 'release'], - const ['free', 'paid'], '/some/dir'); - - printUndefinedTask(project, const BuildInfo(BuildMode.profile, 'unknown')); - expect(mockLogger.errorText, contains('The Gradle project does not define a task suitable for the requested build')); - expect(mockLogger.errorText, contains('Review the android/app/build.gradle file and ensure it defines a profile build type')); - }, overrides: { - Logger: () => mockLogger, - }); - - testUsingContext('print no flavors', () { - final GradleProject project = GradleProject(['debug', 'release'], - const [], '/some/dir'); - - printUndefinedTask(project, const BuildInfo(BuildMode.debug, 'unknown')); - expect(mockLogger.errorText, contains('The Gradle project does not define a task suitable for the requested build')); - expect(mockLogger.errorText, contains('The android/app/build.gradle file does not define any custom product flavors')); - expect(mockLogger.errorText, contains('You cannot use the --flavor option')); - }, overrides: { - Logger: () => mockLogger, - }); - - testUsingContext('print flavors', () { - final GradleProject project = GradleProject(['debug', 'release'], - const ['free', 'paid'], '/some/dir'); - - printUndefinedTask(project, const BuildInfo(BuildMode.debug, 'unknown')); - expect(mockLogger.errorText, contains('The Gradle project does not define a task suitable for the requested build')); - expect(mockLogger.errorText, contains('The android/app/build.gradle file defines product flavors: free, paid')); - }, overrides: { - Logger: () => mockLogger, - }); - }); - group('Gradle local.properties', () { MockLocalEngineArtifacts mockArtifacts; MockProcessManager mockProcessManager; @@ -642,52 +540,6 @@ flutter: ); }); }); - - group('gradle version', () { - test('should be compatible with the Android plugin version', () { - // Granular versions. - expect(getGradleVersionFor('1.0.0'), '2.3'); - expect(getGradleVersionFor('1.0.1'), '2.3'); - expect(getGradleVersionFor('1.0.2'), '2.3'); - expect(getGradleVersionFor('1.0.4'), '2.3'); - expect(getGradleVersionFor('1.0.8'), '2.3'); - expect(getGradleVersionFor('1.1.0'), '2.3'); - expect(getGradleVersionFor('1.1.2'), '2.3'); - expect(getGradleVersionFor('1.1.2'), '2.3'); - expect(getGradleVersionFor('1.1.3'), '2.3'); - // Version Ranges. - expect(getGradleVersionFor('1.2.0'), '2.9'); - expect(getGradleVersionFor('1.3.1'), '2.9'); - - expect(getGradleVersionFor('1.5.0'), '2.2.1'); - - expect(getGradleVersionFor('2.0.0'), '2.13'); - expect(getGradleVersionFor('2.1.2'), '2.13'); - - expect(getGradleVersionFor('2.1.3'), '2.14.1'); - expect(getGradleVersionFor('2.2.3'), '2.14.1'); - - expect(getGradleVersionFor('2.3.0'), '3.3'); - - expect(getGradleVersionFor('3.0.0'), '4.1'); - - expect(getGradleVersionFor('3.1.0'), '4.4'); - - expect(getGradleVersionFor('3.2.0'), '4.6'); - expect(getGradleVersionFor('3.2.1'), '4.6'); - - expect(getGradleVersionFor('3.3.0'), '4.10.2'); - expect(getGradleVersionFor('3.3.2'), '4.10.2'); - - expect(getGradleVersionFor('3.4.0'), '5.1.1'); - expect(getGradleVersionFor('3.5.0'), '5.1.1'); - }); - - test('throws on unsupported versions', () { - expect(() => getGradleVersionFor('3.6.0'), - throwsA(predicate((Exception e) => e is ToolExit))); - }); - }); } Platform fakePlatform(String name) { diff --git a/packages/flutter_tools/test/general.shard/commands/build_aar_test.dart b/packages/flutter_tools/test/general.shard/commands/build_aar_test.dart deleted file mode 100644 index d02d7640508c6..0000000000000 --- a/packages/flutter_tools/test/general.shard/commands/build_aar_test.dart +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 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 'package:args/command_runner.dart'; -import 'package:flutter_tools/src/android/aar.dart'; -import 'package:flutter_tools/src/base/file_system.dart'; -import 'package:flutter_tools/src/cache.dart'; -import 'package:flutter_tools/src/commands/build_aar.dart'; -import 'package:flutter_tools/src/reporting/usage.dart'; -import 'package:mockito/mockito.dart'; - -import '../../src/common.dart'; -import '../../src/context.dart'; - -void main() { - Cache.disableLocking(); - - group('getUsage', () { - Directory tempDir; - AarBuilder mockAarBuilder; - - setUp(() { - tempDir = fs.systemTempDirectory.createTempSync('flutter_tools_packages_test.'); - mockAarBuilder = MockAarBuilder(); - when(mockAarBuilder.build( - project: anyNamed('project'), - androidBuildInfo: anyNamed('androidBuildInfo'), - target: anyNamed('target'), - outputDir: anyNamed('outputDir'))).thenAnswer((_) => Future.value()); - }); - - tearDown(() { - tryToDelete(tempDir); - }); - - Future runCommandIn(String target, { List arguments }) async { - final BuildAarCommand command = BuildAarCommand(); - final CommandRunner runner = createTestCommandRunner(command); - await runner.run([ - 'aar', - ...?arguments, - target, - ]); - return command; - } - - testUsingContext('indicate that project is a module', () async { - final String projectPath = await createProject(tempDir, - arguments: ['--no-pub', '--template=module']); - - final BuildAarCommand command = await runCommandIn(projectPath); - expect(await command.usageValues, - containsPair(kCommandBuildAarProjectType, 'module')); - - }, overrides: { - AarBuilder: () => mockAarBuilder, - }, timeout: allowForCreateFlutterProject); - - testUsingContext('indicate that project is a plugin', () async { - final String projectPath = await createProject(tempDir, - arguments: ['--no-pub', '--template=plugin', '--project-name=aar_test']); - - final BuildAarCommand command = await runCommandIn(projectPath); - expect(await command.usageValues, - containsPair(kCommandBuildAarProjectType, 'plugin')); - - }, overrides: { - AarBuilder: () => mockAarBuilder, - }, timeout: allowForCreateFlutterProject); - - testUsingContext('indicate the target platform', () async { - final String projectPath = await createProject(tempDir, - arguments: ['--no-pub', '--template=module']); - - final BuildAarCommand command = await runCommandIn(projectPath, - arguments: ['--target-platform=android-arm']); - expect(await command.usageValues, - containsPair(kCommandBuildAarTargetPlatform, 'android-arm')); - - }, overrides: { - AarBuilder: () => mockAarBuilder, - }, timeout: allowForCreateFlutterProject); - }); -} - -class MockAarBuilder extends Mock implements AarBuilder {} diff --git a/packages/flutter_tools/test/general.shard/features_test.dart b/packages/flutter_tools/test/general.shard/features_test.dart index 5f56e51d32001..94b336b558124 100644 --- a/packages/flutter_tools/test/general.shard/features_test.dart +++ b/packages/flutter_tools/test/general.shard/features_test.dart @@ -418,21 +418,6 @@ void main() { expect(featureFlags.isWindowsEnabled, false); })); - - /// Plugins as AARS - test('plugins built as AARs with config on master', () => testbed.run(() { - when(mockFlutterVerion.channel).thenReturn('master'); - when(mockFlutterConfig.getValue('enable-build-plugin-as-aar')).thenReturn(true); - - expect(featureFlags.isPluginAsAarEnabled, true); - })); - - test('plugins built as AARs with config on dev', () => testbed.run(() { - when(mockFlutterVerion.channel).thenReturn('dev'); - when(mockFlutterConfig.getValue('enable-build-plugin-as-aar')).thenReturn(true); - - expect(featureFlags.isPluginAsAarEnabled, true); - })); }); } diff --git a/packages/flutter_tools/test/src/testbed.dart b/packages/flutter_tools/test/src/testbed.dart index 634acf0377a1b..c0a6873d1d86f 100644 --- a/packages/flutter_tools/test/src/testbed.dart +++ b/packages/flutter_tools/test/src/testbed.dart @@ -697,7 +697,6 @@ class TestFeatureFlags implements FeatureFlags { this.isMacOSEnabled = false, this.isWebEnabled = false, this.isWindowsEnabled = false, - this.isPluginAsAarEnabled = false, }); @override @@ -711,7 +710,4 @@ class TestFeatureFlags implements FeatureFlags { @override final bool isWindowsEnabled; - - @override - final bool isPluginAsAarEnabled; }