Handle no_libcrt in bp2build.
Test: ci/bp2build.sh
Bug: 187928307
Change-Id: Ib80c4318169652b322e5d878c8784679e42f87dd
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 6bdfc0e..4de5aae 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -567,6 +567,10 @@
} else {
return true
}
+ // Always print bools, if you want a bool attribute to be able to take the default value, use a
+ // bool pointer instead
+ case reflect.Bool:
+ return false
default:
if !value.IsValid() {
return true
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 6d0a9b2..33609af 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -23,12 +23,14 @@
func TestGenerateSoongModuleTargets(t *testing.T) {
testCases := []struct {
+ description string
bp string
expectedBazelTarget string
}{
{
+ description: "only name",
bp: `custom { name: "foo" }
- `,
+ `,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
@@ -36,14 +38,16 @@
soong_module_variant = "",
soong_module_deps = [
],
+ bool_prop = False,
)`,
},
{
+ description: "handles bool",
bp: `custom {
- name: "foo",
- ramdisk: true,
+ name: "foo",
+ bool_prop: true,
}
- `,
+ `,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
@@ -51,15 +55,16 @@
soong_module_variant = "",
soong_module_deps = [
],
- ramdisk = True,
+ bool_prop = True,
)`,
},
{
+ description: "string escaping",
bp: `custom {
- name: "foo",
- owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
+ name: "foo",
+ owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
}
- `,
+ `,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
@@ -67,15 +72,17 @@
soong_module_variant = "",
soong_module_deps = [
],
+ bool_prop = False,
owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
)`,
},
{
+ description: "single item string list",
bp: `custom {
- name: "foo",
- required: ["bar"],
+ name: "foo",
+ required: ["bar"],
}
- `,
+ `,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
@@ -83,15 +90,17 @@
soong_module_variant = "",
soong_module_deps = [
],
+ bool_prop = False,
required = ["bar"],
)`,
},
{
+ description: "list of strings",
bp: `custom {
- name: "foo",
- target_required: ["qux", "bazqux"],
+ name: "foo",
+ target_required: ["qux", "bazqux"],
}
- `,
+ `,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
@@ -99,6 +108,7 @@
soong_module_variant = "",
soong_module_deps = [
],
+ bool_prop = False,
target_required = [
"qux",
"bazqux",
@@ -106,18 +116,19 @@
)`,
},
{
+ description: "dist/dists",
bp: `custom {
- name: "foo",
- dist: {
- targets: ["goal_foo"],
- tag: ".foo",
- },
- dists: [{
- targets: ["goal_bar"],
- tag: ".bar",
- }],
+ name: "foo",
+ dist: {
+ targets: ["goal_foo"],
+ tag: ".foo",
+ },
+ dists: [{
+ targets: ["goal_bar"],
+ tag: ".bar",
+ }],
}
- `,
+ `,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
@@ -125,6 +136,7 @@
soong_module_variant = "",
soong_module_deps = [
],
+ bool_prop = False,
dist = {
"tag": ".foo",
"targets": ["goal_foo"],
@@ -136,20 +148,21 @@
)`,
},
{
+ description: "put it together",
bp: `custom {
- name: "foo",
- required: ["bar"],
- target_required: ["qux", "bazqux"],
- ramdisk: true,
- owner: "custom_owner",
- dists: [
- {
- tag: ".tag",
- targets: ["my_goal"],
- },
- ],
+ name: "foo",
+ required: ["bar"],
+ target_required: ["qux", "bazqux"],
+ bool_prop: true,
+ owner: "custom_owner",
+ dists: [
+ {
+ tag: ".tag",
+ targets: ["my_goal"],
+ },
+ ],
}
- `,
+ `,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
@@ -157,12 +170,12 @@
soong_module_variant = "",
soong_module_deps = [
],
+ bool_prop = True,
dists = [{
"tag": ".tag",
"targets": ["my_goal"],
}],
owner = "custom_owner",
- ramdisk = True,
required = ["bar"],
target_required = [
"qux",
@@ -174,31 +187,33 @@
dir := "."
for _, testCase := range testCases {
- config := android.TestConfig(buildDir, nil, testCase.bp, nil)
- ctx := android.NewTestContext(config)
+ t.Run(testCase.description, func(t *testing.T) {
+ config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+ ctx := android.NewTestContext(config)
- ctx.RegisterModuleType("custom", customModuleFactory)
- ctx.Register()
+ ctx.RegisterModuleType("custom", customModuleFactory)
+ ctx.Register()
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+ _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
- bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
- if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
- t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
- }
+ codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+ if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
+ t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
+ }
- actualBazelTarget := bazelTargets[0]
- if actualBazelTarget.content != testCase.expectedBazelTarget {
- t.Errorf(
- "Expected generated Bazel target to be '%s', got '%s'",
- testCase.expectedBazelTarget,
- actualBazelTarget.content,
- )
- }
+ actualBazelTarget := bazelTargets[0]
+ if actualBazelTarget.content != testCase.expectedBazelTarget {
+ t.Errorf(
+ "Expected generated Bazel target to be '%s', got '%s'",
+ testCase.expectedBazelTarget,
+ actualBazelTarget.content,
+ )
+ }
+ })
}
}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index d84a7bb..c464cec 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -25,18 +25,18 @@
// See cc/testing.go for more context
soongCcLibraryPreamble = `
cc_defaults {
- name: "linux_bionic_supported",
+ 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: "",
+ 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: "",
}`
)
@@ -564,32 +564,32 @@
cc_library {
name: "a",
srcs: [
- "both_source.cpp",
- "both_source.cc",
- "both_source.c",
- "both_source.s",
- "both_source.S",
+ "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",
- ],
+ 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",
- ],
+ srcs: [
+ "shared_source.cpp",
+ "shared_source.cc",
+ "shared_source.c",
+ "shared_source.s",
+ "shared_source.S",
+ ":shared_filegroup",
+ ],
},
bazel_module: { bp2build_available: true },
}
@@ -598,21 +598,21 @@
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
- ],
+ ],
}
`,
},
@@ -710,21 +710,21 @@
dir: "foo/bar",
filesystem: map[string]string{
"foo/bar/Android.bp": `
- cc_library {
- name: "a",
- srcs: ["a.cpp"],
- arch: {
- arm: {
- version_script: "arm.map",
- },
- arm64: {
- version_script: "arm64.map",
- },
- },
+ cc_library {
+ name: "a",
+ srcs: ["a.cpp"],
+ arch: {
+ arm: {
+ version_script: "arm.map",
+ },
+ arm64: {
+ version_script: "arm64.map",
+ },
+ },
- bazel_module: { bp2build_available: true },
- }
- `,
+ bazel_module: { bp2build_available: true },
+ }
+ `,
},
blueprint: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
@@ -805,8 +805,8 @@
srcs: ["b.cpp"],
arch: {
x86_64: {
- pack_relocations: false,
- },
+ pack_relocations: false,
+ },
},
bazel_module: { bp2build_available: true },
}
@@ -816,8 +816,8 @@
srcs: ["c.cpp"],
target: {
darwin: {
- pack_relocations: false,
- },
+ pack_relocations: false,
+ },
},
bazel_module: { bp2build_available: true },
}`,
@@ -900,22 +900,22 @@
name: "a",
srcs: ["a.cpp"],
cflags: [
- "-Wall",
- ],
+ "-Wall",
+ ],
cppflags: [
"-fsigned-char",
"-pedantic",
- ],
+ ],
arch: {
arm64: {
cppflags: ["-DARM64=1"],
- },
- },
+ },
+ },
target: {
android: {
cppflags: ["-DANDROID=1"],
- },
- },
+ },
+ },
bazel_module: { bp2build_available: true },
}
`,
@@ -953,21 +953,21 @@
dir: "foo/bar",
filesystem: map[string]string{
"foo/bar/Android.bp": `
- cc_library {
- name: "a",
- srcs: ["a.cpp"],
- target: {
- android_arm: {
- version_script: "android_arm.map",
- },
- linux_bionic_arm64: {
- version_script: "linux_bionic_arm64.map",
- },
- },
+ cc_library {
+ name: "a",
+ srcs: ["a.cpp"],
+ target: {
+ android_arm: {
+ version_script: "android_arm.map",
+ },
+ linux_bionic_arm64: {
+ version_script: "linux_bionic_arm64.map",
+ },
+ },
- bazel_module: { bp2build_available: true },
- }
- `,
+ bazel_module: { bp2build_available: true },
+ }
+ `,
},
blueprint: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
@@ -1099,3 +1099,135 @@
},
})
}
+
+func TestCCLibraryNoCrtTrue(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library - simple example",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ filesystem: map[string]string{
+ "impl.cpp": "",
+ },
+ blueprint: soongCcLibraryPreamble + `
+cc_library_headers { name: "some-headers" }
+cc_library {
+ name: "foo-lib",
+ srcs: ["impl.cpp"],
+ no_libcrt: true,
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "foo-lib",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ srcs = ["impl.cpp"],
+ use_libcrt = False,
+)`}})
+}
+
+func TestCCLibraryNoCrtFalse(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ filesystem: map[string]string{
+ "impl.cpp": "",
+ },
+ blueprint: soongCcLibraryPreamble + `
+cc_library_headers { name: "some-headers" }
+cc_library {
+ name: "foo-lib",
+ srcs: ["impl.cpp"],
+ no_libcrt: false,
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "foo-lib",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ srcs = ["impl.cpp"],
+ use_libcrt = True,
+)`}})
+}
+
+func TestCCLibraryNoCrtArchVariant(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ filesystem: map[string]string{
+ "impl.cpp": "",
+ },
+ blueprint: soongCcLibraryPreamble + `
+cc_library_headers { name: "some-headers" }
+cc_library {
+ name: "foo-lib",
+ srcs: ["impl.cpp"],
+ arch: {
+ arm: {
+ no_libcrt: true,
+ },
+ x86: {
+ no_libcrt: true,
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "foo-lib",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ srcs = ["impl.cpp"],
+ use_libcrt = select({
+ "//build/bazel/platforms/arch:arm": False,
+ "//build/bazel/platforms/arch:x86": False,
+ "//conditions:default": None,
+ }),
+)`}})
+}
+
+func TestCCLibraryNoCrtArchVariantWithDefault(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ filesystem: map[string]string{
+ "impl.cpp": "",
+ },
+ blueprint: soongCcLibraryPreamble + `
+cc_library_headers { name: "some-headers" }
+cc_library {
+ name: "foo-lib",
+ srcs: ["impl.cpp"],
+ no_libcrt: false,
+ arch: {
+ arm: {
+ no_libcrt: true,
+ },
+ x86: {
+ no_libcrt: true,
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "foo-lib",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ srcs = ["impl.cpp"],
+ use_libcrt = select({
+ "//build/bazel/platforms/arch:arm": False,
+ "//build/bazel/platforms/arch:x86": False,
+ "//conditions:default": True,
+ }),
+)`}})
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 264ba6b..db344de 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -374,3 +374,39 @@
)`},
})
}
+
+func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) {
+ runCcLibraryHeadersTestCase(t, bp2buildTestCase{
+ description: "cc_library_headers test",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
+ filesystem: map[string]string{
+ "lib-1/lib1a.h": "",
+ "lib-1/lib1b.h": "",
+ "lib-2/lib2a.h": "",
+ "lib-2/lib2b.h": "",
+ "dir-1/dir1a.h": "",
+ "dir-1/dir1b.h": "",
+ "dir-2/dir2a.h": "",
+ "dir-2/dir2b.h": "",
+ "arch_arm64_exported_include_dir/a.h": "",
+ "arch_x86_exported_include_dir/b.h": "",
+ "arch_x86_64_exported_include_dir/c.h": "",
+ },
+ blueprint: soongCcLibraryHeadersPreamble + `
+cc_library_headers {
+ name: "lib-1",
+ export_include_dirs: ["lib-1"],
+ no_libcrt: true,
+}`,
+ expectedBazelTargets: []string{`cc_library_headers(
+ name = "lib-1",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ includes = ["lib-1"],
+)`},
+ })
+}
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index 60f6330..c8105eb 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -51,6 +51,28 @@
return value, []selects{ret}
}
+func getBoolValue(boolAttr bazel.BoolAttribute) (reflect.Value, []selects) {
+ value := reflect.ValueOf(boolAttr.Value)
+ if !boolAttr.HasConfigurableValues() {
+ return value, []selects{}
+ }
+
+ ret := selects{}
+ for _, axis := range boolAttr.SortedConfigurationAxes() {
+ configToBools := boolAttr.ConfigurableValues[axis]
+ for config, bools := range configToBools {
+ selectKey := axis.SelectKey(config)
+ ret[selectKey] = reflect.ValueOf(bools)
+ }
+ }
+ // if there is a select, use the base value as the conditions default value
+ if len(ret) > 0 {
+ ret[bazel.ConditionsDefaultSelectKey] = value
+ value = reflect.Zero(value.Type())
+ }
+
+ return value, []selects{ret}
+}
func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects) {
value := reflect.ValueOf(list.Value.Includes)
var ret []selects
@@ -85,22 +107,30 @@
return false, reflect.Zero(reflect.TypeOf([]string{}))
}
+var (
+ emptyBazelList = "[]"
+ bazelNone = "None"
+)
+
// prettyPrintAttribute converts an Attribute to its Bazel syntax. May contain
// select statements.
func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
var value reflect.Value
var configurableAttrs []selects
- var defaultSelectValue string
+ var defaultSelectValue *string
switch list := v.(type) {
case bazel.StringListAttribute:
value, configurableAttrs = getStringListValues(list)
- defaultSelectValue = "[]"
+ defaultSelectValue = &emptyBazelList
case bazel.LabelListAttribute:
value, configurableAttrs = getLabelListValues(list)
- defaultSelectValue = "[]"
+ defaultSelectValue = &emptyBazelList
case bazel.LabelAttribute:
value, configurableAttrs = getLabelValue(list)
- defaultSelectValue = "None"
+ defaultSelectValue = &bazelNone
+ case bazel.BoolAttribute:
+ value, configurableAttrs = getBoolValue(list)
+ defaultSelectValue = &bazelNone
default:
return "", fmt.Errorf("Not a supported Bazel attribute type: %s", v)
}
@@ -116,7 +146,7 @@
ret += s
}
// Convenience function to append selects components to an attribute value.
- appendSelects := func(selectsData selects, defaultValue, s string) (string, error) {
+ appendSelects := func(selectsData selects, defaultValue *string, s string) (string, error) {
selectMap, err := prettyPrintSelectMap(selectsData, defaultValue, indent)
if err != nil {
return "", err
@@ -141,13 +171,11 @@
// prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
// to construct a select map for any kind of attribute type.
-func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue string, indent int) (string, error) {
+func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue *string, indent int) (string, error) {
if selectMap == nil {
return "", nil
}
- // addConditionsDefault := false
-
var selects string
for _, selectKey := range android.SortedStringKeys(selectMap) {
if selectKey == bazel.ConditionsDefaultSelectKey {
@@ -184,14 +212,14 @@
if err != nil {
return "", err
}
- if s == "" {
- // Print an explicit empty list (the default value) even if the value is
- // empty, to avoid errors about not finding a configuration that matches.
- ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), bazel.ConditionsDefaultSelectKey, defaultValue)
- } else {
+ if s != "" {
// Print the custom default value.
ret += s
ret += ",\n"
+ } else if defaultValue != nil {
+ // Print an explicit empty list (the default value) even if the value is
+ // empty, to avoid errors about not finding a configuration that matches.
+ ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), bazel.ConditionsDefaultSelectKey, *defaultValue)
}
ret += makeIndent(indent)