blob: bf7b594a355f5ea7fa0a8dbfb059de4eb90cad4e [file] [log] [blame]
// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package common
import (
"fmt"
"reflect"
"strings"
"android/soong"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
func init() {
soong.RegisterEarlyMutator("variable", VariableMutator)
}
type variableProperties struct {
Product_variables struct {
Device_uses_dlmalloc struct {
Cflags []string
Srcs []string
}
Device_uses_jemalloc struct {
Cflags []string
Srcs []string
Whole_static_libs []string
Include_dirs []string
}
Dlmalloc_alignment struct {
Cflags []string
}
Platform_sdk_version struct {
Asflags []string
}
}
}
var zeroProductVariables variableProperties
type productVariables struct {
Device_uses_jemalloc *bool `json:",omitempty"`
Device_uses_dlmalloc *bool `json:",omitempty"`
Dlmalloc_alignment *int `json:",omitempty"`
Platform_sdk_version *int
}
func boolPtr(v bool) *bool {
return &v
}
func intPtr(v int) *int {
return &v
}
func (productVariables) DefaultConfig() jsonConfigurable {
v := productVariables{
Device_uses_jemalloc: boolPtr(true),
Platform_sdk_version: intPtr(22),
}
return v
}
func VariableMutator(mctx blueprint.EarlyMutatorContext) {
var module AndroidModule
var ok bool
if module, ok = mctx.Module().(AndroidModule); !ok {
return
}
// TODO: depend on config variable, create variants, propagate variants up tree
a := module.base()
variableValues := reflect.ValueOf(a.variableProperties.Product_variables)
zeroValues := reflect.ValueOf(zeroProductVariables.Product_variables)
for i := 0; i < variableValues.NumField(); i++ {
variableValue := variableValues.Field(i)
zeroValue := zeroValues.Field(i)
name := variableValues.Type().Field(i).Name
property := "product_variables." + proptools.PropertyNameForField(name)
// Check that the variable was set for the product
val := reflect.ValueOf(mctx.Config().(Config).ProductVariables).FieldByName(name)
if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
continue
}
val = val.Elem()
// For bools, check that the value is true
if val.Kind() == reflect.Bool && val.Bool() == false {
continue
}
// Check if any properties were set for the module
if reflect.DeepEqual(variableValue.Interface(), zeroValue.Interface()) {
continue
}
a.setVariableProperties(mctx, property, variableValue, val.Interface())
}
}
func (a *AndroidModuleBase) setVariableProperties(ctx blueprint.EarlyMutatorContext,
prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) {
generalPropertyValues := make([]reflect.Value, len(a.generalProperties))
for i := range a.generalProperties {
generalPropertyValues[i] = reflect.ValueOf(a.generalProperties[i]).Elem()
}
if variableValue != nil {
printfIntoProperties(productVariablePropertyValue, variableValue)
}
extendProperties(ctx, "", prefix, generalPropertyValues, productVariablePropertyValue, nil)
}
func printfIntoProperties(productVariablePropertyValue reflect.Value, variableValue interface{}) {
for i := 0; i < productVariablePropertyValue.NumField(); i++ {
propertyValue := productVariablePropertyValue.Field(i)
switch propertyValue.Kind() {
case reflect.String:
printfIntoProperty(propertyValue, variableValue)
case reflect.Slice:
for j := 0; j < propertyValue.Len(); j++ {
printfIntoProperty(propertyValue.Index(j), variableValue)
}
case reflect.Struct:
printfIntoProperties(propertyValue, variableValue)
default:
panic(fmt.Errorf("unsupported field kind %q", propertyValue.Kind()))
}
}
}
func printfIntoProperty(propertyValue reflect.Value, variableValue interface{}) {
s := propertyValue.String()
// For now, we only support int formats
var i int
if strings.Contains(s, "%d") {
switch v := variableValue.(type) {
case int:
i = v
case bool:
if v {
i = 1
}
default:
panic(fmt.Errorf("unsupported type %T", variableValue))
}
propertyValue.Set(reflect.ValueOf(fmt.Sprintf(s, i)))
}
}