bazelbuild / bazelbuild/rules_android

Core library desugaring: the desugared library is appended to the APK unshrunk

Open
#533 0 comments 2 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.