From 2d00f0dcae6c843d4c98cebfe81a901adb0897c5 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 9 May 2019 21:50:00 -0700 Subject: [PATCH] Write dexpreopt.config again during the build Writing $OUT/dexpreopt.config during build setup and then using it during the build causes bad incremental builds if a cleanspec removes $OUT/dexpreopt.config. Create a rule in Soong to write out a copy so that it is a normal build artifact. Bug: 132379813 Test: m checkbuild Change-Id: I7755a7f8c1d6561fc83022a7f4cf7e4a64e989c9 --- dexpreopt/config.go | 20 +++++++++--------- dexpreopt/dexpreopt_gen/dexpreopt_gen.go | 2 +- java/dexpreopt_bootjars.go | 21 +++++++++++++++++++ java/dexpreopt_config.go | 26 ++++++++++++++++-------- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/dexpreopt/config.go b/dexpreopt/config.go index 3b77042ba..1e0f862ed 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -176,7 +176,7 @@ func constructWritablePath(ctx android.PathContext, path string) android.Writabl // 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) { +func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, []byte, error) { type GlobalJSONConfig struct { GlobalConfig @@ -199,9 +199,9 @@ func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, error } config := GlobalJSONConfig{} - err := loadConfig(ctx, path, &config) + data, err := loadConfig(ctx, path, &config) if err != nil { - return config.GlobalConfig, err + return config.GlobalConfig, nil, err } // Construct paths that require a PathContext. @@ -217,7 +217,7 @@ func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, error config.GlobalConfig.Tools.VerifyUsesLibraries = constructPath(ctx, config.Tools.VerifyUsesLibraries) config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext) - return config.GlobalConfig, nil + return config.GlobalConfig, data, nil } // LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct. It is not used in Soong, which @@ -241,7 +241,7 @@ func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error config := ModuleJSONConfig{} - err := loadConfig(ctx, path, &config) + _, err := loadConfig(ctx, path, &config) if err != nil { return config.ModuleConfig, err } @@ -259,24 +259,24 @@ func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error return config.ModuleConfig, nil } -func loadConfig(ctx android.PathContext, path string, config interface{}) error { +func loadConfig(ctx android.PathContext, path string, config interface{}) ([]byte, error) { r, err := ctx.Fs().Open(path) if err != nil { - return err + return nil, err } defer r.Close() data, err := ioutil.ReadAll(r) if err != nil { - return err + return nil, err } err = json.Unmarshal(data, config) if err != nil { - return err + return nil, err } - return nil + return data, nil } func GlobalConfigForTests(ctx android.PathContext) GlobalConfig { diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go index c72f6842d..d54ddb1f0 100644 --- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go +++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go @@ -78,7 +78,7 @@ func main() { ctx := &pathContext{android.TestConfig(*outDir, nil)} - globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath) + globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath) if err != nil { fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err) os.Exit(2) diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index f48428f46..2a1a901b7 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -115,6 +115,8 @@ func skipDexpreoptBootJars(ctx android.PathContext) bool { type dexpreoptBootJars struct { defaultBootImage *bootImage otherImages []*bootImage + + dexpreoptConfigForMake android.WritablePath } // dexpreoptBoot singleton rules @@ -123,6 +125,9 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) { return } + d.dexpreoptConfigForMake = android.PathForOutput(ctx, ctx.Config().DeviceName(), "dexpreopt.config") + writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake) + global := dexpreoptGlobalConfig(ctx) // Skip recompiling the boot image for the second sanitization phase. We'll get separate paths @@ -453,8 +458,24 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImage) { } +func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) { + data := dexpreoptGlobalConfigRaw(ctx).data + + ctx.Build(pctx, android.BuildParams{ + Rule: android.WriteFile, + Output: path, + Args: map[string]string{ + "content": string(data), + }, + }) +} + // Export paths for default boot image to Make func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { + if d.dexpreoptConfigForMake != nil { + ctx.Strict("DEX_PREOPT_CONFIG_FOR_MAKE", d.dexpreoptConfigForMake.String()) + } + image := d.defaultBootImage if image != nil { ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String()) diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 270fcb473..d903f456a 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -15,40 +15,50 @@ package java import ( - "android/soong/android" - "android/soong/dexpreopt" "path/filepath" "strings" + + "android/soong/android" + "android/soong/dexpreopt" ) // dexpreoptGlobalConfig returns the global dexpreopt.config. It is loaded once the first time it is called for any // ctx.Config(), and returns the same data for all future calls with the same ctx.Config(). A value can be inserted // for tests using setDexpreoptTestGlobalConfig. func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig { + return dexpreoptGlobalConfigRaw(ctx).global +} + +type globalConfigAndRaw struct { + global dexpreopt.GlobalConfig + data []byte +} + +func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw { return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} { if f := ctx.Config().DexpreoptGlobalConfig(); f != "" { ctx.AddNinjaFileDeps(f) - globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, f) + globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f) if err != nil { panic(err) } - return globalConfig + return globalConfigAndRaw{globalConfig, data} } // No global config filename set, see if there is a test config set return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} { // Nope, return a config with preopting disabled - return dexpreopt.GlobalConfig{ + return globalConfigAndRaw{dexpreopt.GlobalConfig{ DisablePreopt: true, - } + }, nil} }) - }).(dexpreopt.GlobalConfig) + }).(globalConfigAndRaw) } // setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must // be called before the first call to dexpreoptGlobalConfig for the config. func setDexpreoptTestGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) { - config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfig }) + config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil} }) } var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")