diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 6d935d86a..ebd22cfa1 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -162,11 +162,12 @@ type commonBootclasspathFragment interface { // versioned sdk. produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput - // produceBootImageFiles produces the boot image (i.e. .art, .oat and .vdex) files for each of the - // required android.ArchType values in the returned map. + // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths + // predefined in the bootImageConfig. // - // It must return nil if the boot image files cannot be produced for whatever reason. - produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch + // 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) bootImageFilesByArch } var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil) @@ -454,9 +455,13 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo if imageConfig != nil { // Delegate the production of the boot image files to a module type specific method. common := ctx.Module().(commonBootclasspathFragment) - bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig, contents) + bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig) 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, bootImageFilesByArch) + // Copy the dex jars of this fragment's content modules to their predefined locations. copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule) } @@ -664,7 +669,7 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC } // produceBootImageFiles builds the boot image files from the source if it is required. -func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch { +func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch { if SkipDexpreoptBootJars(ctx) { return nil } @@ -674,45 +679,34 @@ func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleCo dexpreopt.GetGlobalSoongConfig(ctx) // Only generate the boot image if the configuration does not skip it. - if !b.generateBootImageBuildActions(ctx, contents, imageConfig) { - return nil - } - - // Only make the files available to an apex if they were actually generated. - files := bootImageFilesByArch{} - for _, variant := range imageConfig.apexVariants() { - files[variant.target.Arch.ArchType] = variant.imagesDeps.Paths() - } - - return files + return b.generateBootImageBuildActions(ctx, imageConfig) } // generateBootImageBuildActions generates ninja rules to create the boot image if required for this // module. // -// Returns true if the boot image is created, false otherwise. -func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, contents []android.Module, imageConfig *bootImageConfig) bool { +// 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) bootImageFilesByArch { global := dexpreopt.GetGlobalConfig(ctx) if !shouldBuildBootImages(ctx.Config(), global) { - return false + 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 false + return nil } // Bootclasspath fragment modules that are versioned do not produce a boot image. if android.IsModuleInVersionedSdk(ctx.Module()) { - return false + return nil } // Build a profile for the image config and then use that to build the boot image. profile := bootImageProfileRule(ctx, imageConfig) - buildBootImage(ctx, imageConfig, profile) - - return true + return buildBootImage(ctx, imageConfig, profile) } // Collect information for opening IDE project files in java/jdeps.go. @@ -940,7 +934,7 @@ func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an } // produceBootImageFiles extracts the boot image files from the APEX if available. -func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch { +func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch { if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) { return nil } @@ -962,6 +956,7 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and } di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo) + files := bootImageFilesByArch{} for _, variant := range imageConfig.apexVariants() { arch := variant.target.Arch.ArchType for _, toPath := range variant.imagesDeps { @@ -969,6 +964,10 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and // Get the path to the file that the deapexer extracted from the prebuilt apex file. fromPath := di.PrebuiltExportPath(apexRelativePath) + // Return the toPath as the calling code expects the paths in the returned map to be the + // paths predefined in the bootImageConfig. + files[arch] = append(files[arch], toPath) + // Copy the file to the predefined location. ctx.Build(pctx, android.BuildParams{ Rule: android.Cp, @@ -978,10 +977,7 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and } } - // The returned files will be made available to APEXes that include a bootclasspath_fragment. - // However, as a prebuilt_bootclasspath_fragment can never contribute to an APEX there is no point - // in returning any files. - return nil + return files } var _ commonBootclasspathFragment = (*prebuiltBootclasspathFragmentModule)(nil) diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 03769fab7..cb5b6bea9 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -503,29 +503,47 @@ func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJars } // buildBootImage takes a bootImageConfig, and creates rules to build it. -func buildBootImage(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) { - var zipFiles android.Paths +// +// It returns a map from android.ArchType to the predefined paths of the boot image files. +func buildBootImage(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageFilesByArch { + filesByArch := bootImageFilesByArch{} for _, variant := range image.variants { - files := buildBootImageVariant(ctx, variant, profile) + buildBootImageVariant(ctx, variant, profile) if variant.target.Os == android.Android { - zipFiles = append(zipFiles, files.Paths()...) + filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths() } } - if image.zip != nil { - rule := android.NewRuleBuilder(pctx, ctx) - rule.Command(). - BuiltTool("soong_zip"). - FlagWithOutput("-o ", image.zip). - FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()). - FlagWithInputList("-f ", zipFiles, " -f ") + return filesByArch +} - rule.Build("zip_"+image.name, "zip "+image.name+" image") +// buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files. +// +// The supplied filesByArch is nil when the boot image files have not been generated. Otherwise, it +// is a map from android.ArchType to the predefined locations. +func buildBootImageZipInPredefinedLocation(ctx android.ModuleContext, image *bootImageConfig, filesByArch bootImageFilesByArch) { + if filesByArch == nil { + return } + + // Compute the list of files from all the architectures. + zipFiles := android.Paths{} + for _, archType := range android.ArchTypeList() { + zipFiles = append(zipFiles, filesByArch[archType]...) + } + + rule := android.NewRuleBuilder(pctx, ctx) + rule.Command(). + BuiltTool("soong_zip"). + FlagWithOutput("-o ", image.zip). + FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()). + FlagWithInputList("-f ", zipFiles, " -f ") + + rule.Build("zip_"+image.name, "zip "+image.name+" image") } // Generate boot image build rules for a specific target. -func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) android.WritablePaths { +func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) { globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx) global := dexpreopt.GetGlobalConfig(ctx) @@ -641,11 +659,8 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p var vdexInstalls android.RuleBuilderInstalls var unstrippedInstalls android.RuleBuilderInstalls - var zipFiles android.WritablePaths - for _, artOrOat := range image.moduleFiles(ctx, outputDir, ".art", ".oat") { cmd.ImplicitOutput(artOrOat) - zipFiles = append(zipFiles, artOrOat) // Install the .oat and .art files rule.Install(artOrOat, filepath.Join(installDir, artOrOat.Base())) @@ -653,7 +668,6 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p for _, vdex := range image.moduleFiles(ctx, outputDir, ".vdex") { cmd.ImplicitOutput(vdex) - zipFiles = append(zipFiles, vdex) // Note that the vdex files are identical between architectures. // Make rules will create symlinks to share them between architectures. @@ -675,8 +689,6 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p image.installs = rule.Installs() image.vdexInstalls = vdexInstalls image.unstrippedInstalls = unstrippedInstalls - - return zipFiles } const failureMessage = `ERROR: Dex2oat failed to compile a boot image. diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index d72cee0c3..3160a27e1 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -437,7 +437,10 @@ func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android. // Build a profile for the image config and then use that to build the boot image. profile := bootImageProfileRule(ctx, imageConfig) - buildBootImage(ctx, imageConfig, profile) + bootImageFilesByArch := buildBootImage(ctx, imageConfig, profile) + + // Zip the boot image files up. + buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFilesByArch) dumpOatRules(ctx, imageConfig) }