Use boot image extension for framework libraries.

This patch splits the system boot image in two parts:

  - The ART boot image. This is the primary boot image that is
    included in the ART apex and contains dexpreopted Core Libraries.

  - The framweork boot image extension. It depends on the ART boot
    image and contains framework libraries.

The third "apex" boot image (used in the JIT-zygote experiment)
remains unchanged; it is a monolithic primary boot image that
contains both libcore and framework libraries.

Dexpreopting of APKs now uses the framework boot image extension
(which in turn pulls in the ART boot image as a dependency).

Test: m
Test: phone boots:
    lunch aosp_walleye-userdebug && m \
        && adb reboot bootloader && fastboot flashall -w

Bug: b/119800099

Exempt-From-Owner-Approval: rebased after getting approval.

Change-Id: Ida40dfae8c83bf7c2e737d5c7ea418e1197ad826
This commit is contained in:
Ulya Trafimovich
2019-11-08 10:54:21 +00:00
committed by Ulyana Trafimovich
parent 3ae3b17083
commit 4d2eeed0da
8 changed files with 270 additions and 175 deletions

View File

@@ -247,6 +247,33 @@ func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Path
return ret return ret
} }
// OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
type OutputPaths []OutputPath
// Paths returns the OutputPaths as a Paths
func (p OutputPaths) Paths() Paths {
if p == nil {
return nil
}
ret := make(Paths, len(p))
for i, path := range p {
ret[i] = path
}
return ret
}
// Strings returns the string forms of the writable paths.
func (p OutputPaths) Strings() []string {
if p == nil {
return nil
}
ret := make([]string, len(p))
for i, path := range p {
ret[i] = path.String()
}
return ret
}
// PathsAndMissingDepsForModuleSrcExcludes returns Paths rooted from the module's local source directory, excluding // PathsAndMissingDepsForModuleSrcExcludes returns Paths rooted from the module's local source directory, excluding
// paths listed in the excludes arguments, and a list of missing dependencies. It expands globs, references to // paths listed in the excludes arguments, and a list of missing dependencies. It expands globs, references to
// SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the // SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the

View File

@@ -119,7 +119,8 @@ type ModuleConfig struct {
Archs []android.ArchType Archs []android.ArchType
DexPreoptImages []android.Path DexPreoptImages []android.Path
DexPreoptImagesDeps []android.Paths DexPreoptImagesDeps []android.OutputPaths
DexPreoptImageLocations []string
PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files
PreoptBootClassPathDexLocations []string // virtual locations of boot class path files PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
@@ -225,6 +226,7 @@ func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error
ProfileClassListing string ProfileClassListing string
LibraryPaths map[string]string LibraryPaths map[string]string
DexPreoptImages []string DexPreoptImages []string
DexPreoptImageLocations []string
PreoptBootClassPathDexFiles []string PreoptBootClassPathDexFiles []string
} }
@@ -242,10 +244,11 @@ func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error
config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing)) config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths) config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages) config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles) config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
// This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON. // This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON.
config.ModuleConfig.DexPreoptImagesDeps = make([]android.Paths, len(config.ModuleConfig.DexPreoptImages)) config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.DexPreoptImages))
return config.ModuleConfig, nil return config.ModuleConfig, nil
} }

View File

