Loading bazel/properties.go +77 −0 Original line number Diff line number Diff line Loading @@ -350,6 +350,83 @@ func (la *LabelAttribute) SortedConfigurationAxes() []ConfigurationAxis { return keys } type configToBools map[string]bool func (ctb configToBools) setValue(config string, value *bool) { if value == nil { if _, ok := ctb[config]; ok { delete(ctb, config) } return } ctb[config] = *value } type configurableBools map[ConfigurationAxis]configToBools func (cb configurableBools) setValueForAxis(axis ConfigurationAxis, config string, value *bool) { if cb[axis] == nil { cb[axis] = make(configToBools) } cb[axis].setValue(config, value) } // BoolAttribute represents an attribute whose value is a single bool but may be configurable.. type BoolAttribute struct { Value *bool ConfigurableValues configurableBools } // HasConfigurableValues returns whether there are configurable values for this attribute. func (ba BoolAttribute) HasConfigurableValues() bool { return len(ba.ConfigurableValues) > 0 } // SetSelectValue sets value for the given axis/config. func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, value *bool) { axis.validateConfig(config) switch axis.configurationType { case noConfig: ba.Value = value case arch, os, osArch, productVariables: if ba.ConfigurableValues == nil { ba.ConfigurableValues = make(configurableBools) } ba.ConfigurableValues.setValueForAxis(axis, config, value) default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) } } // SelectValue gets the value for the given axis/config. func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool { axis.validateConfig(config) switch axis.configurationType { case noConfig: return ba.Value case arch, os, osArch, productVariables: if v, ok := ba.ConfigurableValues[axis][config]; ok { return &v } else { return nil } default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) } } // SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order. func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis { keys := make([]ConfigurationAxis, 0, len(ba.ConfigurableValues)) for k := range ba.ConfigurableValues { keys = append(keys, k) } sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) }) return keys } // labelListSelectValues supports config-specific label_list typed Bazel attribute values. type labelListSelectValues map[string]LabelList Loading bp2build/build_conversion.go +4 −0 Original line number Diff line number Diff line Loading @@ -567,6 +567,10 @@ func isZero(value reflect.Value) bool { } 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 Loading bp2build/build_conversion_test.go +73 −58 Original line number Diff line number Diff line Loading @@ -23,10 +23,12 @@ import ( func TestGenerateSoongModuleTargets(t *testing.T) { testCases := []struct { description string bp string expectedBazelTarget string }{ { description: "only name", bp: `custom { name: "foo" } `, expectedBazelTarget: `soong_module( Loading @@ -36,12 +38,14 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, )`, }, { description: "handles bool", bp: `custom { name: "foo", ramdisk: true, bool_prop: true, } `, expectedBazelTarget: `soong_module( Loading @@ -51,10 +55,11 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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\\\\", Loading @@ -67,10 +72,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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"], Loading @@ -83,10 +90,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, required = ["bar"], )`, }, { description: "list of strings", bp: `custom { name: "foo", target_required: ["qux", "bazqux"], Loading @@ -99,6 +108,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, target_required = [ "qux", "bazqux", Loading @@ -106,6 +116,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { )`, }, { description: "dist/dists", bp: `custom { name: "foo", dist: { Loading @@ -125,6 +136,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, dist = { "tag": ".foo", "targets": ["goal_foo"], Loading @@ -136,11 +148,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { )`, }, { description: "put it together", bp: `custom { name: "foo", required: ["bar"], target_required: ["qux", "bazqux"], ramdisk: true, bool_prop: true, owner: "custom_owner", dists: [ { Loading @@ -157,12 +170,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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", Loading @@ -174,6 +187,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { dir := "." for _, testCase := range testCases { t.Run(testCase.description, func(t *testing.T) { config := android.TestConfig(buildDir, nil, testCase.bp, nil) ctx := android.NewTestContext(config) Loading @@ -199,6 +213,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { actualBazelTarget.content, ) } }) } } Loading bp2build/cc_library_conversion_test.go +205 −73 Original line number Diff line number Diff line Loading @@ -1099,3 +1099,135 @@ cc_library { }, }) } 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, }), )`}}) } bp2build/cc_library_headers_conversion_test.go +36 −0 Original line number Diff line number Diff line Loading @@ -374,3 +374,39 @@ func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) { )`}, }) } 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"], )`}, }) } Loading
bazel/properties.go +77 −0 Original line number Diff line number Diff line Loading @@ -350,6 +350,83 @@ func (la *LabelAttribute) SortedConfigurationAxes() []ConfigurationAxis { return keys } type configToBools map[string]bool func (ctb configToBools) setValue(config string, value *bool) { if value == nil { if _, ok := ctb[config]; ok { delete(ctb, config) } return } ctb[config] = *value } type configurableBools map[ConfigurationAxis]configToBools func (cb configurableBools) setValueForAxis(axis ConfigurationAxis, config string, value *bool) { if cb[axis] == nil { cb[axis] = make(configToBools) } cb[axis].setValue(config, value) } // BoolAttribute represents an attribute whose value is a single bool but may be configurable.. type BoolAttribute struct { Value *bool ConfigurableValues configurableBools } // HasConfigurableValues returns whether there are configurable values for this attribute. func (ba BoolAttribute) HasConfigurableValues() bool { return len(ba.ConfigurableValues) > 0 } // SetSelectValue sets value for the given axis/config. func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, value *bool) { axis.validateConfig(config) switch axis.configurationType { case noConfig: ba.Value = value case arch, os, osArch, productVariables: if ba.ConfigurableValues == nil { ba.ConfigurableValues = make(configurableBools) } ba.ConfigurableValues.setValueForAxis(axis, config, value) default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) } } // SelectValue gets the value for the given axis/config. func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool { axis.validateConfig(config) switch axis.configurationType { case noConfig: return ba.Value case arch, os, osArch, productVariables: if v, ok := ba.ConfigurableValues[axis][config]; ok { return &v } else { return nil } default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) } } // SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order. func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis { keys := make([]ConfigurationAxis, 0, len(ba.ConfigurableValues)) for k := range ba.ConfigurableValues { keys = append(keys, k) } sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) }) return keys } // labelListSelectValues supports config-specific label_list typed Bazel attribute values. type labelListSelectValues map[string]LabelList Loading
bp2build/build_conversion.go +4 −0 Original line number Diff line number Diff line Loading @@ -567,6 +567,10 @@ func isZero(value reflect.Value) bool { } 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 Loading
bp2build/build_conversion_test.go +73 −58 Original line number Diff line number Diff line Loading @@ -23,10 +23,12 @@ import ( func TestGenerateSoongModuleTargets(t *testing.T) { testCases := []struct { description string bp string expectedBazelTarget string }{ { description: "only name", bp: `custom { name: "foo" } `, expectedBazelTarget: `soong_module( Loading @@ -36,12 +38,14 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, )`, }, { description: "handles bool", bp: `custom { name: "foo", ramdisk: true, bool_prop: true, } `, expectedBazelTarget: `soong_module( Loading @@ -51,10 +55,11 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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\\\\", Loading @@ -67,10 +72,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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"], Loading @@ -83,10 +90,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, required = ["bar"], )`, }, { description: "list of strings", bp: `custom { name: "foo", target_required: ["qux", "bazqux"], Loading @@ -99,6 +108,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, target_required = [ "qux", "bazqux", Loading @@ -106,6 +116,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { )`, }, { description: "dist/dists", bp: `custom { name: "foo", dist: { Loading @@ -125,6 +136,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], bool_prop = False, dist = { "tag": ".foo", "targets": ["goal_foo"], Loading @@ -136,11 +148,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { )`, }, { description: "put it together", bp: `custom { name: "foo", required: ["bar"], target_required: ["qux", "bazqux"], ramdisk: true, bool_prop: true, owner: "custom_owner", dists: [ { Loading @@ -157,12 +170,12 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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", Loading @@ -174,6 +187,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { dir := "." for _, testCase := range testCases { t.Run(testCase.description, func(t *testing.T) { config := android.TestConfig(buildDir, nil, testCase.bp, nil) ctx := android.NewTestContext(config) Loading @@ -199,6 +213,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { actualBazelTarget.content, ) } }) } } Loading
bp2build/cc_library_conversion_test.go +205 −73 Original line number Diff line number Diff line Loading @@ -1099,3 +1099,135 @@ cc_library { }, }) } 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, }), )`}}) }
bp2build/cc_library_headers_conversion_test.go +36 −0 Original line number Diff line number Diff line Loading @@ -374,3 +374,39 @@ func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) { )`}, }) } 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"], )`}, }) }