bazelbuild / bazelbuild/rules_android
Core library desugaring: the desugared library is appended to the APK unshrunk
- Dominant language
- Java
- Stars
- 203
- Forks
- 95
- PR merge metrics
- No merged PRs in 30d
Description
When core library desugaring is enabled, the R8 path appends the prebuilt `java8_legacy_dex` from the toolchain to the final dexes wholesale. There is no shrinking step at all, so every APK bundles the entire j$.* runtime regardless of how much of it the app actually uses.
AGP instead runs an R8 -> TraceReferences -> L8 pipeline: trace which j$.* APIs the optimized app actually reaches, shrink the desugared library down to those with L8, and append the result. So compared to a Gradle build of the same app, the Bazel APK carries a lot of dead j$.* code.
Numbers from our app (nio desugar config): total dex size went from ~16 MiB to ~14 MiB with shrinking, i.e. roughly 2 MiB of unused j$.* code was being shipped.
We're running a patch that reproduces the AGP pipeline: https://github.com/Dolfik1/rules_android/commit/031d22ff19929170e8a8e15bae3e077c96a431dc
Notes on the patch:
- TraceReferences is used to produce the L8 keep rules because R8 9.x removed `--desugared-lib-pg-conf-output`, so R8 can no longer emit them itself. TraceReferences is the R8-sanctioned replacement and what AGP uses.
- TraceReferences needs `--lib` to be the same library set R8 saw (android.jar plus the app's neverlink/compile-only jars), not android.jar alone. If a j$.* member is only reachable through a dependency class missing from --lib, resolution fails and that keep rule is silently dropped, which would surface as runtime NoClassDefFoundError instead of a build error.
- L8 runs with `-dontobfuscate`. AGP also obfuscates the desugared library and surfaces a mapping for retrace; the current rules_android path appends a D8-built (unminified) dex, so keeping names readable matches existing behavior. Matching AGP's obfuscation + mapping would be a follow-up.
- `--min-api` is set to the binary's effective min SDK instead of whatever the prebuilt java8_legacy_dex was baked with.
- New toolchain attrs: l8, tracereferences, desugar_jdk_libs_all, desugared_jdk_libs_jar.
Happy to turn this into a PR with tests if you'd take it. Main design question is whether you'd want the shrinking pipeline gated behind a flag or as the new default for the R8 path.
Contributor guide
Research direction
Start by reviewing the current R8 path and the linked patch that reproduces the AGP R8 -> TraceReferences -> L8 pipeline. Verify that TraceReferences receives the same library set as R8, L8 uses the effective min SDK, and the shrunken desugared library is appended; add tests covering the selected default or flag behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, java
- Domain
- build-system, mobile
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100