Merge changes Ibbb14b0d,I9aa552e3
* changes: Create config_setting per apex_name Add a function to create config_setting(s)
This commit is contained in:
@@ -273,6 +273,12 @@ type TopDownMutatorContext interface {
|
||||
// This function can be used to create alias definitions in a directory that is different
|
||||
// from the directory of the visited Soong module.
|
||||
CreateBazelTargetAliasInDir(dir string, name string, actual bazel.Label)
|
||||
|
||||
// CreateBazelConfigSetting creates a config_setting in <dir>/BUILD.bazel
|
||||
// build/bazel has several static config_setting(s) that are used in Bazel builds.
|
||||
// This function can be used to createa additional config_setting(s) based on the build graph
|
||||
// (e.g. a config_setting specific to an apex variant)
|
||||
CreateBazelConfigSetting(csa bazel.ConfigSettingAttributes, ca CommonAttributes, dir string)
|
||||
}
|
||||
|
||||
type topDownMutatorContext struct {
|
||||
@@ -738,6 +744,23 @@ func (t *topDownMutatorContext) CreateBazelTargetAliasInDir(
|
||||
mod.base().addBp2buildInfo(info)
|
||||
}
|
||||
|
||||
func (t *topDownMutatorContext) CreateBazelConfigSetting(
|
||||
csa bazel.ConfigSettingAttributes,
|
||||
ca CommonAttributes,
|
||||
dir string) {
|
||||
mod := t.Module()
|
||||
info := bp2buildInfo{
|
||||
Dir: dir,
|
||||
BazelProps: bazel.BazelTargetModuleProperties{
|
||||
Rule_class: "config_setting",
|
||||
},
|
||||
CommonAttrs: ca,
|
||||
ConstraintAttrs: constraintAttributes{},
|
||||
Attrs: &csa,
|
||||
}
|
||||
mod.base().addBp2buildInfo(info)
|
||||
}
|
||||
|
||||
// ApexAvailableTags converts the apex_available property value of an ApexModule
|
||||
// module and returns it as a list of keyed tags.
|
||||
func ApexAvailableTags(mod Module) bazel.StringListAttribute {
|
||||
|
@@ -268,9 +268,8 @@ func (ct configurationType) validateConfig(config string) {
|
||||
case productVariables:
|
||||
// do nothing
|
||||
case osAndInApex:
|
||||
if _, ok := osAndInApexMap[config]; !ok {
|
||||
panic(fmt.Errorf("Unknown os+in_apex config: %s", config))
|
||||
}
|
||||
// do nothing
|
||||
// this axis can contain additional per-apex keys
|
||||
case inApex:
|
||||
if _, ok := inApexMap[config]; !ok {
|
||||
panic(fmt.Errorf("Unknown in_apex config: %s", config))
|
||||
@@ -299,7 +298,10 @@ func (ca ConfigurationAxis) SelectKey(config string) string {
|
||||
}
|
||||
return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
|
||||
case osAndInApex:
|
||||
return osAndInApexMap[config]
|
||||
if ret, exists := osAndInApexMap[config]; exists {
|
||||
return ret
|
||||
}
|
||||
return config
|
||||
case inApex:
|
||||
return inApexMap[config]
|
||||
default:
|
||||
|
@@ -1424,3 +1424,14 @@ func TryVariableSubstitution(s string, productVariable string) (string, bool) {
|
||||
sub := productVariableSubstitutionPattern.ReplaceAllString(s, "$("+productVariable+")")
|
||||
return sub, s != sub
|
||||
}
|
||||
|
||||
// StringMapAttribute is a map of strings.
|
||||
// The use case for this is storing the flag_values in a config_setting object.
|
||||
// Bazel rules do not support map attributes, and this should NOT be used in Bazel rules.
|
||||
type StringMapAttribute map[string]string
|
||||
|
||||
// ConfigSettingAttributes stores the keys of a config_setting object.
|
||||
type ConfigSettingAttributes struct {
|
||||
// Each key in Flag_values is a label to a custom string_setting
|
||||
Flag_values StringMapAttribute
|
||||
}
|
||||
|
@@ -600,6 +600,11 @@ func prettyPrint(propertyValue reflect.Value, indent int, emitZeroValues bool) (
|
||||
// TODO(b/164227191): implement pretty print for interfaces.
|
||||
// Interfaces are used for for arch, multilib and target properties.
|
||||
return "", nil
|
||||
case reflect.Map:
|
||||
if v, ok := propertyValue.Interface().(bazel.StringMapAttribute); ok {
|
||||
return starlark_fmt.PrintStringStringDict(v, indent), nil
|
||||
}
|
||||
return "", fmt.Errorf("bp2build expects map of type map[string]string for field: %s", propertyValue)
|
||||
default:
|
||||
return "", fmt.Errorf(
|
||||
"unexpected kind for property struct field: %s", propertyValue.Kind())
|
||||
|
@@ -1898,3 +1898,36 @@ func TestGenerateApiBazelTargets(t *testing.T) {
|
||||
Description: "Generating API contribution Bazel targets for custom module",
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenerateConfigSetting(t *testing.T) {
|
||||
bp := `
|
||||
custom {
|
||||
name: "foo",
|
||||
test_config_setting: true,
|
||||
}
|
||||
`
|
||||
expectedBazelTargets := []string{
|
||||
MakeBazelTargetNoRestrictions(
|
||||
"config_setting",
|
||||
"foo_config_setting",
|
||||
AttrNameToString{
|
||||
"flag_values": `{
|
||||
"//build/bazel/rules/my_string_setting": "foo",
|
||||
}`,
|
||||
},
|
||||
),
|
||||
MakeBazelTarget(
|
||||
"custom",
|
||||
"foo",
|
||||
AttrNameToString{},
|
||||
),
|
||||
}
|
||||
registerCustomModule := func(ctx android.RegistrationContext) {
|
||||
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
||||
}
|
||||
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
||||
Blueprint: bp,
|
||||
ExpectedBazelTargets: expectedBazelTargets,
|
||||
Description: "Generating API contribution Bazel targets for custom module",
|
||||
})
|
||||
}
|
||||
|
@@ -108,6 +108,7 @@ custom = rule(
|
||||
"string_literal_prop": attr.string(),
|
||||
"string_prop": attr.string(),
|
||||
"string_ptr_prop": attr.string(),
|
||||
"test_config_setting": attr.bool(),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -139,6 +140,7 @@ custom_defaults = rule(
|
||||
"string_literal_prop": attr.string(),
|
||||
"string_prop": attr.string(),
|
||||
"string_ptr_prop": attr.string(),
|
||||
"test_config_setting": attr.bool(),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -170,6 +172,7 @@ custom_test_ = rule(
|
||||
"string_literal_prop": attr.string(),
|
||||
"string_prop": attr.string(),
|
||||
"string_ptr_prop": attr.string(),
|
||||
"test_config_setting": attr.bool(),
|
||||
# test_prop start
|
||||
# "test_string_prop": attr.string(),
|
||||
# test_prop end
|
||||
|
@@ -4454,3 +4454,32 @@ cc_library {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Test that a config_setting specific to an apex is created by cc_library.
|
||||
func TestCcLibraryCreatesInApexConfigSetting(t *testing.T) {
|
||||
runCcLibraryTestCase(t, Bp2buildTestCase{
|
||||
Description: "cc_library creates a config_setting for each apex in apex_available",
|
||||
ModuleTypeUnderTest: "cc_library",
|
||||
ModuleTypeUnderTestFactory: cc.LibraryFactory,
|
||||
Dir: "build/bazel/rules/apex",
|
||||
Blueprint: `
|
||||
cc_library {
|
||||
name: "foo",
|
||||
apex_available: [
|
||||
"//apex_available:platform", // This will be skipped, since it is equivalent to //build/bazel/rules/apex:android-non_apex
|
||||
"myapex"
|
||||
],
|
||||
}`,
|
||||
ExpectedBazelTargets: []string{
|
||||
MakeBazelTargetNoRestrictions(
|
||||
"config_setting",
|
||||
"android-in_myapex",
|
||||
AttrNameToString{
|
||||
"flag_values": `{
|
||||
"//build/bazel/rules/apex:apex_name": "myapex",
|
||||
}`,
|
||||
},
|
||||
),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@@ -317,6 +317,8 @@ type customProps struct {
|
||||
One_to_many_prop *bool
|
||||
|
||||
Api *string // File describing the APIs of this module
|
||||
|
||||
Test_config_setting *bool // Used to test generation of config_setting targets
|
||||
}
|
||||
|
||||
type customModule struct {
|
||||
@@ -490,6 +492,27 @@ func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
|
||||
}
|
||||
|
||||
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
|
||||
|
||||
if proptools.Bool(m.props.Test_config_setting) {
|
||||
m.createConfigSetting(ctx)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (m *customModule) createConfigSetting(ctx android.TopDownMutatorContext) {
|
||||
csa := bazel.ConfigSettingAttributes{
|
||||
Flag_values: bazel.StringMapAttribute{
|
||||
"//build/bazel/rules/my_string_setting": m.Name(),
|
||||
},
|
||||
}
|
||||
ca := android.CommonAttributes{
|
||||
Name: m.Name() + "_config_setting",
|
||||
}
|
||||
ctx.CreateBazelConfigSetting(
|
||||
csa,
|
||||
ca,
|
||||
ctx.ModuleDir(),
|
||||
)
|
||||
}
|
||||
|
||||
var _ android.ApiProvider = (*customModule)(nil)
|
||||
|
@@ -17,6 +17,7 @@ import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/bazel"
|
||||
@@ -1196,6 +1197,63 @@ func availableToSameApexes(a, b []string) bool {
|
||||
return !differ
|
||||
}
|
||||
|
||||
var (
|
||||
apexConfigSettingKey = android.NewOnceKey("apexConfigSetting")
|
||||
apexConfigSettingLock sync.Mutex
|
||||
)
|
||||
|
||||
func getApexConfigSettingMap(config android.Config) *map[string]bool {
|
||||
return config.Once(apexConfigSettingKey, func() interface{} {
|
||||
return &map[string]bool{}
|
||||
}).(*map[string]bool)
|
||||
}
|
||||
|
||||
// Create a config setting for this apex in build/bazel/rules/apex
|
||||
// The use case for this is stub/impl selection in cc libraries
|
||||
// Long term, these config_setting(s) should be colocated with the respective apex definitions.
|
||||
// Note that this is an anti-pattern: The config_setting should be created from the apex definition
|
||||
// and not from a cc_library.
|
||||
// This anti-pattern is needed today since not all apexes have been allowlisted.
|
||||
func createInApexConfigSetting(ctx android.TopDownMutatorContext, apexName string) {
|
||||
if apexName == android.AvailableToPlatform || apexName == android.AvailableToAnyApex {
|
||||
// These correspond to android-non_apex and android-in_apex
|
||||
return
|
||||
}
|
||||
apexConfigSettingLock.Lock()
|
||||
defer apexConfigSettingLock.Unlock()
|
||||
|
||||
// Return if a config_setting has already been created
|
||||
acsm := getApexConfigSettingMap(ctx.Config())
|
||||
if _, exists := (*acsm)[apexName]; exists {
|
||||
return
|
||||
}
|
||||
(*acsm)[apexName] = true
|
||||
|
||||
csa := bazel.ConfigSettingAttributes{
|
||||
Flag_values: bazel.StringMapAttribute{
|
||||
"//build/bazel/rules/apex:apex_name": apexName,
|
||||
},
|
||||
}
|
||||
ca := android.CommonAttributes{
|
||||
Name: "android-in_" + apexName,
|
||||
}
|
||||
ctx.CreateBazelConfigSetting(
|
||||
csa,
|
||||
ca,
|
||||
"build/bazel/rules/apex",
|
||||
)
|
||||
}
|
||||
|
||||
func inApexConfigSetting(apexAvailable string) string {
|
||||
if apexAvailable == android.AvailableToPlatform {
|
||||
return bazel.AndroidAndNonApex
|
||||
}
|
||||
if apexAvailable == android.AvailableToAnyApex {
|
||||
return bazel.AndroidAndInApex
|
||||
}
|
||||
return "//build/bazel/rules/apex:android-in_" + apexAvailable
|
||||
}
|
||||
|
||||
func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis,
|
||||
config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) {
|
||||
|
||||
@@ -1241,6 +1299,13 @@ func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.C
|
||||
dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
|
||||
}
|
||||
}
|
||||
|
||||
// Create a config_setting for each apex_available.
|
||||
// This will be used to select impl of a dep if dep is available to the same apex.
|
||||
for _, aa := range apexAvailable {
|
||||
createInApexConfigSetting(ctx.(android.TopDownMutatorContext), aa)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
|
||||
|
@@ -99,6 +99,16 @@ func PrintStringIntDict(dict map[string]int, indentLevel int) string {
|
||||
return PrintDict(valDict, indentLevel)
|
||||
}
|
||||
|
||||
// PrintStringStringDict returns a Starlark-compatible string formatted as dictionary with
|
||||
// string keys and string values.
|
||||
func PrintStringStringDict(dict map[string]string, indentLevel int) string {
|
||||
valDict := make(map[string]string, len(dict))
|
||||
for k, v := range dict {
|
||||
valDict[k] = fmt.Sprintf(`"%s"`, v)
|
||||
}
|
||||
return PrintDict(valDict, indentLevel)
|
||||
}
|
||||
|
||||
// PrintDict returns a starlark-compatible string containing a dictionary with string keys and
|
||||
// values printed with no additional formatting.
|
||||
func PrintDict(dict map[string]string, indentLevel int) string {
|
||||
|
Reference in New Issue
Block a user