Skip to content

Commit 669502d

Browse files
gmackallgemini-code-assist[bot]
authored andcommitted
[tool] Don't require a Flutter compile task when staging jniLibs (flutter#188805)
The variant-API jniLibs copy task referenced the Flutter compile task by name via tasks.named(...), which throws when that task is not registered. It is not registered for builds where shouldConfigureFlutterTask returns false - e.g. `./gradlew :app:assembleAndroidTest` after `flutter build apk --config-only`, which is how flutter/packages' Firebase Test Lab tooling builds - causing "Could not create task ':app:copyJniLibsflutterBuildDebug'. > Task with name 'compileFlutterBuildDebug' not found". Look the compile task up tolerantly with findByName and make the copy task's intermediateDir input optional, so the task degrades to a no-op (empty output) when there is no Flutter build for the variant - matching the forgiving behavior of the previous source-set approach. Adds an assembleAndroidTest regression test. Fixes flutter#188785 --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent f94f4fc commit 669502d

3 files changed

Lines changed: 79 additions & 22 deletions

File tree

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -313,22 +313,28 @@ class FlutterPlugin : Plugin<Project> {
313313
val targetPlatformsList = targetPlatforms
314314
androidComponents.onVariants { variant ->
315315
val capitalizeVariantName = FlutterPluginUtils.capitalize(variant.name)
316-
// Reference the Flutter compile task by name rather than by provider: this variant API
317-
// callback runs before the legacy `applicationVariants` callback in addFlutterDeps that
318-
// registers the task, so its provider does not exist yet here.
319316
val compileTaskName = flutterCompileTaskName(variant.name)
320317
val copyJniLibsTaskProvider: TaskProvider<CopyFlutterJniLibsTask> =
321318
projectToAddTasksTo.tasks.register(
322319
"copyJniLibs${FLUTTER_BUILD_PREFIX}$capitalizeVariantName",
323320
CopyFlutterJniLibsTask::class.java
324321
) {
325-
dependsOn(compileTaskName)
326-
val compileTaskProvider = projectToAddTasksTo.tasks.named(compileTaskName, FlutterTask::class.java)
327-
val outputDirProvider =
328-
compileTaskProvider.flatMap { task ->
329-
projectToAddTasksTo.layout.dir(projectToAddTasksTo.provider { task.outputDirectory!! })
330-
}
331-
intermediateDir.set(outputDirProvider)
322+
// The Flutter compile task is registered later (in the legacy
323+
// `applicationVariants` callback in addFlutterDeps) and only for variants that
324+
// are actually built as a Flutter app. It is absent for e.g. an
325+
// `assembleAndroidTest` build, where `shouldConfigureFlutterTask` returns false.
326+
// Look it up tolerantly (findByName, not named) so this task degrades to a no-op
327+
// with empty output instead of failing to be created when there is no Flutter
328+
// build for the variant. See https://github.com/flutter/flutter/issues/188785.
329+
dependsOn(projectToAddTasksTo.tasks.matching { it.name == compileTaskName })
330+
intermediateDir.set(
331+
projectToAddTasksTo.layout.dir(
332+
projectToAddTasksTo.provider {
333+
val compileTask = projectToAddTasksTo.tasks.findByName(compileTaskName) as? FlutterTask
334+
compileTask?.outputDirectory
335+
}
336+
)
337+
)
332338
this.targetPlatforms.set(targetPlatformsList)
333339
}
334340
variant.sources.jniLibs?.addGeneratedSourceDirectory(

packages/flutter_tools/gradle/src/main/kotlin/tasks/CopyFlutterJniLibsTask.kt

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import org.gradle.api.file.FileSystemOperations
1111
import org.gradle.api.provider.ListProperty
1212
import org.gradle.api.tasks.Input
1313
import org.gradle.api.tasks.InputDirectory
14+
import org.gradle.api.tasks.Optional
1415
import org.gradle.api.tasks.OutputDirectory
1516
import org.gradle.api.tasks.PathSensitive
1617
import org.gradle.api.tasks.PathSensitivity
@@ -30,7 +31,14 @@ import javax.inject.Inject
3031
* https://github.com/flutter/flutter/issues/187388.
3132
*/
3233
abstract class CopyFlutterJniLibsTask : DefaultTask() {
33-
/** The Flutter build output directory (the `flutter assemble` `--output` location). */
34+
/**
35+
* The Flutter build output directory (the `flutter assemble` `--output` location).
36+
*
37+
* Optional: it is absent when there is no Flutter compile task for the variant (e.g. an
38+
* `assembleAndroidTest` build), in which case this task stages nothing. See
39+
* https://github.com/flutter/flutter/issues/188785.
40+
*/
41+
@get:Optional
3442
@get:InputDirectory
3543
@get:PathSensitive(PathSensitivity.RELATIVE)
3644
abstract val intermediateDir: DirectoryProperty
@@ -48,17 +56,21 @@ abstract class CopyFlutterJniLibsTask : DefaultTask() {
4856
fun copy() {
4957
fileSystemOperations.sync {
5058
into(destinationDir)
51-
targetPlatforms.get().forEach { targetPlatform ->
52-
val abi: String? = FlutterPluginConstants.PLATFORM_ARCH_MAP[targetPlatform]
53-
from(intermediateDir.dir(abi ?: "null")) {
54-
include("*.so")
55-
rename { filename: String -> "lib$filename" }
56-
into(abi ?: "null")
57-
}
58-
val nativeAssetsDir = intermediateDir.dir("native_assets/jniLibs/lib/$abi")
59-
from(nativeAssetsDir) {
60-
include("*.so")
61-
into(abi ?: "null")
59+
// When there is no Flutter build for this variant (e.g. an assembleAndroidTest build),
60+
// there is nothing to stage; the empty sync simply clears destinationDir.
61+
if (intermediateDir.isPresent) {
62+
targetPlatforms.get().forEach { targetPlatform ->
63+
val abi: String? = FlutterPluginConstants.PLATFORM_ARCH_MAP[targetPlatform]
64+
from(intermediateDir.dir(abi ?: "null")) {
65+
include("*.so")
66+
rename { filename: String -> "lib$filename" }
67+
into(abi ?: "null")
68+
}
69+
val nativeAssetsDir = intermediateDir.dir("native_assets/jniLibs/lib/$abi")
70+
from(nativeAssetsDir) {
71+
include("*.so")
72+
into(abi ?: "null")
73+
}
6274
}
6375
}
6476
}

packages/flutter_tools/test/integration.shard/gradle_libapp_so_packaging_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,45 @@ android {
254254
expect(libappContent.contains('probe-BBBB'), isTrue);
255255
expect(libappContent.contains('probe-AAAA'), isFalse);
256256
});
257+
258+
// Regression test for https://github.com/flutter/flutter/issues/188785.
259+
//
260+
// Building the androidTest variant directly (as flutter/packages' Firebase Test
261+
// Lab tooling does) configures Gradle without a Flutter compile task: the single
262+
// `assembleAndroidTest` CLI task makes `shouldConfigureFlutterTask` return false,
263+
// so `compileFlutterBuild<Variant>` is never registered. The jniLibs copy task
264+
// wired via the variant API must tolerate that (absent) compile task rather than
265+
// failing with "Task with name 'compileFlutterBuildDebug' not found".
266+
testWithoutContext(
267+
'app:assembleAndroidTest builds when no Flutter compile task is configured',
268+
() async {
269+
final Directory appDir = _createApp(tempDir);
270+
271+
// Configure Gradle without running the Flutter build (no `flutter assemble`).
272+
final ProcessResult configResult = processManager.runSync(<String>[
273+
flutterBin,
274+
'build',
275+
'apk',
276+
'--debug',
277+
'--config-only',
278+
], workingDirectory: appDir.path);
279+
expect(configResult, const ProcessResultMatcher());
280+
281+
final Directory androidDir = appDir.childDirectory('android');
282+
final File gradlew = androidDir.childFile(Platform.isWindows ? 'gradlew.bat' : 'gradlew');
283+
final ProcessResult assembleResult = processManager.runSync(<String>[
284+
gradlew.path,
285+
'app:assembleAndroidTest',
286+
'-Pverbose=true',
287+
], workingDirectory: androidDir.path);
288+
expect(
289+
assembleResult.exitCode,
290+
0,
291+
reason:
292+
'gradlew app:assembleAndroidTest failed:\n${assembleResult.stdout}\n${assembleResult.stderr}',
293+
);
294+
},
295+
);
257296
}
258297

259298
Directory _createApp(Directory workingDir) {

0 commit comments

Comments
 (0)