bp2build: support full/lite protos in cc libs

Test: bp2build.sh
Bug: 200601772
Change-Id: I3a7e00546726bc63b5eb8d5604557c5988a5320b
This commit is contained in:
Liz Kammer 2021-09-28 09:19:17 -04:00
parent a9351ef6e6
commit 12615dbbca
13 changed files with 605 additions and 96 deletions

View file

@ -336,9 +336,8 @@ var (
"host_bionic_linker_asm", // depends on extract_linker, a go binary.
"host_bionic_linker_script", // depends on extract_linker, a go binary.
"pbtombstone", // depends on libprotobuf-cpp-lite, libtombstone_proto
"crash_dump", // depends on unconverted module libprotobuf-cpp-lite
"libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610.
"pbtombstone", // depends on libprotobuf-cpp-lite, libtombstone_proto
"crash_dump", // depends on unconverted module libprotobuf-cpp-lite
"libunwindstack_local", "libunwindstack_utils", // depends on unconverted module libunwindstack
"libunwindstack", // depends on libdexfile_support, of unsupported module type art_cc_library_static
@ -373,19 +372,10 @@ var (
// APEX support
"com.android.runtime", // http://b/194746715, apex, depends on 'libc_malloc_debug'
"libadb_crypto", // Depends on libadb_protos
"libadb_crypto_static", // Depends on libadb_protos_static
"libadb_pairing_connection", // Depends on libadb_protos
"libadb_pairing_connection_static", // Depends on libadb_protos_static
"libadb_pairing_server", // Depends on libadb_protos
"libadb_pairing_server_static", // Depends on libadb_protos_static
"libadbd", // Depends on libadbd_core
"libadbd_core", // Depends on libadb_protos
"libadbd_services", // Depends on libadb_protos
"libadbd_core", // http://b/208481704: requijres use_version_lib
"libadbd_services", // http://b/208481704: requires use_version_lib
"libadb_protos_static", // b/200601772: Requires cc_library proto support
"libadb_protos", // b/200601772: Requires cc_library proto support
"libapp_processes_protos_lite", // b/200601772: Requires cc_library proto support
"libadbd", // depends on unconverted modules: libadbd_core, libadbd_services
"libgtest_ndk_c++", // b/201816222: Requires sdk_version support.
"libgtest_main_ndk_c++", // b/201816222: Requires sdk_version support.
@ -418,6 +408,13 @@ var (
"cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds
"libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds
"libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610.
// Depends on libprotobuf-cpp-*
"libadb_crypto", "libadb_crypto_static", "libadb_pairing_connection",
"libadb_pairing_connection_static",
"libadb_pairing_server", "libadb_pairing_server_static",
"libadb_protos_static", "libadb_protos",
"libapp_processes_protos_lite",
}
// Used for quicker lookups

View file

@ -221,6 +221,13 @@ var bp2buildMutators = map[string]RegisterMutatorFunc{}
// See http://b/192523357
var bp2buildLock sync.Mutex
// A minimal context for Bp2build conversion
type Bp2buildMutatorContext interface {
BazelConversionPathContext
CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
}
// RegisterBp2BuildMutator registers specially crafted mutators for
// converting Blueprint/Android modules into special modules that can
// be code-generated into Bazel BUILD targets.

View file

@ -15,12 +15,17 @@
package android
import (
"android/soong/bazel"
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
const (
canonicalPathFromRootDefault = true
)
// TODO(ccross): protos are often used to communicate between multiple modules. If the only
// way to convert a proto to source is to reference it as a source file, and external modules cannot
// reference source files in other modules, then every module that owns a proto file will need to
@ -90,7 +95,7 @@ func GetProtoFlags(ctx ModuleContext, p *ProtoProperties) ProtoFlags {
Flags: flags,
Deps: deps,
OutTypeFlag: protoOutFlag,
CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, true),
CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, canonicalPathFromRootDefault),
Dir: PathForModuleGen(ctx, "proto"),
SubDir: PathForModuleGen(ctx, "proto", ctx.ModuleDir()),
}
@ -146,3 +151,57 @@ func ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths,
rule.Command().
BuiltTool("dep_fixer").Flag(depFile.String())
}
// Bp2buildProtoInfo contains information necessary to pass on to language specific conversion.
type Bp2buildProtoInfo struct {
Type *string
Name string
}
type protoAttrs struct {
Srcs bazel.LabelListAttribute
Strip_import_prefix *string
}
// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the
// information necessary for language-specific handling.
func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, module Module, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) {
var info Bp2buildProtoInfo
if srcs.IsEmpty() {
return info, false
}
m := module.base()
info.Name = m.Name() + "_proto"
attrs := protoAttrs{
Srcs: srcs,
}
for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
for _, rawProps := range configToProps {
var props *ProtoProperties
var ok bool
if props, ok = rawProps.(*ProtoProperties); !ok {
ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
}
if axis == bazel.NoConfigAxis {
info.Type = props.Proto.Type
if proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
// an empty string indicates to strips the package path
path := ""
attrs.Strip_import_prefix = &path
}
} else if props.Proto.Type != info.Type && props.Proto.Type != nil {
ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
}
}
}
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
CommonAttributes{Name: info.Name},
&attrs)
return info, true
}

