[tool] Fix libapp.so dropped from APK/app bundle#188119
Conversation
…robustness)
libapp.so could be missing from the merged native libraries - causing a
"VM snapshot invalid" crash for APKs, or a "failed to strip debug symbols"
build failure for app bundles - in two scenarios:
* A combined "subprojects { ... evaluationDependsOn(\":app\") }" block in the
root android build.gradle together with a plugin whose Gradle subproject
sorts before ":app". This evaluated ":app" before its build directory was
redirected, so the source-set jniLibs srcDir (resolved eagerly via
.get().asFile) disagreed with the destination copyJniLibs writes to
(resolved lazily), dropping libapp.so.
flutter#186810
* Flavored builds where a prior single-ABI build (e.g. a flutter run on one
device) left the build up to date for only that ABI. copyJniLibs wrote into
a directory nested inside the Flutter task's own output directory, creating
overlapping task outputs that undermined incremental checks.
flutter#187388
Both stem from flutter#181275 moving libapp.so from a jar dependency onto a
source-set jniLibs directory.
Register the source-set srcDir from the lazy provider (not .get().asFile) so
it resolves to the same (possibly redirected) build directory as the copy
destination, and move the staged jniLibs directory to a sibling of the
Flutter task output directory to avoid overlapping outputs. Adds integration
tests covering both scenarios.
…id Windows test failure
…ection, assert non-null outputDirectory
- Remove the stale comment left over from the abandoned source-set approach. - Add KDoc to CopyFlutterJniLibsTask and PathSensitivity.RELATIVE on its input directory for build-cache relocatability. - Use getByType (not findByType) for AndroidComponentsExtension so a misconfiguration fails loudly instead of silently skipping libapp.so. - Extract a shared flutterCompileTaskName() helper used by both the variant API callback and addFlutterDeps, with a comment explaining the name-based lookup (the callback runs before the task is registered).
The test passed as you had written. However, the cache setup and the local engine args both seemed unnecessary so I removed them. Let me know if they were actually structurally important. |
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
## Summary `libapp.so` could be silently dropped from release APKs and app bundles, surfacing as either: - a runtime crash on launch — `VM snapshot invalid and could not be inferred from settings` — for APKs, or - a `Release app bundle failed to strip debug symbols from native libraries` build failure for app bundles. ## Root cause Regression from flutter#181275, which moved `libapp.so` from a jar dependency onto a Flutter Gradle Plugin source-set `jniLibs` directory. That delivery was fragile in two ways, both of which dropped `libapp.so` from the merged native libraries (while `libflutter.so`/`libdartjni.so`, delivered as AAR dependencies, were unaffected — which is why the failure looked asymmetric): 1. The source-set `jniLibs` `srcDir` was resolved eagerly (`.get().asFile`) at `:app` configuration time, while the copy task wrote lazily. When `:app` was evaluated before its build directory had been redirected — a combined `subprojects { … evaluationDependsOn(":app") }` block (the pre-flutter#91030 template shape) together with a plugin whose Gradle subproject name sorts before `:app` — the two disagreed on the build directory and the staged `libapp.so` was never merged. (flutter#186810) 2. The copy task wrote into a directory nested inside the Flutter task's own output directory, creating overlapping task outputs that undermined Gradle's incremental checks — e.g. a flavored project where a prior single-ABI build (a `flutter run` on one device) left the other ABIs missing `libapp.so`. (flutter#187388) ## Fix Stage `libapp.so` (and any bundled native assets) through a dedicated `CopyFlutterJniLibsTask` whose output is registered on each variant via AGP's variant API: [`variant.sources.jniLibs.addGeneratedSourceDirectory(...)`](https://developer.android.com/reference/tools/gradle-api/9.1/com/android/build/api/variant/SourceDirectories#addStaticSourceDirectory(kotlin.String)). AGP then owns the task dependency, resolves the output path lazily (correct regardless of project evaluation order or build-dir redirection), keeps it in its own output directory (no overlapping outputs), and strips/extracts debug symbols from it like any other native library. This restores the robustness of the original jar-based inclusion while keeping `libapp.so` strippable. ## Tests New integration test `gradle_libapp_so_packaging_test.dart` covering both triggers: the combined `subprojects` block + a plugin sorted before `:app`, and a flavored single-ABI build preceding a multi-ABI build. Fixes flutter#186810 Fixes flutter#187388 Fixes flutter#187553
Summary
libapp.socould be silently dropped from release APKsand app bundles, surfacing as either:
VM snapshot invalid and could not be inferred from settings— for APKs, orRelease app bundle failed to strip debug symbols from native librariesbuild failure for app bundles.
Root cause
Regression from #181275, which moved
libapp.sofrom a jar dependency onto aFlutter Gradle Plugin source-set
jniLibsdirectory. That delivery was fragilein two ways, both of which dropped
libapp.sofrom the merged native libraries(while
libflutter.so/libdartjni.so, delivered as AAR dependencies, wereunaffected — which is why the failure looked asymmetric):
jniLibssrcDirwas resolved eagerly (.get().asFile) at:appconfiguration time, while the copy task wrote lazily. When:appwasevaluated before its build directory had been redirected — a combined
subprojects { … evaluationDependsOn(":app") }block (the pre-Change project.buildDir in standalonesubprojectsproperty #91030 templateshape) together with a plugin whose Gradle subproject name sorts before
:app— the two disagreed on the build directory and the stagedlibapp.sowas never merged. (Flutter 3.44.0: appbundle release fails with "Release app bundle failed to strip debug symbols from native libraries" #186810)
output directory, creating overlapping task outputs that undermined Gradle's
incremental checks — e.g. a flavored project where a prior single-ABI build
(a
flutter runon one device) left the other ABIs missinglibapp.so.(After updating to flutter 3.44.1 - release - versions of the app crash with VM snapshot failed #187388)
Fix
Stage
libapp.so(and any bundled native assets) through a dedicatedCopyFlutterJniLibsTaskwhose output is registered on each variant via AGP'svariant API:
variant.sources.jniLibs.addGeneratedSourceDirectory(...). AGP thenowns the task dependency, resolves the output path lazily (correct regardless of
project evaluation order or build-dir redirection), keeps it in its own output
directory (no overlapping outputs), and strips/extracts debug symbols from it
like any other native library. This restores the robustness of the original
jar-based inclusion while keeping
libapp.sostrippable.Tests
New integration test
gradle_libapp_so_packaging_test.dartcovering bothtriggers: the combined
subprojectsblock + a plugin sorted before:app, anda flavored single-ABI build preceding a multi-ABI build.
Fixes #186810
Fixes #187388
Fixes #187553