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 15package dexpreopt 16 17import ( 18 "encoding/json" 19 "fmt" 20 "reflect" 21 "strings" 22 23 "github.com/google/blueprint" 24 25 "android/soong/android" 26) 27 28// GlobalConfig stores the configuration for dex preopting. The fields are set 29// from product variables via dex_preopt_config.mk. 30type GlobalConfig struct { 31 DisablePreopt bool // disable preopt for all modules (excluding boot images) 32 DisablePreoptBootImages bool // disable prepot for boot images 33 DisablePreoptModules []string // modules with preopt disabled by product-specific config 34 35 OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server 36 37 PreoptWithUpdatableBcp bool // If updatable boot jars are included in dexpreopt or not. 38 39 UseArtImage bool // use the art image (use other boot class path dex files without image) 40 41 HasSystemOther bool // store odex files that match PatternsOnSystemOther on the system_other partition 42 PatternsOnSystemOther []string // patterns (using '%' to denote a prefix match) to put odex on the system_other partition 43 44 DisableGenerateProfile bool // don't generate profiles 45 ProfileDir string // directory to find profiles in 46 47 BootJars android.ConfiguredJarList // modules for jars that form the boot class path 48 UpdatableBootJars android.ConfiguredJarList // jars within apex that form the boot class path 49 50 ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX 51 52 SystemServerJars android.ConfiguredJarList // jars that form the system server 53 SystemServerApps []string // apps that are loaded into system server 54 UpdatableSystemServerJars android.ConfiguredJarList // jars within apex that are loaded into system server 55 SpeedApps []string // apps that should be speed optimized 56 57 BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error 58 59 PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified 60 61 DefaultCompilerFilter string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags 62 SystemServerCompilerFilter string // default compiler filter to pass to dex2oat for system server jars 63 64 GenerateDMFiles bool // generate Dex Metadata files 65 66 NoDebugInfo bool // don't generate debug info by default 67 DontResolveStartupStrings bool // don't resolve string literals loaded during application startup. 68 AlwaysSystemServerDebugInfo bool // always generate mini debug info for system server modules (overrides NoDebugInfo=true) 69 NeverSystemServerDebugInfo bool // never generate mini debug info for system server modules (overrides NoDebugInfo=false) 70 AlwaysOtherDebugInfo bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true) 71 NeverOtherDebugInfo bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true) 72 73 IsEng bool // build is a eng variant 74 SanitizeLite bool // build is the second phase of a SANITIZE_LITE build 75 76 DefaultAppImages bool // build app images (TODO: .art files?) by default 77 78 Dex2oatXmx string // max heap size for dex2oat 79 Dex2oatXms string // initial heap size for dex2oat 80 81 EmptyDirectory string // path to an empty directory 82 83 CpuVariant map[android.ArchType]string // cpu variant for each architecture 84 InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture 85 86 BootImageProfiles android.Paths // path to a boot-image-profile.txt file 87 BootFlags string // extra flags to pass to dex2oat for the boot image 88 Dex2oatImageXmx string // max heap size for dex2oat for the boot image 89 Dex2oatImageXms string // initial heap size for dex2oat for the boot image 90 91 // If true, downgrade the compiler filter of dexpreopt to "verify" when verify_uses_libraries 92 // check fails, instead of failing the build. This will disable any AOT-compilation. 93 // 94 // The intended use case for this flag is to have a smoother migration path for the Java 95 // modules that need to add <uses-library> information in their build files. The flag allows to 96 // quickly silence build errors. This flag should be used with caution and only as a temporary 97 // measure, as it masks real errors and affects performance. 98 RelaxUsesLibraryCheck bool 99} 100 101// GlobalSoongConfig contains the global config that is generated from Soong, 102// stored in dexpreopt_soong.config. 103type GlobalSoongConfig struct { 104 // Paths to tools possibly used by the generated commands. 105 Profman android.Path 106 Dex2oat android.Path 107 Aapt android.Path 108 SoongZip android.Path 109 Zip2zip android.Path 110 ManifestCheck android.Path 111 ConstructContext android.Path 112} 113 114type ModuleConfig struct { 115 Name string 116 DexLocation string // dex location on device 117 BuildPath android.OutputPath 118 DexPath android.Path 119 ManifestPath android.OptionalPath 120 UncompressedDex bool 121 HasApkLibraries bool 122 PreoptFlags []string 123 124 ProfileClassListing android.OptionalPath 125 ProfileIsTextListing bool 126 ProfileBootListing android.OptionalPath 127 128 EnforceUsesLibraries bool // turn on build-time verify_uses_libraries check 129 EnforceUsesLibrariesStatusFile android.Path // a file with verify_uses_libraries errors (if any) 130 ProvidesUsesLibrary string // library name (usually the same as module name) 131 ClassLoaderContexts ClassLoaderContextMap 132 133 Archs []android.ArchType 134 DexPreoptImagesDeps []android.OutputPaths 135 136 DexPreoptImageLocationsOnHost []string // boot image location on host (file path without the arch subdirectory) 137 DexPreoptImageLocationsOnDevice []string // boot image location on device (file path without the arch subdirectory) 138 139 PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files 140 PreoptBootClassPathDexLocations []string // virtual locations of boot class path files 141 142 PreoptExtractedApk bool // Overrides OnlyPreoptModules 143 144 NoCreateAppImage bool 145 ForceCreateAppImage bool 146 147 PresignedPrebuilt bool 148} 149 150type globalSoongConfigSingleton struct{} 151 152var pctx = android.NewPackageContext("android/soong/dexpreopt") 153 154func init() { 155 pctx.Import("android/soong/android") 156 android.RegisterSingletonType("dexpreopt-soong-config", func() android.Singleton { 157 return &globalSoongConfigSingleton{} 158 }) 159} 160 161func constructPath(ctx android.PathContext, path string) android.Path { 162 buildDirPrefix := ctx.Config().BuildDir() + "/" 163 if path == "" { 164 return nil 165 } else if strings.HasPrefix(path, buildDirPrefix) { 166 return android.PathForOutput(ctx, strings.TrimPrefix(path, buildDirPrefix)) 167 } else { 168 return android.PathForSource(ctx, path) 169 } 170} 171 172func constructPaths(ctx android.PathContext, paths []string) android.Paths { 173 var ret android.Paths 174 for _, path := range paths { 175 ret = append(ret, constructPath(ctx, path)) 176 } 177 return ret 178} 179 180func constructWritablePath(ctx android.PathContext, path string) android.WritablePath { 181 if path == "" { 182 return nil 183 } 184 return constructPath(ctx, path).(android.WritablePath) 185} 186 187// ParseGlobalConfig parses the given data assumed to be read from the global 188// dexpreopt.config file into a GlobalConfig struct. 189func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, error) { 190 type GlobalJSONConfig struct { 191 *GlobalConfig 192 193 // Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be 194 // used to construct the real value manually below. 195 BootImageProfiles []string 196 } 197 198 config := GlobalJSONConfig{} 199 err := json.Unmarshal(data, &config) 200 if err != nil { 201 return config.GlobalConfig, err 202 } 203 204 // Construct paths that require a PathContext. 205 config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles) 206 207 return config.GlobalConfig, nil 208} 209 210type globalConfigAndRaw struct { 211 global *GlobalConfig 212 data []byte 213} 214 215// GetGlobalConfig returns the global dexpreopt.config that's created in the 216// make config phase. It is loaded once the first time it is called for any 217// ctx.Config(), and returns the same data for all future calls with the same 218// ctx.Config(). A value can be inserted for tests using 219// setDexpreoptTestGlobalConfig. 220func GetGlobalConfig(ctx android.PathContext) *GlobalConfig { 221 return getGlobalConfigRaw(ctx).global 222} 223 224// GetGlobalConfigRawData is the same as GetGlobalConfig, except that it returns 225// the literal content of dexpreopt.config. 226func GetGlobalConfigRawData(ctx android.PathContext) []byte { 227 return getGlobalConfigRaw(ctx).data 228} 229 230var globalConfigOnceKey = android.NewOnceKey("DexpreoptGlobalConfig") 231var testGlobalConfigOnceKey = android.NewOnceKey("TestDexpreoptGlobalConfig") 232 233func getGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw { 234 return ctx.Config().Once(globalConfigOnceKey, func() interface{} { 235 if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil { 236 panic(err) 237 } else if data != nil { 238 globalConfig, err := ParseGlobalConfig(ctx, data) 239 if err != nil { 240 panic(err) 241 } 242 return globalConfigAndRaw{globalConfig, data} 243 } 244 245 // No global config filename set, see if there is a test config set 246 return ctx.Config().Once(testGlobalConfigOnceKey, func() interface{} { 247 // Nope, return a config with preopting disabled 248 return globalConfigAndRaw{&GlobalConfig{ 249 DisablePreopt: true, 250 DisablePreoptBootImages: true, 251 DisableGenerateProfile: true, 252 }, nil} 253 }) 254 }).(globalConfigAndRaw) 255} 256 257// SetTestGlobalConfig sets a GlobalConfig that future calls to GetGlobalConfig 258// will return. It must be called before the first call to GetGlobalConfig for 259// the config. 260func SetTestGlobalConfig(config android.Config, globalConfig *GlobalConfig) { 261 config.Once(testGlobalConfigOnceKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} }) 262} 263 264// This struct is required to convert ModuleConfig from/to JSON. 265// The types of fields in ModuleConfig are not convertible, 266// so moduleJSONConfig has those fields as a convertible type. 267type moduleJSONConfig struct { 268 *ModuleConfig 269 270 BuildPath string 271 DexPath string 272 ManifestPath string 273 274 ProfileClassListing string 275 ProfileBootListing string 276 277 EnforceUsesLibrariesStatusFile string 278 ClassLoaderContexts jsonClassLoaderContextMap 279 280 DexPreoptImagesDeps [][]string 281 282 PreoptBootClassPathDexFiles []string 283} 284 285// ParseModuleConfig parses a per-module dexpreopt.config file into a 286// ModuleConfig struct. It is not used in Soong, which receives a ModuleConfig 287// struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called 288// from Make to read the module dexpreopt.config written in the Make config 289// stage. 290func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) { 291 config := moduleJSONConfig{} 292 293 err := json.Unmarshal(data, &config) 294 if err != nil { 295 return config.ModuleConfig, err 296 } 297 298 // Construct paths that require a PathContext. 299 config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath) 300 config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath) 301 config.ModuleConfig.ManifestPath = android.OptionalPathForPath(constructPath(ctx, config.ManifestPath)) 302 config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing)) 303 config.ModuleConfig.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile) 304 config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts) 305 config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles) 306 307 // This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON. 308 config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.Archs)) 309 310 return config.ModuleConfig, nil 311} 312 313func pathsListToStringLists(pathsList []android.OutputPaths) [][]string { 314 ret := make([][]string, 0, len(pathsList)) 315 for _, paths := range pathsList { 316 ret = append(ret, paths.Strings()) 317 } 318 return ret 319} 320 321func moduleConfigToJSON(config *ModuleConfig) ([]byte, error) { 322 return json.MarshalIndent(&moduleJSONConfig{ 323 BuildPath: config.BuildPath.String(), 324 DexPath: config.DexPath.String(), 325 ManifestPath: config.ManifestPath.String(), 326 ProfileClassListing: config.ProfileClassListing.String(), 327 ProfileBootListing: config.ProfileBootListing.String(), 328 EnforceUsesLibrariesStatusFile: config.EnforceUsesLibrariesStatusFile.String(), 329 ClassLoaderContexts: toJsonClassLoaderContext(config.ClassLoaderContexts), 330 DexPreoptImagesDeps: pathsListToStringLists(config.DexPreoptImagesDeps), 331 PreoptBootClassPathDexFiles: config.PreoptBootClassPathDexFiles.Strings(), 332 ModuleConfig: config, 333 }, "", " ") 334} 335 336// WriteModuleConfig serializes a ModuleConfig into a per-module dexpreopt.config JSON file. 337// These config files are used for post-processing. 338func WriteModuleConfig(ctx android.ModuleContext, config *ModuleConfig, path android.WritablePath) { 339 if path == nil { 340 return 341 } 342 343 data, err := moduleConfigToJSON(config) 344 if err != nil { 345 ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err) 346 return 347 } 348 349 android.WriteFileRule(ctx, path, string(data)) 350} 351 352// dex2oatModuleName returns the name of the module to use for the dex2oat host 353// tool. It should be a binary module with public visibility that is compiled 354// and installed for host. 355func dex2oatModuleName(config android.Config) string { 356 // Default to the debug variant of dex2oat to help find bugs. 357 // Set USE_DEX2OAT_DEBUG to false for only building non-debug versions. 358 if config.Getenv("USE_DEX2OAT_DEBUG") == "false" { 359 return "dex2oat" 360 } else { 361 return "dex2oatd" 362 } 363} 364 365type dex2oatDependencyTag struct { 366 blueprint.BaseDependencyTag 367} 368 369func (d dex2oatDependencyTag) ExcludeFromVisibilityEnforcement() { 370} 371 372func (d dex2oatDependencyTag) ExcludeFromApexContents() { 373} 374 375func (d dex2oatDependencyTag) AllowDisabledModuleDependency(target android.Module) bool { 376 // RegisterToolDeps may run after the prebuilt mutators and hence register a 377 // dependency on the source module even when the prebuilt is to be used. 378 // dex2oatPathFromDep takes that into account when it retrieves the path to 379 // the binary, but we also need to disable the check for dependencies on 380 // disabled modules. 381 return target.IsReplacedByPrebuilt() 382} 383 384// Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that 385// needs dexpreopting and so it makes no sense for it to be checked for visibility or included in 386// the apex. 387var Dex2oatDepTag = dex2oatDependencyTag{} 388 389var _ android.ExcludeFromVisibilityEnforcementTag = Dex2oatDepTag 390var _ android.ExcludeFromApexContentsTag = Dex2oatDepTag 391var _ android.AllowDisabledModuleDependency = Dex2oatDepTag 392 393// RegisterToolDeps adds the necessary dependencies to binary modules for tools 394// that are required later when Get(Cached)GlobalSoongConfig is called. It 395// should be called from a mutator that's registered with 396// android.RegistrationContext.FinalDepsMutators. 397func RegisterToolDeps(ctx android.BottomUpMutatorContext) { 398 dex2oatBin := dex2oatModuleName(ctx.Config()) 399 v := ctx.Config().BuildOSTarget.Variations() 400 ctx.AddFarVariationDependencies(v, Dex2oatDepTag, dex2oatBin) 401} 402 403func dex2oatPathFromDep(ctx android.ModuleContext) android.Path { 404 dex2oatBin := dex2oatModuleName(ctx.Config()) 405 406 // Find the right dex2oat module, trying to follow PrebuiltDepTag from source 407 // to prebuilt if there is one. We wouldn't have to do this if the 408 // prebuilt_postdeps mutator that replaces source deps with prebuilt deps was 409 // run after RegisterToolDeps above, but changing that leads to ordering 410 // problems between mutators (RegisterToolDeps needs to run late to act on 411 // final variants, while prebuilt_postdeps needs to run before many of the 412 // PostDeps mutators, like the APEX mutators). Hence we need to dig out the 413 // prebuilt explicitly here instead. 414 var dex2oatModule android.Module 415 ctx.WalkDeps(func(child, parent android.Module) bool { 416 if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag { 417 // Found the source module, or prebuilt module that has replaced the source. 418 dex2oatModule = child 419 if android.IsModulePrebuilt(child) { 420 return false // If it's the prebuilt we're done. 421 } else { 422 return true // Recurse to check if the source has a prebuilt dependency. 423 } 424 } 425 if parent == dex2oatModule && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag { 426 if p := android.GetEmbeddedPrebuilt(child); p != nil && p.UsePrebuilt() { 427 dex2oatModule = child // Found a prebuilt that should be used. 428 } 429 } 430 return false 431 }) 432 433 if dex2oatModule == nil { 434 // If this happens there's probably a missing call to AddToolDeps in DepsMutator. 435 panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin)) 436 } 437 438 dex2oatPath := dex2oatModule.(android.HostToolProvider).HostToolPath() 439 if !dex2oatPath.Valid() { 440 panic(fmt.Sprintf("Failed to find host tool path in %s", dex2oatModule)) 441 } 442 443 return dex2oatPath.Path() 444} 445 446// createGlobalSoongConfig creates a GlobalSoongConfig from the current context. 447// Should not be used in dexpreopt_gen. 448func createGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig { 449 return &GlobalSoongConfig{ 450 Profman: ctx.Config().HostToolPath(ctx, "profman"), 451 Dex2oat: dex2oatPathFromDep(ctx), 452 Aapt: ctx.Config().HostToolPath(ctx, "aapt"), 453 SoongZip: ctx.Config().HostToolPath(ctx, "soong_zip"), 454 Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"), 455 ManifestCheck: ctx.Config().HostToolPath(ctx, "manifest_check"), 456 ConstructContext: ctx.Config().HostToolPath(ctx, "construct_context"), 457 } 458} 459 460// The main reason for this Once cache for GlobalSoongConfig is to make the 461// dex2oat path available to singletons. In ordinary modules we get it through a 462// Dex2oatDepTag dependency, but in singletons there's no simple way to do the 463// same thing and ensure the right variant is selected, hence this cache to make 464// the resolved path available to singletons. This means we depend on there 465// being at least one ordinary module with a Dex2oatDepTag dependency. 466// 467// TODO(b/147613152): Implement a way to deal with dependencies from singletons, 468// and then possibly remove this cache altogether. 469var globalSoongConfigOnceKey = android.NewOnceKey("DexpreoptGlobalSoongConfig") 470 471// GetGlobalSoongConfig creates a GlobalSoongConfig the first time it's called, 472// and later returns the same cached instance. 473func GetGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig { 474 globalSoong := ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { 475 return createGlobalSoongConfig(ctx) 476 }).(*GlobalSoongConfig) 477 478 // Always resolve the tool path from the dependency, to ensure that every 479 // module has the dependency added properly. 480 myDex2oat := dex2oatPathFromDep(ctx) 481 if myDex2oat != globalSoong.Dex2oat { 482 panic(fmt.Sprintf("Inconsistent dex2oat path in cached config: expected %s, got %s", globalSoong.Dex2oat, myDex2oat)) 483 } 484 485 return globalSoong 486} 487 488// GetCachedGlobalSoongConfig returns a cached GlobalSoongConfig created by an 489// earlier GetGlobalSoongConfig call. This function works with any context 490// compatible with a basic PathContext, since it doesn't try to create a 491// GlobalSoongConfig with the proper paths (which requires a full 492// ModuleContext). If there has been no prior call to GetGlobalSoongConfig, nil 493// is returned. 494func GetCachedGlobalSoongConfig(ctx android.PathContext) *GlobalSoongConfig { 495 return ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { 496 return (*GlobalSoongConfig)(nil) 497 }).(*GlobalSoongConfig) 498} 499 500type globalJsonSoongConfig struct { 501 Profman string 502 Dex2oat string 503 Aapt string 504 SoongZip string 505 Zip2zip string 506 ManifestCheck string 507 ConstructContext string 508} 509 510// ParseGlobalSoongConfig parses the given data assumed to be read from the 511// global dexpreopt_soong.config file into a GlobalSoongConfig struct. It is 512// only used in dexpreopt_gen. 513func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (*GlobalSoongConfig, error) { 514 var jc globalJsonSoongConfig 515 516 err := json.Unmarshal(data, &jc) 517 if err != nil { 518 return &GlobalSoongConfig{}, err 519 } 520 521 config := &GlobalSoongConfig{ 522 Profman: constructPath(ctx, jc.Profman), 523 Dex2oat: constructPath(ctx, jc.Dex2oat), 524 Aapt: constructPath(ctx, jc.Aapt), 525 SoongZip: constructPath(ctx, jc.SoongZip), 526 Zip2zip: constructPath(ctx, jc.Zip2zip), 527 ManifestCheck: constructPath(ctx, jc.ManifestCheck), 528 ConstructContext: constructPath(ctx, jc.ConstructContext), 529 } 530 531 return config, nil 532} 533 534// checkBootJarsConfigConsistency checks the consistency of BootJars and UpdatableBootJars fields in 535// DexpreoptGlobalConfig and Config.productVariables. 536func checkBootJarsConfigConsistency(ctx android.SingletonContext, dexpreoptConfig *GlobalConfig, config android.Config) { 537 compareBootJars := func(property string, dexpreoptJars, variableJars android.ConfiguredJarList) { 538 dexpreoptPairs := dexpreoptJars.CopyOfApexJarPairs() 539 variablePairs := variableJars.CopyOfApexJarPairs() 540 if !reflect.DeepEqual(dexpreoptPairs, variablePairs) { 541 ctx.Errorf("Inconsistent configuration of %[1]s\n"+ 542 " dexpreopt.GlobalConfig.%[1]s = %[2]s\n"+ 543 " productVariables.%[1]s = %[3]s", 544 property, dexpreoptPairs, variablePairs) 545 } 546 } 547 548 compareBootJars("BootJars", dexpreoptConfig.BootJars, config.NonUpdatableBootJars()) 549 compareBootJars("UpdatableBootJars", dexpreoptConfig.UpdatableBootJars, config.UpdatableBootJars()) 550} 551 552func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) { 553 checkBootJarsConfigConsistency(ctx, GetGlobalConfig(ctx), ctx.Config()) 554 555 if GetGlobalConfig(ctx).DisablePreopt { 556 return 557 } 558 559 config := GetCachedGlobalSoongConfig(ctx) 560 if config == nil { 561 // No module has enabled dexpreopting, so we assume there will be no calls 562 // to dexpreopt_gen. 563 return 564 } 565 566 jc := globalJsonSoongConfig{ 567 Profman: config.Profman.String(), 568 Dex2oat: config.Dex2oat.String(), 569 Aapt: config.Aapt.String(), 570 SoongZip: config.SoongZip.String(), 571 Zip2zip: config.Zip2zip.String(), 572 ManifestCheck: config.ManifestCheck.String(), 573 ConstructContext: config.ConstructContext.String(), 574 } 575 576 data, err := json.Marshal(jc) 577 if err != nil { 578 ctx.Errorf("failed to JSON marshal GlobalSoongConfig: %v", err) 579 return 580 } 581 582 android.WriteFileRule(ctx, android.PathForOutput(ctx, "dexpreopt_soong.config"), string(data)) 583} 584 585func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { 586 if GetGlobalConfig(ctx).DisablePreopt { 587 return 588 } 589 590 config := GetCachedGlobalSoongConfig(ctx) 591 if config == nil { 592 return 593 } 594 595 ctx.Strict("DEX2OAT", config.Dex2oat.String()) 596 ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{ 597 config.Profman.String(), 598 config.Dex2oat.String(), 599 config.Aapt.String(), 600 config.SoongZip.String(), 601 config.Zip2zip.String(), 602 config.ManifestCheck.String(), 603 config.ConstructContext.String(), 604 }, " ")) 605} 606 607func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig { 608 return &GlobalConfig{ 609 DisablePreopt: false, 610 DisablePreoptModules: nil, 611 OnlyPreoptBootImageAndSystemServer: false, 612 HasSystemOther: false, 613 PatternsOnSystemOther: nil, 614 DisableGenerateProfile: false, 615 ProfileDir: "", 616 BootJars: android.EmptyConfiguredJarList(), 617 UpdatableBootJars: android.EmptyConfiguredJarList(), 618 ArtApexJars: android.EmptyConfiguredJarList(), 619 SystemServerJars: android.EmptyConfiguredJarList(), 620 SystemServerApps: nil, 621 UpdatableSystemServerJars: android.EmptyConfiguredJarList(), 622 SpeedApps: nil, 623 PreoptFlags: nil, 624 DefaultCompilerFilter: "", 625 SystemServerCompilerFilter: "", 626 GenerateDMFiles: false, 627 NoDebugInfo: false, 628 DontResolveStartupStrings: false, 629 AlwaysSystemServerDebugInfo: false, 630 NeverSystemServerDebugInfo: false, 631 AlwaysOtherDebugInfo: false, 632 NeverOtherDebugInfo: false, 633 IsEng: false, 634 SanitizeLite: false, 635 DefaultAppImages: false, 636 Dex2oatXmx: "", 637 Dex2oatXms: "", 638 EmptyDirectory: "empty_dir", 639 CpuVariant: nil, 640 InstructionSetFeatures: nil, 641 BootImageProfiles: nil, 642 BootFlags: "", 643 Dex2oatImageXmx: "", 644 Dex2oatImageXms: "", 645 } 646} 647 648func globalSoongConfigForTests() *GlobalSoongConfig { 649 return &GlobalSoongConfig{ 650 Profman: android.PathForTesting("profman"), 651 Dex2oat: android.PathForTesting("dex2oat"), 652 Aapt: android.PathForTesting("aapt"), 653 SoongZip: android.PathForTesting("soong_zip"), 654 Zip2zip: android.PathForTesting("zip2zip"), 655 ManifestCheck: android.PathForTesting("manifest_check"), 656 ConstructContext: android.PathForTesting("construct_context"), 657 } 658} 659