View file

@ -107,6 +107,14 @@ func (ll *LabelList) uniqueParentDirectories() []string {
return dirs
}
// Add inserts the label Label at the end of the LabelList.
func (ll *LabelList) Add(label *Label) {
if label == nil {
return
}
ll.Includes = append(ll.Includes, *label)
}
// Append appends the fields of other labelList to the corresponding fields of ll.
func (ll *LabelList) Append(other LabelList) {
if len(ll.Includes) > 0 || len(other.Includes) > 0 {
@ -366,6 +374,17 @@ func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis {
// labelListSelectValues supports config-specific label_list typed Bazel attribute values.
type labelListSelectValues map[string]LabelList
func (ll labelListSelectValues) addSelects(label labelSelectValues) {
for k, v := range label {
if label == nil {
continue
}
l := ll[k]
(&l).Add(v)
ll[k] = l
}
}
func (ll labelListSelectValues) appendSelects(other labelListSelectValues) {
for k, v := range other {
l := ll[k]
@ -500,6 +519,25 @@ func (lla *LabelListAttribute) Append(other LabelListAttribute) {
lla.ConfigurableValues.Append(other.ConfigurableValues)
}
// Add inserts the labels for each axis of LabelAttribute at the end of corresponding axis's
// LabelList within the LabelListAttribute
func (lla *LabelListAttribute) Add(label *LabelAttribute) {
if label == nil {
return
}
lla.Value.Add(label.Value)
if lla.ConfigurableValues == nil && label.ConfigurableValues != nil {
lla.ConfigurableValues = make(configurableLabelLists)
}
for axis, _ := range label.ConfigurableValues {
if _, exists := lla.ConfigurableValues[axis]; !exists {
lla.ConfigurableValues[axis] = make(labelListSelectValues)
}
lla.ConfigurableValues[axis].addSelects(label.ConfigurableValues[axis])
}
}
// HasConfigurableValues returns true if the attribute contains axis-specific label list values.
func (lla LabelListAttribute) HasConfigurableValues() bool {
return len(lla.ConfigurableValues) > 0
@ -566,7 +604,7 @@ type OtherModuleContext interface {
// LabelMapper is a function that takes a OtherModuleContext and returns a (potentially changed)
// label and whether it was changed.
type LabelMapper func(OtherModuleContext, string) (string, bool)
type LabelMapper func(OtherModuleContext, Label) (string, bool)
// LabelPartition contains descriptions of a partition for labels
type LabelPartition struct {
@ -588,7 +626,7 @@ type LabelPartitions map[string]LabelPartition
// not.
func (lf LabelPartition) filter(ctx OtherModuleContext, label Label) *Label {
if lf.LabelMapper != nil {
if newLabel, changed := lf.LabelMapper(ctx, label.Label); changed {
if newLabel, changed := lf.LabelMapper(ctx, label); changed {
return &Label{newLabel, label.OriginalModuleName}
}
}

View file

@ -313,16 +313,16 @@ func TestResolveExcludes(t *testing.T) {
// labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of
// typ
func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper {
return func(omc OtherModuleContext, label string) (string, bool) {
m, ok := omc.ModuleFromName(label)
return func(omc OtherModuleContext, label Label) (string, bool) {
m, ok := omc.ModuleFromName(label.Label)
if !ok {
return label, false
return label.Label, false
}
mTyp := omc.OtherModuleType(m)
if typ == mTyp {
return label + suffix, true
return label.Label + suffix, true
}
return label, false
return label.Label, false
}
}

View file

@ -24,8 +24,7 @@ import (
)
const (
ccBinaryTypePlaceHolder = "{rule_name}"
compatibleWithPlaceHolder = "{target_compatible_with}"
ccBinaryTypePlaceHolder = "{rule_name}"
)
type testBazelTarget struct {
@ -84,12 +83,15 @@ func runCcBinaryTestCase(t *testing.T, tc ccBinaryBp2buildTestCase) {
func runCcHostBinaryTestCase(t *testing.T, tc ccBinaryBp2buildTestCase) {
t.Helper()
testCase := tc
for i, t := range testCase.targets {
t.attrs["target_compatible_with"] = `select({
for i, tar := range testCase.targets {
if tar.typ != "cc_binary" {
continue
}
tar.attrs["target_compatible_with"] = `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`
testCase.targets[i] = t
testCase.targets[i] = tar
}
moduleTypeUnderTest := "cc_binary_host"
t.Run(testCase.description, func(t *testing.T) {
@ -448,3 +450,51 @@ func TestCcBinaryPropertiesToFeatures(t *testing.T) {
})
}
}
func TestCcBinarySharedProto(t *testing.T) {
runCcBinaryTests(t, ccBinaryBp2buildTestCase{
blueprint: soongCcProtoLibraries + `{rule_name} {
name: "foo",
srcs: ["foo.proto"],
proto: {
canonical_path_from_root: false,
},
include_build_directory: false,
}`,
targets: []testBazelTarget{
{"proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}}, {"cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}}, {"cc_binary", "foo", attrNameToString{
"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
"whole_archive_deps": `[":foo_cc_proto_lite"]`,
}},
},
})
}
func TestCcBinaryStaticProto(t *testing.T) {
runCcBinaryTests(t, ccBinaryBp2buildTestCase{
blueprint: soongCcProtoLibraries + `{rule_name} {
name: "foo",
srcs: ["foo.proto"],
static_executable: true,
proto: {
canonical_path_from_root: false,
},
include_build_directory: false,
}`,
targets: []testBazelTarget{
{"proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}}, {"cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}}, {"cc_binary", "foo", attrNameToString{
"deps": `[":libprotobuf-cpp-lite"]`,
"whole_archive_deps": `[":foo_cc_proto_lite"]`,
"linkshared": `False`,
}},
},
})
}

View file

@ -39,6 +39,19 @@ toolchain_library {
native_bridge_supported: true,
src: "",
}`
soongCcProtoLibraries = `
cc_library {
name: "libprotobuf-cpp-lite",
bazel_module: { bp2build_available: false },
}
cc_library {
name: "libprotobuf-cpp-full",
bazel_module: { bp2build_available: false },
}`
soongCcProtoPreamble = soongCcLibraryPreamble + soongCcProtoLibraries
)
func runCcLibraryTestCase(t *testing.T, tc bp2buildTestCase) {
@ -1829,3 +1842,187 @@ cc_library_shared {
})
}
}
func TestCcLibraryProtoSimple(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.proto"],
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
"strip_import_prefix": `""`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library", "foo", attrNameToString{
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"shared": `{
"dynamic_deps": [":libprotobuf-cpp-lite"],
}`,
"static": `{
"deps": [":libprotobuf-cpp-lite"],
}`,
}),
},
})
}
func TestCcLibraryProtoNoCanonicalPathFromRoot(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.proto"],
proto: { canonical_path_from_root: false},
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library", "foo", attrNameToString{
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"shared": `{
"dynamic_deps": [":libprotobuf-cpp-lite"],
}`,
"static": `{
"deps": [":libprotobuf-cpp-lite"],
}`,
}),
},
})
}
func TestCcLibraryProtoExplicitCanonicalPathFromRoot(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.proto"],
proto: { canonical_path_from_root: true},
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
"strip_import_prefix": `""`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library", "foo", attrNameToString{
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"shared": `{
"dynamic_deps": [":libprotobuf-cpp-lite"],
}`,
"static": `{
"deps": [":libprotobuf-cpp-lite"],
}`,
}),
},
})
}
func TestCcLibraryProtoFull(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.proto"],
proto: {
canonical_path_from_root: false,
type: "full",
},
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_proto_library", "foo_cc_proto", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library", "foo", attrNameToString{
"implementation_whole_archive_deps": `[":foo_cc_proto"]`,
"shared": `{
"dynamic_deps": [":libprotobuf-cpp-full"],
}`,
"static": `{
"deps": [":libprotobuf-cpp-full"],
}`,
}),
},
})
}
func TestCcLibraryProtoLite(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.proto"],
proto: {
canonical_path_from_root: false,
type: "lite",
},
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library", "foo", attrNameToString{
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"shared": `{
"dynamic_deps": [":libprotobuf-cpp-lite"],
}`,
"static": `{
"deps": [":libprotobuf-cpp-lite"],
}`,
}),
},
})
}
func TestCcLibraryProtoExportHeaders(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
blueprint: soongCcProtoPreamble + `cc_library {
name: "foo",
srcs: ["foo.proto"],
proto: {
canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library", "foo", attrNameToString{
"whole_archive_deps": `[":foo_cc_proto_lite"]`,
"shared": `{
"dynamic_deps": [":libprotobuf-cpp-lite"],
}`,
"static": `{
"deps": [":libprotobuf-cpp-lite"],
}`,
}),
},
})
}

View file

@ -33,6 +33,7 @@ func registerCcLibrarySharedModuleTypes(ctx android.RegistrationContext) {
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
}
func runCcLibrarySharedTestCase(t *testing.T, tc bp2buildTestCase) {
@ -425,3 +426,27 @@ cc_library_shared {
expectedErr: fmt.Errorf("Android.bp:16:1: module \"foo_shared\": nocrt is not supported for arch variants"),
})
}
func TestCcLibrarySharedProto(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
blueprint: soongCcProtoPreamble + `cc_library_shared {
name: "foo",
srcs: ["foo.proto"],
proto: {
canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
"whole_archive_deps": `[":foo_cc_proto_lite"]`,
}),
},
})
}

