diff options
Diffstat (limited to 'bazel/properties.go')
| -rw-r--r-- | bazel/properties.go | 189 |
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 |