diff --git a/android/filegroup.go b/android/filegroup.go index fc6850eb5..e2074127e 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -63,7 +63,10 @@ func FilegroupBp2Build(ctx TopDownMutatorContext) { Srcs: srcs, } - props := bazel.BazelTargetModuleProperties{Rule_class: "filegroup"} + props := bazel.BazelTargetModuleProperties{ + Rule_class: "filegroup", + Bzl_load_location: "//build/bazel/rules:filegroup.bzl", + } ctx.CreateBazelTargetModule(BazelFileGroupFactory, fg.Name(), props, attrs) } diff --git a/bazel/properties.go b/bazel/properties.go index b2d68da52..951081cc3 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -137,6 +137,39 @@ func SubtractStrings(haystack []string, needle []string) []string { return strings } +// Map a function over all labels in a LabelList. +func MapLabelList(mapOver LabelList, mapFn func(string) string) LabelList { + var includes []Label + for _, inc := range mapOver.Includes { + mappedLabel := Label{Label: mapFn(inc.Label), OriginalModuleName: inc.OriginalModuleName} + includes = append(includes, mappedLabel) + } + // mapFn is not applied over excludes, but they are propagated as-is. + return LabelList{Includes: includes, Excludes: mapOver.Excludes} +} + +// Map a function over all Labels in a LabelListAttribute +func MapLabelListAttribute(mapOver LabelListAttribute, mapFn func(string) string) LabelListAttribute { + var result LabelListAttribute + + result.Value = MapLabelList(mapOver.Value, mapFn) + + for arch := range PlatformArchMap { + result.SetValueForArch(arch, MapLabelList(mapOver.GetValueForArch(arch), mapFn)) + } + + for os := range PlatformOsMap { + result.SetOsValueForTarget(os, MapLabelList(mapOver.GetOsValueForTarget(os), mapFn)) + + // TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues) + for _, arch := range AllArches { + result.SetOsArchValueForTarget(os, arch, MapLabelList(mapOver.GetOsArchValueForTarget(os, arch), mapFn)) + } + } + + return result +} + // Return all needles in a given haystack, where needleFn is true for needles. func FilterLabelList(haystack LabelList, needleFn func(string) bool) LabelList { var includes []Label @@ -145,6 +178,7 @@ func FilterLabelList(haystack LabelList, needleFn func(string) bool) LabelList { includes = append(includes, inc) } } + // needleFn is not applied over excludes, but they are propagated as-is. return LabelList{Includes: includes, Excludes: haystack.Excludes} } diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index b87d71330..c8ae031a2 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -47,6 +47,7 @@ func runCcLibraryTestCase(t *testing.T, tc bp2buildTestCase) { func registerCcLibraryModuleTypes(ctx android.RegistrationContext) { cc.RegisterCCBuildComponents(ctx) + ctx.RegisterModuleType("filegroup", android.FileGroupFactory) ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory) ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) @@ -535,6 +536,139 @@ cc_library_static { name: "android_dep_for_shared" } }) } +func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) { + runCcLibraryTestCase(t, bp2buildTestCase{ + description: "cc_library shared/static props with c/cpp/s mixed sources", + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build}, + dir: "foo/bar", + filesystem: map[string]string{ + "foo/bar/both_source.cpp": "", + "foo/bar/both_source.cc": "", + "foo/bar/both_source.c": "", + "foo/bar/both_source.s": "", + "foo/bar/both_source.S": "", + "foo/bar/shared_source.cpp": "", + "foo/bar/shared_source.cc": "", + "foo/bar/shared_source.c": "", + "foo/bar/shared_source.s": "", + "foo/bar/shared_source.S": "", + "foo/bar/static_source.cpp": "", + "foo/bar/static_source.cc": "", + "foo/bar/static_source.c": "", + "foo/bar/static_source.s": "", + "foo/bar/static_source.S": "", + "foo/bar/Android.bp": ` +cc_library { + name: "a", + srcs: [ + "both_source.cpp", + "both_source.cc", + "both_source.c", + "both_source.s", + "both_source.S", + ":both_filegroup", + ], + static: { + srcs: [ + "static_source.cpp", + "static_source.cc", + "static_source.c", + "static_source.s", + "static_source.S", + ":static_filegroup", + ], + }, + shared: { + srcs: [ + "shared_source.cpp", + "shared_source.cc", + "shared_source.c", + "shared_source.s", + "shared_source.S", + ":shared_filegroup", + ], + }, + bazel_module: { bp2build_available: true }, +} + +filegroup { + name: "both_filegroup", + srcs: [ + // Not relevant, handled by filegroup macro + ], +} + +filegroup { + name: "shared_filegroup", + srcs: [ + // Not relevant, handled by filegroup macro + ], +} + +filegroup { + name: "static_filegroup", + srcs: [ + // Not relevant, handled by filegroup macro + ], +} +`, + }, + blueprint: soongCcLibraryPreamble, + expectedBazelTargets: []string{`cc_library( + name = "a", + copts = [ + "-Ifoo/bar", + "-I$(BINDIR)/foo/bar", + ], + shared_srcs = [ + ":shared_filegroup_cpp_srcs", + "shared_source.cc", + "shared_source.cpp", + ], + shared_srcs_as = [ + "shared_source.s", + "shared_source.S", + ":shared_filegroup_as_srcs", + ], + shared_srcs_c = [ + "shared_source.c", + ":shared_filegroup_c_srcs", + ], + srcs = [ + ":both_filegroup_cpp_srcs", + "both_source.cc", + "both_source.cpp", + ], + srcs_as = [ + "both_source.s", + "both_source.S", + ":both_filegroup_as_srcs", + ], + srcs_c = [ + "both_source.c", + ":both_filegroup_c_srcs", + ], + static_srcs = [ + ":static_filegroup_cpp_srcs", + "static_source.cc", + "static_source.cpp", + ], + static_srcs_as = [ + "static_source.s", + "static_source.S", + ":static_filegroup_as_srcs", + ], + static_srcs_c = [ + "static_source.c", + ":static_filegroup_c_srcs", + ], +)`}, + }) +} + func TestCcLibraryNonConfiguredVersionScript(t *testing.T) { runCcLibraryTestCase(t, bp2buildTestCase{ description: "cc_library non-configured version script", diff --git a/cc/bp2build.go b/cc/bp2build.go index fed993670..a156d5444 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -14,6 +14,7 @@ package cc import ( + "fmt" "path/filepath" "strings" @@ -164,13 +165,86 @@ func depsBp2BuildMutator(ctx android.BottomUpMutatorContext) { // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties -- // properties which apply to either the shared or static version of a cc_library module. type staticOrSharedAttributes struct { - copts bazel.StringListAttribute - srcs bazel.LabelListAttribute + srcs bazel.LabelListAttribute + srcs_c bazel.LabelListAttribute + srcs_as bazel.LabelListAttribute + + copts bazel.StringListAttribute + staticDeps bazel.LabelListAttribute dynamicDeps bazel.LabelListAttribute wholeArchiveDeps bazel.LabelListAttribute } +func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) (cppSrcs, cSrcs, asSrcs bazel.LabelListAttribute) { + // Branch srcs into three language-specific groups. + // 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. + // TODO(b/190006308): Handle language detection of sources in a Bazel rule. + isCSrcOrFilegroup := func(s string) bool { + return strings.HasSuffix(s, ".c") || strings.HasSuffix(s, "_c_srcs") + } + + isAsmSrcOrFilegroup := func(s string) bool { + return strings.HasSuffix(s, ".S") || strings.HasSuffix(s, ".s") || strings.HasSuffix(s, "_as_srcs") + } + + // Check that a module is a filegroup type named