Handle the 'enabled' property in bp2build

Also fix some bugs pertaining to configurable attribute handling of bool
attributes and label sttributes, so that they may support values across
multiple different axes at the same time.

Test: unit tests for bp2build
Test: mixed_droid

Change-Id: I411efcfddf02d55dbc0775962068a11348a8bb2c
This commit is contained in:
Chris Parsons
2021-12-09 18:10:18 -05:00
parent 68542bfcb5
commit 58852a05f3
14 changed files with 612 additions and 49 deletions

View File

@@ -367,13 +367,21 @@ var (
"libandroid_runtime_lazy", // depends on unconverted modules: libbinder_headers "libandroid_runtime_lazy", // depends on unconverted modules: libbinder_headers
"libcmd", // depends on unconverted modules: libbinder "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 "chkcon", "sefcontext_compile", // depends on unconverted modules: libsepol
"libsepol", // TODO(b/207408632): Unsupported case of .l sources in cc library rules "libsepol", // TODO(b/207408632): Unsupported case of .l sources in cc library rules
"gen-kotlin-build-file.py", // module has same name as source "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. "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 "libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libgmock_ndk
@@ -434,8 +442,7 @@ var (
"linkerconfig", // http://b/202876379 has arch-variant static_executable "linkerconfig", // http://b/202876379 has arch-variant static_executable
"mdnsd", // 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
"CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
"libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette, "libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette "libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
@@ -443,9 +450,7 @@ var (
// Per-module denylist of cc_library modules to only generate the static // Per-module denylist of cc_library modules to only generate the static
// variant if their shared variant isn't ready or buildable by Bazel. // variant if their shared variant isn't ready or buildable by Bazel.
bp2buildCcLibraryStaticOnlyList = []string{ bp2buildCcLibraryStaticOnlyList = []string{}
"libjemalloc5", // http://b/188503688, cc_library, `target: { android: { enabled: false } }` for android targets.
}
// Per-module denylist to opt modules out of mixed builds. Such modules will // Per-module denylist to opt modules out of mixed builds. Such modules will
// still be generated via bp2build. // still be generated via bp2build.
@@ -513,6 +518,9 @@ func (b *BazelModuleBase) MixedBuildsEnabled(ctx ModuleContext) bool {
// Windows toolchains are not currently supported. // Windows toolchains are not currently supported.
return false return false
} }
if !ctx.Module().Enabled() {
return false
}
if !ctx.Config().BazelContext.BazelEnabled() { if !ctx.Config().BazelContext.BazelEnabled() {
return false return false
} }

View File

@@ -869,6 +869,13 @@ type CommonAttributes struct {
Data bazel.LabelListAttribute 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 { type distProperties struct {
// configuration to distribute output files from this module to the distribution // configuration to distribute output files from this module to the distribution
// directory (default: $OUT/dist, configurable with $DIST_DIR) // directory (default: $OUT/dist, configurable with $DIST_DIR)
@@ -1089,7 +1096,8 @@ func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupport
m.base().commonProperties.CreateCommonOSVariant = true 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 // Assert passed-in attributes include Name
name := attrs.Name name := attrs.Name
if len(name) == 0 { if len(name) == 0 {
@@ -1107,14 +1115,45 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator
required := depsToLabelList(props.Required) required := depsToLabelList(props.Required)
archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{}) archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})
var enabledProperty bazel.BoolAttribute
if props.Enabled != nil {
enabledProperty.Value = props.Enabled
}
for axis, configToProps := range archVariantProps { for axis, configToProps := range archVariantProps {
for config, _props := range configToProps { for config, _props := range configToProps {
if archProps, ok := _props.(*commonProperties); ok { if archProps, ok := _props.(*commonProperties); ok {
required.SetSelectValue(axis, config, depsToLabelList(archProps.Required).Value) 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) 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 // A ModuleBase object contains the properties that are common to all Android
@@ -1233,10 +1272,11 @@ type ModuleBase struct {
// A struct containing all relevant information about a Bazel target converted via bp2build. // A struct containing all relevant information about a Bazel target converted via bp2build.
type bp2buildInfo struct { type bp2buildInfo struct {
Dir string Dir string
BazelProps bazel.BazelTargetModuleProperties BazelProps bazel.BazelTargetModuleProperties
CommonAttrs CommonAttributes CommonAttrs CommonAttributes
Attrs interface{} ConstraintAttrs constraintAttributes
Attrs interface{}
} }
// TargetName returns the Bazel target name of a bp2build converted target. // TargetName returns the Bazel target name of a bp2build converted target.
@@ -1262,7 +1302,7 @@ func (b bp2buildInfo) BazelRuleLoadLocation() string {
// BazelAttributes returns the Bazel attributes of a bp2build converted target. // BazelAttributes returns the Bazel attributes of a bp2build converted target.
func (b bp2buildInfo) BazelAttributes() []interface{} { 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) { func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {

View File

@@ -254,6 +254,14 @@ type TopDownMutatorContext interface {
// BazelTargetModuleProperties containing additional metadata for the // BazelTargetModuleProperties containing additional metadata for the
// bp2build codegenerator. // bp2build codegenerator.
CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}) 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 { type topDownMutatorContext struct {
@@ -502,13 +510,30 @@ func (t *topDownMutatorContext) CreateBazelTargetModule(
bazelProps bazel.BazelTargetModuleProperties, bazelProps bazel.BazelTargetModuleProperties,
commonAttrs CommonAttributes, commonAttrs CommonAttributes,
attrs interface{}) { 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() mod := t.Module()
info := bp2buildInfo{ info := bp2buildInfo{
Dir: t.OtherModuleDir(mod), Dir: t.OtherModuleDir(mod),
BazelProps: bazelProps, BazelProps: bazelProps,
CommonAttrs: commonAttrs, CommonAttrs: commonAttrs,
Attrs: attrs, ConstraintAttrs: constraintAttributes,
Attrs: attrs,
} }
mod.base().addBp2buildInfo(info) mod.base().addBp2buildInfo(info)
} }

View File

@@ -109,6 +109,21 @@ var (
osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64", osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map. 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 // basic configuration types
@@ -122,6 +137,10 @@ const (
productVariables productVariables
) )
func osArchString(os string, arch string) string {
return fmt.Sprintf("%s_%s", os, arch)
}
func (ct configurationType) String() string { func (ct configurationType) String() string {
return map[configurationType]string{ return map[configurationType]string{
noConfig: "no_config", noConfig: "no_config",

View File

@@ -244,9 +244,69 @@ type LabelAttribute struct {
ConfigurableValues configurableLabels 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. // HasConfigurableValues returns whether there are configurable values set for this label.
func (la LabelAttribute) HasConfigurableValues() bool { 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 // 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. // 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) axis.validateConfig(config)
switch axis.configurationType { switch axis.configurationType {
case noConfig: case noConfig:
return *la.Value return la.Value
case arch, os, osArch, productVariables: case arch, os, osArch, productVariables:
return *la.ConfigurableValues[axis][config] return la.ConfigurableValues[axis][config]
default: default:
panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
} }
@@ -324,7 +384,12 @@ type BoolAttribute struct {
// HasConfigurableValues returns whether there are configurable values for this attribute. // HasConfigurableValues returns whether there are configurable values for this attribute.
func (ba BoolAttribute) HasConfigurableValues() bool { 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. // 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. // SelectValue gets the value for the given axis/config.
func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool { func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool {
axis.validateConfig(config) 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. // HasConfigurableValues returns true if the attribute contains axis-specific label list values.
func (lla LabelListAttribute) HasConfigurableValues() bool { 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. // 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. // HasConfigurableValues returns true if the attribute contains axis-specific string_list values.
func (sla StringListAttribute) HasConfigurableValues() bool { 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 // Append appends all values, including os and arch specific ones, from another

View File

@@ -1369,6 +1369,94 @@ cc_library {
}) })
} }
func TestCCLibraryNoLibCrtArchAndTargetVariant(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "foo-lib",
srcs: ["impl.cpp"],
arch: {
arm: {
no_libcrt: true,
},
x86: {
no_libcrt: true,
},
},
target: {
darwin: {
no_libcrt: true,
}
},
include_build_directory: false,
}
`,
expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
"srcs": `["impl.cpp"]`,
"use_libcrt": `select({
"//build/bazel/platforms/os_arch:android_arm": False,
"//build/bazel/platforms/os_arch:android_x86": False,
"//build/bazel/platforms/os_arch:darwin_arm64": False,
"//build/bazel/platforms/os_arch:darwin_x86_64": False,
"//build/bazel/platforms/os_arch:linux_glibc_x86": False,
"//build/bazel/platforms/os_arch:linux_musl_x86": False,
"//build/bazel/platforms/os_arch:windows_x86": False,
"//conditions:default": None,
})`,
}),
})
}
func TestCCLibraryNoLibCrtArchAndTargetVariantConflict(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "foo-lib",
srcs: ["impl.cpp"],
arch: {
arm: {
no_libcrt: true,
},
// This is expected to override the value for darwin_x86_64.
x86_64: {
no_libcrt: true,
},
},
target: {
darwin: {
no_libcrt: false,
}
},
include_build_directory: false,
}
`,
expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
"srcs": `["impl.cpp"]`,
"use_libcrt": `select({
"//build/bazel/platforms/os_arch:android_arm": False,
"//build/bazel/platforms/os_arch:android_x86_64": False,
"//build/bazel/platforms/os_arch:darwin_arm64": True,
"//build/bazel/platforms/os_arch:darwin_x86_64": False,
"//build/bazel/platforms/os_arch:linux_bionic_x86_64": False,
"//build/bazel/platforms/os_arch:linux_glibc_x86_64": False,
"//build/bazel/platforms/os_arch:linux_musl_x86_64": False,
"//build/bazel/platforms/os_arch:windows_x86_64": False,
"//conditions:default": None,
})`,
}),
})
}
func TestCcLibraryStrip(t *testing.T) { func TestCcLibraryStrip(t *testing.T) {
expectedTargets := []string{} expectedTargets := []string{}
expectedTargets = append(expectedTargets, makeCcLibraryTargets("all", attrNameToString{ expectedTargets = append(expectedTargets, makeCcLibraryTargets("all", attrNameToString{
@@ -2159,3 +2247,146 @@ cc_library {
}, },
}) })
} }
func TestCcLibraryDisabledArchAndTarget(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.cpp"],
target: {
darwin: {
enabled: false,
},
windows: {
enabled: false,
},
linux_glibc_x86: {
enabled: false,
},
},
include_build_directory: false,
}`,
expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
"srcs": `["foo.cpp"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os_arch:darwin_arm64": ["@platforms//:incompatible"],
"//build/bazel/platforms/os_arch:darwin_x86_64": ["@platforms//:incompatible"],
"//build/bazel/platforms/os_arch:linux_glibc_x86": ["@platforms//:incompatible"],
"//build/bazel/platforms/os_arch:windows_x86": ["@platforms//:incompatible"],
"//build/bazel/platforms/os_arch:windows_x86_64": ["@platforms//:incompatible"],
"//conditions:default": [],
})`,
}),
})
}
func TestCcLibraryDisabledArchAndTargetWithDefault(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.cpp"],
enabled: false,
target: {
darwin: {
enabled: true,
},
windows: {
enabled: false,
},
linux_glibc_x86: {
enabled: false,
},
},
include_build_directory: false,
}`,
expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
"srcs": `["foo.cpp"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os_arch:darwin_arm64": [],
"//build/bazel/platforms/os_arch:darwin_x86_64": [],
"//conditions:default": ["@platforms//:incompatible"],
})`,
}),
})
}
func TestCcLibrarySharedDisabled(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.cpp"],
enabled: false,
shared: {
enabled: true,
},
target: {
android: {
shared: {
enabled: false,
},
}
},
include_build_directory: false,
}`,
expectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
"srcs": `["foo.cpp"]`,
"target_compatible_with": `["@platforms//:incompatible"]`,
}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
"srcs": `["foo.cpp"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`,
}),
},
})
}
func TestCcLibraryStaticDisabledForSomeArch(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.cpp"],
shared: {
enabled: false
},
target: {
darwin: {
enabled: true,
},
windows: {
enabled: false,
},
linux_glibc_x86: {
shared: {
enabled: true,
},
},
},
include_build_directory: false,
}`,
expectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
"srcs": `["foo.cpp"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:windows": ["@platforms//:incompatible"],
"//conditions:default": [],
})`,
}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
"srcs": `["foo.cpp"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os_arch:darwin_arm64": [],
"//build/bazel/platforms/os_arch:darwin_x86_64": [],
"//build/bazel/platforms/os_arch:linux_glibc_x86": [],
"//conditions:default": ["@platforms//:incompatible"],
})`,
}),
}})
}

View File

@@ -1,10 +1,11 @@
package bp2build package bp2build
import ( import (
"android/soong/android"
"android/soong/bazel"
"fmt" "fmt"
"reflect" "reflect"
"android/soong/android"
"android/soong/bazel"
) )
// Configurability support for bp2build. // Configurability support for bp2build.
@@ -89,13 +90,15 @@ func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects
} }
archSelects := map[string]reflect.Value{} archSelects := map[string]reflect.Value{}
defaultVal := configToLabels[bazel.ConditionsDefaultConfigKey] defaultVal := configToLabels[bazel.ConditionsDefaultConfigKey]
// Skip empty list values unless ether EmitEmptyList is true, or these values differ from the default.
emitEmptyList := list.EmitEmptyList || len(defaultVal.Includes) > 0
for config, labels := range configToLabels { for config, labels := range configToLabels {
// Omit any entries in the map which match the default value, for brevity. // Omit any entries in the map which match the default value, for brevity.
if config != bazel.ConditionsDefaultConfigKey && labels.Equals(defaultVal) { if config != bazel.ConditionsDefaultConfigKey && labels.Equals(defaultVal) {
continue continue
} }
selectKey := axis.SelectKey(config) selectKey := axis.SelectKey(config)
if use, value := labelListSelectValue(selectKey, labels, list.EmitEmptyList); use { if use, value := labelListSelectValue(selectKey, labels, emitEmptyList); use {
archSelects[selectKey] = value archSelects[selectKey] = value
} }
} }
@@ -144,9 +147,15 @@ func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
shouldPrintDefault = true shouldPrintDefault = true
} }
case bazel.LabelAttribute: case bazel.LabelAttribute:
if err := list.Collapse(); err != nil {
return "", err
}
value, configurableAttrs = getLabelValue(list) value, configurableAttrs = getLabelValue(list)
defaultSelectValue = &bazelNone defaultSelectValue = &bazelNone
case bazel.BoolAttribute: case bazel.BoolAttribute:
if err := list.Collapse(); err != nil {
return "", err
}
value, configurableAttrs = getBoolValue(list) value, configurableAttrs = getBoolValue(list)
defaultSelectValue = &bazelNone defaultSelectValue = &bazelNone
default: default:
@@ -204,11 +213,12 @@ func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue *stri
continue continue
} }
value := selectMap[selectKey] value := selectMap[selectKey]
if isZero(value) && !emitZeroValues { if isZero(value) && !emitZeroValues && isZero(selectMap[bazel.ConditionsDefaultSelectKey]) {
// Ignore zero values to not generate empty lists. // Ignore zero values to not generate empty lists. However, always note zero values if
// the default value is non-zero.
continue continue
} }
s, err := prettyPrintSelectEntry(value, selectKey, indent, emitZeroValues) s, err := prettyPrintSelectEntry(value, selectKey, indent, true)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@@ -86,3 +86,45 @@ prebuilt_etc {
"sub_dir": `"tz"`, "sub_dir": `"tz"`,
})}}) })}})
} }
func TestPrebuiltEtcArchAndTargetVariant(t *testing.T) {
runPrebuiltEtcTestCase(t, bp2buildTestCase{
description: "prebuilt_etc - arch variant",
filesystem: map[string]string{},
blueprint: `
prebuilt_etc {
name: "apex_tz_version",
src: "version/tz_version",
filename: "tz_version",
sub_dir: "tz",
installable: false,
arch: {
arm: {
src: "arm",
},
arm64: {
src: "darwin_or_arm64",
},
},
target: {
darwin: {
src: "darwin_or_arm64",
}
},
}
`,
expectedBazelTargets: []string{
makeBazelTarget("prebuilt_etc", "apex_tz_version", attrNameToString{
"filename": `"tz_version"`,
"installable": `False`,
"src": `select({
"//build/bazel/platforms/os_arch:android_arm": "arm",
"//build/bazel/platforms/os_arch:android_arm64": "darwin_or_arm64",
"//build/bazel/platforms/os_arch:darwin_arm64": "darwin_or_arm64",
"//build/bazel/platforms/os_arch:darwin_x86_64": "darwin_or_arm64",
"//build/bazel/platforms/os_arch:linux_bionic_arm64": "darwin_or_arm64",
"//conditions:default": "version/tz_version",
})`,
"sub_dir": `"tz"`,
})}})
}

