Refactor dexpreopt for boot jars to make it flexible to config changes.
In the past, dexpreopt for boot jars was very inflexible, and it was
incredibly hard to make a change that is as simple as adding a jar to a
boot image. Boot image generation was handled by
"platform_bootclasspath" and "bootclasspath_fragment" separately. This
caused not only code duplication but also the inflexiblity as such a
design did not fit today's use cases, where a boot image may take jars
from multiple mainline modules and the platform, and a mainline module
can contribute to multiple boot images. The design casued a huge
maintenance burden as any change to the boot image cost multi-week
efforts.
In recent years, efforts have been made to improve this a bit by a bit.
This change is another step towards making dexpreopt reasonable.
After this change, all boot images are generated by "dex_bootjars",
which is in build/soong and is therefore available on both the full
source tree and the thin manifest (master-art). The change decouples
profile generation/extraction from boot image generation. Profiles for
mainline modules are still handled by "bootclasspath_fragment"
because they need to be packed into APEXes when building mainline
modules and extracted from APEXes whem building the system image from
prebuilt modules. Boot images are not handled by
"bootclasspath_fragment" anymore.
Bug: 290583827
Test: m (all existing tests are still passing)
Test: Manually checked that the boot images are exactly the same as
before.
Change-Id: Ib5a5f401bee334ffcab5c26618e0c8888b84575a
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 0d4db7c..a4bba48 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -123,15 +123,15 @@
}
func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
- // Add dependencies on all the modules configured in the "art" boot image.
- artImageConfig := genBootImageConfigs(ctx)[artBootImageName]
- addDependenciesOntoBootImageModules(ctx, artImageConfig.modules, platformBootclasspathArtBootJarDepTag)
+ // Add dependencies on all the ART jars.
+ global := dexpreopt.GetGlobalConfig(ctx)
+ addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
- // Add dependencies on all the non-updatable module configured in the "boot" boot image. That does
- // not include modules configured in the "art" boot image.
+ // Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
+ // APEXes.
addDependenciesOntoBootImageModules(ctx, b.platformJars(ctx), platformBootclasspathBootJarDepTag)
- // Add dependencies on all the apex jars.
+ // Add dependencies on all the updatable jars, except the ART jars.
apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
@@ -186,7 +186,6 @@
bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
- b.generateBootImageBuildActions(ctx)
b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
}
@@ -218,7 +217,8 @@
}
func (b *platformBootclasspathModule) platformJars(ctx android.PathContext) android.ConfiguredJarList {
- return defaultBootImageConfig(ctx).modules.RemoveList(artBootImageConfig(ctx).modules)
+ global := dexpreopt.GetGlobalConfig(ctx)
+ return global.BootJars.RemoveList(global.ArtApexJars)
}
// checkPlatformModules ensures that the non-updatable modules supplied are not part of an
@@ -399,78 +399,9 @@
ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", b.hiddenAPIFlagsCSV.String())
}
-// generateBootImageBuildActions generates ninja rules related to the boot image creation.
-func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext) {
- // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
- // GenerateSingletonBuildActions method as it cannot create it for itself.
- dexpreopt.GetGlobalSoongConfig(ctx)
-
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- return
- }
-
- frameworkBootImageConfig := defaultBootImageConfig(ctx)
- bootFrameworkProfileRule(ctx, frameworkBootImageConfig)
- b.generateBootImage(ctx, frameworkBootImageName)
- b.generateBootImage(ctx, mainlineBootImageName)
- dumpOatRules(ctx, frameworkBootImageConfig)
-}
-
-func (b *platformBootclasspathModule) generateBootImage(ctx android.ModuleContext, imageName string) {
- imageConfig := genBootImageConfigs(ctx)[imageName]
-
- modules := b.getModulesForImage(ctx, imageConfig)
-
- // Copy module dex jars to their predefined locations.
- bootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, modules)
- copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule)
-
- // Build a profile for the image config and then use that to build the boot image.
- profile := bootImageProfileRule(ctx, imageConfig)
-
- // If dexpreopt of boot image jars should be skipped, generate only a profile.
- global := dexpreopt.GetGlobalConfig(ctx)
- if global.DisablePreoptBootImages {
- return
- }
-
- // Build boot image files for the android variants.
- androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-
- // Zip the android variant boot image files up.
- buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
-
- // Build boot image files for the host variants. There are use directly by ART host side tests.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-}
-
// Copy apex module dex jars to their predefined locations. They will be used for dexpreopt for apps.
func (b *platformBootclasspathModule) copyApexBootJarsForAppsDexpreopt(ctx android.ModuleContext, apexModules []android.Module) {
config := GetApexBootConfig(ctx)
apexBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, apexModules)
copyBootJarsToPredefinedLocations(ctx, apexBootDexJarsByModule, config.dexPathsByModule)
}
-
-func (b *platformBootclasspathModule) getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []android.Module {
- modules := make([]android.Module, 0, imageConfig.modules.Len())
- for i := 0; i < imageConfig.modules.Len(); i++ {
- found := false
- for _, module := range b.configuredModules {
- name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- if name == imageConfig.modules.Jar(i) {
- modules = append(modules, module)
- found = true
- break
- }
- }
- if !found && !ctx.Config().AllowMissingDependencies() {
- ctx.ModuleErrorf(
- "Boot image '%s' module '%s' not added as a dependency of platform_bootclasspath",
- imageConfig.name,
- imageConfig.modules.Jar(i))
- return []android.Module{}
- }
- }
- return modules
-}