From 4ff85ebeb782a08ffeaefb8fbcdd678e89aec87f Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 14 Dec 2018 11:47:19 -0800 Subject: [PATCH] Revert "Dexpreopt soong modules inside soong" This reverts commit 29ff88741e710b05743dcf347484c31311e81cda. Test: none Bug: 119412419 --- Android.bp | 2 - android/config.go | 24 +- android/paths.go | 90 ++-- android/variable.go | 9 +- dexpreopt/Android.bp | 15 - dexpreopt/config.go | 141 ------ dexpreopt/dexpreopt.go | 541 ----------------------- dexpreopt/dexpreopt_gen/Android.bp | 11 - dexpreopt/dexpreopt_gen/dexpreopt_gen.go | 172 ------- dexpreopt/dexpreopt_test.go | 208 --------- dexpreopt/script.go | 173 -------- java/aar.go | 1 - java/androidmk.go | 29 +- java/app.go | 64 +-- java/builder.go | 20 - java/config/config.go | 3 - java/config/makevars.go | 1 - java/dexpreopt.go | 246 ----------- java/java.go | 45 +- java/sdk_library.go | 13 +- 20 files changed, 118 insertions(+), 1690 deletions(-) delete mode 100644 dexpreopt/Android.bp delete mode 100644 dexpreopt/config.go delete mode 100644 dexpreopt/dexpreopt.go delete mode 100644 dexpreopt/dexpreopt_gen/Android.bp delete mode 100644 dexpreopt/dexpreopt_gen/dexpreopt_gen.go delete mode 100644 dexpreopt/dexpreopt_test.go delete mode 100644 dexpreopt/script.go delete mode 100644 java/dexpreopt.go diff --git a/Android.bp b/Android.bp index 37be36cd5..76f6798cd 100644 --- a/Android.bp +++ b/Android.bp @@ -224,7 +224,6 @@ bootstrap_go_package { "soong", "soong-android", "soong-cc", - "soong-dexpreopt", "soong-genrule", "soong-java-config", "soong-tradefed", @@ -239,7 +238,6 @@ bootstrap_go_package { "java/app.go", "java/builder.go", "java/dex.go", - "java/dexpreopt.go", "java/droiddoc.go", "java/gen.go", "java/genrule.go", diff --git a/android/config.go b/android/config.go index a0954b67e..54c9da8b1 100644 --- a/android/config.go +++ b/android/config.go @@ -732,18 +732,14 @@ func (c *config) ModulesLoadedByPrivilegedModules() []string { return c.productVariables.ModulesLoadedByPrivilegedModules } +func (c *config) DefaultStripDex() bool { + return Bool(c.productVariables.DefaultStripDex) +} + func (c *config) DisableDexPreopt(name string) bool { return Bool(c.productVariables.DisableDexPreopt) || InList(name, c.productVariables.DisableDexPreoptModules) } -func (c *config) DexpreoptGlobalConfig() string { - return String(c.productVariables.DexpreoptGlobalConfig) -} - -func (c *config) DexPreoptProfileDir() string { - return String(c.productVariables.DexPreoptProfileDir) -} - func (c *deviceConfig) Arches() []Arch { var arches []Arch for _, target := range c.config.Targets[Android] { @@ -858,18 +854,6 @@ func (c *deviceConfig) PlatPrivateSepolicyDirs() []string { return c.config.productVariables.BoardPlatPrivateSepolicyDirs } -func (c *config) SecondArchIsTranslated() bool { - deviceTargets := c.Targets[Android] - if len(deviceTargets) < 2 { - return false - } - - arch := deviceTargets[0].Arch - - return (arch.ArchType == X86 || arch.ArchType == X86_64) && - (hasArmAbi(arch) || hasArmAndroidArch(deviceTargets)) -} - func (c *config) IntegerOverflowDisabledForPath(path string) bool { if c.productVariables.IntegerOverflowExcludePaths == nil { return false diff --git a/android/paths.go b/android/paths.go index 20039d4a5..b22e3c7da 100644 --- a/android/paths.go +++ b/android/paths.go @@ -659,7 +659,11 @@ func (p SourcePath) OverlayPath(ctx ModuleContext, path Path) OptionalPath { if len(paths) == 0 { return OptionalPath{} } - relPath := Rel(ctx, p.config.srcDir, paths[0]) + relPath, err := filepath.Rel(p.config.srcDir, paths[0]) + if err != nil { + reportPathError(ctx, err) + return OptionalPath{} + } return OptionalPathForPath(PathForSource(ctx, relPath)) } @@ -784,7 +788,13 @@ func (p ModuleSrcPath) resPathWithName(ctx ModuleContext, name string) ModuleRes func (p ModuleSrcPath) WithSubDir(ctx ModuleContext, subdir string) ModuleSrcPath { subdir = PathForModuleSrc(ctx, subdir).String() - p.rel = Rel(ctx, subdir, p.path) + var err error + rel, err := filepath.Rel(subdir, p.path) + if err != nil { + ctx.ModuleErrorf("source file %q is not under path %q", p.path, subdir) + return p + } + p.rel = rel return p } @@ -922,7 +932,27 @@ func PathForModuleRes(ctx ModuleContext, pathComponents ...string) ModuleResPath func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) OutputPath { var outPaths []string if ctx.Device() { - partition := modulePartition(ctx) + var partition string + if ctx.InstallInData() { + partition = "data" + } else if ctx.InstallInRecovery() { + // the layout of recovery partion is the same as that of system partition + partition = "recovery/root/system" + } else if ctx.SocSpecific() { + partition = ctx.DeviceConfig().VendorPath() + } else if ctx.DeviceSpecific() { + partition = ctx.DeviceConfig().OdmPath() + } else if ctx.ProductSpecific() { + partition = ctx.DeviceConfig().ProductPath() + } else if ctx.ProductServicesSpecific() { + partition = ctx.DeviceConfig().ProductServicesPath() + } else { + partition = "system" + } + + if ctx.InstallInSanitizerDir() { + partition = "data/asan/" + partition + } outPaths = []string{"target", "product", ctx.Config().DeviceName(), partition} } else { switch ctx.Os() { @@ -942,36 +972,6 @@ func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string return PathForOutput(ctx, outPaths...) } -func InstallPathToOnDevicePath(ctx PathContext, path OutputPath) string { - rel := Rel(ctx, PathForOutput(ctx, "target", "product", ctx.Config().DeviceName()).String(), path.String()) - - return "/" + rel -} - -func modulePartition(ctx ModuleInstallPathContext) string { - var partition string - if ctx.InstallInData() { - partition = "data" - } else if ctx.InstallInRecovery() { - // the layout of recovery partion is the same as that of system partition - partition = "recovery/root/system" - } else if ctx.SocSpecific() { - partition = ctx.DeviceConfig().VendorPath() - } else if ctx.DeviceSpecific() { - partition = ctx.DeviceConfig().OdmPath() - } else if ctx.ProductSpecific() { - partition = ctx.DeviceConfig().ProductPath() - } else if ctx.ProductServicesSpecific() { - partition = ctx.DeviceConfig().ProductServicesPath() - } else { - partition = "system" - } - if ctx.InstallInSanitizerDir() { - partition = "data/asan/" + partition - } - return partition -} - // validateSafePath validates a path that we trust (may contain ninja variables). // Ensures that each path component does not attempt to leave its component. func validateSafePath(pathComponents ...string) (string, error) { @@ -1039,27 +1039,3 @@ func PathsForTesting(strs []string) Paths { return p } - -// Rel performs the same function as filepath.Rel, but reports errors to a PathContext, and reports an error if -// targetPath is not inside basePath. -func Rel(ctx PathContext, basePath string, targetPath string) string { - rel, isRel := MaybeRel(ctx, basePath, targetPath) - if !isRel { - reportPathErrorf(ctx, "path %q is not under path %q", targetPath, basePath) - return "" - } - return rel -} - -// MaybeRel performs the same function as filepath.Rel, but reports errors to a PathContext, and returns false if -// targetPath is not inside basePath. -func MaybeRel(ctx PathContext, basePath string, targetPath string) (string, bool) { - rel, err := filepath.Rel(basePath, targetPath) - if err != nil { - reportPathError(ctx, err) - return "", false - } else if rel == ".." || strings.HasPrefix(rel, "../") || strings.HasPrefix(rel, "/") { - return "", false - } - return rel, true -} diff --git a/android/variable.go b/android/variable.go index 85937e3b1..f4960086d 100644 --- a/android/variable.go +++ b/android/variable.go @@ -196,10 +196,9 @@ type productVariables struct { UncompressPrivAppDex *bool `json:",omitempty"` ModulesLoadedByPrivilegedModules []string `json:",omitempty"` - - DisableDexPreopt *bool `json:",omitempty"` - DisableDexPreoptModules []string `json:",omitempty"` - DexPreoptProfileDir *string `json:",omitempty"` + DefaultStripDex *bool `json:",omitempty"` + DisableDexPreopt *bool `json:",omitempty"` + DisableDexPreoptModules []string `json:",omitempty"` IntegerOverflowExcludePaths *[]string `json:",omitempty"` @@ -258,8 +257,6 @@ type productVariables struct { Exclude_draft_ndk_apis *bool `json:",omitempty"` FlattenApex *bool `json:",omitempty"` - - DexpreoptGlobalConfig *string `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp deleted file mode 100644 index b83252983..000000000 --- a/dexpreopt/Android.bp +++ /dev/null @@ -1,15 +0,0 @@ -bootstrap_go_package { - name: "soong-dexpreopt", - pkgPath: "android/soong/dexpreopt", - srcs: [ - "config.go", - "dexpreopt.go", - "script.go", - ], - testSrcs: [ - "dexpreopt_test.go", - ], - deps: [ - "blueprint-pathtools", - ], -} \ No newline at end of file diff --git a/dexpreopt/config.go b/dexpreopt/config.go deleted file mode 100644 index 6a4fd4a05..000000000 --- a/dexpreopt/config.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package dexpreopt - -import ( - "encoding/json" - "io/ioutil" -) - -// GlobalConfig stores the configuration for dex preopting set by the product -type GlobalConfig struct { - DefaultNoStripping bool // don't strip dex files by default - - DisablePreoptModules []string // modules with preopt disabled by product-specific config - - OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server - - HasSystemOther bool // store odex files that match PatternsOnSystemOther on the system_other partition - PatternsOnSystemOther []string // patterns (using '%' to denote a prefix match) to put odex on the system_other partition - - DisableGenerateProfile bool // don't generate profiles - - BootJars []string // jars that form the boot image - SystemServerJars []string // jars that form the system server - SystemServerApps []string // apps that are loaded into system server - SpeedApps []string // apps that should be speed optimized - - PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified - - DefaultCompilerFilter string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags - SystemServerCompilerFilter string // default compiler filter to pass to dex2oat for system server jars - - GenerateDMFiles bool // generate Dex Metadata files - - NoDebugInfo bool // don't generate debug info by default - AlwaysSystemServerDebugInfo bool // always generate mini debug info for system server modules (overrides NoDebugInfo=true) - NeverSystemServerDebugInfo bool // never generate mini debug info for system server modules (overrides NoDebugInfo=false) - AlwaysOtherDebugInfo bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true) - NeverOtherDebugInfo bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true) - - MissingUsesLibraries []string // libraries that may be listed in OptionalUsesLibraries but will not be installed by the product - - IsEng bool // build is a eng variant - SanitizeLite bool // build is the second phase of a SANITIZE_LITE build - - DefaultAppImages bool // build app images (TODO: .art files?) by default - - Dex2oatXmx string // max heap size - Dex2oatXms string // initial heap size - - EmptyDirectory string // path to an empty directory - - DefaultDexPreoptImageLocation map[string]string // default boot image location for each architecture - CpuVariant map[string]string // cpu variant for each architecture - InstructionSetFeatures map[string]string // instruction set for each architecture - - Tools Tools // paths to tools possibly used by the generated commands -} - -// Tools contains paths to tools possibly used by the generated commands. If you add a new tool here you MUST add it -// to the order-only dependency list in DEXPREOPT_GEN_DEPS. -type Tools struct { - Profman string - Dex2oat string - Aapt string - SoongZip string - Zip2zip string - - VerifyUsesLibraries string - ConstructContext string -} - -type ModuleConfig struct { - Name string - DexLocation string // dex location on device - BuildPath string - DexPath string - PreferIntegrity bool - UncompressedDex bool - HasApkLibraries bool - PreoptFlags []string - - ProfileClassListing string - ProfileIsTextListing bool - - EnforceUsesLibraries bool - OptionalUsesLibraries []string - UsesLibraries []string - LibraryPaths map[string]string - - Archs []string - DexPreoptImageLocation string - - PreoptExtractedApk bool // Overrides OnlyPreoptModules - - NoCreateAppImage bool - ForceCreateAppImage bool - - PresignedPrebuilt bool - - StripInputPath string - StripOutputPath string -} - -func LoadGlobalConfig(path string) (GlobalConfig, error) { - config := GlobalConfig{} - err := loadConfig(path, &config) - return config, err -} - -func LoadModuleConfig(path string) (ModuleConfig, error) { - config := ModuleConfig{} - err := loadConfig(path, &config) - return config, err -} - -func loadConfig(path string, config interface{}) error { - data, err := ioutil.ReadFile(path) - if err != nil { - return err - } - - err = json.Unmarshal(data, config) - if err != nil { - return err - } - - return nil -} diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go deleted file mode 100644 index 0c2df6e5a..000000000 --- a/dexpreopt/dexpreopt.go +++ /dev/null @@ -1,541 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// The dexpreopt package converts a global dexpreopt config and a module dexpreopt config into rules to perform -// dexpreopting and to strip the dex files from the APK or JAR. -// -// It is used in two places; in the dexpeopt_gen binary for modules defined in Make, and directly linked into Soong. -// -// For Make modules it is built into the dexpreopt_gen binary, which is executed as a Make rule using global config and -// module config specified in JSON files. The binary writes out two shell scripts, only updating them if they have -// changed. One script takes an APK or JAR as an input and produces a zip file containing any outputs of preopting, -// in the location they should be on the device. The Make build rules will unzip the zip file into $(PRODUCT_OUT) when -// installing the APK, which will install the preopt outputs into $(PRODUCT_OUT)/system or $(PRODUCT_OUT)/system_other -// as necessary. The zip file may be empty if preopting was disabled for any reason. The second script takes an APK or -// JAR as an input and strips the dex files in it as necessary. -// -// The intermediate shell scripts allow changes to this package or to the global config to regenerate the shell scripts -// but only require re-executing preopting if the script has changed. -// -// For Soong modules this package is linked directly into Soong and run from the java package. It generates the same -// commands as for make, using athe same global config JSON file used by make, but using a module config structure -// provided by Soong. The generated commands are then converted into Soong rule and written directly to the ninja file, -// with no extra shell scripts involved. -package dexpreopt - -import ( - "fmt" - "path/filepath" - "strings" - - "github.com/google/blueprint/pathtools" -) - -const SystemPartition = "/system/" -const SystemOtherPartition = "/system_other/" - -// GenerateStripRule generates a set of commands that will take an APK or JAR as an input and strip the dex files if -// they are no longer necessary after preopting. -func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *Rule, err error) { - defer func() { - if r := recover(); r != nil { - if e, ok := r.(error); ok { - err = e - rule = nil - } else { - panic(r) - } - } - }() - - tools := global.Tools - - rule = &Rule{} - - strip := shouldStripDex(module, global) - - if strip { - // Only strips if the dex files are not already uncompressed - rule.Command(). - Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, module.StripInputPath). - Tool(tools.Zip2zip).FlagWithInput("-i ", module.StripInputPath).FlagWithOutput("-o ", module.StripOutputPath). - FlagWithArg("-x ", `"classes*.dex"`). - Textf(`; else cp -f %s %s; fi`, module.StripInputPath, module.StripOutputPath) - } else { - rule.Command().Text("cp -f").Input(module.StripInputPath).Output(module.StripOutputPath) - } - - return rule, nil -} - -// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a -// ModuleConfig. The produced files and their install locations will be available through rule.Installs(). -func GenerateDexpreoptRule(global GlobalConfig, module ModuleConfig) (rule *Rule, err error) { - defer func() { - if r := recover(); r != nil { - if e, ok := r.(error); ok { - err = e - rule = nil - } else { - panic(r) - } - } - }() - - rule = &Rule{} - - dexpreoptDisabled := contains(global.DisablePreoptModules, module.Name) - - if contains(global.BootJars, module.Name) { - // Don't preopt individual boot jars, they will be preopted together - dexpreoptDisabled = true - } - - // If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip - // Also preopt system server jars since selinux prevents system server from loading anything from - // /data. If we don't do this they will need to be extracted which is not favorable for RAM usage - // or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options. - if global.OnlyPreoptBootImageAndSystemServer && !contains(global.BootJars, module.Name) && - !contains(global.SystemServerJars, module.Name) && !module.PreoptExtractedApk { - dexpreoptDisabled = true - } - - generateProfile := module.ProfileClassListing != "" && !global.DisableGenerateProfile - - var profile string - if generateProfile { - profile = profileCommand(global, module, rule) - } - - if !dexpreoptDisabled { - appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) && - !module.NoCreateAppImage - - generateDM := shouldGenerateDM(module, global) - - for _, arch := range module.Archs { - imageLocation := module.DexPreoptImageLocation - if imageLocation == "" { - imageLocation = global.DefaultDexPreoptImageLocation[arch] - } - dexpreoptCommand(global, module, rule, profile, arch, imageLocation, appImage, generateDM) - } - } - - return rule, nil -} - -func profileCommand(global GlobalConfig, module ModuleConfig, rule *Rule) string { - profilePath := filepath.Join(filepath.Dir(module.BuildPath), "profile.prof") - profileInstalledPath := module.DexLocation + ".prof" - - if !module.ProfileIsTextListing { - rule.Command().FlagWithOutput("touch ", profilePath) - } - - cmd := rule.Command(). - Text(`ANDROID_LOG_TAGS="*:e"`). - Tool(global.Tools.Profman) - - if module.ProfileIsTextListing { - // The profile is a test listing of classes (used for framework jars). - // We need to generate the actual binary profile before being able to compile. - cmd.FlagWithInput("--create-profile-from=", module.ProfileClassListing) - } else { - // The profile is binary profile (used for apps). Run it through profman to - // ensure the profile keys match the apk. - cmd. - Flag("--copy-and-update-profile-key"). - FlagWithInput("--profile-file=", module.ProfileClassListing) - } - - cmd. - FlagWithInput("--apk=", module.DexPath). - Flag("--dex-location="+module.DexLocation). - FlagWithOutput("--reference-profile-file=", profilePath) - - if !module.ProfileIsTextListing { - cmd.Text(fmt.Sprintf(`|| echo "Profile out of date for %s"`, module.DexPath)) - } - rule.Install(profilePath, profileInstalledPath) - - return profilePath -} - -func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *Rule, profile, arch, bootImageLocation string, - appImage, generateDM bool) { - - // HACK: make soname in Soong-generated .odex files match Make. - base := filepath.Base(module.DexLocation) - if filepath.Ext(base) == ".jar" { - base = "javalib.jar" - } else if filepath.Ext(base) == ".apk" { - base = "package.apk" - } - - toOdexPath := func(path string) string { - return filepath.Join( - filepath.Dir(path), - "oat", - arch, - pathtools.ReplaceExtension(filepath.Base(path), "odex")) - } - - odexPath := toOdexPath(filepath.Join(filepath.Dir(module.BuildPath), base)) - odexInstallPath := toOdexPath(module.DexLocation) - if odexOnSystemOther(module, global) { - odexInstallPath = strings.Replace(odexInstallPath, SystemPartition, SystemOtherPartition, 1) - } - - vdexPath := pathtools.ReplaceExtension(odexPath, "vdex") - vdexInstallPath := pathtools.ReplaceExtension(odexInstallPath, "vdex") - - // bootImageLocation is $OUT/dex_bootjars/system/framework/boot.art, but dex2oat actually reads - // $OUT/dex_bootjars/system/framework/arm64/boot.art - var bootImagePath string - if bootImageLocation != "" { - bootImagePath = filepath.Join(filepath.Dir(bootImageLocation), arch, filepath.Base(bootImageLocation)) - } - - // Lists of used and optional libraries from the build config to be verified against the manifest in the APK - var verifyUsesLibs []string - var verifyOptionalUsesLibs []string - - // Lists of used and optional libraries from the build config, with optional libraries that are known to not - // be present in the current product removed. - var filteredUsesLibs []string - var filteredOptionalUsesLibs []string - - // The class loader context using paths in the build - var classLoaderContextHost []string - - // The class loader context using paths as they will be on the device - var classLoaderContextTarget []string - - // Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 28 - var conditionalClassLoaderContextHost []string - var conditionalClassLoaderContextTarget []string - - if module.EnforceUsesLibraries { - verifyUsesLibs = copyOf(module.UsesLibraries) - verifyOptionalUsesLibs = copyOf(module.OptionalUsesLibraries) - - filteredOptionalUsesLibs = filterOut(global.MissingUsesLibraries, module.OptionalUsesLibraries) - filteredUsesLibs = append(copyOf(module.UsesLibraries), filteredOptionalUsesLibs...) - - // Create class loader context for dex2oat from uses libraries and filtered optional libraries - for _, l := range filteredUsesLibs { - - classLoaderContextHost = append(classLoaderContextHost, - pathForLibrary(module, l)) - classLoaderContextTarget = append(classLoaderContextTarget, - filepath.Join("/system/framework", l+".jar")) - } - - const httpLegacy = "org.apache.http.legacy" - const httpLegacyImpl = "org.apache.http.legacy.impl" - - // Fix up org.apache.http.legacy.impl since it should be org.apache.http.legacy in the manifest. - replace(verifyUsesLibs, httpLegacyImpl, httpLegacy) - replace(verifyOptionalUsesLibs, httpLegacyImpl, httpLegacy) - - if !contains(verifyUsesLibs, httpLegacy) && !contains(verifyOptionalUsesLibs, httpLegacy) { - conditionalClassLoaderContextHost = append(conditionalClassLoaderContextHost, - pathForLibrary(module, httpLegacyImpl)) - conditionalClassLoaderContextTarget = append(conditionalClassLoaderContextTarget, - filepath.Join("/system/framework", httpLegacyImpl+".jar")) - } - } else { - // Pass special class loader context to skip the classpath and collision check. - // This will get removed once LOCAL_USES_LIBRARIES is enforced. - // Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default - // to the &. - classLoaderContextHost = []string{`\&`} - } - - rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath)) - rule.Command().FlagWithOutput("rm -f ", odexPath) - // Set values in the environment of the rule. These may be modified by construct_context.sh. - rule.Command().FlagWithArg("class_loader_context_arg=--class-loader-context=", - strings.Join(classLoaderContextHost, ":")) - rule.Command().Text(`stored_class_loader_context_arg=""`) - - if module.EnforceUsesLibraries { - rule.Command().FlagWithList("stored_class_loader_context_libs=", classLoaderContextTarget, ":") - rule.Command().FlagWithInputList("class_loader_context=", classLoaderContextHost, ":") - rule.Command().Textf(`uses_library_names="%s"`, strings.Join(verifyUsesLibs, " ")) - rule.Command().Textf(`optional_uses_library_names="%s"`, strings.Join(verifyOptionalUsesLibs, " ")) - rule.Command().Textf(`aapt_binary="%s"`, global.Tools.Aapt) - rule.Command().Text("source").Tool(global.Tools.VerifyUsesLibraries).Input(module.DexPath) - rule.Command().Text("source").Tool(global.Tools.ConstructContext). - Textf(`"%s"`, strings.Join(conditionalClassLoaderContextHost, ":")). - Textf(`"%s"`, strings.Join(conditionalClassLoaderContextTarget, ":")) - } - - cmd := rule.Command(). - Text(`ANDROID_LOG_TAGS="*:e"`). - Tool(global.Tools.Dex2oat). - Flag("--avoid-storing-invocation"). - Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatXms). - Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatXmx). - Flag("${class_loader_context_arg}"). - Flag("${stored_class_loader_context_arg}"). - FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImagePath). - FlagWithInput("--dex-file=", module.DexPath). - FlagWithArg("--dex-location=", module.DexLocation). - FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath). - // Pass an empty directory, dex2oat shouldn't be reading arbitrary files - FlagWithArg("--android-root=", global.EmptyDirectory). - FlagWithArg("--instruction-set=", arch). - FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]). - FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]). - Flag("--no-generate-debug-info"). - Flag("--generate-build-id"). - Flag("--abort-on-hard-verifier-error"). - Flag("--force-determinism"). - FlagWithArg("--no-inline-from=", "core-oj.jar") - - var preoptFlags []string - if len(module.PreoptFlags) > 0 { - preoptFlags = module.PreoptFlags - } else if len(global.PreoptFlags) > 0 { - preoptFlags = global.PreoptFlags - } - - if len(preoptFlags) > 0 { - cmd.Text(strings.Join(preoptFlags, " ")) - } - - if module.UncompressedDex { - cmd.FlagWithArg("--copy-dex-files=", "false") - } - - if !anyHavePrefix(preoptFlags, "--compiler-filter=") { - var compilerFilter string - if contains(global.SystemServerJars, module.Name) { - // Jars of system server, use the product option if it is set, speed otherwise. - if global.SystemServerCompilerFilter != "" { - compilerFilter = global.SystemServerCompilerFilter - } else { - compilerFilter = "speed" - } - } else if contains(global.SpeedApps, module.Name) || contains(global.SystemServerApps, module.Name) { - // Apps loaded into system server, and apps the product default to being compiled with the - // 'speed' compiler filter. - compilerFilter = "speed" - } else if profile != "" { - // For non system server jars, use speed-profile when we have a profile. - compilerFilter = "speed-profile" - } else if global.DefaultCompilerFilter != "" { - compilerFilter = global.DefaultCompilerFilter - } else { - compilerFilter = "quicken" - } - cmd.FlagWithArg("--compiler-filter=", compilerFilter) - } - - if generateDM { - cmd.FlagWithArg("--copy-dex-files=", "false") - dmPath := filepath.Join(filepath.Dir(module.BuildPath), "generated.dm") - dmInstalledPath := pathtools.ReplaceExtension(module.DexLocation, "dm") - tmpPath := filepath.Join(filepath.Dir(module.BuildPath), "primary.vdex") - rule.Command().Text("cp -f").Input(vdexPath).Output(tmpPath) - rule.Command().Tool(global.Tools.SoongZip). - FlagWithArg("-L", "9"). - FlagWithOutput("-o", dmPath). - Flag("-j"). - Input(tmpPath) - rule.Install(dmPath, dmInstalledPath) - } - - // By default, emit debug info. - debugInfo := true - if global.NoDebugInfo { - // If the global setting suppresses mini-debug-info, disable it. - debugInfo = false - } - - // PRODUCT_SYSTEM_SERVER_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO. - // PRODUCT_OTHER_JAVA_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO. - if contains(global.SystemServerJars, module.Name) { - if global.AlwaysSystemServerDebugInfo { - debugInfo = true - } else if global.NeverSystemServerDebugInfo { - debugInfo = false - } - } else { - if global.AlwaysOtherDebugInfo { - debugInfo = true - } else if global.NeverOtherDebugInfo { - debugInfo = false - } - } - - // Never enable on eng. - if global.IsEng { - debugInfo = false - } - - if debugInfo { - cmd.Flag("--generate-mini-debug-info") - } else { - cmd.Flag("--no-generate-mini-debug-info") - } - - // Set the compiler reason to 'prebuilt' to identify the oat files produced - // during the build, as opposed to compiled on the device. - cmd.FlagWithArg("--compilation-reason=", "prebuilt") - - if appImage { - appImagePath := pathtools.ReplaceExtension(odexPath, "art") - appImageInstallPath := pathtools.ReplaceExtension(odexInstallPath, "art") - cmd.FlagWithOutput("--app-image-file=", appImagePath). - FlagWithArg("--image-format=", "lz4") - rule.Install(appImagePath, appImageInstallPath) - } - - if profile != "" { - cmd.FlagWithArg("--profile-file=", profile) - } - - rule.Install(odexPath, odexInstallPath) - rule.Install(vdexPath, vdexInstallPath) -} - -// Return if the dex file in the APK should be stripped. If an APK is found to contain uncompressed dex files at -// dex2oat time it will not be stripped even if strip=true. -func shouldStripDex(module ModuleConfig, global GlobalConfig) bool { - strip := !global.DefaultNoStripping - - // Don't strip modules that are not on the system partition in case the oat/vdex version in system ROM - // doesn't match the one in other partitions. It needs to be able to fall back to the APK for that case. - if !strings.HasPrefix(module.DexLocation, SystemPartition) { - strip = false - } - - // system_other isn't there for an OTA, so don't strip if module is on system, and odex is on system_other. - if odexOnSystemOther(module, global) { - strip = false - } - - if module.HasApkLibraries { - strip = false - } - - // Don't strip with dex files we explicitly uncompress (dexopt will not store the dex code). - if module.UncompressedDex { - strip = false - } - - if shouldGenerateDM(module, global) { - strip = false - } - - if module.PresignedPrebuilt { - // Only strip out files if we can re-sign the package. - strip = false - } - - return strip -} - -func shouldGenerateDM(module ModuleConfig, global GlobalConfig) bool { - // Generating DM files only makes sense for verify, avoid doing for non verify compiler filter APKs. - // No reason to use a dm file if the dex is already uncompressed. - return global.GenerateDMFiles && !module.UncompressedDex && - contains(module.PreoptFlags, "--compiler-filter=verify") -} - -func odexOnSystemOther(module ModuleConfig, global GlobalConfig) bool { - if !global.HasSystemOther { - return false - } - - if global.SanitizeLite { - return false - } - - if contains(global.SpeedApps, module.Name) || contains(global.SystemServerApps, module.Name) { - return false - } - - for _, f := range global.PatternsOnSystemOther { - if makefileMatch(filepath.Join(SystemPartition, f), module.DexLocation) { - return true - } - } - - return false -} - -func pathForLibrary(module ModuleConfig, lib string) string { - path := module.LibraryPaths[lib] - if path == "" { - panic(fmt.Errorf("unknown library path for %q", lib)) - } - return path -} - -func makefileMatch(pattern, s string) bool { - percent := strings.IndexByte(pattern, '%') - switch percent { - case -1: - return pattern == s - case len(pattern) - 1: - return strings.HasPrefix(s, pattern[:len(pattern)-1]) - default: - panic(fmt.Errorf("unsupported makefile pattern %q", pattern)) - } -} - -func contains(l []string, s string) bool { - for _, e := range l { - if e == s { - return true - } - } - return false -} - -// remove all elements in a from b, returning a new slice -func filterOut(a []string, b []string) []string { - var ret []string - for _, x := range b { - if !contains(a, x) { - ret = append(ret, x) - } - } - return ret -} - -func replace(l []string, from, to string) { - for i := range l { - if l[i] == from { - l[i] = to - } - } -} - -func copyOf(l []string) []string { - return append([]string(nil), l...) -} - -func anyHavePrefix(l []string, prefix string) bool { - for _, x := range l { - if strings.HasPrefix(x, prefix) { - return true - } - } - return false -} diff --git a/dexpreopt/dexpreopt_gen/Android.bp b/dexpreopt/dexpreopt_gen/Android.bp deleted file mode 100644 index 07903910e..000000000 --- a/dexpreopt/dexpreopt_gen/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -blueprint_go_binary { - name: "dexpreopt_gen", - srcs: [ - "dexpreopt_gen.go", - ], - deps: [ - "soong-dexpreopt", - "blueprint-pathtools", - "blueprint-proptools", - ], -} \ No newline at end of file diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go deleted file mode 100644 index d541c7017..000000000 --- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "bytes" - "flag" - "fmt" - "os" - "path/filepath" - "runtime" - - "android/soong/dexpreopt" - - "github.com/google/blueprint/pathtools" - "github.com/google/blueprint/proptools" -) - -var ( - extrasOutputPath = flag.String("extras_zip", "", "path to output zip file of extra files") - dexpreoptScriptPath = flag.String("dexpreopt_script", "", "path to output dexpreopt script") - stripScriptPath = flag.String("strip_script", "", "path to output strip script") - globalConfigPath = flag.String("global", "", "path to global configuration file") - moduleConfigPath = flag.String("module", "", "path to module configuration file") -) - -func main() { - flag.Parse() - - usage := func(err string) { - if err != "" { - fmt.Println(err) - flag.Usage() - os.Exit(1) - } - } - - if flag.NArg() > 0 { - usage("unrecognized argument " + flag.Arg(0)) - } - - if *dexpreoptScriptPath == "" { - usage("path to output dexpreopt script is required") - } - - if *stripScriptPath == "" { - usage("path to output strip script is required") - } - - if *globalConfigPath == "" { - usage("path to global configuration file is required") - } - - if *moduleConfigPath == "" { - usage("path to module configuration file is required") - } - - globalConfig, err := dexpreopt.LoadGlobalConfig(*globalConfigPath) - if err != nil { - fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err) - os.Exit(2) - } - - moduleConfig, err := dexpreopt.LoadModuleConfig(*moduleConfigPath) - if err != nil { - fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err) - os.Exit(2) - } - - defer func() { - if r := recover(); r != nil { - switch x := r.(type) { - case runtime.Error: - panic(x) - case error: - fmt.Fprintln(os.Stderr, "error:", r) - os.Exit(3) - default: - panic(x) - } - } - }() - - writeScripts(globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath, *extrasOutputPath) -} - -func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig, - dexpreoptScriptPath, stripScriptPath, extrasOutputPath string) { - dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(global, module) - if err != nil { - panic(err) - } - - installDir := filepath.Join(filepath.Dir(module.BuildPath), "dexpreopt_install") - - dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir) - - for _, install := range dexpreoptRule.Installs() { - installPath := filepath.Join(installDir, install.To) - dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath)) - dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath) - } - dexpreoptRule.Command().Tool(global.Tools.SoongZip). - FlagWithOutput("-o ", extrasOutputPath). - FlagWithArg("-C ", installDir). - FlagWithArg("-D ", installDir) - - stripRule, err := dexpreopt.GenerateStripRule(global, module) - if err != nil { - panic(err) - } - - write := func(rule *dexpreopt.Rule, file, output string) { - script := &bytes.Buffer{} - script.WriteString(scriptHeader) - for _, c := range rule.Commands() { - script.WriteString(c) - script.WriteString("\n\n") - } - - depFile := &bytes.Buffer{} - fmt.Fprintf(depFile, "%s: \\\n", output) - for _, tool := range dexpreoptRule.Tools() { - fmt.Fprintf(depFile, " %s \\\n", tool) - } - for _, input := range dexpreoptRule.Inputs() { - fmt.Fprintf(depFile, " %s \\\n", input) - } - depFile.WriteString("\n") - - fmt.Fprintf(script, `/bin/bash -c 'echo -e $0 > %s' %s\n`, - output+".d", proptools.ShellEscape([]string{depFile.String()})[0]) - - err := pathtools.WriteFileIfChanged(file, script.Bytes(), 0755) - if err != nil { - panic(err) - } - } - - write(dexpreoptRule, dexpreoptScriptPath, extrasOutputPath) - write(stripRule, stripScriptPath, module.StripOutputPath) -} - -const scriptHeader = `#!/bin/bash - -err() { - errno=$? - echo "error: $0:$1 exited with status $errno" >&2 - echo "error in command:" >&2 - sed -n -e "$1p" $0 >&2 - if [ "$errno" -ne 0 ]; then - exit $errno - else - exit 1 - fi -} - -trap 'err $LINENO' ERR - -` diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go deleted file mode 100644 index 526524815..000000000 --- a/dexpreopt/dexpreopt_test.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package dexpreopt - -import ( - "reflect" - "strings" - "testing" -) - -var testGlobalConfig = GlobalConfig{ - DefaultNoStripping: false, - DisablePreoptModules: nil, - OnlyPreoptBootImageAndSystemServer: false, - HasSystemOther: false, - PatternsOnSystemOther: nil, - DisableGenerateProfile: false, - BootJars: nil, - SystemServerJars: nil, - SystemServerApps: nil, - SpeedApps: nil, - PreoptFlags: nil, - DefaultCompilerFilter: "", - SystemServerCompilerFilter: "", - GenerateDMFiles: false, - NoDebugInfo: false, - AlwaysSystemServerDebugInfo: false, - NeverSystemServerDebugInfo: false, - AlwaysOtherDebugInfo: false, - NeverOtherDebugInfo: false, - MissingUsesLibraries: nil, - IsEng: false, - SanitizeLite: false, - DefaultAppImages: false, - Dex2oatXmx: "", - Dex2oatXms: "", - EmptyDirectory: "", - DefaultDexPreoptImageLocation: nil, - CpuVariant: nil, - InstructionSetFeatures: nil, - Tools: Tools{ - Profman: "profman", - Dex2oat: "dex2oat", - Aapt: "aapt", - SoongZip: "soong_zip", - Zip2zip: "zip2zip", - VerifyUsesLibraries: "verify_uses_libraries.sh", - ConstructContext: "construct_context.sh", - }, -} - -var testModuleConfig = ModuleConfig{ - Name: "", - DexLocation: "", - BuildPath: "", - DexPath: "", - PreferIntegrity: false, - UncompressedDex: false, - HasApkLibraries: false, - PreoptFlags: nil, - ProfileClassListing: "", - ProfileIsTextListing: false, - EnforceUsesLibraries: false, - OptionalUsesLibraries: nil, - UsesLibraries: nil, - LibraryPaths: nil, - Archs: nil, - DexPreoptImageLocation: "", - PreoptExtractedApk: false, - NoCreateAppImage: false, - ForceCreateAppImage: false, - PresignedPrebuilt: false, - StripInputPath: "", - StripOutputPath: "", -} - -func TestDexPreopt(t *testing.T) { - global, module := testGlobalConfig, testModuleConfig - - module.Name = "test" - module.DexLocation = "/system/app/test/test.apk" - module.BuildPath = "out/test/test.apk" - module.Archs = []string{"arm"} - - rule, err := GenerateDexpreoptRule(global, module) - if err != nil { - t.Error(err) - } - - wantInstalls := []Install{ - {"out/test/oat/arm/package.odex", "/system/app/test/oat/arm/test.odex"}, - {"out/test/oat/arm/package.vdex", "/system/app/test/oat/arm/test.vdex"}, - } - - if !reflect.DeepEqual(rule.Installs(), wantInstalls) { - t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs()) - } -} - -func TestDexPreoptSystemOther(t *testing.T) { - global, module := testGlobalConfig, testModuleConfig - - global.HasSystemOther = true - global.PatternsOnSystemOther = []string{"app/%"} - - module.Name = "test" - module.DexLocation = "/system/app/test/test.apk" - module.BuildPath = "out/test/test.apk" - module.Archs = []string{"arm"} - - rule, err := GenerateDexpreoptRule(global, module) - if err != nil { - t.Error(err) - } - - wantInstalls := []Install{ - {"out/test/oat/arm/package.odex", "/system_other/app/test/oat/arm/test.odex"}, - {"out/test/oat/arm/package.vdex", "/system_other/app/test/oat/arm/test.vdex"}, - } - - if !reflect.DeepEqual(rule.Installs(), wantInstalls) { - t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs()) - } -} - -func TestDexPreoptProfile(t *testing.T) { - global, module := testGlobalConfig, testModuleConfig - - module.Name = "test" - module.DexLocation = "/system/app/test/test.apk" - module.BuildPath = "out/test/test.apk" - module.ProfileClassListing = "profile" - module.Archs = []string{"arm"} - - rule, err := GenerateDexpreoptRule(global, module) - if err != nil { - t.Error(err) - } - - wantInstalls := []Install{ - {"out/test/profile.prof", "/system/app/test/test.apk.prof"}, - {"out/test/oat/arm/package.art", "/system/app/test/oat/arm/test.art"}, - {"out/test/oat/arm/package.odex", "/system/app/test/oat/arm/test.odex"}, - {"out/test/oat/arm/package.vdex", "/system/app/test/oat/arm/test.vdex"}, - } - - if !reflect.DeepEqual(rule.Installs(), wantInstalls) { - t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs()) - } -} - -func TestStripDex(t *testing.T) { - global, module := testGlobalConfig, testModuleConfig - - module.Name = "test" - module.DexLocation = "/system/app/test/test.apk" - module.BuildPath = "out/test/test.apk" - module.Archs = []string{"arm"} - module.StripInputPath = "$1" - module.StripOutputPath = "$2" - - rule, err := GenerateStripRule(global, module) - if err != nil { - t.Error(err) - } - - want := `zip2zip -i $1 -o $2 -x "classes*.dex"` - if len(rule.Commands()) < 1 || !strings.Contains(rule.Commands()[0], want) { - t.Errorf("\nwant commands[0] to have:\n %v\ngot:\n %v", want, rule.Commands()[0]) - } -} - -func TestNoStripDex(t *testing.T) { - global, module := testGlobalConfig, testModuleConfig - - global.DefaultNoStripping = true - - module.Name = "test" - module.DexLocation = "/system/app/test/test.apk" - module.BuildPath = "out/test/test.apk" - module.Archs = []string{"arm"} - module.StripInputPath = "$1" - module.StripOutputPath = "$2" - - rule, err := GenerateStripRule(global, module) - if err != nil { - t.Error(err) - } - - wantCommands := []string{ - "cp -f $1 $2", - } - if !reflect.DeepEqual(rule.Commands(), wantCommands) { - t.Errorf("\nwant commands:\n %v\ngot:\n %v", wantCommands, rule.Commands()) - } -} diff --git a/dexpreopt/script.go b/dexpreopt/script.go deleted file mode 100644 index fd4cf823e..000000000 --- a/dexpreopt/script.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package dexpreopt - -import ( - "fmt" - "sort" - "strings" -) - -type Install struct { - From, To string -} - -type Rule struct { - commands []*Command - installs []Install -} - -func (r *Rule) Install(from, to string) { - r.installs = append(r.installs, Install{from, to}) -} - -func (r *Rule) Command() *Command { - command := &Command{} - r.commands = append(r.commands, command) - return command -} - -func (r *Rule) Inputs() []string { - outputs := r.outputSet() - - inputs := make(map[string]bool) - for _, c := range r.commands { - for _, input := range c.inputs { - if !outputs[input] { - inputs[input] = true - } - } - } - - var inputList []string - for input := range inputs { - inputList = append(inputList, input) - } - sort.Strings(inputList) - - return inputList -} - -func (r *Rule) outputSet() map[string]bool { - outputs := make(map[string]bool) - for _, c := range r.commands { - for _, output := range c.outputs { - outputs[output] = true - } - } - return outputs -} - -func (r *Rule) Outputs() []string { - outputs := r.outputSet() - - var outputList []string - for output := range outputs { - outputList = append(outputList, output) - } - sort.Strings(outputList) - return outputList -} - -func (r *Rule) Installs() []Install { - return append([]Install(nil), r.installs...) -} - -func (r *Rule) Tools() []string { - var tools []string - for _, c := range r.commands { - tools = append(tools, c.tools...) - } - return tools -} - -func (r *Rule) Commands() []string { - var commands []string - for _, c := range r.commands { - commands = append(commands, string(c.buf)) - } - return commands -} - -type Command struct { - buf []byte - inputs []string - outputs []string - tools []string -} - -func (c *Command) Text(text string) *Command { - if len(c.buf) > 0 { - c.buf = append(c.buf, ' ') - } - c.buf = append(c.buf, text...) - return c -} - -func (c *Command) Textf(format string, a ...interface{}) *Command { - return c.Text(fmt.Sprintf(format, a...)) -} - -func (c *Command) Flag(flag string) *Command { - return c.Text(flag) -} - -func (c *Command) FlagWithArg(flag, arg string) *Command { - return c.Text(flag + arg) -} - -func (c *Command) FlagWithList(flag string, list []string, sep string) *Command { - return c.Text(flag + strings.Join(list, sep)) -} - -func (c *Command) Tool(path string) *Command { - c.tools = append(c.tools, path) - return c.Text(path) -} - -func (c *Command) Input(path string) *Command { - c.inputs = append(c.inputs, path) - return c.Text(path) -} - -func (c *Command) Implicit(path string) *Command { - c.inputs = append(c.inputs, path) - return c -} - -func (c *Command) Output(path string) *Command { - c.outputs = append(c.outputs, path) - return c.Text(path) -} - -func (c *Command) ImplicitOutput(path string) *Command { - c.outputs = append(c.outputs, path) - return c -} - -func (c *Command) FlagWithInput(flag, path string) *Command { - c.inputs = append(c.inputs, path) - return c.Text(flag + path) -} - -func (c *Command) FlagWithInputList(flag string, paths []string, sep string) *Command { - c.inputs = append(c.inputs, paths...) - return c.FlagWithList(flag, paths, sep) -} - -func (c *Command) FlagWithOutput(flag, path string) *Command { - c.outputs = append(c.outputs, path) - return c.Text(flag + path) -} diff --git a/java/aar.go b/java/aar.go index 89517fede..99e9136d8 100644 --- a/java/aar.go +++ b/java/aar.go @@ -357,7 +357,6 @@ func AndroidLibraryFactory() android.Module { module.AddProperties( &module.Module.properties, &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, &module.Module.protoProperties, &module.aaptProperties, &module.androidLibraryProperties) diff --git a/java/androidmk.go b/java/androidmk.go index 70d0f7f98..0700b5873 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -25,7 +25,7 @@ import ( func (library *Library) AndroidMk() android.AndroidMkData { return android.AndroidMkData{ Class: "JAVA_LIBRARIES", - OutputFile: android.OptionalPathForPath(library.outputFile), + OutputFile: android.OptionalPathForPath(library.implementationAndResourcesJar), Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", Extra: []android.AndroidMkExtraFunc{ func(w io.Writer, outputFile android.Path) { @@ -42,12 +42,21 @@ func (library *Library) AndroidMk() android.AndroidMkData { } if library.dexJarFile != nil { fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", library.dexJarFile.String()) - } - if len(library.dexpreopter.builtInstalled) > 0 { - fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", strings.Join(library.dexpreopter.builtInstalled, " ")) + if library.deviceProperties.Dex_preopt.Enabled != nil { + fmt.Fprintln(w, "LOCAL_DEX_PREOPT :=", *library.deviceProperties.Dex_preopt.Enabled) + } + if library.deviceProperties.Dex_preopt.App_image != nil { + fmt.Fprintln(w, "LOCAL_DEX_PREOPT_APP_IMAGE :=", *library.deviceProperties.Dex_preopt.App_image) + } + if library.deviceProperties.Dex_preopt.Profile_guided != nil { + fmt.Fprintln(w, "LOCAL_DEX_PREOPT_GENERATE_PROFILE :=", *library.deviceProperties.Dex_preopt.Profile_guided) + } + if library.deviceProperties.Dex_preopt.Profile != nil { + fmt.Fprintln(w, "LOCAL_DEX_PREOPT_GENERATE_PROFILE := true") + fmt.Fprintln(w, "LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING := $(LOCAL_PATH)/"+*library.deviceProperties.Dex_preopt.Profile) + } } fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", library.sdkVersion()) - fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", library.implementationAndResourcesJar.String()) fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String()) if library.jacocoReportClassesFile != nil { @@ -75,6 +84,7 @@ func (library *Library) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_MODULE := "+name+"-hostdex") fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true") fmt.Fprintln(w, "LOCAL_MODULE_CLASS := JAVA_LIBRARIES") + fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", library.implementationAndResourcesJar.String()) if library.installFile == nil { fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true") } @@ -82,7 +92,6 @@ func (library *Library) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", library.dexJarFile.String()) } fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String()) - fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", library.implementationAndResourcesJar.String()) fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+strings.Join(data.Required, " ")) fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk") } @@ -119,7 +128,6 @@ func (prebuilt *Import) AndroidMk() android.AndroidMkData { func(w io.Writer, outputFile android.Path) { fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := ", !Bool(prebuilt.properties.Installable)) fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.combinedClasspathFile.String()) - fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", prebuilt.combinedClasspathFile.String()) fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", prebuilt.sdkVersion()) }, }, @@ -134,8 +142,8 @@ func (prebuilt *AARImport) AndroidMk() android.AndroidMkData { Extra: []android.AndroidMkExtraFunc{ func(w io.Writer, outputFile android.Path) { fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true") + fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false") fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.classpathFile.String()) - fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", prebuilt.classpathFile.String()) fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", prebuilt.exportPackage.String()) fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=", prebuilt.proguardFlags.String()) fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", prebuilt.extraAaptPackagesFile.String()) @@ -156,7 +164,6 @@ func (binary *Binary) AndroidMk() android.AndroidMkData { Extra: []android.AndroidMkExtraFunc{ func(w io.Writer, outputFile android.Path) { fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", binary.headerJarFile.String()) - fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", binary.implementationAndResourcesJar.String()) }, }, Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { @@ -243,9 +250,6 @@ func (app *AndroidApp) AndroidMk() android.AndroidMkData { for _, jniLib := range app.installJniLibs { fmt.Fprintln(w, "LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), "+=", jniLib.name) } - if len(app.dexpreopter.builtInstalled) > 0 { - fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", strings.Join(app.dexpreopter.builtInstalled, " ")) - } }, }, } @@ -309,6 +313,7 @@ func (a *AndroidLibrary) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=", strings.Join(a.exportedProguardFlagFiles.Strings(), " ")) fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true") + fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false") }) return data diff --git a/java/app.go b/java/app.go index b44fc3448..392ad3fc8 100644 --- a/java/app.go +++ b/java/app.go @@ -17,7 +17,6 @@ package java // This file contains the module types for compiling Android apps. import ( - "path/filepath" "strings" "github.com/google/blueprint" @@ -70,6 +69,7 @@ type appProperties struct { AllowDexPreopt bool `blueprint:"mutated"` EmbedJNI bool `blueprint:"mutated"` + StripDex bool `blueprint:"mutated"` } type AndroidApp struct { @@ -143,16 +143,42 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.generateAndroidBuildActions(ctx) } -// Returns whether this module should have the dex file stored uncompressed in the APK. -func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool { +// Returns whether this module should have the dex file stored uncompressed in the APK, or stripped completely. If +// stripped, the code will still be present on the device in the dexpreopted files. +// This is only necessary for APKs, and not jars, because APKs are signed and the dex file should not be uncompressed +// or removed after the signature has been generated. For jars, which are not signed, the dex file is uncompressed +// or removed at installation time in Make. +func (a *AndroidApp) uncompressOrStripDex(ctx android.ModuleContext) (uncompress, strip bool) { if ctx.Config().UnbundledBuild() { - return false + return false, false } + strip = ctx.Config().DefaultStripDex() + // TODO(ccross): don't strip dex installed on partitions that may be updated separately (like vendor) + // TODO(ccross): don't strip dex on modules with LOCAL_APK_LIBRARIES equivalent + // Uncompress dex in APKs of privileged apps, and modules used by privileged apps. - return ctx.Config().UncompressPrivAppDex() && + if ctx.Config().UncompressPrivAppDex() && (Bool(a.appProperties.Privileged) || - inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules())) + inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules())) { + + uncompress = true + // If the dex files is store uncompressed, don't strip it, we will reuse the uncompressed dex from the APK + // instead of copying it into the odex file. + strip = false + } + + // If dexpreopt is disabled, don't strip the dex file + if !a.appProperties.AllowDexPreopt || + !BoolDefault(a.deviceProperties.Dex_preopt.Enabled, true) || + ctx.Config().DisableDexPreopt(ctx.ModuleName()) { + strip = false + } + + // TODO(ccross): strip dexpropted modules that are not propted to system_other + strip = false + + return uncompress, strip } func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { @@ -202,25 +228,16 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...) a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile) - a.deviceProperties.UncompressDex = a.shouldUncompressDex(ctx) - - var installDir string - if ctx.ModuleName() == "framework-res" { - // framework-res.apk is installed as system/framework/framework-res.apk - installDir = "framework" - } else if Bool(a.appProperties.Privileged) { - installDir = filepath.Join("priv-app", ctx.ModuleName()) - } else { - installDir = filepath.Join("app", ctx.ModuleName()) - } - a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, ctx.ModuleName()+".apk") - a.dexpreopter.isPrivApp = Bool(a.appProperties.Privileged) + a.deviceProperties.UncompressDex, a.appProperties.StripDex = a.uncompressOrStripDex(ctx) if ctx.ModuleName() != "framework-res" { a.Module.compile(ctx, a.aaptSrcJar) } + dexJarFile := a.dexJarFile - dexJarFile := a.maybeStrippedDexJarFile + if a.appProperties.StripDex { + dexJarFile = nil + } var certificates []Certificate @@ -270,9 +287,9 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { // framework-res.apk is installed as system/framework/framework-res.apk ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".apk", a.outputFile) } else if Bool(a.appProperties.Privileged) { - ctx.InstallFile(android.PathForModuleInstall(ctx, "priv-app", ctx.ModuleName()), ctx.ModuleName()+".apk", a.outputFile) + ctx.InstallFile(android.PathForModuleInstall(ctx, "priv-app"), ctx.ModuleName()+".apk", a.outputFile) } else { - ctx.InstallFile(android.PathForModuleInstall(ctx, "app", ctx.ModuleName()), ctx.ModuleName()+".apk", a.outputFile) + ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile) } } @@ -325,7 +342,6 @@ func AndroidAppFactory() android.Module { module.AddProperties( &module.Module.properties, &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, &module.Module.protoProperties, &module.aaptProperties, &module.appProperties) @@ -388,7 +404,6 @@ func AndroidTestFactory() android.Module { module.AddProperties( &module.Module.properties, &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, &module.Module.protoProperties, &module.aaptProperties, &module.appProperties, @@ -424,7 +439,6 @@ func AndroidTestHelperAppFactory() android.Module { module.AddProperties( &module.Module.properties, &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, &module.Module.protoProperties, &module.aaptProperties, &module.appProperties, diff --git a/java/builder.go b/java/builder.go index 861566495..cefb916df 100644 --- a/java/builder.go +++ b/java/builder.go @@ -138,17 +138,6 @@ var ( CommandDeps: []string{"${config.JavaCmd}", "${config.JetifierJar}"}, }, ) - - zipalign = pctx.AndroidStaticRule("zipalign", - blueprint.RuleParams{ - Command: "if ! ${config.ZipAlign} -c 4 $in > /dev/null; then " + - "${config.ZipAlign} -f 4 $in $out; " + - "else " + - "cp -f $in $out; " + - "fi", - CommandDeps: []string{"${config.ZipAlign}"}, - }, - ) ) func init() { @@ -421,15 +410,6 @@ func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.Wri }) } -func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) { - ctx.Build(pctx, android.BuildParams{ - Rule: zipalign, - Description: "align", - Input: inputFile, - Output: outputFile, - }) -} - type classpath []android.Path func (x *classpath) FormJavaClassPath(optName string) string { diff --git a/java/config/config.go b/java/config/config.go index da4eed7be..d2a8c4672 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -126,7 +126,6 @@ func init() { pctx.HostJavaToolVariable("JetifierJar", "jetifier.jar") pctx.HostBinToolVariable("SoongJavacWrapper", "soong_javac_wrapper") - pctx.HostBinToolVariable("DexpreoptGen", "dexpreopt_gen") pctx.VariableFunc("JavacWrapper", func(ctx android.PackageVarContext) string { if override := ctx.Config().Getenv("JAVAC_WRAPPER"); override != "" { @@ -153,6 +152,4 @@ func init() { pctx.SourcePathsVariable("ManifestMergerJars", " ", ManifestMergerClasspath...) pctx.SourcePathsVariable("ManifestMergerClasspath", ":", ManifestMergerClasspath...) - - pctx.HostBinToolVariable("ZipAlign", "zipalign") } diff --git a/java/config/makevars.go b/java/config/makevars.go index 01adaa7d1..275f4966e 100644 --- a/java/config/makevars.go +++ b/java/config/makevars.go @@ -65,7 +65,6 @@ func makeVarsProvider(ctx android.MakeVarsContext) { ctx.Strict("JMOD", "${JmodCmd}") ctx.Strict("SOONG_JAVAC_WRAPPER", "${SoongJavacWrapper}") - ctx.Strict("DEXPREOPT_GEN", "${DexpreoptGen}") ctx.Strict("ZIPSYNC", "${ZipSyncCmd}") ctx.Strict("JACOCO_CLI_JAR", "${JacocoCLIJar}") diff --git a/java/dexpreopt.go b/java/dexpreopt.go deleted file mode 100644 index 3ee1205e6..000000000 --- a/java/dexpreopt.go +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package java - -import ( - "path/filepath" - "strings" - - "github.com/google/blueprint" - "github.com/google/blueprint/proptools" - - "android/soong/android" - "android/soong/dexpreopt" -) - -type dexpreopter struct { - dexpreoptProperties DexpreoptProperties - - installPath android.OutputPath - isPrivApp bool - isSDKLibrary bool - - builtInstalled []string -} - -type DexpreoptProperties struct { - Dex_preopt struct { - // If false, prevent dexpreopting and stripping the dex file from the final jar. Defaults to - // true. - Enabled *bool - - // If true, generate an app image (.art file) for this module. - App_image *bool - - // If true, use a checked-in profile to guide optimization. Defaults to false unless - // a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR - // that matches the name of this module, in which case it is defaulted to true. - Profile_guided *bool - - // If set, provides the path to profile relative to the Android.bp file. If not set, - // defaults to searching for a file that matches the name of this module in the default - // profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found. - Profile *string - } -} - -func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool { - if ctx.Config().DisableDexPreopt(ctx.ModuleName()) { - return true - } - - if ctx.Config().UnbundledBuild() { - return true - } - - if !BoolDefault(d.dexpreoptProperties.Dex_preopt.Enabled, true) { - return true - } - - // TODO: contains no java code - // TODO: is test - - return false -} - -func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) android.ModuleOutPath { - if d.dexpreoptDisabled(ctx) { - return dexJarFile - } - - globalConfig := ctx.Config().Once("DexpreoptGlobalConfig", func() interface{} { - if f := ctx.Config().DexpreoptGlobalConfig(); f != "" { - ctx.AddNinjaFileDeps(f) - globalConfig, err := dexpreopt.LoadGlobalConfig(f) - if err != nil { - panic(err) - } - return globalConfig - } - return dexpreopt.GlobalConfig{} - }).(dexpreopt.GlobalConfig) - - var archs []string - for _, a := range ctx.MultiTargets() { - archs = append(archs, a.Arch.ArchType.String()) - } - if len(archs) == 0 { - // assume this is a java library, dexpreopt for all arches for now - for _, target := range ctx.Config().Targets[android.Android] { - archs = append(archs, target.Arch.ArchType.String()) - } - if inList(ctx.ModuleName(), globalConfig.SystemServerJars) && !d.isSDKLibrary { - // If the module is not an SDK library and it's a system server jar, only preopt the primary arch. - archs = archs[:1] - } - } - if ctx.Config().SecondArchIsTranslated() { - // Only preopt primary arch for translated arch since there is only an image there. - archs = archs[:1] - } - - dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath) - - strippedDexJarFile := android.PathForModuleOut(ctx, "dexpreopt", dexJarFile.Base()) - - deps := android.Paths{dexJarFile} - - var profileClassListing android.OptionalPath - profileIsTextListing := false - if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) { - // If dex_preopt.profile_guided is not set, default it based on the existence of the - // dexprepot.profile option or the profile class listing. - if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" { - profileClassListing = android.OptionalPathForPath( - android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile))) - profileIsTextListing = true - } else { - profileClassListing = android.ExistentPathForSource(ctx, - ctx.Config().DexPreoptProfileDir(), ctx.ModuleName()+".prof") - } - } - - if profileClassListing.Valid() { - deps = append(deps, profileClassListing.Path()) - } - - uncompressedDex := false - if ctx.Config().UncompressPrivAppDex() && - (d.isPrivApp || inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules())) { - uncompressedDex = true - } - - dexpreoptConfig := dexpreopt.ModuleConfig{ - Name: ctx.ModuleName(), - DexLocation: dexLocation, - BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").String(), - DexPath: dexJarFile.String(), - PreferIntegrity: false, - UncompressedDex: uncompressedDex, - HasApkLibraries: false, - PreoptFlags: nil, - - ProfileClassListing: profileClassListing.String(), - ProfileIsTextListing: profileIsTextListing, - - EnforceUsesLibraries: false, - OptionalUsesLibraries: nil, - UsesLibraries: nil, - LibraryPaths: nil, - - Archs: archs, - DexPreoptImageLocation: "", - - PreoptExtractedApk: false, - - NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true), - ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false), - - StripInputPath: dexJarFile.String(), - StripOutputPath: strippedDexJarFile.String(), - } - - dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(globalConfig, dexpreoptConfig) - if err != nil { - ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error()) - return dexJarFile - } - - var inputs android.Paths - for _, input := range dexpreoptRule.Inputs() { - if input == "" { - // Tests sometimes have empty configuration values that lead to empty inputs - continue - } - rel, isRel := android.MaybeRel(ctx, android.PathForModuleOut(ctx).String(), input) - if isRel { - inputs = append(inputs, android.PathForModuleOut(ctx, rel)) - } else { - // TODO: use PathForOutput once boot image is moved to where PathForOutput can find it. - inputs = append(inputs, &bootImagePath{input}) - } - } - - var outputs android.WritablePaths - for _, output := range dexpreoptRule.Outputs() { - rel := android.Rel(ctx, android.PathForModuleOut(ctx).String(), output) - outputs = append(outputs, android.PathForModuleOut(ctx, rel)) - } - - for _, install := range dexpreoptRule.Installs() { - d.builtInstalled = append(d.builtInstalled, install.From+":"+install.To) - } - - if len(dexpreoptRule.Commands()) > 0 { - ctx.Build(pctx, android.BuildParams{ - Rule: ctx.Rule(pctx, "dexpreopt", blueprint.RuleParams{ - Command: strings.Join(proptools.NinjaEscape(dexpreoptRule.Commands()), " && "), - CommandDeps: dexpreoptRule.Tools(), - }), - Implicits: inputs, - Outputs: outputs, - Description: "dexpreopt", - }) - } - - stripRule, err := dexpreopt.GenerateStripRule(globalConfig, dexpreoptConfig) - if err != nil { - ctx.ModuleErrorf("error generating dexpreopt strip rule: %s", err.Error()) - return dexJarFile - } - - ctx.Build(pctx, android.BuildParams{ - Rule: ctx.Rule(pctx, "dexpreopt_strip", blueprint.RuleParams{ - Command: strings.Join(proptools.NinjaEscape(stripRule.Commands()), " && "), - CommandDeps: stripRule.Tools(), - }), - Input: dexJarFile, - Output: strippedDexJarFile, - Description: "dexpreopt strip", - }) - - return strippedDexJarFile -} - -type bootImagePath struct { - path string -} - -var _ android.Path = (*bootImagePath)(nil) - -func (p *bootImagePath) String() string { return p.path } -func (p *bootImagePath) Ext() string { return filepath.Ext(p.path) } -func (p *bootImagePath) Base() string { return filepath.Base(p.path) } -func (p *bootImagePath) Rel() string { return p.path } diff --git a/java/java.go b/java/java.go index aea1ef90d..5ed99f7e8 100644 --- a/java/java.go +++ b/java/java.go @@ -217,6 +217,25 @@ type CompilerDeviceProperties struct { // If set to true, compile dex regardless of installable. Defaults to false. Compile_dex *bool + Dex_preopt struct { + // If false, prevent dexpreopting and stripping the dex file from the final jar. Defaults to + // true. + Enabled *bool + + // If true, generate an app image (.art file) for this module. + App_image *bool + + // If true, use a checked-in profile to guide optimization. Defaults to false unless + // a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR + // that matches the name of this module, in which case it is defaulted to true. + Profile_guided *bool + + // If set, provides the path to profile relative to the Android.bp file. If not set, + // defaults to searching for a file that matches the name of this module in the default + // profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found. + Profile *string + } + Optimize struct { // If false, disable all optimization. Defaults to true for android_app and android_test // modules, false for java_library and java_test modules. @@ -247,7 +266,6 @@ type CompilerDeviceProperties struct { System_modules *string UncompressDex bool `blueprint:"mutated"` - IsSDKLibrary bool `blueprint:"mutated"` } // Module contains the properties and members used by all java module types @@ -277,9 +295,6 @@ type Module struct { // output file containing classes.dex and resources dexJarFile android.Path - // output file that contains classes.dex if it should be in the output file - maybeStrippedDexJarFile android.Path - // output file containing uninstrumented classes that will be instrumented by jacoco jacocoReportClassesFile android.Path @@ -312,8 +327,6 @@ type Module struct { // list of source files, collected from compiledJavaSrcs and compiledSrcJars // filter out Exclude_srcs, will be used by android.IDEInfo struct expandIDEInfoCompiledSrcs []string - - dexpreopter } func (j *Module) Srcs() android.Paths { @@ -1319,15 +1332,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path j.dexJarFile = dexOutputFile - dexOutputFile = j.dexpreopt(ctx, dexOutputFile) - - j.maybeStrippedDexJarFile = dexOutputFile - outputFile = dexOutputFile - - if ctx.Failed() { - return - } } else { outputFile = implementationAndResourcesJar } @@ -1481,17 +1486,9 @@ type Library struct { } func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { - j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", ctx.ModuleName()+".jar") - j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary j.compile(ctx) if Bool(j.properties.Installable) || ctx.Host() { - if j.deviceProperties.UncompressDex { - alignedOutputFile := android.PathForModuleOut(ctx, "aligned", ctx.ModuleName()+".jar") - TransformZipAlign(ctx, alignedOutputFile, j.outputFile) - j.outputFile = alignedOutputFile - } - j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.outputFile) } @@ -1507,7 +1504,6 @@ func LibraryFactory() android.Module { module.AddProperties( &module.Module.properties, &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, &module.Module.protoProperties) InitJavaModule(module, android.HostAndDeviceSupported) @@ -1578,7 +1574,6 @@ func TestFactory() android.Module { module.AddProperties( &module.Module.properties, &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, &module.Module.protoProperties, &module.testProperties) @@ -1675,7 +1670,6 @@ func BinaryFactory() android.Module { module.AddProperties( &module.Module.properties, &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, &module.Module.protoProperties, &module.binaryProperties) @@ -1895,7 +1889,6 @@ func DefaultsFactory(props ...interface{}) android.Module { module.AddProperties( &CompilerProperties{}, &CompilerDeviceProperties{}, - &DexpreoptProperties{}, &android.ProtoProperties{}, &aaptProperties{}, &androidLibraryProperties{}, diff --git a/java/sdk_library.go b/java/sdk_library.go index 877abe489..fdbf19d20 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -141,9 +141,8 @@ type sdkLibrary struct { android.ModuleBase android.DefaultableModuleBase - properties sdkLibraryProperties - deviceProperties CompilerDeviceProperties - dexpreoptProperties DexpreoptProperties + properties sdkLibraryProperties + deviceProperties CompilerDeviceProperties publicApiStubsPath android.Paths systemApiStubsPath android.Paths @@ -565,7 +564,6 @@ func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) Errorprone struct { Javacflags []string } - IsSDKLibrary bool }{} props.Name = proptools.StringPtr(module.implName()) @@ -576,7 +574,6 @@ func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) // XML file is installed along with the impl lib props.Required = []string{module.xmlFileName()} props.Errorprone.Javacflags = module.properties.Errorprone.Javacflags - props.IsSDKLibrary = true if module.SocSpecific() { props.Soc_specific = proptools.BoolPtr(true) @@ -586,10 +583,7 @@ func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) props.Product_specific = proptools.BoolPtr(true) } - mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), - &props, - &module.deviceProperties, - &module.dexpreoptProperties) + mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), &props, &module.deviceProperties) } // Creates the xml file that publicizes the runtime library @@ -722,7 +716,6 @@ func sdkLibraryFactory() android.Module { module := &sdkLibrary{} module.AddProperties(&module.properties) module.AddProperties(&module.deviceProperties) - module.AddProperties(&module.dexpreoptProperties) InitJavaModule(module, android.DeviceSupported) return module }