diff options
Diffstat (limited to 'java/dex.go')
| -rw-r--r-- | java/dex.go | 358 |
1 files changed, 321 insertions, 37 deletions
diff --git a/java/dex.go b/java/dex.go index e3058e9bf..fa38d6131 100644 --- a/java/dex.go +++ b/java/dex.go @@ -15,6 +15,8 @@ package java import ( + "fmt" + "path/filepath" "strconv" "strings" @@ -25,6 +27,10 @@ import ( "android/soong/remoteexec" ) +func init() { + pctx.HostBinToolVariable("symbols_map", "symbols_map") +} + type DexProperties struct { // If set to true, compile dex regardless of installable. Defaults to false. Compile_dex *bool @@ -80,9 +86,10 @@ type DexProperties struct { Shrink *bool // If true, optimize bytecode. Defaults to false. - Optimize *bool + Optimize proptools.Configurable[bool] `android:"replace_instead_of_append"` - // If true, obfuscate bytecode. Defaults to false. + // If true, obfuscate bytecode by renaming packages, classes, and members. + // Defaults to false. Obfuscate *bool // If true, do not use the flag files generated by aapt that automatically keep @@ -135,6 +142,11 @@ type DexProperties struct { // TODO(b/212737576): Handle this implicitly using bottom-up deps mutation and implicit // creation of a proxy `.impl` library. Trace_references_from proptools.Configurable[[]string] `android:"arch_variant"` + + // Add libraries using `--classpath` instead of `--libs`, to allow overrides. This + // should normally not be used, but can be necessary when running R8 on the boot + // classpath itself. + Import_libraries_as_classpath *bool } // Keep the data uncompressed. We always need uncompressed dex for execution, @@ -182,10 +194,125 @@ func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleCont return d.resourceShrinkingEnabled(ctx) && BoolDefault(d.Optimize.Optimized_shrink_resources, ctx.Config().UseOptimizedResourceShrinkingByDefault()) } -func (d *dexer) optimizeOrObfuscateEnabled(ctx android.EarlyModuleContext) bool { - return d.effectiveOptimizeEnabled(ctx) && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate)) +func (d *dexer) optimizeOrObfuscateEnabled(ctx android.ModuleContext) bool { + return d.effectiveOptimizeEnabled(ctx) && (d.dexProperties.Optimize.Optimize.GetOrDefault(ctx, false) || proptools.Bool(d.dexProperties.Optimize.Obfuscate)) } +// Removes all outputs of d8Inc rule +var d8IncClean = pctx.AndroidStaticRule("d8Inc-partialcompileclean", + blueprint.RuleParams{ + Command: `rm -rf "${outDir}" "${builtOut}" "${d8Deps}"`, + }, "outDir", "d8Flags", "d8Deps", "zipFlags", "mergeZipsFlags", "builtOut", +) + +var d8Inc, d8IncRE = pctx.MultiCommandRemoteStaticRules("d8Inc", + blueprint.RuleParams{ + Command: `mkdir -p "$outDir" "$outDir/packages" && ` + + `${config.IncrementalDexInputCmd} ` + + `--classesJar $in --dexTarget $out --deps $d8Deps --outputDir $outDir --packageOutputDir $outDir/packages && ` + + `$d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in --packages $out.rsp --mod-packages $out.inc.rsp --package-output $outDir/packages && ` + + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` + + `if [ -f "$out.input.pc_state.new" ]; then mv "$out.input.pc_state.new" "$out.input.pc_state" && ` + + `rm -rf $out.input.pc_state.new; fi && ` + + `if [ -f "$out.deps.pc_state.new" ]; then mv "$out.deps.pc_state.new" "$out.deps.pc_state" && ` + + `rm -rf $out.deps.pc_state.new; fi && ` + + `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`, + CommandDeps: []string{ + "${config.IncrementalDexInputCmd}", + "${config.D8Cmd}", + "${config.SoongZipCmd}", + "${config.MergeZipsCmd}", + }, + }, map[string]*remoteexec.REParams{ + "$d8Template": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "compiler": "d8"}, + Inputs: []string{"${config.D8Jar}"}, + ExecStrategy: "${config.RED8ExecStrategy}", + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$outDir/classes.dex.jar"}, + ExecStrategy: "${config.RED8ExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + }, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags", "d8Deps"}, nil) + +// Include all of the args for d8IncR8, so that we can generate the partialcompileclean target's build using the same list. +var d8IncR8Clean = pctx.AndroidStaticRule("d8Incr8-partialcompileclean", + blueprint.RuleParams{ + Command: `rm -rf "${outDir}" "${outDict}" "${outConfig}" "${outUsage}" "${outUsageZip}" "${outUsageDir}" ` + + `"${resourcesOutput}" "${outR8ArtProfile}" ${builtOut} ${d8Deps}`, + }, "outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir", "builtOut", + "d8Flags", "d8Deps", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile", "implicits", +) + +var d8IncR8, d8IncR8RE = pctx.MultiCommandRemoteStaticRules("d8Incr8", + blueprint.RuleParams{ + Command: `mkdir -p "$outDir" "$outDir/packages" && ` + + `rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` + + `mkdir -p $$(dirname ${outUsage}) && ` + + `if [ -n "$${SOONG_USE_PARTIAL_COMPILE}" ]; then ` + + ` for f in "${outConfig}" "${outDict}" "${outUsage}" "${resourcesOutput}"; do ` + + ` test -n "$${f}" && test ! -f "$${f}" && mkdir -p "$$(dirname "$${f}")" && touch "$${f}" || true; ` + + ` done && ` + + ` ${config.IncrementalDexInputCmd} --classesJar $in --dexTarget $out --deps $d8Deps --outputDir $outDir --packageOutputDir $outDir/packages && ` + + ` $d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in --packages $out.rsp --mod-packages $out.inc.rsp --package-output $outDir/packages; ` + + `else ` + + ` rm -rf "$outDir" && mkdir -p "$outDir" && ` + + ` $r8Template${config.R8Cmd} ${config.R8Flags} $r8Flags -injars $in --output $outDir ` + + ` --no-data-resources ` + + ` -printmapping ${outDict} ` + + ` -printconfiguration ${outConfig} ` + + ` -printusage ${outUsage} ` + + ` --deps-file ${out}.d && ` + + ` touch "${outDict}" "${outConfig}" "${outUsage}"; ` + + `fi && ` + + `${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" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` + + `if [ -f "$out.input.pc_state.new" ]; then mv "$out.input.pc_state.new" "$out.input.pc_state" && ` + + `rm -rf $out.input.pc_state.new; fi && ` + + `if [ -f "$out.deps.pc_state.new" ]; then mv "$out.deps.pc_state.new" "$out.deps.pc_state" && ` + + `rm -rf $out.deps.pc_state.new; fi && ` + + `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar" `, + CommandDeps: []string{ + "${config.IncrementalDexInputCmd}", + "${config.D8Cmd}", + "${config.R8Cmd}", + "${config.SoongZipCmd}", + "${config.MergeZipsCmd}", + }, + }, map[string]*remoteexec.REParams{ + "$d8Template": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "compiler": "d8"}, + Inputs: []string{"${config.D8Jar}"}, + ExecStrategy: "${config.RED8ExecStrategy}", + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$r8Template": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "compiler": "r8"}, + Inputs: []string{"$implicits", "${config.R8Jar}"}, + OutputFiles: []string{"${outUsage}", "${outConfig}", "${outDict}", "${resourcesOutput}", "${outR8ArtProfile}"}, + ExecStrategy: "${config.RER8ExecStrategy}", + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$outDir/classes.dex.jar"}, + ExecStrategy: "${config.RED8ExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + }, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir", + "d8Flags", "d8Deps", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"}) + var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + @@ -195,6 +322,7 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`, CommandDeps: []string{ "${config.D8Cmd}", + "${config.D8Jar}", "${config.SoongZipCmd}", "${config.MergeZipsCmd}", }, @@ -250,7 +378,9 @@ var d8r8, d8r8RE = pctx.MultiCommandRemoteStaticRules("d8r8", `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar" `, CommandDeps: []string{ "${config.D8Cmd}", + "${config.D8Jar}", "${config.R8Cmd}", + "${config.R8Jar}", "${config.SoongZipCmd}", "${config.MergeZipsCmd}", }, @@ -301,6 +431,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", Deps: blueprint.DepsGCC, CommandDeps: []string{ "${config.R8Cmd}", + "${config.R8Jar}", "${config.SoongZipCmd}", "${config.MergeZipsCmd}", }, @@ -330,8 +461,14 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", }, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"}) +var proguardDictToProto = pctx.AndroidStaticRule("proguard_dict_to_proto", blueprint.RuleParams{ + Command: `${symbols_map} -r8 $in -location $location -write_if_changed $out`, + Restat: true, + CommandDeps: []string{"${symbols_map}"}, +}, "location") + func (d *dexer) dexCommonFlags(ctx android.ModuleContext, - dexParams *compileDexParams) (flags []string, deps android.Paths) { + dexParams *compileDexParams) (flags []string, deps android.Paths, incD8Compatible bool) { flags = d.dexProperties.Dxflags // Translate all the DX flags to D8 ones until all the build files have been migrated @@ -401,36 +538,41 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext, } flags = append(flags, "--min-api "+strconv.Itoa(minApiFlagValue)) + incD8Compatible = false + // Incremental d8 does not have libraries passed to it for speed, so any + // desugaring with library classes is not possible. + // To cater for this we only enable incD8 when platform build flag is passed + // as it automatically disables desugaring. if addAndroidPlatformBuildFlag { flags = append(flags, "--android-platform-build") + incD8Compatible = true } - return flags, deps + return flags, deps, incD8Compatible } -func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) { +func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams, useD8Inc bool) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) { flags := dexParams.flags d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...) d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...) - d8Deps = append(d8Deps, flags.bootClasspath...) d8Deps = append(d8Deps, flags.dexClasspath...) - - if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil { - d8Flags = append(d8Flags, flags...) - d8Deps = append(d8Deps, deps...) - artProfileOutput = profileOutput + if !useD8Inc { + if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil { + d8Flags = append(d8Flags, flags...) + d8Deps = append(d8Deps, deps...) + artProfileOutput = profileOutput + } } return d8Flags, d8Deps, artProfileOutput } -func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, debugMode bool) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) { - flags := dexParams.flags - opt := d.dexProperties.Optimize +func (d *dexer) r8DepLibFlags(ctx android.ModuleContext, dexParams *compileDexParams) (r8Flags []string, r8Deps android.Paths) { + var depLibs classpath // When an app contains references to APIs that are not in the SDK specified by // its LOCAL_SDK_VERSION for example added by support library or by runtime - // classes added by desugaring, we artifically raise the "SDK version" "linked" by + // classes added by desugaring, we artificially raise the "SDK version" "linked" by // ProGuard, to // - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version. // - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version. @@ -443,14 +585,11 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...) } }) - r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars")) - r8Deps = append(r8Deps, proguardRaiseDeps...) + depLibs = append(depLibs, proguardRaiseDeps...) } - r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars")) - r8Deps = append(r8Deps, flags.bootClasspath...) - r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars")) - r8Deps = append(r8Deps, flags.dexClasspath...) + depLibs = append(depLibs, dexParams.flags.bootClasspath...) + depLibs = append(depLibs, dexParams.flags.dexClasspath...) transitiveStaticLibsLookupMap := map[android.Path]bool{} for _, jar := range d.transitiveStaticLibsHeaderJarsForR8.ToList() { @@ -465,8 +604,27 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, transitiveHeaderJars = append(transitiveHeaderJars, jar) } transitiveClasspath := classpath(transitiveHeaderJars) - r8Flags = append(r8Flags, transitiveClasspath.FormJavaClassPath("-libraryjars")) - r8Deps = append(r8Deps, transitiveClasspath...) + depLibs = append(depLibs, transitiveClasspath...) + + depLibs = depLibs.FirstUniquePaths() + r8Deps = append(r8Deps, depLibs...) + + var libraryDepArg string + if Bool(d.dexProperties.Optimize.Import_libraries_as_classpath) { + libraryDepArg = "--classpath " + } else { + libraryDepArg = "--lib " + } + r8Flags = append(r8Flags, depLibs.FormRepeatedClassPath(libraryDepArg)...) + + return r8Flags, r8Deps +} + +func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, debugMode, useD8Inc bool) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) { + r8Flags, r8Deps = d.r8DepLibFlags(ctx, dexParams) + + flags := dexParams.flags + opt := d.dexProperties.Optimize flagFiles := android.Paths{ android.PathForSource(ctx, "build/make/core/proguard.flags"), @@ -525,7 +683,8 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, // Avoid unnecessary stack frame noise by only injecting source map ids for non-debug // optimized or obfuscated targets. - if (Bool(opt.Optimize) || Bool(opt.Obfuscate)) && !debugMode { + optimize := opt.Optimize.GetOrDefault(ctx, false) + if (optimize || Bool(opt.Obfuscate)) && !debugMode { // TODO(b/213833843): Allow configuration of the prefix via a build variable. var sourceFilePrefix = "go/retraceme " var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\"" @@ -538,7 +697,7 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, r8Flags = append(r8Flags, "-dontshrink") } - if !Bool(opt.Optimize) { + if !optimize { r8Flags = append(r8Flags, "-dontoptimize") } @@ -569,10 +728,12 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, } } - if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil { - r8Flags = append(r8Flags, flags...) - r8Deps = append(r8Deps, deps...) - artProfileOutput = profileOutput + if !useD8Inc { + if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil { + r8Flags = append(r8Flags, flags...) + r8Deps = append(r8Deps, deps...) + artProfileOutput = profileOutput + } } if ctx.Config().UseR8StoreStoreFenceConstructorInlining() { @@ -623,21 +784,23 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam cleanPhonyPath := android.PathForModuleOut(ctx, "dex", dexParams.jarName+"-partialcompileclean").OutputPath outDir := android.PathForModuleOut(ctx, "dex") - zipFlags := "--ignore_missing_files" + zipFlags := "--ignore_missing_files --quiet" if proptools.Bool(d.dexProperties.Uncompress_dex) { zipFlags += " -L 0" } - commonFlags, commonDeps := d.dexCommonFlags(ctx, dexParams) + commonFlags, commonDeps, incD8Compatible := d.dexCommonFlags(ctx, dexParams) // Exclude kotlinc generated files when "exclude_kotlinc_generated_files" is set to true. mergeZipsFlags := "" if proptools.BoolDefault(d.dexProperties.Exclude_kotlinc_generated_files, false) { - mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins" + mergeZipsFlags = "-stripFile META-INF/**/*.kotlin_module -stripFile **/*.kotlin_builtins" } useR8 := d.effectiveOptimizeEnabled(ctx) useD8 := !useR8 || ctx.Config().PartialCompileFlags().Use_d8 + // d8Inc is applicable only when d8 is allowed. + useD8Inc := useD8 && ctx.Config().PartialCompileFlags().Enable_inc_d8 && incD8Compatible rbeR8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") rbeD8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") var rule blueprint.Rule @@ -669,7 +832,7 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam }...) description = "r8" debugMode := android.InList("--debug", commonFlags) - r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode) + r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode, useD8Inc) deps = append(deps, r8Deps...) args["r8Flags"] = strings.Join(append(commonFlags, r8Flags...), " ") if r8ArtProfileOutputPath != nil { @@ -694,25 +857,61 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam args["implicits"] = strings.Join(deps.Strings(), ",") } } + cleanupD8R8, cleanupD8IncR8, cleanupD8Inc := false, false, false if useD8 { description = "d8" - d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams) + d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams, useD8Inc) deps = append(deps, d8Deps...) deps = append(deps, commonDeps...) args["d8Flags"] = strings.Join(append(commonFlags, d8Flags...), " ") if d8ArtProfileOutputPath != nil { artProfileOutputPath = d8ArtProfileOutputPath } + // The file containing dependencies of the current module + // Any change in them may warrant changes in the incremental dex compilation + // source set. + if useD8Inc { + d8DepsFile := android.PathForModuleOut(ctx, dexParams.jarName+".dex.deps.rsp") + android.WriteFileRule(ctx, d8DepsFile, strings.Join(deps.Strings(), "\n")) + deps = append(deps, d8DepsFile) + args["d8Deps"] = d8DepsFile.String() + } // If we are generating both d8 and r8, only use RBE when both are enabled. switch { + // r8 is the selected rule, useD8Inc is the override + case useR8 && rule == r8 && useD8Inc: + rule = d8IncR8 + cleanupD8IncR8 = true + description = "d8IncR8" + // r8 is the selected rule, useD8 is the override case useR8 && rule == r8: rule = d8r8 + cleanupD8R8 = true description = "d8r8" + // rbeR8 is the selected rule, useD8Inc is the override + case useR8 && rule == r8RE && useD8Inc: + rule = d8IncR8RE + cleanupD8IncR8 = true + description = "d8IncR8" + // rbeR8 is the selected rule, useD8 is the override case useR8 && rule == r8RE && rbeD8: rule = d8r8RE + cleanupD8R8 = true description = "d8r8" + // rbeD8 is the selected rule, useD8Inc is the override + case rbeD8 && useD8Inc: + rule = d8IncRE + cleanupD8Inc = true + description = "d8Inc" + // rbeD8 is the selected rule case rbeD8: rule = d8RE + // D8 is the selected rule, useD8Inc is the override + case useD8Inc: + rule = d8Inc + cleanupD8Inc = true + description = "d8Inc" + // D8 is the selected rule default: rule = d8 } @@ -732,7 +931,8 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam Implicits: deps, Args: args, }) - if useR8 && useD8 { + // Run cleanup when d8r8 was used + if cleanupD8R8 { // Generate the rule for partial compile clean. args["builtOut"] = javalibJar.String() ctx.Build(pctx, android.BuildParams{ @@ -744,6 +944,32 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam }) ctx.Phony("partialcompileclean", cleanPhonyPath) } + // Run cleanup when d8IncR8 was used + if cleanupD8IncR8 { + // Generate the rule for partial compile clean. + args["builtOut"] = javalibJar.String() + ctx.Build(pctx, android.BuildParams{ + Rule: d8IncR8Clean, + Description: "d8IncR8Clean", + Output: cleanPhonyPath, + Args: args, + PhonyOutput: true, + }) + ctx.Phony("partialcompileclean", cleanPhonyPath) + } + // Run cleanup when d8Inc was used + if cleanupD8Inc { + // Generate the rule for partial compile clean. + args["builtOut"] = javalibJar.String() + ctx.Build(pctx, android.BuildParams{ + Rule: d8IncClean, + Description: "d8IncClean", + Output: cleanPhonyPath, + Args: args, + PhonyOutput: true, + }) + ctx.Phony("partialcompileclean", cleanPhonyPath) + } if proptools.Bool(d.dexProperties.Uncompress_dex) { alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath @@ -754,6 +980,64 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam return javalibJar, artProfileOutputPath } +type ProguardZips struct { + DictZip android.Path + DictMapping android.Path + UsageZip android.Path +} + +func BuildProguardZips(ctx android.ModuleContext, modules []android.ModuleOrProxy) ProguardZips { + dictZip := android.PathForModuleOut(ctx, "proguard-dict.zip") + dictZipBuilder := android.NewRuleBuilder(pctx, ctx) + dictZipCmd := dictZipBuilder.Command().BuiltTool("soong_zip").Flag("-d").FlagWithOutput("-o ", dictZip) + + dictMapping := android.PathForModuleOut(ctx, "proguard-dict-mapping.textproto") + dictMappingBuilder := android.NewRuleBuilder(pctx, ctx) + dictMappingCmd := dictMappingBuilder.Command().BuiltTool("symbols_map").Flag("-merge").Output(dictMapping) + + protosDir := android.PathForModuleOut(ctx, "proguard_mapping_protos") + + usageZip := android.PathForModuleOut(ctx, "proguard-usage.zip") + usageZipBuilder := android.NewRuleBuilder(pctx, ctx) + usageZipCmd := usageZipBuilder.Command().BuiltTool("merge_zips").Output(usageZip) + + for _, mod := range modules { + if proguardInfo, ok := android.OtherModuleProvider(ctx, mod, ProguardProvider); ok { + // Maintain these out/target/common paths for backwards compatibility. They may be able + // to be changed if tools look up file locations from the protobuf, but I'm not + // exactly sure how that works. + dictionaryFakePath := fmt.Sprintf("out/target/common/obj/%s/%s_intermediates/proguard_dictionary", proguardInfo.Class, proguardInfo.ModuleName) + dictZipCmd.FlagWithArg("-e ", dictionaryFakePath) + dictZipCmd.FlagWithInput("-f ", proguardInfo.ProguardDictionary) + dictZipCmd.Textf("-e out/target/common/obj/%s/%s_intermediates/classes.jar", proguardInfo.Class, proguardInfo.ModuleName) + dictZipCmd.FlagWithInput("-f ", proguardInfo.ClassesJar) + + protoFile := protosDir.Join(ctx, filepath.Dir(dictionaryFakePath), "proguard_dictionary.textproto") + ctx.Build(pctx, android.BuildParams{ + Rule: proguardDictToProto, + Input: proguardInfo.ProguardDictionary, + Output: protoFile, + Args: map[string]string{ + "location": dictionaryFakePath, + }, + }) + dictMappingCmd.Input(protoFile) + + usageZipCmd.Input(proguardInfo.ProguardUsageZip) + } + } + + dictZipBuilder.Build("proguard_dict_zip", "Building proguard dictionary zip") + dictMappingBuilder.Build("proguard_dict_mapping_proto", "Building proguard mapping proto") + usageZipBuilder.Build("proguard_usage_zip", "Building proguard usage zip") + + return ProguardZips{ + DictZip: dictZip, + DictMapping: dictMapping, + UsageZip: usageZip, + } +} + type ProguardInfo struct { ModuleName string Class string |
