1*333d2b36SAndroid Build Coastguard Worker// Copyright (C) 2019 The Android Open Source Project 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage sdk 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "reflect" 20*333d2b36SAndroid Build Coastguard Worker "strings" 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 23*333d2b36SAndroid Build Coastguard Worker) 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Workertype bpPropertySet struct { 26*333d2b36SAndroid Build Coastguard Worker properties map[string]interface{} 27*333d2b36SAndroid Build Coastguard Worker tags map[string]android.BpPropertyTag 28*333d2b36SAndroid Build Coastguard Worker comments map[string]string 29*333d2b36SAndroid Build Coastguard Worker order []string 30*333d2b36SAndroid Build Coastguard Worker} 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Workervar _ android.BpPropertySet = (*bpPropertySet)(nil) 33*333d2b36SAndroid Build Coastguard Worker 34*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) init() { 35*333d2b36SAndroid Build Coastguard Worker s.properties = make(map[string]interface{}) 36*333d2b36SAndroid Build Coastguard Worker s.tags = make(map[string]android.BpPropertyTag) 37*333d2b36SAndroid Build Coastguard Worker} 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Worker// Converts the given value, which is assumed to be a struct, to a 40*333d2b36SAndroid Build Coastguard Worker// bpPropertySet. 41*333d2b36SAndroid Build Coastguard Workerfunc convertToPropertySet(value reflect.Value) *bpPropertySet { 42*333d2b36SAndroid Build Coastguard Worker res := newPropertySet() 43*333d2b36SAndroid Build Coastguard Worker structType := value.Type() 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Worker for i := 0; i < structType.NumField(); i++ { 46*333d2b36SAndroid Build Coastguard Worker field := structType.Field(i) 47*333d2b36SAndroid Build Coastguard Worker fieldVal := value.Field(i) 48*333d2b36SAndroid Build Coastguard Worker 49*333d2b36SAndroid Build Coastguard Worker switch fieldVal.Type().Kind() { 50*333d2b36SAndroid Build Coastguard Worker case reflect.Ptr: 51*333d2b36SAndroid Build Coastguard Worker if fieldVal.IsNil() { 52*333d2b36SAndroid Build Coastguard Worker continue // nil pointer means the property isn't set. 53*333d2b36SAndroid Build Coastguard Worker } 54*333d2b36SAndroid Build Coastguard Worker fieldVal = fieldVal.Elem() 55*333d2b36SAndroid Build Coastguard Worker case reflect.Slice: 56*333d2b36SAndroid Build Coastguard Worker if fieldVal.IsNil() { 57*333d2b36SAndroid Build Coastguard Worker continue // Ignore a nil slice (but not one with length zero). 58*333d2b36SAndroid Build Coastguard Worker } 59*333d2b36SAndroid Build Coastguard Worker } 60*333d2b36SAndroid Build Coastguard Worker 61*333d2b36SAndroid Build Coastguard Worker if fieldVal.Type().Kind() == reflect.Struct { 62*333d2b36SAndroid Build Coastguard Worker fieldVal = fieldVal.Addr() // Avoid struct copy below. 63*333d2b36SAndroid Build Coastguard Worker } 64*333d2b36SAndroid Build Coastguard Worker res.AddProperty(strings.ToLower(field.Name), fieldVal.Interface()) 65*333d2b36SAndroid Build Coastguard Worker } 66*333d2b36SAndroid Build Coastguard Worker 67*333d2b36SAndroid Build Coastguard Worker return res 68*333d2b36SAndroid Build Coastguard Worker} 69*333d2b36SAndroid Build Coastguard Worker 70*333d2b36SAndroid Build Coastguard Worker// Converts the given value to something that can be set in a property. 71*333d2b36SAndroid Build Coastguard Workerfunc coercePropertyValue(value interface{}) interface{} { 72*333d2b36SAndroid Build Coastguard Worker val := reflect.ValueOf(value) 73*333d2b36SAndroid Build Coastguard Worker switch val.Kind() { 74*333d2b36SAndroid Build Coastguard Worker case reflect.Struct: 75*333d2b36SAndroid Build Coastguard Worker // convertToPropertySet requires an addressable struct, and this is probably 76*333d2b36SAndroid Build Coastguard Worker // a mistake. 77*333d2b36SAndroid Build Coastguard Worker panic(fmt.Sprintf("Value is a struct, not a pointer to one: %v", value)) 78*333d2b36SAndroid Build Coastguard Worker case reflect.Ptr: 79*333d2b36SAndroid Build Coastguard Worker if _, ok := value.(*bpPropertySet); !ok { 80*333d2b36SAndroid Build Coastguard Worker derefValue := reflect.Indirect(val) 81*333d2b36SAndroid Build Coastguard Worker if derefValue.Kind() != reflect.Struct { 82*333d2b36SAndroid Build Coastguard Worker panic(fmt.Sprintf("A pointer must be to a struct, got: %v", value)) 83*333d2b36SAndroid Build Coastguard Worker } 84*333d2b36SAndroid Build Coastguard Worker return convertToPropertySet(derefValue) 85*333d2b36SAndroid Build Coastguard Worker } 86*333d2b36SAndroid Build Coastguard Worker } 87*333d2b36SAndroid Build Coastguard Worker return value 88*333d2b36SAndroid Build Coastguard Worker} 89*333d2b36SAndroid Build Coastguard Worker 90*333d2b36SAndroid Build Coastguard Worker// Merges the fields of the given property set into s. 91*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) mergePropertySet(propSet *bpPropertySet) { 92*333d2b36SAndroid Build Coastguard Worker for _, name := range propSet.order { 93*333d2b36SAndroid Build Coastguard Worker if tag, ok := propSet.tags[name]; ok { 94*333d2b36SAndroid Build Coastguard Worker s.AddPropertyWithTag(name, propSet.properties[name], tag) 95*333d2b36SAndroid Build Coastguard Worker } else { 96*333d2b36SAndroid Build Coastguard Worker s.AddProperty(name, propSet.properties[name]) 97*333d2b36SAndroid Build Coastguard Worker } 98*333d2b36SAndroid Build Coastguard Worker } 99*333d2b36SAndroid Build Coastguard Worker} 100*333d2b36SAndroid Build Coastguard Worker 101*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) AddProperty(name string, value interface{}) { 102*333d2b36SAndroid Build Coastguard Worker value = coercePropertyValue(value) 103*333d2b36SAndroid Build Coastguard Worker 104*333d2b36SAndroid Build Coastguard Worker if propSetValue, ok := value.(*bpPropertySet); ok { 105*333d2b36SAndroid Build Coastguard Worker if curValue, ok := s.properties[name]; ok { 106*333d2b36SAndroid Build Coastguard Worker if curSet, ok := curValue.(*bpPropertySet); ok { 107*333d2b36SAndroid Build Coastguard Worker curSet.mergePropertySet(propSetValue) 108*333d2b36SAndroid Build Coastguard Worker return 109*333d2b36SAndroid Build Coastguard Worker } 110*333d2b36SAndroid Build Coastguard Worker // If the current value isn't a property set we got conflicting types. 111*333d2b36SAndroid Build Coastguard Worker // Continue down to the check below to complain about it. 112*333d2b36SAndroid Build Coastguard Worker } 113*333d2b36SAndroid Build Coastguard Worker } 114*333d2b36SAndroid Build Coastguard Worker 115*333d2b36SAndroid Build Coastguard Worker if s.properties[name] != nil { 116*333d2b36SAndroid Build Coastguard Worker panic(fmt.Sprintf("Property %q already exists in property set", name)) 117*333d2b36SAndroid Build Coastguard Worker } 118*333d2b36SAndroid Build Coastguard Worker 119*333d2b36SAndroid Build Coastguard Worker s.properties[name] = value 120*333d2b36SAndroid Build Coastguard Worker s.order = append(s.order, name) 121*333d2b36SAndroid Build Coastguard Worker} 122*333d2b36SAndroid Build Coastguard Worker 123*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) AddPropertyWithTag(name string, value interface{}, tag android.BpPropertyTag) { 124*333d2b36SAndroid Build Coastguard Worker s.AddProperty(name, value) 125*333d2b36SAndroid Build Coastguard Worker s.tags[name] = tag 126*333d2b36SAndroid Build Coastguard Worker} 127*333d2b36SAndroid Build Coastguard Worker 128*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) AddPropertySet(name string) android.BpPropertySet { 129*333d2b36SAndroid Build Coastguard Worker s.AddProperty(name, newPropertySet()) 130*333d2b36SAndroid Build Coastguard Worker return s.properties[name].(android.BpPropertySet) 131*333d2b36SAndroid Build Coastguard Worker} 132*333d2b36SAndroid Build Coastguard Worker 133*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) getValue(name string) interface{} { 134*333d2b36SAndroid Build Coastguard Worker return s.properties[name] 135*333d2b36SAndroid Build Coastguard Worker} 136*333d2b36SAndroid Build Coastguard Worker 137*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) getOptionalValue(name string) (interface{}, bool) { 138*333d2b36SAndroid Build Coastguard Worker value, ok := s.properties[name] 139*333d2b36SAndroid Build Coastguard Worker return value, ok 140*333d2b36SAndroid Build Coastguard Worker} 141*333d2b36SAndroid Build Coastguard Worker 142*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) getTag(name string) interface{} { 143*333d2b36SAndroid Build Coastguard Worker return s.tags[name] 144*333d2b36SAndroid Build Coastguard Worker} 145*333d2b36SAndroid Build Coastguard Worker 146*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) AddCommentForProperty(name, text string) { 147*333d2b36SAndroid Build Coastguard Worker if s.comments == nil { 148*333d2b36SAndroid Build Coastguard Worker s.comments = map[string]string{} 149*333d2b36SAndroid Build Coastguard Worker } 150*333d2b36SAndroid Build Coastguard Worker s.comments[name] = strings.TrimSpace(text) 151*333d2b36SAndroid Build Coastguard Worker} 152*333d2b36SAndroid Build Coastguard Worker 153*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) transformContents(transformer bpPropertyTransformer) { 154*333d2b36SAndroid Build Coastguard Worker var newOrder []string 155*333d2b36SAndroid Build Coastguard Worker for _, name := range s.order { 156*333d2b36SAndroid Build Coastguard Worker value := s.properties[name] 157*333d2b36SAndroid Build Coastguard Worker tag := s.tags[name] 158*333d2b36SAndroid Build Coastguard Worker var newValue interface{} 159*333d2b36SAndroid Build Coastguard Worker var newTag android.BpPropertyTag 160*333d2b36SAndroid Build Coastguard Worker if propertySet, ok := value.(*bpPropertySet); ok { 161*333d2b36SAndroid Build Coastguard Worker var newPropertySet *bpPropertySet 162*333d2b36SAndroid Build Coastguard Worker newPropertySet, newTag = transformPropertySet(transformer, name, propertySet, tag) 163*333d2b36SAndroid Build Coastguard Worker if newPropertySet == nil { 164*333d2b36SAndroid Build Coastguard Worker newValue = nil 165*333d2b36SAndroid Build Coastguard Worker } else { 166*333d2b36SAndroid Build Coastguard Worker newValue = newPropertySet 167*333d2b36SAndroid Build Coastguard Worker } 168*333d2b36SAndroid Build Coastguard Worker } else { 169*333d2b36SAndroid Build Coastguard Worker newValue, newTag = transformer.transformProperty(name, value, tag) 170*333d2b36SAndroid Build Coastguard Worker } 171*333d2b36SAndroid Build Coastguard Worker 172*333d2b36SAndroid Build Coastguard Worker if newValue == nil { 173*333d2b36SAndroid Build Coastguard Worker // Delete the property from the map and exclude it from the new order. 174*333d2b36SAndroid Build Coastguard Worker delete(s.properties, name) 175*333d2b36SAndroid Build Coastguard Worker } else { 176*333d2b36SAndroid Build Coastguard Worker // Update the property in the map and add the name to the new order list. 177*333d2b36SAndroid Build Coastguard Worker s.properties[name] = newValue 178*333d2b36SAndroid Build Coastguard Worker s.tags[name] = newTag 179*333d2b36SAndroid Build Coastguard Worker newOrder = append(newOrder, name) 180*333d2b36SAndroid Build Coastguard Worker } 181*333d2b36SAndroid Build Coastguard Worker } 182*333d2b36SAndroid Build Coastguard Worker s.order = newOrder 183*333d2b36SAndroid Build Coastguard Worker} 184*333d2b36SAndroid Build Coastguard Worker 185*333d2b36SAndroid Build Coastguard Workerfunc transformPropertySet(transformer bpPropertyTransformer, name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { 186*333d2b36SAndroid Build Coastguard Worker newPropertySet, newTag := transformer.transformPropertySetBeforeContents(name, propertySet, tag) 187*333d2b36SAndroid Build Coastguard Worker if newPropertySet != nil { 188*333d2b36SAndroid Build Coastguard Worker newPropertySet.transformContents(transformer) 189*333d2b36SAndroid Build Coastguard Worker 190*333d2b36SAndroid Build Coastguard Worker newPropertySet, newTag = transformer.transformPropertySetAfterContents(name, newPropertySet, newTag) 191*333d2b36SAndroid Build Coastguard Worker } 192*333d2b36SAndroid Build Coastguard Worker return newPropertySet, newTag 193*333d2b36SAndroid Build Coastguard Worker} 194*333d2b36SAndroid Build Coastguard Worker 195*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) setProperty(name string, value interface{}) { 196*333d2b36SAndroid Build Coastguard Worker if s.properties[name] == nil { 197*333d2b36SAndroid Build Coastguard Worker s.AddProperty(name, value) 198*333d2b36SAndroid Build Coastguard Worker } else { 199*333d2b36SAndroid Build Coastguard Worker s.properties[name] = value 200*333d2b36SAndroid Build Coastguard Worker s.tags[name] = nil 201*333d2b36SAndroid Build Coastguard Worker } 202*333d2b36SAndroid Build Coastguard Worker} 203*333d2b36SAndroid Build Coastguard Worker 204*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) removeProperty(name string) { 205*333d2b36SAndroid Build Coastguard Worker delete(s.properties, name) 206*333d2b36SAndroid Build Coastguard Worker delete(s.tags, name) 207*333d2b36SAndroid Build Coastguard Worker _, s.order = android.RemoveFromList(name, s.order) 208*333d2b36SAndroid Build Coastguard Worker} 209*333d2b36SAndroid Build Coastguard Worker 210*333d2b36SAndroid Build Coastguard Workerfunc (s *bpPropertySet) insertAfter(position string, name string, value interface{}) { 211*333d2b36SAndroid Build Coastguard Worker if s.properties[name] != nil { 212*333d2b36SAndroid Build Coastguard Worker panic("Property %q already exists in property set") 213*333d2b36SAndroid Build Coastguard Worker } 214*333d2b36SAndroid Build Coastguard Worker 215*333d2b36SAndroid Build Coastguard Worker // Add the name to the end of the order, to ensure it has necessary capacity 216*333d2b36SAndroid Build Coastguard Worker // and to handle the case when the position does not exist. 217*333d2b36SAndroid Build Coastguard Worker s.order = append(s.order, name) 218*333d2b36SAndroid Build Coastguard Worker 219*333d2b36SAndroid Build Coastguard Worker // Search through the order for the item that matches supplied position. If 220*333d2b36SAndroid Build Coastguard Worker // found then insert the name of the new property after it. 221*333d2b36SAndroid Build Coastguard Worker for i, v := range s.order { 222*333d2b36SAndroid Build Coastguard Worker if v == position { 223*333d2b36SAndroid Build Coastguard Worker // Copy the items after the one where the new property should be inserted. 224*333d2b36SAndroid Build Coastguard Worker copy(s.order[i+2:], s.order[i+1:]) 225*333d2b36SAndroid Build Coastguard Worker // Insert the item in the list. 226*333d2b36SAndroid Build Coastguard Worker s.order[i+1] = name 227*333d2b36SAndroid Build Coastguard Worker } 228*333d2b36SAndroid Build Coastguard Worker } 229*333d2b36SAndroid Build Coastguard Worker 230*333d2b36SAndroid Build Coastguard Worker s.properties[name] = value 231*333d2b36SAndroid Build Coastguard Worker} 232*333d2b36SAndroid Build Coastguard Worker 233*333d2b36SAndroid Build Coastguard Workertype bpModule struct { 234*333d2b36SAndroid Build Coastguard Worker *bpPropertySet 235*333d2b36SAndroid Build Coastguard Worker moduleType string 236*333d2b36SAndroid Build Coastguard Worker} 237*333d2b36SAndroid Build Coastguard Worker 238*333d2b36SAndroid Build Coastguard Workerfunc (m *bpModule) ModuleType() string { 239*333d2b36SAndroid Build Coastguard Worker return m.moduleType 240*333d2b36SAndroid Build Coastguard Worker} 241*333d2b36SAndroid Build Coastguard Worker 242*333d2b36SAndroid Build Coastguard Workerfunc (m *bpModule) Name() string { 243*333d2b36SAndroid Build Coastguard Worker name, hasName := m.getOptionalValue("name") 244*333d2b36SAndroid Build Coastguard Worker if hasName { 245*333d2b36SAndroid Build Coastguard Worker return name.(string) 246*333d2b36SAndroid Build Coastguard Worker } else { 247*333d2b36SAndroid Build Coastguard Worker return "" 248*333d2b36SAndroid Build Coastguard Worker } 249*333d2b36SAndroid Build Coastguard Worker} 250*333d2b36SAndroid Build Coastguard Worker 251*333d2b36SAndroid Build Coastguard Workervar _ android.BpModule = (*bpModule)(nil) 252*333d2b36SAndroid Build Coastguard Worker 253*333d2b36SAndroid Build Coastguard Workertype bpPropertyTransformer interface { 254*333d2b36SAndroid Build Coastguard Worker // Transform the property set, returning the new property set/tag to insert back into the 255*333d2b36SAndroid Build Coastguard Worker // parent property set (or module if this is the top level property set). 256*333d2b36SAndroid Build Coastguard Worker // 257*333d2b36SAndroid Build Coastguard Worker // This will be called before transforming the properties in the supplied set. 258*333d2b36SAndroid Build Coastguard Worker // 259*333d2b36SAndroid Build Coastguard Worker // The name will be "" for the top level property set. 260*333d2b36SAndroid Build Coastguard Worker // 261*333d2b36SAndroid Build Coastguard Worker // Returning (nil, ...) will cause the property set to be removed. 262*333d2b36SAndroid Build Coastguard Worker transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) 263*333d2b36SAndroid Build Coastguard Worker 264*333d2b36SAndroid Build Coastguard Worker // Transform the property set, returning the new property set/tag to insert back into the 265*333d2b36SAndroid Build Coastguard Worker // parent property set (or module if this is the top level property set). 266*333d2b36SAndroid Build Coastguard Worker // 267*333d2b36SAndroid Build Coastguard Worker // This will be called after transforming the properties in the supplied set. 268*333d2b36SAndroid Build Coastguard Worker // 269*333d2b36SAndroid Build Coastguard Worker // The name will be "" for the top level property set. 270*333d2b36SAndroid Build Coastguard Worker // 271*333d2b36SAndroid Build Coastguard Worker // Returning (nil, ...) will cause the property set to be removed. 272*333d2b36SAndroid Build Coastguard Worker transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) 273*333d2b36SAndroid Build Coastguard Worker 274*333d2b36SAndroid Build Coastguard Worker // Transform a property, return the new value/tag to insert back into the property set. 275*333d2b36SAndroid Build Coastguard Worker // 276*333d2b36SAndroid Build Coastguard Worker // Returning (nil, ...) will cause the property to be removed. 277*333d2b36SAndroid Build Coastguard Worker transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) 278*333d2b36SAndroid Build Coastguard Worker} 279*333d2b36SAndroid Build Coastguard Worker 280*333d2b36SAndroid Build Coastguard Worker// Interface for transforming bpModule objects. 281*333d2b36SAndroid Build Coastguard Workertype bpTransformer interface { 282*333d2b36SAndroid Build Coastguard Worker // Transform the module, returning the result. 283*333d2b36SAndroid Build Coastguard Worker // 284*333d2b36SAndroid Build Coastguard Worker // The method can either create a new module and return that, or modify the supplied module 285*333d2b36SAndroid Build Coastguard Worker // in place and return that. 286*333d2b36SAndroid Build Coastguard Worker // 287*333d2b36SAndroid Build Coastguard Worker // After this returns the transformer is applied to the contents of the returned module. 288*333d2b36SAndroid Build Coastguard Worker transformModule(module *bpModule) *bpModule 289*333d2b36SAndroid Build Coastguard Worker 290*333d2b36SAndroid Build Coastguard Worker bpPropertyTransformer 291*333d2b36SAndroid Build Coastguard Worker} 292*333d2b36SAndroid Build Coastguard Worker 293*333d2b36SAndroid Build Coastguard Workertype identityTransformation struct{} 294*333d2b36SAndroid Build Coastguard Worker 295*333d2b36SAndroid Build Coastguard Workervar _ bpTransformer = (*identityTransformation)(nil) 296*333d2b36SAndroid Build Coastguard Worker 297*333d2b36SAndroid Build Coastguard Workerfunc (t identityTransformation) transformModule(module *bpModule) *bpModule { 298*333d2b36SAndroid Build Coastguard Worker return module 299*333d2b36SAndroid Build Coastguard Worker} 300*333d2b36SAndroid Build Coastguard Worker 301*333d2b36SAndroid Build Coastguard Workerfunc (t identityTransformation) transformPropertySetBeforeContents(_ string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { 302*333d2b36SAndroid Build Coastguard Worker return propertySet, tag 303*333d2b36SAndroid Build Coastguard Worker} 304*333d2b36SAndroid Build Coastguard Worker 305*333d2b36SAndroid Build Coastguard Workerfunc (t identityTransformation) transformPropertySetAfterContents(_ string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { 306*333d2b36SAndroid Build Coastguard Worker return propertySet, tag 307*333d2b36SAndroid Build Coastguard Worker} 308*333d2b36SAndroid Build Coastguard Worker 309*333d2b36SAndroid Build Coastguard Workerfunc (t identityTransformation) transformProperty(_ string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) { 310*333d2b36SAndroid Build Coastguard Worker return value, tag 311*333d2b36SAndroid Build Coastguard Worker} 312*333d2b36SAndroid Build Coastguard Worker 313*333d2b36SAndroid Build Coastguard Workerfunc (m *bpModule) deepCopy() *bpModule { 314*333d2b36SAndroid Build Coastguard Worker return transformModule(m, deepCopyTransformer) 315*333d2b36SAndroid Build Coastguard Worker} 316*333d2b36SAndroid Build Coastguard Worker 317*333d2b36SAndroid Build Coastguard Workerfunc transformModule(m *bpModule, transformer bpTransformer) *bpModule { 318*333d2b36SAndroid Build Coastguard Worker transformedModule := transformer.transformModule(m) 319*333d2b36SAndroid Build Coastguard Worker if transformedModule != nil { 320*333d2b36SAndroid Build Coastguard Worker // Copy the contents of the returned property set into the module and then transform that. 321*333d2b36SAndroid Build Coastguard Worker transformedModule.bpPropertySet, _ = transformPropertySet(transformer, "", transformedModule.bpPropertySet, nil) 322*333d2b36SAndroid Build Coastguard Worker } 323*333d2b36SAndroid Build Coastguard Worker return transformedModule 324*333d2b36SAndroid Build Coastguard Worker} 325*333d2b36SAndroid Build Coastguard Worker 326*333d2b36SAndroid Build Coastguard Workertype deepCopyTransformation struct { 327*333d2b36SAndroid Build Coastguard Worker identityTransformation 328*333d2b36SAndroid Build Coastguard Worker} 329*333d2b36SAndroid Build Coastguard Worker 330*333d2b36SAndroid Build Coastguard Workerfunc (t deepCopyTransformation) transformModule(module *bpModule) *bpModule { 331*333d2b36SAndroid Build Coastguard Worker // Take a shallow copy of the module. Any mutable property values will be copied by the 332*333d2b36SAndroid Build Coastguard Worker // transformer. 333*333d2b36SAndroid Build Coastguard Worker moduleCopy := *module 334*333d2b36SAndroid Build Coastguard Worker return &moduleCopy 335*333d2b36SAndroid Build Coastguard Worker} 336*333d2b36SAndroid Build Coastguard Worker 337*333d2b36SAndroid Build Coastguard Workerfunc (t deepCopyTransformation) transformPropertySetBeforeContents(_ string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { 338*333d2b36SAndroid Build Coastguard Worker // Create a shallow copy of the properties map. Any mutable property values will be copied by the 339*333d2b36SAndroid Build Coastguard Worker // transformer. 340*333d2b36SAndroid Build Coastguard Worker propertiesCopy := make(map[string]interface{}) 341*333d2b36SAndroid Build Coastguard Worker for propertyName, value := range propertySet.properties { 342*333d2b36SAndroid Build Coastguard Worker propertiesCopy[propertyName] = value 343*333d2b36SAndroid Build Coastguard Worker } 344*333d2b36SAndroid Build Coastguard Worker 345*333d2b36SAndroid Build Coastguard Worker // Ditto for tags map. 346*333d2b36SAndroid Build Coastguard Worker tagsCopy := make(map[string]android.BpPropertyTag) 347*333d2b36SAndroid Build Coastguard Worker for propertyName, propertyTag := range propertySet.tags { 348*333d2b36SAndroid Build Coastguard Worker tagsCopy[propertyName] = propertyTag 349*333d2b36SAndroid Build Coastguard Worker } 350*333d2b36SAndroid Build Coastguard Worker 351*333d2b36SAndroid Build Coastguard Worker // Create a new property set. 352*333d2b36SAndroid Build Coastguard Worker return &bpPropertySet{ 353*333d2b36SAndroid Build Coastguard Worker properties: propertiesCopy, 354*333d2b36SAndroid Build Coastguard Worker tags: tagsCopy, 355*333d2b36SAndroid Build Coastguard Worker order: append([]string(nil), propertySet.order...), 356*333d2b36SAndroid Build Coastguard Worker }, tag 357*333d2b36SAndroid Build Coastguard Worker} 358*333d2b36SAndroid Build Coastguard Worker 359*333d2b36SAndroid Build Coastguard Workerfunc (t deepCopyTransformation) transformProperty(_ string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) { 360*333d2b36SAndroid Build Coastguard Worker // Copy string slice, otherwise return value. 361*333d2b36SAndroid Build Coastguard Worker if values, ok := value.([]string); ok { 362*333d2b36SAndroid Build Coastguard Worker valuesCopy := make([]string, len(values)) 363*333d2b36SAndroid Build Coastguard Worker copy(valuesCopy, values) 364*333d2b36SAndroid Build Coastguard Worker return valuesCopy, tag 365*333d2b36SAndroid Build Coastguard Worker } 366*333d2b36SAndroid Build Coastguard Worker return value, tag 367*333d2b36SAndroid Build Coastguard Worker} 368*333d2b36SAndroid Build Coastguard Worker 369*333d2b36SAndroid Build Coastguard Workervar deepCopyTransformer bpTransformer = deepCopyTransformation{} 370*333d2b36SAndroid Build Coastguard Worker 371*333d2b36SAndroid Build Coastguard Worker// A .bp file 372*333d2b36SAndroid Build Coastguard Workertype bpFile struct { 373*333d2b36SAndroid Build Coastguard Worker modules map[string]*bpModule 374*333d2b36SAndroid Build Coastguard Worker order []*bpModule 375*333d2b36SAndroid Build Coastguard Worker} 376*333d2b36SAndroid Build Coastguard Worker 377*333d2b36SAndroid Build Coastguard Worker// AddModule adds a module to this. 378*333d2b36SAndroid Build Coastguard Worker// 379*333d2b36SAndroid Build Coastguard Worker// The module must have had its "name" property set to a string value that 380*333d2b36SAndroid Build Coastguard Worker// is unique within this file. 381*333d2b36SAndroid Build Coastguard Workerfunc (f *bpFile) AddModule(module android.BpModule) { 382*333d2b36SAndroid Build Coastguard Worker m := module.(*bpModule) 383*333d2b36SAndroid Build Coastguard Worker moduleType := module.ModuleType() 384*333d2b36SAndroid Build Coastguard Worker name := m.Name() 385*333d2b36SAndroid Build Coastguard Worker hasName := true 386*333d2b36SAndroid Build Coastguard Worker if name == "" { 387*333d2b36SAndroid Build Coastguard Worker // Use a prefixed module type as the name instead just in case this is something like a package 388*333d2b36SAndroid Build Coastguard Worker // of namespace module which does not require a name. 389*333d2b36SAndroid Build Coastguard Worker name = "#" + moduleType 390*333d2b36SAndroid Build Coastguard Worker hasName = false 391*333d2b36SAndroid Build Coastguard Worker } 392*333d2b36SAndroid Build Coastguard Worker 393*333d2b36SAndroid Build Coastguard Worker if f.modules[name] != nil { 394*333d2b36SAndroid Build Coastguard Worker if hasName { 395*333d2b36SAndroid Build Coastguard Worker panic(fmt.Sprintf("Module %q already exists in bp file", name)) 396*333d2b36SAndroid Build Coastguard Worker } else { 397*333d2b36SAndroid Build Coastguard Worker panic(fmt.Sprintf("Unnamed module type %q already exists in bp file", moduleType)) 398*333d2b36SAndroid Build Coastguard Worker } 399*333d2b36SAndroid Build Coastguard Worker } 400*333d2b36SAndroid Build Coastguard Worker 401*333d2b36SAndroid Build Coastguard Worker f.modules[name] = m 402*333d2b36SAndroid Build Coastguard Worker f.order = append(f.order, m) 403*333d2b36SAndroid Build Coastguard Worker} 404*333d2b36SAndroid Build Coastguard Worker 405*333d2b36SAndroid Build Coastguard Workerfunc (f *bpFile) newModule(moduleType string) *bpModule { 406*333d2b36SAndroid Build Coastguard Worker return newModule(moduleType) 407*333d2b36SAndroid Build Coastguard Worker} 408*333d2b36SAndroid Build Coastguard Worker 409*333d2b36SAndroid Build Coastguard Workerfunc newModule(moduleType string) *bpModule { 410*333d2b36SAndroid Build Coastguard Worker module := &bpModule{ 411*333d2b36SAndroid Build Coastguard Worker moduleType: moduleType, 412*333d2b36SAndroid Build Coastguard Worker bpPropertySet: newPropertySet(), 413*333d2b36SAndroid Build Coastguard Worker } 414*333d2b36SAndroid Build Coastguard Worker return module 415*333d2b36SAndroid Build Coastguard Worker} 416*333d2b36SAndroid Build Coastguard Worker 417*333d2b36SAndroid Build Coastguard Workerfunc newPropertySet() *bpPropertySet { 418*333d2b36SAndroid Build Coastguard Worker set := &bpPropertySet{} 419*333d2b36SAndroid Build Coastguard Worker set.init() 420*333d2b36SAndroid Build Coastguard Worker return set 421*333d2b36SAndroid Build Coastguard Worker} 422