Unverified Commit 51251f2e authored by Bartek Pacia's avatar Bartek Pacia Committed by GitHub

Refactor Flutter Gradle Plugin so it can be applied using the declarative...

Refactor Flutter Gradle Plugin so it can be applied using the declarative `plugins {}` block (#123511)

This PR aims to resolve #121552.

Resources used:
- [Developing Plugins](https://docs.gradle.org/current/userguide/custom_plugins.html)
- [Using Gradle Plugins](https://docs.gradle.org/current/userguide/plugins.html#sec:plugins_block)
- [Composite Builds Plugin Development Sample](https://docs.gradle.org/current/samples/sample_composite_builds_plugin_development.html)

This PR also paves way for #121541, because apps will no longer have:

```groovy
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
```

hardcoded. Instead, they'll use:

```groovy
plugins {
    // ...
    id "dev.flutter.flutter-gradle-plugin" // the exact name is tentative
}
```
parent 122dacfa
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
plugins {
id "com.android.application"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties() def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties') def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) { if (localPropertiesFile.exists()) {
...@@ -10,11 +15,6 @@ if (localPropertiesFile.exists()) { ...@@ -10,11 +15,6 @@ if (localPropertiesFile.exists()) {
} }
} }
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode') def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = '1' flutterVersionCode = '1'
...@@ -25,9 +25,6 @@ if (flutterVersionName == null) { ...@@ -25,9 +25,6 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0' flutterVersionName = '1.0'
} }
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
namespace "io.flutter.examples.hello_world" namespace "io.flutter.examples.hello_world"
compileSdkVersion flutter.compileSdkVersion compileSdkVersion flutter.compileSdkVersion
......
...@@ -6,16 +6,27 @@ ...@@ -6,16 +6,27 @@
// To update all the settings.gradle files in the Flutter repo, // To update all the settings.gradle files in the Flutter repo,
// See dev/tools/bin/generate_gradle_lockfiles.dart. // See dev/tools/bin/generate_gradle_lockfiles.dart.
include ':app' pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
enableFeaturePreview('ONE_LOCKFILE_PER_PROJECT') // Flutter Gradle Plugin ships together with the Flutter SDK
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
def localPropertiesFile = new File(rootProject.projectDir, "local.properties") plugins {
def properties = new Properties() // Flutter Gradle Plugin's ID is defined in /packages/flutter_tools/gradle/build.gradle.kts.
// We set `apply false`, because we don't want to apply the plugin to
// the `android` root project, but only to the `app` subproject.
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
}
}
assert localPropertiesFile.exists() include ':app'
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk") apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle"
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
plugins {
`groovy-gradle-plugin`
}
repositories {
google()
mavenCentral()
}
group = "dev.flutter.plugin"
version = "1.0.0"
gradlePlugin {
plugins {
// The "flutterPlugin" name isn't used anywhere.
create("flutterPlugin") {
id = "dev.flutter.flutter-gradle-plugin"
implementationClass = "FlutterPlugin"
}
}
}
dependencies {
// When bumping, also update:
// * ndkVersion in FlutterExtension in packages/flutter_tools/gradle/src/main/flutter.groovy
// * AGP version constants in packages/flutter_tools/lib/src/android/gradle_utils.dart
// * AGP version in buildscript block in packages/flutter_tools/gradle/src/main/flutter.groovy
compileOnly("com.android.tools.build:gradle:7.3.0")
}
This diff is collapsed.
...@@ -7,7 +7,6 @@ import 'package:process/process.dart'; ...@@ -7,7 +7,6 @@ import 'package:process/process.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/platform.dart'; import '../base/platform.dart';
...@@ -33,7 +32,7 @@ const String templateAndroidGradlePluginVersion = '7.3.0'; ...@@ -33,7 +32,7 @@ const String templateAndroidGradlePluginVersion = '7.3.0';
const String templateDefaultGradleVersionForModule = '7.3.0'; const String templateDefaultGradleVersionForModule = '7.3.0';
const String templateKotlinGradlePluginVersion = '1.7.10'; const String templateKotlinGradlePluginVersion = '1.7.10';
// These versions should match the values in flutter.gradle (FlutterExtension). // These versions should match the values in Flutter Gradle Plugin (FlutterExtension).
// The Flutter Gradle plugin is only applied to app projects, and modules that are built from source // The Flutter Gradle plugin is only applied to app projects, and modules that are built from source
// using (include_flutter.groovy). // using (include_flutter.groovy).
// The remaining projects are: plugins, and modules compiled as AARs. In modules, the ephemeral directory // The remaining projects are: plugins, and modules compiled as AARs. In modules, the ephemeral directory
......
...@@ -217,7 +217,7 @@ class BuildInfo { ...@@ -217,7 +217,7 @@ class BuildInfo {
String get modeName => mode.cliName; String get modeName => mode.cliName;
String get friendlyModeName => getFriendlyModeName(mode); String get friendlyModeName => getFriendlyModeName(mode);
/// the flavor name in the output apk files is lower-cased (see flutter.gradle), /// the flavor name in the output apk files is lower-cased (see Flutter Gradle Plugin),
/// so the lower cased flavor name is used to compute the output file name /// so the lower cased flavor name is used to compute the output file name
String? get lowerCasedFlavor => flavor?.toLowerCase(); String? get lowerCasedFlavor => flavor?.toLowerCase();
......
...@@ -442,7 +442,8 @@ class AndroidProject extends FlutterProjectPlatform { ...@@ -442,7 +442,8 @@ class AndroidProject extends FlutterProjectPlatform {
static final RegExp _androidNamespacePattern = RegExp('android {[\\S\\s]+namespace[\\s]+[\'"](.+)[\'"]'); static final RegExp _androidNamespacePattern = RegExp('android {[\\S\\s]+namespace[\\s]+[\'"](.+)[\'"]');
static final RegExp _applicationIdPattern = RegExp('^\\s*applicationId\\s+[\'"](.*)[\'"]\\s*\$'); static final RegExp _applicationIdPattern = RegExp('^\\s*applicationId\\s+[\'"](.*)[\'"]\\s*\$');
static final RegExp _kotlinPluginPattern = RegExp('^\\s*apply plugin\\:\\s+[\'"]kotlin-android[\'"]\\s*\$'); static final RegExp _imperativeKotlinPluginPattern = RegExp('^\\s*apply plugin\\:\\s+[\'"]kotlin-android[\'"]\\s*\$');
static final RegExp _declarativeKotlinPluginPattern = RegExp('^\\s*id\\s+[\'"]kotlin-android[\'"]\\s*\$');
static final RegExp _groupPattern = RegExp('^\\s*group\\s+[\'"](.*)[\'"]\\s*\$'); static final RegExp _groupPattern = RegExp('^\\s*group\\s+[\'"](.*)[\'"]\\s*\$');
/// The Gradle root directory of the Android host app. This is the directory /// The Gradle root directory of the Android host app. This is the directory
...@@ -495,8 +496,10 @@ class AndroidProject extends FlutterProjectPlatform { ...@@ -495,8 +496,10 @@ class AndroidProject extends FlutterProjectPlatform {
return false; return false;
} }
for (final String line in appGradle.readAsLinesSync()) { for (final String line in appGradle.readAsLinesSync()) {
if (line.contains(RegExp(r'apply from: .*/flutter.gradle')) || final bool fileBasedApply = line.contains(RegExp(r'apply from: .*/flutter.gradle'));
line.contains("def flutterPluginVersion = 'managed'")) { final bool declarativeApply = line.contains('dev.flutter.flutter-gradle-plugin');
final bool managed = line.contains("def flutterPluginVersion = 'managed'");
if (fileBasedApply || declarativeApply || managed) {
return true; return true;
} }
} }
...@@ -506,7 +509,9 @@ class AndroidProject extends FlutterProjectPlatform { ...@@ -506,7 +509,9 @@ class AndroidProject extends FlutterProjectPlatform {
/// True, if the app project is using Kotlin. /// True, if the app project is using Kotlin.
bool get isKotlin { bool get isKotlin {
final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle'); final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle');
return firstMatchInFile(gradleFile, _kotlinPluginPattern) != null; final bool imperativeMatch = firstMatchInFile(gradleFile, _imperativeKotlinPluginPattern) != null;
final bool declarativeMatch = firstMatchInFile(gradleFile, _declarativeKotlinPluginPattern) != null;
return imperativeMatch || declarativeMatch;
} }
File get appManifestFile { File get appManifestFile {
......
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties() def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties') def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) { if (localPropertiesFile.exists()) {
...@@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) { ...@@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
} }
} }
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode') def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = '1' flutterVersionCode = '1'
...@@ -21,10 +22,6 @@ if (flutterVersionName == null) { ...@@ -21,10 +22,6 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0' flutterVersionName = '1.0'
} }
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
namespace "{{androidIdentifier}}" namespace "{{androidIdentifier}}"
compileSdkVersion flutter.compileSdkVersion compileSdkVersion flutter.compileSdkVersion
......
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties() def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties') def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) { if (localPropertiesFile.exists()) {
...@@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) { ...@@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
} }
} }
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode') def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = '1' flutterVersionCode = '1'
...@@ -21,10 +22,6 @@ if (flutterVersionName == null) { ...@@ -21,10 +22,6 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0' flutterVersionName = '1.0'
} }
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
namespace "{{androidIdentifier}}" namespace "{{androidIdentifier}}"
compileSdkVersion flutter.compileSdkVersion compileSdkVersion flutter.compileSdkVersion
......
include ':app' pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties") includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
def properties = new Properties()
assert localPropertiesFile.exists() plugins {
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
}
}
def flutterSdkPath = properties.getProperty("flutter.sdk") include ":app"
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment