Skip to content

Commit e971379

Browse files
gmackallGray Mackall
andauthored
Convert AppPluginLoaderPlugin to Kotlin, and add NativePluginLoaderReflectionBridge to expose it in Kotlin (flutter#166027)
Graph [stolen from Barteks comment](flutter#161352 (comment)) documenting the existing (pre pr) state: ```mermaid graph TD; flutter.groovy -- import --> native_plugin_loader.groovy; flutter.groovy -- import --> BaseApplicationNameHandler.kt; module_plugin_loader.groovy -- "ext" --> native_plugin_loader.groovy; app_plugin_loader.groovy -- import --> native_plugin_loader.groovy; include_flutter.groovy -- "apply from: " --> module_plugin_loader.groovy; ``` 1. Converts the `app_plugin_loader.groovy` to kotlin source. 2. Converts the `module_plugin_loader.groovy` to kotlin script. This can't be changed to kotlin source yet, as we will need to instruct users to make a change to their host app-level gradle files before we can turn down script application of this separate gradle plugin. This is a breaking change, and will need a quarter at least of notice. 3. Unfortunately, the main Flutter Gradle plugin depends on being able to call methods of the `native_plugin_loader`, which we could do in groovy via wacky dynamic behavior, calling across the compiled plugin->script plugin barrier. We can't do this in Kotlin source, and we also can't fully convert `native_plugin_loader` to kotlin source yet because of (2), so I've added a `NativePluginLoaderReflectionBridge` that allows us to access the methods in the `native_plugin_loader.gradle.kts` from the Kotlin source files, calling across the compiled plugin->script plugin barrier as we were before. The plan here is 1. to follow up by adding a converted `native_plugin_loader.gradle.kts` in Kotlin source, and migrating all paths but the host-app using a module-as-source to use the converted approach (but not deleting the old way) 2. maintaining both ways for a release or two, with the script application printing a message notifying users to update to the non-script based application of the `module_plugin_loader`. 3. Then we can delete the script based apply, and also the reflection bridge. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Gray Mackall <[email protected]>
1 parent d90c961 commit e971379

16 files changed

+263
-177
lines changed

packages/flutter_tools/gradle/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ gradlePlugin {
3939
// The "flutterAppPluginLoaderPlugin" name isn't used anywhere.
4040
create("flutterAppPluginLoaderPlugin") {
4141
id = "dev.flutter.flutter-plugin-loader"
42-
implementationClass = "FlutterAppPluginLoaderPlugin"
42+
implementationClass = "com.flutter.gradle.FlutterAppPluginLoaderPlugin"
4343
}
4444
}
4545
}

packages/flutter_tools/gradle/module_plugin_loader.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.nio.file.Paths
99

1010
File pathToThisDirectory = buildscript.sourceFile.parentFile
11-
apply from: Paths.get(pathToThisDirectory.absolutePath, "src", "main", "groovy", "native_plugin_loader.groovy")
11+
apply from: Paths.get(pathToThisDirectory.absolutePath, "src", "main", "scripts", "native_plugin_loader.gradle.kts")
1212

1313
def moduleProjectRoot = project(':flutter').projectDir.parentFile.parentFile
1414

packages/flutter_tools/gradle/src/main/groovy/app_plugin_loader.groovy

Lines changed: 0 additions & 32 deletions
This file was deleted.

packages/flutter_tools/gradle/src/main/groovy/flutter.groovy

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.flutter.gradle.FlutterExtension
1515
import com.flutter.gradle.FlutterPluginConstants
1616
import com.flutter.gradle.FlutterTask
1717
import com.flutter.gradle.FlutterPluginUtils
18+
import com.flutter.gradle.NativePluginLoaderReflectionBridge
1819
import org.gradle.api.file.Directory
1920

2021
import java.nio.file.Paths
@@ -114,7 +115,7 @@ class FlutterPlugin implements Plugin<Project> {
114115
}
115116

116117
// Load shared gradle functions
117-
project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "groovy", "native_plugin_loader.groovy")
118+
project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "scripts", "native_plugin_loader.gradle.kts")
118119

