Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 948e851b authored by Christopher Parsons's avatar Christopher Parsons Committed by Gerrit Code Review
Browse files

Merge "Handle the 'enabled' property in bp2build"

parents d461407c 58852a05
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -367,13 +367,21 @@ var (
		"libandroid_runtime_lazy", // depends on unconverted modules: libbinder_headers
		"libcmd",                  // depends on unconverted modules: libbinder

		"libdexfile_support_static",                                                       // Depends on unconverted module: libdexfile_external_headers
		"libunwindstack_local", "libunwindstack_utils", "libc_malloc_debug", "libfdtrack", // Depends on unconverted module: libunwindstack

		"libdexfile_support",          // TODO(b/210546943): Enabled based on product variables.
		"libdexfile_external_headers", // TODO(b/210546943): Enabled based on product variables.

		"libunwindstack",                // Depends on unconverted module libdexfile_support.
		"libnativehelper_compat_libc++", // Broken compile: implicit declaration of function 'strerror_r' is invalid in C99

		"chkcon", "sefcontext_compile", // depends on unconverted modules: libsepol

		"libsepol", // TODO(b/207408632): Unsupported case of .l sources in cc library rules

		"gen-kotlin-build-file.py", // module has same name as source

		"libbinder",               // TODO(b/188503688): Disabled for some archs,
		"libactivitymanager_aidl", // TODO(b/207426160): Depends on activity_manager_procstate_aidl, which is an aidl filegroup.

		"libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libgmock_ndk
@@ -434,7 +442,6 @@ var (
		"linkerconfig", // http://b/202876379 has arch-variant static_executable
		"mdnsd",        // http://b/202876379 has arch-variant static_executable

		"acvp_modulewrapper", // disabled for android x86/x86_64
		"CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib

		"libdexfile",  // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
@@ -443,9 +450,7 @@ var (

	// Per-module denylist of cc_library modules to only generate the static
	// variant if their shared variant isn't ready or buildable by Bazel.
	bp2buildCcLibraryStaticOnlyList = []string{
		"libjemalloc5", // http://b/188503688, cc_library, `target: { android: { enabled: false } }` for android targets.
	}
	bp2buildCcLibraryStaticOnlyList = []string{}

	// Per-module denylist to opt modules out of mixed builds. Such modules will
	// still be generated via bp2build.
@@ -513,6 +518,9 @@ func (b *BazelModuleBase) MixedBuildsEnabled(ctx ModuleContext) bool {
		// Windows toolchains are not currently supported.
		return false
	}
	if !ctx.Module().Enabled() {
		return false
	}
	if !ctx.Config().BazelContext.BazelEnabled() {
		return false
	}
+46 −6
Original line number Diff line number Diff line
@@ -869,6 +869,13 @@ type CommonAttributes struct {
	Data bazel.LabelListAttribute
}

// constraintAttributes represents Bazel attributes pertaining to build constraints,
// which make restrict building a Bazel target for some set of platforms.
type constraintAttributes struct {
	// Constraint values this target can be built for.
	Target_compatible_with bazel.LabelListAttribute
}

type distProperties struct {
	// configuration to distribute output files from this module to the distribution
	// directory (default: $OUT/dist, configurable with $DIST_DIR)
@@ -1089,7 +1096,8 @@ func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupport
	m.base().commonProperties.CreateCommonOSVariant = true
}

func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutatorContext) {
func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutatorContext,
	enabledPropertyOverrides bazel.BoolAttribute) constraintAttributes {
	// Assert passed-in attributes include Name
	name := attrs.Name
	if len(name) == 0 {
@@ -1107,14 +1115,45 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator

	required := depsToLabelList(props.Required)
	archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})

	var enabledProperty bazel.BoolAttribute
	if props.Enabled != nil {
		enabledProperty.Value = props.Enabled
	}

	for axis, configToProps := range archVariantProps {
		for config, _props := range configToProps {
			if archProps, ok := _props.(*commonProperties); ok {
				required.SetSelectValue(axis, config, depsToLabelList(archProps.Required).Value)
				if archProps.Enabled != nil {
					enabledProperty.SetSelectValue(axis, config, archProps.Enabled)
				}
			}
		}
	}

	if enabledPropertyOverrides.Value != nil {
		enabledProperty.Value = enabledPropertyOverrides.Value
	}
	for _, axis := range enabledPropertyOverrides.SortedConfigurationAxes() {
		configToBools := enabledPropertyOverrides.ConfigurableValues[axis]
		for cfg, val := range configToBools {
			enabledProperty.SetSelectValue(axis, cfg, &val)
		}
	}

	data.Append(required)

	var err error
	constraints := constraintAttributes{}
	constraints.Target_compatible_with, err = enabledProperty.ToLabelListAttribute(
		bazel.LabelList{[]bazel.Label{bazel.Label{Label: "@platforms//:incompatible"}}, nil},
		bazel.LabelList{[]bazel.Label{}, nil})

	if err != nil {
		ctx.ModuleErrorf("Error processing enabled attribute: %s", err)
	}
	return constraints
}

// A ModuleBase object contains the properties that are common to all Android
@@ -1236,6 +1275,7 @@ type bp2buildInfo struct {
	Dir             string
	BazelProps      bazel.BazelTargetModuleProperties
	CommonAttrs     CommonAttributes
	ConstraintAttrs constraintAttributes
	Attrs           interface{}
}

@@ -1262,7 +1302,7 @@ func (b bp2buildInfo) BazelRuleLoadLocation() string {

// BazelAttributes returns the Bazel attributes of a bp2build converted target.
func (b bp2buildInfo) BazelAttributes() []interface{} {
	return []interface{}{&b.CommonAttrs, b.Attrs}
	return []interface{}{&b.CommonAttrs, &b.ConstraintAttrs, b.Attrs}
}

func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
+30 −5
Original line number Diff line number Diff line
@@ -254,6 +254,14 @@ type TopDownMutatorContext interface {
	// BazelTargetModuleProperties containing additional metadata for the
	// bp2build codegenerator.
	CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})

	// CreateBazelTargetModuleWithRestrictions creates a BazelTargetModule by calling the
	// factory method, just like in CreateModule, but also requires
	// BazelTargetModuleProperties containing additional metadata for the
	// bp2build codegenerator. The generated target is restricted to only be buildable for certain
	// platforms, as dictated by a given bool attribute: the target will not be buildable in
	// any platform for which this bool attribute is false.
	CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
}

