diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index 7be8477df..4b95f516b 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -315,7 +315,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { // Make sure that the source bootclasspath_fragment copies its dex files to the predefined // locations for the art image. - module := result.ModuleForTests("art-bootclasspath-fragment", "android_common_apex10000") + module := result.ModuleForTests("dex_bootjars", "android_common") checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo") }) @@ -386,7 +386,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { // Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined // locations for the art image. - module := result.ModuleForTests("prebuilt_art-bootclasspath-fragment", "android_common_com.android.art") + module := result.ModuleForTests("dex_bootjars", "android_common") checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo") }) @@ -537,7 +537,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { `prebuilt_foo`, }) - module := result.ModuleForTests("art-bootclasspath-fragment", "android_common_com.android.art") + module := result.ModuleForTests("dex_bootjars", "android_common") checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo") }) diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go index ff8f912b9..2e828cade 100644 --- a/apex/dexpreopt_bootjars_test.go +++ b/apex/dexpreopt_bootjars_test.go @@ -138,8 +138,8 @@ func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOu prepareForTestWithArtApex, ).RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt)) - platformBootclasspath := result.ModuleForTests("platform-bootclasspath", "android_common") - rule := platformBootclasspath.Output(ruleFile) + dexBootJars := result.ModuleForTests("dex_bootjars", "android_common") + rule := dexBootJars.Output(ruleFile) inputs := rule.Implicits.Strings() sort.Strings(inputs) @@ -162,8 +162,8 @@ func TestDexpreoptBootJarsWithSourceArtApex(t *testing.T) { "out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar", "out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar", "out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar", - "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art/boot.prof", - "out/soong/.intermediates/platform-bootclasspath/android_common/boot/boot.prof", + "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof", + "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof", } expectedOutputs := []string{ @@ -200,7 +200,7 @@ func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) { "out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar", "out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar", "out/soong/.intermediates/com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof", - "out/soong/.intermediates/platform-bootclasspath/android_common/boot/boot.prof", + "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof", } expectedOutputs := []string{ diff --git a/java/bootclasspath.go b/java/bootclasspath.go index 29eed795d..c7dc3afae 100644 --- a/java/bootclasspath.go +++ b/java/bootclasspath.go @@ -185,6 +185,9 @@ var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathDependencyTag{} // The tag used for dependencies onto bootclasspath_fragments. var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"} +// The tag used for dependencies onto platform_bootclasspath. +var platformBootclasspathDepTag = bootclasspathDependencyTag{name: "platform"} + // BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the // bootclasspath that are nested within the main BootclasspathAPIProperties. type BootclasspathNestedAPIProperties struct { diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index ac45ce181..dcc2dece7 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -242,7 +242,7 @@ type BootclasspathFragmentModule struct { modulePaths []string // Path to the boot image profile. - profilePath android.Path + profilePath android.WritablePath } // commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt @@ -256,16 +256,6 @@ type commonBootclasspathFragment interface { // versioned sdk. produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput - // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths - // predefined in the bootImageConfig. - // - // If it could not create the files then it will return nil. Otherwise, it will return a map from - // android.ArchType to the predefined paths of the boot image files. - produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs - - // getImageName returns the `image_name` property of this fragment. - getImageName() *string - // getProfilePath returns the path to the boot image profile. getProfilePath() android.Path } @@ -295,9 +285,6 @@ func bootclasspathFragmentFactory() android.Module { return } } - - // Initialize the contents property from the image_name. - bootclasspathFragmentInitContentsFromImage(ctx, m) }) return m } @@ -308,9 +295,7 @@ func testBootclasspathFragmentFactory() android.Module { return m } -// bootclasspathFragmentInitContentsFromImage will initialize the contents property from the image_name if -// necessary. -func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, m *BootclasspathFragmentModule) { +func (m *BootclasspathFragmentModule) bootclasspathFragmentPropertyCheck(ctx android.EarlyModuleContext) { contents := m.properties.Contents if len(contents) == 0 { ctx.PropertyErrorf("contents", "required property is missing") @@ -332,6 +317,18 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, // too early in the Soong processing for that to work. global := dexpreopt.GetGlobalConfig(ctx) modules := global.ArtApexJars + configuredJars := modules.CopyOfJars() + + // Skip the check if the configured jars list is empty as that is a common configuration when + // building targets that do not result in a system image. + if len(configuredJars) == 0 { + return + } + + if !reflect.DeepEqual(configuredJars, contents) { + ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v", + configuredJars, contents) + } // Make sure that the apex specified in the configuration is consistent and is one for which // this boot image is available. @@ -357,33 +354,6 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, } } -// bootclasspathImageNameContentsConsistencyCheck checks that the configuration that applies to this -// module (if any) matches the contents. -// -// This should be a noop as if image_name="art" then the contents will be set from the ArtApexJars -// config by bootclasspathFragmentInitContentsFromImage so it will be guaranteed to match. However, -// in future this will not be the case. -func (b *BootclasspathFragmentModule) bootclasspathImageNameContentsConsistencyCheck(ctx android.BaseModuleContext) { - imageName := proptools.String(b.properties.Image_name) - if imageName == "art" { - // Get the configuration for the art apex jars. - modules := b.getImageConfig(ctx).modules - configuredJars := modules.CopyOfJars() - - // Skip the check if the configured jars list is empty as that is a common configuration when - // building targets that do not result in a system image. - if len(configuredJars) == 0 { - return - } - - contents := b.properties.Contents - if !reflect.DeepEqual(configuredJars, contents) { - ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v", - configuredJars, contents) - } - } -} - var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(BootclasspathFragmentApexContentInfo{}) // BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the @@ -495,7 +465,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // unused prebuilt that was created without instrumentation from breaking an instrumentation // build. if isActiveModule(ctx.Module()) { - b.bootclasspathImageNameContentsConsistencyCheck(ctx) + b.bootclasspathFragmentPropertyCheck(ctx) } // Generate classpaths.proto config @@ -515,34 +485,15 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag) - // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a - // prebuilt which will not use the image config. - imageConfig := b.getImageConfig(ctx) - // Perform hidden API processing. hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments) - var bootImageFiles bootImageOutputs - if imageConfig != nil { - // Delegate the production of the boot image files to a module type specific method. - common := ctx.Module().(commonBootclasspathFragment) - bootImageFiles = common.produceBootImageFiles(ctx, imageConfig) - b.profilePath = bootImageFiles.profile - - if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) { - // Zip the boot image files up, if available. This will generate the zip file in a - // predefined location. - buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch) - - // Copy the dex jars of this fragment's content modules to their predefined locations. - copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule) - } - } - - // A prebuilt fragment cannot contribute to an apex. - if !android.IsModulePrebuilt(ctx.Module()) { - // Provide the apex content info. - b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles) + if android.IsModulePrebuilt(ctx.Module()) { + b.profilePath = ctx.Module().(*PrebuiltBootclasspathFragmentModule).produceBootImageProfile(ctx) + } else { + b.profilePath = b.produceBootImageProfileFromSource(ctx, contents, hiddenAPIOutput.EncodedBootDexFilesByModule) + // Provide the apex content info. A prebuilt fragment cannot contribute to an apex. + b.provideApexContentInfo(ctx, hiddenAPIOutput, b.profilePath) } // In order for information about bootclasspath_fragment modules to be added to module-info.json @@ -556,44 +507,37 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo } } -// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot -// files, e.g. boot dex jars or boot image files, to the predefined location expected by the rest -// of the build. -// -// This ensures that only a single module will copy its files to the image configuration. -func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageConfig *bootImageConfig) bool { +// getProfileProviderApex returns the name of the apex that provides a boot image profile, or an +// empty string if this module should not provide a boot image profile. +func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseModuleContext) string { + // Only use the profile from the module that is preferred. + if !isActiveModule(ctx.Module()) { + return "" + } + // Bootclasspath fragment modules that are for the platform do not produce boot related files. apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) - if apexInfo.IsForPlatform() { - return false + for _, apex := range apexInfo.InApexVariants { + if isProfileProviderApex(ctx, apex) { + return apex + } } - // If the image configuration has no modules specified then it means that the build has been - // configured to build something other than a boot image, e.g. an sdk, so do not try and copy the - // files. - if imageConfig.modules.Len() == 0 { - return false - } - - // Only copy files from the module that is preferred. - return isActiveModule(ctx.Module()) + return "" } // provideApexContentInfo creates, initializes and stores the apex content info for use by other // modules. -func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) { +func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, hiddenAPIOutput *HiddenAPIOutput, profile android.WritablePath) { // Construct the apex content info from the config. info := BootclasspathFragmentApexContentInfo{ // Populate the apex content info with paths to the dex jars. contentModuleDexJarPaths: hiddenAPIOutput.EncodedBootDexFilesByModule, } - if imageConfig != nil { - global := dexpreopt.GetGlobalConfig(ctx) - if !global.DisableGenerateProfile { - info.profilePathOnHost = bootImageFiles.profile - info.profileInstallPathInApex = imageConfig.profileInstallPathInApex - } + if profile != nil { + info.profilePathOnHost = profile + info.profileInstallPathInApex = profileInstallPathInApex } // Make the apex content info available for other modules. @@ -614,12 +558,12 @@ func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx and } func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { - if "art" == proptools.String(b.properties.Image_name) { - return b.getImageConfig(ctx).modules - } - global := dexpreopt.GetGlobalConfig(ctx) + if "art" == proptools.String(b.properties.Image_name) { + return global.ArtApexJars + } + possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag) jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules) @@ -645,25 +589,6 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) return jars } -func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { - // Get a map of the image configs that are supported. - imageConfigs := genBootImageConfigs(ctx) - - // Retrieve the config for this image. - imageNamePtr := b.properties.Image_name - if imageNamePtr == nil { - return nil - } - - imageName := *imageNamePtr - imageConfig := imageConfigs[imageName] - if imageConfig == nil { - ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedKeys(imageConfigs), ", ")) - return nil - } - return imageConfig -} - // generateHiddenAPIBuildActions generates all the hidden API related build rules. func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput { @@ -846,48 +771,22 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC return output } -// produceBootImageFiles builds the boot image files from the source if it is required. -func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { - // Only generate the boot image if the configuration does not skip it. - return b.generateBootImageBuildActions(ctx, imageConfig) -} - -// generateBootImageBuildActions generates ninja rules to create the boot image if required for this -// module. -// -// If it could not create the files then it will return nil. Otherwise, it will return a map from -// android.ArchType to the predefined paths of the boot image files. -func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { - global := dexpreopt.GetGlobalConfig(ctx) - if !shouldBuildBootImages(ctx.Config(), global) { - return bootImageOutputs{} +// produceBootImageProfileFromSource builds the boot image profile from the source if it is required. +func (b *BootclasspathFragmentModule) produceBootImageProfileFromSource(ctx android.ModuleContext, contents []android.Module, modules bootDexJarByModule) android.WritablePath { + apex := b.getProfileProviderApex(ctx) + if apex == "" { + return nil } - // 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 bootImageOutputs{} + dexPaths := make(android.Paths, 0, len(contents)) + dexLocations := make([]string, 0, len(contents)) + for _, module := range contents { + dexPaths = append(dexPaths, modules[module.Name()]) + dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name() + ".jar")) } - // 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. - if SkipDexpreoptBootJars(ctx) { - return bootImageOutputs{ - profile: profile, - } - } - - // Build boot image files for the host variants. - buildBootImageVariantsForBuildOs(ctx, imageConfig, profile) - - // Build boot image files for the android variants. - bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) - - // Return the boot image files for the android variants for inclusion in an APEX and to be zipped - // up for the dist. - return bootImageFiles + // Build a profile for the modules in this fragment. + return bootImageProfileRuleCommon(ctx, b.Name(), dexPaths, dexLocations) } func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries { @@ -910,10 +809,6 @@ func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntr return entriesList } -func (b *BootclasspathFragmentModule) getImageName() *string { - return b.properties.Image_name -} - func (b *BootclasspathFragmentModule) getProfilePath() android.Path { return b.profilePath } @@ -1183,39 +1078,19 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an return &output } -// produceBootImageFiles extracts the boot image files from the APEX if available. -func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { - if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) { - return bootImageOutputs{} +// produceBootImageProfile extracts the boot image profile from the APEX if available. +func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx android.ModuleContext) android.WritablePath { + // This module does not provide a boot image profile. + if module.getProfileProviderApex(ctx) == "" { + return nil } di := android.FindDeapexerProviderForModule(ctx) if di == nil { - return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule. + return nil // An error has been reported by FindDeapexerProviderForModule. } - profile := (android.WritablePath)(nil) - if imageConfig.profileInstallPathInApex != "" { - profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex) - } - - // Build the boot image files for the host variants. These are always built from the dex files - // provided by the contents of this module as prebuilt versions of the host boot image files are - // not available, i.e. there is no host specific prebuilt apex containing them. This has to be - // built without a profile as the prebuilt modules do not provide a profile. - buildBootImageVariantsForBuildOs(ctx, imageConfig, profile) - - if profile == nil && imageConfig.isProfileGuided() { - ctx.ModuleErrorf("Unable to produce boot image files: profiles not found in the prebuilt apex") - return bootImageOutputs{} - } - // Build boot image files for the android variants from the dex files provided by the contents - // of this module. - return buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) -} - -func (b *PrebuiltBootclasspathFragmentModule) getImageName() *string { - return b.properties.Image_name + return di.PrebuiltExportPath(profileInstallPathInApex) } func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path { @@ -1230,14 +1105,10 @@ var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil) // If there is no image config associated with this fragment then it returns nil. Otherwise, it // returns the files that are listed in the image config. func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string { - imageConfig := module.getImageConfig(ctx) - if imageConfig != nil { - files := []string{} - if imageConfig.profileInstallPathInApex != "" { - // Add the boot image profile. - files = append(files, imageConfig.profileInstallPathInApex) + for _, apex := range module.ApexProperties.Apex_available { + if isProfileProviderApex(ctx, apex) { + return []string{profileInstallPathInApex} } - return files } return nil } @@ -1253,9 +1124,5 @@ func prebuiltBootclasspathFragmentFactory() android.Module { android.InitApexModule(m) android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon) - // Initialize the contents property from the image_name. - android.AddLoadHook(m, func(ctx android.LoadHookContext) { - bootclasspathFragmentInitContentsFromImage(ctx, &m.BootclasspathFragmentModule) - }) return m } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 7b56a1909..479dd45ea 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -16,7 +16,6 @@ package java import ( "path/filepath" - "sort" "strings" "android/soong/android" @@ -224,6 +223,11 @@ var artApexNames = []string{ "com.google.android.art.testing", } +var ( + dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"} + dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments") +) + func init() { RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext) } @@ -241,6 +245,9 @@ type bootImageConfig struct { // Image name (used in directory names and ninja rule names). name string + // If the module with the given name exists, this config is enabled. + enabledIfExists string + // Basename of the image: the resulting filenames are [-].{art,oat,vdex}. stem string @@ -257,10 +264,6 @@ type bootImageConfig struct { // the location is relative to "/". installDir string - // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not - // needed. - profileInstallPathInApex string - // A list of (location, jar) pairs for the Java modules in this image. modules android.ConfiguredJarList @@ -296,10 +299,9 @@ type bootImageConfig struct { // The "--single-image" argument. singleImage bool - // Profiles imported from other boot image configs. Each element must represent a - // `bootclasspath_fragment` of an APEX (i.e., the `name` field of each element must refer to the - // `image_name` property of a `bootclasspath_fragment`). - profileImports []*bootImageConfig + // Profiles imported from APEXes, in addition to the profile at the default path. Each entry must + // be the name of an APEX module. + profileImports []string } // Target-dependent description of a boot image. @@ -458,18 +460,26 @@ func (image *bootImageConfig) isProfileGuided() bool { return image.compilerFilter == "speed-profile" } +func (image *bootImageConfig) isEnabled(ctx android.BaseModuleContext) bool { + return ctx.OtherModuleExists(image.enabledIfExists) +} + func dexpreoptBootJarsFactory() android.SingletonModule { m := &dexpreoptBootJars{} - android.InitAndroidModule(m) + android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) return m } func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) { ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory) + ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator).Parallel() + }) } func SkipDexpreoptBootJars(ctx android.PathContext) bool { - return dexpreopt.GetGlobalConfig(ctx).DisablePreoptBootImages + global := dexpreopt.GetGlobalConfig(ctx) + return global.DisablePreoptBootImages || !shouldBuildBootImages(ctx.Config(), global) } // Singleton module for generating boot image build rules. @@ -492,38 +502,90 @@ type dexpreoptBootJars struct { dexpreoptConfigForMake android.WritablePath } -// Provide paths to boot images for use by modules that depend upon them. -// -// The build rules are created in GenerateSingletonBuildActions(). -func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) { - // Placeholder for now. +func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) { + if _, ok := ctx.Module().(*dexpreoptBootJars); !ok { + return + } + + if dexpreopt.IsDex2oatNeeded(ctx) { + // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The + // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). + dexpreopt.RegisterToolDeps(ctx) + } + + imageConfigs := genBootImageConfigs(ctx) + for _, config := range imageConfigs { + if !config.isEnabled(ctx) { + continue + } + // For accessing the boot jars. + addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag) + } + + if ctx.OtherModuleExists("platform-bootclasspath") { + // For accessing all bootclasspath fragments. + addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platformBootclasspathDepTag) + } else if ctx.OtherModuleExists("art-bootclasspath-fragment") { + // For accessing the ART bootclasspath fragment on a thin manifest (e.g., master-art) where + // platform-bootclasspath doesn't exist. + addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", bootclasspathFragmentDepTag) + } } -// Generate build rules for boot images. -func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) { - if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil { - // No module has enabled dexpreopting, so we assume there will be no boot image to make. - return - } - d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config") - writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake) +func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module { + return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} { + fragments := make(map[string]android.Module) + ctx.WalkDeps(func(child, parent android.Module) bool { + if !isActiveModule(child) { + return false + } + tag := ctx.OtherModuleDependencyTag(child) + if tag == platformBootclasspathDepTag { + return true + } + if tag == bootclasspathFragmentDepTag { + apexInfo := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo) + for _, apex := range apexInfo.InApexVariants { + fragments[apex] = child + } + return false + } + return false + }) + return fragments + }).(map[string]android.Module) +} - global := dexpreopt.GetGlobalConfig(ctx) - if !shouldBuildBootImages(ctx.Config(), global) { - return - } +func getBootclasspathFragmentByApex(ctx android.ModuleContext, apexName string) android.Module { + return gatherBootclasspathFragments(ctx)[apexName] +} - defaultImageConfig := defaultBootImageConfig(ctx) - d.defaultBootImage = defaultImageConfig +// GenerateAndroidBuildActions generates the build rules for boot images. +func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) { imageConfigs := genBootImageConfigs(ctx) + d.defaultBootImage = defaultBootImageConfig(ctx) d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1) - for _, config := range imageConfigs { - if config != defaultImageConfig { + for _, name := range getImageNames() { + config := imageConfigs[name] + if config != d.defaultBootImage { d.otherImages = append(d.otherImages, config) } + if !config.isEnabled(ctx) { + continue + } + generateBootImage(ctx, config) + if config == d.defaultBootImage { + bootFrameworkProfileRule(ctx, config) + } } } +// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make. +func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) { + d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config") + writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake) +} + // shouldBuildBootImages determines whether boot images should be built. func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig) bool { // Skip recompiling the boot image for the second sanitization phase. We'll get separate paths @@ -536,6 +598,101 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig return true } +func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) { + apexJarModulePairs := getModulesForImage(ctx, imageConfig) + + // Copy module dex jars to their predefined locations. + bootDexJarsByModule := extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx, apexJarModulePairs) + copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule) + + // Build a profile for the image config from the profile at the default path. The profile will + // then be used along with profiles imported from APEXes to build the boot image. + profile := bootImageProfileRule(ctx, imageConfig) + + // If dexpreopt of boot image jars should be skipped, stop after generating a profile. + if SkipDexpreoptBootJars(ctx) { + 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) + + // Create a `dump-oat-` rule that runs `oatdump` for debugging purposes. + dumpOatRules(ctx, imageConfig) +} + +type apexJarModulePair struct { + apex string + jarModule android.Module +} + +func getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []apexJarModulePair { + modules := make([]apexJarModulePair, 0, imageConfig.modules.Len()) + for i := 0; i < imageConfig.modules.Len(); i++ { + found := false + for _, module := range gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJarDepTag) { + name := android.RemoveOptionalPrebuiltPrefix(module.Name()) + if name == imageConfig.modules.Jar(i) { + modules = append(modules, apexJarModulePair{ + apex: imageConfig.modules.Apex(i), + jarModule: module, + }) + found = true + break + } + } + if !found && !ctx.Config().AllowMissingDependencies() { + ctx.ModuleErrorf( + "Boot image '%s' module '%s' not added as a dependency of dex_bootjars", + imageConfig.name, + imageConfig.modules.Jar(i)) + return []apexJarModulePair{} + } + } + return modules +} + +// extractEncodedDexJarsFromModulesOrBootclasspathFragments gets the hidden API encoded dex jars for +// the given modules. +func extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx android.ModuleContext, apexJarModulePairs []apexJarModulePair) bootDexJarByModule { + encodedDexJarsByModuleName := bootDexJarByModule{} + for _, pair := range apexJarModulePairs { + var path android.Path + if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) { + // This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API + // files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for + // a source APEX because there is no guarantee that it is the same as the jar packed into the + // APEX. In practice, they are the same when we are building from a full source tree, but they + // are different when we are building from a thin manifest (e.g., master-art), where there is + // no monolithic hidden API files at all. + path = retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule) + } else { + // Use exactly the same jar that is packed into the APEX. + fragment := getBootclasspathFragmentByApex(ctx, pair.apex) + if fragment == nil { + ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+ + "APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars", + pair.jarModule.Name(), + pair.apex) + } + bootclasspathFragmentInfo := ctx.OtherModuleProvider(fragment, BootclasspathFragmentApexContentInfoProvider).(BootclasspathFragmentApexContentInfo) + jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule) + if err != nil { + ctx.ModuleErrorf("%s", err) + } + path = jar + } + encodedDexJarsByModuleName.addPath(pair.jarModule, path) + } + return encodedDexJarsByModuleName +} + // copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined // paths in the global config. func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) { @@ -686,10 +843,12 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p rule.Command().Text("rm").Flag("-f"). Flag(symbolsDir.Join(ctx, "*.art").String()). Flag(symbolsDir.Join(ctx, "*.oat").String()). + Flag(symbolsDir.Join(ctx, "*.vdex").String()). Flag(symbolsDir.Join(ctx, "*.invocation").String()) rule.Command().Text("rm").Flag("-f"). Flag(outputDir.Join(ctx, "*.art").String()). Flag(outputDir.Join(ctx, "*.oat").String()). + Flag(outputDir.Join(ctx, "*.vdex").String()). Flag(outputDir.Join(ctx, "*.invocation").String()) cmd := rule.Command() @@ -711,36 +870,31 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms). Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx) - if profile != nil { - cmd.FlagWithInput("--profile-file=", profile) - } + if image.isProfileGuided() && !global.DisableGenerateProfile { + if profile != nil { + cmd.FlagWithInput("--profile-file=", profile) + } - fragments := make(map[string]commonBootclasspathFragment) - ctx.VisitDirectDepsWithTag(bootclasspathFragmentDepTag, func(child android.Module) { - fragment := child.(commonBootclasspathFragment) - if fragment.getImageName() != nil && android.IsModulePreferred(child) { - fragments[*fragment.getImageName()] = fragment + for _, apex := range image.profileImports { + fragment := getBootclasspathFragmentByApex(ctx, apex) + if fragment == nil { + ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+ + "bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+ + "dependency of dex_bootjars", + image.name, + apex) + return bootImageVariantOutputs{} + } + importedProfile := fragment.(commonBootclasspathFragment).getProfilePath() + if importedProfile == nil { + ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+ + "doesn't provide a profile", + image.name, + apex) + return bootImageVariantOutputs{} + } + cmd.FlagWithInput("--profile-file=", importedProfile) } - }) - - for _, profileImport := range image.profileImports { - fragment := fragments[profileImport.name] - if fragment == nil { - ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+ - "bootclasspath_fragment with image name '%[2]s' doesn't exist or is not added as a "+ - "dependency of '%[1]s'", - image.name, - profileImport.name) - return bootImageVariantOutputs{} - } - if fragment.getProfilePath() == nil { - ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+ - "doesn't provide a profile", - image.name, - profileImport.name) - return bootImageVariantOutputs{} - } - cmd.FlagWithInput("--profile-file=", fragment.getProfilePath()) } dirtyImageFile := "frameworks/base/config/dirty-image-objects" @@ -1059,11 +1213,9 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " ")) ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " ")) - var imageNames []string // The primary ART boot image is exposed to Make for testing (gtests) and benchmarking // (golem) purposes. for _, current := range append(d.otherImages, image) { - imageNames = append(imageNames, current.name) for _, variant := range current.variants { suffix := "" if variant.target.Os.Class == android.Host { @@ -1084,8 +1236,6 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE"+current.name, strings.Join(imageLocationsOnDevice, ":")) ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String()) } - // Ensure determinism. - sort.Strings(imageNames) - ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " ")) + ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(getImageNames(), " ")) } } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index abbb96a26..842f39275 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -40,57 +40,68 @@ func dexpreoptTargets(ctx android.PathContext) []android.Target { } var ( - bootImageConfigKey = android.NewOnceKey("bootImageConfig") - bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw") - artBootImageName = "art" - frameworkBootImageName = "boot" - mainlineBootImageName = "mainline" - bootImageStem = "boot" + bootImageConfigKey = android.NewOnceKey("bootImageConfig") + bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw") + frameworkBootImageName = "boot" + mainlineBootImageName = "mainline" + bootImageStem = "boot" + profileInstallPathInApex = "etc/boot-image.prof" ) +// getImageNames returns an ordered list of image names. The order doesn't matter but needs to be +// deterministic. The names listed here must match the map keys returned by genBootImageConfigs. +func getImageNames() []string { + return []string{"art", "boot", "mainline"} +} + func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig { return ctx.Config().Once(bootImageConfigRawKey, func() interface{} { global := dexpreopt.GetGlobalConfig(ctx) + artBootImageName := "art" // Keep this local to avoid accidental references. artModules := global.ArtApexJars - frameworkModules := global.BootJars // This includes `artModules`. + frameworkModules := global.BootJars // This includes `global.ArtApexJars`. mainlineBcpModules := global.ApexBootJars frameworkSubdir := "system/framework" - // ART config for the primary boot image in the ART apex. - // It includes the Core Libraries. + profileImports := []string{"com.android.art"} + + // ART boot image for testing only. Do not rely on it to make any build-time decision. artCfg := bootImageConfig{ - name: artBootImageName, - stem: bootImageStem, - installDir: "apex/art_boot_images/javalib", - profileInstallPathInApex: "etc/boot-image.prof", - modules: artModules, - preloadedClassesFile: "art/build/boot/preloaded-classes", - compilerFilter: "speed-profile", - singleImage: false, + name: artBootImageName, + enabledIfExists: "art-bootclasspath-fragment", + stem: bootImageStem, + installDir: "apex/art_boot_images/javalib", + modules: artModules, + preloadedClassesFile: "art/build/boot/preloaded-classes", + compilerFilter: "speed-profile", + singleImage: false, + profileImports: profileImports, } // Framework config for the boot image extension. // It includes framework libraries and depends on the ART config. frameworkCfg := bootImageConfig{ name: frameworkBootImageName, + enabledIfExists: "platform-bootclasspath", stem: bootImageStem, installDir: frameworkSubdir, modules: frameworkModules, preloadedClassesFile: "frameworks/base/config/preloaded-classes", compilerFilter: "speed-profile", singleImage: false, - profileImports: []*bootImageConfig{&artCfg}, + profileImports: profileImports, } mainlineCfg := bootImageConfig{ - extends: &frameworkCfg, - name: mainlineBootImageName, - stem: bootImageStem, - installDir: frameworkSubdir, - modules: mainlineBcpModules, - compilerFilter: "verify", - singleImage: true, + extends: &frameworkCfg, + name: mainlineBootImageName, + enabledIfExists: "platform-bootclasspath", + stem: bootImageStem, + installDir: frameworkSubdir, + modules: mainlineBcpModules, + compilerFilter: "verify", + singleImage: true, } return map[string]*bootImageConfig{ @@ -180,10 +191,6 @@ func calculateDepsRecursive(c *bootImageConfig, targets []android.Target, visite } } -func artBootImageConfig(ctx android.PathContext) *bootImageConfig { - return genBootImageConfigs(ctx)[artBootImageName] -} - func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig { return genBootImageConfigs(ctx)[frameworkBootImageName] } @@ -192,6 +199,18 @@ func mainlineBootImageConfig(ctx android.PathContext) *bootImageConfig { return genBootImageConfigs(ctx)[mainlineBootImageName] } +// isProfileProviderApex returns true if this apex provides a boot image profile. +func isProfileProviderApex(ctx android.PathContext, apexName string) bool { + for _, config := range genBootImageConfigs(ctx) { + for _, profileImport := range config.profileImports { + if profileImport == apexName { + return true + } + } + } + return false +} + // Apex boot config allows to access build/install paths of apex boot jars without going // through the usual trouble of registering dependencies on those modules and extracting build paths // from those dependencies. diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go index cd7f295c8..44d2127fd 100644 --- a/java/dexpreopt_config_test.go +++ b/java/dexpreopt_config_test.go @@ -16,6 +16,7 @@ package java import ( "runtime" + "sort" "testing" "android/soong/android" @@ -35,3 +36,22 @@ func TestBootImageConfig(t *testing.T) { CheckFrameworkBootImageConfig(t, result) CheckMainlineBootImageConfig(t, result) } + +func TestImageNames(t *testing.T) { + result := android.GroupFixturePreparers( + PrepareForBootImageConfigTest, + ).RunTest(t) + + names := getImageNames() + sort.Strings(names) + + ctx := &android.TestPathContext{TestResult: result} + configs := genBootImageConfigs(ctx) + namesFromConfigs := make([]string, 0, len(configs)) + for name, _ := range configs { + namesFromConfigs = append(namesFromConfigs, name) + } + sort.Strings(namesFromConfigs) + + android.AssertArrayString(t, "getImageNames vs genBootImageConfigs", names, namesFromConfigs) +} diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go index 56f16e01f..db430810e 100644 --- a/java/dexpreopt_config_testing.go +++ b/java/dexpreopt_config_testing.go @@ -813,8 +813,8 @@ func checkFrameworkBootImageConfig(t *testing.T, result *android.TestResult, mut }, }, profileInstalls: []normalizedInstall{ + {from: "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof", to: "/system/etc/boot-image.prof"}, {from: "out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof", to: "/system/etc/boot-image.bprof"}, - {from: "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/boot/boot.prof", to: "/system/etc/boot-image.prof"}, }, profileLicenseMetadataFile: expectedLicenseMetadataFile, } @@ -1230,14 +1230,14 @@ DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm=%[1]s DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm64=%[1]s DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86=%[1]s DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86_64=%[1]s -DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic -DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic -DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic -DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic -DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic -DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic -DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic -DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEart=/apex/art_boot_images/javalib/boot.art DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEmainline=/system/framework/boot.art:/system/framework/boot-framework-foo.art @@ -1245,8 +1245,8 @@ DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTart=out/soong/dexpreopt_arm64/dex_artjars/andro DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art:out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/boot-framework-foo.art DEXPREOPT_IMAGE_NAMES=art boot mainline -DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/boot/boot.prof:/system/etc/boot-image.prof -DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic +DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof:/system/etc/boot-image.prof out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof +DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 0d4db7ca1..a4bba486d 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -123,15 +123,15 @@ func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpM } 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 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo 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) configuredJars(ctx android.ModuleContext) } 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 @@ func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.Make 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 -} diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index ac23aab86..ee1b5dbf6 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -145,8 +145,8 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "art-bootclasspath-fragment") // Check that source on its own configures the bootImageConfig correctly. - java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/meta_lic") - java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") CheckSnapshot(t, result, "mysdk", "", checkAndroidBpContents(` @@ -213,24 +213,24 @@ java_import { java.ApexBootJarDexJarPaths..., )..., ) - java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/art-bootclasspath-fragment/android_common_com.android.art/meta_lic") - java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") }), snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot), // Check the behavior of the snapshot when the source is preferred. snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) { - java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/meta_lic") - java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") }), snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), // Check the behavior of the snapshot when it is preferred. snapshotTestChecker(checkSnapshotPreferredWithSource, func(t *testing.T, result *android.TestResult) { - java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/prebuilt_art-bootclasspath-fragment/android_common_com.android.art/meta_lic") - java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic") }), )