Capture list of unused methods when shrinking in R8
Use the -printusage flag in R8 to output a list of the unused
methods. Some of the files can be large (2MB for DocumentsUI,
87MB for all of AOSP), so immediately zip them and remove the
originals. The zipped files will be merged and disted.
Bug: 151857441
Test: m TARGET_BUILD_APPS=DocumentsUI dist
Change-Id: I780e84e80eba7fe4d4fa15fec0f461890afd900b
Merged-In: I780e84e80eba7fe4d4fa15fec0f461890afd900b
(cherry picked from commit cb6143a142a3a7985d18ad346a6c21314b90cf87)
diff --git a/android/override_module.go b/android/override_module.go
index 90ddf50..3d8b18b 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -302,3 +302,15 @@
}
}
}
+
+// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
+// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
+// or if this variant is not overridden.
+func ModuleNameWithPossibleOverride(ctx ModuleContext) string {
+ if overridable, ok := ctx.Module().(OverridableModule); ok {
+ if o := overridable.GetOverriddenBy(); o != "" {
+ return o
+ }
+ }
+ return ctx.ModuleName()
+}
diff --git a/java/androidmk.go b/java/androidmk.go
index ae257d7..a159b77 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -130,6 +130,9 @@
if library.proguardDictionary != nil {
entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
}
+ if library.proguardUsageZip.Valid() {
+ entries.SetPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", library.proguardUsageZip.Path())
+ }
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
@@ -335,6 +338,9 @@
if app.proguardDictionary != nil {
entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.proguardDictionary)
}
+ if app.proguardUsageZip.Valid() {
+ entries.SetPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", app.proguardUsageZip.Path())
+ }
if app.Name() == "framework-res" {
entries.SetString("LOCAL_MODULE_PATH", "$(TARGET_OUT_JAVA_LIBRARIES)")
diff --git a/java/dex.go b/java/dex.go
index 9e61e95..fd7110f 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -55,13 +55,17 @@
var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `rm -f "$outDict" && ` +
+ `rm -f "$outDict" && rm -rf "${outUsageDir}" && ` +
+ `mkdir -p $$(dirname ${outUsage}) && ` +
`$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
`--force-proguard-compatibility ` +
`--no-data-resources ` +
- `-printmapping $outDict ` +
+ `-printmapping ${outDict} ` +
+ `-printusage ${outUsage} ` +
`$r8Flags && ` +
- `touch "$outDict" && ` +
+ `touch "${outDict}" "${outUsage}" && ` +
+ `${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
+ `rm -rf ${outUsageDir} && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
@@ -84,7 +88,15 @@
ExecStrategy: "${config.RER8ExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- }, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"})
+ "$zipUsageTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "${outUsage}"},
+ OutputFiles: []string{"${outUsageZip}"},
+ ExecStrategy: "${config.RER8ExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir",
+ "r8Flags", "zipFlags"}, []string{"implicits"})
func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
flags := j.deviceProperties.Dxflags
@@ -214,26 +226,34 @@
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
j.proguardDictionary = proguardDictionary
+ proguardUsageDir := android.PathForModuleOut(ctx, "proguard_usage")
+ proguardUsage := proguardUsageDir.Join(ctx, ctx.Namespace().Path,
+ android.ModuleNameWithPossibleOverride(ctx), "unused.txt")
+ proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip")
+ j.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
r8Flags, r8Deps := j.r8Flags(ctx, flags)
rule := r8
args := map[string]string{
- "r8Flags": strings.Join(r8Flags, " "),
- "zipFlags": zipFlags,
- "outDict": j.proguardDictionary.String(),
- "outDir": outDir.String(),
+ "r8Flags": strings.Join(r8Flags, " "),
+ "zipFlags": zipFlags,
+ "outDict": j.proguardDictionary.String(),
+ "outUsageDir": proguardUsageDir.String(),
+ "outUsage": proguardUsage.String(),
+ "outUsageZip": proguardUsageZip.String(),
+ "outDir": outDir.String(),
}
if ctx.Config().IsEnvTrue("RBE_R8") {
rule = r8RE
args["implicits"] = strings.Join(r8Deps.Strings(), ",")
}
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "r8",
- Output: javalibJar,
- ImplicitOutput: proguardDictionary,
- Input: classesJar,
- Implicits: r8Deps,
- Args: args,
+ Rule: rule,
+ Description: "r8",
+ Output: javalibJar,
+ ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip},
+ Input: classesJar,
+ Implicits: r8Deps,
+ Args: args,
})
} else {
d8Flags, d8Deps := j.d8Flags(ctx, flags)
diff --git a/java/java.go b/java/java.go
index 4612b76..c89d669 100644
--- a/java/java.go
+++ b/java/java.go
@@ -439,6 +439,9 @@
// output file containing mapping of obfuscated names
proguardDictionary android.Path
+ // output file containing list of unused methods
+ proguardUsageZip android.OptionalPath
+
// output file of the module, which may be a classes jar or a dex jar
outputFile android.Path
extraOutputFiles android.Paths