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
"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,8 +442,7 @@ 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
"CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
"libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, 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
// 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
}

View file

@ -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
@ -1233,10 +1272,11 @@ type ModuleBase struct {
// A struct containing all relevant information about a Bazel target converted via bp2build.
type bp2buildInfo struct {
Dir string
BazelProps bazel.BazelTargetModuleProperties
CommonAttrs CommonAttributes
Attrs interface{}
Dir string
BazelProps bazel.BazelTargetModuleProperties
CommonAttrs CommonAttributes
ConstraintAttrs constraintAttributes
Attrs interface{}
}
// 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.
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) {

View file

@ -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,13 +510,30 @@ 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,
Attrs: attrs,
Dir: t.OtherModuleDir(mod),
BazelProps: bazelProps,
CommonAttrs: commonAttrs,
ConstraintAttrs: constraintAttributes,
Attrs: attrs,
}
mod.base().addBp2buildInfo(info)
}

View file

@ -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",

View file

@ -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

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

View file

@ -86,3 +86,45 @@ prebuilt_etc {
"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) {
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)
binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
@ -610,16 +603,22 @@ func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) {
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",
Bzl_load_location: "//build/bazel/rules:cc_binary.bzl",
},
android.CommonAttributes{Name: m.Name()},
attrs)
attrs,
enabledProperty)
}
// binaryAttributes contains Bazel attributes corresponding to a cc binary
@ -655,6 +654,4 @@ type binaryAttributes struct {
Strip stripAttributes
Features bazel.StringListAttribute
Target_compatible_with bazel.StringListAttribute
}

View file

@ -57,6 +57,8 @@ type staticOrSharedAttributes struct {
Implementation_whole_archive_deps bazel.LabelListAttribute
System_dynamic_deps bazel.LabelListAttribute
Enabled bazel.BoolAttribute
}
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.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:
// nil -> use default values

View file

@ -3461,8 +3461,15 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
objectBp2Build(ctx, c)
}
} else if c.CcLibrary() {
static := c.BuildStaticVariant()
shared := c.BuildSharedVariant()
static := false
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 !prebuilt {

View file

@ -392,8 +392,12 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl",
}
ctx.CreateBazelTargetModule(staticProps, android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"}, staticTargetAttrs)
ctx.CreateBazelTargetModule(sharedProps, android.CommonAttributes{Name: m.Name()}, sharedTargetAttrs)
ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
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

View file

@ -155,7 +155,8 @@ func objectBp2Build(ctx android.TopDownMutatorContext, m *Module) {
for config, props := range configToProps {
if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok {
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))
systemSharedLibs := objectLinkerProps.System_shared_libs

View file

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