@@ -86,10 +86,8 @@ func GenerateDexpreoptRule(ctx android.PathContext,
generateDM := shouldGenerateDM(module, global) generateDM := shouldGenerateDM(module, global)
for i, arch := range module.Archs { for archIdx, _ := range module.Archs {
image := module.DexPreoptImages[i] dexpreoptCommand(ctx, global, module, rule, archIdx, profile, appImage, generateDM)
imageDeps := module.DexPreoptImagesDeps[i]
dexpreoptCommand(ctx, global, module, rule, arch, profile, image, imageDeps, appImage, generateDM)
} }
} }
} }
@@ -193,7 +191,9 @@ func bootProfileCommand(ctx android.PathContext, global GlobalConfig, module Mod
} }
func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder, func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
arch android.ArchType, profile, bootImage android.Path, bootImageDeps android.Paths, appImage, generateDM bool) { archIdx int, profile android.WritablePath, appImage bool, generateDM bool) {
arch := module.Archs[archIdx]
// HACK: make soname in Soong-generated .odex files match Make. // HACK: make soname in Soong-generated .odex files match Make.
base := filepath.Base(module.DexLocation) base := filepath.Base(module.DexLocation)
@@ -222,13 +222,6 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
invocationPath := odexPath.ReplaceExtension(ctx, "invocation") invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
// bootImage is .../dex_bootjars/system/framework/arm64/boot.art, but dex2oat wants
// .../dex_bootjars/system/framework/boot.art on the command line
var bootImageLocation string
if bootImage != nil {
bootImageLocation = PathToLocation(bootImage, arch)
}
// The class loader context using paths in the build // The class loader context using paths in the build
var classLoaderContextHost android.Paths var classLoaderContextHost android.Paths
@@ -356,7 +349,7 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":"). Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":").
Flag("${class_loader_context_arg}"). Flag("${class_loader_context_arg}").
Flag("${stored_class_loader_context_arg}"). Flag("${stored_class_loader_context_arg}").
FlagWithArg("--boot-image=", bootImageLocation).Implicits(bootImageDeps). FlagWithArg("--boot-image=", strings.Join(module.DexPreoptImageLocations, ":")).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()).
FlagWithInput("--dex-file=", module.DexPath). FlagWithInput("--dex-file=", module.DexPath).
FlagWithArg("--dex-location=", dexLocationArg). FlagWithArg("--dex-location=", dexLocationArg).
FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath). FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath).
@@ -555,7 +548,7 @@ func SplitApexJarPair(apexJarValue string) (string, string) {
} }
// Expected format for apexJarValue = <apex name>:<jar name> // Expected format for apexJarValue = <apex name>:<jar name>
func GetJarLocationFromApexJarPair(apexJarValue string) (string) { func GetJarLocationFromApexJarPair(apexJarValue string) string {
apex, jar := SplitApexJarPair(apexJarValue) apex, jar := SplitApexJarPair(apexJarValue)
return filepath.Join("/apex", apex, "javalib", jar+".jar") return filepath.Join("/apex", apex, "javalib", jar+".jar")
} }

View File

@@ -49,7 +49,8 @@ func testModuleConfig(ctx android.PathContext, name, partition string) ModuleCon
LibraryPaths: nil, LibraryPaths: nil,
Archs: []android.ArchType{android.Arm}, Archs: []android.ArchType{android.Arm},
DexPreoptImages: android.Paths{android.PathForTesting("system/framework/arm/boot.art")}, DexPreoptImages: android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
DexPreoptImagesDeps: []android.Paths{android.Paths{}}, DexPreoptImagesDeps: []android.OutputPaths{android.OutputPaths{}},
DexPreoptImageLocations: []string{},
PreoptBootClassPathDexFiles: nil, PreoptBootClassPathDexFiles: nil,
PreoptBootClassPathDexLocations: nil, PreoptBootClassPathDexLocations: nil,
PreoptExtractedApk: false, PreoptExtractedApk: false,

View File

