xref: /aosp_15_r20/build/soong/sdk/bp.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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