summaryrefslogtreecommitdiff
path: root/java/dex.go
diff options
context:
space:
mode:
Diffstat (limited to 'java/dex.go')
-rw-r--r--java/dex.go251
1 files changed, 192 insertions, 59 deletions
diff --git a/java/dex.go b/java/dex.go
index 7b99549d4..ed2df2103 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -49,10 +49,28 @@ type DexProperties struct {
// Whether to continue building even if warnings are emitted. Defaults to true.
Ignore_warnings *bool
+ // Whether runtime invisible annotations should be kept by R8. Defaults to false.
+ // This is equivalent to:
+ // -keepattributes RuntimeInvisibleAnnotations,
+ // RuntimeInvisibleParameterAnnotations,
+ // RuntimeInvisibleTypeAnnotations
+ // This is only applicable when RELEASE_R8_ONLY_RUNTIME_VISIBLE_ANNOTATIONS is
+ // enabled and will be used to migrate away from keeping runtime invisible
+ // annotations (b/387958004).
+ Keep_runtime_invisible_annotations *bool
+
// If true, runs R8 in Proguard compatibility mode, otherwise runs R8 in full mode.
// Defaults to false for apps and tests, true for libraries.
Proguard_compatibility *bool
+ // If true, R8 will not add public or protected members (fields or methods) to
+ // the API surface of the compilation unit, i.e., classes that are kept or
+ // have kept subclasses will not expose any members added by R8 for internal
+ // use. That includes renamed members if obfuscation is enabled.
+ // This should only be used for building targets that go on the bootclasspath.
+ // Defaults to false.
+ Protect_api_surface *bool
+
// If true, optimize for size by removing unused code. Defaults to true for apps,
// false for libraries and tests.
Shrink *bool
@@ -160,6 +178,71 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
},
}, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags"}, nil)
+// Include all of the args for d8r8, so that we can generate the partialcompileclean target's build using the same list.
+var d8r8Clean = pctx.AndroidStaticRule("d8r8-partialcompileclean",
+ blueprint.RuleParams{
+ Command: `rm -rf "${outDir}" "${outDict}" "${outConfig}" "${outUsage}" "${outUsageZip}" "${outUsageDir}" ` +
+ `"${resourcesOutput}" "${outR8ArtProfile}" ${builtOut}`,
+ }, "outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir", "builtOut",
+ "d8Flags", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile", "implicits",
+)
+
+var d8r8, d8r8RE = pctx.MultiCommandRemoteStaticRules("d8r8",
+ blueprint.RuleParams{
+ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ `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 && ` +
+ ` $d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in; ` +
+ `else ` +
+ ` $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 && ` +
+ `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar" `,
+ CommandDeps: []string{
+ "${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", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"})
+
var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -224,21 +307,29 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
deps = append(deps, f)
}
- var requestReleaseMode bool
+ var requestReleaseMode, requestDebugMode bool
requestReleaseMode, flags = android.RemoveFromList("--release", flags)
+ requestDebugMode, flags = android.RemoveFromList("--debug", flags)
if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" || ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
- flags = append(flags, "--debug")
+ requestDebugMode = true
requestReleaseMode = false
}
// Don't strip out debug information for eng builds, unless the target
// explicitly provided the `--release` build flag. This allows certain
// test targets to remain optimized as part of eng test_suites builds.
- if requestReleaseMode {
+ if requestDebugMode {
+ flags = append(flags, "--debug")
+ } else if requestReleaseMode {
flags = append(flags, "--release")
} else if ctx.Config().Eng() {
flags = append(flags, "--debug")
+ } else if !d.effectiveOptimizeEnabled() && d.dexProperties.Optimize.EnabledByDefault {
+ // D8 uses --debug by default, whereas R8 uses --release by default.
+ // For targets that default to R8 usage (e.g., apps), but override this default, we still
+ // want D8 to run in release mode, preserving semantics as much as possible between the two.
+ flags = append(flags, "--release")
}
// Supplying the platform build flag disables various features like API modeling and desugaring.
@@ -310,7 +401,7 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
// TODO(b/360905238): Remove SdkSystemServer exception after resolving missing class references.
if !dexParams.sdkVersion.Stable() || dexParams.sdkVersion.Kind == android.SdkSystemServer {
var proguardRaiseDeps classpath
- ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(proguardRaiseTag, func(m android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
}
@@ -344,6 +435,11 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
android.PathForSource(ctx, "build/make/core/proguard.flags"),
}
+ if ctx.Config().UseR8GlobalCheckNotNullFlags() {
+ flagFiles = append(flagFiles, android.PathForSource(ctx,
+ "build/make/core/proguard/checknotnull.flags"))
+ }
+
flagFiles = append(flagFiles, d.extraProguardFlagsFiles...)
// TODO(ccross): static android library proguard files
@@ -364,10 +460,18 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams,
r8Flags = append(r8Flags, "--ignore-library-extends-program")
}
- if BoolDefault(opt.Proguard_compatibility, true) {
+ if BoolDefault(opt.Keep_runtime_invisible_annotations, false) {
+ r8Flags = append(r8Flags, "--keep-runtime-invisible-annotations")
+ }
+
+ if BoolDefault(opt.Proguard_compatibility, !ctx.Config().UseR8FullModeByDefault()) {
r8Flags = append(r8Flags, "--force-proguard-compatibility")
}
+ if BoolDefault(opt.Protect_api_surface, false) {
+ r8Flags = append(r8Flags, "--protect-api-surface")
+ }
+
// 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 {
@@ -460,6 +564,7 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
+ cleanPhonyPath := android.PathForModuleOut(ctx, "dex", dexParams.jarName+"-partialcompileclean").OutputPath
outDir := android.PathForModuleOut(ctx, "dex")
zipFlags := "--ignore_missing_files"
@@ -476,7 +581,19 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
}
useR8 := d.effectiveOptimizeEnabled()
+ useD8 := !useR8 || ctx.Config().PartialCompileFlags().Use_d8
+ rbeR8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8")
+ rbeD8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8")
+ var rule blueprint.Rule
+ var description string
var artProfileOutputPath *android.OutputPath
+ var implicitOutputs android.WritablePaths
+ var deps android.Paths
+ args := map[string]string{
+ "zipFlags": zipFlags,
+ "outDir": outDir.String(),
+ "mergeZipsFlags": mergeZipsFlags,
+ }
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
@@ -489,83 +606,89 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
resourcesOutput := android.PathForModuleOut(ctx, "package-res-shrunken.apk")
d.resourcesOutput = android.OptionalPathForPath(resourcesOutput)
- implicitOutputs := android.WritablePaths{
+ implicitOutputs = append(implicitOutputs, android.WritablePaths{
proguardDictionary,
proguardUsageZip,
proguardConfiguration,
- }
+ }...)
+ description = "r8"
debugMode := android.InList("--debug", commonFlags)
r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode)
- rule := r8
- args := map[string]string{
- "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
- "zipFlags": zipFlags,
- "outDict": proguardDictionary.String(),
- "outConfig": proguardConfiguration.String(),
- "outUsageDir": proguardUsageDir.String(),
- "outUsage": proguardUsage.String(),
- "outUsageZip": proguardUsageZip.String(),
- "outDir": outDir.String(),
- "mergeZipsFlags": mergeZipsFlags,
- }
+ deps = append(deps, r8Deps...)
+ args["r8Flags"] = strings.Join(append(commonFlags, r8Flags...), " ")
if r8ArtProfileOutputPath != nil {
artProfileOutputPath = r8ArtProfileOutputPath
- implicitOutputs = append(
- implicitOutputs,
- artProfileOutputPath,
- )
// Add the implicit r8 Art profile output to args so that r8RE knows
// about this implicit output
- args["outR8ArtProfile"] = artProfileOutputPath.String()
- }
-
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") {
- rule = r8RE
- args["implicits"] = strings.Join(r8Deps.Strings(), ",")
+ args["outR8ArtProfile"] = r8ArtProfileOutputPath.String()
}
+ args["outDict"] = proguardDictionary.String()
+ args["outConfig"] = proguardConfiguration.String()
+ args["outUsageDir"] = proguardUsageDir.String()
+ args["outUsage"] = proguardUsage.String()
+ args["outUsageZip"] = proguardUsageZip.String()
if d.resourcesInput.Valid() {
implicitOutputs = append(implicitOutputs, resourcesOutput)
args["resourcesOutput"] = resourcesOutput.String()
}
- ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "r8",
- Output: javalibJar,
- ImplicitOutputs: implicitOutputs,
- Input: dexParams.classesJar,
- Implicits: r8Deps,
- Args: args,
- })
- } else {
- implicitOutputs := android.WritablePaths{}
+
+ rule = r8
+ if rbeR8 {
+ rule = r8RE
+ args["implicits"] = strings.Join(deps.Strings(), ",")
+ }
+ }
+ if useD8 {
+ description = "d8"
d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams)
+ deps = append(deps, d8Deps...)
+ deps = append(deps, commonDeps...)
+ args["d8Flags"] = strings.Join(append(commonFlags, d8Flags...), " ")
if d8ArtProfileOutputPath != nil {
artProfileOutputPath = d8ArtProfileOutputPath
- implicitOutputs = append(
- implicitOutputs,
- artProfileOutputPath,
- )
}
- d8Deps = append(d8Deps, commonDeps...)
- rule := d8
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
+ // If we are generating both d8 and r8, only use RBE when both are enabled.
+ switch {
+ case useR8 && rule == r8:
+ rule = d8r8
+ description = "d8r8"
+ case useR8 && rule == r8RE && rbeD8:
+ rule = d8r8RE
+ description = "d8r8"
+ case rbeD8:
rule = d8RE
+ default:
+ rule = d8
}
+ }
+ if artProfileOutputPath != nil {
+ implicitOutputs = append(
+ implicitOutputs,
+ artProfileOutputPath,
+ )
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: description,
+ Output: javalibJar,
+ ImplicitOutputs: implicitOutputs,
+ Input: dexParams.classesJar,
+ Implicits: deps,
+ Args: args,
+ })
+ if useR8 && useD8 {
+ // Generate the rule for partial compile clean.
+ args["builtOut"] = javalibJar.String()
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "d8",
- Output: javalibJar,
- Input: dexParams.classesJar,
- ImplicitOutputs: implicitOutputs,
- Implicits: d8Deps,
- Args: map[string]string{
- "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
- "zipFlags": zipFlags,
- "outDir": outDir.String(),
- "mergeZipsFlags": mergeZipsFlags,
- },
+ Rule: d8r8Clean,
+ Description: "d8r8Clean",
+ 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
TransformZipAlign(ctx, alignedJavalibJar, javalibJar, nil)
@@ -574,3 +697,13 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
return javalibJar, artProfileOutputPath
}
+
+type ProguardInfo struct {
+ ModuleName string
+ Class string
+ ProguardDictionary android.Path
+ ProguardUsageZip android.Path
+ ClassesJar android.Path
+}
+
+var ProguardProvider = blueprint.NewProvider[ProguardInfo]()