Merge "Handle the 'enabled' property in bp2build" am: 948e851b83

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1917398

Change-Id: Ica906b1be0280c6b3f1a3690d407c4141046022d
This commit is contained in:
Christopher Parsons 2021-12-22 16:07:42 +00:00 committed by Automerger Merge Worker
commit fdb30910fc
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)
}
}
}