From 036f8f5e8d384e7007619401a2a10eeb34b95992 Mon Sep 17 00:00:00 2001 From: Jeongik Cha Date: Tue, 27 Apr 2021 23:56:44 +0900 Subject: [PATCH] Add usesTargetFiles option in dexpreopt_gen For running dex2oat on the target_files, the paths should be use the device install path instead of the path starting with $(OUT). So add usesTargetFiles option and basePath option which indicates extracted path. With those options, the path is replaced with $(basePath)/$(device path) And also, add DexPreoptImageDeviceLocations in the config which refers to the boot image path(without arch) on the device. Because DexPreoptImage related device path was missing. Bug: 158843648 Test: dexpreopt_gen -usesTargetFiles -basePath (extract path) and then check if paths in the generated shell script are based on on-device path. Change-Id: I9667fadbf3b7c6f770e0d1bcbee5d67c1ecd8a3d Merged-In: I9667fadbf3b7c6f770e0d1bcbee5d67c1ecd8a3d (cherry picked from commit 4dda75e73e3e52e11b1cd37af33645fcfe5ed980) --- dexpreopt/config.go | 8 +-- dexpreopt/dexpreopt.go | 9 +++- dexpreopt/dexpreopt_gen/dexpreopt_gen.go | 68 ++++++++++++++++-------- java/dexpreopt.go | 9 ++-- java/dexpreopt_bootjars.go | 22 +++++--- java/dexpreopt_config.go | 32 ++++++----- 6 files changed, 96 insertions(+), 52 deletions(-) diff --git a/dexpreopt/config.go b/dexpreopt/config.go index 1844bce6e..7e73bf71d 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -130,9 +130,11 @@ type ModuleConfig struct { ProvidesUsesLibrary string // library name (usually the same as module name) ClassLoaderContexts ClassLoaderContextMap - Archs []android.ArchType - DexPreoptImagesDeps []android.OutputPaths - DexPreoptImageLocationsOnHost []string // boot image location on host (file path without the arch subdirectory) + Archs []android.ArchType + DexPreoptImagesDeps []android.OutputPaths + + DexPreoptImageLocationsOnHost []string // boot image location on host (file path without the arch subdirectory) + DexPreoptImageLocationsOnDevice []string // boot image location on device (file path without the arch subdirectory) PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files PreoptBootClassPathDexLocations []string // virtual locations of boot class path files diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 9d9234ff4..da015a389 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -499,11 +499,16 @@ func odexOnSystemOther(module *ModuleConfig, global *GlobalConfig) bool { // PathToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art func PathToLocation(path android.Path, arch android.ArchType) string { - pathArch := filepath.Base(filepath.Dir(path.String())) + return PathStringToLocation(path.String(), arch) +} + +// PathStringToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art +func PathStringToLocation(path string, arch android.ArchType) string { + pathArch := filepath.Base(filepath.Dir(path)) if pathArch != arch.String() { panic(fmt.Errorf("last directory in %q must be %q", path, arch.String())) } - return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String())) + return filepath.Join(filepath.Dir(filepath.Dir(path)), filepath.Base(path)) } func makefileMatch(pattern, s string) bool { diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go index 32c4f845b..7dbe74c27 100644 --- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go +++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go @@ -37,6 +37,12 @@ var ( globalConfigPath = flag.String("global", "", "path to global configuration file") moduleConfigPath = flag.String("module", "", "path to module configuration file") outDir = flag.String("out_dir", "", "path to output directory") + // If uses_target_files is true, dexpreopt_gen will be running on extracted target_files.zip files. + // In this case, the tool replace output file path with $(basePath)/$(on-device file path). + // The flag is useful when running dex2oat on system image and vendor image which are built separately. + usesTargetFiles = flag.Bool("uses_target_files", false, "whether or not dexpreopt is running on target_files") + // basePath indicates the path where target_files.zip is extracted. + basePath = flag.String("base_path", ".", "base path where images and tools are extracted") ) type builderContext struct { @@ -134,32 +140,28 @@ func main() { } } }() - + if *usesTargetFiles { + moduleConfig.ManifestPath = android.OptionalPath{} + prefix := "dex2oat_result" + moduleConfig.BuildPath = android.PathForOutput(ctx, filepath.Join(prefix, moduleConfig.DexLocation)) + for i, location := range moduleConfig.PreoptBootClassPathDexLocations { + moduleConfig.PreoptBootClassPathDexFiles[i] = android.PathForSource(ctx, *basePath+location) + } + for i := range moduleConfig.ClassLoaderContexts { + for _, v := range moduleConfig.ClassLoaderContexts[i] { + v.Host = android.PathForSource(ctx, *basePath+v.Device) + } + } + moduleConfig.EnforceUsesLibraries = false + for i, location := range moduleConfig.DexPreoptImageLocationsOnDevice { + moduleConfig.DexPreoptImageLocationsOnHost[i] = *basePath + location + } + } writeScripts(ctx, globalSoongConfig, globalConfig, moduleConfig, *dexpreoptScriptPath) } func writeScripts(ctx android.BuilderContext, globalSoong *dexpreopt.GlobalSoongConfig, global *dexpreopt.GlobalConfig, module *dexpreopt.ModuleConfig, dexpreoptScriptPath string) { - dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module) - if err != nil { - panic(err) - } - - installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install") - - dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String()) - dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String()) - - for _, install := range dexpreoptRule.Installs() { - installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/")) - dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String())) - dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath) - } - dexpreoptRule.Command().Tool(globalSoong.SoongZip). - FlagWithArg("-o ", "$2"). - FlagWithArg("-C ", installDir.String()). - FlagWithArg("-D ", installDir.String()) - write := func(rule *android.RuleBuilder, file string) { script := &bytes.Buffer{} script.WriteString(scriptHeader) @@ -195,6 +197,30 @@ func writeScripts(ctx android.BuilderContext, globalSoong *dexpreopt.GlobalSoong panic(err) } } + dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, module) + if err != nil { + panic(err) + } + // When usesTargetFiles is true, only odex/vdex files are necessary. + // So skip redunant processes(such as copying the result to the artifact path, and zipping, and so on.) + if *usesTargetFiles { + write(dexpreoptRule, dexpreoptScriptPath) + return + } + installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install") + + dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String()) + dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String()) + + for _, install := range dexpreoptRule.Installs() { + installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/")) + dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String())) + dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath) + } + dexpreoptRule.Command().Tool(globalSoong.SoongZip). + FlagWithArg("-o ", "$2"). + FlagWithArg("-C ", installDir.String()). + FlagWithArg("-D ", installDir.String()) // The written scripts will assume the input is $1 and the output is $2 if module.DexPath.String() != "$1" { diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 8d23ad6bd..2e46d74fa 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -184,7 +184,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr imagesDeps = append(imagesDeps, variant.imagesDeps) } // The image locations for all Android variants are identical. - hostImageLocations := bootImage.getAnyAndroidVariant().imageLocations() + hostImageLocations, deviceImageLocations := bootImage.getAnyAndroidVariant().imageLocations() var profileClassListing android.OptionalPath var profileBootListing android.OptionalPath @@ -224,9 +224,10 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr ProvidesUsesLibrary: providesUsesLib, ClassLoaderContexts: d.classLoaderContexts, - Archs: archs, - DexPreoptImagesDeps: imagesDeps, - DexPreoptImageLocationsOnHost: hostImageLocations, + Archs: archs, + DexPreoptImagesDeps: imagesDeps, + DexPreoptImageLocationsOnHost: hostImageLocations, + DexPreoptImageLocationsOnDevice: deviceImageLocations, PreoptBootClassPathDexFiles: dexFiles.Paths(), PreoptBootClassPathDexLocations: dexLocations, diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 07715ab87..be202c0db 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -244,6 +244,9 @@ type bootImageConfig struct { // Subdirectory where the image files are installed. installDirOnHost string + // Subdirectory where the image files on device are installed. + installDirOnDevice string + // A list of (location, jar) pairs for the Java modules in this image. modules android.ConfiguredJarList @@ -273,8 +276,9 @@ type bootImageVariant struct { dexLocationsDeps []string // for the dependency images and in this image // Paths to image files. - imagePathOnHost android.OutputPath // first image file - imagesDeps android.OutputPaths // all files + imagePathOnHost android.OutputPath // first image file path on host + imagePathOnDevice string // first image file path on device + imagesDeps android.OutputPaths // all files // Only for extensions, paths to the primary boot images. primaryImages android.OutputPath @@ -361,11 +365,12 @@ func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.Ou // The location is passed as an argument to the ART tools like dex2oat instead of the real path. // ART tools will then reconstruct the architecture-specific real path. // -func (image *bootImageVariant) imageLocations() (imageLocations []string) { +func (image *bootImageVariant) imageLocations() (imageLocationsOnHost []string, imageLocationsOnDevice []string) { if image.extends != nil { - imageLocations = image.extends.getVariant(image.target).imageLocations() + imageLocationsOnHost, imageLocationsOnDevice = image.extends.getVariant(image.target).imageLocations() } - return append(imageLocations, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType)) + return append(imageLocationsOnHost, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType)), + append(imageLocationsOnDevice, dexpreopt.PathStringToLocation(image.imagePathOnDevice, image.target.Arch.ArchType)) } func dexpreoptBootJarsFactory() android.SingletonModule { @@ -796,12 +801,13 @@ func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) { // Create a rule to call oatdump. output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt") rule := android.NewRuleBuilder(pctx, ctx) + imageLocationsOnHost, _ := image.imageLocations() rule.Command(). // TODO: for now, use the debug version for better error reporting BuiltTool("oatdumpd"). FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":"). - FlagWithArg("--image=", strings.Join(image.imageLocations(), ":")).Implicits(image.imagesDeps.Paths()). + FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()). FlagWithOutput("--output=", output). FlagWithArg("--instruction-set=", arch.String()) rule.Build("dump-oat-boot-"+suffix, "dump oat boot "+arch.String()) @@ -871,8 +877,8 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String()) ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String()) } - imageLocations := current.getAnyAndroidVariant().imageLocations() - ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocations, ":")) + imageLocationsOnHost, _ := current.getAnyAndroidVariant().imageLocations() + ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocationsOnHost, ":")) ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String()) } ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " ")) diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 7fb0444c2..37248609d 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -84,25 +84,28 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { frameworkModules := global.BootJars.RemoveList(artModules) artDirOnHost := "apex/art_boot_images/javalib" + artDirOnDevice := "apex/com.android.art/javalib" frameworkSubdir := "system/framework" // ART config for the primary boot image in the ART apex. // It includes the Core Libraries. artCfg := bootImageConfig{ - name: artBootImageName, - stem: "boot", - installDirOnHost: artDirOnHost, - modules: artModules, + name: artBootImageName, + stem: "boot", + installDirOnHost: artDirOnHost, + installDirOnDevice: artDirOnDevice, + modules: artModules, } // Framework config for the boot image extension. // It includes framework libraries and depends on the ART config. frameworkCfg := bootImageConfig{ - extends: &artCfg, - name: frameworkBootImageName, - stem: "boot", - installDirOnHost: frameworkSubdir, - modules: frameworkModules, + extends: &artCfg, + name: frameworkBootImageName, + stem: "boot", + installDirOnHost: frameworkSubdir, + installDirOnDevice: frameworkSubdir, + modules: frameworkModules, } configs := map[string]*bootImageConfig{ @@ -131,11 +134,12 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { arch := target.Arch.ArchType imageDir := c.dir.Join(ctx, target.Os.String(), c.installDirOnHost, arch.String()) variant := &bootImageVariant{ - bootImageConfig: c, - target: target, - imagePathOnHost: imageDir.Join(ctx, imageName), - imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), - dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os), + bootImageConfig: c, + target: target, + imagePathOnHost: imageDir.Join(ctx, imageName), + imagePathOnDevice: filepath.Join("/", c.installDirOnDevice, arch.String(), imageName), + imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"), + dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os), } variant.dexLocationsDeps = variant.dexLocations c.variants = append(c.variants, variant)