Home | History | Annotate | Download | only in dexpreopt
      1 // Copyright 2018 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package dexpreopt
     16 
     17 import (
     18 	"encoding/json"
     19 	"io/ioutil"
     20 	"strings"
     21 
     22 	"android/soong/android"
     23 )
     24 
     25 // GlobalConfig stores the configuration for dex preopting set by the product
     26 type GlobalConfig struct {
     27 	DefaultNoStripping bool // don't strip dex files by default
     28 
     29 	DisablePreopt        bool     // disable preopt for all modules
     30 	DisablePreoptModules []string // modules with preopt disabled by product-specific config
     31 
     32 	OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
     33 
     34 	GenerateApexImage bool // generate an extra boot image only containing jars from the runtime apex
     35 	UseApexImage      bool // use the apex image by default
     36 
     37 	HasSystemOther        bool     // store odex files that match PatternsOnSystemOther on the system_other partition
     38 	PatternsOnSystemOther []string // patterns (using '%' to denote a prefix match) to put odex on the system_other partition
     39 
     40 	DisableGenerateProfile bool   // don't generate profiles
     41 	ProfileDir             string // directory to find profiles in
     42 
     43 	BootJars []string // modules for jars that form the boot class path
     44 
     45 	RuntimeApexJars               []string // modules for jars that are in the runtime apex
     46 	ProductUpdatableBootModules   []string
     47 	ProductUpdatableBootLocations []string
     48 
     49 	SystemServerJars []string // jars that form the system server
     50 	SystemServerApps []string // apps that are loaded into system server
     51 	SpeedApps        []string // apps that should be speed optimized
     52 
     53 	PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified
     54 
     55 	DefaultCompilerFilter      string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags
     56 	SystemServerCompilerFilter string // default compiler filter to pass to dex2oat for system server jars
     57 
     58 	GenerateDMFiles     bool // generate Dex Metadata files
     59 	NeverAllowStripping bool // whether stripping should not be done - used as build time check to make sure dex files are always available
     60 
     61 	NoDebugInfo                 bool // don't generate debug info by default
     62 	DontResolveStartupStrings   bool // don't resolve string literals loaded during application startup.
     63 	AlwaysSystemServerDebugInfo bool // always generate mini debug info for system server modules (overrides NoDebugInfo=true)
     64 	NeverSystemServerDebugInfo  bool // never generate mini debug info for system server modules (overrides NoDebugInfo=false)
     65 	AlwaysOtherDebugInfo        bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
     66 	NeverOtherDebugInfo         bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
     67 
     68 	MissingUsesLibraries []string // libraries that may be listed in OptionalUsesLibraries but will not be installed by the product
     69 
     70 	IsEng        bool // build is a eng variant
     71 	SanitizeLite bool // build is the second phase of a SANITIZE_LITE build
     72 
     73 	DefaultAppImages bool // build app images (TODO: .art files?) by default
     74 
     75 	Dex2oatXmx string // max heap size for dex2oat
     76 	Dex2oatXms string // initial heap size for dex2oat
     77 
     78 	EmptyDirectory string // path to an empty directory
     79 
     80 	CpuVariant             map[android.ArchType]string // cpu variant for each architecture
     81 	InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture
     82 
     83 	// Only used for boot image
     84 	DirtyImageObjects      android.OptionalPath // path to a dirty-image-objects file
     85 	PreloadedClasses       android.OptionalPath // path to a preloaded-classes file
     86 	BootImageProfiles      android.Paths        // path to a boot-image-profile.txt file
     87 	UseProfileForBootImage bool                 // whether a profile should be used to compile the boot image
     88 	BootFlags              string               // extra flags to pass to dex2oat for the boot image
     89 	Dex2oatImageXmx        string               // max heap size for dex2oat for the boot image
     90 	Dex2oatImageXms        string               // initial heap size for dex2oat for the boot image
     91 
     92 	Tools Tools // paths to tools possibly used by the generated commands
     93 }
     94 
     95 // Tools contains paths to tools possibly used by the generated commands.  If you add a new tool here you MUST add it
     96 // to the order-only dependency list in DEXPREOPT_GEN_DEPS.
     97 type Tools struct {
     98 	Profman  android.Path
     99 	Dex2oat  android.Path
    100 	Aapt     android.Path
    101 	SoongZip android.Path
    102 	Zip2zip  android.Path
    103 
    104 	VerifyUsesLibraries android.Path
    105 	ConstructContext    android.Path
    106 }
    107 
    108 type ModuleConfig struct {
    109 	Name            string
    110 	DexLocation     string // dex location on device
    111 	BuildPath       android.OutputPath
    112 	DexPath         android.Path
    113 	UncompressedDex bool
    114 	HasApkLibraries bool
    115 	PreoptFlags     []string
    116 
    117 	ProfileClassListing  android.OptionalPath
    118 	ProfileIsTextListing bool
    119 
    120 	EnforceUsesLibraries  bool
    121 	OptionalUsesLibraries []string
    122 	UsesLibraries         []string
    123 	LibraryPaths          map[string]android.Path
    124 
    125 	Archs           []android.ArchType
    126 	DexPreoptImages []android.Path
    127 
    128 	PreoptBootClassPathDexFiles     android.Paths // file paths of boot class path files
    129 	PreoptBootClassPathDexLocations []string      // virtual locations of boot class path files
    130 
    131 	PreoptExtractedApk bool // Overrides OnlyPreoptModules
    132 
    133 	NoCreateAppImage    bool
    134 	ForceCreateAppImage bool
    135 
    136 	PresignedPrebuilt bool
    137 
    138 	NoStripping     bool
    139 	StripInputPath  android.Path
    140 	StripOutputPath android.WritablePath
    141 }
    142 
    143 func constructPath(ctx android.PathContext, path string) android.Path {
    144 	buildDirPrefix := ctx.Config().BuildDir() + "/"
    145 	if path == "" {
    146 		return nil
    147 	} else if strings.HasPrefix(path, buildDirPrefix) {
    148 		return android.PathForOutput(ctx, strings.TrimPrefix(path, buildDirPrefix))
    149 	} else {
    150 		return android.PathForSource(ctx, path)
    151 	}
    152 }
    153 
    154 func constructPaths(ctx android.PathContext, paths []string) android.Paths {
    155 	var ret android.Paths
    156 	for _, path := range paths {
    157 		ret = append(ret, constructPath(ctx, path))
    158 	}
    159 	return ret
    160 }
    161 
    162 func constructPathMap(ctx android.PathContext, paths map[string]string) map[string]android.Path {
    163 	ret := map[string]android.Path{}
    164 	for key, path := range paths {
    165 		ret[key] = constructPath(ctx, path)
    166 	}
    167 	return ret
    168 }
    169 
    170 func constructWritablePath(ctx android.PathContext, path string) android.WritablePath {
    171 	if path == "" {
    172 		return nil
    173 	}
    174 	return constructPath(ctx, path).(android.WritablePath)
    175 }
    176 
    177 // LoadGlobalConfig reads the global dexpreopt.config file into a GlobalConfig struct.  It is used directly in Soong
    178 // and in dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by Make.
    179 func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, error) {
    180 	type GlobalJSONConfig struct {
    181 		GlobalConfig
    182 
    183 		// Copies of entries in GlobalConfig that are not constructable without extra parameters.  They will be
    184 		// used to construct the real value manually below.
    185 		DirtyImageObjects string
    186 		PreloadedClasses  string
    187 		BootImageProfiles []string
    188 
    189 		Tools struct {
    190 			Profman  string
    191 			Dex2oat  string
    192 			Aapt     string
    193 			SoongZip string
    194 			Zip2zip  string
    195 
    196 			VerifyUsesLibraries string
    197 			ConstructContext    string
    198 		}
    199 	}
    200 
    201 	config := GlobalJSONConfig{}
    202 	err := loadConfig(ctx, path, &config)
    203 	if err != nil {
    204 		return config.GlobalConfig, err
    205 	}
    206 
    207 	// Construct paths that require a PathContext.
    208 	config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
    209 	config.GlobalConfig.PreloadedClasses = android.OptionalPathForPath(constructPath(ctx, config.PreloadedClasses))
    210 	config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
    211 
    212 	config.GlobalConfig.Tools.Profman = constructPath(ctx, config.Tools.Profman)
    213 	config.GlobalConfig.Tools.Dex2oat = constructPath(ctx, config.Tools.Dex2oat)
    214 	config.GlobalConfig.Tools.Aapt = constructPath(ctx, config.Tools.Aapt)
    215 	config.GlobalConfig.Tools.SoongZip = constructPath(ctx, config.Tools.SoongZip)
    216 	config.GlobalConfig.Tools.Zip2zip = constructPath(ctx, config.Tools.Zip2zip)
    217 	config.GlobalConfig.Tools.VerifyUsesLibraries = constructPath(ctx, config.Tools.VerifyUsesLibraries)
    218 	config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext)
    219 
    220 	return config.GlobalConfig, nil
    221 }
    222 
    223 // LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct.  It is not used in Soong, which
    224 // receives a ModuleConfig struct directly from java/dexpreopt.go.  It is used in dexpreopt_gen called from oMake to
    225 // read the module dexpreopt.config written by Make.
    226 func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error) {
    227 	type ModuleJSONConfig struct {
    228 		ModuleConfig
    229 
    230 		// Copies of entries in ModuleConfig that are not constructable without extra parameters.  They will be
    231 		// used to construct the real value manually below.
    232 		BuildPath                   string
    233 		DexPath                     string
    234 		ProfileClassListing         string
    235 		LibraryPaths                map[string]string
    236 		DexPreoptImages             []string
    237 		PreoptBootClassPathDexFiles []string
    238 		StripInputPath              string
    239 		StripOutputPath             string
    240 	}
    241 
    242 	config := ModuleJSONConfig{}
    243 
    244 	err := loadConfig(ctx, path, &config)
    245 	if err != nil {
    246 		return config.ModuleConfig, err
    247 	}
    248 
    249 	// Construct paths that require a PathContext.
    250 	config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath)
    251 	config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
    252 	config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
    253 	config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
    254 	config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
    255 	config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
    256 	config.ModuleConfig.StripInputPath = constructPath(ctx, config.StripInputPath)
    257 	config.ModuleConfig.StripOutputPath = constructWritablePath(ctx, config.StripOutputPath)
    258 
    259 	return config.ModuleConfig, nil
    260 }
    261 
    262 func loadConfig(ctx android.PathContext, path string, config interface{}) error {
    263 	r, err := ctx.Fs().Open(path)
    264 	if err != nil {
    265 		return err
    266 	}
    267 	defer r.Close()
    268 
    269 	data, err := ioutil.ReadAll(r)
    270 	if err != nil {
    271 		return err
    272 	}
    273 
    274 	err = json.Unmarshal(data, config)
    275 	if err != nil {
    276 		return err
    277 	}
    278 
    279 	return nil
    280 }
    281 
    282 func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
    283 	return GlobalConfig{
    284 		DefaultNoStripping:                 false,
    285 		DisablePreopt:                      false,
    286 		DisablePreoptModules:               nil,
    287 		OnlyPreoptBootImageAndSystemServer: false,
    288 		HasSystemOther:                     false,
    289 		PatternsOnSystemOther:              nil,
    290 		DisableGenerateProfile:             false,
    291 		ProfileDir:                         "",
    292 		BootJars:                           nil,
    293 		RuntimeApexJars:                    nil,
    294 		ProductUpdatableBootModules:        nil,
    295 		ProductUpdatableBootLocations:      nil,
    296 		SystemServerJars:                   nil,
    297 		SystemServerApps:                   nil,
    298 		SpeedApps:                          nil,
    299 		PreoptFlags:                        nil,
    300 		DefaultCompilerFilter:              "",
    301 		SystemServerCompilerFilter:         "",
    302 		GenerateDMFiles:                    false,
    303 		NeverAllowStripping:                false,
    304 		NoDebugInfo:                        false,
    305 		DontResolveStartupStrings:          false,
    306 		AlwaysSystemServerDebugInfo:        false,
    307 		NeverSystemServerDebugInfo:         false,
    308 		AlwaysOtherDebugInfo:               false,
    309 		NeverOtherDebugInfo:                false,
    310 		MissingUsesLibraries:               nil,
    311 		IsEng:                              false,
    312 		SanitizeLite:                       false,
    313 		DefaultAppImages:                   false,
    314 		Dex2oatXmx:                         "",
    315 		Dex2oatXms:                         "",
    316 		EmptyDirectory:                     "empty_dir",
    317 		CpuVariant:                         nil,
    318 		InstructionSetFeatures:             nil,
    319 		DirtyImageObjects:                  android.OptionalPath{},
    320 		PreloadedClasses:                   android.OptionalPath{},
    321 		BootImageProfiles:                  nil,
    322 		UseProfileForBootImage:             false,
    323 		BootFlags:                          "",
    324 		Dex2oatImageXmx:                    "",
    325 		Dex2oatImageXms:                    "",
    326 		Tools: Tools{
    327 			Profman:             android.PathForTesting("profman"),
    328 			Dex2oat:             android.PathForTesting("dex2oat"),
    329 			Aapt:                android.PathForTesting("aapt"),
    330 			SoongZip:            android.PathForTesting("soong_zip"),
    331 			Zip2zip:             android.PathForTesting("zip2zip"),
    332 			VerifyUsesLibraries: android.PathForTesting("verify_uses_libraries.sh"),
    333 			ConstructContext:    android.PathForTesting("construct_context.sh"),
    334 		},
    335 	}
    336 }
    337