bp2build: split as, c, and cpp srcs for cc_library
This CL adds support for cc_library to correctly split c, as and cpp
srcs in shared/static nested props, as well as splitting
the *filegroup* deps in those props, where each filegroup is expanded
into its own c, cpp and as srcs filegroups. This ensures that the
correct sources go into cc_library_static's underlying cc_libraries for
c, cpp and as sources respectively.
See the bp2build conversion test for a better visualization.
Bug: 183064430
Test: TH
Change-Id: I29add5140672d042adff65527d8b65f4a5f0a05b
diff --git a/android/filegroup.go b/android/filegroup.go
index fc6850e..e207412 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -63,7 +63,10 @@
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 b2d68da..951081c 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -137,6 +137,39 @@
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 @@
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 b87d713..c8ae031 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -47,6 +47,7 @@
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 @@
})
}
+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 fed9936..a156d54 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -14,6 +14,7 @@
package cc
import (
+ "fmt"
"path/filepath"
"strings"
@@ -164,13 +165,86 @@
// 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 <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.
+ panic(fmt.Errorf("%s is not a valid Bazel label for a filegroup", fullLabel))
+ } else {
+ return m.Name() == labelParts[len(labelParts)-1]
+ }
+ }
+
+ // Convert the filegroup dependencies into the extension-specific filegroups
+ // filtered in the filegroup.bzl macro.
+ cppFilegroup := func(label string) string {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if isFilegroupNamed(m, label) {
+ label = label + "_cpp_srcs"
+ return
+ }
+ })
+ return label
+ }
+ cFilegroup := func(label string) string {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if isFilegroupNamed(m, label) {
+ label = label + "_c_srcs"
+ return
+ }
+ })
+ return label
+ }
+ asFilegroup := func(label string) string {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if isFilegroupNamed(m, label) {
+ label = label + "_as_srcs"
+ return
+ }
+ })
+ return label
+ }
+
+ cSrcs = bazel.MapLabelListAttribute(srcs, cFilegroup)
+ cSrcs = bazel.FilterLabelListAttribute(cSrcs, isCSrcOrFilegroup)
+
+ asSrcs = bazel.MapLabelListAttribute(srcs, asFilegroup)
+ asSrcs = bazel.FilterLabelListAttribute(asSrcs, isAsmSrcOrFilegroup)
+
+ cppSrcs = bazel.MapLabelListAttribute(srcs, cppFilegroup)
+ cppSrcs = bazel.SubtractBazelLabelListAttribute(cppSrcs, cSrcs)
+ cppSrcs = bazel.SubtractBazelLabelListAttribute(cppSrcs, asSrcs)
+ return
+}
+
// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
func bp2BuildParseSharedProps(ctx android.TopDownMutatorContext, module *Module) staticOrSharedAttributes {
lib, ok := module.compiler.(*libraryDecorator)
@@ -265,6 +339,11 @@
}
}
+ cppSrcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, attrs.srcs)
+ attrs.srcs = cppSrcs
+ attrs.srcs_c = cSrcs
+ attrs.srcs_as = asSrcs
+
return attrs
}
@@ -528,20 +607,8 @@
}
}
- // 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/): Handle language detection of sources in a Bazel rule.
- isCSrc := func(s string) bool {
- return strings.HasSuffix(s, ".c")
- }
- isAsmSrc := func(s string) bool {
- return strings.HasSuffix(s, ".S") || strings.HasSuffix(s, ".s")
- }
- cSrcs := bazel.FilterLabelListAttribute(srcs, isCSrc)
- asSrcs := bazel.FilterLabelListAttribute(srcs, isAsmSrc)
- srcs = bazel.SubtractBazelLabelListAttribute(srcs, cSrcs)
- srcs = bazel.SubtractBazelLabelListAttribute(srcs, asSrcs)
+ srcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, srcs)
+
return compilerAttributes{
copts: copts,
srcs: srcs,
diff --git a/cc/library.go b/cc/library.go
index 5e70c51..cdac01c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -221,25 +221,29 @@
// For bp2build conversion.
type bazelCcLibraryAttributes struct {
// Attributes pertaining to both static and shared variants.
- Srcs bazel.LabelListAttribute
+ Srcs bazel.LabelListAttribute
+ Srcs_c bazel.LabelListAttribute
+ Srcs_as bazel.LabelListAttribute
+
+ Copts bazel.StringListAttribute
+ Cppflags bazel.StringListAttribute
+ Conlyflags bazel.StringListAttribute
+ Asflags bazel.StringListAttribute
+
Hdrs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
- Copts bazel.StringListAttribute
Includes bazel.StringListAttribute
Linkopts bazel.StringListAttribute
- Cppflags bazel.StringListAttribute
- Srcs_c bazel.LabelListAttribute
- Conlyflags bazel.StringListAttribute
- Srcs_as bazel.LabelListAttribute
- Asflags bazel.StringListAttribute
-
// Attributes pertaining to shared variant.
- Shared_copts bazel.StringListAttribute
- Shared_srcs bazel.LabelListAttribute
+ Shared_srcs bazel.LabelListAttribute
+ Shared_srcs_c bazel.LabelListAttribute
+ Shared_srcs_as bazel.LabelListAttribute
+ Shared_copts bazel.StringListAttribute
+
Exported_deps_for_shared bazel.LabelListAttribute
Static_deps_for_shared bazel.LabelListAttribute
Dynamic_deps_for_shared bazel.LabelListAttribute
@@ -248,8 +252,11 @@
Version_script bazel.LabelAttribute
// Attributes pertaining to static variant.
- Static_copts bazel.StringListAttribute
- Static_srcs bazel.LabelListAttribute
+ Static_srcs bazel.LabelListAttribute
+ Static_srcs_c bazel.LabelListAttribute
+ Static_srcs_as bazel.LabelListAttribute
+ Static_copts bazel.StringListAttribute
+
Exported_deps_for_static bazel.LabelListAttribute
Static_deps_for_static bazel.LabelListAttribute
Dynamic_deps_for_static bazel.LabelListAttribute
@@ -302,29 +309,35 @@
srcs.Append(compilerAttrs.srcs)
attrs := &bazelCcLibraryAttributes{
- Srcs: srcs,
+ Srcs: srcs,
+ Srcs_c: compilerAttrs.cSrcs,
+ Srcs_as: compilerAttrs.asSrcs,
+
+ Copts: compilerAttrs.copts,
+ Cppflags: compilerAttrs.cppFlags,
+ Conlyflags: compilerAttrs.conlyFlags,
+ Asflags: compilerAttrs.asFlags,
+
Implementation_deps: linkerAttrs.deps,
Deps: linkerAttrs.exportedDeps,
Dynamic_deps: linkerAttrs.dynamicDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
- Copts: compilerAttrs.copts,
Includes: exportedIncludes,
Linkopts: linkerAttrs.linkopts,
- Cppflags: compilerAttrs.cppFlags,
- Srcs_c: compilerAttrs.cSrcs,
- Conlyflags: compilerAttrs.conlyFlags,
- Srcs_as: compilerAttrs.asSrcs,
- Asflags: compilerAttrs.asFlags,
- Shared_copts: sharedAttrs.copts,
Shared_srcs: sharedAttrs.srcs,
+ Shared_srcs_c: sharedAttrs.srcs_c,
+ Shared_srcs_as: sharedAttrs.srcs_as,
+ Shared_copts: sharedAttrs.copts,
Static_deps_for_shared: sharedAttrs.staticDeps,
Whole_archive_deps_for_shared: sharedAttrs.wholeArchiveDeps,
Dynamic_deps_for_shared: sharedAttrs.dynamicDeps,
Version_script: linkerAttrs.versionScript,
- Static_copts: staticAttrs.copts,
Static_srcs: staticAttrs.srcs,
+ Static_srcs_c: staticAttrs.srcs_c,
+ Static_srcs_as: staticAttrs.srcs_as,
+ Static_copts: staticAttrs.copts,
Static_deps_for_static: staticAttrs.staticDeps,
Whole_archive_deps_for_static: staticAttrs.wholeArchiveDeps,
Dynamic_deps_for_static: staticAttrs.dynamicDeps,