diff --git a/android/Android.bp b/android/Android.bp index 2ac1d5fbe..26317b8e4 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -79,6 +79,7 @@ bootstrap_go_package { "prebuilt.go", "prebuilt_build_tool.go", "proto.go", + "provider.go", "register.go", "rule_builder.go", "sandbox.go", diff --git a/android/androidmk.go b/android/androidmk.go index c4b93c77f..097075e5b 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -159,7 +159,7 @@ type AndroidMkEntriesContext interface { } type AndroidMkExtraEntriesContext interface { - Provider(provider blueprint.ProviderKey) interface{} + Provider(provider blueprint.AnyProviderKey) (any, bool) } type androidMkExtraEntriesContext struct { @@ -167,8 +167,8 @@ type androidMkExtraEntriesContext struct { mod blueprint.Module } -func (a *androidMkExtraEntriesContext) Provider(provider blueprint.ProviderKey) interface{} { - return a.ctx.ModuleProvider(a.mod, provider) +func (a *androidMkExtraEntriesContext) Provider(provider blueprint.AnyProviderKey) (any, bool) { + return a.ctx.moduleProvider(a.mod, provider) } type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) @@ -492,8 +492,9 @@ type fillInEntriesContext interface { ModuleDir(module blueprint.Module) string ModuleSubDir(module blueprint.Module) string Config() Config - ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} - ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool + ModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) any + ModuleHasProvider(module blueprint.Module, provider blueprint.AnyProviderKey) bool + moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) ModuleType(module blueprint.Module) string } diff --git a/android/base_module_context.go b/android/base_module_context.go index 4312e9bd4..2a4b12ee5 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -79,26 +79,30 @@ type BaseModuleContext interface { // not set it returns the zero value of the type of the provider, so the return value can always // be type asserted to the type of the provider. The value returned may be a deep copy of the // value originally passed to SetProvider. - OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} + OtherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) any // OtherModuleHasProvider returns true if the provider for the given module has been set. - OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool + OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool + + otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) // Provider returns the value for a provider for the current module. If the value is // not set it returns the zero value of the type of the provider, so the return value can always // be type asserted to the type of the provider. It panics if called before the appropriate // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep // copy of the value originally passed to SetProvider. - Provider(provider blueprint.ProviderKey) interface{} + Provider(provider blueprint.AnyProviderKey) any // HasProvider returns true if the provider for the current module has been set. - HasProvider(provider blueprint.ProviderKey) bool + HasProvider(provider blueprint.AnyProviderKey) bool + + provider(provider blueprint.AnyProviderKey) (any, bool) // SetProvider sets the value for a provider for the current module. It panics if not called // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value // is not of the appropriate type, or if the value has already been set. The value should not // be modified after being passed to SetProvider. - SetProvider(provider blueprint.ProviderKey, value interface{}) + SetProvider(provider blueprint.AnyProviderKey, value interface{}) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module @@ -260,19 +264,35 @@ func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name strin func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { return b.bp.OtherModuleType(m) } -func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} { +func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) any { + value, _ := b.bp.OtherModuleProvider(m, provider) + return value +} + +func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool { + _, ok := b.bp.OtherModuleProvider(m, provider) + return ok +} + +func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { return b.bp.OtherModuleProvider(m, provider) } -func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool { - return b.bp.OtherModuleHasProvider(m, provider) + +func (b *baseModuleContext) Provider(provider blueprint.AnyProviderKey) any { + value, _ := b.bp.Provider(provider) + return value } -func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} { + +func (b *baseModuleContext) HasProvider(provider blueprint.AnyProviderKey) bool { + _, ok := b.bp.Provider(provider) + return ok +} + +func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) { return b.bp.Provider(provider) } -func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool { - return b.bp.HasProvider(provider) -} -func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) { + +func (b *baseModuleContext) SetProvider(provider blueprint.AnyProviderKey, value any) { b.bp.SetProvider(provider, value) } diff --git a/android/makevars.go b/android/makevars.go index 0800190c3..5a9fe7c66 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -92,7 +92,8 @@ type MakeVarsContext interface { ModuleDir(module blueprint.Module) string ModuleSubDir(module blueprint.Module) string ModuleType(module blueprint.Module) string - ModuleProvider(module blueprint.Module, key blueprint.ProviderKey) interface{} + ModuleProvider(module blueprint.Module, key blueprint.AnyProviderKey) any + moduleProvider(module blueprint.Module, key blueprint.AnyProviderKey) (any, bool) BlueprintFile(module blueprint.Module) string ModuleErrorf(module blueprint.Module, format string, args ...interface{}) diff --git a/android/mutator.go b/android/mutator.go index 0d391a47b..93c519d27 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -325,7 +325,7 @@ type BottomUpMutatorContext interface { // if the value is not of the appropriate type, or if the module is not a newly created // variant of the current module. The value should not be modified after being passed to // SetVariationProvider. - SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) + SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{}) } type bottomUpMutatorContext struct { @@ -746,6 +746,6 @@ func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVaria b.bp.CreateAliasVariation(fromVariationName, toVariationName) } -func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) { +func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{}) { b.bp.SetVariationProvider(module, provider, value) } diff --git a/android/provider.go b/android/provider.go new file mode 100644 index 000000000..b2cc7c06d --- /dev/null +++ b/android/provider.go @@ -0,0 +1,120 @@ +package android + +import ( + "github.com/google/blueprint" +) + +// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext for use in OtherModuleProvider. +type OtherModuleProviderContext interface { + otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) +} + +var _ OtherModuleProviderContext = BaseModuleContext(nil) +var _ OtherModuleProviderContext = ModuleContext(nil) +var _ OtherModuleProviderContext = BottomUpMutatorContext(nil) +var _ OtherModuleProviderContext = TopDownMutatorContext(nil) + +// OtherModuleProvider reads the provider for the given module. If the provider has been set the value is +// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned +// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. +// +// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext. +func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) { + value, ok := ctx.otherModuleProvider(module, provider) + if !ok { + var k K + return k, false + } + return value.(K), ok +} + +// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext for use in ModuleProvider. +type ModuleProviderContext interface { + provider(provider blueprint.AnyProviderKey) (any, bool) +} + +var _ ModuleProviderContext = BaseModuleContext(nil) +var _ ModuleProviderContext = ModuleContext(nil) +var _ ModuleProviderContext = BottomUpMutatorContext(nil) +var _ ModuleProviderContext = TopDownMutatorContext(nil) + +// ModuleProvider reads the provider for the current module. If the provider has been set the value is +// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned +// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. +// +// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext. +func ModuleProvider[K any](ctx ModuleProviderContext, provider blueprint.ProviderKey[K]) (K, bool) { + value, ok := ctx.provider(provider) + if !ok { + var k K + return k, false + } + return value.(K), ok +} + +type SingletonModuleProviderContext interface { + moduleProvider(blueprint.Module, blueprint.AnyProviderKey) (any, bool) +} + +var _ SingletonModuleProviderContext = SingletonContext(nil) +var _ SingletonModuleProviderContext = (*TestContext)(nil) + +// SingletonModuleProvider wraps blueprint.SingletonModuleProvider to provide a type-safe method to retrieve the value +// of the given provider from a module using a SingletonContext. If the provider has not been set the first return +// value will be the zero value of the provider's type, and the second return value will be false. If the provider has +// been set the second return value will be true. +func SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) { + value, ok := ctx.moduleProvider(module, provider) + if !ok { + var k K + return k, false + } + return value.(K), ok +} + +// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext for use in SetProvider. +type SetProviderContext interface { + SetProvider(provider blueprint.AnyProviderKey, value any) +} + +var _ SetProviderContext = BaseModuleContext(nil) +var _ SetProviderContext = ModuleContext(nil) +var _ SetProviderContext = BottomUpMutatorContext(nil) +var _ SetProviderContext = TopDownMutatorContext(nil) + +// SetProvider sets the value for a provider for the current module. It panics if not called +// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value +// is not of the appropriate type, or if the value has already been set. The value should not +// be modified after being passed to SetProvider. +// +// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext. +func SetProvider[K any](ctx SetProviderContext, provider blueprint.ProviderKey[K], value K) { + ctx.SetProvider(provider, value) +} + +var _ OtherModuleProviderContext = (*otherModuleProviderAdaptor)(nil) + +// An OtherModuleProviderFunc can be passed to NewOtherModuleProviderAdaptor to create an OtherModuleProviderContext +// for use in tests. +type OtherModuleProviderFunc func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) + +type otherModuleProviderAdaptor struct { + otherModuleProviderFunc OtherModuleProviderFunc +} + +func (p *otherModuleProviderAdaptor) otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { + return p.otherModuleProviderFunc(module, provider) +} + +// NewOtherModuleProviderAdaptor returns an OtherModuleProviderContext that proxies calls to otherModuleProvider to +// the provided OtherModuleProviderFunc. It can be used in tests to unit test methods that need to call +// android.OtherModuleProvider. +func NewOtherModuleProviderAdaptor(otherModuleProviderFunc OtherModuleProviderFunc) OtherModuleProviderContext { + return &otherModuleProviderAdaptor{otherModuleProviderFunc} +} diff --git a/android/singleton.go b/android/singleton.go index 7c6cf4fd6..8936cac65 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -20,6 +20,8 @@ import ( // SingletonContext type SingletonContext interface { + blueprintSingletonContext() blueprint.SingletonContext + Config() Config DeviceConfig() DeviceConfig @@ -38,10 +40,12 @@ type SingletonContext interface { // return value can always be type-asserted to the type of the provider. The return value should // always be considered read-only. It panics if called before the appropriate mutator or // GenerateBuildActions pass for the provider on the module. - ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} + ModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) any // ModuleHasProvider returns true if the provider for the given module has been set. - ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool + ModuleHasProvider(module blueprint.Module, provider blueprint.AnyProviderKey) bool + + moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) ModuleErrorf(module blueprint.Module, format string, args ...interface{}) Errorf(format string, args ...interface{}) @@ -135,6 +139,10 @@ type singletonContextAdaptor struct { ruleParams map[blueprint.Rule]blueprint.RuleParams } +func (s *singletonContextAdaptor) blueprintSingletonContext() blueprint.SingletonContext { + return s.SingletonContext +} + func (s *singletonContextAdaptor) Config() Config { return s.SingletonContext.Config().(Config) } @@ -282,3 +290,18 @@ func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name st } return result } + +func (s *singletonContextAdaptor) ModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) any { + value, _ := s.SingletonContext.ModuleProvider(module, provider) + return value +} + +// ModuleHasProvider returns true if the provider for the given module has been set. +func (s *singletonContextAdaptor) ModuleHasProvider(module blueprint.Module, provider blueprint.AnyProviderKey) bool { + _, ok := s.SingletonContext.ModuleProvider(module, provider) + return ok +} + +func (s *singletonContextAdaptor) moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { + return s.SingletonContext.ModuleProvider(module, provider) +} diff --git a/android/testing.go b/android/testing.go index fa4dffd9b..39a268b23 100644 --- a/android/testing.go +++ b/android/testing.go @@ -203,7 +203,17 @@ func (ctx *TestContext) HardCodedPreArchMutators(f RegisterMutatorFunc) { ctx.PreArchMutators(f) } -func (ctx *TestContext) ModuleProvider(m blueprint.Module, p blueprint.ProviderKey) interface{} { +func (ctx *TestContext) ModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) any { + value, _ := ctx.Context.ModuleProvider(m, p) + return value +} + +func (ctx *TestContext) ModuleHasProvider(m blueprint.Module, p blueprint.AnyProviderKey) bool { + _, ok := ctx.Context.ModuleProvider(m, p) + return ok +} + +func (ctx *TestContext) moduleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) { return ctx.Context.ModuleProvider(m, p) } @@ -225,6 +235,12 @@ func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) { ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f) } +func (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext { + return NewOtherModuleProviderAdaptor(func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { + return ctx.moduleProvider(module, provider) + }) +} + // registeredComponentOrder defines the order in which a sortableComponent type is registered at // runtime and provides support for reordering the components registered for a test in the same // way. diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go index 9142eed99..1ce60ced9 100644 --- a/apex/classpath_element_test.go +++ b/apex/classpath_element_test.go @@ -33,11 +33,11 @@ type testClasspathElementContext struct { errs []error } -func (t *testClasspathElementContext) OtherModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool { +func (t *testClasspathElementContext) OtherModuleHasProvider(module blueprint.Module, provider blueprint.AnyProviderKey) bool { return t.testContext.ModuleHasProvider(module, provider) } -func (t *testClasspathElementContext) OtherModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} { +func (t *testClasspathElementContext) OtherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) interface{} { return t.testContext.ModuleProvider(module, provider) } diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go index 3cff60fe6..eea857239 100644 --- a/bloaty/bloaty.go +++ b/bloaty/bloaty.go @@ -26,7 +26,7 @@ const bloatyDescriptorExt = ".bloaty.csv" const protoFilename = "binary_sizes.pb.gz" var ( - fileSizeMeasurerKey blueprint.ProviderKey + fileSizeMeasurerKey blueprint.ProviderKey[measuredFiles] pctx = android.NewPackageContext("android/soong/bloaty") // bloaty is used to measure a binary section sizes. diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go index 31e668ea9..cfc9ed215 100644 --- a/cc/sanitize_test.go +++ b/cc/sanitize_test.go @@ -49,7 +49,7 @@ var prepareForTsanTest = android.FixtureAddFile("tsan/Android.bp", []byte(` `)) type providerInterface interface { - ModuleProvider(blueprint.Module, blueprint.ProviderKey) interface{} + ModuleProvider(blueprint.Module, blueprint.AnyProviderKey) interface{} } // expectSharedLinkDep verifies that the from module links against the to module as a diff --git a/java/classpath_element.go b/java/classpath_element.go index 496291678..af99fb4fb 100644 --- a/java/classpath_element.go +++ b/java/classpath_element.go @@ -72,8 +72,8 @@ var _ ClasspathElement = (*ClasspathLibraryElement)(nil) // ClasspathElementContext defines the context methods needed by CreateClasspathElements type ClasspathElementContext interface { - OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool - OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} + OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool + OtherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) interface{} ModuleErrorf(fmt string, args ...interface{}) }