diff options
author | 2025-02-26 15:17:29 -0800 | |
---|---|---|
committer | 2025-02-26 15:17:29 -0800 | |
commit | e8d5d13b78ffe0db056f1329d87130c2068b75f7 (patch) | |
tree | 416b6d4e751df906d46d00964a044e72ef451c9f | |
parent | 44beed8ba6f9b2955281c44dae1078811a7c3a4e (diff) | |
parent | 3b536fff7c188ddbd3b1d4c3f9e8d6106d415c97 (diff) |
Merge "Build boot.zip in soong" into main
-rw-r--r-- | java/dexpreopt_bootjars.go | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 313d8c7a4..228704355 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -675,6 +675,139 @@ func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContex installs: artBootImageHostInstalls, }, ) + + d.buildBootZip(ctx) +} + +// Build the boot.zip which contains the boot jars and their compilation output +// We can do this only if preopt is enabled and if the product uses libart config (which sets the +// default properties for preopting). +// Origionally, this was only for ART Cloud. +func (d *dexpreoptBootJars) buildBootZip(ctx android.ModuleContext) { + image := d.defaultBootImage + if image == nil || SkipDexpreoptBootJars(ctx) { + return + } + global := dexpreopt.GetGlobalConfig(ctx) + globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) + if global.DisablePreopt || global.OnlyPreoptArtBootImage { + return + } + + bootclasspathDexFiles, bootclassPathLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp) + if len(bootclasspathDexFiles) == 0 { + return + } + + systemServerDexjarsDir := android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir) + + bootZipMetadataTmp := android.PathForModuleOut(ctx, "boot_zip", "METADATA.txt.tmp") + bootZipMetadata := android.PathForModuleOut(ctx, "boot_zip", "METADATA.txt") + newlineFile := android.PathForModuleOut(ctx, "boot_zip", "newline.txt") + android.WriteFileRule(ctx, newlineFile, "") + + dexPreoptRootDir := filepath.Dir(filepath.Dir(bootclasspathDexFiles[0].String())) + + var sb strings.Builder + sb.WriteString("bootclasspath = ") + for i, bootclasspathJar := range bootclasspathDexFiles { + if i > 0 { + sb.WriteString(":") + } + rel, err := filepath.Rel(dexPreoptRootDir, bootclasspathJar.String()) + if err != nil { + ctx.ModuleErrorf("All dexpreopt jars should be under the same rootdir %q, but %q wasn't.", dexPreoptRootDir, bootclasspathJar) + } else { + sb.WriteString(rel) + } + } + sb.WriteString("\nbootclasspath-locations = ") + for i, bootclasspathLocation := range bootclassPathLocations { + if i > 0 { + sb.WriteString(":") + } + sb.WriteString(bootclasspathLocation) + } + sb.WriteString("\nboot-image = ") + + // Infix can be 'art' (ART image for testing), 'boot' (primary), or 'mainline' (mainline + // extension). Soong creates a set of variables for Make, one or each boot image. The only + // reason why the ART image is exposed to Make is testing (art gtests) and benchmarking (art + // golem benchmarks). Install rules that use those variables are in dex_preopt_libart.mk. Here + // for dexpreopt purposes the infix is always 'boot' or 'mainline'. + dexpreoptInfix := "boot" + if global.PreoptWithUpdatableBcp { + dexpreoptInfix = "mainline" + } + + var dexPreoptImageZipBoot android.Path + var dexPreoptImageZipArt android.Path + var dexPreoptImageZipMainline android.Path + for _, current := range append(d.otherImages, image) { + if current.name == dexpreoptInfix { + _, imageLocationsOnDevice := current.getAnyAndroidVariant().imageLocations() + for i, location := range imageLocationsOnDevice { + imageLocationsOnDevice[i] = strings.TrimPrefix(location, "/") + } + sb.WriteString(strings.Join(imageLocationsOnDevice, ":")) + } + switch current.name { + case "boot": + dexPreoptImageZipBoot = current.zip + case "art": + dexPreoptImageZipArt = current.zip + case "mainline": + dexPreoptImageZipMainline = current.zip + } + } + sb.WriteString("\nextra-args = ") + android.WriteFileRuleVerbatim(ctx, bootZipMetadataTmp, sb.String()) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cat, + Inputs: []android.Path{ + bootZipMetadataTmp, + globalSoong.UffdGcFlag, + newlineFile, + }, + Output: bootZipMetadata, + }) + + bootZipFirstPart := android.PathForModuleOut(ctx, "boot_zip", "boot_first_part.zip") + bootZip := android.PathForModuleOut(ctx, "boot_zip", "boot.zip") + builder := android.NewRuleBuilder(pctx, ctx) + cmd := builder.Command().BuiltTool("soong_zip"). + FlagWithOutput("-o ", bootZipFirstPart). + FlagWithArg("-C ", filepath.Dir(filepath.Dir(bootclasspathDexFiles[0].String()))) + for _, bootclasspathJar := range bootclasspathDexFiles { + cmd.FlagWithInput("-f ", bootclasspathJar) + } + for i := range global.SystemServerJars.Len() { + // Use "/system" path for JARs with "platform:" prefix. These JARs counterintuitively use + // "platform" prefix but they will be actually installed to /system partition. + // For the remaining system server JARs use the partition signified by the prefix. + // For example, prefix "system_ext:" will use "/system_ext" path. + dir := global.SystemServerJars.Apex(i) + if dir == "platform" { + dir = "system" + } + jar := global.SystemServerJars.Jar(i) + ".jar" + cmd.FlagWithArg("-e ", dir+"/framework/"+jar) + cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar)) + } + cmd.Flag("-j") + cmd.FlagWithInput("-f ", bootZipMetadata) + + builder.Command().BuiltTool("merge_zips"). + Output(bootZip). + Input(bootZipFirstPart). + Input(dexPreoptImageZipBoot). + Input(dexPreoptImageZipArt). + Input(dexPreoptImageZipMainline) + + builder.Build("boot_zip", "build boot.zip") + + ctx.DistForGoal("droidcore", bootZipMetadata) + ctx.DistForGoal("droidcore", bootZip) } // GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make. |