Merge "bp2build: support full/lite protos in cc libs"

This commit is contained in:
Liz Kammer
2021-12-06 14:46:34 +00:00
committed by Gerrit Code Review
13 changed files with 605 additions and 96 deletions

View File

@@ -340,7 +340,6 @@ var (
"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.
"libunwindstack_local", "libunwindstack_utils", // depends on unconverted module libunwindstack
"libunwindstack", // depends on libdexfile_support, of unsupported module type art_cc_library_static
@@ -375,19 +374,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.
@@ -420,6 +410,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

@@ -25,7 +25,6 @@ import (
const (
ccBinaryTypePlaceHolder = "{rule_name}"
compatibleWithPlaceHolder = "{target_compatible_with}"
)
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

@@ -30,6 +30,7 @@ const (
cSrcPartition = "c"
asSrcPartition = "as"
cppSrcPartition = "cpp"
protoSrcPartition = "proto"
)
// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
@@ -46,38 +47,38 @@ type staticOrSharedAttributes struct {
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 labelStr + suffix, true
}
return label + 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.
@@ -87,6 +88,7 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab
// 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},
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,9 +469,18 @@ 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,
}
}
@@ -469,6 +491,7 @@ type linkerAttributes struct {
dynamicDeps bazel.LabelListAttribute
implementationDynamicDeps bazel.LabelListAttribute
wholeArchiveDeps bazel.LabelListAttribute
implementationWholeArchiveDeps bazel.LabelListAttribute
systemDynamicDeps bazel.LabelListAttribute
linkCrt bazel.BoolAttribute

View File

@@ -241,6 +241,7 @@ type bazelCcLibraryAttributes struct {
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
@@ -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.
@@ -325,6 +329,7 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) {
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,
@@ -2410,11 +2415,13 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext,
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
}