Merge "Remove more unused code" into main am: a17792e2eb
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/3038267 Change-Id: I2059c16492fa27e4a4a93518ef69a45a4f655f01 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -20,8 +20,6 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"android/soong/bazel"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
@@ -492,10 +490,6 @@ type ProductVariables struct {
|
||||
|
||||
CheckVendorSeappViolations *bool `json:",omitempty"`
|
||||
|
||||
// PartitionVarsForBazelMigrationOnlyDoNotUse are extra variables that are used to define the
|
||||
// partition images. They should not be read from soong modules.
|
||||
PartitionVarsForBazelMigrationOnlyDoNotUse PartitionVariables `json:",omitempty"`
|
||||
|
||||
BuildFlags map[string]string `json:",omitempty"`
|
||||
|
||||
BuildFromSourceStub *bool `json:",omitempty"`
|
||||
@@ -644,387 +638,6 @@ func (this *ProductVariables) GetBuildFlagBool(flag string) bool {
|
||||
return val == "true"
|
||||
}
|
||||
|
||||
// ProductConfigContext requires the access to the Module to get product config properties.
|
||||
type ProductConfigContext interface {
|
||||
Module() Module
|
||||
}
|
||||
|
||||
// ProductConfigOrSoongConfigProperty represents either a soong config variable + its value
|
||||
// or a product config variable. You can get both a ConfigurationAxis and a SelectKey from it
|
||||
// for use in bazel attributes. ProductVariableProperties() will return a map from properties ->
|
||||
// this interface -> property structs for use in bp2build converters
|
||||
type ProductConfigOrSoongConfigProperty interface {
|
||||
// Name of the product variable or soong config variable
|
||||
Name() string
|
||||
// AlwaysEmit returns true for soong config variables but false for product variables. This
|
||||
// is intended to indicate if we need to always emit empty lists in the select statements.
|
||||
AlwaysEmit() bool
|
||||
// ConfigurationAxis returns the bazel.ConfigurationAxis that represents this variable. The
|
||||
// configuration axis will change depending on the variable and whether it's arch/os variant
|
||||
// as well.
|
||||
ConfigurationAxis() bazel.ConfigurationAxis
|
||||
// SelectKey returns a string that represents the key of a select branch, however, it is not
|
||||
// actually the real label written out to the build file.
|
||||
// this.ConfigurationAxis().SelectKey(this.SelectKey()) will give the actual label.
|
||||
SelectKey() string
|
||||
}
|
||||
|
||||
// ProductConfigProperty represents a product config variable, and if it is arch-variant or not.
|
||||
type ProductConfigProperty struct {
|
||||
// The name of the product variable, e.g. "safestack", "malloc_not_svelte",
|
||||
// "board"
|
||||
name string
|
||||
|
||||
arch string
|
||||
}
|
||||
|
||||
func (p ProductConfigProperty) Name() string {
|
||||
return p.name
|
||||
}
|
||||
|
||||
func (p ProductConfigProperty) AlwaysEmit() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p ProductConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
|
||||
return bazel.ProductVariableConfigurationAxis(p.arch != "", p.name+"__"+p.arch)
|
||||
}
|
||||
|
||||
func (p ProductConfigProperty) SelectKey() string {
|
||||
if p.arch == "" {
|
||||
return strings.ToLower(p.name)
|
||||
} else {
|
||||
return strings.ToLower(p.name + "-" + p.arch)
|
||||
}
|
||||
}
|
||||
|
||||
// SoongConfigProperty represents a soong config variable, its value if it's a string variable,
|
||||
// and if it's dependent on the OS or not
|
||||
type SoongConfigProperty struct {
|
||||
name string
|
||||
namespace string
|
||||
// Can be an empty string for bool/value soong config variables
|
||||
value string
|
||||
// If there is a target: field inside a soong config property struct, the os that it selects
|
||||
// on will be represented here.
|
||||
os string
|
||||
}
|
||||
|
||||
func (p SoongConfigProperty) Name() string {
|
||||
return p.name
|
||||
}
|
||||
|
||||
func (p SoongConfigProperty) AlwaysEmit() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p SoongConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
|
||||
return bazel.ProductVariableConfigurationAxis(false, p.namespace+"__"+p.name+"__"+p.os)
|
||||
}
|
||||
|
||||
// SelectKey returns the literal string that represents this variable in a BUILD
|
||||
// select statement.
|
||||
func (p SoongConfigProperty) SelectKey() string {
|
||||
// p.value being conditions_default can happen with or without a desired os. When not using
|
||||
// an os, we want to emit literally just //conditions:default in the select statement, but
|
||||
// when using an os, we want to emit namespace__name__conditions_default__os, so that
|
||||
// the branch is only taken if the variable is not set, and we're on the desired os.
|
||||
// ConfigurationAxis#SelectKey will map the conditions_default result of this function to
|
||||
// //conditions:default.
|
||||
if p.value == bazel.ConditionsDefaultConfigKey && p.os == "" {
|
||||
return bazel.ConditionsDefaultConfigKey
|
||||
}
|
||||
|
||||
parts := []string{p.namespace, p.name}
|
||||
if p.value != "" && p.value != bazel.ConditionsDefaultSelectKey {
|
||||
parts = append(parts, p.value)
|
||||
}
|
||||
if p.os != "" {
|
||||
parts = append(parts, p.os)
|
||||
}
|
||||
|
||||
// e.g. acme__feature1, android__board__soc_a, my_namespace__my_variables__my_value__my_os
|
||||
return strings.ToLower(strings.Join(parts, "__"))
|
||||
}
|
||||
|
||||
// ProductConfigProperties is a map of maps to group property values according
|
||||
// their property name and the product config variable they're set under.
|
||||
//
|
||||
// The outer map key is the name of the property, like "cflags".
|
||||
//
|
||||
// The inner map key is a ProductConfigProperty, which is a struct of product
|
||||
// variable name, namespace, and the "full configuration" of the product
|
||||
// variable.
|
||||
//
|
||||
// e.g. product variable name: board, namespace: acme, full config: vendor_chip_foo
|
||||
//
|
||||
// The value of the map is the interface{} representing the value of the
|
||||
// property, like ["-DDEFINES"] for cflags.
|
||||
type ProductConfigProperties map[string]map[ProductConfigOrSoongConfigProperty]interface{}
|
||||
|
||||
func (p *ProductConfigProperties) AddProductConfigProperty(
|
||||
propertyName, productVariableName, arch string, propertyValue interface{}) {
|
||||
|
||||
productConfigProp := ProductConfigProperty{
|
||||
name: productVariableName, // e.g. size, feature1, feature2, FEATURE3, board
|
||||
arch: arch, // e.g. "", x86, arm64
|
||||
}
|
||||
|
||||
p.AddEitherProperty(propertyName, productConfigProp, propertyValue)
|
||||
}
|
||||
|
||||
func (p *ProductConfigProperties) AddSoongConfigProperty(
|
||||
propertyName, namespace, variableName, value, os string, propertyValue interface{}) {
|
||||
|
||||
soongConfigProp := SoongConfigProperty{
|
||||
namespace: namespace,
|
||||
name: variableName, // e.g. size, feature1, feature2, FEATURE3, board
|
||||
value: value,
|
||||
os: os, // e.g. android, linux_x86
|
||||
}
|
||||
|
||||
p.AddEitherProperty(propertyName, soongConfigProp, propertyValue)
|
||||
}
|
||||
|
||||
func (p *ProductConfigProperties) AddEitherProperty(
|
||||
propertyName string, key ProductConfigOrSoongConfigProperty, propertyValue interface{}) {
|
||||
if (*p)[propertyName] == nil {
|
||||
(*p)[propertyName] = make(map[ProductConfigOrSoongConfigProperty]interface{})
|
||||
}
|
||||
|
||||
if existing, ok := (*p)[propertyName][key]; ok {
|
||||
switch dst := existing.(type) {
|
||||
case []string:
|
||||
src, ok := propertyValue.([]string)
|
||||
if !ok {
|
||||
panic("Conflicting types")
|
||||
}
|
||||
dst = append(dst, src...)
|
||||
(*p)[propertyName][key] = dst
|
||||
default:
|
||||
if existing != propertyValue {
|
||||
panic(fmt.Errorf("TODO: handle merging value %#v", existing))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(*p)[propertyName][key] = propertyValue
|
||||
}
|
||||
}
|
||||
|
||||
// maybeExtractConfigVarProp attempts to read this value as a config var struct
|
||||
// wrapped by interfaces and ptrs. If it's not the right type, the second return
|
||||
// value is false.
|
||||
func maybeExtractConfigVarProp(v reflect.Value) (reflect.Value, bool) {
|
||||
if v.Kind() == reflect.Interface {
|
||||
// The conditions_default value can be either
|
||||
// 1) an ptr to an interface of a struct (bool config variables and product variables)
|
||||
// 2) an interface of 1) (config variables with nested structs, like string vars)
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Ptr {
|
||||
return v, false
|
||||
}
|
||||
v = reflect.Indirect(v)
|
||||
if v.Kind() == reflect.Interface {
|
||||
// Extract the struct from the interface
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if !v.IsValid() {
|
||||
return v, false
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct {
|
||||
return v, false
|
||||
}
|
||||
return v, true
|
||||
}
|
||||
|
||||
func (productConfigProperties *ProductConfigProperties) AddProductConfigProperties(variableValues reflect.Value, arch string) {
|
||||
// Example of product_variables:
|
||||
//
|
||||
// product_variables: {
|
||||
// malloc_not_svelte: {
|
||||
// shared_libs: ["malloc_not_svelte_shared_lib"],
|
||||
// whole_static_libs: ["malloc_not_svelte_whole_static_lib"],
|
||||
// exclude_static_libs: [
|
||||
// "malloc_not_svelte_static_lib_excludes",
|
||||
// "malloc_not_svelte_whole_static_lib_excludes",
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
|
||||
for i := 0; i < variableValues.NumField(); i++ {
|
||||
// e.g. Platform_sdk_version, Unbundled_build, Malloc_not_svelte, etc.
|
||||
productVariableName := variableValues.Type().Field(i).Name
|
||||
|
||||
variableValue := variableValues.Field(i)
|
||||
// Check if any properties were set for the module
|
||||
if variableValue.IsZero() {
|
||||
// e.g. feature1: {}, malloc_not_svelte: {}
|
||||
continue
|
||||
}
|
||||
|
||||
for j := 0; j < variableValue.NumField(); j++ {
|
||||
property := variableValue.Field(j)
|
||||
// e.g. Asflags, Cflags, Enabled, etc.
|
||||
propertyName := variableValue.Type().Field(j).Name
|
||||
if property.Kind() != reflect.Interface {
|
||||
productConfigProperties.AddProductConfigProperty(propertyName, productVariableName, arch, property.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) error {
|
||||
//
|
||||
// Example of soong_config_variables:
|
||||
//
|
||||
// soong_config_variables: {
|
||||
// feature1: {
|
||||
// conditions_default: {
|
||||
// ...
|
||||
// },
|
||||
// cflags: ...
|
||||
// },
|
||||
// feature2: {
|
||||
// cflags: ...
|
||||
// conditions_default: {
|
||||
// ...
|
||||
// },
|
||||
// },
|
||||
// board: {
|
||||
// soc_a: {
|
||||
// ...
|
||||
// },
|
||||
// soc_b: {
|
||||
// ...
|
||||
// },
|
||||
// soc_c: {},
|
||||
// conditions_default: {
|
||||
// ...
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
for i := 0; i < soongConfigVariablesStruct.NumField(); i++ {
|
||||
// e.g. feature1, feature2, board
|
||||
variableName := soongConfigVariablesStruct.Type().Field(i).Name
|
||||
variableStruct := soongConfigVariablesStruct.Field(i)
|
||||
// Check if any properties were set for the module
|
||||
if variableStruct.IsZero() {
|
||||
// e.g. feature1: {}
|
||||
continue
|
||||
}
|
||||
|
||||
// Unlike product variables, config variables require a few more
|
||||
// indirections to extract the struct from the reflect.Value.
|
||||
if v, ok := maybeExtractConfigVarProp(variableStruct); ok {
|
||||
variableStruct = v
|
||||
} else if !v.IsValid() {
|
||||
// Skip invalid variables which may not used, else leads to panic
|
||||
continue
|
||||
}
|
||||
|
||||
for j := 0; j < variableStruct.NumField(); j++ {
|
||||
propertyOrStruct := variableStruct.Field(j)
|
||||
// propertyOrValueName can either be:
|
||||
// - A property, like: Asflags, Cflags, Enabled, etc.
|
||||
// - A soong config string variable's value, like soc_a, soc_b, soc_c in the example above
|
||||
// - "conditions_default"
|
||||
propertyOrValueName := variableStruct.Type().Field(j).Name
|
||||
|
||||
// If the property wasn't set, no need to pass it along
|
||||
if propertyOrStruct.IsZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
if v, ok := maybeExtractConfigVarProp(propertyOrStruct); ok {
|
||||
// The field is a struct, which is used by:
|
||||
// 1) soong_config_string_variables
|
||||
//
|
||||
// soc_a: {
|
||||
// cflags: ...,
|
||||
// }
|
||||
//
|
||||
// soc_b: {
|
||||
// cflags: ...,
|
||||
// }
|
||||
//
|
||||
// 2) conditions_default structs for all soong config variable types.
|
||||
//
|
||||
// conditions_default: {
|
||||
// cflags: ...,
|
||||
// static_libs: ...
|
||||
// }
|
||||
//
|
||||
// This means that propertyOrValueName is either conditions_default, or a soong
|
||||
// config string variable's value.
|
||||
field := v
|
||||
// Iterate over fields of this struct prop.
|
||||
for k := 0; k < field.NumField(); k++ {
|
||||
// For product variables, zero values are irrelevant; however, for soong config variables,
|
||||
// empty values are relevant because there can also be a conditions default which is not
|
||||
// applied for empty variables.
|
||||
if field.Field(k).IsZero() && namespace == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
propertyName := field.Type().Field(k).Name
|
||||
if propertyName == "Target" {
|
||||
productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), field.Field(k))
|
||||
} else if propertyName == "Arch" || propertyName == "Multilib" {
|
||||
return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
|
||||
} else {
|
||||
productConfigProperties.AddSoongConfigProperty(propertyName, namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), "", field.Field(k).Interface())
|
||||
}
|
||||
}
|
||||
} else if propertyOrStruct.Kind() != reflect.Interface {
|
||||
// If not an interface, then this is not a conditions_default or
|
||||
// a struct prop. That is, this is a bool/value config variable.
|
||||
if propertyOrValueName == "Target" {
|
||||
productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, "", propertyOrStruct)
|
||||
} else if propertyOrValueName == "Arch" || propertyOrValueName == "Multilib" {
|
||||
return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
|
||||
} else {
|
||||
productConfigProperties.AddSoongConfigProperty(propertyOrValueName, namespace, variableName, "", "", propertyOrStruct.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (productConfigProperties *ProductConfigProperties) AddSoongConfigPropertiesFromTargetStruct(namespace, soongConfigVariableName string, soongConfigVariableValue string, targetStruct reflect.Value) {
|
||||
// targetStruct will be a struct with fields like "android", "host", "arm", "x86",
|
||||
// "android_arm", etc. The values of each of those fields will be a regular property struct.
|
||||
for i := 0; i < targetStruct.NumField(); i++ {
|
||||
targetFieldName := targetStruct.Type().Field(i).Name
|
||||
archOrOsSpecificStruct := targetStruct.Field(i)
|
||||
for j := 0; j < archOrOsSpecificStruct.NumField(); j++ {
|
||||
property := archOrOsSpecificStruct.Field(j)
|
||||
// e.g. Asflags, Cflags, Enabled, etc.
|
||||
propertyName := archOrOsSpecificStruct.Type().Field(j).Name
|
||||
|
||||
if targetFieldName == "Android" {
|
||||
productConfigProperties.AddSoongConfigProperty(propertyName, namespace, soongConfigVariableName, soongConfigVariableValue, "android", property.Interface())
|
||||
} else if targetFieldName == "Host" {
|
||||
for _, os := range osTypeList {
|
||||
if os.Class == Host {
|
||||
productConfigProperties.AddSoongConfigProperty(propertyName, namespace, soongConfigVariableName, soongConfigVariableValue, os.Name, property.Interface())
|
||||
}
|
||||
}
|
||||
} else if !archOrOsSpecificStruct.IsZero() {
|
||||
// One problem with supporting additional fields is that if multiple branches of
|
||||
// "target" overlap, we don't want them to be in the same select statement (aka
|
||||
// configuration axis). "android" and "host" are disjoint, so it's ok that we only
|
||||
// have 2 axes right now. (soongConfigVariables and soongConfigVariablesPlusOs)
|
||||
panic("TODO: support other target types in soong config variable structs: " + targetFieldName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func VariableMutator(mctx BottomUpMutatorContext) {
|
||||
var module Module
|
||||
var ok bool
|
||||
|
Reference in New Issue
Block a user