type topDownMutatorContext struct {
@@ -502,12 +510,29 @@ func (t *topDownMutatorContext) CreateBazelTargetModule(
	bazelProps bazel.BazelTargetModuleProperties,
	commonAttrs CommonAttributes,
	attrs interface{}) {
	commonAttrs.fillCommonBp2BuildModuleAttrs(t)
	t.createBazelTargetModule(bazelProps, commonAttrs, attrs, bazel.BoolAttribute{})
}

func (t *topDownMutatorContext) CreateBazelTargetModuleWithRestrictions(
	bazelProps bazel.BazelTargetModuleProperties,
	commonAttrs CommonAttributes,
	attrs interface{},
	enabledProperty bazel.BoolAttribute) {
	t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
}

func (t *topDownMutatorContext) createBazelTargetModule(
	bazelProps bazel.BazelTargetModuleProperties,
	commonAttrs CommonAttributes,
	attrs interface{},
	enabledProperty bazel.BoolAttribute) {
	constraintAttributes := commonAttrs.fillCommonBp2BuildModuleAttrs(t, enabledProperty)
	mod := t.Module()
	info := bp2buildInfo{
		Dir:             t.OtherModuleDir(mod),
		BazelProps:      bazelProps,
		CommonAttrs:     commonAttrs,
		ConstraintAttrs: constraintAttributes,
		Attrs:           attrs,
	}
	mod.base().addBp2buildInfo(info)
+19 −0
Original line number Diff line number Diff line
@@ -109,6 +109,21 @@ var (
		osArchWindowsX86_64:        "//build/bazel/platforms/os_arch:windows_x86_64",
		ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
	}

	// Map where keys are OsType names, and values are slices containing the archs
	// that that OS supports.
	// These definitions copied from arch.go.
	// TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
	// in a cyclic dependency.
	osToArchMap = map[string][]string{
		osAndroid:     {archArm, archArm64, archX86, archX86_64},
		osLinux:       {archX86, archX86_64},
		osLinuxMusl:   {archX86, archX86_64},
		osDarwin:      {archArm64, archX86_64},
		osLinuxBionic: {archArm64, archX86_64},
		// TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
		osWindows: {archX86, archX86_64},
	}
)

// basic configuration types
@@ -122,6 +137,10 @@ const (
	productVariables
)

func osArchString(os string, arch string) string {
	return fmt.Sprintf("%s_%s", os, arch)
}

func (ct configurationType) String() string {
	return map[configurationType]string{
		noConfig:         "no_config",
+182 −7
Original line number Diff line number Diff line
@@ -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
Loading