[tool] Fix libapp.so dropped from APK/app bundle#188119
Merged
auto-submit[bot] merged 14 commits intoJun 23, 2026
Merged
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).
Contributor
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
This was referenced Jun 24, 2026
This was referenced Jun 25, 2026
via-guy
pushed a commit
to via-guy/flutter
that referenced
this pull request
Jun 26, 2026
## 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
auto-submit Bot
pushed a commit
that referenced
this pull request
Jun 30, 2026
…188589) ### Issue Link: What is the link to the issue this cherry-pick is addressing? #186810 #187388 #187553 ### Impact Description: What is the impact (ex. visual jank on Samsung phones, app crash, cannot ship an iOS app)? Does it impact development (ex. flutter doctor crashes when Android Studio is installed), or the shipping of production apps (the app crashes on launch). This information is for domain experts and release engineers to understand the consequences of saying yes or no to the cherry pick. The root cause either presents as the app crashing on startup, or the build failing with the message > "Release app bundle failed to strip debug symbols from native libraries" ### Changelog Description: Explain this cherry pick: * In one line that is accessible to most Flutter developers. * That describes the state prior to the fix. * That includes which platforms are impacted. See [best practices](https://github.com/flutter/flutter/blob/main/docs/releases/Hotfix-Documentation-Best-Practices.md) for examples. < Replace with changelog description here > [flutter/186810 flutter/187388 flutter/187553] When building android app bundles using flavors, or with an old app template combined with a plugin coming alphabetically before app, fixes problems with failing to include libapp.so in the produced app bundle. ### Workaround: Is there a workaround for this issue? For the case of the old app template combined with a plugin coming before "app" alphabetically, there is a workaround here #186810 (comment). For the flavors case there is not a workaround. ### Risk: What is the risk level of this cherry-pick? ### Test Coverage: Are you confident that your fix is well-tested by automated tests? ### Validation Steps: What are the steps to validate that this fix works? 1. make a fresh project 2. combine the subprojects in `android/build.gradle(.kts)`: find ```kotlin subprojects { val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) project.layout.buildDirectory.value(newSubprojectBuildDir) } subprojects { project.evaluationDependsOn(":app") } ``` and combine ```kotlin subprojects { val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) project.layout.buildDirectory.value(newSubprojectBuildDir) project.evaluationDependsOn(":app") } ``` 3. add a plugin which comes alphabetically before "app" 4. also you will need to disable r8, due to how the templates have drifted over time. ``` // after signingConfig = signingConfigs.getByName("debug") isMinifyEnabled = false isShrinkResources = false ``` Also, you can separately test the repro steps listed in #187388 to validate that this fixes the flavors-symptom of this underlying root cause.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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