@@ -124,7 +124,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
} }
var images android.Paths var images android.Paths
var imagesDeps []android.Paths var imagesDeps []android.OutputPaths
for _, arch := range archs { for _, arch := range archs {
images = append(images, bootImage.images[arch]) images = append(images, bootImage.images[arch])
imagesDeps = append(imagesDeps, bootImage.imagesDeps[arch]) imagesDeps = append(imagesDeps, bootImage.imagesDeps[arch])
@@ -172,12 +172,13 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
Archs: archs, Archs: archs,
DexPreoptImages: images, DexPreoptImages: images,
DexPreoptImagesDeps: imagesDeps, DexPreoptImagesDeps: imagesDeps,
DexPreoptImageLocations: bootImage.imageLocations,
// We use the dex paths and dex locations of the default boot image, as it // We use the dex paths and dex locations of the default boot image, as it
// contains the full dexpreopt boot classpath. Other images may just contain a subset of // contains the full dexpreopt boot classpath. Other images may just contain a subset of
// the dexpreopt boot classpath. // the dexpreopt boot classpath.
PreoptBootClassPathDexFiles: defaultBootImage.dexPaths.Paths(), PreoptBootClassPathDexFiles: defaultBootImage.dexPathsDeps.Paths(),
PreoptBootClassPathDexLocations: defaultBootImage.dexLocations, PreoptBootClassPathDexLocations: defaultBootImage.dexLocationsDeps,
PreoptExtractedApk: false, PreoptExtractedApk: false,

View File

@@ -22,7 +22,6 @@ import (
"android/soong/android" "android/soong/android"
"android/soong/dexpreopt" "android/soong/dexpreopt"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools"
) )
@@ -50,38 +49,77 @@ func init() {
// will then reconstruct the real path, so the rules must have a dependency on the real path. // will then reconstruct the real path, so the rules must have a dependency on the real path.
type bootImageConfig struct { type bootImageConfig struct {
// Whether this image is an extension.
extension bool
// Image name (used in directory names and ninja rule names).
name string name string
// Basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}.
stem string stem string
modules []string
dexLocations []string // Output directory for the image files.
dexPaths android.WritablePaths
dir android.OutputPath dir android.OutputPath
// Output directory for the image files with debug symbols.
symbolsDir android.OutputPath symbolsDir android.OutputPath
// Subdirectory where the image files are installed.
installSubdir string
// Targets for which the image is generated.
targets []android.Target targets []android.Target
images map[android.ArchType]android.OutputPath
imagesDeps map[android.ArchType]android.Paths // The names of jars that constitute this image.
modules []string
// The "locations" of jars.
dexLocations []string // for this image
dexLocationsDeps []string // for the dependency images and in this image
// File paths to jars.
dexPaths android.WritablePaths // for this image
dexPathsDeps android.WritablePaths // for the dependency images and in this image
// The "locations" of the dependency images and in this image.
imageLocations []string
// Paths to image files (grouped by target).
images map[android.ArchType]android.OutputPath // first image file
imagesDeps map[android.ArchType]android.OutputPaths // all files
// File path to a zip archive with all image files (or nil, if not needed).
zip android.WritablePath zip android.WritablePath
} }
func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) []android.OutputPath { func (image bootImageConfig) moduleName(idx int) string {
ret := make([]android.OutputPath, 0, len(image.modules)*len(exts)) // Dexpreopt on the boot class path produces multiple files. The first dex file
// is converted into 'name'.art (to match the legacy assumption that 'name'.art
// dex preopt on the bootclasspath produces multiple files. The first dex file
// is converted into to 'name'.art (to match the legacy assumption that 'name'.art
// exists), and the rest are converted to 'name'-<jar>.art. // exists), and the rest are converted to 'name'-<jar>.art.
// In addition, each .art file has an associated .oat and .vdex file, and an m := image.modules[idx]
// unstripped .oat file
for i, m := range image.modules {
name := image.stem name := image.stem
if i != 0 { if idx != 0 || image.extension {
name += "-" + stemOf(m) name += "-" + stemOf(m)
} }
return name
}
func (image bootImageConfig) firstModuleNameOrStem() string {
if len(image.modules) > 0 {
return image.moduleName(0)
} else {
return image.stem
}
}
func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) android.OutputPaths {
ret := make(android.OutputPaths, 0, len(image.modules)*len(exts))
for i := range image.modules {
name := image.moduleName(i)
for _, ext := range exts { for _, ext := range exts {
ret = append(ret, dir.Join(ctx, name+ext)) ret = append(ret, dir.Join(ctx, name+ext))
} }
} }
return ret return ret
} }
@@ -140,12 +178,6 @@ func skipDexpreoptBootJars(ctx android.PathContext) bool {
return false return false
} }
func skipDexpreoptArtBootJars(ctx android.BuilderContext) bool {
// with EMMA_INSTRUMENT_FRAMEWORK=true ART boot class path libraries have dependencies on framework,
// therefore dexpreopt ART libraries cannot be dexpreopted in isolation => no ART boot image
return ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
}
type dexpreoptBootJars struct { type dexpreoptBootJars struct {
defaultBootImage *bootImage defaultBootImage *bootImage
otherImages []*bootImage otherImages []*bootImage
@@ -154,8 +186,8 @@ type dexpreoptBootJars struct {
} }
// Accessor function for the apex package. Returns nil if dexpreopt is disabled. // Accessor function for the apex package. Returns nil if dexpreopt is disabled.
func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.Paths { func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.OutputPaths {
if skipDexpreoptBootJars(ctx) || skipDexpreoptArtBootJars(ctx) { if skipDexpreoptBootJars(ctx) {
return nil return nil
} }
return artBootImageConfig(ctx).imagesDeps return artBootImageConfig(ctx).imagesDeps
@@ -184,10 +216,8 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
// Always create the default boot image first, to get a unique profile rule for all images. // Always create the default boot image first, to get a unique profile rule for all images.
d.defaultBootImage = buildBootImage(ctx, defaultBootImageConfig(ctx)) d.defaultBootImage = buildBootImage(ctx, defaultBootImageConfig(ctx))
if !skipDexpreoptArtBootJars(ctx) {
// Create boot image for the ART apex (build artifacts are accessed via the global boot image config). // Create boot image for the ART apex (build artifacts are accessed via the global boot image config).
buildBootImage(ctx, artBootImageConfig(ctx)) buildBootImage(ctx, artBootImageConfig(ctx))
}
if global.GenerateApexImage { if global.GenerateApexImage {
// Create boot images for the JIT-zygote experiment. // Create boot images for the JIT-zygote experiment.
d.otherImages = append(d.otherImages, buildBootImage(ctx, apexBootImageConfig(ctx))) d.otherImages = append(d.otherImages, buildBootImage(ctx, apexBootImageConfig(ctx)))
@@ -201,7 +231,6 @@ func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootI
image := newBootImage(ctx, config) image := newBootImage(ctx, config)
bootDexJars := make(android.Paths, len(image.modules)) bootDexJars := make(android.Paths, len(image.modules))
ctx.VisitAllModules(func(module android.Module) { ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above. // Collect dex jar paths for the modules listed above.
if j, ok := module.(interface{ DexJar() android.Path }); ok { if j, ok := module.(interface{ DexJar() android.Path }); ok {
@@ -265,11 +294,12 @@ func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
global := dexpreoptGlobalConfig(ctx) global := dexpreoptGlobalConfig(ctx)
symbolsDir := image.symbolsDir.Join(ctx, "system/framework", arch.String()) symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String())
symbolsFile := symbolsDir.Join(ctx, image.stem+".oat") symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
outputDir := image.dir.Join(ctx, "system/framework", arch.String()) outputDir := image.dir.Join(ctx, image.installSubdir, arch.String())
outputPath := image.images[arch] outputPath := outputDir.Join(ctx, image.stem+".oat")
oatLocation := pathtools.ReplaceExtension(dexpreopt.PathToLocation(outputPath, arch), "oat") oatLocation := dexpreopt.PathToLocation(outputPath, arch)
imagePath := outputPath.ReplaceExtension(ctx, "art")
rule := android.NewRuleBuilder() rule := android.NewRuleBuilder()
rule.MissingDeps(missingDeps) rule.MissingDeps(missingDeps)
@@ -312,18 +342,27 @@ func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
cmd.FlagWithInput("--dirty-image-objects=", global.DirtyImageObjects.Path()) cmd.FlagWithInput("--dirty-image-objects=", global.DirtyImageObjects.Path())
} }
if image.extension {
artImage := artBootImageConfig(ctx).images[arch]
cmd.
Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":").
FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage)
} else {
cmd.FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress())
}
cmd. cmd.
FlagForEachInput("--dex-file=", image.dexPaths.Paths()). FlagForEachInput("--dex-file=", image.dexPaths.Paths()).
FlagForEachArg("--dex-location=", image.dexLocations). FlagForEachArg("--dex-location=", image.dexLocations).
Flag("--generate-debug-info"). Flag("--generate-debug-info").
Flag("--generate-build-id"). Flag("--generate-build-id").
Flag("--image-format=lz4hc"). Flag("--image-format=lz4hc").
FlagWithOutput("--oat-symbols=", symbolsFile). FlagWithArg("--oat-symbols=", symbolsFile.String()).
Flag("--strip"). Flag("--strip").
FlagWithOutput("--oat-file=", outputPath.ReplaceExtension(ctx, "oat")). FlagWithArg("--oat-file=", outputPath.String()).
FlagWithArg("--oat-location=", oatLocation). FlagWithArg("--oat-location=", oatLocation).
FlagWithOutput("--image=", outputPath). FlagWithArg("--image=", imagePath.String()).
FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress()).
FlagWithArg("--instruction-set=", arch.String()). FlagWithArg("--instruction-set=", arch.String()).
FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]). FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]).
FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]). FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]).
@@ -341,8 +380,8 @@ func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage)) cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage))
installDir := filepath.Join("/system/framework", arch.String()) installDir := filepath.Join("/", image.installSubdir, arch.String())
vdexInstallDir := filepath.Join("/system/framework") vdexInstallDir := filepath.Join("/", image.installSubdir)
var vdexInstalls android.RuleBuilderInstalls var vdexInstalls android.RuleBuilderInstalls
var unstrippedInstalls android.RuleBuilderInstalls var unstrippedInstalls android.RuleBuilderInstalls
@@ -425,8 +464,8 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missin
Text(`ANDROID_LOG_TAGS="*:e"`). Text(`ANDROID_LOG_TAGS="*:e"`).
Tool(tools.Profman). Tool(tools.Profman).
FlagWithInput("--create-profile-from=", bootImageProfile). FlagWithInput("--create-profile-from=", bootImageProfile).
FlagForEachInput("--apk=", image.dexPaths.Paths()). FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
FlagForEachArg("--dex-location=", image.dexLocations). FlagForEachArg("--dex-location=", image.dexLocationsDeps).
FlagWithOutput("--reference-profile-file=", profile) FlagWithOutput("--reference-profile-file=", profile)
rule.Install(profile, "/system/etc/boot-image.prof") rule.Install(profile, "/system/etc/boot-image.prof")
@@ -477,8 +516,8 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, mi
Tool(tools.Profman). Tool(tools.Profman).
Flag("--generate-boot-profile"). Flag("--generate-boot-profile").
FlagWithInput("--create-profile-from=", bootFrameworkProfile). FlagWithInput("--create-profile-from=", bootFrameworkProfile).
FlagForEachInput("--apk=", image.dexPaths.Paths()). FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
FlagForEachArg("--dex-location=", image.dexLocations). FlagForEachArg("--dex-location=", image.dexLocationsDeps).
FlagWithOutput("--reference-profile-file=", profile) FlagWithOutput("--reference-profile-file=", profile)
rule.Install(profile, "/system/etc/boot-image.bprof") rule.Install(profile, "/system/etc/boot-image.bprof")
@@ -506,8 +545,8 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImage) {
rule.Command(). rule.Command().
// TODO: for now, use the debug version for better error reporting // TODO: for now, use the debug version for better error reporting
BuiltTool(ctx, "oatdumpd"). BuiltTool(ctx, "oatdumpd").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPaths.Paths(), ":"). FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocations, ":"). FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]). FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]).
FlagWithOutput("--output=", output). FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String()) FlagWithArg("--instruction-set=", arch.String())
@@ -556,8 +595,9 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
image := d.defaultBootImage image := d.defaultBootImage
if image != nil { if image != nil {
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String()) ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPaths.Strings(), " ")) ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " "))
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocations, " ")) ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocationsDeps, " "))
ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS", strings.Join(image.imageLocations, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+image.name, image.zip.String()) ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+image.name, image.zip.String())
var imageNames []string var imageNames []string