View File

@@ -558,13 +558,6 @@ func (binary *binaryDecorator) verifyHostBionicLinker(ctx ModuleContext, in, lin
} }
func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) { func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) {
var compatibleWith bazel.StringListAttribute
if typ == "cc_binary_host" {
//incompatible with android OS
compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, []string{"@platforms//:incompatible"})
compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, bazel.ConditionsDefaultConfigKey, []string{})
}
baseAttrs := bp2BuildParseBaseProps(ctx, m) baseAttrs := bp2BuildParseBaseProps(ctx, m)
binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m) binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
@@ -610,16 +603,22 @@ func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) {
None: baseAttrs.stripNone, None: baseAttrs.stripNone,
}, },
Target_compatible_with: compatibleWith, Features: baseAttrs.features,
Features: baseAttrs.features,
} }
ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{ var enabledProperty bazel.BoolAttribute
if typ == "cc_binary_host" {
falseVal := false
enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, &falseVal)
}
ctx.CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties{
Rule_class: "cc_binary", Rule_class: "cc_binary",
Bzl_load_location: "//build/bazel/rules:cc_binary.bzl", Bzl_load_location: "//build/bazel/rules:cc_binary.bzl",
}, },
android.CommonAttributes{Name: m.Name()}, android.CommonAttributes{Name: m.Name()},
attrs) attrs,
enabledProperty)
} }
// binaryAttributes contains Bazel attributes corresponding to a cc binary // binaryAttributes contains Bazel attributes corresponding to a cc binary
@@ -655,6 +654,4 @@ type binaryAttributes struct {
Strip stripAttributes Strip stripAttributes
Features bazel.StringListAttribute Features bazel.StringListAttribute
Target_compatible_with bazel.StringListAttribute
} }

