summaryrefslogtreecommitdiff
path: root/bazel/properties.go
diff options
context:
space:
mode:
Diffstat (limited to 'bazel/properties.go')
-rw-r--r--bazel/properties.go189
1 files changed, 182 insertions, 7 deletions
diff --git a/bazel/properties.go b/bazel/properties.go
index 76be0581b..d8b3a3a02 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -244,9 +244,69 @@ type LabelAttribute struct {
ConfigurableValues configurableLabels
}
+func (la *LabelAttribute) axisTypes() map[configurationType]bool {
+ types := map[configurationType]bool{}
+ for k := range la.ConfigurableValues {
+ if len(la.ConfigurableValues[k]) > 0 {
+ types[k.configurationType] = true
+ }
+ }
+ return types
+}
+
+// Collapse reduces the configurable axes of the label attribute to a single axis.
+// This is necessary for final writing to bp2build, as a configurable label
+// attribute can only be comprised by a single select.
+func (la *LabelAttribute) Collapse() error {
+ axisTypes := la.axisTypes()
+ _, containsOs := axisTypes[os]
+ _, containsArch := axisTypes[arch]
+ _, containsOsArch := axisTypes[osArch]
+ _, 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 (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
+ // If a bool attribute has both os and arch configuration axes, the only
+ // way to successfully union their values is to increase the granularity
+ // of the configuration criteria to os_arch.
+ for osType, supportedArchs := range osToArchMap {
+ for _, supportedArch := range supportedArchs {
+ osArch := osArchString(osType, supportedArch)
+ if archOsVal := la.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
+ // Do nothing, as the arch_os is explicitly defined already.
+ } else {
+ archVal := la.SelectValue(ArchConfigurationAxis, supportedArch)
+ osVal := la.SelectValue(OsConfigurationAxis, osType)
+ if osVal != nil && archVal != nil {
+ // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
+ // runs after os mutator.
+ la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
+ } else if osVal != nil && archVal == nil {
+ la.SetSelectValue(OsArchConfigurationAxis, osArch, *osVal)
+ } else if osVal == nil && archVal != nil {
+ la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
+ }
+ }
+ }
+ }
+ // All os_arch values are now set. Clear os and arch axes.
+ delete(la.ConfigurableValues, ArchConfigurationAxis)
+ delete(la.ConfigurableValues, OsConfigurationAxis)
+ }
+ return nil
+}
+
// HasConfigurableValues returns whether there are configurable values set for this label.
func (la LabelAttribute) HasConfigurableValues() bool {
- return len(la.ConfigurableValues) > 0
+ for _, selectValues := range la.ConfigurableValues {
+ if len(selectValues) > 0 {
+ return true
+ }
+ }
+ return false
}
// SetValue sets the base, non-configured value for the Label
@@ -271,13 +331,13 @@ func (la *LabelAttribute) SetSelectValue(axis ConfigurationAxis, config string,
}
// SelectValue gets a value for a bazel select for the given axis and config.
-func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) Label {
+func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) *Label {
axis.validateConfig(config)
switch axis.configurationType {
case noConfig:
- return *la.Value
+ return la.Value
case arch, os, osArch, productVariables:
- return *la.ConfigurableValues[axis][config]
+ return la.ConfigurableValues[axis][config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
}
@@ -324,7 +384,12 @@ type BoolAttribute struct {
// HasConfigurableValues returns whether there are configurable values for this attribute.
func (ba BoolAttribute) HasConfigurableValues() bool {
- return len(ba.ConfigurableValues) > 0
+ for _, cfgToBools := range ba.ConfigurableValues {
+ if len(cfgToBools) > 0 {
+ return true
+ }
+ }
+ return false
}
// SetSelectValue sets value for the given axis/config.
@@ -343,6 +408,106 @@ func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, v
}
}
+// ToLabelListAttribute creates and returns a LabelListAttribute from this
+// bool attribute, where each bool in this attribute corresponds to a
+// label list value in the resultant attribute.
+func (ba *BoolAttribute) ToLabelListAttribute(falseVal LabelList, trueVal LabelList) (LabelListAttribute, error) {
+ getLabelList := func(boolPtr *bool) LabelList {
+ if boolPtr == nil {
+ return LabelList{nil, nil}
+ } else if *boolPtr {
+ return trueVal
+ } else {
+ return falseVal
+ }
+ }
+
+ mainVal := getLabelList(ba.Value)
+ if !ba.HasConfigurableValues() {
+ return MakeLabelListAttribute(mainVal), nil
+ }
+
+ result := LabelListAttribute{}
+ if err := ba.Collapse(); err != nil {
+ return result, err
+ }
+
+ for axis, configToBools := range ba.ConfigurableValues {
+ if len(configToBools) < 1 {
+ continue
+ }
+ for config, boolPtr := range configToBools {
+ val := getLabelList(&boolPtr)
+ if !val.Equals(mainVal) {
+ result.SetSelectValue(axis, config, val)
+ }
+ }
+ result.SetSelectValue(axis, ConditionsDefaultConfigKey, mainVal)
+ }
+
+ return result, nil
+}
+
+// Collapse reduces the configurable axes of the boolean attribute to a single axis.
+// This is necessary for final writing to bp2build, as a configurable boolean
+// attribute can only be comprised by a single select.
+func (ba *BoolAttribute) Collapse() error {
+ axisTypes := ba.axisTypes()
+ _, containsOs := axisTypes[os]
+ _, containsArch := axisTypes[arch]
+ _, containsOsArch := axisTypes[osArch]
+ _, containsProductVariables := axisTypes[productVariables]
+ if containsProductVariables {
+ if containsOs || containsArch || containsOsArch {
+ return fmt.Errorf("boolean attribute could not be collapsed as it has two or more unrelated axes")
+ }
+ }
+ if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
+ // If a bool attribute has both os and arch configuration axes, the only
+ // way to successfully union their values is to increase the granularity
+ // of the configuration criteria to os_arch.
+ for osType, supportedArchs := range osToArchMap {
+ for _, supportedArch := range supportedArchs {
+ osArch := osArchString(osType, supportedArch)
+ if archOsVal := ba.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
+ // Do nothing, as the arch_os is explicitly defined already.
+ } else {
+ archVal := ba.SelectValue(ArchConfigurationAxis, supportedArch)
+ osVal := ba.SelectValue(OsConfigurationAxis, osType)
+ if osVal != nil && archVal != nil {
+ // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
+ // runs after os mutator.
+ ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
+ } else if osVal != nil && archVal == nil {
+ ba.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
+ } else if osVal == nil && archVal != nil {
+ ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
+ }
+ }
+ }
+ }
+ // All os_arch values are now set. Clear os and arch axes.
+ delete(ba.ConfigurableValues, ArchConfigurationAxis)
+ delete(ba.ConfigurableValues, OsConfigurationAxis)
+ // Verify post-condition; this should never fail, provided no additional
+ // axes are introduced.
+ if len(ba.ConfigurableValues) > 1 {
+ panic(fmt.Errorf("error in collapsing attribute: %s", ba))
+ }
+ }
+ return nil
+}
+
+func (ba *BoolAttribute) axisTypes() map[configurationType]bool {
+ types := map[configurationType]bool{}
+ for k := range ba.ConfigurableValues {
+ if len(ba.ConfigurableValues[k]) > 0 {
+ types[k.configurationType] = true
+ }
+ }
+ return types
+}
+
// SelectValue gets the value for the given axis/config.
func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool {
axis.validateConfig(config)
@@ -550,7 +715,12 @@ func (lla *LabelListAttribute) Add(label *LabelAttribute) {
// HasConfigurableValues returns true if the attribute contains axis-specific label list values.
func (lla LabelListAttribute) HasConfigurableValues() bool {
- return len(lla.ConfigurableValues) > 0
+ for _, selectValues := range lla.ConfigurableValues {
+ if len(selectValues) > 0 {
+ return true
+ }
+ }
+ return false
}
// IsEmpty returns true if the attribute has no values under any configuration.
@@ -800,7 +970,12 @@ func MakeStringListAttribute(value []string) StringListAttribute {
// HasConfigurableValues returns true if the attribute contains axis-specific string_list values.
func (sla StringListAttribute) HasConfigurableValues() bool {
- return len(sla.ConfigurableValues) > 0
+ for _, selectValues := range sla.ConfigurableValues {
+ if len(selectValues) > 0 {
+ return true
+ }
+ }
+ return false
}
// Append appends all values, including os and arch specific ones, from another