diff --git a/bazel/properties.go b/bazel/properties.go index 99119cde1..7093d6cdf 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -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 diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go index 6bdfc0e69..4de5aae18 100644 --- a/bp2build/build_conversion.go +++ b/bp2build/build_conversion.go @@ -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 diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index 6d0a9b21a..33609af03 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -23,12 +23,14 @@ import ( 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 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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 @@ 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\\\\", + name: "foo", + owner: "a_string_with\"quotes\"_and_\\backslashes\\\\", } - `, + `, expectedBazelTarget: `soong_module( name = "foo", soong_module_name = "foo", @@ -67,15 +72,17 @@ 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"], + name: "foo", + required: ["bar"], } - `, + `, expectedBazelTarget: `soong_module( name = "foo", soong_module_name = "foo", @@ -83,15 +90,17 @@ 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"], + name: "foo", + target_required: ["qux", "bazqux"], } - `, + `, expectedBazelTarget: `soong_module( name = "foo", soong_module_name = "foo", @@ -99,6 +108,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], + bool_prop = False, target_required = [ "qux", "bazqux", @@ -106,18 +116,19 @@ func TestGenerateSoongModuleTargets(t *testing.T) { )`, }, { + 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 @@ func TestGenerateSoongModuleTargets(t *testing.T) { soong_module_variant = "", soong_module_deps = [ ], + bool_prop = False, dist = { "tag": ".foo", "targets": ["goal_foo"], @@ -136,20 +148,21 @@ func TestGenerateSoongModuleTargets(t *testing.T) { )`, }, { + 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 @@ 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", @@ -174,31 +187,33 @@ func TestGenerateSoongModuleTargets(t *testing.T) { 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 d84a7bbe5..c464cec87 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -25,18 +25,18 @@ const ( // 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 @@ func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) { 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 @@ 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 - ], + ], } `, }, @@ -710,21 +710,21 @@ func TestCcLibraryConfiguredVersionScript(t *testing.T) { 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 @@ cc_library { srcs: ["b.cpp"], arch: { x86_64: { - pack_relocations: false, - }, + pack_relocations: false, + }, }, bazel_module: { bp2build_available: true }, } @@ -816,8 +816,8 @@ cc_library { srcs: ["c.cpp"], target: { darwin: { - pack_relocations: false, - }, + pack_relocations: false, + }, }, bazel_module: { bp2build_available: true }, }`, @@ -900,22 +900,22 @@ func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) { 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 @@ func TestCcLibraryLabelAttributeGetTargetProperties(t *testing.T) { 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 @@ 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, + }), +)`}}) +} diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go index 264ba6bb8..db344decc 100644 --- a/bp2build/cc_library_headers_conversion_test.go +++ b/bp2build/cc_library_headers_conversion_test.go @@ -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"], +)`}, + }) +} diff --git a/bp2build/configurability.go b/bp2build/configurability.go index 60f6330e3..c8105eb9b 100644 --- a/bp2build/configurability.go +++ b/bp2build/configurability.go @@ -51,6 +51,28 @@ func getLabelValue(label bazel.LabelAttribute) (reflect.Value, []selects) { 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 @@ func labelListSelectValue(selectKey string, list bazel.LabelList) (bool, reflect 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 @@ func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) { 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 @@ func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) { // 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 @@ func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue strin 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) diff --git a/cc/bp2build.go b/cc/bp2build.go index 752d43b50..211fe5e05 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -489,6 +489,7 @@ type linkerAttributes struct { dynamicDeps bazel.LabelListAttribute wholeArchiveDeps bazel.LabelListAttribute exportedDeps bazel.LabelListAttribute + useLibcrt bazel.BoolAttribute linkopts bazel.StringListAttribute versionScript bazel.LabelAttribute } @@ -512,6 +513,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) var wholeArchiveDeps bazel.LabelListAttribute var linkopts bazel.StringListAttribute var versionScript bazel.LabelAttribute + var useLibcrt bazel.BoolAttribute for _, linkerProps := range module.linker.linkerProps() { if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok { @@ -535,6 +537,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) if baseLinkerProps.Version_script != nil { versionScript.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script)) } + useLibcrt.Value = baseLinkerProps.libCrt() break } @@ -559,6 +562,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) if baseLinkerProps.Version_script != nil { versionScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script)) } + useLibcrt.SetSelectValue(axis, config, baseLinkerProps.libCrt()) } } } @@ -624,6 +628,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) dynamicDeps: dynamicDeps, wholeArchiveDeps: wholeArchiveDeps, linkopts: linkopts, + useLibcrt: useLibcrt, versionScript: versionScript, } } diff --git a/cc/library.go b/cc/library.go index c88c29afb..5995e9802 100644 --- a/cc/library.go +++ b/cc/library.go @@ -234,6 +234,7 @@ type bazelCcLibraryAttributes struct { Whole_archive_deps bazel.LabelListAttribute Includes bazel.StringListAttribute Linkopts bazel.StringListAttribute + Use_libcrt bazel.BoolAttribute // Attributes pertaining to shared variant. Shared_srcs bazel.LabelListAttribute @@ -320,6 +321,7 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { Whole_archive_deps: linkerAttrs.wholeArchiveDeps, Includes: exportedIncludes, Linkopts: linkerAttrs.linkopts, + Use_libcrt: linkerAttrs.useLibcrt, Shared_srcs: sharedAttrs.srcs, Shared_srcs_c: sharedAttrs.srcs_c, @@ -2262,6 +2264,7 @@ type bazelCcLibraryStaticAttributes struct { Whole_archive_deps bazel.LabelListAttribute Linkopts bazel.StringListAttribute Linkstatic bool + Use_libcrt bazel.BoolAttribute Includes bazel.StringListAttribute Hdrs bazel.LabelListAttribute @@ -2298,6 +2301,7 @@ func ccLibraryStaticBp2BuildInternal(ctx android.TopDownMutatorContext, module * Linkopts: linkerAttrs.linkopts, Linkstatic: true, + Use_libcrt: linkerAttrs.useLibcrt, Includes: exportedIncludes, Cppflags: compilerAttrs.cppFlags, diff --git a/cc/linker.go b/cc/linker.go index 1d8c649c1..895931acb 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -200,6 +200,18 @@ type BaseLinkerProperties struct { Exclude_shared_libs []string `android:"arch_variant"` } +func invertBoolPtr(value *bool) *bool { + if value == nil { + return nil + } + ret := !(*value) + return &ret +} + +func (blp *BaseLinkerProperties) libCrt() *bool { + return invertBoolPtr(blp.No_libcrt) +} + func NewBaseLinker(sanitize *sanitize) *baseLinker { return &baseLinker{sanitize: sanitize} }