diff options
| -rw-r--r-- | android/prebuilt.go | 139 |
1 files changed, 84 insertions, 55 deletions
diff --git a/android/prebuilt.go b/android/prebuilt.go index 2d16f65d7..c902ec826 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -50,12 +50,9 @@ type PrebuiltProperties struct { type Prebuilt struct { properties PrebuiltProperties - module Module - srcs *[]string - // Metadata for single source Prebuilt modules. - srcProps reflect.Value - srcField reflect.StructField + srcsSupplier PrebuiltSrcsSupplier + srcsPropertyName string } func (p *Prebuilt) Name(name string) string { @@ -72,31 +69,26 @@ func (p *Prebuilt) ForcePrefer() { // preference configs. We'll want to add native support for dynamic source cases if we end up having // more modules like this. func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { - if p.srcs != nil { - if len(*p.srcs) == 0 { - ctx.PropertyErrorf("srcs", "missing prebuilt source file") + if p.srcsSupplier != nil { + srcs := p.srcsSupplier() + + if len(srcs) == 0 { + ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file") return nil } - if len(*p.srcs) > 1 { - ctx.PropertyErrorf("srcs", "multiple prebuilt source files") + if len(srcs) > 1 { + ctx.PropertyErrorf(p.srcsPropertyName, "multiple prebuilt source files") return nil } // Return the singleton source after expanding any filegroup in the // sources. - return PathForModuleSrc(ctx, (*p.srcs)[0]) - } else { - if !p.srcProps.IsValid() { - ctx.ModuleErrorf("prebuilt source was not set") - } - src := p.getSingleSourceFieldValue() - if src == "" { - ctx.PropertyErrorf(proptools.FieldNameForProperty(p.srcField.Name), - "missing prebuilt source file") - return nil - } + src := srcs[0] return PathForModuleSrc(ctx, src) + } else { + ctx.ModuleErrorf("prebuilt source was not set") + return nil } } @@ -104,18 +96,80 @@ func (p *Prebuilt) UsePrebuilt() bool { return p.properties.UsePrebuilt } -func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { +// Called to provide the srcs value for the prebuilt module. +// +// Return the src value or nil if it is not available. +type PrebuiltSrcsSupplier func() []string + +// Initialize the module as a prebuilt module that uses the provided supplier to access the +// prebuilt sources of the module. +// +// The supplier will be called multiple times and must return the same values each time it +// is called. If it returns an empty array (or nil) then the prebuilt module will not be used +// as a replacement for a source module with the same name even if prefer = true. +// +// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array +// containing exactly one source file. +// +// The provided property name is used to provide helpful error messages in the event that +// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided. +func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) { p := module.Prebuilt() module.AddProperties(&p.properties) - p.srcs = srcs + + if srcsSupplier == nil { + panic(fmt.Errorf("srcsSupplier must not be nil")) + } + if srcsPropertyName == "" { + panic(fmt.Errorf("srcsPropertyName must not be empty")) + } + + p.srcsSupplier = srcsSupplier + p.srcsPropertyName = srcsPropertyName +} + +func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { + if srcs == nil { + panic(fmt.Errorf("srcs must not be nil")) + } + + srcsSupplier := func() []string { + return *srcs + } + + InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") } func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) { - p := module.Prebuilt() - module.AddProperties(&p.properties) - p.srcProps = reflect.ValueOf(srcProps).Elem() - p.srcField, _ = p.srcProps.Type().FieldByName(srcField) - p.checkSingleSourceProperties() + srcPropsValue := reflect.ValueOf(srcProps).Elem() + srcStructField, _ := srcPropsValue.Type().FieldByName(srcField) + if !srcPropsValue.IsValid() || srcStructField.Name == "" { + panic(fmt.Errorf("invalid single source prebuilt %+v", module)) + } + + if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface { + panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps)) + } + + srcFieldIndex := srcStructField.Index + srcPropertyName := proptools.PropertyNameForField(srcField) + + srcsSupplier := func() []string { + value := srcPropsValue.FieldByIndex(srcFieldIndex) + if value.Kind() == reflect.Ptr { + value = value.Elem() + } + if value.Kind() != reflect.String { + panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one but was %d %q", srcPropertyName, value.Kind(), value)) + } + src := value.String() + if src == "" { + return nil + } + return []string{src} + } + + InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName) } type PrebuiltInterface interface { @@ -152,7 +206,7 @@ func PrebuiltMutator(ctx BottomUpMutatorContext) { func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { p := m.Prebuilt() - if p.srcs == nil && !p.srcProps.IsValid() { + if p.srcsSupplier == nil { panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it")) } if !p.properties.SourceExists { @@ -191,11 +245,7 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { // usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt // will be used if it is marked "prefer" or if the source module is disabled. func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool { - if p.srcs != nil && len(*p.srcs) == 0 { - return false - } - - if p.srcProps.IsValid() && p.getSingleSourceFieldValue() == "" { + if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 { return false } @@ -210,24 +260,3 @@ func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool { func (p *Prebuilt) SourceExists() bool { return p.properties.SourceExists } - -func (p *Prebuilt) checkSingleSourceProperties() { - if !p.srcProps.IsValid() || p.srcField.Name == "" { - panic(fmt.Errorf("invalid single source prebuilt %+v", p)) - } - - if p.srcProps.Kind() != reflect.Struct && p.srcProps.Kind() != reflect.Interface { - panic(fmt.Errorf("invalid single source prebuilt %+v", p.srcProps)) - } -} - -func (p *Prebuilt) getSingleSourceFieldValue() string { - value := p.srcProps.FieldByIndex(p.srcField.Index) - if value.Kind() == reflect.Ptr { - value = value.Elem() - } - if value.Kind() != reflect.String { - panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one", p.srcField.Name)) - } - return value.String() -} |