Add flag for optimized resource shrinking with R8

If the flag is set we will:
 - pass --optimized-resource-shrinking to the r8 invocation
 - use non final fields for the generated R classes
 - not pass the aapt2 generated proguard rules, R8 will do the tracing of xml files

Bug: 325905703
Test: This is simply passing the flag through to R8, this is off by default
Change-Id: Ib2043f3201578c3bcd39c1de9a524fd78f6d795c
This commit is contained in:
Rico Wind
2024-03-13 13:09:17 +01:00
parent 1f4ffda2ed
commit a2fa263786
3 changed files with 35 additions and 6 deletions

View File

@@ -351,6 +351,7 @@ type aaptBuildActionOptions struct {
classLoaderContexts dexpreopt.ClassLoaderContextMap classLoaderContexts dexpreopt.ClassLoaderContextMap
excludedLibs []string excludedLibs []string
enforceDefaultTargetSdkVersion bool enforceDefaultTargetSdkVersion bool
forceNonFinalResourceIDs bool
extraLinkFlags []string extraLinkFlags []string
aconfigTextFiles android.Paths aconfigTextFiles android.Paths
} }
@@ -544,7 +545,8 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio
if a.useResourceProcessorBusyBox(ctx) { if a.useResourceProcessorBusyBox(ctx) {
rJar := android.PathForModuleOut(ctx, "busybox/R.jar") rJar := android.PathForModuleOut(ctx, "busybox/R.jar")
resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags) resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags,
opts.forceNonFinalResourceIDs)
aapt2ExtractExtraPackages(ctx, extraPackages, rJar) aapt2ExtractExtraPackages(ctx, extraPackages, rJar)
transitiveRJars = append(transitiveRJars, rJar) transitiveRJars = append(transitiveRJars, rJar)
a.rJar = rJar a.rJar = rJar
@@ -608,7 +610,8 @@ var resourceProcessorBusyBox = pctx.AndroidStaticRule("resourceProcessorBusyBox"
// using Bazel's ResourceProcessorBusyBox tool, which is faster than compiling the R.java files and // using Bazel's ResourceProcessorBusyBox tool, which is faster than compiling the R.java files and
// supports producing classes for static dependencies that only include resources from that dependency. // supports producing classes for static dependencies that only include resources from that dependency.
func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, manifest android.Path, func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, manifest android.Path,
rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string) { rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string,
forceNonFinalIds bool) {
var args []string var args []string
var deps android.Paths var deps android.Paths
@@ -618,6 +621,9 @@ func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, ma
// to ResourceProcessorBusyBox so that it can regenerate R.class files with the final resource IDs for each // to ResourceProcessorBusyBox so that it can regenerate R.class files with the final resource IDs for each
// package. // package.
args, deps = transitiveDeps.resourceProcessorDeps() args, deps = transitiveDeps.resourceProcessorDeps()
if forceNonFinalIds {
args = append(args, "--finalFields=false")
}
} else { } else {
// When compiling a library don't pass any dependencies as it only needs to generate an R.class file for this // When compiling a library don't pass any dependencies as it only needs to generate an R.class file for this
// library. Pass --finalFields=false so that the R.class file contains non-final fields so they don't get // library. Pass --finalFields=false so that the R.class file contains non-final fields so they don't get
@@ -1221,7 +1227,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil) linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil)
a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar") a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar")
resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil) resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil, false)
aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar) aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar)

View File

@@ -519,12 +519,15 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
} }
// Use non final ids if we are doing optimized shrinking and are using R8.
nonFinalIds := Bool(a.dexProperties.Optimize.Optimized_shrink_resources) && a.dexer.effectiveOptimizeEnabled()
a.aapt.buildActions(ctx, a.aapt.buildActions(ctx,
aaptBuildActionOptions{ aaptBuildActionOptions{
sdkContext: android.SdkContext(a), sdkContext: android.SdkContext(a),
classLoaderContexts: a.classLoaderContexts, classLoaderContexts: a.classLoaderContexts,
excludedLibs: a.usesLibraryProperties.Exclude_uses_libs, excludedLibs: a.usesLibraryProperties.Exclude_uses_libs,
enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(), enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(),
forceNonFinalResourceIDs: nonFinalIds,
extraLinkFlags: aaptLinkFlags, extraLinkFlags: aaptLinkFlags,
aconfigTextFiles: getAconfigFilePaths(ctx), aconfigTextFiles: getAconfigFilePaths(ctx),
}, },
@@ -547,7 +550,13 @@ func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles) staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...) a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile) if !Bool(a.dexProperties.Optimize.Optimized_shrink_resources) {
// When using the optimized shrinking the R8 enqueuer will traverse the xml files that become
// live for code references and (transitively) mark these as live.
// In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now
// dead code alive)
a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
}
} }
func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath { func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath {
@@ -580,7 +589,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a
var packageResources = a.exportPackage var packageResources = a.exportPackage
if ctx.ModuleName() != "framework-res" { if ctx.ModuleName() != "framework-res" {
if Bool(a.dexProperties.Optimize.Shrink_resources) { if a.dexProperties.resourceShrinkingEnabled() {
protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk") protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
aapt2Convert(ctx, protoFile, packageResources, "proto") aapt2Convert(ctx, protoFile, packageResources, "proto")
a.dexer.resourcesInput = android.OptionalPathForPath(protoFile) a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
@@ -603,7 +612,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a
} }
a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars) a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
if Bool(a.dexProperties.Optimize.Shrink_resources) { if a.dexProperties.resourceShrinkingEnabled() {
binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk") binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary") aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
packageResources = binaryResources packageResources = binaryResources

View File

@@ -66,6 +66,12 @@ type DexProperties struct {
// If true, optimize for size by removing unused resources. Defaults to false. // If true, optimize for size by removing unused resources. Defaults to false.
Shrink_resources *bool Shrink_resources *bool
// If true, use optimized resource shrinking in R8, overriding the
// Shrink_resources setting. Defaults to false.
// Optimized shrinking means that R8 will trace and treeshake resources together with code
// and apply additional optimizations. This implies non final fields in the R classes.
Optimized_shrink_resources *bool
// Flags to pass to proguard. // Flags to pass to proguard.
Proguard_flags []string Proguard_flags []string
@@ -105,6 +111,10 @@ func (d *dexer) effectiveOptimizeEnabled() bool {
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault) return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
} }
func (d *DexProperties) resourceShrinkingEnabled() bool {
return BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
}
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{ blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -351,10 +361,14 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
r8Flags = append(r8Flags, "-ignorewarnings") r8Flags = append(r8Flags, "-ignorewarnings")
} }
// resourcesInput is empty when we don't use resource shrinking, if on, pass these to R8
if d.resourcesInput.Valid() { if d.resourcesInput.Valid() {
r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String()) r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
r8Deps = append(r8Deps, d.resourcesInput.Path()) r8Deps = append(r8Deps, d.resourcesInput.Path())
r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String()) r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
if Bool(opt.Optimized_shrink_resources) {
r8Flags = append(r8Flags, "--optimized-resource-shrinking")
}
} }
return r8Flags, r8Deps return r8Flags, r8Deps