From d19f894512ba558fe1ac6811a74c4c17218ead7e Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Wed, 14 Jul 2021 12:08:37 +0100 Subject: Add support to sdk/module_exports to specify required traits Currently, every sdk member of a specific module type has to be treated in the same way as every other sdk member of that type. e.g. it is not possible for an sdk member to use different variants to other members of the same type. Adding a new member type for each different way to treat the members is not scalable as if there were N different ways treat a member then it would require 2^N types for all the possible combinations. This adds a new traits mechanism that allows the behavior of member types to be customized per sdk member. Each member type can specify a list of supported traits and customize its behavior based on which traits are required for each member. A trait can be supported by multiple different member types. Bug: 195754365 Test: m nothing Change-Id: I165ac80d208c0402d2a9ffa8085bba29562c19b7 --- sdk/sdk.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) (limited to 'sdk/sdk.go') diff --git a/sdk/sdk.go b/sdk/sdk.go index 6dea752b3..949a4b4f8 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -53,6 +53,13 @@ type sdk struct { // list properties, e.g. java_libs. dynamicMemberTypeListProperties interface{} + // The dynamically generated information about the registered SdkMemberTrait + dynamicSdkMemberTraits *dynamicSdkMemberTraits + + // The dynamically created instance of the properties struct containing the sdk member trait + // list properties. + dynamicMemberTraitListProperties interface{} + // Information about the OsType specific member variants depended upon by this variant. // // Set by OsType specific variants in the collectMembers() method and used by the @@ -114,7 +121,20 @@ func newSdkModule(moduleExports bool) *sdk { // Create an instance of the dynamically created struct that contains all the // properties for the member type specific list properties. s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberTypeListProperties() - s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties) + + traitRegistry := android.RegisteredSdkMemberTraits + s.dynamicSdkMemberTraits = getDynamicSdkMemberTraits(traitRegistry) + // Create an instance of the dynamically created struct that contains all the properties for the + // member trait specific list properties. + s.dynamicMemberTraitListProperties = s.dynamicSdkMemberTraits.createMemberTraitListProperties() + + // Create a wrapper around the dynamic trait specific properties so that they have to be + // specified within a traits:{} section in the .bp file. + traitsWrapper := struct { + Traits interface{} + }{s.dynamicMemberTraitListProperties} + + s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties, &traitsWrapper) // Make sure that the prebuilt visibility property is verified for errors. android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility) @@ -145,6 +165,11 @@ func (s *sdk) memberTypeListProperty(memberType android.SdkMemberType) *sdkMembe return s.dynamicSdkMemberTypes.memberTypeToProperty[memberType] } +// memberTraitListProperties returns the list of *sdkMemberTraitListProperty instances for this sdk. +func (s *sdk) memberTraitListProperties() []*sdkMemberTraitListProperty { + return s.dynamicSdkMemberTraits.memberTraitListProperties +} + func (s *sdk) snapshot() bool { return s.properties.Snapshot } @@ -198,15 +223,53 @@ func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries { }} } +// gatherTraits gathers the traits from the dynamically generated trait specific properties. +// +// Returns a map from member name to the set of required traits. +func (s *sdk) gatherTraits() map[string]android.SdkMemberTraitSet { + traitListByMember := map[string][]android.SdkMemberTrait{} + for _, memberListProperty := range s.memberTraitListProperties() { + names := memberListProperty.getter(s.dynamicMemberTraitListProperties) + for _, name := range names { + traitListByMember[name] = append(traitListByMember[name], memberListProperty.memberTrait) + } + } + + traitSetByMember := map[string]android.SdkMemberTraitSet{} + for name, list := range traitListByMember { + traitSetByMember[name] = android.NewSdkMemberTraitSet(list) + } + + return traitSetByMember +} + // newDependencyContext creates a new SdkDependencyContext for this sdk. func (s *sdk) newDependencyContext(mctx android.BottomUpMutatorContext) android.SdkDependencyContext { + traits := s.gatherTraits() + return &dependencyContext{ BottomUpMutatorContext: mctx, + requiredTraits: traits, } } type dependencyContext struct { android.BottomUpMutatorContext + + // Map from member name to the set of traits that the sdk requires the member provides. + requiredTraits map[string]android.SdkMemberTraitSet +} + +func (d *dependencyContext) RequiredTraits(name string) android.SdkMemberTraitSet { + if s, ok := d.requiredTraits[name]; ok { + return s + } else { + return android.EmptySdkMemberTraitSet() + } +} + +func (d *dependencyContext) RequiresTrait(name string, trait android.SdkMemberTrait) bool { + return d.RequiredTraits(name).Contains(trait) } var _ android.SdkDependencyContext = (*dependencyContext)(nil) @@ -287,8 +350,21 @@ func memberMutator(mctx android.BottomUpMutatorContext) { } names := memberListProperty.getter(s.dynamicMemberTypeListProperties) if len(names) > 0 { + memberType := memberListProperty.memberType + + // Verify that the member type supports the specified traits. + supportedTraits := memberType.SupportedTraits() + for _, name := range names { + requiredTraits := ctx.RequiredTraits(name) + unsupportedTraits := requiredTraits.Subtract(supportedTraits) + if !unsupportedTraits.Empty() { + ctx.ModuleErrorf("sdk member %q has traits %s that are unsupported by its member type %q", name, unsupportedTraits, memberType.SdkPropertyName()) + } + } + + // Add dependencies using the appropriate tag. tag := memberListProperty.dependencyTag - memberListProperty.memberType.AddDependencies(ctx, tag, names) + memberType.AddDependencies(ctx, tag, names) } } } -- cgit v1.2.3-59-g8ed1b