Merge "Handle no_libcrt in bp2build."

This commit is contained in:
Treehugger Robot
2021-06-09 00:48:06 +00:00
committed by Gerrit Code Review
9 changed files with 457 additions and 144 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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(
@@ -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(
@@ -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\\\\",
@@ -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"],
@@ -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"],
@@ -99,6 +108,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = False,
target_required = [
"qux",
"bazqux",
@@ -106,6 +116,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
)`,
},
{
description: "dist/dists",
bp: `custom {
name: "foo",
dist: {
@@ -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,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: [
{
@@ -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,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)
@@ -199,6 +213,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
actualBazelTarget.content,
)
}
})
}
}

View File

@@ -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,
}),
)`}})
}

View File

@@ -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"],
)`},
})
}

View File

@@ -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)

View File

@@ -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,
}
}

View File

@@ -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,

View File

@@ -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}
}