diff --git a/apex/apex_test.go b/apex/apex_test.go index 08d82e90c..922e40a53 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -4546,7 +4546,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) { t.Helper() - s := ctx.SingletonForTests("dex_bootjars") + s := ctx.ModuleForTests("platform-bootclasspath", "android_common") foundLibfooJar := false base := stem + ".jar" for _, output := range s.AllOutputs() { diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index bed629da3..5b1be22c5 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -361,6 +361,15 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // Generate classpaths.proto config b.generateClasspathProtoBuildActions(ctx) + // Gather the bootclasspath fragment's contents. + var contents []android.Module + ctx.VisitDirectDeps(func(module android.Module) { + tag := ctx.OtherModuleDependencyTag(module) + if IsBootclasspathFragmentContentDepTag(tag) { + contents = append(contents, module) + } + }) + // Perform hidden API processing. b.generateHiddenAPIBuildActions(ctx) @@ -376,6 +385,9 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // GenerateSingletonBuildActions method as it cannot create it for itself. dexpreopt.GetGlobalSoongConfig(ctx) info.imageConfig = b.getImageConfig(ctx) + + // Only generate the boot image if the configuration does not skip it. + b.generateBootImageBuildActions(ctx, contents) } // Make it available for other modules. @@ -434,6 +446,40 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo) } +// generateBootImageBuildActions generates ninja rules to create the boot image if required for this +// module. +func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, contents []android.Module) { + global := dexpreopt.GetGlobalConfig(ctx) + if !shouldBuildBootImages(ctx.Config(), global) { + return + } + + // Bootclasspath fragment modules that are not preferred do not produce a boot image. + if !isActiveModule(ctx.Module()) { + return + } + + // Bootclasspath fragment modules that have no image_name property do not produce a boot image. + imageConfig := b.getImageConfig(ctx) + if imageConfig == nil { + return + } + + // Bootclasspath fragment modules that are for the platform do not produce a boot image. + apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) + if apexInfo.IsForPlatform() { + return + } + + // Bootclasspath fragment modules that are versioned do not produce a boot image. + if android.IsModuleInVersionedSdk(ctx.Module()) { + return + } + + // Copy the dex jars of this fragment's content modules to their predefined locations. + copyBootJarsToPredefinedLocations(ctx, contents, imageConfig.modules, imageConfig.dexPaths) +} + type bootclasspathFragmentMemberType struct { android.SdkMemberTypeBase } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index ce68c4856..0a324a9a0 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -436,8 +436,6 @@ func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonC // Create boot image for the ART apex (build artifacts are accessed via the global boot image config). d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx), profile)) - - copyUpdatableBootJars(ctx) } // shouldBuildBootImages determines whether boot images should be built. @@ -452,77 +450,19 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig return true } -// A copy of isModuleInConfiguredList created to work with singleton context. -// -// TODO(b/177892522): Remove this. -func isModuleInConfiguredListForSingleton(ctx android.SingletonContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool { - name := ctx.ModuleName(module) - - // Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed. - name = android.RemoveOptionalPrebuiltPrefix(name) - - // Ignore any module that is not listed in the boot image configuration. - index := configuredBootJars.IndexOfJar(name) - if index == -1 { - return false - } - - // It is an error if the module is not an ApexModule. - if _, ok := module.(android.ApexModule); !ok { - ctx.Errorf("%s is configured in boot jars but does not support being added to an apex", ctx.ModuleName(module)) - return false - } - - apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) - - // Now match the apex part of the boot image configuration. - requiredApex := configuredBootJars.Apex(index) - if requiredApex == "platform" || requiredApex == "system_ext" { - if len(apexInfo.InApexes) != 0 { - // A platform variant is required but this is for an apex so ignore it. - return false - } - } else if !apexInfo.InApexByBaseName(requiredApex) { - // An apex variant for a specific apex is required but this is the wrong apex. - return false - } - - return true -} - -// findBootJarModules finds the boot jar module variants specified in the bootjars parameter. -// -// It returns a list of modules such that the module at index i corresponds to the configured jar -// at index i. -func findBootJarModules(ctx android.SingletonContext, bootjars android.ConfiguredJarList) []android.Module { - modules := make([]android.Module, bootjars.Len()) - - // This logic is tested in the apex package to avoid import cycle apex <-> java. - ctx.VisitAllModules(func(module android.Module) { - if !isActiveModule(module) || !isModuleInConfiguredListForSingleton(ctx, module, bootjars) { - return - } - - name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module)) - index := bootjars.IndexOfJar(name) - if existing := modules[index]; existing != nil { - ctx.Errorf("Multiple boot jar modules found for %s:%s - %q and %q", - bootjars.Apex(index), bootjars.Jar(index), existing, module) - return - } - modules[index] = module - }) - return modules -} - // copyBootJarsToPredefinedLocations generates commands that will copy boot jars to // predefined paths in the global config. -func copyBootJarsToPredefinedLocations(ctx android.SingletonContext, bootModules []android.Module, bootjars android.ConfiguredJarList, jarPathsPredefined android.WritablePaths) { +func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, bootModules []android.Module, bootjars android.ConfiguredJarList, jarPathsPredefined android.WritablePaths) { jarPaths := make(android.Paths, bootjars.Len()) for i, module := range bootModules { if module != nil { bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath() jarPaths[i] = bootDexJar + + name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(module)) + if bootjars.Jar(i) != name { + ctx.ModuleErrorf("expected module %s at position %d but found %s", bootjars.Jar(i), i, name) + } } } @@ -548,7 +488,7 @@ func copyBootJarsToPredefinedLocations(ctx android.SingletonContext, bootModules }, }) } else { - ctx.Errorf("failed to find a dex jar path for module '%s'"+ + ctx.ModuleErrorf("failed to find a dex jar path for module '%s'"+ ", note that some jars may be filtered out by module constraints", module) } @@ -564,9 +504,6 @@ func copyBootJarsToPredefinedLocations(ctx android.SingletonContext, bootModules // buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image. func buildBootImage(ctx android.SingletonContext, image *bootImageConfig, profile android.WritablePath) *bootImageConfig { - bootModules := findBootJarModules(ctx, image.modules) - copyBootJarsToPredefinedLocations(ctx, bootModules, image.modules, image.dexPaths) - var zipFiles android.Paths for _, variant := range image.variants { files := buildBootImageVariant(ctx, variant, profile) @@ -589,13 +526,6 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig, profil return image } -// Generate commands that will copy updatable boot jars to predefined paths in the global config. -func copyUpdatableBootJars(ctx android.SingletonContext) { - config := GetUpdatableBootConfig(ctx) - bootModules := findBootJarModules(ctx, config.modules) - copyBootJarsToPredefinedLocations(ctx, bootModules, config.modules, config.dexPaths) -} - // Generate boot image build rules for a specific target. func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant, profile android.Path) android.WritablePaths { diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index f6af50132..676a0e722 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -151,9 +151,7 @@ func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) // Checks to see whether the supplied module variant is in the list of boot jars. // -// Apart from the context this is identical to isModuleInConfiguredListForSingleton. -// -// TODO(b/179354495): Avoid having to perform this type of check or if necessary dedup it. +// TODO(b/179354495): Avoid having to perform this type of check. func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool { name := ctx.OtherModuleName(module) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index c787e4797..eccea6172 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -196,7 +196,7 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo return } - b.generateBootImageBuildActions(ctx, updatableModules) + b.generateBootImageBuildActions(ctx, nonUpdatableModules, updatableModules) } // Generate classpaths.proto config @@ -430,7 +430,7 @@ func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.Make } // generateBootImageBuildActions generates ninja rules related to the boot image creation. -func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext, updatableModules []android.Module) { +func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext, nonUpdatableModules, updatableModules []android.Module) { // 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) @@ -451,5 +451,12 @@ func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android. // Generate the updatable bootclasspath packages rule. generateUpdatableBcpPackagesRule(ctx, imageConfig, updatableModules) + // Copy non-updatable module dex jars to their predefined locations. + copyBootJarsToPredefinedLocations(ctx, nonUpdatableModules, imageConfig.modules, imageConfig.dexPaths) + + // Copy updatable module dex jars to their predefined locations. + config := GetUpdatableBootConfig(ctx) + copyBootJarsToPredefinedLocations(ctx, updatableModules, config.modules, config.dexPaths) + dumpOatRules(ctx, imageConfig) }