diff --git a/android/bazel.go b/android/bazel.go index eb6aca4e9..843ec1865 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -32,10 +32,13 @@ const ( Bp2BuildTopLevel = "." ) -// Bp2buildAidlLibrary describes a filegroup module that are converted to aidl_library -type Bp2buildAidlLibrary interface { +// FileGroupAsLibrary describes a filegroup module that is converted to some library +// such as aidl_library or proto_library. +type FileGroupAsLibrary interface { ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool + ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool GetAidlLibraryLabel(ctx BazelConversionPathContext) string + GetProtoLibraryLabel(ctx BazelConversionPathContext) string } type BazelConversionStatus struct { diff --git a/android/filegroup.go b/android/filegroup.go index e609f6362..e5eec87cf 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -33,6 +33,8 @@ var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx Registrati ctx.RegisterModuleType("filegroup", FileGroupFactory) }) +var convertedProtoLibrarySuffix = "_bp2build_converted" + // IsFilegroup checks that a module is a filegroup type func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool { return ctx.OtherModuleType(m) == "filegroup" @@ -117,6 +119,20 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) { ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs) } else { + if fg.ShouldConvertToProtoLibrary(ctx) { + attrs := &ProtoAttrs{ + Srcs: srcs, + Strip_import_prefix: fg.properties.Path, + } + + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{Rule_class: "proto_library"}, + CommonAttributes{Name: fg.Name() + convertedProtoLibrarySuffix}, + attrs) + } + + // TODO(b/242847534): Still convert to a filegroup because other unconverted + // modules may depend on the filegroup attrs := &bazelFilegroupAttributes{ Srcs: srcs, } @@ -150,14 +166,14 @@ type fileGroupProperties struct { type fileGroup struct { ModuleBase BazelModuleBase - Bp2buildAidlLibrary + FileGroupAsLibrary properties fileGroupProperties srcs Paths } var _ MixedBuildBuildable = (*fileGroup)(nil) var _ SourceFileProducer = (*fileGroup)(nil) -var _ Bp2buildAidlLibrary = (*fileGroup)(nil) +var _ FileGroupAsLibrary = (*fileGroup)(nil) // filegroup contains a list of files that are referenced by other modules // properties (such as "srcs") using the syntax ":". filegroup are @@ -243,11 +259,19 @@ func (fg *fileGroup) ProcessBazelQueryResponse(ctx ModuleContext) { } func (fg *fileGroup) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool { + return fg.shouldConvertToLibrary(ctx, ".aidl") +} + +func (fg *fileGroup) ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool { + return fg.shouldConvertToLibrary(ctx, ".proto") +} + +func (fg *fileGroup) shouldConvertToLibrary(ctx BazelConversionPathContext, suffix string) bool { if len(fg.properties.Srcs) == 0 || !fg.ShouldConvertWithBp2build(ctx) { return false } for _, src := range fg.properties.Srcs { - if !strings.HasSuffix(src, ".aidl") { + if !strings.HasSuffix(src, suffix) { return false } } @@ -255,6 +279,14 @@ func (fg *fileGroup) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) } func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string { + return fg.getFileGroupAsLibraryLabel(ctx) +} + +func (fg *fileGroup) GetProtoLibraryLabel(ctx BazelConversionPathContext) string { + return fg.getFileGroupAsLibraryLabel(ctx) + convertedProtoLibrarySuffix +} + +func (fg *fileGroup) getFileGroupAsLibraryLabel(ctx BazelConversionPathContext) string { if ctx.OtherModuleDir(fg.module) == ctx.ModuleDir() { return ":" + fg.Name() } else { @@ -265,12 +297,19 @@ func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string // Given a name in srcs prop, check to see if the name references a filegroup // and the filegroup is converted to aidl_library func IsConvertedToAidlLibrary(ctx BazelConversionPathContext, name string) bool { - if module, ok := ctx.ModuleFromName(name); ok { - if IsFilegroup(ctx, module) { - if fg, ok := module.(Bp2buildAidlLibrary); ok { - return fg.ShouldConvertToAidlLibrary(ctx) - } - } + if fg, ok := ToFileGroupAsLibrary(ctx, name); ok { + return fg.ShouldConvertToAidlLibrary(ctx) } return false } + +func ToFileGroupAsLibrary(ctx BazelConversionPathContext, name string) (FileGroupAsLibrary, bool) { + if module, ok := ctx.ModuleFromName(name); ok { + if IsFilegroup(ctx, module) { + if fg, ok := module.(FileGroupAsLibrary); ok { + return fg, true + } + } + } + return nil, false +} diff --git a/android/proto.go b/android/proto.go index 25cecf411..3a5d4da5c 100644 --- a/android/proto.go +++ b/android/proto.go @@ -155,11 +155,12 @@ func ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths, // Bp2buildProtoInfo contains information necessary to pass on to language specific conversion. type Bp2buildProtoInfo struct { - Type *string - Name string + Type *string + Name string + Proto_libs bazel.LabelList } -type protoAttrs struct { +type ProtoAttrs struct { Srcs bazel.LabelListAttribute Strip_import_prefix *string Deps bazel.LabelListAttribute @@ -179,44 +180,70 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz return info, false } - info.Name = m.Name() + "_proto" - attrs := protoAttrs{ - Srcs: srcs, - } + var protoLibraries bazel.LabelList + var directProtoSrcs bazel.LabelList - 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 - } - - for _, dir := range props.Proto.Include_dirs { - if dep, ok := includeDirsToProtoDeps[dir]; ok { - attrs.Deps.Add(bazel.MakeLabelAttribute(dep)) - } else { - ctx.PropertyErrorf("Could not find the proto_library target for include dir", dir) - } - } - } else if props.Proto.Type != info.Type && props.Proto.Type != nil { - ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.") - } + // For filegroups that should be converted to proto_library just collect the + // labels of converted proto_library targets. + for _, protoSrc := range srcs.Value.Includes { + src := protoSrc.OriginalModuleName + if fg, ok := ToFileGroupAsLibrary(ctx, src); ok && + fg.ShouldConvertToProtoLibrary(ctx) { + protoLibraries.Add(&bazel.Label{ + Label: fg.GetProtoLibraryLabel(ctx), + }) + } else { + directProtoSrcs.Add(&protoSrc) } } - ctx.CreateBazelTargetModule( - bazel.BazelTargetModuleProperties{Rule_class: "proto_library"}, - CommonAttributes{Name: info.Name}, - &attrs) + info.Name = m.Name() + "_proto" + + if len(directProtoSrcs.Includes) > 0 { + attrs := ProtoAttrs{ + Srcs: bazel.MakeLabelListAttribute(directProtoSrcs), + } + + 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 + } + + for _, dir := range props.Proto.Include_dirs { + if dep, ok := includeDirsToProtoDeps[dir]; ok { + attrs.Deps.Add(bazel.MakeLabelAttribute(dep)) + } else { + ctx.PropertyErrorf("Could not find the proto_library target for include dir", dir) + } + } + } 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) + + protoLibraries.Add(&bazel.Label{ + Label: ":" + info.Name, + }) + } + + info.Proto_libs = protoLibraries return info, true } diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 880ae75c0..ba7af0945 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -2261,6 +2261,130 @@ func TestCcLibraryProtoIncludeDirsUnknown(t *testing.T) { }) } +func TestCcLibraryConvertedProtoFilegroups(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Blueprint: soongCcProtoPreamble + ` +filegroup { + name: "a_fg_proto", + srcs: ["a_fg.proto"], +} + +cc_library { + name: "a", + srcs: [ + ":a_fg_proto", + "a.proto", + ], + proto: { + export_proto_headers: true, + }, + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("proto_library", "a_proto", AttrNameToString{ + "srcs": `["a.proto"]`, + }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{ + "deps": `[ + ":a_fg_proto_bp2build_converted", + ":a_proto", + ]`, + }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + "deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":a_cc_proto_lite"]`, + }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":a_cc_proto_lite"]`, + }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{ + "srcs": `["a_fg.proto"]`, + }), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{ + "srcs": `["a_fg.proto"]`, + }), + }, + }) +} + +func TestCcLibraryConvertedProtoFilegroupsNoProtoFiles(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Blueprint: soongCcProtoPreamble + ` +filegroup { + name: "a_fg_proto", + srcs: ["a_fg.proto"], +} + +cc_library { + name: "a", + srcs: [ + ":a_fg_proto", + ], + proto: { + export_proto_headers: true, + }, + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{ + "deps": `[":a_fg_proto_bp2build_converted"]`, + }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + "deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":a_cc_proto_lite"]`, + }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":a_cc_proto_lite"]`, + }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{ + "srcs": `["a_fg.proto"]`, + }), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{ + "srcs": `["a_fg.proto"]`, + }), + }, + }) +} + +func TestCcLibraryExternalConvertedProtoFilegroups(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Filesystem: map[string]string{ + "path/to/A/Android.bp": ` +filegroup { + name: "a_fg_proto", + srcs: ["a_fg.proto"], +}`, + }, + Blueprint: soongCcProtoPreamble + ` +cc_library { + name: "a", + srcs: [ + ":a_fg_proto", + "a.proto", + ], + proto: { + export_proto_headers: true, + }, + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("proto_library", "a_proto", AttrNameToString{ + "srcs": `["a.proto"]`, + }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{ + "deps": `[ + "//path/to/A:a_fg_proto_bp2build_converted", + ":a_proto", + ]`, + }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + "deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":a_cc_proto_lite"]`, + }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "whole_archive_deps": `[":a_cc_proto_lite"]`, + }), + }, + }) +} + func TestCcLibraryProtoFilegroups(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ ModuleTypeUnderTest: "cc_library", diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go index de09a1787..d84d4b374 100644 --- a/bp2build/filegroup_conversion_test.go +++ b/bp2build/filegroup_conversion_test.go @@ -15,10 +15,10 @@ package bp2build import ( - "android/soong/android" "fmt" - "testing" + + "android/soong/android" ) func runFilegroupTestCase(t *testing.T, tc Bp2buildTestCase) { @@ -121,3 +121,43 @@ filegroup { ]`}), }}) } + +func TestFilegroupWithProtoSrcs(t *testing.T) { + runFilegroupTestCase(t, Bp2buildTestCase{ + Description: "filegroup with proto and non-proto srcs", + Filesystem: map[string]string{}, + Blueprint: ` +filegroup { + name: "foo", + srcs: ["proto/foo.proto"], + path: "proto", +}`, + ExpectedBazelTargets: []string{ + MakeBazelTargetNoRestrictions("proto_library", "foo_bp2build_converted", AttrNameToString{ + "srcs": `["proto/foo.proto"]`, + "strip_import_prefix": `"proto"`}), + MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{ + "srcs": `["proto/foo.proto"]`}), + }}) +} + +func TestFilegroupWithProtoAndNonProtoSrcs(t *testing.T) { + runFilegroupTestCase(t, Bp2buildTestCase{ + Description: "filegroup with proto and non-proto srcs", + Filesystem: map[string]string{}, + Blueprint: ` +filegroup { + name: "foo", + srcs: [ + "foo.proto", + "buf.cpp", + ], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{ + "srcs": `[ + "foo.proto", + "buf.cpp", + ]`}), + }}) +} diff --git a/cc/bp2build.go b/cc/bp2build.go index e001d2489..51d8e2270 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -79,10 +79,10 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab if !exists || !android.IsFilegroup(otherModuleCtx, m) { return labelStr, false } - // If the filegroup is already converted to aidl_library, skip creating - // _c_srcs, _as_srcs, _cpp_srcs filegroups - fg, _ := m.(android.Bp2buildAidlLibrary) - if fg.ShouldConvertToAidlLibrary(ctx) { + // If the filegroup is already converted to aidl_library or proto_library, + // skip creating _c_srcs, _as_srcs, _cpp_srcs filegroups + fg, _ := m.(android.FileGroupAsLibrary) + if fg.ShouldConvertToAidlLibrary(ctx) || fg.ShouldConvertToProtoLibrary(ctx) { return labelStr, false } return labelStr + suffix, true @@ -506,19 +506,6 @@ func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProper return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs } -// Given a name in srcs prop, check to see if the name references a filegroup -// and the filegroup is converted to aidl_library -func isConvertedToAidlLibrary(ctx android.BazelConversionPathContext, name string) bool { - if module, ok := ctx.ModuleFromName(name); ok { - if android.IsFilegroup(ctx, module) { - if fg, ok := module.(android.Bp2buildAidlLibrary); ok { - return fg.ShouldConvertToAidlLibrary(ctx) - } - } - } - return false -} - func bp2buildStdVal(std *string, prefix string, useGnu bool) *string { defaultVal := prefix + "_std_default" // If c{,pp}std properties are not specified, don't generate them in the BUILD file. @@ -770,9 +757,8 @@ func bp2buildAidlLibraries( // Make a list of labels that correspond to filegroups that are already converted to aidl_library for _, aidlSrc := range aidlSrcs.Value.Includes { src := aidlSrc.OriginalModuleName - if isConvertedToAidlLibrary(ctx, src) { - module, _ := ctx.ModuleFromName(src) - fg, _ := module.(android.Bp2buildAidlLibrary) + if fg, ok := android.ToFileGroupAsLibrary(ctx, src); ok && + fg.ShouldConvertToAidlLibrary(ctx) { aidlLibraries.Add(&bazel.Label{ Label: fg.GetAidlLibraryLabel(ctx), }) diff --git a/cc/proto.go b/cc/proto.go index 8e6d5ed5f..cf5ed04f2 100644 --- a/cc/proto.go +++ b/cc/proto.go @@ -178,7 +178,7 @@ func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs baze var ret bp2buildProtoDeps protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs) - if !ok { + if !ok || protoInfo.Proto_libs.IsEmpty() { return ret } @@ -201,9 +201,8 @@ func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs baze 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}}) + protoAttrs.Deps.SetValue(protoInfo.Proto_libs) name := m.Name() + suffix