blob: bf7b594a355f5ea7fa0a8dbfb059de4eb90cad4e [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 }
Dan Willemsen47cf66b2015-09-16 16:48:54 -070047 Platform_sdk_version struct {
48 Asflags []string
49 }
Colin Cross7f64b6d2015-07-09 13:57:48 -070050 }
51}
52
53var zeroProductVariables variableProperties
54
Colin Cross485e5722015-08-27 13:28:01 -070055type productVariables struct {
Colin Crossa6bc19e2015-09-16 13:53:42 -070056 Device_uses_jemalloc *bool `json:",omitempty"`
57 Device_uses_dlmalloc *bool `json:",omitempty"`
58 Dlmalloc_alignment *int `json:",omitempty"`
Dan Willemsen47cf66b2015-09-16 16:48:54 -070059 Platform_sdk_version *int
Colin Crossa6bc19e2015-09-16 13:53:42 -070060}
61
62func boolPtr(v bool) *bool {
63 return &v
Colin Cross485e5722015-08-27 13:28:01 -070064}
65
Dan Willemsen47cf66b2015-09-16 16:48:54 -070066func intPtr(v int) *int {
67 return &v
68}
69
Colin Cross485e5722015-08-27 13:28:01 -070070func (productVariables) DefaultConfig() jsonConfigurable {
71 v := productVariables{
Colin Crossa6bc19e2015-09-16 13:53:42 -070072 Device_uses_jemalloc: boolPtr(true),
Dan Willemsen47cf66b2015-09-16 16:48:54 -070073 Platform_sdk_version: intPtr(22),
Colin Cross485e5722015-08-27 13:28:01 -070074 }
75 return v
Colin Cross7f64b6d2015-07-09 13:57:48 -070076}
77
78func VariableMutator(mctx blueprint.EarlyMutatorContext) {
79 var module AndroidModule
80 var ok bool
81 if module, ok = mctx.Module().(AndroidModule); !ok {
82 return
83 }
84
85 // TODO: depend on config variable, create variants, propagate variants up tree
86 a := module.base()
87 variableValues := reflect.ValueOf(a.variableProperties.Product_variables)
88 zeroValues := reflect.ValueOf(zeroProductVariables.Product_variables)
89
90 for i := 0; i < variableValues.NumField(); i++ {
91 variableValue := variableValues.Field(i)
92 zeroValue := zeroValues.Field(i)
Colin Cross485e5722015-08-27 13:28:01 -070093 name := variableValues.Type().Field(i).Name
94 property := "product_variables." + proptools.PropertyNameForField(name)
Colin Cross7f64b6d2015-07-09 13:57:48 -070095
Colin Crossa6bc19e2015-09-16 13:53:42 -070096 // Check that the variable was set for the product
Colin Cross485e5722015-08-27 13:28:01 -070097 val := reflect.ValueOf(mctx.Config().(Config).ProductVariables).FieldByName(name)
Colin Crossa6bc19e2015-09-16 13:53:42 -070098 if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
99 continue
Colin Cross7f64b6d2015-07-09 13:57:48 -0700100 }
Colin Crossa6bc19e2015-09-16 13:53:42 -0700101
102 val = val.Elem()
103
104 // For bools, check that the value is true
105 if val.Kind() == reflect.Bool && val.Bool() == false {
106 continue
107 }
108
109 // Check if any properties were set for the module
110 if reflect.DeepEqual(variableValue.Interface(), zeroValue.Interface()) {
111 continue
112 }
113
114 a.setVariableProperties(mctx, property, variableValue, val.Interface())
Colin Cross7f64b6d2015-07-09 13:57:48 -0700115 }
116}
117
118func (a *AndroidModuleBase) setVariableProperties(ctx blueprint.EarlyMutatorContext,
119 prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) {
120
121 generalPropertyValues := make([]reflect.Value, len(a.generalProperties))
122 for i := range a.generalProperties {
123 generalPropertyValues[i] = reflect.ValueOf(a.generalProperties[i]).Elem()
124 }
125
126 if variableValue != nil {
127 printfIntoProperties(productVariablePropertyValue, variableValue)
128 }
129
130 extendProperties(ctx, "", prefix, generalPropertyValues, productVariablePropertyValue, nil)
131}
132
133func printfIntoProperties(productVariablePropertyValue reflect.Value, variableValue interface{}) {
134 for i := 0; i < productVariablePropertyValue.NumField(); i++ {
135 propertyValue := productVariablePropertyValue.Field(i)
136 switch propertyValue.Kind() {
137 case reflect.String:
138 printfIntoProperty(propertyValue, variableValue)
139 case reflect.Slice:
140 for j := 0; j < propertyValue.Len(); j++ {
141 printfIntoProperty(propertyValue.Index(j), variableValue)
142 }
143 case reflect.Struct:
144 printfIntoProperties(propertyValue, variableValue)
145 default:
146 panic(fmt.Errorf("unsupported field kind %q", propertyValue.Kind()))
147 }
148 }
149}
150
151func printfIntoProperty(propertyValue reflect.Value, variableValue interface{}) {
152 s := propertyValue.String()
153 // For now, we only support int formats
154 var i int
155 if strings.Contains(s, "%d") {
156 switch v := variableValue.(type) {
157 case int:
158 i = v
159 case bool:
160 if v {
161 i = 1
162 }
163 default:
164 panic(fmt.Errorf("unsupported type %T", variableValue))
165 }
166 propertyValue.Set(reflect.ValueOf(fmt.Sprintf(s, i)))
167 }
168}