blob: 0118a6a3e170c646fd8fae4ce2bc478d99528f04 [file] [log] [blame]
Colin Cross7f64b6d2015-07-09 13:57:48 -07001// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package common
16
17import (
18 "fmt"
19 "reflect"
20 "strings"
21
22 "android/soong"
23
24 "github.com/google/blueprint"
25 "github.com/google/blueprint/proptools"
26)
27
28func init() {
29 soong.RegisterEarlyMutator("variable", VariableMutator)
30}
31
32type variableProperties struct {
33 Product_variables struct {
Colin Cross7f64b6d2015-07-09 13:57:48 -070034 Device_uses_dlmalloc struct {
35 Cflags []string
36 Srcs []string
37 }
38 Device_uses_jemalloc struct {
39 Cflags []string
40 Srcs []string
41 Whole_static_libs []string
42 Include_dirs []string
43 }
44 Dlmalloc_alignment struct {
45 Cflags []string
46 }
47 }
48}
49
50var zeroProductVariables variableProperties
51
Colin Cross485e5722015-08-27 13:28:01 -070052type productVariables struct {
Colin Crossa6bc19e2015-09-16 13:53:42 -070053 Device_uses_jemalloc *bool `json:",omitempty"`
54 Device_uses_dlmalloc *bool `json:",omitempty"`
55 Dlmalloc_alignment *int `json:",omitempty"`
56}
57
58func boolPtr(v bool) *bool {
59 return &v
Colin Cross485e5722015-08-27 13:28:01 -070060}
61
62func (productVariables) DefaultConfig() jsonConfigurable {
63 v := productVariables{
Colin Crossa6bc19e2015-09-16 13:53:42 -070064 Device_uses_jemalloc: boolPtr(true),
Colin Cross485e5722015-08-27 13:28:01 -070065 }
66 return v
Colin Cross7f64b6d2015-07-09 13:57:48 -070067}
68
69func VariableMutator(mctx blueprint.EarlyMutatorContext) {
70 var module AndroidModule
71 var ok bool
72 if module, ok = mctx.Module().(AndroidModule); !ok {
73 return
74 }
75
76 // TODO: depend on config variable, create variants, propagate variants up tree
77 a := module.base()
78 variableValues := reflect.ValueOf(a.variableProperties.Product_variables)
79 zeroValues := reflect.ValueOf(zeroProductVariables.Product_variables)
80
81 for i := 0; i < variableValues.NumField(); i++ {
82 variableValue := variableValues.Field(i)
83 zeroValue := zeroValues.Field(i)
Colin Cross485e5722015-08-27 13:28:01 -070084 name := variableValues.Type().Field(i).Name
85 property := "product_variables." + proptools.PropertyNameForField(name)
Colin Cross7f64b6d2015-07-09 13:57:48 -070086
Colin Crossa6bc19e2015-09-16 13:53:42 -070087 // Check that the variable was set for the product
Colin Cross485e5722015-08-27 13:28:01 -070088 val := reflect.ValueOf(mctx.Config().(Config).ProductVariables).FieldByName(name)
Colin Crossa6bc19e2015-09-16 13:53:42 -070089 if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
90 continue
Colin Cross7f64b6d2015-07-09 13:57:48 -070091 }
Colin Crossa6bc19e2015-09-16 13:53:42 -070092
93 val = val.Elem()
94
95 // For bools, check that the value is true
96 if val.Kind() == reflect.Bool && val.Bool() == false {
97 continue
98 }
99
100 // Check if any properties were set for the module
101 if reflect.DeepEqual(variableValue.Interface(), zeroValue.Interface()) {
102 continue
103 }
104
105 a.setVariableProperties(mctx, property, variableValue, val.Interface())
Colin Cross7f64b6d2015-07-09 13:57:48 -0700106 }
107}
108
109func (a *AndroidModuleBase) setVariableProperties(ctx blueprint.EarlyMutatorContext,
110 prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) {
111
112 generalPropertyValues := make([]reflect.Value, len(a.generalProperties))
113 for i := range a.generalProperties {
114 generalPropertyValues[i] = reflect.ValueOf(a.generalProperties[i]).Elem()
115 }
116
117 if variableValue != nil {
118 printfIntoProperties(productVariablePropertyValue, variableValue)
119 }
120
121 extendProperties(ctx, "", prefix, generalPropertyValues, productVariablePropertyValue, nil)
122}
123
124func printfIntoProperties(productVariablePropertyValue reflect.Value, variableValue interface{}) {
125 for i := 0; i < productVariablePropertyValue.NumField(); i++ {
126 propertyValue := productVariablePropertyValue.Field(i)
127 switch propertyValue.Kind() {
128 case reflect.String:
129 printfIntoProperty(propertyValue, variableValue)
130 case reflect.Slice:
131 for j := 0; j < propertyValue.Len(); j++ {
132 printfIntoProperty(propertyValue.Index(j), variableValue)
133 }
134 case reflect.Struct:
135 printfIntoProperties(propertyValue, variableValue)
136 default:
137 panic(fmt.Errorf("unsupported field kind %q", propertyValue.Kind()))
138 }
139 }
140}
141
142func printfIntoProperty(propertyValue reflect.Value, variableValue interface{}) {
143 s := propertyValue.String()
144 // For now, we only support int formats
145 var i int
146 if strings.Contains(s, "%d") {
147 switch v := variableValue.(type) {
148 case int:
149 i = v
150 case bool:
151 if v {
152 i = 1
153 }
154 default:
155 panic(fmt.Errorf("unsupported type %T", variableValue))
156 }
157 propertyValue.Set(reflect.ValueOf(fmt.Sprintf(s, i)))
158 }
159}