Loading README.md +0 −6 Original line number Diff line number Diff line Loading @@ -594,12 +594,6 @@ modules (`cc_defaults`, `java_defaults`, etc.), which can then be referenced by all of the vendor's other modules using the normal namespace and visibility rules. `soongConfigTraceMutator` enables modules affected by soong config variables to write outputs into a hashed directory path. It does this by recording accesses to soong config variables on each module, and then accumulating records of each module's all dependencies. `m soong_config_trace` builds information about hashes to `$OUT_DIR/soong/soong_config_trace.json`. ## Build logic The build logic is written in Go using the Loading android/module.go +0 −89 Original line number Diff line number Diff line Loading @@ -15,9 +15,6 @@ package android import ( "crypto/md5" "encoding/hex" "encoding/json" "fmt" "net/url" "path/filepath" Loading Loading @@ -247,31 +244,6 @@ func SortedUniqueNamedPaths(l NamedPaths) NamedPaths { return l[:k+1] } // soongConfigTrace holds all references to VendorVars. Uses []string for blueprint:"mutated" type soongConfigTrace struct { Bools []string `json:",omitempty"` Strings []string `json:",omitempty"` IsSets []string `json:",omitempty"` } func (c *soongConfigTrace) isEmpty() bool { return len(c.Bools) == 0 && len(c.Strings) == 0 && len(c.IsSets) == 0 } // Returns hash of serialized trace records (empty string if there's no trace recorded) func (c *soongConfigTrace) hash() string { // Use MD5 for speed. We don't care collision or preimage attack if c.isEmpty() { return "" } j, err := json.Marshal(c) if err != nil { panic(fmt.Errorf("json marshal of %#v failed: %#v", *c, err)) } hash := md5.Sum(j) return hex.EncodeToString(hash[:]) } type nameProperties struct { // The name of the module. Must be unique across all modules. Name *string Loading Loading @@ -523,14 +495,6 @@ type commonProperties struct { // constants in image.go, but can also be set to a custom value by individual module types. ImageVariation string `blueprint:"mutated"` // SoongConfigTrace records accesses to VendorVars (soong_config). The trace will be hashed // and used as a subdir of PathForModuleOut. Note that we mainly focus on incremental // builds among similar products (e.g. aosp_cf_x86_64_phone and aosp_cf_x86_64_foldable), // and there are variables other than soong_config, which isn't captured by soong config // trace, but influence modules among products. SoongConfigTrace soongConfigTrace `blueprint:"mutated"` SoongConfigTraceHash string `blueprint:"mutated"` // The team (defined by the owner/vendor) who owns the property. Team *string `android:"path"` } Loading Loading @@ -2614,8 +2578,6 @@ type HostToolProvider interface { func init() { RegisterParallelSingletonType("buildtarget", BuildTargetSingleton) RegisterParallelSingletonType("soongconfigtrace", soongConfigTraceSingletonFunc) FinalDepsMutators(registerSoongConfigTraceMutator) } func BuildTargetSingleton() Singleton { Loading Loading @@ -2777,54 +2739,3 @@ func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents strin bpctx := ctx.blueprintBaseModuleContext() return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents) } func registerSoongConfigTraceMutator(ctx RegisterMutatorsContext) { ctx.BottomUp("soongconfigtrace", soongConfigTraceMutator).Parallel() } // soongConfigTraceMutator accumulates recorded soong_config trace from children. Also it normalizes // SoongConfigTrace to make it consistent. func soongConfigTraceMutator(ctx BottomUpMutatorContext) { trace := &ctx.Module().base().commonProperties.SoongConfigTrace ctx.VisitDirectDeps(func(m Module) { childTrace := &m.base().commonProperties.SoongConfigTrace trace.Bools = append(trace.Bools, childTrace.Bools...) trace.Strings = append(trace.Strings, childTrace.Strings...) trace.IsSets = append(trace.IsSets, childTrace.IsSets...) }) trace.Bools = SortedUniqueStrings(trace.Bools) trace.Strings = SortedUniqueStrings(trace.Strings) trace.IsSets = SortedUniqueStrings(trace.IsSets) ctx.Module().base().commonProperties.SoongConfigTraceHash = trace.hash() } // soongConfigTraceSingleton writes a map from each module's config hash value to trace data. func soongConfigTraceSingletonFunc() Singleton { return &soongConfigTraceSingleton{} } type soongConfigTraceSingleton struct { } func (s *soongConfigTraceSingleton) GenerateBuildActions(ctx SingletonContext) { outFile := PathForOutput(ctx, "soong_config_trace.json") traces := make(map[string]*soongConfigTrace) ctx.VisitAllModules(func(module Module) { trace := &module.base().commonProperties.SoongConfigTrace if !trace.isEmpty() { hash := module.base().commonProperties.SoongConfigTraceHash traces[hash] = trace } }) j, err := json.Marshal(traces) if err != nil { ctx.Errorf("json marshal to %q failed: %#v", outFile, err) return } WriteFileRule(ctx, outFile, string(j)) ctx.Phony("soong_config_trace", outFile) } android/module_context.go +0 −5 Original line number Diff line number Diff line Loading @@ -188,7 +188,6 @@ type ModuleContext interface { TargetRequiredModuleNames() []string ModuleSubDir() string SoongConfigTraceHash() string Variable(pctx PackageContext, name, value string) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule Loading Loading @@ -382,10 +381,6 @@ func (m *moduleContext) ModuleSubDir() string { return m.bp.ModuleSubDir() } func (m *moduleContext) SoongConfigTraceHash() string { return m.module.base().commonProperties.SoongConfigTraceHash } func (m *moduleContext) InstallInData() bool { return m.module.InstallInData() } Loading android/paths.go +1 −2 Original line number Diff line number Diff line Loading @@ -1604,11 +1604,10 @@ type ModuleOutPathContext interface { ModuleName() string ModuleDir() string ModuleSubDir() string SoongConfigTraceHash() string } func pathForModuleOut(ctx ModuleOutPathContext) OutputPath { return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir(), ctx.SoongConfigTraceHash()) return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir()) } // PathForModuleOut returns a Path representing the paths... under the module's Loading android/soong_config_modules.go +2 −55 Original line number Diff line number Diff line Loading @@ -463,57 +463,6 @@ func loadSoongConfigModuleTypeDefinition(ctx LoadHookContext, from string) map[s }).(map[string]blueprint.ModuleFactory) } // tracingConfig is a wrapper to soongconfig.SoongConfig which records all accesses to SoongConfig. type tracingConfig struct { config soongconfig.SoongConfig boolSet map[string]bool stringSet map[string]string isSetSet map[string]bool } func (c *tracingConfig) Bool(name string) bool { c.boolSet[name] = c.config.Bool(name) return c.boolSet[name] } func (c *tracingConfig) String(name string) string { c.stringSet[name] = c.config.String(name) return c.stringSet[name] } func (c *tracingConfig) IsSet(name string) bool { c.isSetSet[name] = c.config.IsSet(name) return c.isSetSet[name] } func (c *tracingConfig) getTrace() soongConfigTrace { ret := soongConfigTrace{} for k, v := range c.boolSet { ret.Bools = append(ret.Bools, fmt.Sprintf("%q:%t", k, v)) } for k, v := range c.stringSet { ret.Strings = append(ret.Strings, fmt.Sprintf("%q:%q", k, v)) } for k, v := range c.isSetSet { ret.IsSets = append(ret.IsSets, fmt.Sprintf("%q:%t", k, v)) } return ret } func newTracingConfig(config soongconfig.SoongConfig) *tracingConfig { c := tracingConfig{ config: config, boolSet: make(map[string]bool), stringSet: make(map[string]string), isSetSet: make(map[string]bool), } return &c } var _ soongconfig.SoongConfig = (*tracingConfig)(nil) // configModuleFactory takes an existing soongConfigModuleFactory and a // ModuleType to create a new ModuleFactory that uses a custom loadhook. func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfig.ModuleType) blueprint.ModuleFactory { Loading Loading @@ -561,8 +510,8 @@ func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfi // conditional on Soong config variables by reading the product // config variables from Make. AddLoadHook(module, func(ctx LoadHookContext) { tracingConfig := newTracingConfig(ctx.Config().VendorConfig(moduleType.ConfigNamespace)) newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, tracingConfig) config := ctx.Config().VendorConfig(moduleType.ConfigNamespace) newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, config) if err != nil { ctx.ModuleErrorf("%s", err) return Loading @@ -570,8 +519,6 @@ func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfi for _, ps := range newProps { ctx.AppendProperties(ps) } module.(Module).base().commonProperties.SoongConfigTrace = tracingConfig.getTrace() }) return module, props } Loading Loading
README.md +0 −6 Original line number Diff line number Diff line Loading @@ -594,12 +594,6 @@ modules (`cc_defaults`, `java_defaults`, etc.), which can then be referenced by all of the vendor's other modules using the normal namespace and visibility rules. `soongConfigTraceMutator` enables modules affected by soong config variables to write outputs into a hashed directory path. It does this by recording accesses to soong config variables on each module, and then accumulating records of each module's all dependencies. `m soong_config_trace` builds information about hashes to `$OUT_DIR/soong/soong_config_trace.json`. ## Build logic The build logic is written in Go using the Loading
android/module.go +0 −89 Original line number Diff line number Diff line Loading @@ -15,9 +15,6 @@ package android import ( "crypto/md5" "encoding/hex" "encoding/json" "fmt" "net/url" "path/filepath" Loading Loading @@ -247,31 +244,6 @@ func SortedUniqueNamedPaths(l NamedPaths) NamedPaths { return l[:k+1] } // soongConfigTrace holds all references to VendorVars. Uses []string for blueprint:"mutated" type soongConfigTrace struct { Bools []string `json:",omitempty"` Strings []string `json:",omitempty"` IsSets []string `json:",omitempty"` } func (c *soongConfigTrace) isEmpty() bool { return len(c.Bools) == 0 && len(c.Strings) == 0 && len(c.IsSets) == 0 } // Returns hash of serialized trace records (empty string if there's no trace recorded) func (c *soongConfigTrace) hash() string { // Use MD5 for speed. We don't care collision or preimage attack if c.isEmpty() { return "" } j, err := json.Marshal(c) if err != nil { panic(fmt.Errorf("json marshal of %#v failed: %#v", *c, err)) } hash := md5.Sum(j) return hex.EncodeToString(hash[:]) } type nameProperties struct { // The name of the module. Must be unique across all modules. Name *string Loading Loading @@ -523,14 +495,6 @@ type commonProperties struct { // constants in image.go, but can also be set to a custom value by individual module types. ImageVariation string `blueprint:"mutated"` // SoongConfigTrace records accesses to VendorVars (soong_config). The trace will be hashed // and used as a subdir of PathForModuleOut. Note that we mainly focus on incremental // builds among similar products (e.g. aosp_cf_x86_64_phone and aosp_cf_x86_64_foldable), // and there are variables other than soong_config, which isn't captured by soong config // trace, but influence modules among products. SoongConfigTrace soongConfigTrace `blueprint:"mutated"` SoongConfigTraceHash string `blueprint:"mutated"` // The team (defined by the owner/vendor) who owns the property. Team *string `android:"path"` } Loading Loading @@ -2614,8 +2578,6 @@ type HostToolProvider interface { func init() { RegisterParallelSingletonType("buildtarget", BuildTargetSingleton) RegisterParallelSingletonType("soongconfigtrace", soongConfigTraceSingletonFunc) FinalDepsMutators(registerSoongConfigTraceMutator) } func BuildTargetSingleton() Singleton { Loading Loading @@ -2777,54 +2739,3 @@ func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents strin bpctx := ctx.blueprintBaseModuleContext() return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents) } func registerSoongConfigTraceMutator(ctx RegisterMutatorsContext) { ctx.BottomUp("soongconfigtrace", soongConfigTraceMutator).Parallel() } // soongConfigTraceMutator accumulates recorded soong_config trace from children. Also it normalizes // SoongConfigTrace to make it consistent. func soongConfigTraceMutator(ctx BottomUpMutatorContext) { trace := &ctx.Module().base().commonProperties.SoongConfigTrace ctx.VisitDirectDeps(func(m Module) { childTrace := &m.base().commonProperties.SoongConfigTrace trace.Bools = append(trace.Bools, childTrace.Bools...) trace.Strings = append(trace.Strings, childTrace.Strings...) trace.IsSets = append(trace.IsSets, childTrace.IsSets...) }) trace.Bools = SortedUniqueStrings(trace.Bools) trace.Strings = SortedUniqueStrings(trace.Strings) trace.IsSets = SortedUniqueStrings(trace.IsSets) ctx.Module().base().commonProperties.SoongConfigTraceHash = trace.hash() } // soongConfigTraceSingleton writes a map from each module's config hash value to trace data. func soongConfigTraceSingletonFunc() Singleton { return &soongConfigTraceSingleton{} } type soongConfigTraceSingleton struct { } func (s *soongConfigTraceSingleton) GenerateBuildActions(ctx SingletonContext) { outFile := PathForOutput(ctx, "soong_config_trace.json") traces := make(map[string]*soongConfigTrace) ctx.VisitAllModules(func(module Module) { trace := &module.base().commonProperties.SoongConfigTrace if !trace.isEmpty() { hash := module.base().commonProperties.SoongConfigTraceHash traces[hash] = trace } }) j, err := json.Marshal(traces) if err != nil { ctx.Errorf("json marshal to %q failed: %#v", outFile, err) return } WriteFileRule(ctx, outFile, string(j)) ctx.Phony("soong_config_trace", outFile) }
android/module_context.go +0 −5 Original line number Diff line number Diff line Loading @@ -188,7 +188,6 @@ type ModuleContext interface { TargetRequiredModuleNames() []string ModuleSubDir() string SoongConfigTraceHash() string Variable(pctx PackageContext, name, value string) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule Loading Loading @@ -382,10 +381,6 @@ func (m *moduleContext) ModuleSubDir() string { return m.bp.ModuleSubDir() } func (m *moduleContext) SoongConfigTraceHash() string { return m.module.base().commonProperties.SoongConfigTraceHash } func (m *moduleContext) InstallInData() bool { return m.module.InstallInData() } Loading
android/paths.go +1 −2 Original line number Diff line number Diff line Loading @@ -1604,11 +1604,10 @@ type ModuleOutPathContext interface { ModuleName() string ModuleDir() string ModuleSubDir() string SoongConfigTraceHash() string } func pathForModuleOut(ctx ModuleOutPathContext) OutputPath { return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir(), ctx.SoongConfigTraceHash()) return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir()) } // PathForModuleOut returns a Path representing the paths... under the module's Loading
android/soong_config_modules.go +2 −55 Original line number Diff line number Diff line Loading @@ -463,57 +463,6 @@ func loadSoongConfigModuleTypeDefinition(ctx LoadHookContext, from string) map[s }).(map[string]blueprint.ModuleFactory) } // tracingConfig is a wrapper to soongconfig.SoongConfig which records all accesses to SoongConfig. type tracingConfig struct { config soongconfig.SoongConfig boolSet map[string]bool stringSet map[string]string isSetSet map[string]bool } func (c *tracingConfig) Bool(name string) bool { c.boolSet[name] = c.config.Bool(name) return c.boolSet[name] } func (c *tracingConfig) String(name string) string { c.stringSet[name] = c.config.String(name) return c.stringSet[name] } func (c *tracingConfig) IsSet(name string) bool { c.isSetSet[name] = c.config.IsSet(name) return c.isSetSet[name] } func (c *tracingConfig) getTrace() soongConfigTrace { ret := soongConfigTrace{} for k, v := range c.boolSet { ret.Bools = append(ret.Bools, fmt.Sprintf("%q:%t", k, v)) } for k, v := range c.stringSet { ret.Strings = append(ret.Strings, fmt.Sprintf("%q:%q", k, v)) } for k, v := range c.isSetSet { ret.IsSets = append(ret.IsSets, fmt.Sprintf("%q:%t", k, v)) } return ret } func newTracingConfig(config soongconfig.SoongConfig) *tracingConfig { c := tracingConfig{ config: config, boolSet: make(map[string]bool), stringSet: make(map[string]string), isSetSet: make(map[string]bool), } return &c } var _ soongconfig.SoongConfig = (*tracingConfig)(nil) // configModuleFactory takes an existing soongConfigModuleFactory and a // ModuleType to create a new ModuleFactory that uses a custom loadhook. func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfig.ModuleType) blueprint.ModuleFactory { Loading Loading @@ -561,8 +510,8 @@ func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfi // conditional on Soong config variables by reading the product // config variables from Make. AddLoadHook(module, func(ctx LoadHookContext) { tracingConfig := newTracingConfig(ctx.Config().VendorConfig(moduleType.ConfigNamespace)) newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, tracingConfig) config := ctx.Config().VendorConfig(moduleType.ConfigNamespace) newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, config) if err != nil { ctx.ModuleErrorf("%s", err) return Loading @@ -570,8 +519,6 @@ func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfi for _, ps := range newProps { ctx.AppendProperties(ps) } module.(Module).base().commonProperties.SoongConfigTrace = tracingConfig.getTrace() }) return module, props } Loading