View File

@@ -57,6 +57,8 @@ type staticOrSharedAttributes struct {
Implementation_whole_archive_deps bazel.LabelListAttribute Implementation_whole_archive_deps bazel.LabelListAttribute
System_dynamic_deps bazel.LabelListAttribute System_dynamic_deps bazel.LabelListAttribute
Enabled bazel.BoolAttribute
} }
func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute { func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
@@ -175,6 +177,7 @@ func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, mo
attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation) attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation)
attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs)) attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs))
attrs.Enabled.SetSelectValue(axis, config, props.Enabled)
} }
// system_dynamic_deps distinguishes between nil/empty list behavior: // system_dynamic_deps distinguishes between nil/empty list behavior:
// nil -> use default values // nil -> use default values

View File

@@ -3461,8 +3461,15 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
objectBp2Build(ctx, c) objectBp2Build(ctx, c)
} }
} else if c.CcLibrary() { } else if c.CcLibrary() {
static := c.BuildStaticVariant() static := false
shared := c.BuildSharedVariant() shared := false
if library, ok := c.linker.(*libraryDecorator); ok {
static = library.MutatedProperties.BuildStatic
shared = library.MutatedProperties.BuildShared
} else if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
static = library.MutatedProperties.BuildStatic
shared = library.MutatedProperties.BuildShared
}
if static && shared { if static && shared {
if !prebuilt { if !prebuilt {

View File

@@ -392,8 +392,12 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl", Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl",
} }
ctx.CreateBazelTargetModule(staticProps, android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"}, staticTargetAttrs) ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
ctx.CreateBazelTargetModule(sharedProps, android.CommonAttributes{Name: m.Name()}, sharedTargetAttrs) android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"},
staticTargetAttrs, staticAttrs.Enabled)
ctx.CreateBazelTargetModuleWithRestrictions(sharedProps,
android.CommonAttributes{Name: m.Name()},
sharedTargetAttrs, sharedAttrs.Enabled)
} }
// cc_library creates both static and/or shared libraries for a device and/or // cc_library creates both static and/or shared libraries for a device and/or

View File

@@ -155,7 +155,8 @@ func objectBp2Build(ctx android.TopDownMutatorContext, m *Module) {
for config, props := range configToProps { for config, props := range configToProps {
if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok { if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok {
if objectLinkerProps.Linker_script != nil { if objectLinkerProps.Linker_script != nil {
linkerScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *objectLinkerProps.Linker_script)) label := android.BazelLabelForModuleSrcSingle(ctx, *objectLinkerProps.Linker_script)
linkerScript.SetSelectValue(axis, config, label)
} }
deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs)) deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs))
systemSharedLibs := objectLinkerProps.System_shared_libs systemSharedLibs := objectLinkerProps.System_shared_libs

View File

@@ -681,7 +681,8 @@ func prebuiltEtcBp2BuildInternal(ctx android.TopDownMutatorContext, module *Preb
continue continue
} }
if props.Src != nil { if props.Src != nil {
srcLabelAttribute.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *props.Src)) label := android.BazelLabelForModuleSrcSingle(ctx, *props.Src)
srcLabelAttribute.SetSelectValue(axis, config, label)
} }
} }
} }