xref: /aosp_15_r20/build/soong/java/dex.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18	"strconv"
19	"strings"
20
21	"github.com/google/blueprint"
22	"github.com/google/blueprint/proptools"
23
24	"android/soong/android"
25	"android/soong/remoteexec"
26)
27
28type DexProperties struct {
29	// If set to true, compile dex regardless of installable.  Defaults to false.
30	Compile_dex *bool
31
32	// list of module-specific flags that will be used for dex compiles
33	Dxflags []string `android:"arch_variant"`
34
35	// A list of files containing rules that specify the classes to keep in the main dex file.
36	Main_dex_rules []string `android:"path"`
37
38	Optimize struct {
39		// If false, disable all optimization.  Defaults to true for android_app and
40		// android_test_helper_app modules, false for android_test, java_library, and java_test modules.
41		Enabled *bool
42		// True if the module containing this has it set by default.
43		EnabledByDefault bool `blueprint:"mutated"`
44
45		// Whether to continue building even if warnings are emitted.  Defaults to true.
46		Ignore_warnings *bool
47
48		// If true, runs R8 in Proguard compatibility mode, otherwise runs R8 in full mode.
49		// Defaults to false for apps, true for libraries and tests.
50		Proguard_compatibility *bool
51
52		// If true, optimize for size by removing unused code.  Defaults to true for apps,
53		// false for libraries and tests.
54		Shrink *bool
55
56		// If true, optimize bytecode.  Defaults to false.
57		Optimize *bool
58
59		// If true, obfuscate bytecode.  Defaults to false.
60		Obfuscate *bool
61
62		// If true, do not use the flag files generated by aapt that automatically keep
63		// classes referenced by the app manifest.  Defaults to false.
64		No_aapt_flags *bool
65
66		// If true, optimize for size by removing unused resources. Defaults to false.
67		Shrink_resources *bool
68
69		// If true, use optimized resource shrinking in R8, overriding the
70		// Shrink_resources setting. Defaults to false.
71		// Optimized shrinking means that R8 will trace and treeshake resources together with code
72		// and apply additional optimizations. This implies non final fields in the R classes.
73		Optimized_shrink_resources *bool
74
75		// Flags to pass to proguard.
76		Proguard_flags []string
77
78		// Specifies the locations of files containing proguard flags.
79		Proguard_flags_files []string `android:"path"`
80
81		// If true, transitive reverse dependencies of this module will have this
82		// module's proguard spec appended to their optimization action
83		Export_proguard_flags_files *bool
84	}
85
86	// Keep the data uncompressed. We always need uncompressed dex for execution,
87	// so this might actually save space by avoiding storing the same data twice.
88	// This defaults to reasonable value based on module and should not be set.
89	// It exists only to support ART tests.
90	Uncompress_dex *bool
91
92	// Exclude kotlinc generate files: *.kotlin_module, *.kotlin_builtins. Defaults to false.
93	Exclude_kotlinc_generated_files *bool
94
95	// Disable dex container (also known as "multi-dex").
96	// This may be necessary as a temporary workaround to mask toolchain bugs (see b/341652226).
97	No_dex_container *bool
98}
99
100type dexer struct {
101	dexProperties DexProperties
102
103	// list of extra proguard flag files
104	extraProguardFlagsFiles android.Paths
105	proguardDictionary      android.OptionalPath
106	proguardConfiguration   android.OptionalPath
107	proguardUsageZip        android.OptionalPath
108	resourcesInput          android.OptionalPath
109	resourcesOutput         android.OptionalPath
110
111	providesTransitiveHeaderJarsForR8
112}
113
114func (d *dexer) effectiveOptimizeEnabled() bool {
115	return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
116}
117
118func (d *DexProperties) resourceShrinkingEnabled(ctx android.ModuleContext) bool {
119	return !ctx.Config().Eng() && BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
120}
121
122func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool {
123	return d.resourceShrinkingEnabled(ctx) && BoolDefault(d.Optimize.Optimized_shrink_resources, ctx.Config().UseOptimizedResourceShrinkingByDefault())
124}
125
126func (d *dexer) optimizeOrObfuscateEnabled() bool {
127	return d.effectiveOptimizeEnabled() && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate))
128}
129
130var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
131	blueprint.RuleParams{
132		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
133			`$d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in && ` +
134			`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
135			`${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
136			`rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`,
137		CommandDeps: []string{
138			"${config.D8Cmd}",
139			"${config.SoongZipCmd}",
140			"${config.MergeZipsCmd}",
141		},
142	}, map[string]*remoteexec.REParams{
143		"$d8Template": &remoteexec.REParams{
144			Labels:          map[string]string{"type": "compile", "compiler": "d8"},
145			Inputs:          []string{"${config.D8Jar}"},
146			ExecStrategy:    "${config.RED8ExecStrategy}",
147			ToolchainInputs: []string{"${config.JavaCmd}"},
148			Platform:        map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
149		},
150		"$zipTemplate": &remoteexec.REParams{
151			Labels:       map[string]string{"type": "tool", "name": "soong_zip"},
152			Inputs:       []string{"${config.SoongZipCmd}", "$outDir"},
153			OutputFiles:  []string{"$outDir/classes.dex.jar"},
154			ExecStrategy: "${config.RED8ExecStrategy}",
155			Platform:     map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
156		},
157	}, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags"}, nil)
158
159var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
160	blueprint.RuleParams{
161		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
162			`rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` +
163			`mkdir -p $$(dirname ${outUsage}) && ` +
164			`$r8Template${config.R8Cmd} ${config.R8Flags} $r8Flags -injars $in --output $outDir ` +
165			`--no-data-resources ` +
166			`-printmapping ${outDict} ` +
167			`-printconfiguration ${outConfig} ` +
168			`-printusage ${outUsage} ` +
169			`--deps-file ${out}.d && ` +
170			`touch "${outDict}" "${outConfig}" "${outUsage}" && ` +
171			`${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
172			`rm -rf ${outUsageDir} && ` +
173			`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
174			`${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
175			`rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`,
176		Depfile: "${out}.d",
177		Deps:    blueprint.DepsGCC,
178		CommandDeps: []string{
179			"${config.R8Cmd}",
180			"${config.SoongZipCmd}",
181			"${config.MergeZipsCmd}",
182		},
183	}, map[string]*remoteexec.REParams{
184		"$r8Template": &remoteexec.REParams{
185			Labels:          map[string]string{"type": "compile", "compiler": "r8"},
186			Inputs:          []string{"$implicits", "${config.R8Jar}"},
187			OutputFiles:     []string{"${outUsage}", "${outConfig}", "${outDict}", "${resourcesOutput}", "${outR8ArtProfile}"},
188			ExecStrategy:    "${config.RER8ExecStrategy}",
189			ToolchainInputs: []string{"${config.JavaCmd}"},
190			Platform:        map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
191		},
192		"$zipTemplate": &remoteexec.REParams{
193			Labels:       map[string]string{"type": "tool", "name": "soong_zip"},
194			Inputs:       []string{"${config.SoongZipCmd}", "$outDir"},
195			OutputFiles:  []string{"$outDir/classes.dex.jar"},
196			ExecStrategy: "${config.RER8ExecStrategy}",
197			Platform:     map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
198		},
199		"$zipUsageTemplate": &remoteexec.REParams{
200			Labels:       map[string]string{"type": "tool", "name": "soong_zip"},
201			Inputs:       []string{"${config.SoongZipCmd}", "${outUsage}"},
202			OutputFiles:  []string{"${outUsageZip}"},
203			ExecStrategy: "${config.RER8ExecStrategy}",
204			Platform:     map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
205		},
206	}, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir",
207		"r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"})
208
209func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
210	dexParams *compileDexParams) (flags []string, deps android.Paths) {
211
212	flags = d.dexProperties.Dxflags
213	// Translate all the DX flags to D8 ones until all the build files have been migrated
214	// to D8 flags. See: b/69377755
215	flags = android.RemoveListFromList(flags,
216		[]string{"--core-library", "--dex", "--multi-dex"})
217
218	for _, f := range android.PathsForModuleSrc(ctx, d.dexProperties.Main_dex_rules) {
219		flags = append(flags, "--main-dex-rules", f.String())
220		deps = append(deps, f)
221	}
222
223	var requestReleaseMode bool
224	requestReleaseMode, flags = android.RemoveFromList("--release", flags)
225
226	if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" || ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
227		flags = append(flags, "--debug")
228		requestReleaseMode = false
229	}
230
231	// Don't strip out debug information for eng builds, unless the target
232	// explicitly provided the `--release` build flag. This allows certain
233	// test targets to remain optimized as part of eng test_suites builds.
234	if requestReleaseMode {
235		flags = append(flags, "--release")
236	} else if ctx.Config().Eng() {
237		flags = append(flags, "--debug")
238	}
239
240	// Supplying the platform build flag disables various features like API modeling and desugaring.
241	// For targets with a stable min SDK version (i.e., when the min SDK is both explicitly specified
242	// and managed+versioned), we suppress this flag to ensure portability.
243	// Note: Targets with a min SDK kind of core_platform (e.g., framework.jar) or unspecified (e.g.,
244	// services.jar), are not classified as stable, which is WAI.
245	// TODO(b/232073181): Expand to additional min SDK cases after validation.
246	var addAndroidPlatformBuildFlag = false
247	if !dexParams.sdkVersion.Stable() {
248		addAndroidPlatformBuildFlag = true
249	}
250
251	effectiveVersion, err := dexParams.minSdkVersion.EffectiveVersion(ctx)
252	if err != nil {
253		ctx.PropertyErrorf("min_sdk_version", "%s", err)
254	}
255	if !Bool(d.dexProperties.No_dex_container) && effectiveVersion.FinalOrFutureInt() >= 36 && ctx.Config().UseDexV41() {
256		// W is 36, but we have not bumped the SDK version yet, so check for both.
257		if ctx.Config().PlatformSdkVersion().FinalInt() >= 36 ||
258			ctx.Config().PlatformSdkCodename() == "Baklava" {
259			flags = append([]string{"-JDcom.android.tools.r8.dexContainerExperiment"}, flags...)
260		}
261	}
262
263	// If the specified SDK level is 10000, then configure the compiler to use the
264	// current platform SDK level and to compile the build as a platform build.
265	var minApiFlagValue = effectiveVersion.FinalOrFutureInt()
266	if minApiFlagValue == 10000 {
267		minApiFlagValue = ctx.Config().PlatformSdkVersion().FinalInt()
268		addAndroidPlatformBuildFlag = true
269	}
270	flags = append(flags, "--min-api "+strconv.Itoa(minApiFlagValue))
271
272	if addAndroidPlatformBuildFlag {
273		flags = append(flags, "--android-platform-build")
274	}
275	return flags, deps
276}
277
278func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) {
279	flags := dexParams.flags
280	d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
281	d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...)
282
283	d8Deps = append(d8Deps, flags.bootClasspath...)
284	d8Deps = append(d8Deps, flags.dexClasspath...)
285
286	if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
287		d8Flags = append(d8Flags, flags...)
288		d8Deps = append(d8Deps, deps...)
289		artProfileOutput = profileOutput
290	}
291
292	return d8Flags, d8Deps, artProfileOutput
293}
294
295func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, debugMode bool) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) {
296	flags := dexParams.flags
297	opt := d.dexProperties.Optimize
298
299	// When an app contains references to APIs that are not in the SDK specified by
300	// its LOCAL_SDK_VERSION for example added by support library or by runtime
301	// classes added by desugaring, we artifically raise the "SDK version" "linked" by
302	// ProGuard, to
303	// - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version.
304	// - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version.
305	// See b/20667396
306	// TODO(b/360905238): Remove SdkSystemServer exception after resolving missing class references.
307	if !dexParams.sdkVersion.Stable() || dexParams.sdkVersion.Kind == android.SdkSystemServer {
308		var proguardRaiseDeps classpath
309		ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
310			if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
311				proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
312			}
313		})
314		r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
315		r8Deps = append(r8Deps, proguardRaiseDeps...)
316	}
317
318	r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
319	r8Deps = append(r8Deps, flags.bootClasspath...)
320	r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
321	r8Deps = append(r8Deps, flags.dexClasspath...)
322
323	transitiveStaticLibsLookupMap := map[android.Path]bool{}
324	for _, jar := range d.transitiveStaticLibsHeaderJarsForR8.ToList() {
325		transitiveStaticLibsLookupMap[jar] = true
326	}
327	transitiveHeaderJars := android.Paths{}
328	for _, jar := range d.transitiveLibsHeaderJarsForR8.ToList() {
329		if _, ok := transitiveStaticLibsLookupMap[jar]; ok {
330			// don't include a lib if it is already packaged in the current JAR as a static lib
331			continue
332		}
333		transitiveHeaderJars = append(transitiveHeaderJars, jar)
334	}
335	transitiveClasspath := classpath(transitiveHeaderJars)
336	r8Flags = append(r8Flags, transitiveClasspath.FormJavaClassPath("-libraryjars"))
337	r8Deps = append(r8Deps, transitiveClasspath...)
338
339	flagFiles := android.Paths{
340		android.PathForSource(ctx, "build/make/core/proguard.flags"),
341	}
342
343	flagFiles = append(flagFiles, d.extraProguardFlagsFiles...)
344	// TODO(ccross): static android library proguard files
345
346	flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...)
347
348	flagFiles = android.FirstUniquePaths(flagFiles)
349
350	r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
351	r8Deps = append(r8Deps, flagFiles...)
352
353	// TODO(b/70942988): This is included from build/make/core/proguard.flags
354	r8Deps = append(r8Deps, android.PathForSource(ctx,
355		"build/make/core/proguard_basic_keeps.flags"))
356
357	r8Flags = append(r8Flags, opt.Proguard_flags...)
358
359	if BoolDefault(opt.Proguard_compatibility, true) {
360		r8Flags = append(r8Flags, "--force-proguard-compatibility")
361	}
362
363	// Avoid unnecessary stack frame noise by only injecting source map ids for non-debug
364	// optimized or obfuscated targets.
365	if (Bool(opt.Optimize) || Bool(opt.Obfuscate)) && !debugMode {
366		// TODO(b/213833843): Allow configuration of the prefix via a build variable.
367		var sourceFilePrefix = "go/retraceme "
368		var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\""
369		r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
370		r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
371	}
372
373	// TODO(ccross): Don't shrink app instrumentation tests by default.
374	if !Bool(opt.Shrink) {
375		r8Flags = append(r8Flags, "-dontshrink")
376	}
377
378	if !Bool(opt.Optimize) {
379		r8Flags = append(r8Flags, "-dontoptimize")
380	}
381
382	// TODO(ccross): error if obufscation + app instrumentation test.
383	if !Bool(opt.Obfuscate) {
384		r8Flags = append(r8Flags, "-dontobfuscate")
385	}
386	// TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
387	// dictionary of the app and move the app from libraryjars to injars.
388
389	// TODO(b/180878971): missing classes should be added to the relevant builds.
390	// TODO(b/229727645): do not use true as default for Android platform builds.
391	if proptools.BoolDefault(opt.Ignore_warnings, true) {
392		r8Flags = append(r8Flags, "-ignorewarnings")
393	}
394
395	// resourcesInput is empty when we don't use resource shrinking, if on, pass these to R8
396	if d.resourcesInput.Valid() {
397		r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
398		r8Deps = append(r8Deps, d.resourcesInput.Path())
399		r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
400		if d.dexProperties.optimizedResourceShrinkingEnabled(ctx) {
401			r8Flags = append(r8Flags, "--optimized-resource-shrinking")
402			if Bool(d.dexProperties.Optimize.Optimized_shrink_resources) {
403				// Explicitly opted into optimized shrinking, no need for keeping R$id entries
404				r8Flags = append(r8Flags, "--force-optimized-resource-shrinking")
405			}
406		}
407	}
408
409	if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
410		r8Flags = append(r8Flags, flags...)
411		r8Deps = append(r8Deps, deps...)
412		artProfileOutput = profileOutput
413	}
414
415	return r8Flags, r8Deps, artProfileOutput
416}
417
418type compileDexParams struct {
419	flags           javaBuilderFlags
420	sdkVersion      android.SdkSpec
421	minSdkVersion   android.ApiLevel
422	classesJar      android.Path
423	jarName         string
424	artProfileInput *string
425}
426
427// Adds --art-profile to r8/d8 command.
428// r8/d8 will output a generated profile file to match the optimized dex code.
429func (d *dexer) addArtProfile(ctx android.ModuleContext, dexParams *compileDexParams) (flags []string, deps android.Paths, artProfileOutputPath *android.OutputPath) {
430	if dexParams.artProfileInput == nil {
431		return nil, nil, nil
432	}
433	artProfileInputPath := android.PathForModuleSrc(ctx, *dexParams.artProfileInput)
434	artProfileOutputPathValue := android.PathForModuleOut(ctx, "profile.prof.txt").OutputPath
435	artProfileOutputPath = &artProfileOutputPathValue
436	flags = []string{
437		"--art-profile",
438		artProfileInputPath.String(),
439		artProfileOutputPath.String(),
440	}
441	deps = append(deps, artProfileInputPath)
442	return flags, deps, artProfileOutputPath
443
444}
445
446// Return the compiled dex jar and (optional) profile _after_ r8 optimization
447func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) (android.Path, android.Path) {
448
449	// Compile classes.jar into classes.dex and then javalib.jar
450	javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
451	outDir := android.PathForModuleOut(ctx, "dex")
452
453	zipFlags := "--ignore_missing_files"
454	if proptools.Bool(d.dexProperties.Uncompress_dex) {
455		zipFlags += " -L 0"
456	}
457
458	commonFlags, commonDeps := d.dexCommonFlags(ctx, dexParams)
459
460	// Exclude kotlinc generated files when "exclude_kotlinc_generated_files" is set to true.
461	mergeZipsFlags := ""
462	if proptools.BoolDefault(d.dexProperties.Exclude_kotlinc_generated_files, false) {
463		mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins"
464	}
465
466	useR8 := d.effectiveOptimizeEnabled()
467	var artProfileOutputPath *android.OutputPath
468	if useR8 {
469		proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
470		d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
471		proguardConfiguration := android.PathForModuleOut(ctx, "proguard_configuration")
472		d.proguardConfiguration = android.OptionalPathForPath(proguardConfiguration)
473		proguardUsageDir := android.PathForModuleOut(ctx, "proguard_usage")
474		proguardUsage := proguardUsageDir.Join(ctx, ctx.Namespace().Path,
475			android.ModuleNameWithPossibleOverride(ctx), "unused.txt")
476		proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip")
477		d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
478		resourcesOutput := android.PathForModuleOut(ctx, "package-res-shrunken.apk")
479		d.resourcesOutput = android.OptionalPathForPath(resourcesOutput)
480		implicitOutputs := android.WritablePaths{
481			proguardDictionary,
482			proguardUsageZip,
483			proguardConfiguration,
484		}
485		debugMode := android.InList("--debug", commonFlags)
486		r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode)
487		rule := r8
488		args := map[string]string{
489			"r8Flags":        strings.Join(append(commonFlags, r8Flags...), " "),
490			"zipFlags":       zipFlags,
491			"outDict":        proguardDictionary.String(),
492			"outConfig":      proguardConfiguration.String(),
493			"outUsageDir":    proguardUsageDir.String(),
494			"outUsage":       proguardUsage.String(),
495			"outUsageZip":    proguardUsageZip.String(),
496			"outDir":         outDir.String(),
497			"mergeZipsFlags": mergeZipsFlags,
498		}
499		if r8ArtProfileOutputPath != nil {
500			artProfileOutputPath = r8ArtProfileOutputPath
501			implicitOutputs = append(
502				implicitOutputs,
503				artProfileOutputPath,
504			)
505			// Add the implicit r8 Art profile output to args so that r8RE knows
506			// about this implicit output
507			args["outR8ArtProfile"] = artProfileOutputPath.String()
508		}
509
510		if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") {
511			rule = r8RE
512			args["implicits"] = strings.Join(r8Deps.Strings(), ",")
513		}
514		if d.resourcesInput.Valid() {
515			implicitOutputs = append(implicitOutputs, resourcesOutput)
516			args["resourcesOutput"] = resourcesOutput.String()
517		}
518		ctx.Build(pctx, android.BuildParams{
519			Rule:            rule,
520			Description:     "r8",
521			Output:          javalibJar,
522			ImplicitOutputs: implicitOutputs,
523			Input:           dexParams.classesJar,
524			Implicits:       r8Deps,
525			Args:            args,
526		})
527	} else {
528		implicitOutputs := android.WritablePaths{}
529		d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams)
530		if d8ArtProfileOutputPath != nil {
531			artProfileOutputPath = d8ArtProfileOutputPath
532			implicitOutputs = append(
533				implicitOutputs,
534				artProfileOutputPath,
535			)
536		}
537		d8Deps = append(d8Deps, commonDeps...)
538		rule := d8
539		if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
540			rule = d8RE
541		}
542		ctx.Build(pctx, android.BuildParams{
543			Rule:            rule,
544			Description:     "d8",
545			Output:          javalibJar,
546			Input:           dexParams.classesJar,
547			ImplicitOutputs: implicitOutputs,
548			Implicits:       d8Deps,
549			Args: map[string]string{
550				"d8Flags":        strings.Join(append(commonFlags, d8Flags...), " "),
551				"zipFlags":       zipFlags,
552				"outDir":         outDir.String(),
553				"mergeZipsFlags": mergeZipsFlags,
554			},
555		})
556	}
557	if proptools.Bool(d.dexProperties.Uncompress_dex) {
558		alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath
559		TransformZipAlign(ctx, alignedJavalibJar, javalibJar, nil)
560		javalibJar = alignedJavalibJar
561	}
562
563	return javalibJar, artProfileOutputPath
564}
565