From cb6143a142a3a7985d18ad346a6c21314b90cf87 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 14 Aug 2020 17:39:29 -0700 Subject: [PATCH] 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 --- android/override_module.go | 12 +++++++++ java/androidmk.go | 10 +++----- java/dex.go | 51 +++++++++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 21 deletions(-) diff --git a/android/override_module.go b/android/override_module.go index 3994084a8..f8342d52d 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -313,3 +313,15 @@ func replaceDepsOnOverridingModuleMutator(ctx BottomUpMutatorContext) { } } } + +// 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 bc327cf68..f0e635745 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -127,9 +127,8 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...) } - if library.dexer.proguardDictionary.Valid() { - entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.dexer.proguardDictionary.Path()) - } + entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_DICT", library.dexer.proguardDictionary) + entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", library.dexer.proguardUsageZip) entries.SetString("LOCAL_MODULE_STEM", library.Stem()) entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports) @@ -332,9 +331,8 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { if app.jacocoReportClassesFile != nil { entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", app.jacocoReportClassesFile) } - if app.dexer.proguardDictionary.Valid() { - entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.dexer.proguardDictionary.Path()) - } + entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_DICT", app.dexer.proguardDictionary) + entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", app.dexer.proguardUsageZip) 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 cd45a9319..c85914c41 100644 --- a/java/dex.go +++ b/java/dex.go @@ -72,6 +72,7 @@ type dexer struct { // list of extra proguard flag files extraProguardFlagFiles android.Paths proguardDictionary android.OptionalPath + proguardUsageZip android.OptionalPath } func (d *dexer) effectiveOptimizeEnabled() bool { @@ -109,13 +110,17 @@ var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8", 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{ @@ -138,7 +143,15 @@ var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8", 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 (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion sdkSpec) []string { flags := d.dexProperties.Dxflags @@ -259,26 +272,34 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi if useR8 { proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary") d.proguardDictionary = android.OptionalPathForPath(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") + d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip) r8Flags, r8Deps := d.r8Flags(ctx, flags) rule := r8 args := map[string]string{ - "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "), - "zipFlags": zipFlags, - "outDict": proguardDictionary.String(), - "outDir": outDir.String(), + "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "), + "zipFlags": zipFlags, + "outDict": 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 := d8Flags(flags)