bp2build: cc_library converter for //bionic/libdl:libdl_android
This CL contains the converter for libdl_android, a cc_library that
expands into a cc_shared_library and a regular cc_library.
Test: TH
Test: bp2build; bazel test //build/bazel/tests/...
Change-Id: If70641a538211b0d6b2aac0e4d0d06912318304d
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index cc616f2..d2a8729 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -26,6 +26,7 @@
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 dd14c7d..16e7278 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -374,16 +374,9 @@
// 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 @@
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 0000000..6a148a8
--- /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 74226ae..655218d 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -23,7 +23,7 @@
const (
// See cc/testing.go for more context
- soongCcLibraryPreamble = `
+ soongCcLibraryHeadersPreamble = `
cc_defaults {
name: "linux_bionic_supported",
}
@@ -98,7 +98,7 @@
"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 @@
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 ef528e9..a6a0028 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -194,6 +194,8 @@
":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 @@
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 @@
"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 4f3babe..840bf42 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -52,7 +52,6 @@
"-Werror",
],
srcs: [
- "a/b/*.h",
"a/b/*.c"
],
exclude_srcs: ["a/b/exclude.c"],
@@ -68,14 +67,16 @@
"-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 b2b3379..97729df 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -69,20 +69,26 @@
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 @@
}
// 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)