Merge "Handle product config vars in bp2build."
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BazelTargetModuleProperties contain properties and metadata used for
|
// BazelTargetModuleProperties contain properties and metadata used for
|
||||||
@@ -200,6 +201,10 @@ const (
|
|||||||
// config variable default key in an Android.bp file, although there's no
|
// config variable default key in an Android.bp file, although there's no
|
||||||
// integration with Soong config variables (yet).
|
// integration with Soong config variables (yet).
|
||||||
CONDITIONS_DEFAULT = "conditions_default"
|
CONDITIONS_DEFAULT = "conditions_default"
|
||||||
|
|
||||||
|
ConditionsDefaultSelectKey = "//conditions:default"
|
||||||
|
|
||||||
|
productVariableBazelPackage = "//build/bazel/product_variables"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -215,7 +220,7 @@ var (
|
|||||||
ARCH_ARM64: "//build/bazel/platforms/arch:arm64",
|
ARCH_ARM64: "//build/bazel/platforms/arch:arm64",
|
||||||
ARCH_X86: "//build/bazel/platforms/arch:x86",
|
ARCH_X86: "//build/bazel/platforms/arch:x86",
|
||||||
ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
|
ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
|
||||||
CONDITIONS_DEFAULT: "//conditions:default", // The default condition of as arch select map.
|
CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of as arch select map.
|
||||||
}
|
}
|
||||||
|
|
||||||
// A map of target operating systems to the Bazel label of the
|
// A map of target operating systems to the Bazel label of the
|
||||||
@@ -227,7 +232,7 @@ var (
|
|||||||
OS_LINUX: "//build/bazel/platforms/os:linux",
|
OS_LINUX: "//build/bazel/platforms/os:linux",
|
||||||
OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
|
OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
|
||||||
OS_WINDOWS: "//build/bazel/platforms/os:windows",
|
OS_WINDOWS: "//build/bazel/platforms/os:windows",
|
||||||
CONDITIONS_DEFAULT: "//conditions:default", // The default condition of an os select map.
|
CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of an os select map.
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -435,6 +440,10 @@ type StringListAttribute struct {
|
|||||||
// are generated in a select statement and appended to the non-os specific
|
// are generated in a select statement and appended to the non-os specific
|
||||||
// label list Value.
|
// label list Value.
|
||||||
OsValues stringListOsValues
|
OsValues stringListOsValues
|
||||||
|
|
||||||
|
// list of product-variable string list values. Optional. if used, each will generate a select
|
||||||
|
// statement appended to the label list Value.
|
||||||
|
ProductValues []ProductVariableValues
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
|
// MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
|
||||||
@@ -466,6 +475,18 @@ type stringListOsValues struct {
|
|||||||
ConditionsDefault []string
|
ConditionsDefault []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Product Variable values for StringListAttribute
|
||||||
|
type ProductVariableValues struct {
|
||||||
|
ProductVariable string
|
||||||
|
|
||||||
|
Values []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectKey returns the appropriate select key for the receiving ProductVariableValues.
|
||||||
|
func (p ProductVariableValues) SelectKey() string {
|
||||||
|
return fmt.Sprintf("%s:%s", productVariableBazelPackage, strings.ToLower(p.ProductVariable))
|
||||||
|
}
|
||||||
|
|
||||||
// HasConfigurableValues returns true if the attribute contains
|
// HasConfigurableValues returns true if the attribute contains
|
||||||
// architecture-specific string_list values.
|
// architecture-specific string_list values.
|
||||||
func (attrs StringListAttribute) HasConfigurableValues() bool {
|
func (attrs StringListAttribute) HasConfigurableValues() bool {
|
||||||
@@ -480,7 +501,8 @@ func (attrs StringListAttribute) HasConfigurableValues() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
|
return len(attrs.ProductValues) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
|
func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
|
||||||
@@ -558,6 +580,21 @@ func (attrs *StringListAttribute) Append(other StringListAttribute) {
|
|||||||
attrs.SetValueForOS(os, this)
|
attrs.SetValueForOS(os, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
productValues := make(map[string][]string, 0)
|
||||||
|
for _, pv := range attrs.ProductValues {
|
||||||
|
productValues[pv.ProductVariable] = pv.Values
|
||||||
|
}
|
||||||
|
for _, pv := range other.ProductValues {
|
||||||
|
productValues[pv.ProductVariable] = append(productValues[pv.ProductVariable], pv.Values...)
|
||||||
|
}
|
||||||
|
attrs.ProductValues = make([]ProductVariableValues, 0, len(productValues))
|
||||||
|
for pv, vals := range productValues {
|
||||||
|
attrs.ProductValues = append(attrs.ProductValues, ProductVariableValues{
|
||||||
|
ProductVariable: pv,
|
||||||
|
Values: vals,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
attrs.Value = append(attrs.Value, other.Value...)
|
attrs.Value = append(attrs.Value, other.Value...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1156,3 +1156,48 @@ cc_library_static {
|
|||||||
)`},
|
)`},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCcLibraryStaticProductVariableSelects(t *testing.T) {
|
||||||
|
runCcLibraryStaticTestCase(t, bp2buildTestCase{
|
||||||
|
description: "cc_library_static product variable selects",
|
||||||
|
moduleTypeUnderTest: "cc_library_static",
|
||||||
|
moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
|
||||||
|
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
|
||||||
|
depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
|
||||||
|
filesystem: map[string]string{},
|
||||||
|
blueprint: soongCcLibraryStaticPreamble + `
|
||||||
|
cc_library_static {
|
||||||
|
name: "foo_static",
|
||||||
|
srcs: ["common.c"],
|
||||||
|
product_variables: {
|
||||||
|
malloc_not_svelte: {
|
||||||
|
cflags: ["-Wmalloc_not_svelte"],
|
||||||
|
},
|
||||||
|
malloc_zero_contents: {
|
||||||
|
cflags: ["-Wmalloc_zero_contents"],
|
||||||
|
},
|
||||||
|
binder32bit: {
|
||||||
|
cflags: ["-Wbinder32bit"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} `,
|
||||||
|
expectedBazelTargets: []string{`cc_library_static(
|
||||||
|
name = "foo_static",
|
||||||
|
copts = [
|
||||||
|
"-I.",
|
||||||
|
"-I$(BINDIR)/.",
|
||||||
|
] + select({
|
||||||
|
"//build/bazel/product_variables:malloc_not_svelte": ["-Wmalloc_not_svelte"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}) + select({
|
||||||
|
"//build/bazel/product_variables:malloc_zero_contents": ["-Wmalloc_zero_contents"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}) + select({
|
||||||
|
"//build/bazel/product_variables:binder32bit": ["-Wbinder32bit"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
linkstatic = True,
|
||||||
|
srcs = ["common.c"],
|
||||||
|
)`},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@@ -208,7 +208,10 @@ func TestCcObjectProductVariable(t *testing.T) {
|
|||||||
`,
|
`,
|
||||||
expectedBazelTargets: []string{`cc_object(
|
expectedBazelTargets: []string{`cc_object(
|
||||||
name = "foo",
|
name = "foo",
|
||||||
asflags = ["-DPLATFORM_SDK_VERSION={Platform_sdk_version}"],
|
asflags = select({
|
||||||
|
"//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION={Platform_sdk_version}"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
copts = ["-fno-addrsig"],
|
copts = ["-fno-addrsig"],
|
||||||
)`,
|
)`,
|
||||||
},
|
},
|
||||||
|
@@ -11,26 +11,42 @@ import (
|
|||||||
|
|
||||||
type selects map[string]reflect.Value
|
type selects map[string]reflect.Value
|
||||||
|
|
||||||
func getStringListValues(list bazel.StringListAttribute) (reflect.Value, selects, selects) {
|
func getStringListValues(list bazel.StringListAttribute) (reflect.Value, []selects) {
|
||||||
value := reflect.ValueOf(list.Value)
|
value := reflect.ValueOf(list.Value)
|
||||||
if !list.HasConfigurableValues() {
|
if !list.HasConfigurableValues() {
|
||||||
return value, nil, nil
|
return value, []selects{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectValues := make([]selects, 0)
|
||||||
archSelects := map[string]reflect.Value{}
|
archSelects := map[string]reflect.Value{}
|
||||||
for arch, selectKey := range bazel.PlatformArchMap {
|
for arch, selectKey := range bazel.PlatformArchMap {
|
||||||
archSelects[selectKey] = reflect.ValueOf(list.GetValueForArch(arch))
|
archSelects[selectKey] = reflect.ValueOf(list.GetValueForArch(arch))
|
||||||
}
|
}
|
||||||
|
if len(archSelects) > 0 {
|
||||||
|
selectValues = append(selectValues, archSelects)
|
||||||
|
}
|
||||||
|
|
||||||
osSelects := map[string]reflect.Value{}
|
osSelects := map[string]reflect.Value{}
|
||||||
for os, selectKey := range bazel.PlatformOsMap {
|
for os, selectKey := range bazel.PlatformOsMap {
|
||||||
osSelects[selectKey] = reflect.ValueOf(list.GetValueForOS(os))
|
osSelects[selectKey] = reflect.ValueOf(list.GetValueForOS(os))
|
||||||
}
|
}
|
||||||
|
if len(osSelects) > 0 {
|
||||||
|
selectValues = append(selectValues, osSelects)
|
||||||
|
}
|
||||||
|
|
||||||
return value, archSelects, osSelects
|
for _, pv := range list.ProductValues {
|
||||||
|
s := make(selects)
|
||||||
|
if len(pv.Values) > 0 {
|
||||||
|
s[pv.SelectKey()] = reflect.ValueOf(pv.Values)
|
||||||
|
s[bazel.ConditionsDefaultSelectKey] = reflect.ValueOf([]string{})
|
||||||
|
selectValues = append(selectValues, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, selectValues
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLabelValue(label bazel.LabelAttribute) (reflect.Value, selects, selects) {
|
func getLabelValue(label bazel.LabelAttribute) (reflect.Value, []selects) {
|
||||||
var value reflect.Value
|
var value reflect.Value
|
||||||
var archSelects selects
|
var archSelects selects
|
||||||
|
|
||||||
@@ -43,13 +59,13 @@ func getLabelValue(label bazel.LabelAttribute) (reflect.Value, selects, selects)
|
|||||||
value = reflect.ValueOf(label.Value)
|
value = reflect.ValueOf(label.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, archSelects, nil
|
return value, []selects{archSelects}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, selects, selects) {
|
func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects) {
|
||||||
value := reflect.ValueOf(list.Value.Includes)
|
value := reflect.ValueOf(list.Value.Includes)
|
||||||
if !list.HasConfigurableValues() {
|
if !list.HasConfigurableValues() {
|
||||||
return value, nil, nil
|
return value, []selects{}
|
||||||
}
|
}
|
||||||
|
|
||||||
archSelects := map[string]reflect.Value{}
|
archSelects := map[string]reflect.Value{}
|
||||||
@@ -62,29 +78,30 @@ func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, selects,
|
|||||||
osSelects[selectKey] = reflect.ValueOf(list.GetValueForOS(os).Includes)
|
osSelects[selectKey] = reflect.ValueOf(list.GetValueForOS(os).Includes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, archSelects, osSelects
|
return value, []selects{archSelects, osSelects}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prettyPrintAttribute converts an Attribute to its Bazel syntax. May contain
|
// prettyPrintAttribute converts an Attribute to its Bazel syntax. May contain
|
||||||
// select statements.
|
// select statements.
|
||||||
func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
|
func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
|
||||||
var value reflect.Value
|
var value reflect.Value
|
||||||
var archSelects, osSelects selects
|
var configurableAttrs []selects
|
||||||
var defaultSelectValue string
|
var defaultSelectValue string
|
||||||
switch list := v.(type) {
|
switch list := v.(type) {
|
||||||
case bazel.StringListAttribute:
|
case bazel.StringListAttribute:
|
||||||
value, archSelects, osSelects = getStringListValues(list)
|
value, configurableAttrs = getStringListValues(list)
|
||||||
defaultSelectValue = "[]"
|
defaultSelectValue = "[]"
|
||||||
case bazel.LabelListAttribute:
|
case bazel.LabelListAttribute:
|
||||||
value, archSelects, osSelects = getLabelListValues(list)
|
value, configurableAttrs = getLabelListValues(list)
|
||||||
defaultSelectValue = "[]"
|
defaultSelectValue = "[]"
|
||||||
case bazel.LabelAttribute:
|
case bazel.LabelAttribute:
|
||||||
value, archSelects, osSelects = getLabelValue(list)
|
value, configurableAttrs = getLabelValue(list)
|
||||||
defaultSelectValue = "None"
|
defaultSelectValue = "None"
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("Not a supported Bazel attribute type: %s", v)
|
return "", fmt.Errorf("Not a supported Bazel attribute type: %s", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
ret := ""
|
ret := ""
|
||||||
if value.Kind() != reflect.Invalid {
|
if value.Kind() != reflect.Invalid {
|
||||||
s, err := prettyPrint(value, indent)
|
s, err := prettyPrint(value, indent)
|
||||||
@@ -108,13 +125,14 @@ func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err := appendSelects(archSelects, defaultSelectValue, ret)
|
for _, configurableAttr := range configurableAttrs {
|
||||||
if err != nil {
|
ret, err = appendSelects(configurableAttr, defaultSelectValue, ret)
|
||||||
return "", err
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err = appendSelects(osSelects, defaultSelectValue, ret)
|
return ret, nil
|
||||||
return ret, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
|
// prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
|
||||||
@@ -125,11 +143,10 @@ func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// addConditionsDefault := false
|
// addConditionsDefault := false
|
||||||
conditionsDefaultKey := bazel.PlatformArchMap[bazel.CONDITIONS_DEFAULT]
|
|
||||||
|
|
||||||
var selects string
|
var selects string
|
||||||
for _, selectKey := range android.SortedStringKeys(selectMap) {
|
for _, selectKey := range android.SortedStringKeys(selectMap) {
|
||||||
if selectKey == conditionsDefaultKey {
|
if selectKey == bazel.ConditionsDefaultSelectKey {
|
||||||
// Handle default condition later.
|
// Handle default condition later.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -159,14 +176,14 @@ func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue strin
|
|||||||
ret += selects
|
ret += selects
|
||||||
|
|
||||||
// Handle the default condition
|
// Handle the default condition
|
||||||
s, err := prettyPrintSelectEntry(selectMap[conditionsDefaultKey], conditionsDefaultKey, indent)
|
s, err := prettyPrintSelectEntry(selectMap[bazel.ConditionsDefaultSelectKey], bazel.ConditionsDefaultSelectKey, indent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if s == "" {
|
if s == "" {
|
||||||
// Print an explicit empty list (the default value) even if the value is
|
// Print an explicit empty list (the default value) even if the value is
|
||||||
// empty, to avoid errors about not finding a configuration that matches.
|
// empty, to avoid errors about not finding a configuration that matches.
|
||||||
ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue)
|
ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), bazel.ConditionsDefaultSelectKey, defaultValue)
|
||||||
} else {
|
} else {
|
||||||
// Print the custom default value.
|
// Print the custom default value.
|
||||||
ret += s
|
ret += s
|
||||||
|
@@ -318,6 +318,21 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
productVariableProps := android.ProductVariableProperties(ctx)
|
||||||
|
if props, exists := productVariableProps["Cflags"]; exists {
|
||||||
|
for _, prop := range props {
|
||||||
|
flags, ok := prop.Property.([]string)
|
||||||
|
if !ok {
|
||||||
|
ctx.ModuleErrorf("Could not convert product variable cflag property")
|
||||||
|
}
|
||||||
|
newFlags, _ := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable)
|
||||||
|
copts.ProductValues = append(copts.ProductValues, bazel.ProductVariableValues{
|
||||||
|
ProductVariable: prop.ProductConfigVariable,
|
||||||
|
Values: newFlags,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return compilerAttributes{
|
return compilerAttributes{
|
||||||
srcs: srcs,
|
srcs: srcs,
|
||||||
copts: copts,
|
copts: copts,
|
||||||
|
13
cc/object.go
13
cc/object.go
@@ -116,7 +116,7 @@ type bazelObjectAttributes struct {
|
|||||||
Hdrs bazel.LabelListAttribute
|
Hdrs bazel.LabelListAttribute
|
||||||
Deps bazel.LabelListAttribute
|
Deps bazel.LabelListAttribute
|
||||||
Copts bazel.StringListAttribute
|
Copts bazel.StringListAttribute
|
||||||
Asflags []string
|
Asflags bazel.StringListAttribute
|
||||||
}
|
}
|
||||||
|
|
||||||
type bazelObject struct {
|
type bazelObject struct {
|
||||||
@@ -157,7 +157,7 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) {
|
|||||||
|
|
||||||
// Set arch-specific configurable attributes
|
// Set arch-specific configurable attributes
|
||||||
compilerAttrs := bp2BuildParseCompilerProps(ctx, m)
|
compilerAttrs := bp2BuildParseCompilerProps(ctx, m)
|
||||||
var asFlags []string
|
var asFlags bazel.StringListAttribute
|
||||||
|
|
||||||
var deps bazel.LabelListAttribute
|
var deps bazel.LabelListAttribute
|
||||||
for _, props := range m.linker.linkerProps() {
|
for _, props := range m.linker.linkerProps() {
|
||||||
@@ -176,10 +176,11 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) {
|
|||||||
ctx.ModuleErrorf("Could not convert product variable asflag property")
|
ctx.ModuleErrorf("Could not convert product variable asflag property")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO(b/183595873) handle other product variable usages -- as selects?
|
newFlags, _ := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable)
|
||||||
if newFlags, subbed := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable); subbed {
|
asFlags.ProductValues = append(asFlags.ProductValues, bazel.ProductVariableValues{
|
||||||
asFlags = append(asFlags, newFlags...)
|
ProductVariable: prop.ProductConfigVariable,
|
||||||
}
|
Values: newFlags,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(b/183595872) warn/error if we're not handling product variables
|
// TODO(b/183595872) warn/error if we're not handling product variables
|
||||||
|
Reference in New Issue
Block a user