119120
FlutterExtension extension = project.extensions.create("flutter", FlutterExtension)
120121
Properties localProperties = new Properties()
@@ -298,7 +299,7 @@ class FlutterPlugin implements Plugin<Project> {
298299
* and filtered then with the [doesSupportAndroidPlatform] method instead of
299300
* just using the `plugins.android` list.
300301
*/
301-
private void configureLegacyPluginEachProjects(Project project) {
302+
static private void configureLegacyPluginEachProjects(Project project) {
302303
try {
303304
// Read the contents of the settings.gradle file.
304305
// Remove block/line comments
@@ -340,11 +341,11 @@ class FlutterPlugin implements Plugin<Project> {
340341
*
341342
* The map value contains either the plugins `name` (String),
342343
* its `path` (String), or its `dependencies` (List<String>).
343-
* See [NativePluginLoader#getPlugins] in packages/flutter_tools/gradle/src/main/groovy/native_plugin_loader.groovy
344+
* See [NativePluginLoader#getPlugins] in packages/flutter_tools/gradle/src/main/scripts/native_plugin_loader.gradle.kts
344345
*/
345346
private List<Map<String, Object>> getPluginList(Project project) {
346347
if (pluginList == null) {
347-
pluginList = project.ext.nativePluginLoader.getPlugins(FlutterPluginUtils.getFlutterSourceDirectory(project))
348+
pluginList = NativePluginLoaderReflectionBridge.getPlugins(project.ext, FlutterPluginUtils.getFlutterSourceDirectory(project))
348349
}
349350
return pluginList
350351
}
@@ -354,7 +355,7 @@ class FlutterPlugin implements Plugin<Project> {
354355
/** Gets the plugins dependencies from `.flutter-plugins-dependencies`. */
355356
private List<Map<String, Object>> getPluginDependencies(Project project) {
356357
if (pluginDependencies == null) {
357-
Map meta = project.ext.nativePluginLoader.getDependenciesMetadata(FlutterPluginUtils.getFlutterSourceDirectory(project))
358+
Map meta = NativePluginLoaderReflectionBridge.getDependenciesMetadata(project.ext, FlutterPluginUtils.getFlutterSourceDirectory(project))
358359
if (meta == null) {
359360
pluginDependencies = []
360361
} else {

packages/flutter_tools/gradle/src/main/groovy/native_plugin_loader.groovy

Lines changed: 0 additions & 137 deletions
This file was deleted.

packages/flutter_tools/gradle/src/main/kotlin/BaseApplicationNameHandler.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
15
package com.flutter.gradle
26

37
import com.android.build.api.dsl.ApplicationExtension

packages/flutter_tools/gradle/src/main/kotlin/BaseFlutterTaskHelper.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
15
package com.flutter.gradle
26

37
import androidx.annotation.VisibleForTesting

packages/flutter_tools/gradle/src/main/kotlin/DependencyVersionChecker.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
15
package com.flutter.gradle
26

37
import androidx.annotation.VisibleForTesting
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package com.flutter.gradle
6+
7+
import org.gradle.api.Plugin
8+
import org.gradle.api.initialization.Settings
9+
import org.jetbrains.kotlin.gradle.plugin.extraProperties
10+
import java.io.File
11+
import java.nio.file.Paths
12+
import java.util.Properties
13+
14+
private const val FLUTTER_SDK_PATH = "flutterSdkPath"
15+
16+
// Integration tests that cover this class include
17+
// - packages/flutter_tools/test/integration.shard/android_gradle_daemon_cache_test.dart
18+
// - packages/flutter_tools/test/integration.shard/android_plugin_compilesdkversion_mismatch_test.dart
19+
// And can be run by following the README in packages/flutter_tools/.
20+
21+
/**
22+
* This plugin applies the native plugin loader plugin (../scripts/native_plugin_loader.gradle.kts)
23+
* and then configures the main project to `include` each of the loaded flutter plugins.
24+
*/
25+
class FlutterAppPluginLoaderPlugin : Plugin<Settings> {
26+
override fun apply(settings: Settings) {
27+
val flutterProjectRoot: File = settings.settingsDir.parentFile
28+
29+
if (!settings.extraProperties.has(FLUTTER_SDK_PATH)) {
30+
val properties = Properties()
31+
val localPropertiesFile = File(settings.rootProject.projectDir, "local.properties")
32+
localPropertiesFile.inputStream().use { properties.load(it) }
33+
settings.extraProperties.set(FLUTTER_SDK_PATH, properties.getProperty("flutter.sdk"))
34+
assert(
35+
settings.extraProperties.get(FLUTTER_SDK_PATH) != null
36+
) { "flutter.sdk not set in local.properties" }
37+
}
38+
39+
settings.apply {
40+
from(
41+
Paths.get(
42+
settings.extraProperties.get(FLUTTER_SDK_PATH) as String,
43+
"packages",
44+
"flutter_tools",
45+
"gradle",
46+
"src",
47+
"main",
48+
"scripts",
49+
"native_plugin_loader.gradle.kts"
50+
)
51+
)
52+
}
53+
54+
NativePluginLoaderReflectionBridge
55+
.getPlugins(settings.extraProperties, flutterProjectRoot)
56+
.forEach { androidPlugin ->
57+
val pluginDirectory = File(androidPlugin["path"] as String, "android")
58+
check(
59+
pluginDirectory.exists()
60+
) { "Plugin directory does not exist: ${pluginDirectory.absolutePath}" }
61+
val pluginName = androidPlugin["name"] as String
62+
settings.include(":$pluginName")
63+
settings.project(":$pluginName").projectDir = pluginDirectory
64+
}
65+
}
66+
}

packages/flutter_tools/gradle/src/main/kotlin/FlutterExtension.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
15
package com.flutter.gradle
26

37
import org.gradle.api.GradleException

0 commit comments

Comments
 (0)