Fix bp2build select generation for inter-attribute soong config am: 58ff6801f4 am: d4c0c1fc12 am: 19de6d49ea am: c71a9482c5

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1894968

Change-Id: I742ff28ab3c601571d6fbe38d76e0274a8713119
This commit is contained in:
Jingwen Chen
2021-11-23 12:46:21 +00:00
committed by Automerger Merge Worker
6 changed files with 418 additions and 21 deletions

View File

@@ -567,6 +567,10 @@ type ProductConfigProperty struct {
FullConfig string
}
func (p *ProductConfigProperty) AlwaysEmit() bool {
return p.Namespace != ""
}
func (p *ProductConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
if p.Namespace == "" {
return bazel.ProductVariableConfigurationAxis(p.FullConfig)
@@ -655,9 +659,123 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp
}
}
productConfigProperties.zeroValuesForNamespacedVariables()
return productConfigProperties
}
// zeroValuesForNamespacedVariables ensures that selects that contain __only__
// conditions default values have zero values set for the other non-default
// values for that select statement.
//
// If the ProductConfigProperties map contains these items, as parsed from the .bp file:
//
// library_linking_strategy: {
// prefer_static: {
// static_libs: [
// "lib_a",
// "lib_b",
// ],
// },
// conditions_default: {
// shared_libs: [
// "lib_a",
// "lib_b",
// ],
// },
// },
//
// Static_libs {Library_linking_strategy ANDROID prefer_static} [lib_a lib_b]
// Shared_libs {Library_linking_strategy ANDROID conditions_default} [lib_a lib_b]
//
// We need to add this:
//
// Shared_libs {Library_linking_strategy ANDROID prefer_static} []
//
// so that the following gets generated for the "dynamic_deps" attribute,
// instead of putting lib_a and lib_b directly into dynamic_deps without a
// select:
//
// dynamic_deps = select({
// "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
// "//conditions:default": [
// "//foo/bar:lib_a",
// "//foo/bar:lib_b",
// ],
// }),
func (props *ProductConfigProperties) zeroValuesForNamespacedVariables() {
// A map of product config properties to the zero values of their respective
// property value.
zeroValues := make(map[ProductConfigProperty]interface{})
// A map of prop names (e.g. cflags) to product config properties where the
// (prop name, ProductConfigProperty) tuple contains a non-conditions_default key.
//
// e.g.
//
// prefer_static: {
// static_libs: [
// "lib_a",
// "lib_b",
// ],
// },
// conditions_default: {
// shared_libs: [
// "lib_a",
// "lib_b",
// ],
// },
//
// The tuple of ("static_libs", prefer_static) would be in this map.
hasNonDefaultValue := make(map[string]map[ProductConfigProperty]bool)
// Iterate over all added soong config variables.
for propName, v := range *props {
for p, intf := range v {
if p.Namespace == "" {
// If there's no namespace, this isn't a soong config variable,
// i.e. this is a product variable. product variables have no
// conditions_defaults, so skip them.
continue
}
if p.FullConfig == bazel.ConditionsDefaultConfigKey {
// Skip conditions_defaults.
continue
}
if hasNonDefaultValue[propName] == nil {
hasNonDefaultValue[propName] = make(map[ProductConfigProperty]bool)
hasNonDefaultValue[propName][p] = false
}
// Create the zero value of the variable.
if _, exists := zeroValues[p]; !exists {
zeroValue := reflect.Zero(reflect.ValueOf(intf).Type()).Interface()
if zeroValue == nil {
panic(fmt.Errorf("Expected non-nil zero value for product/config variable %+v\n", intf))
}
zeroValues[p] = zeroValue
}
hasNonDefaultValue[propName][p] = true
}
}
for propName := range *props {
for p, zeroValue := range zeroValues {
// Ignore variables that already have a non-default value for that axis
if exists, _ := hasNonDefaultValue[propName][p]; !exists {
// fmt.Println(propName, p.Namespace, p.Name, p.FullConfig, zeroValue)
// Insert the zero value for this propname + product config value.
props.AddProductConfigProperty(
propName,
p.Namespace,
p.Name,
p.FullConfig,
zeroValue,
)
}
}
}
}
func (p *ProductConfigProperties) AddProductConfigProperty(
propertyName, namespace, productVariableName, config string, property interface{}) {
if (*p)[propertyName] == nil {
@@ -678,7 +796,7 @@ func (p *ProductConfigProperties) AddProductConfigProperty(
(*p)[propertyName][productConfigProp] = dst
}
default:
// TODO(jingwen): Add support for more types.
panic(fmt.Errorf("TODO: handle merging value %s", existing))
}
} else {
(*p)[propertyName][productConfigProp] = property
@@ -826,9 +944,10 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti
field.Field(k).Interface(), // e.g. ["-DDEFAULT"], ["foo", "bar"]
)
}
} else {
// Not a conditions_default or a struct prop, i.e. regular
// product variables, or not a string-typed config var.
} else if property.Kind() != reflect.Interface {
// If not an interface, then this is not a conditions_default or
// a struct prop. That is, this is a regular product variable,
// or a bool/value config variable.
config := productVariableName + suffix
productConfigProperties.AddProductConfigProperty(
propertyName,