Files
build_soong/common/variable.go
Colin Cross 2738597af0 Fix product variables with no soong.variables
If soong.variables didn't exist, loadFromConfigFile would write default
values to soong.variables, but return with the product variables set to
the zero values.  Replace jsonConfigurable.DefaultConfig() with
SetDefaultConfig() that modifies the current object, and call it before
writing the values.

Change-Id: I7b7404c7a51975dc4493e25c775b3cf56ef335e3
2015-09-18 10:59:41 -07:00

194 lines
5.5 KiB
Go

// 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
DeviceArch *string `json:",omitempty"`
DeviceArchVariant *string `json:",omitempty"`
DeviceCpuVariant *string `json:",omitempty"`
DeviceAbi *[]string `json:",omitempty"`
DeviceSecondaryArch *string `json:",omitempty"`
DeviceSecondaryArchVariant *string `json:",omitempty"`
DeviceSecondaryCpuVariant *string `json:",omitempty"`
DeviceSecondaryAbi *[]string `json:",omitempty"`
HostArch *string `json:",omitempty"`
HostSecondaryArch *string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
return &v
}
func intPtr(v int) *int {
return &v
}
func stringPtr(v string) *string {
return &v
}
func (v *productVariables) SetDefaultConfig() {
*v = productVariables{
Device_uses_jemalloc: boolPtr(true),
Platform_sdk_version: intPtr(22),
HostArch: stringPtr("x86_64"),
HostSecondaryArch: stringPtr("x86"),
DeviceArch: stringPtr("arm64"),
DeviceCpuVariant: stringPtr("denver64"),
DeviceAbi: &[]string{"arm64-v8a"},
DeviceSecondaryArch: stringPtr("arm"),
DeviceSecondaryArchVariant: stringPtr("armv7-a-neon"),
DeviceSecondaryCpuVariant: stringPtr("cortex-a15"),
DeviceSecondaryAbi: &[]string{"armeabi-v7a"},
}
}
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)))
}
}