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
This commit is contained in:
@@ -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
|
// 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.
|
// 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 {
|
type GlobalJSONConfig struct {
|
||||||
GlobalConfig
|
GlobalConfig
|
||||||
|
|
||||||
@@ -199,9 +199,9 @@ func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := GlobalJSONConfig{}
|
config := GlobalJSONConfig{}
|
||||||
err := loadConfig(ctx, path, &config)
|
data, err := loadConfig(ctx, path, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return config.GlobalConfig, err
|
return config.GlobalConfig, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct paths that require a PathContext.
|
// 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.VerifyUsesLibraries = constructPath(ctx, config.Tools.VerifyUsesLibraries)
|
||||||
config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext)
|
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
|
// 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{}
|
config := ModuleJSONConfig{}
|
||||||
|
|
||||||
err := loadConfig(ctx, path, &config)
|
_, err := loadConfig(ctx, path, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return config.ModuleConfig, err
|
return config.ModuleConfig, err
|
||||||
}
|
}
|
||||||
@@ -259,24 +259,24 @@ func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error
|
|||||||
return config.ModuleConfig, nil
|
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)
|
r, err := ctx.Fs().Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(r)
|
data, err := ioutil.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(data, config)
|
err = json.Unmarshal(data, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
|
func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
|
||||||
|
@@ -78,7 +78,7 @@ func main() {
|
|||||||
|
|
||||||
ctx := &pathContext{android.TestConfig(*outDir, nil)}
|
ctx := &pathContext{android.TestConfig(*outDir, nil)}
|
||||||
|
|
||||||
globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath)
|
globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
|
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
|
@@ -115,6 +115,8 @@ func skipDexpreoptBootJars(ctx android.PathContext) bool {
|
|||||||
type dexpreoptBootJars struct {
|
type dexpreoptBootJars struct {
|
||||||
defaultBootImage *bootImage
|
defaultBootImage *bootImage
|
||||||
otherImages []*bootImage
|
otherImages []*bootImage
|
||||||
|
|
||||||
|
dexpreoptConfigForMake android.WritablePath
|
||||||
}
|
}
|
||||||
|
|
||||||
// dexpreoptBoot singleton rules
|
// dexpreoptBoot singleton rules
|
||||||
@@ -123,6 +125,9 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.dexpreoptConfigForMake = android.PathForOutput(ctx, ctx.Config().DeviceName(), "dexpreopt.config")
|
||||||
|
writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
|
||||||
|
|
||||||
global := dexpreoptGlobalConfig(ctx)
|
global := dexpreoptGlobalConfig(ctx)
|
||||||
|
|
||||||
// Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
|
// 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
|
// Export paths for default boot image to Make
|
||||||
func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
|
func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
|
||||||
|
if d.dexpreoptConfigForMake != nil {
|
||||||
|
ctx.Strict("DEX_PREOPT_CONFIG_FOR_MAKE", d.dexpreoptConfigForMake.String())
|
||||||
|
}
|
||||||
|
|
||||||
image := d.defaultBootImage
|
image := d.defaultBootImage
|
||||||
if image != nil {
|
if image != nil {
|
||||||
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
|
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
|
||||||
|
@@ -15,40 +15,50 @@
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
|
||||||
"android/soong/dexpreopt"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"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
|
// 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
|
// 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.
|
// for tests using setDexpreoptTestGlobalConfig.
|
||||||
func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig {
|
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{} {
|
return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
|
||||||
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
|
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
|
||||||
ctx.AddNinjaFileDeps(f)
|
ctx.AddNinjaFileDeps(f)
|
||||||
globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, f)
|
globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return globalConfig
|
return globalConfigAndRaw{globalConfig, data}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No global config filename set, see if there is a test config set
|
// No global config filename set, see if there is a test config set
|
||||||
return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} {
|
return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} {
|
||||||
// Nope, return a config with preopting disabled
|
// Nope, return a config with preopting disabled
|
||||||
return dexpreopt.GlobalConfig{
|
return globalConfigAndRaw{dexpreopt.GlobalConfig{
|
||||||
DisablePreopt: true,
|
DisablePreopt: true,
|
||||||
}
|
}, nil}
|
||||||
})
|
})
|
||||||
}).(dexpreopt.GlobalConfig)
|
}).(globalConfigAndRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must
|
// setDexpreoptTestGlobalConfig sets a GlobalConfig that future calls to dexpreoptGlobalConfig will return. It must
|
||||||
// be called before the first call to dexpreoptGlobalConfig for the config.
|
// be called before the first call to dexpreoptGlobalConfig for the config.
|
||||||
func setDexpreoptTestGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) {
|
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")
|
var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
|
||||||
|
Reference in New Issue
Block a user