| // 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" |
| "strings" |
| |
| "android/soong/android" |
| ) |
| |
| // GlobalConfig stores the configuration for dex preopting set by the product |
| type GlobalConfig struct { |
| DefaultNoStripping bool // don't strip dex files by default |
| |
| DisablePreopt bool // disable preopt for all modules |
| DisablePreoptModules []string // modules with preopt disabled by product-specific config |
| |
| OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server |
| |
| GenerateApexImage bool // generate an extra boot image only containing jars from the runtime apex |
| |
| 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 |
| ProfileDir string // directory to find profiles in |
| |
| BootJars []string // modules for jars that form the boot class path |
| |
| RuntimeApexJars []string // modules for jars that are in the runtime apex |
| ProductUpdatableBootModules []string |
| ProductUpdatableBootLocations []string |
| |
| 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 |
| NeverAllowStripping bool // whether stripping should not be done - used as build time check to make sure dex files are always available |
| |
| 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 for dex2oat |
| Dex2oatXms string // initial heap size for dex2oat |
| |
| EmptyDirectory string // path to an empty directory |
| |
| CpuVariant map[android.ArchType]string // cpu variant for each architecture |
| InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture |
| |
| // Only used for boot image |
| DirtyImageObjects android.OptionalPath // path to a dirty-image-objects file |
| PreloadedClasses android.OptionalPath // path to a preloaded-classes file |
| BootImageProfiles android.Paths // path to a boot-image-profile.txt file |
| UseProfileForBootImage bool // whether a profile should be used to compile the boot image |
| BootFlags string // extra flags to pass to dex2oat for the boot image |
| Dex2oatImageXmx string // max heap size for dex2oat for the boot image |
| Dex2oatImageXms string // initial heap size for dex2oat for the boot image |
| |
| 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 android.Path |
| Dex2oat android.Path |
| Aapt android.Path |
| SoongZip android.Path |
| Zip2zip android.Path |
| |
| VerifyUsesLibraries android.Path |
| ConstructContext android.Path |
| } |
| |
| type ModuleConfig struct { |
| Name string |
| DexLocation string // dex location on device |
| BuildPath android.OutputPath |
| DexPath android.Path |
| UncompressedDex bool |
| HasApkLibraries bool |
| PreoptFlags []string |
| |
| ProfileClassListing android.OptionalPath |
| ProfileIsTextListing bool |
| |
| EnforceUsesLibraries bool |
| OptionalUsesLibraries []string |
| UsesLibraries []string |
| LibraryPaths map[string]android.Path |
| |
| Archs []android.ArchType |
| DexPreoptImages []android.Path |
| |
| PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files |
| PreoptBootClassPathDexLocations []string // virtual locations of boot class path files |
| |
| PreoptExtractedApk bool // Overrides OnlyPreoptModules |
| |
| NoCreateAppImage bool |
| ForceCreateAppImage bool |
| |
| PresignedPrebuilt bool |
| |
| NoStripping bool |
| StripInputPath android.Path |
| StripOutputPath android.WritablePath |
| } |
| |
| func constructPath(ctx android.PathContext, path string) android.Path { |
| buildDirPrefix := ctx.Config().BuildDir() + "/" |
| if path == "" { |
| return nil |
| } else if strings.HasPrefix(path, buildDirPrefix) { |
| return android.PathForOutput(ctx, strings.TrimPrefix(path, buildDirPrefix)) |
| } else { |
| return android.PathForSource(ctx, path) |
| } |
| } |
| |
| func constructPaths(ctx android.PathContext, paths []string) android.Paths { |
| var ret android.Paths |
| for _, path := range paths { |
| ret = append(ret, constructPath(ctx, path)) |
| } |
| return ret |
| } |
| |
| func constructPathMap(ctx android.PathContext, paths map[string]string) map[string]android.Path { |
| ret := map[string]android.Path{} |
| for key, path := range paths { |
| ret[key] = constructPath(ctx, path) |
| } |
| return ret |
| } |
| |
| func constructWritablePath(ctx android.PathContext, path string) android.WritablePath { |
| if path == "" { |
| return nil |
| } |
| return constructPath(ctx, path).(android.WritablePath) |
| } |
| |
| // LoadGlobalConfig reads the global dexpreopt.config file into a GlobalConfig struct. It is used directly in Soong |
| // and in dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by Make. |
| func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, error) { |
| type GlobalJSONConfig struct { |
| GlobalConfig |
| |
| // Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be |
| // used to construct the real value manually below. |
| DirtyImageObjects string |
| PreloadedClasses string |
| BootImageProfiles []string |
| |
| Tools struct { |
| Profman string |
| Dex2oat string |
| Aapt string |
| SoongZip string |
| Zip2zip string |
| |
| VerifyUsesLibraries string |
| ConstructContext string |
| } |
| } |
| |
| config := GlobalJSONConfig{} |
| err := loadConfig(ctx, path, &config) |
| if err != nil { |
| return config.GlobalConfig, err |
| } |
| |
| // Construct paths that require a PathContext. |
| config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects)) |
| config.GlobalConfig.PreloadedClasses = android.OptionalPathForPath(constructPath(ctx, config.PreloadedClasses)) |
| config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles) |
| |
| config.GlobalConfig.Tools.Profman = constructPath(ctx, config.Tools.Profman) |
| config.GlobalConfig.Tools.Dex2oat = constructPath(ctx, config.Tools.Dex2oat) |
| config.GlobalConfig.Tools.Aapt = constructPath(ctx, config.Tools.Aapt) |
| config.GlobalConfig.Tools.SoongZip = constructPath(ctx, config.Tools.SoongZip) |
| config.GlobalConfig.Tools.Zip2zip = constructPath(ctx, config.Tools.Zip2zip) |
| config.GlobalConfig.Tools.VerifyUsesLibraries = constructPath(ctx, config.Tools.VerifyUsesLibraries) |
| config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext) |
| |
| return config.GlobalConfig, nil |
| } |
| |
| // LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct. It is not used in Soong, which |
| // receives a ModuleConfig struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called from oMake to |
| // read the module dexpreopt.config written by Make. |
| func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error) { |
| type ModuleJSONConfig struct { |
| ModuleConfig |
| |
| // Copies of entries in ModuleConfig that are not constructable without extra parameters. They will be |
| // used to construct the real value manually below. |
| BuildPath string |
| DexPath string |
| ProfileClassListing string |
| LibraryPaths map[string]string |
| DexPreoptImages []string |
| PreoptBootClassPathDexFiles []string |
| StripInputPath string |
| StripOutputPath string |
| } |
| |
| config := ModuleJSONConfig{} |
| |
| err := loadConfig(ctx, path, &config) |
| if err != nil { |
| return config.ModuleConfig, err |
| } |
| |
| // Construct paths that require a PathContext. |
| config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath) |
| config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath) |
| config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing)) |
| config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths) |
| config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages) |
| config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles) |
| config.ModuleConfig.StripInputPath = constructPath(ctx, config.StripInputPath) |
| config.ModuleConfig.StripOutputPath = constructWritablePath(ctx, config.StripOutputPath) |
| |
| return config.ModuleConfig, nil |
| } |
| |
| func loadConfig(ctx android.PathContext, path string, config interface{}) error { |
| r, err := ctx.Fs().Open(path) |
| if err != nil { |
| return err |
| } |
| defer r.Close() |
| |
| data, err := ioutil.ReadAll(r) |
| if err != nil { |
| return err |
| } |
| |
| err = json.Unmarshal(data, config) |
| if err != nil { |
| return err |
| } |
| |
| return nil |
| } |
| |
| func GlobalConfigForTests(ctx android.PathContext) GlobalConfig { |
| return GlobalConfig{ |
| DefaultNoStripping: false, |
| DisablePreopt: false, |
| DisablePreoptModules: nil, |
| OnlyPreoptBootImageAndSystemServer: false, |
| HasSystemOther: false, |
| PatternsOnSystemOther: nil, |
| DisableGenerateProfile: false, |
| ProfileDir: "", |
| BootJars: nil, |
| RuntimeApexJars: nil, |
| ProductUpdatableBootModules: nil, |
| ProductUpdatableBootLocations: nil, |
| SystemServerJars: nil, |
| SystemServerApps: nil, |
| SpeedApps: nil, |
| PreoptFlags: nil, |
| DefaultCompilerFilter: "", |
| SystemServerCompilerFilter: "", |
| GenerateDMFiles: false, |
| NeverAllowStripping: false, |
| NoDebugInfo: false, |
| AlwaysSystemServerDebugInfo: false, |
| NeverSystemServerDebugInfo: false, |
| AlwaysOtherDebugInfo: false, |
| NeverOtherDebugInfo: false, |
| MissingUsesLibraries: nil, |
| IsEng: false, |
| SanitizeLite: false, |
| DefaultAppImages: false, |
| Dex2oatXmx: "", |
| Dex2oatXms: "", |
| EmptyDirectory: "empty_dir", |
| CpuVariant: nil, |
| InstructionSetFeatures: nil, |
| DirtyImageObjects: android.OptionalPath{}, |
| PreloadedClasses: android.OptionalPath{}, |
| BootImageProfiles: nil, |
| UseProfileForBootImage: false, |
| BootFlags: "", |
| Dex2oatImageXmx: "", |
| Dex2oatImageXms: "", |
| Tools: Tools{ |
| Profman: android.PathForTesting("profman"), |
| Dex2oat: android.PathForTesting("dex2oat"), |
| Aapt: android.PathForTesting("aapt"), |
| SoongZip: android.PathForTesting("soong_zip"), |
| Zip2zip: android.PathForTesting("zip2zip"), |
| VerifyUsesLibraries: android.PathForTesting("verify_uses_libraries.sh"), |
| ConstructContext: android.PathForTesting("construct_context.sh"), |
| }, |
| } |
| } |