product_variables srcs in prebuilt_etc

bp2build conversion handles product_variable srcs

bug: 228353067
Test: prebuilt_etc_conversion_test.go
Change-Id: I82d3a384ee14d4e981d502dd9eb824c87d5ae2c7
This commit is contained in:
Alix 2022-06-09 18:52:05 +00:00
parent 94e2603ab7
commit bbfd538326
6 changed files with 144 additions and 20 deletions

View file

@ -592,6 +592,9 @@ type ProductConfigProperty struct {
// "acme__board__soc_a", "acme__board__soc_b", and
// "acme__board__conditions_default"
FullConfig string
// keeps track of whether this product variable is nested under an arch variant
OuterAxis bazel.ConfigurationAxis
}
func (p *ProductConfigProperty) AlwaysEmit() bool {
@ -600,11 +603,11 @@ func (p *ProductConfigProperty) AlwaysEmit() bool {
func (p *ProductConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
if p.Namespace == "" {
return bazel.ProductVariableConfigurationAxis(p.FullConfig)
return bazel.ProductVariableConfigurationAxis(p.FullConfig, p.OuterAxis)
} else {
// Soong config variables can be uniquely identified by the namespace
// (e.g. acme, android) and the product variable name (e.g. board, size)
return bazel.ProductVariableConfigurationAxis(p.Namespace + "__" + p.Name)
return bazel.ProductVariableConfigurationAxis(p.Namespace+"__"+p.Name, bazel.NoConfigAxis)
}
}
@ -663,9 +666,11 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp
moduleBase.variableProperties,
"",
"",
&productConfigProperties)
&productConfigProperties,
bazel.ConfigurationAxis{},
)
for _, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
for axis, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
for config, props := range configToProps {
// GetArchVariantProperties is creating an instance of the requested type
// and productVariablesValues expects an interface, so no need to cast
@ -674,7 +679,8 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp
props,
"",
config,
&productConfigProperties)
&productConfigProperties,
axis)
}
}
}
@ -687,7 +693,8 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp
namespacedVariableProp,
namespace,
"",
&productConfigProperties)
&productConfigProperties,
bazel.NoConfigAxis)
}
}
}
@ -803,6 +810,7 @@ func (props *ProductConfigProperties) zeroValuesForNamespacedVariables() {
p.Name,
p.FullConfig,
zeroValue,
bazel.NoConfigAxis,
)
}
}
@ -810,7 +818,7 @@ func (props *ProductConfigProperties) zeroValuesForNamespacedVariables() {
}
func (p *ProductConfigProperties) AddProductConfigProperty(
propertyName, namespace, productVariableName, config string, property interface{}) {
propertyName, namespace, productVariableName, config string, property interface{}, outerAxis bazel.ConfigurationAxis) {
if (*p)[propertyName] == nil {
(*p)[propertyName] = make(map[ProductConfigProperty]interface{})
}
@ -819,6 +827,7 @@ func (p *ProductConfigProperties) AddProductConfigProperty(
Namespace: namespace, // e.g. acme, android
Name: productVariableName, // e.g. size, feature1, feature2, FEATURE3, board
FullConfig: config, // e.g. size, feature1-x86, size__conditions_default
OuterAxis: outerAxis,
}
if existing, ok := (*p)[propertyName][productConfigProp]; ok && namespace != "" {
@ -869,7 +878,7 @@ func maybeExtractConfigVarProp(v reflect.Value) (reflect.Value, bool) {
return v, true
}
func (productConfigProperties *ProductConfigProperties) AddProductConfigProperties(namespace, suffix string, variableValues reflect.Value) {
func (productConfigProperties *ProductConfigProperties) AddProductConfigProperties(namespace, suffix string, variableValues reflect.Value, outerAxis bazel.ConfigurationAxis) {
// variableValues can either be a product_variables or
// soong_config_variables struct.
//
@ -974,7 +983,8 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti
namespace, // e.g. acme, android
productVariableName, // e.g. size, feature1, FEATURE2, board
config,
field.Field(k).Interface(), // e.g. ["-DDEFAULT"], ["foo", "bar"]
field.Field(k).Interface(), // e.g. ["-DDEFAULT"], ["foo", "bar"],
outerAxis,
)
}
} else if property.Kind() != reflect.Interface {
@ -988,6 +998,7 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti
productVariableName,
config,
property.Interface(),
outerAxis,
)
}
}
@ -998,14 +1009,14 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti
// product_variables and soong_config_variables to structs that can be generated
// as select statements.
func productVariableValues(
fieldName string, variableProps interface{}, namespace, suffix string, productConfigProperties *ProductConfigProperties) {
fieldName string, variableProps interface{}, namespace, suffix string, productConfigProperties *ProductConfigProperties, outerAxis bazel.ConfigurationAxis) {
if suffix != "" {
suffix = "-" + suffix
}
// variableValues represent the product_variables or soong_config_variables struct.
variableValues := reflect.ValueOf(variableProps).Elem().FieldByName(fieldName)
productConfigProperties.AddProductConfigProperties(namespace, suffix, variableValues)
productConfigProperties.AddProductConfigProperties(namespace, suffix, variableValues, outerAxis)
}
func VariableMutator(mctx BottomUpMutatorContext) {

View file

@ -295,10 +295,11 @@ var (
)
// ProductVariableConfigurationAxis returns an axis for the given product variable
func ProductVariableConfigurationAxis(variable string) ConfigurationAxis {
func ProductVariableConfigurationAxis(variable string, outerAxis ConfigurationAxis) ConfigurationAxis {
return ConfigurationAxis{
configurationType: productVariables,
subType: variable,
outerAxisType: outerAxis.configurationType,
}
}
@ -309,6 +310,8 @@ type ConfigurationAxis struct {
// some configuration types (e.g. productVariables) have multiple independent axes, subType helps
// distinguish between them without needing to list all 17 product variables.
subType string
// used to keep track of which product variables are arch variant
outerAxisType configurationType
}
func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {

View file

@ -309,7 +309,19 @@ func (la *LabelAttribute) Collapse() error {
_, containsProductVariables := axisTypes[productVariables]
if containsProductVariables {
if containsOs || containsArch || containsOsArch {
return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
if containsArch {
allProductVariablesAreArchVariant := true
for k := range la.ConfigurableValues {
if k.configurationType == productVariables && k.outerAxisType != arch {
allProductVariablesAreArchVariant = false
}
}
if !allProductVariablesAreArchVariant {
return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
}
} else {
return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
}
}
}
if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {

View file

@ -247,13 +247,13 @@ func TestResolveExcludes(t *testing.T) {
OsArchConfigurationAxis: labelListSelectValues{
"linux_x86": makeLabelList([]string{"linux_x86_include"}, []string{}),
},
ProductVariableConfigurationAxis("product_with_defaults"): labelListSelectValues{
ProductVariableConfigurationAxis("product_with_defaults", NoConfigAxis): labelListSelectValues{
"a": makeLabelList([]string{}, []string{"not_in_value"}),
"b": makeLabelList([]string{"b_val"}, []string{}),
"c": makeLabelList([]string{"c_val"}, []string{}),
ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2"}, []string{}),
},
ProductVariableConfigurationAxis("product_only_with_excludes"): labelListSelectValues{
ProductVariableConfigurationAxis("product_only_with_excludes", NoConfigAxis): labelListSelectValues{
"a": makeLabelList([]string{}, []string{"not_in_value"}),
},
},
@ -281,7 +281,7 @@ func TestResolveExcludes(t *testing.T) {
"linux_x86": makeLabels("linux_x86_include"),
ConditionsDefaultConfigKey: nilLabels,
},
ProductVariableConfigurationAxis("product_with_defaults"): {
ProductVariableConfigurationAxis("product_with_defaults", NoConfigAxis): {
"a": nilLabels,
"b": makeLabels("b_val"),
"c": makeLabels("c_val"),
@ -674,7 +674,7 @@ func TestDeduplicateAxesFromBase(t *testing.T) {
OsArchConfigurationAxis: stringListSelectValues{
"linux_x86": {"linux_x86_include"},
},
ProductVariableConfigurationAxis("a"): stringListSelectValues{
ProductVariableConfigurationAxis("a", NoConfigAxis): stringListSelectValues{
"a": []string{"not_in_value"},
},
},
@ -699,7 +699,7 @@ func TestDeduplicateAxesFromBase(t *testing.T) {
"linux": []string{"linux_include"},
},
OsArchConfigurationAxis: stringListSelectValues{},
ProductVariableConfigurationAxis("a"): stringListSelectValues{
ProductVariableConfigurationAxis("a", NoConfigAxis): stringListSelectValues{
"a": []string{"not_in_value"},
},
}

View file

@ -15,10 +15,11 @@
package bp2build
import (
"fmt"
"testing"
"android/soong/android"
"android/soong/etc"
"testing"
)
func runPrebuiltEtcTestCase(t *testing.T, tc Bp2buildTestCase) {
@ -128,6 +129,32 @@ prebuilt_etc {
"dir": `"etc/tz"`,
})}})
}
func TestPrebuiltEtcProductVariables(t *testing.T) {
runPrebuiltEtcTestCase(t, Bp2buildTestCase{
Description: "prebuilt etc - product variables",
Filesystem: map[string]string{},
Blueprint: `
prebuilt_etc {
name: "apex_tz_version",
src: "version/tz_version",
filename: "tz_version",
product_variables: {
native_coverage: {
src: "src1",
},
},
}
`,
ExpectedBazelTargets: []string{
MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
"filename": `"tz_version"`,
"src": `select({
"//build/bazel/product_variables:native_coverage": "src1",
"//conditions:default": "version/tz_version",
})`,
"dir": `"etc"`,
})}})
}
func runPrebuiltUsrShareTestCase(t *testing.T, tc Bp2buildTestCase) {
t.Helper()
@ -265,3 +292,57 @@ prebuilt_etc {
"dir": `"etc"`,
})}})
}
func TestPrebuiltEtcProductVariableArchSrcs(t *testing.T) {
runPrebuiltEtcTestCase(t, Bp2buildTestCase{
Description: "prebuilt etc- SRcs from arch variant product variables",
Filesystem: map[string]string{},
Blueprint: `
prebuilt_etc {
name: "foo",
filename: "fooFilename",
arch: {
arm: {
src: "armSrc",
product_variables: {
native_coverage: {
src: "nativeCoverageArmSrc",
},
},
},
},
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
"filename": `"fooFilename"`,
"dir": `"etc"`,
"src": `select({
"//build/bazel/platforms/arch:arm": "armSrc",
"//build/bazel/product_variables:native_coverage-arm": "nativeCoverageArmSrc",
"//conditions:default": None,
})`,
})}})
}
func TestPrebuiltEtcProductVariableError(t *testing.T) {
runPrebuiltEtcTestCase(t, Bp2buildTestCase{
Description: "",
Filesystem: map[string]string{},
Blueprint: `
prebuilt_etc {
name: "foo",
filename: "fooFilename",
arch: {
arm: {
src: "armSrc",
},
},
product_variables: {
native_coverage: {
src: "nativeCoverageArmSrc",
},
},
}`,
ExpectedErr: fmt.Errorf("label attribute could not be collapsed"),
})
}

View file

@ -31,6 +31,7 @@ import (
"encoding/json"
"fmt"
"path/filepath"
"reflect"
"strings"
"github.com/google/blueprint/proptools"
@ -692,6 +693,22 @@ func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext
src.SetSelectValue(axis, config, label)
}
}
for propName, productConfigProps := range android.ProductVariableProperties(ctx) {
for configProp, propVal := range productConfigProps {
if propName == "Src" {
props, ok := propVal.(*string)
if !ok {
ctx.PropertyErrorf(" Expected Property to have type string, but was %s\n", reflect.TypeOf(propVal).String())
continue
}
if props != nil {
label := android.BazelLabelForModuleSrcSingle(ctx, *props)
src.SetSelectValue(configProp.ConfigurationAxis(), configProp.SelectKey(), label)
}
}
}
}
}
var filename string