Merge "Add target/os configurable string_list attrs."
diff --git a/bazel/properties.go b/bazel/properties.go
index 250fea4..2440ca1 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -96,21 +96,10 @@
)
var (
- // This is the list of architectures with a Bazel config_setting and
- // constraint value equivalent. is actually android.ArchTypeList, but the
- // android package depends on the bazel package, so a cyclic dependency
- // prevents using that here.
- selectableArchs = []string{ARCH_X86, ARCH_X86_64, ARCH_ARM, ARCH_ARM64}
-
- // Likewise, this is the list of target operating systems.
- selectableTargetOs = []string{
- OS_ANDROID,
- OS_DARWIN,
- OS_FUCHSIA,
- OS_LINUX,
- OS_LINUX_BIONIC,
- OS_WINDOWS,
- }
+ // These are the list of OSes and architectures with a Bazel config_setting
+ // and constraint value equivalent. These exist in arch.go, but the android
+ // package depends on the bazel package, so a cyclic dependency prevents
+ // using those variables here.
// A map of architectures to the Bazel label of the constraint_value
// for the @platforms//cpu:cpu constraint_setting
@@ -133,6 +122,10 @@
}
)
+type Attribute interface {
+ HasConfigurableValues() bool
+}
+
// Arch-specific label_list typed Bazel attribute values. This should correspond
// to the types of architectures supported for compilation in arch.go.
type labelListArchValues struct {
@@ -176,14 +169,14 @@
// HasArchSpecificValues returns true if the attribute contains
// architecture-specific label_list values.
-func (attrs *LabelListAttribute) HasConfigurableValues() bool {
- for _, arch := range selectableArchs {
+func (attrs LabelListAttribute) HasConfigurableValues() bool {
+ for arch := range PlatformArchMap {
if len(attrs.GetValueForArch(arch).Includes) > 0 {
return true
}
}
- for _, os := range selectableTargetOs {
+ for os := range PlatformOsMap {
if len(attrs.GetValueForOS(os).Includes) > 0 {
return true
}
@@ -253,8 +246,15 @@
// The base value of the string list attribute.
Value []string
- // Optional additive set of list values to the base value.
+ // The arch-specific attribute string list values. Optional. If used, these
+ // are generated in a select statement and appended to the non-arch specific
+ // label list Value.
ArchValues stringListArchValues
+
+ // The os-specific attribute string list values. Optional. If used, these
+ // are generated in a select statement and appended to the non-os specific
+ // label list Value.
+ OsValues stringListOsValues
}
// Arch-specific string_list typed Bazel attribute values. This should correspond
@@ -267,14 +267,29 @@
Common []string
}
+type stringListOsValues struct {
+ Android []string
+ Darwin []string
+ Fuchsia []string
+ Linux []string
+ LinuxBionic []string
+ Windows []string
+}
+
// HasConfigurableValues returns true if the attribute contains
// architecture-specific string_list values.
-func (attrs *StringListAttribute) HasConfigurableValues() bool {
- for _, arch := range selectableArchs {
+func (attrs StringListAttribute) HasConfigurableValues() bool {
+ for arch := range PlatformArchMap {
if len(attrs.GetValueForArch(arch)) > 0 {
return true
}
}
+
+ for os := range PlatformOsMap {
+ if len(attrs.GetValueForOS(os)) > 0 {
+ return true
+ }
+ }
return false
}
@@ -305,6 +320,35 @@
*v = value
}
+func (attrs *StringListAttribute) osValuePtrs() map[string]*[]string {
+ return map[string]*[]string{
+ OS_ANDROID: &attrs.OsValues.Android,
+ OS_DARWIN: &attrs.OsValues.Darwin,
+ OS_FUCHSIA: &attrs.OsValues.Fuchsia,
+ OS_LINUX: &attrs.OsValues.Linux,
+ OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
+ OS_WINDOWS: &attrs.OsValues.Windows,
+ }
+}
+
+// GetValueForOS returns the string_list attribute value for an OS target.
+func (attrs *StringListAttribute) GetValueForOS(os string) []string {
+ var v *[]string
+ if v = attrs.osValuePtrs()[os]; v == nil {
+ panic(fmt.Errorf("Unknown os: %s", os))
+ }
+ return *v
+}
+
+// SetValueForArch sets the string_list attribute value for an OS target.
+func (attrs *StringListAttribute) SetValueForOS(os string, value []string) {
+ var v *[]string
+ if v = attrs.osValuePtrs()[os]; v == nil {
+ panic(fmt.Errorf("Unknown os: %s", os))
+ }
+ *v = value
+}
+
// TryVariableSubstitution, replace string substitution formatting within each string in slice with
// Starlark string.format compatible tag for productVariable.
func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 1d254c8..dd14c7d 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -415,12 +415,10 @@
case reflect.Struct:
// Special cases where the bp2build sends additional information to the codegenerator
// by wrapping the attributes in a custom struct type.
- if labels, ok := propertyValue.Interface().(bazel.LabelListAttribute); ok {
- return prettyPrintLabelListAttribute(labels, indent)
+ if attr, ok := propertyValue.Interface().(bazel.Attribute); ok {
+ return prettyPrintAttribute(attr, indent)
} else if label, ok := propertyValue.Interface().(bazel.Label); ok {
return fmt.Sprintf("%q", label.Label), nil
- } else if stringList, ok := propertyValue.Interface().(bazel.StringListAttribute); ok {
- return prettyPrintStringListAttribute(stringList, indent)
}
ret = "{\n"
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index fcc3080..4f3babe 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -415,6 +415,54 @@
)`,
},
},
+ {
+ description: "cc_object setting cflags for multiple OSes",
+ moduleTypeUnderTest: "cc_object",
+ moduleTypeUnderTestFactory: cc.ObjectFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ blueprint: `cc_object {
+ name: "foo",
+ srcs: ["base.cpp"],
+ target: {
+ android: {
+ cflags: ["-fPIC"],
+ },
+ windows: {
+ cflags: ["-fPIC"],
+ },
+ darwin: {
+ cflags: ["-Wall"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ `cc_object(
+ name = "foo",
+ copts = [
+ "-fno-addrsig",
+ ] + select({
+ "//build/bazel/platforms/os:android": [
+ "-fPIC",
+ ],
+ "//build/bazel/platforms/os:darwin": [
+ "-Wall",
+ ],
+ "//build/bazel/platforms/os:windows": [
+ "-fPIC",
+ ],
+ "//conditions:default": [],
+ }),
+ local_include_dirs = [
+ ".",
+ ],
+ srcs = [
+ "base.cpp",
+ ],
+)`,
+ },
+ },
}
dir := "."
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index 6ca0d6d..b2b3379 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -9,48 +9,67 @@
// Configurability support for bp2build.
-// prettyPrintStringListAttribute converts a StringListAttribute to its Bazel
-// syntax. May contain a select statement.
-func prettyPrintStringListAttribute(stringList bazel.StringListAttribute, indent int) (string, error) {
- ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent)
- if err != nil {
- return ret, err
+type selects map[string]reflect.Value
+
+func getStringListValues(list bazel.StringListAttribute) (reflect.Value, selects, selects) {
+ value := reflect.ValueOf(list.Value)
+ if !list.HasConfigurableValues() {
+ return value, nil, nil
}
- if !stringList.HasConfigurableValues() {
- // Select statement not needed.
- return ret, nil
- }
-
- // Create the selects for arch specific values.
- selects := map[string]reflect.Value{}
- for arch, selectKey := range bazel.PlatformArchMap {
- selects[selectKey] = reflect.ValueOf(stringList.GetValueForArch(arch))
- }
-
- selectMap, err := prettyPrintSelectMap(selects, "[]", indent)
- return ret + selectMap, err
-}
-
-// prettyPrintLabelListAttribute converts a LabelListAttribute to its Bazel
-// syntax. May contain select statements.
-func prettyPrintLabelListAttribute(labels bazel.LabelListAttribute, indent int) (string, error) {
- // TODO(b/165114590): convert glob syntax
- ret, err := prettyPrint(reflect.ValueOf(labels.Value.Includes), indent)
- if err != nil {
- return ret, err
- }
-
- if !labels.HasConfigurableValues() {
- // Select statements not needed.
- return ret, nil
- }
-
- // Create the selects for arch specific values.
archSelects := map[string]reflect.Value{}
for arch, selectKey := range bazel.PlatformArchMap {
- archSelects[selectKey] = reflect.ValueOf(labels.GetValueForArch(arch).Includes)
+ archSelects[selectKey] = reflect.ValueOf(list.GetValueForArch(arch))
}
+
+ osSelects := map[string]reflect.Value{}
+ for os, selectKey := range bazel.PlatformOsMap {
+ osSelects[selectKey] = reflect.ValueOf(list.GetValueForOS(os))
+ }
+
+ return value, archSelects, osSelects
+}
+
+func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, selects, selects) {
+ value := reflect.ValueOf(list.Value.Includes)
+ if !list.HasConfigurableValues() {
+ return value, nil, nil
+ }
+
+ archSelects := map[string]reflect.Value{}
+ for arch, selectKey := range bazel.PlatformArchMap {
+ archSelects[selectKey] = reflect.ValueOf(list.GetValueForArch(arch).Includes)
+ }
+
+ osSelects := map[string]reflect.Value{}
+ for os, selectKey := range bazel.PlatformOsMap {
+ osSelects[selectKey] = reflect.ValueOf(list.GetValueForOS(os).Includes)
+ }
+
+ return value, archSelects, osSelects
+}
+
+// prettyPrintAttribute converts an Attribute to its Bazel syntax. May contain
+// select statements.
+func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
+ var value reflect.Value
+ var archSelects, osSelects selects
+
+ switch list := v.(type) {
+ case bazel.StringListAttribute:
+ value, archSelects, osSelects = getStringListValues(list)
+ case bazel.LabelListAttribute:
+ value, archSelects, osSelects = getLabelListValues(list)
+ default:
+ return "", fmt.Errorf("Not a supported Bazel attribute type: %s", v)
+ }
+
+ ret, err := prettyPrint(value, indent)
+ if err != nil {
+ return ret, err
+ }
+
+ // Create the selects for arch specific values.
selectMap, err := prettyPrintSelectMap(archSelects, "[]", indent)
if err != nil {
return "", err
@@ -58,17 +77,22 @@
ret += selectMap
// Create the selects for target os specific values.
- osSelects := map[string]reflect.Value{}
- for os, selectKey := range bazel.PlatformOsMap {
- osSelects[selectKey] = reflect.ValueOf(labels.GetValueForOS(os).Includes)
- }
selectMap, err = prettyPrintSelectMap(osSelects, "[]", indent)
- return ret + selectMap, err
+ if err != nil {
+ return "", err
+ }
+ ret += selectMap
+
+ return ret, err
}
// prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
// to construct a select map for any kind of attribute type.
func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue string, indent int) (string, error) {
+ if selectMap == nil {
+ return "", nil
+ }
+
var selects string
for _, selectKey := range android.SortedStringKeys(selectMap) {
value := selectMap[selectKey]
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 2a590eb..497d227 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -58,6 +58,31 @@
ctx.AddDependency(module, nil, android.SortedUniqueStrings(allDeps)...)
}
+// bp2buildParseCflags creates a label list attribute containing the cflags of a module, including
+func bp2BuildParseCflags(ctx android.TopDownMutatorContext, module *Module) bazel.StringListAttribute {
+ var ret bazel.StringListAttribute
+ for _, props := range module.compiler.compilerProps() {
+ if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+ ret.Value = baseCompilerProps.Cflags
+ break
+ }
+ }
+
+ for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) {
+ if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+ ret.SetValueForArch(arch.Name, baseCompilerProps.Cflags)
+ }
+ }
+
+ for os, props := range module.GetTargetProperties(&BaseCompilerProperties{}) {
+ if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+ ret.SetValueForOS(os.Name, baseCompilerProps.Cflags)
+ }
+ }
+
+ return ret
+}
+
// bp2BuildParseHeaderLibs creates a label list attribute containing the header library deps of a module, including
// configurable attribute values.
func bp2BuildParseHeaderLibs(ctx android.TopDownMutatorContext, module *Module) bazel.LabelListAttribute {
diff --git a/cc/library_headers.go b/cc/library_headers.go
index c8dd2c2..82af16a 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -62,6 +62,7 @@
}
type bazelCcLibraryHeadersAttributes struct {
+ Copts bazel.StringListAttribute
Hdrs bazel.LabelListAttribute
Includes bazel.LabelListAttribute
Deps bazel.LabelListAttribute
@@ -99,6 +100,7 @@
headerLibsLabels := bp2BuildParseHeaderLibs(ctx, module)
attrs := &bazelCcLibraryHeadersAttributes{
+ Copts: bp2BuildParseCflags(ctx, module),
Includes: exportedIncludesLabels,
Hdrs: exportedIncludesHeadersLabels,
Deps: headerLibsLabels,
diff --git a/cc/object.go b/cc/object.go
index ea8d7d3..4f8797d 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -156,13 +156,11 @@
}
// Set arch-specific configurable attributes
- var copts bazel.StringListAttribute
var srcs bazel.LabelListAttribute
var localIncludeDirs []string
var asFlags []string
for _, props := range m.compiler.compilerProps() {
if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
- copts.Value = baseCompilerProps.Cflags
srcs = bazel.MakeLabelListAttribute(
android.BazelLabelForModuleSrcExcludes(
ctx,
@@ -205,14 +203,13 @@
for arch, p := range m.GetArchProperties(&BaseCompilerProperties{}) {
if cProps, ok := p.(*BaseCompilerProperties); ok {
srcs.SetValueForArch(arch.Name, android.BazelLabelForModuleSrcExcludes(ctx, cProps.Srcs, cProps.Exclude_srcs))
- copts.SetValueForArch(arch.Name, cProps.Cflags)
}
}
attrs := &bazelObjectAttributes{
Srcs: srcs,
Deps: deps,
- Copts: copts,
+ Copts: bp2BuildParseCflags(ctx, m),
Asflags: asFlags,
Local_include_dirs: localIncludeDirs,
}