diff --git a/android/bazel.go b/android/bazel.go index b2170be79..4a02b44de 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -174,6 +174,15 @@ var ( "liblinker_debuggerd_stub", // ruperts@, cc_library_static, depends on //system/libbase "libbionic_tests_headers_posix", // ruperts@, cc_library_static "libc_dns", // ruperts@, cc_library_static + + // List of all full_cc_libraries in //bionic, with their immediate failures + "libc", // jingwen@, cc_library, depends on //external/gwp_asan + "libc_malloc_debug", // jingwen@, cc_library, fatal error: 'assert.h' file not found + "libc_malloc_hooks", // jingwen@, cc_library, fatal error: 'errno.h' file not found + "libdl", // jingwen@, cc_library, ld.lld: error: no input files + "libm", // jingwen@, cc_library, fatal error: 'freebsd-compat.h' file not found + "libseccomp_policy", // jingwen@, cc_library, fatal error: 'seccomp_policy.h' file not found + "libstdc++", // jingwen@, cc_library, depends on //external/gwp_asan } // Used for quicker lookups diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 5ac69240a..5a73666b1 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -326,15 +326,20 @@ func (context *bazelContext) workspaceFileContents() []byte { # This file is generated by soong_build. Do not edit. local_repository( name = "sourceroot", - path = "%s", + path = "%[1]s", ) local_repository( name = "rules_cc", - path = "%s/build/bazel/rules_cc", + path = "%[1]s/build/bazel/rules_cc", +) + +local_repository( + name = "bazel_skylib", + path = "%[1]s/build/bazel/bazel_skylib", ) ` - return []byte(fmt.Sprintf(formatString, context.workspaceDir, context.workspaceDir)) + return []byte(fmt.Sprintf(formatString, context.workspaceDir)) } func (context *bazelContext) mainBzlFileContents() []byte { diff --git a/android/paths.go b/android/paths.go index ba1ab1138..37b04ddfc 100644 --- a/android/paths.go +++ b/android/paths.go @@ -421,6 +421,9 @@ func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) b // bazel-compatible labels. Properties passed as the paths or excludes argument must have been // annotated with struct tag `android:"path"` so that dependencies on other modules will have // already been handled by the path_properties mutator. +// +// With expanded globs, we can catch package boundaries problem instead of +// silently failing to potentially missing files from Bazel's globs. func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList { return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil)) } @@ -431,6 +434,9 @@ func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) baze // passed as the paths or excludes argument must have been annotated with struct tag // `android:"path"` so that dependencies on other modules will have already been handled by the // path_properties mutator. +// +// With expanded globs, we can catch package boundaries problem instead of +// silently failing to potentially missing files from Bazel's globs. func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList { excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil)) excluded := make([]string, 0, len(excludeLabels.Includes)) diff --git a/bazel/properties.go b/bazel/properties.go index 148386f6a..4bb239101 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -16,6 +16,7 @@ package bazel import ( "fmt" + "path/filepath" "regexp" "sort" ) @@ -47,6 +48,57 @@ type LabelList struct { Excludes []Label } +// GlobsInDir returns a list of glob expressions for a list of extensions +// (optionally recursive) within a directory. +func GlobsInDir(dir string, recursive bool, extensions []string) []string { + globs := []string{} + + globInfix := "" + if dir == "." { + if recursive { + // e.g "**/*.h" + globInfix = "**/" + } // else e.g. "*.h" + for _, ext := range extensions { + globs = append(globs, globInfix+"*"+ext) + } + } else { + if recursive { + // e.g. "foo/bar/**/*.h" + dir += "/**" + } // else e.g. "foo/bar/*.h" + for _, ext := range extensions { + globs = append(globs, dir+"/*"+ext) + } + } + return globs +} + +// LooseHdrsGlobs returns the list of non-recursive header globs for each parent directory of +// each source file in this LabelList's Includes. +func (ll *LabelList) LooseHdrsGlobs(exts []string) []string { + var globs []string + for _, parentDir := range ll.uniqueParentDirectories() { + globs = append(globs, + GlobsInDir(parentDir, false, exts)...) + } + return globs +} + +// uniqueParentDirectories returns a list of the unique parent directories for +// all files in ll.Includes. +func (ll *LabelList) uniqueParentDirectories() []string { + dirMap := map[string]bool{} + for _, label := range ll.Includes { + dirMap[filepath.Dir(label.Label)] = true + } + dirs := []string{} + for dir := range dirMap { + dirs = append(dirs, dir) + } + return dirs +} + // 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 { @@ -224,6 +276,26 @@ func MakeLabelListAttribute(value LabelList) LabelListAttribute { return LabelListAttribute{Value: UniqueBazelLabelList(value)} } +// Append appends all values, including os and arch specific ones, from another +// LabelListAttribute to this LabelListAttribute. +func (attrs *LabelListAttribute) Append(other LabelListAttribute) { + for arch := range PlatformArchMap { + this := attrs.GetValueForArch(arch) + that := other.GetValueForArch(arch) + this.Append(that) + attrs.SetValueForArch(arch, this) + } + + for os := range PlatformOsMap { + this := attrs.GetValueForOS(os) + that := other.GetValueForOS(os) + this.Append(that) + attrs.SetValueForOS(os, this) + } + + attrs.Value.Append(other.Value) +} + // HasArchSpecificValues returns true if the attribute contains // architecture-specific label_list values. func (attrs LabelListAttribute) HasConfigurableValues() bool { diff --git a/bp2build/Android.bp b/bp2build/Android.bp index cc616f23e..d2a872976 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -26,6 +26,7 @@ bootstrap_go_package { testSrcs: [ "build_conversion_test.go", "bzl_conversion_test.go", + "cc_library_conversion_test.go", "cc_library_headers_conversion_test.go", "cc_library_static_conversion_test.go", "cc_object_conversion_test.go", diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go index dd14c7dbb..16e7278da 100644 --- a/bp2build/build_conversion.go +++ b/bp2build/build_conversion.go @@ -374,16 +374,9 @@ func prettyPrint(propertyValue reflect.Value, indent int) (string, error) { // value>)" to set the default value of unset attributes. In the cases // where the bp2build converter didn't set the default value within the // mutator when creating the BazelTargetModule, this would be a zero - // value. For those cases, we return a non-surprising default value so - // generated BUILD files are syntactically correct. - switch propertyValue.Kind() { - case reflect.Slice: - return "[]", nil - case reflect.Map: - return "{}", nil - default: - return "", nil - } + // value. For those cases, we return an empty string so we don't + // unnecessarily generate empty values. + return "", nil } var ret string @@ -397,6 +390,10 @@ func prettyPrint(propertyValue reflect.Value, indent int) (string, error) { case reflect.Ptr: return prettyPrint(propertyValue.Elem(), indent) case reflect.Slice: + if propertyValue.Len() == 0 { + return "", nil + } + ret = "[\n" for i := 0; i < propertyValue.Len(); i++ { indexedValue, err := prettyPrint(propertyValue.Index(i), indent+1) diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go new file mode 100644 index 000000000..6a148a8a3 --- /dev/null +++ b/bp2build/cc_library_conversion_test.go @@ -0,0 +1,303 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bp2build + +import ( + "android/soong/android" + "android/soong/cc" + "strings" + "testing" +) + +const ( + // See cc/testing.go for more context + soongCcLibraryPreamble = ` +cc_defaults { + name: "linux_bionic_supported", +} + +toolchain_library { + name: "libclang_rt.builtins-x86_64-android", + defaults: ["linux_bionic_supported"], + vendor_available: true, + vendor_ramdisk_available: true, + product_available: true, + recovery_available: true, + native_bridge_supported: true, + src: "", +}` +) + +func TestCcLibraryBp2Build(t *testing.T) { + testCases := []struct { + description string + moduleTypeUnderTest string + moduleTypeUnderTestFactory android.ModuleFactory + moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext) + bp string + expectedBazelTargets []string + filesystem map[string]string + dir string + }{ + { + description: "cc_library - simple example", + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + filesystem: map[string]string{ + "android.cpp": "", + "darwin.cpp": "", + // Refer to cc.headerExts for the supported header extensions in Soong. + "header.h": "", + "header.hh": "", + "header.hpp": "", + "header.hxx": "", + "header.h++": "", + "header.inl": "", + "header.inc": "", + "header.ipp": "", + "header.h.generic": "", + "impl.cpp": "", + "linux.cpp": "", + "x86.cpp": "", + "x86_64.cpp": "", + "foo-dir/a.h": "", + }, + bp: soongCcLibraryPreamble + ` +cc_library_headers { name: "some-headers" } +cc_library { + name: "foo-lib", + srcs: ["impl.cpp"], + cflags: ["-Wall"], + header_libs: ["some-headers"], + export_include_dirs: ["foo-dir"], + ldflags: ["-Wl,--exclude-libs=bar.a"], + arch: { + x86: { + ldflags: ["-Wl,--exclude-libs=baz.a"], + srcs: ["x86.cpp"], + }, + x86_64: { + ldflags: ["-Wl,--exclude-libs=qux.a"], + srcs: ["x86_64.cpp"], + }, + }, + target: { + android: { + srcs: ["android.cpp"], + }, + linux_glibc: { + srcs: ["linux.cpp"], + }, + darwin: { + srcs: ["darwin.cpp"], + }, + }, +} +`, + expectedBazelTargets: []string{`cc_library( + name = "foo-lib", + copts = [ + "-Wall", + ], + deps = [ + ":some-headers", + ], + hdrs = [ + "header.h", + "header.hh", + "header.hpp", + "header.hxx", + "header.h++", + "header.inl", + "header.inc", + "header.ipp", + "header.h.generic", + "foo-dir/a.h", + ], + includes = [ + "foo-dir", + ], + linkopts = [ + "-Wl,--exclude-libs=bar.a", + ] + select({ + "//build/bazel/platforms/arch:x86": [ + "-Wl,--exclude-libs=baz.a", + ], + "//build/bazel/platforms/arch:x86_64": [ + "-Wl,--exclude-libs=qux.a", + ], + "//conditions:default": [], + }), + srcs = [ + "impl.cpp", + ] + select({ + "//build/bazel/platforms/arch:x86": [ + "x86.cpp", + ], + "//build/bazel/platforms/arch:x86_64": [ + "x86_64.cpp", + ], + "//conditions:default": [], + }) + select({ + "//build/bazel/platforms/os:android": [ + "android.cpp", + ], + "//build/bazel/platforms/os:darwin": [ + "darwin.cpp", + ], + "//build/bazel/platforms/os:linux": [ + "linux.cpp", + ], + "//conditions:default": [], + }), +)`}, + }, + { + description: "cc_library - trimmed example of //bionic/linker:ld-android", + moduleTypeUnderTest: "cc_library", + moduleTypeUnderTestFactory: cc.LibraryFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, + filesystem: map[string]string{ + "ld-android.cpp": "", + "linked_list.h": "", + "linker.h": "", + "linker_block_allocator.h": "", + "linker_cfi.h": "", + }, + bp: soongCcLibraryPreamble + ` +cc_library_headers { name: "libc_headers" } +cc_library { + name: "fake-ld-android", + srcs: ["ld_android.cpp"], + cflags: [ + "-Wall", + "-Wextra", + "-Wunused", + "-Werror", + ], + header_libs: ["libc_headers"], + ldflags: [ + "-Wl,--exclude-libs=libgcc.a", + "-Wl,--exclude-libs=libgcc_stripped.a", + "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a", + "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a", + "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a", + "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a", + ], + arch: { + x86: { + ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"], + }, + x86_64: { + ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"], + }, + }, +} +`, + expectedBazelTargets: []string{`cc_library( + name = "fake-ld-android", + copts = [ + "-Wall", + "-Wextra", + "-Wunused", + "-Werror", + ], + deps = [ + ":libc_headers", + ], + hdrs = [ + "linked_list.h", + "linker.h", + "linker_block_allocator.h", + "linker_cfi.h", + ], + linkopts = [ + "-Wl,--exclude-libs=libgcc.a", + "-Wl,--exclude-libs=libgcc_stripped.a", + "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a", + "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a", + "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a", + "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a", + ] + select({ + "//build/bazel/platforms/arch:x86": [ + "-Wl,--exclude-libs=libgcc_eh.a", + ], + "//build/bazel/platforms/arch:x86_64": [ + "-Wl,--exclude-libs=libgcc_eh.a", + ], + "//conditions:default": [], + }), + srcs = [ + "ld_android.cpp", + ], +)`}, + }, + } + + dir := "." + for _, testCase := range testCases { + filesystem := make(map[string][]byte) + toParse := []string{ + "Android.bp", + } + for f, content := range testCase.filesystem { + if strings.HasSuffix(f, "Android.bp") { + toParse = append(toParse, f) + } + filesystem[f] = []byte(content) + } + config := android.TestConfig(buildDir, nil, testCase.bp, filesystem) + ctx := android.NewTestContext(config) + + cc.RegisterCCBuildComponents(ctx) + ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory) + ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) + ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory) + ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator) + ctx.RegisterBp2BuildConfig(bp2buildConfig) // TODO(jingwen): make this the default for all tests + ctx.RegisterForBazelConversion() + + _, errs := ctx.ParseFileList(dir, toParse) + if Errored(t, testCase.description, errs) { + continue + } + _, errs = ctx.ResolveDependencies(config) + if Errored(t, testCase.description, errs) { + continue + } + + checkDir := dir + if testCase.dir != "" { + checkDir = testCase.dir + } + codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) + bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir) + if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { + t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount) + } else { + for i, target := range bazelTargets { + if w, g := testCase.expectedBazelTargets[i], target.content; w != g { + t.Errorf( + "%s: Expected generated Bazel target to be '%s', got '%s'", + testCase.description, + w, + g, + ) + } + } + } + } +} diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go index 74226aeb4..655218d29 100644 --- a/bp2build/cc_library_headers_conversion_test.go +++ b/bp2build/cc_library_headers_conversion_test.go @@ -23,7 +23,7 @@ import ( const ( // See cc/testing.go for more context - soongCcLibraryPreamble = ` + soongCcLibraryHeadersPreamble = ` cc_defaults { name: "linux_bionic_supported", } @@ -98,7 +98,7 @@ func TestCcLibraryHeadersBp2Build(t *testing.T) { "arch_x86_exported_include_dir/b.h": "", "arch_x86_64_exported_include_dir/c.h": "", }, - bp: soongCcLibraryPreamble + ` + bp: soongCcLibraryHeadersPreamble + ` cc_library_headers { name: "lib-1", export_include_dirs: ["lib-1"], @@ -278,7 +278,7 @@ cc_library_headers { name = "exported-lib", )`, `cc_library_headers( name = "foo_headers", - deps = [] + select({ + deps = select({ "//build/bazel/platforms/os:android": [ ":android-lib", ":exported-lib", diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index ef528e96b..a6a002818 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -194,6 +194,8 @@ cc_library_static { ":whole_static_lib_2", ], hdrs = [ + "implicit_include_1.h", + "implicit_include_2.h", "export_include_dir_1/export_include_dir_1_a.h", "export_include_dir_1/export_include_dir_1_b.h", "export_include_dir_2/export_include_dir_2_a.h", @@ -212,8 +214,6 @@ cc_library_static { srcs = [ "foo_static1.cc", "foo_static2.cc", - "implicit_include_1.h", - "implicit_include_2.h", "include_dir_1/include_dir_1_a.h", "include_dir_1/include_dir_1_b.h", "include_dir_2/include_dir_2_a.h", @@ -222,50 +222,68 @@ cc_library_static { "local_include_dir_1/local_include_dir_1_b.h", "local_include_dir_2/local_include_dir_2_a.h", "local_include_dir_2/local_include_dir_2_b.h", + "implicit_include_1.h", + "implicit_include_2.h", ], )`, `cc_library_static( name = "static_lib_1", + hdrs = [ + "implicit_include_1.h", + "implicit_include_2.h", + ], includes = [ ".", ], linkstatic = True, srcs = [ + "static_lib_1.cc", "implicit_include_1.h", "implicit_include_2.h", - "static_lib_1.cc", ], )`, `cc_library_static( name = "static_lib_2", + hdrs = [ + "implicit_include_1.h", + "implicit_include_2.h", + ], includes = [ ".", ], linkstatic = True, srcs = [ + "static_lib_2.cc", "implicit_include_1.h", "implicit_include_2.h", - "static_lib_2.cc", ], )`, `cc_library_static( name = "whole_static_lib_1", + hdrs = [ + "implicit_include_1.h", + "implicit_include_2.h", + ], includes = [ ".", ], linkstatic = True, srcs = [ + "whole_static_lib_1.cc", "implicit_include_1.h", "implicit_include_2.h", - "whole_static_lib_1.cc", ], )`, `cc_library_static( name = "whole_static_lib_2", + hdrs = [ + "implicit_include_1.h", + "implicit_include_2.h", + ], includes = [ ".", ], linkstatic = True, srcs = [ + "whole_static_lib_2.cc", "implicit_include_1.h", "implicit_include_2.h", - "whole_static_lib_2.cc", ], )`}, }, diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go index 4f3babe87..840bf4299 100644 --- a/bp2build/cc_object_conversion_test.go +++ b/bp2build/cc_object_conversion_test.go @@ -52,7 +52,6 @@ func TestCcObjectBp2Build(t *testing.T) { "-Werror", ], srcs: [ - "a/b/*.h", "a/b/*.c" ], exclude_srcs: ["a/b/exclude.c"], @@ -68,14 +67,16 @@ func TestCcObjectBp2Build(t *testing.T) { "-Wall", "-Werror", ], + hdrs = [ + "a/b/bar.h", + "a/b/foo.h", + ], local_include_dirs = [ "include", ".", ], srcs = [ - "a/b/bar.h", "a/b/c.c", - "a/b/foo.h", ], )`, }, diff --git a/bp2build/configurability.go b/bp2build/configurability.go index b2b3379fc..97729df51 100644 --- a/bp2build/configurability.go +++ b/bp2build/configurability.go @@ -69,20 +69,26 @@ func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) { return ret, err } - // Create the selects for arch specific values. - selectMap, err := prettyPrintSelectMap(archSelects, "[]", indent) + // Convenience function to append selects components to an attribute value. + appendSelects := func(selectsData selects, defaultValue, s string) (string, error) { + selectMap, err := prettyPrintSelectMap(selectsData, defaultValue, indent) + if err != nil { + return "", err + } + if s != "" && selectMap != "" { + s += " + " + } + s += selectMap + + return s, nil + } + + ret, err = appendSelects(archSelects, "[]", ret) if err != nil { return "", err } - ret += selectMap - - // Create the selects for target os specific values. - selectMap, err = prettyPrintSelectMap(osSelects, "[]", indent) - if err != nil { - return "", err - } - ret += selectMap + ret, err = appendSelects(osSelects, "[]", ret) return ret, err } @@ -113,7 +119,7 @@ func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue strin } // Create the map. - ret := " + select({\n" + ret := "select({\n" ret += selects // default condition comes last. ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue) diff --git a/cc/bp2build.go b/cc/bp2build.go index cffeb2474..e7e4aa8b0 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -59,72 +59,95 @@ func depsBp2BuildMutator(ctx android.BottomUpMutatorContext) { ctx.AddDependency(module, nil, android.SortedUniqueStrings(allDeps)...) } -// bp2buildParseCflags creates a label list attribute containing the cflags of a module, including -func bp2BuildParseCflags(ctx android.TopDownMutatorContext, module *Module) bazel.StringListAttribute { - var ret bazel.StringListAttribute +// bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes. +func bp2BuildParseCompilerProps( + ctx android.TopDownMutatorContext, + module *Module) ( + copts bazel.StringListAttribute, + srcs bazel.LabelListAttribute, + hdrs bazel.LabelListAttribute) { + + hdrsAndSrcs := func(baseCompilerProps *BaseCompilerProperties) (bazel.LabelList, bazel.LabelList) { + srcsList := android.BazelLabelForModuleSrcExcludes( + ctx, baseCompilerProps.Srcs, baseCompilerProps.Exclude_srcs) + hdrsList := android.BazelLabelForModuleSrc(ctx, srcsList.LooseHdrsGlobs(headerExts)) + return hdrsList, srcsList + } + for _, props := range module.compiler.compilerProps() { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { - ret.Value = baseCompilerProps.Cflags + hdrs.Value, srcs.Value = hdrsAndSrcs(baseCompilerProps) + copts.Value = baseCompilerProps.Cflags break } } for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { - ret.SetValueForArch(arch.Name, baseCompilerProps.Cflags) + hdrsList, srcsList := hdrsAndSrcs(baseCompilerProps) + hdrs.SetValueForArch(arch.Name, bazel.SubtractBazelLabelList(hdrsList, hdrs.Value)) + srcs.SetValueForArch(arch.Name, srcsList) + copts.SetValueForArch(arch.Name, baseCompilerProps.Cflags) } } for os, props := range module.GetTargetProperties(&BaseCompilerProperties{}) { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { - ret.SetValueForOS(os.Name, baseCompilerProps.Cflags) + hdrsList, srcsList := hdrsAndSrcs(baseCompilerProps) + hdrs.SetValueForOS(os.Name, bazel.SubtractBazelLabelList(hdrsList, hdrs.Value)) + srcs.SetValueForOS(os.Name, srcsList) + copts.SetValueForOS(os.Name, baseCompilerProps.Cflags) } } - return ret + return copts, srcs, hdrs } -// bp2BuildParseHeaderLibs creates a label list attribute containing the header library deps of a module, including +// bp2BuildParseLinkerProps creates a label list attribute containing the header library deps of a module, including // configurable attribute values. -func bp2BuildParseHeaderLibs(ctx android.TopDownMutatorContext, module *Module) bazel.LabelListAttribute { - var ret bazel.LabelListAttribute +func bp2BuildParseLinkerProps( + ctx android.TopDownMutatorContext, module *Module) (bazel.LabelListAttribute, bazel.StringListAttribute) { + + var deps bazel.LabelListAttribute + var linkopts bazel.StringListAttribute + for _, linkerProps := range module.linker.linkerProps() { if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok { libs := baseLinkerProps.Header_libs libs = append(libs, baseLinkerProps.Export_header_lib_headers...) - ret = bazel.MakeLabelListAttribute( + deps = bazel.MakeLabelListAttribute( android.BazelLabelForModuleDeps(ctx, android.SortedUniqueStrings(libs))) + linkopts.Value = baseLinkerProps.Ldflags break } } + for arch, p := range module.GetArchProperties(&BaseLinkerProperties{}) { + if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok { + libs := baseLinkerProps.Header_libs + libs = append(libs, baseLinkerProps.Export_header_lib_headers...) + libs = android.SortedUniqueStrings(libs) + deps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, libs)) + linkopts.SetValueForArch(arch.Name, baseLinkerProps.Ldflags) + } + } + for os, p := range module.GetTargetProperties(&BaseLinkerProperties{}) { if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok { libs := baseLinkerProps.Header_libs libs = append(libs, baseLinkerProps.Export_header_lib_headers...) libs = android.SortedUniqueStrings(libs) - ret.SetValueForOS(os.Name, android.BazelLabelForModuleDeps(ctx, libs)) + deps.SetValueForOS(os.Name, android.BazelLabelForModuleDeps(ctx, libs)) + linkopts.SetValueForOS(os.Name, baseLinkerProps.Ldflags) } } - return ret + return deps, linkopts } func bp2BuildListHeadersInDir(ctx android.TopDownMutatorContext, includeDir string) bazel.LabelList { - var globInfix string - - if includeDir == "." { - globInfix = "" - } else { - globInfix = "/**" - } - - var includeDirGlobs []string - includeDirGlobs = append(includeDirGlobs, includeDir+globInfix+"/*.h") - includeDirGlobs = append(includeDirGlobs, includeDir+globInfix+"/*.inc") - includeDirGlobs = append(includeDirGlobs, includeDir+globInfix+"/*.hpp") - - return android.BazelLabelForModuleSrc(ctx, includeDirGlobs) + globs := bazel.GlobsInDir(includeDir, includeDir != ".", headerExts) + return android.BazelLabelForModuleSrc(ctx, globs) } // Bazel wants include paths to be relative to the module diff --git a/cc/library.go b/cc/library.go index 18f9fae28..0ebcbaad5 100644 --- a/cc/library.go +++ b/cc/library.go @@ -206,6 +206,7 @@ func init() { RegisterLibraryBuildComponents(android.InitRegistrationContext) android.RegisterBp2BuildMutator("cc_library_static", CcLibraryStaticBp2Build) + android.RegisterBp2BuildMutator("cc_library", CcLibraryBp2Build) } func RegisterLibraryBuildComponents(ctx android.RegistrationContext) { @@ -216,6 +217,67 @@ func RegisterLibraryBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory) } +// For bp2build conversion. +type bazelCcLibraryAttributes struct { + Srcs bazel.LabelListAttribute + Hdrs bazel.LabelListAttribute + Copts bazel.StringListAttribute + Linkopts bazel.StringListAttribute + Deps bazel.LabelListAttribute + User_link_flags bazel.StringListAttribute + Includes bazel.StringListAttribute +} + +type bazelCcLibrary struct { + android.BazelTargetModuleBase + bazelCcLibraryAttributes +} + +func (m *bazelCcLibrary) Name() string { + return m.BaseModuleName() +} + +func (m *bazelCcLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {} + +func BazelCcLibraryFactory() android.Module { + module := &bazelCcLibrary{} + module.AddProperties(&module.bazelCcLibraryAttributes) + android.InitBazelTargetModule(module) + return module +} + +func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { + m, ok := ctx.Module().(*Module) + if !ok || !m.ConvertWithBp2build(ctx) { + return + } + + if ctx.ModuleType() != "cc_library" { + return + } + + copts, srcs, hdrs := bp2BuildParseCompilerProps(ctx, m) + deps, linkopts := bp2BuildParseLinkerProps(ctx, m) + exportedIncludes, exportedIncludesHeaders := bp2BuildParseExportedIncludes(ctx, m) + hdrs.Append(exportedIncludesHeaders) + + attrs := &bazelCcLibraryAttributes{ + Srcs: srcs, + Hdrs: hdrs, + Copts: copts, + Linkopts: linkopts, + Deps: deps, + Includes: exportedIncludes, + } + + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_library", + Bzl_load_location: "//build/bazel/rules:full_cc_library.bzl", + } + + ctx.CreateBazelTargetModule(BazelCcLibraryFactory, m.Name(), props, attrs) +} + // cc_library creates both static and/or shared libraries for a device and/or // host. By default, a cc_library has a single variant that targets the device. // Specifying `host_supported: true` also creates a library that targets the @@ -2058,9 +2120,10 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu } type bazelCcLibraryStaticAttributes struct { - Copts []string + Copts bazel.StringListAttribute Srcs bazel.LabelListAttribute Deps bazel.LabelListAttribute + Linkopts bazel.StringListAttribute Linkstatic bool Includes bazel.StringListAttribute Hdrs bazel.LabelListAttribute @@ -2091,14 +2154,12 @@ func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) { return } - var copts []string - var srcs []string + copts, srcs, hdrs := bp2BuildParseCompilerProps(ctx, module) + var includeDirs []string var localIncludeDirs []string for _, props := range module.compiler.compilerProps() { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { - copts = baseCompilerProps.Cflags - srcs = baseCompilerProps.Srcs includeDirs = bp2BuildMakePathsRelativeToModule(ctx, baseCompilerProps.Include_dirs) localIncludeDirs = bp2BuildMakePathsRelativeToModule(ctx, baseCompilerProps.Local_include_dirs) break @@ -2111,14 +2172,12 @@ func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) { localIncludeDirs = append(localIncludeDirs, ".") } - srcsLabels := android.BazelLabelForModuleSrc(ctx, srcs) - // For Bazel, be more explicit about headers - list all header files in include dirs as srcs for _, includeDir := range includeDirs { - srcsLabels.Append(bp2BuildListHeadersInDir(ctx, includeDir)) + srcs.Value.Append(bp2BuildListHeadersInDir(ctx, includeDir)) } for _, localIncludeDir := range localIncludeDirs { - srcsLabels.Append(bp2BuildListHeadersInDir(ctx, localIncludeDir)) + srcs.Value.Append(bp2BuildListHeadersInDir(ctx, localIncludeDir)) } var staticLibs []string @@ -2145,16 +2204,18 @@ func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) { allIncludes.Value = append(allIncludes.Value, includeDirs...) allIncludes.Value = append(allIncludes.Value, localIncludeDirs...) - headerLibsLabels := bp2BuildParseHeaderLibs(ctx, module) + hdrs.Append(exportedIncludesHeaders) + + headerLibsLabels, _ := bp2BuildParseLinkerProps(ctx, module) depsLabels.Append(headerLibsLabels.Value) attrs := &bazelCcLibraryStaticAttributes{ Copts: copts, - Srcs: bazel.MakeLabelListAttribute(srcsLabels), + Srcs: srcs, Deps: bazel.MakeLabelListAttribute(depsLabels), Linkstatic: true, Includes: allIncludes, - Hdrs: exportedIncludesHeaders, + Hdrs: hdrs, } props := bazel.BazelTargetModuleProperties{ diff --git a/cc/library_headers.go b/cc/library_headers.go index d35748bcb..0f7f8f846 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -96,11 +96,11 @@ func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) { } exportedIncludes, exportedIncludesHeaders := bp2BuildParseExportedIncludes(ctx, module) - - headerLibs := bp2BuildParseHeaderLibs(ctx, module) + copts, _, _ := bp2BuildParseCompilerProps(ctx, module) + headerLibs, _ := bp2BuildParseLinkerProps(ctx, module) attrs := &bazelCcLibraryHeadersAttributes{ - Copts: bp2BuildParseCflags(ctx, module), + Copts: copts, Includes: exportedIncludes, Hdrs: exportedIncludesHeaders, Deps: headerLibs, diff --git a/cc/object.go b/cc/object.go index 4f8797dea..de45293dc 100644 --- a/cc/object.go +++ b/cc/object.go @@ -113,6 +113,7 @@ func ObjectFactory() android.Module { // For bp2build conversion. type bazelObjectAttributes struct { Srcs bazel.LabelListAttribute + Hdrs bazel.LabelListAttribute Deps bazel.LabelListAttribute Copts bazel.StringListAttribute Asflags []string @@ -156,16 +157,11 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { } // Set arch-specific configurable attributes - var srcs bazel.LabelListAttribute + copts, srcs, hdrs := bp2BuildParseCompilerProps(ctx, m) var localIncludeDirs []string var asFlags []string for _, props := range m.compiler.compilerProps() { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { - srcs = bazel.MakeLabelListAttribute( - android.BazelLabelForModuleSrcExcludes( - ctx, - baseCompilerProps.Srcs, - baseCompilerProps.Exclude_srcs)) localIncludeDirs = baseCompilerProps.Local_include_dirs break } @@ -208,8 +204,9 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { attrs := &bazelObjectAttributes{ Srcs: srcs, + Hdrs: hdrs, Deps: deps, - Copts: bp2BuildParseCflags(ctx, m), + Copts: copts, Asflags: asFlags, Local_include_dirs: localIncludeDirs, }