View File

@@ -48,7 +48,7 @@ func TestDexpreoptBootJars(t *testing.T) {
pathCtx := android.PathContextForTesting(config, nil) pathCtx := android.PathContextForTesting(config, nil)
dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx) dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
dexpreoptConfig.ArtApexJars = []string{"foo", "bar", "baz"} dexpreoptConfig.BootJars = []string{"foo", "bar", "baz"}
setDexpreoptTestGlobalConfig(config, dexpreoptConfig) setDexpreoptTestGlobalConfig(config, dexpreoptConfig)
ctx := testContext(bp, nil) ctx := testContext(bp, nil)
@@ -59,9 +59,10 @@ func TestDexpreoptBootJars(t *testing.T) {
dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars") dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars")
bootArt := dexpreoptBootJars.Output("boot.art") bootArt := dexpreoptBootJars.Output("boot-foo.art")
expectedInputs := []string{ expectedInputs := []string{
"dex_artjars/apex/com.android.art/javalib/arm64/boot.art",
"dex_bootjars_input/foo.jar", "dex_bootjars_input/foo.jar",
"dex_bootjars_input/bar.jar", "dex_bootjars_input/bar.jar",
"dex_bootjars_input/baz.jar", "dex_bootjars_input/baz.jar",
@@ -82,19 +83,19 @@ func TestDexpreoptBootJars(t *testing.T) {
expectedOutputs := []string{ expectedOutputs := []string{
"dex_bootjars/system/framework/arm64/boot.invocation", "dex_bootjars/system/framework/arm64/boot.invocation",
"dex_bootjars/system/framework/arm64/boot.art", "dex_bootjars/system/framework/arm64/boot-foo.art",
"dex_bootjars/system/framework/arm64/boot-bar.art", "dex_bootjars/system/framework/arm64/boot-bar.art",
"dex_bootjars/system/framework/arm64/boot-baz.art", "dex_bootjars/system/framework/arm64/boot-baz.art",
"dex_bootjars/system/framework/arm64/boot.oat", "dex_bootjars/system/framework/arm64/boot-foo.oat",
"dex_bootjars/system/framework/arm64/boot-bar.oat", "dex_bootjars/system/framework/arm64/boot-bar.oat",
"dex_bootjars/system/framework/arm64/boot-baz.oat", "dex_bootjars/system/framework/arm64/boot-baz.oat",
"dex_bootjars/system/framework/arm64/boot.vdex", "dex_bootjars/system/framework/arm64/boot-foo.vdex",
"dex_bootjars/system/framework/arm64/boot-bar.vdex", "dex_bootjars/system/framework/arm64/boot-bar.vdex",
"dex_bootjars/system/framework/arm64/boot-baz.vdex", "dex_bootjars/system/framework/arm64/boot-baz.vdex",
"dex_bootjars_unstripped/system/framework/arm64/boot.oat", "dex_bootjars_unstripped/system/framework/arm64/boot-foo.oat",
"dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat", "dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat",
"dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat", "dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat",
} }

View File

@@ -119,118 +119,147 @@ func getJarsFromApexJarPairs(apexJarPairs []string) []string {
return modules return modules
} }
// Construct a variant of the global config for dexpreopted bootclasspath jars. The variants differ var (
// in the list of input jars (libcore, framework, or both), in the naming scheme for the dexpreopt bootImageConfigKey = android.NewOnceKey("bootImageConfig")
// files (ART recognizes "apex" names as special), and whether to include a zip archive. artBootImageName = "art"
// frameworkBootImageName = "boot"
// 'name' is a string unique for each profile (used in directory names and ninja rule names) apexBootImageName = "apex"
// 'stem' is the basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}. )
func getBootImageConfig(ctx android.PathContext, key android.OnceKey, name string, stem string,
needZip bool, artApexJarsOnly bool) bootImageConfig { // Construct the global boot image configs.
func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigKey, func() interface{} {
return ctx.Config().Once(key, func() interface{} {
global := dexpreoptGlobalConfig(ctx) global := dexpreoptGlobalConfig(ctx)
targets := dexpreoptTargets(ctx)
deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
artModules := global.ArtApexJars artModules := global.ArtApexJars
imageModules := artModules // In coverage builds ART boot class path jars are instrumented and have additional dependencies.
if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
artModules = append(artModules, "jacocoagent")
}
frameworkModules := android.RemoveListFromList(global.BootJars,
concat(artModules, getJarsFromApexJarPairs(global.UpdatableBootJars)))
var bootLocations []string artSubdir := "apex/com.android.art/javalib"
frameworkSubdir := "system/framework"
var artLocations, frameworkLocations []string
for _, m := range artModules { for _, m := range artModules {
bootLocations = append(bootLocations, artLocations = append(artLocations, filepath.Join("/"+artSubdir, stemOf(m)+".jar"))
filepath.Join("/apex/com.android.art/javalib", stemOf(m)+".jar"))
} }
if !artApexJarsOnly {
nonFrameworkModules := concat(artModules, getJarsFromApexJarPairs(global.UpdatableBootJars))
frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules)
imageModules = concat(imageModules, frameworkModules)
for _, m := range frameworkModules { for _, m := range frameworkModules {
bootLocations = append(bootLocations, frameworkLocations = append(frameworkLocations, filepath.Join("/"+frameworkSubdir, stemOf(m)+".jar"))
filepath.Join("/system/framework", stemOf(m)+".jar"))
}
} }
// The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before // ART config for the primary boot image in the ART apex.
// the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy // It includes the Core Libraries.
// them there. artCfg := bootImageConfig{
extension: false,
name: artBootImageName,
stem: "boot",
installSubdir: artSubdir,
modules: artModules,
dexLocations: artLocations,
dexLocationsDeps: artLocations,
}
// Framework config for the boot image extension.
// It includes framework libraries and depends on the ART config.
frameworkCfg := bootImageConfig{
extension: true,
name: frameworkBootImageName,
stem: "boot",
installSubdir: frameworkSubdir,
modules: frameworkModules,
dexLocations: frameworkLocations,
dexLocationsDeps: append(artLocations, frameworkLocations...),
}
// Apex config for the boot image used in the JIT-zygote experiment.
// It includes both the Core libraries and framework.
apexCfg := bootImageConfig{
extension: false,
name: apexBootImageName,
stem: "apex",
installSubdir: frameworkSubdir,
modules: concat(artModules, frameworkModules),
dexLocations: concat(artLocations, frameworkLocations),
dexLocationsDeps: concat(artLocations, frameworkLocations),
}
configs := map[string]*bootImageConfig{
artBootImageName: &artCfg,
frameworkBootImageName: &frameworkCfg,
apexBootImageName: &apexCfg,
}
// common to all configs
for _, c := range configs {
c.targets = targets
c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars")
c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped")
// expands to <stem>.art for primary image and <stem>-<1st module>.art for extension
imageName := c.firstModuleNameOrStem() + ".art"
c.imageLocations = []string{c.dir.Join(ctx, c.installSubdir, imageName).String()}
// The path to bootclasspath dex files needs to be known at module
// GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled.
// Set up known paths for them, the singleton rules will copy them there.
// TODO(b/143682396): use module dependencies instead // TODO(b/143682396): use module dependencies instead
var bootDexPaths android.WritablePaths inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input")
for _, m := range imageModules { for _, m := range c.modules {
bootDexPaths = append(bootDexPaths, c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(m)+".jar"))
android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_input", m+".jar"))
} }
c.dexPathsDeps = c.dexPaths
dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars") c.images = make(map[android.ArchType]android.OutputPath)
symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_unstripped") c.imagesDeps = make(map[android.ArchType]android.OutputPaths)
var zip android.WritablePath
if needZip {
zip = dir.Join(ctx, stem+".zip")
}
targets := dexpreoptTargets(ctx)
imageConfig := bootImageConfig{
name: name,
stem: stem,
modules: imageModules,
dexLocations: bootLocations,
dexPaths: bootDexPaths,
dir: dir,
symbolsDir: symbolsDir,
targets: targets,
images: make(map[android.ArchType]android.OutputPath),
imagesDeps: make(map[android.ArchType]android.Paths),
zip: zip,
}
for _, target := range targets { for _, target := range targets {
imageDir := dir.Join(ctx, "system/framework", target.Arch.ArchType.String()) arch := target.Arch.ArchType
imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, stem+".art") imageDir := c.dir.Join(ctx, c.installSubdir, arch.String())
c.images[arch] = imageDir.Join(ctx, imageName)
imagesDeps := make([]android.Path, 0, len(imageConfig.modules)*3) c.imagesDeps[arch] = c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex")
for _, dep := range imageConfig.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex") {
imagesDeps = append(imagesDeps, dep)
} }
imageConfig.imagesDeps[target.Arch.ArchType] = imagesDeps
} }
return imageConfig // specific to the framework config
}).(bootImageConfig) frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...)
frameworkCfg.zip = frameworkCfg.dir.Join(ctx, frameworkCfg.stem+".zip")
return configs
}).(map[string]*bootImageConfig)
} }
// Default config is the one that goes in the system image. It includes both libcore and framework.
var defaultBootImageConfigKey = android.NewOnceKey("defaultBootImageConfig")
func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
return getBootImageConfig(ctx, defaultBootImageConfigKey, "boot", "boot", true, false)
}
// Apex config is used for the JIT-zygote experiment. It includes both libcore and framework, but AOT-compiles only libcore.
var apexBootImageConfigKey = android.NewOnceKey("apexBootImageConfig")
func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
return getBootImageConfig(ctx, apexBootImageConfigKey, "apex", "apex", false, false)
}
// ART config is the one used for the ART apex. It includes only libcore.
var artBootImageConfigKey = android.NewOnceKey("artBootImageConfig")
func artBootImageConfig(ctx android.PathContext) bootImageConfig { func artBootImageConfig(ctx android.PathContext) bootImageConfig {
return getBootImageConfig(ctx, artBootImageConfigKey, "art", "boot", false, true) return *genBootImageConfigs(ctx)[artBootImageName]
}
func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
return *genBootImageConfigs(ctx)[frameworkBootImageName]
}
func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
return *genBootImageConfigs(ctx)[apexBootImageName]
} }
func defaultBootclasspath(ctx android.PathContext) []string { func defaultBootclasspath(ctx android.PathContext) []string {
return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string { return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
global := dexpreoptGlobalConfig(ctx) global := dexpreoptGlobalConfig(ctx)
image := defaultBootImageConfig(ctx) image := defaultBootImageConfig(ctx)
updatableBootclasspath := make([]string, len(global.UpdatableBootJars)) updatableBootclasspath := make([]string, len(global.UpdatableBootJars))
for i, p := range global.UpdatableBootJars { for i, p := range global.UpdatableBootJars {
updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(p) updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(p)
} }
bootclasspath := append(copyOf(image.dexLocations), updatableBootclasspath...)
bootclasspath := append(copyOf(image.dexLocationsDeps), updatableBootclasspath...)
return bootclasspath return bootclasspath
}) })
} }
@@ -245,7 +274,7 @@ func init() {
func dexpreoptConfigMakevars(ctx android.MakeVarsContext) { func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":")) ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":"))
ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocations, ":")) ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocationsDeps, ":"))
ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":")) ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":"))
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":")) ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":"))