View file

@ -1419,3 +1419,27 @@ cc_library_static {
},
})
}
func TestCcLibraryStaticProto(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
blueprint: soongCcProtoPreamble + `cc_library_static {
name: "foo",
srcs: ["foo.proto"],
proto: {
canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
"srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library_static", "foo", attrNameToString{
"deps": `[":libprotobuf-cpp-lite"]`,
"whole_archive_deps": `[":foo_cc_proto_lite"]`,
}),
},
})
}

View file

@ -18,6 +18,7 @@ import (
"path/filepath"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/bazel"
@ -578,9 +579,16 @@ func binaryBp2build(ctx android.TopDownMutatorContext, typ string) {
}
baseAttrs := bp2BuildParseBaseProps(ctx, m)
binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
if proptools.BoolDefault(binaryLinkerAttrs.Linkshared, true) {
baseAttrs.implementationDynamicDeps.Add(baseAttrs.protoDependency)
} else {
baseAttrs.implementationDeps.Add(baseAttrs.protoDependency)
}
attrs := &binaryAttributes{
binaryLinkerAttrs: bp2buildBinaryLinkerProps(ctx, m),
binaryLinkerAttrs: binaryLinkerAttrs,
Srcs: baseAttrs.srcs,
Srcs_c: baseAttrs.cSrcs,

View file

@ -27,9 +27,10 @@ import (
)
const (
cSrcPartition = "c"
asSrcPartition = "as"
cppSrcPartition = "cpp"
cSrcPartition = "c"
asSrcPartition = "as"
cppSrcPartition = "cpp"
protoSrcPartition = "proto"
)
// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
@ -41,52 +42,53 @@ type staticOrSharedAttributes struct {
Hdrs bazel.LabelListAttribute
Copts bazel.StringListAttribute
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Implementation_dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Implementation_dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
Implementation_whole_archive_deps bazel.LabelListAttribute
System_dynamic_deps bazel.LabelListAttribute
}
func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
// Check that a module is a filegroup type named <label>.
isFilegroupNamed := func(m android.Module, fullLabel string) bool {
if ctx.OtherModuleType(m) != "filegroup" {
return false
}
labelParts := strings.Split(fullLabel, ":")
if len(labelParts) > 2 {
// There should not be more than one colon in a label.
ctx.ModuleErrorf("%s is not a valid Bazel label for a filegroup", fullLabel)
}
return m.Name() == labelParts[len(labelParts)-1]
// Check that a module is a filegroup type
isFilegroup := func(m blueprint.Module) bool {
return ctx.OtherModuleType(m) == "filegroup"
}
// Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl
// macro.
addSuffixForFilegroup := func(suffix string) bazel.LabelMapper {
return func(ctx bazel.OtherModuleContext, label string) (string, bool) {
m, exists := ctx.ModuleFromName(label)
if !exists {
return label, false
return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
m, exists := ctx.ModuleFromName(label.OriginalModuleName)
labelStr := label.Label
if !exists || !isFilegroup(m) {
return labelStr, false
}
aModule, _ := m.(android.Module)
if !isFilegroupNamed(aModule, label) {
return label, false
}
return label + suffix, true
return labelStr + suffix, true
}
}
isProtoFilegroup := func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
m, exists := ctx.ModuleFromName(label.OriginalModuleName)
labelStr := label.Label
if !exists || !isFilegroup(m) {
return labelStr, false
}
likelyProtos := strings.HasSuffix(labelStr, "proto") || strings.HasSuffix(labelStr, "protos")
return labelStr, likelyProtos
}
// TODO(b/190006308): Handle language detection of sources in a Bazel rule.
partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
// C++ is the "catch-all" group, and comprises generated sources because we don't
// know the language of these sources until the genrule is executed.
cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
protoSrcPartition: bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup},
})
return partitioned
@ -195,6 +197,11 @@ func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, mo
attrs.Srcs_c = partitionedSrcs[cSrcPartition]
attrs.Srcs_as = partitionedSrcs[asSrcPartition]
if !partitionedSrcs[protoSrcPartition].IsEmpty() {
// TODO(b/208815215): determine whether this is used and add support if necessary
ctx.ModuleErrorf("Migrating static/shared only proto srcs is not currently supported")
}
return attrs
}
@ -230,6 +237,8 @@ func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, m
type baseAttributes struct {
compilerAttributes
linkerAttributes
protoDependency *bazel.LabelAttribute
}
// Convenience struct to hold all attributes parsed from compiler properties.
@ -257,6 +266,8 @@ type compilerAttributes struct {
localIncludes bazel.StringListAttribute
absoluteIncludes bazel.StringListAttribute
protoSrcs bazel.LabelListAttribute
}
func parseCommandLineFlags(soongFlags []string) []string {
@ -337,6 +348,8 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i
ca.srcs.ResolveExcludes()
partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs)
ca.protoSrcs = partitionedSrcs[protoSrcPartition]
for p, lla := range partitionedSrcs {
// if there are no sources, there is no need for headers
if lla.IsEmpty() {
@ -400,7 +413,7 @@ func bp2buildResolveCppStdValue(c_std *string, cpp_std *string, gnu_extensions *
}
// bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Module) baseAttributes {
func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes {
archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{})
@ -456,20 +469,30 @@ func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Modu
(&compilerAttrs).finalize(ctx, implementationHdrs)
(&linkerAttrs).finalize()
protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
// bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know
// which. This will add the newly generated proto library to the appropriate attribute and nothing
// to the other
(&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
(&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
return baseAttributes{
compilerAttrs,
linkerAttrs,
protoDep.protoDep,
}
}
// Convenience struct to hold all attributes parsed from linker properties.
type linkerAttributes struct {
deps bazel.LabelListAttribute
implementationDeps bazel.LabelListAttribute
dynamicDeps bazel.LabelListAttribute
implementationDynamicDeps bazel.LabelListAttribute
wholeArchiveDeps bazel.LabelListAttribute
systemDynamicDeps bazel.LabelListAttribute
deps bazel.LabelListAttribute
implementationDeps bazel.LabelListAttribute
dynamicDeps bazel.LabelListAttribute
implementationDynamicDeps bazel.LabelListAttribute
wholeArchiveDeps bazel.LabelListAttribute
implementationWholeArchiveDeps bazel.LabelListAttribute
systemDynamicDeps bazel.LabelListAttribute
linkCrt bazel.BoolAttribute
useLibcrt bazel.BoolAttribute

View file

@ -236,12 +236,13 @@ type bazelCcLibraryAttributes struct {
Hdrs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Implementation_dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
System_dynamic_deps bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Implementation_dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
Implementation_whole_archive_deps bazel.LabelListAttribute
System_dynamic_deps bazel.LabelListAttribute
Export_includes bazel.StringListAttribute
Export_system_includes bazel.StringListAttribute
@ -303,6 +304,9 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) {
srcs := compilerAttrs.srcs
sharedAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
staticAttrs.Deps.Add(baseAttributes.protoDependency)
asFlags := compilerAttrs.asFlags
if compilerAttrs.asSrcs.IsEmpty() && sharedAttrs.Srcs_as.IsEmpty() && staticAttrs.Srcs_as.IsEmpty() {
// Skip asflags for BUILD file simplicity if there are no assembly sources.
@ -320,23 +324,24 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) {
Conlyflags: compilerAttrs.conlyFlags,
Asflags: asFlags,
Implementation_deps: linkerAttrs.implementationDeps,
Deps: linkerAttrs.deps,
Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
Dynamic_deps: linkerAttrs.dynamicDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
System_dynamic_deps: linkerAttrs.systemDynamicDeps,
Export_includes: exportedIncludes.Includes,
Export_system_includes: exportedIncludes.SystemIncludes,
Local_includes: compilerAttrs.localIncludes,
Absolute_includes: compilerAttrs.absoluteIncludes,
Linkopts: linkerAttrs.linkopts,
Link_crt: linkerAttrs.linkCrt,
Use_libcrt: linkerAttrs.useLibcrt,
Rtti: compilerAttrs.rtti,
Stl: compilerAttrs.stl,
Cpp_std: compilerAttrs.cppStd,
C_std: compilerAttrs.cStd,
Implementation_deps: linkerAttrs.implementationDeps,
Deps: linkerAttrs.deps,
Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
Dynamic_deps: linkerAttrs.dynamicDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
System_dynamic_deps: linkerAttrs.systemDynamicDeps,
Export_includes: exportedIncludes.Includes,
Export_system_includes: exportedIncludes.SystemIncludes,
Local_includes: compilerAttrs.localIncludes,
Absolute_includes: compilerAttrs.absoluteIncludes,
Linkopts: linkerAttrs.linkopts,
Link_crt: linkerAttrs.linkCrt,
Use_libcrt: linkerAttrs.useLibcrt,
Rtti: compilerAttrs.rtti,
Stl: compilerAttrs.stl,
Cpp_std: compilerAttrs.cppStd,
C_std: compilerAttrs.cStd,
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
@ -2405,16 +2410,18 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext,
Copts: compilerAttrs.copts,
Hdrs: compilerAttrs.hdrs,
Deps: linkerAttrs.deps,
Implementation_deps: linkerAttrs.implementationDeps,
Dynamic_deps: linkerAttrs.dynamicDeps,
Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
System_dynamic_deps: linkerAttrs.systemDynamicDeps,
Deps: linkerAttrs.deps,
Implementation_deps: linkerAttrs.implementationDeps,
Dynamic_deps: linkerAttrs.dynamicDeps,
Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
System_dynamic_deps: linkerAttrs.systemDynamicDeps,
}
var attrs interface{}
if isStatic {
commonAttrs.Deps.Add(baseAttributes.protoDependency)
attrs = &bazelCcLibraryStaticAttributes{
staticOrSharedAttributes: commonAttrs,
@ -2435,6 +2442,8 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext,
Features: linkerAttrs.features,
}
} else {
commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
attrs = &bazelCcLibrarySharedAttributes{
staticOrSharedAttributes: commonAttrs,

View file

@ -16,8 +16,14 @@ package cc
import (
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/bazel"
)
const (
protoTypeDefault = "lite"
)
// genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns
@ -63,7 +69,7 @@ func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bo
var lib string
if String(p.Proto.Plugin) == "" {
switch String(p.Proto.Type) {
switch proptools.StringDefault(p.Proto.Type, protoTypeDefault) {
case "full":
if ctx.useSdk() {
lib = "libprotobuf-cpp-full-ndk"
@ -71,7 +77,7 @@ func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bo
} else {
lib = "libprotobuf-cpp-full"
}
case "lite", "":
case "lite":
if ctx.useSdk() {
lib = "libprotobuf-cpp-lite-ndk"
static = true
@ -157,3 +163,69 @@ func protoFlags(ctx ModuleContext, flags Flags, p *android.ProtoProperties) Flag
return flags
}
type protoAttributes struct {
Deps bazel.LabelListAttribute
}
type bp2buildProtoDeps struct {
wholeStaticLib *bazel.LabelAttribute
implementationWholeStaticLib *bazel.LabelAttribute
protoDep *bazel.LabelAttribute
}
func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) bp2buildProtoDeps {
var ret bp2buildProtoDeps
protoInfo, ok := android.Bp2buildProtoProperties(ctx, m, protoSrcs)
if !ok {
return ret
}
var depName string
typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault)
var rule_class string
suffix := "_cc_proto"
switch typ {
case "lite":
suffix += "_lite"
rule_class = "cc_lite_proto_library"
depName = "libprotobuf-cpp-lite"
case "full":
rule_class = "cc_proto_library"
depName = "libprotobuf-cpp-full"
default:
ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
}
dep := android.BazelLabelForModuleDepSingle(ctx, depName)
ret.protoDep = &bazel.LabelAttribute{Value: &dep}
protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
var protoAttrs protoAttributes
protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
name := m.Name() + suffix
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: rule_class,
Bzl_load_location: "//build/bazel/rules:cc_proto.bzl",
},
android.CommonAttributes{Name: name},
&protoAttrs)
var privateHdrs bool
if lib, ok := m.linker.(*libraryDecorator); ok {
privateHdrs = !proptools.Bool(lib.Properties.Proto.Export_proto_headers)
}
labelAttr := &bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}}
if privateHdrs {
ret.implementationWholeStaticLib = labelAttr
} else {
ret.wholeStaticLib = labelAttr
}
return ret
}