diff options
Diffstat (limited to 'android/variable.go')
-rw-r--r-- | android/variable.go | 387 |
1 files changed, 0 insertions, 387 deletions
diff --git a/android/variable.go b/android/variable.go index 0040d836d..599f88e3f 100644 --- a/android/variable.go +++ b/android/variable.go @@ -20,8 +20,6 @@ import ( "runtime" "strings" - "android/soong/bazel" - "github.com/google/blueprint/proptools" ) @@ -492,10 +490,6 @@ type ProductVariables struct { CheckVendorSeappViolations *bool `json:",omitempty"` - // PartitionVarsForBazelMigrationOnlyDoNotUse are extra variables that are used to define the - // partition images. They should not be read from soong modules. - PartitionVarsForBazelMigrationOnlyDoNotUse PartitionVariables `json:",omitempty"` - BuildFlags map[string]string `json:",omitempty"` BuildFromSourceStub *bool `json:",omitempty"` @@ -644,387 +638,6 @@ func (this *ProductVariables) GetBuildFlagBool(flag string) bool { return val == "true" } -// ProductConfigContext requires the access to the Module to get product config properties. -type ProductConfigContext interface { - Module() Module -} - -// ProductConfigOrSoongConfigProperty represents either a soong config variable + its value -// or a product config variable. You can get both a ConfigurationAxis and a SelectKey from it -// for use in bazel attributes. ProductVariableProperties() will return a map from properties -> -// this interface -> property structs for use in bp2build converters -type ProductConfigOrSoongConfigProperty interface { - // Name of the product variable or soong config variable - Name() string - // AlwaysEmit returns true for soong config variables but false for product variables. This - // is intended to indicate if we need to always emit empty lists in the select statements. - AlwaysEmit() bool - // ConfigurationAxis returns the bazel.ConfigurationAxis that represents this variable. The - // configuration axis will change depending on the variable and whether it's arch/os variant - // as well. - ConfigurationAxis() bazel.ConfigurationAxis - // SelectKey returns a string that represents the key of a select branch, however, it is not - // actually the real label written out to the build file. - // this.ConfigurationAxis().SelectKey(this.SelectKey()) will give the actual label. - SelectKey() string -} - -// ProductConfigProperty represents a product config variable, and if it is arch-variant or not. -type ProductConfigProperty struct { - // The name of the product variable, e.g. "safestack", "malloc_not_svelte", - // "board" - name string - - arch string -} - -func (p ProductConfigProperty) Name() string { - return p.name -} - -func (p ProductConfigProperty) AlwaysEmit() bool { - return false -} - -func (p ProductConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis { - return bazel.ProductVariableConfigurationAxis(p.arch != "", p.name+"__"+p.arch) -} - -func (p ProductConfigProperty) SelectKey() string { - if p.arch == "" { - return strings.ToLower(p.name) - } else { - return strings.ToLower(p.name + "-" + p.arch) - } -} - -// SoongConfigProperty represents a soong config variable, its value if it's a string variable, -// and if it's dependent on the OS or not -type SoongConfigProperty struct { - name string - namespace string - // Can be an empty string for bool/value soong config variables - value string - // If there is a target: field inside a soong config property struct, the os that it selects - // on will be represented here. - os string -} - -func (p SoongConfigProperty) Name() string { - return p.name -} - -func (p SoongConfigProperty) AlwaysEmit() bool { - return true -} - -func (p SoongConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis { - return bazel.ProductVariableConfigurationAxis(false, p.namespace+"__"+p.name+"__"+p.os) -} - -// SelectKey returns the literal string that represents this variable in a BUILD -// select statement. -func (p SoongConfigProperty) SelectKey() string { - // p.value being conditions_default can happen with or without a desired os. When not using - // an os, we want to emit literally just //conditions:default in the select statement, but - // when using an os, we want to emit namespace__name__conditions_default__os, so that - // the branch is only taken if the variable is not set, and we're on the desired os. - // ConfigurationAxis#SelectKey will map the conditions_default result of this function to - // //conditions:default. - if p.value == bazel.ConditionsDefaultConfigKey && p.os == "" { - return bazel.ConditionsDefaultConfigKey - } - - parts := []string{p.namespace, p.name} - if p.value != "" && p.value != bazel.ConditionsDefaultSelectKey { - parts = append(parts, p.value) - } - if p.os != "" { - parts = append(parts, p.os) - } - - // e.g. acme__feature1, android__board__soc_a, my_namespace__my_variables__my_value__my_os - return strings.ToLower(strings.Join(parts, "__")) -} - -// ProductConfigProperties is a map of maps to group property values according -// their property name and the product config variable they're set under. -// -// The outer map key is the name of the property, like "cflags". -// -// The inner map key is a ProductConfigProperty, which is a struct of product -// variable name, namespace, and the "full configuration" of the product -// variable. -// -// e.g. product variable name: board, namespace: acme, full config: vendor_chip_foo -// -// The value of the map is the interface{} representing the value of the -// property, like ["-DDEFINES"] for cflags. -type ProductConfigProperties map[string]map[ProductConfigOrSoongConfigProperty]interface{} - -func (p *ProductConfigProperties) AddProductConfigProperty( - propertyName, productVariableName, arch string, propertyValue interface{}) { - - productConfigProp := ProductConfigProperty{ - name: productVariableName, // e.g. size, feature1, feature2, FEATURE3, board - arch: arch, // e.g. "", x86, arm64 - } - - p.AddEitherProperty(propertyName, productConfigProp, propertyValue) -} - -func (p *ProductConfigProperties) AddSoongConfigProperty( - propertyName, namespace, variableName, value, os string, propertyValue interface{}) { - - soongConfigProp := SoongConfigProperty{ - namespace: namespace, - name: variableName, // e.g. size, feature1, feature2, FEATURE3, board - value: value, - os: os, // e.g. android, linux_x86 - } - - p.AddEitherProperty(propertyName, soongConfigProp, propertyValue) -} - -func (p *ProductConfigProperties) AddEitherProperty( - propertyName string, key ProductConfigOrSoongConfigProperty, propertyValue interface{}) { - if (*p)[propertyName] == nil { - (*p)[propertyName] = make(map[ProductConfigOrSoongConfigProperty]interface{}) - } - - if existing, ok := (*p)[propertyName][key]; ok { - switch dst := existing.(type) { - case []string: - src, ok := propertyValue.([]string) - if !ok { - panic("Conflicting types") - } - dst = append(dst, src...) - (*p)[propertyName][key] = dst - default: - if existing != propertyValue { - panic(fmt.Errorf("TODO: handle merging value %#v", existing)) - } - } - } else { - (*p)[propertyName][key] = propertyValue - } -} - -// maybeExtractConfigVarProp attempts to read this value as a config var struct -// wrapped by interfaces and ptrs. If it's not the right type, the second return -// value is false. -func maybeExtractConfigVarProp(v reflect.Value) (reflect.Value, bool) { - if v.Kind() == reflect.Interface { - // The conditions_default value can be either - // 1) an ptr to an interface of a struct (bool config variables and product variables) - // 2) an interface of 1) (config variables with nested structs, like string vars) - v = v.Elem() - } - if v.Kind() != reflect.Ptr { - return v, false - } - v = reflect.Indirect(v) - if v.Kind() == reflect.Interface { - // Extract the struct from the interface - v = v.Elem() - } - - if !v.IsValid() { - return v, false - } - - if v.Kind() != reflect.Struct { - return v, false - } - return v, true -} - -func (productConfigProperties *ProductConfigProperties) AddProductConfigProperties(variableValues reflect.Value, arch string) { - // Example of product_variables: - // - // product_variables: { - // malloc_not_svelte: { - // shared_libs: ["malloc_not_svelte_shared_lib"], - // whole_static_libs: ["malloc_not_svelte_whole_static_lib"], - // exclude_static_libs: [ - // "malloc_not_svelte_static_lib_excludes", - // "malloc_not_svelte_whole_static_lib_excludes", - // ], - // }, - // }, - - for i := 0; i < variableValues.NumField(); i++ { - // e.g. Platform_sdk_version, Unbundled_build, Malloc_not_svelte, etc. - productVariableName := variableValues.Type().Field(i).Name - - variableValue := variableValues.Field(i) - // Check if any properties were set for the module - if variableValue.IsZero() { - // e.g. feature1: {}, malloc_not_svelte: {} - continue - } - - for j := 0; j < variableValue.NumField(); j++ { - property := variableValue.Field(j) - // e.g. Asflags, Cflags, Enabled, etc. - propertyName := variableValue.Type().Field(j).Name - if property.Kind() != reflect.Interface { - productConfigProperties.AddProductConfigProperty(propertyName, productVariableName, arch, property.Interface()) - } - } - } - -} - -func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) error { - // - // Example of soong_config_variables: - // - // soong_config_variables: { - // feature1: { - // conditions_default: { - // ... - // }, - // cflags: ... - // }, - // feature2: { - // cflags: ... - // conditions_default: { - // ... - // }, - // }, - // board: { - // soc_a: { - // ... - // }, - // soc_b: { - // ... - // }, - // soc_c: {}, - // conditions_default: { - // ... - // }, - // }, - // } - for i := 0; i < soongConfigVariablesStruct.NumField(); i++ { - // e.g. feature1, feature2, board - variableName := soongConfigVariablesStruct.Type().Field(i).Name - variableStruct := soongConfigVariablesStruct.Field(i) - // Check if any properties were set for the module - if variableStruct.IsZero() { - // e.g. feature1: {} - continue - } - - // Unlike product variables, config variables require a few more - // indirections to extract the struct from the reflect.Value. - if v, ok := maybeExtractConfigVarProp(variableStruct); ok { - variableStruct = v - } else if !v.IsValid() { - // Skip invalid variables which may not used, else leads to panic - continue - } - - for j := 0; j < variableStruct.NumField(); j++ { - propertyOrStruct := variableStruct.Field(j) - // propertyOrValueName can either be: - // - A property, like: Asflags, Cflags, Enabled, etc. - // - A soong config string variable's value, like soc_a, soc_b, soc_c in the example above - // - "conditions_default" - propertyOrValueName := variableStruct.Type().Field(j).Name - - // If the property wasn't set, no need to pass it along - if propertyOrStruct.IsZero() { - continue - } - - if v, ok := maybeExtractConfigVarProp(propertyOrStruct); ok { - // The field is a struct, which is used by: - // 1) soong_config_string_variables - // - // soc_a: { - // cflags: ..., - // } - // - // soc_b: { - // cflags: ..., - // } - // - // 2) conditions_default structs for all soong config variable types. - // - // conditions_default: { - // cflags: ..., - // static_libs: ... - // } - // - // This means that propertyOrValueName is either conditions_default, or a soong - // config string variable's value. - field := v - // Iterate over fields of this struct prop. - for k := 0; k < field.NumField(); k++ { - // For product variables, zero values are irrelevant; however, for soong config variables, - // empty values are relevant because there can also be a conditions default which is not - // applied for empty variables. - if field.Field(k).IsZero() && namespace == "" { - continue - } - - propertyName := field.Type().Field(k).Name - if propertyName == "Target" { - productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), field.Field(k)) - } else if propertyName == "Arch" || propertyName == "Multilib" { - return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs") - } else { - productConfigProperties.AddSoongConfigProperty(propertyName, namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), "", field.Field(k).Interface()) - } - } - } else if propertyOrStruct.Kind() != reflect.Interface { - // If not an interface, then this is not a conditions_default or - // a struct prop. That is, this is a bool/value config variable. - if propertyOrValueName == "Target" { - productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, "", propertyOrStruct) - } else if propertyOrValueName == "Arch" || propertyOrValueName == "Multilib" { - return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs") - } else { - productConfigProperties.AddSoongConfigProperty(propertyOrValueName, namespace, variableName, "", "", propertyOrStruct.Interface()) - } - } - } - } - return nil -} - -func (productConfigProperties *ProductConfigProperties) AddSoongConfigPropertiesFromTargetStruct(namespace, soongConfigVariableName string, soongConfigVariableValue string, targetStruct reflect.Value) { - // targetStruct will be a struct with fields like "android", "host", "arm", "x86", - // "android_arm", etc. The values of each of those fields will be a regular property struct. - for i := 0; i < targetStruct.NumField(); i++ { - targetFieldName := targetStruct.Type().Field(i).Name - archOrOsSpecificStruct := targetStruct.Field(i) - for j := 0; j < archOrOsSpecificStruct.NumField(); j++ { - property := archOrOsSpecificStruct.Field(j) - // e.g. Asflags, Cflags, Enabled, etc. - propertyName := archOrOsSpecificStruct.Type().Field(j).Name - - if targetFieldName == "Android" { - productConfigProperties.AddSoongConfigProperty(propertyName, namespace, soongConfigVariableName, soongConfigVariableValue, "android", property.Interface()) - } else if targetFieldName == "Host" { - for _, os := range osTypeList { - if os.Class == Host { - productConfigProperties.AddSoongConfigProperty(propertyName, namespace, soongConfigVariableName, soongConfigVariableValue, os.Name, property.Interface()) - } - } - } else if !archOrOsSpecificStruct.IsZero() { - // One problem with supporting additional fields is that if multiple branches of - // "target" overlap, we don't want them to be in the same select statement (aka - // configuration axis). "android" and "host" are disjoint, so it's ok that we only - // have 2 axes right now. (soongConfigVariables and soongConfigVariablesPlusOs) - panic("TODO: support other target types in soong config variable structs: " + targetFieldName) - } - } - } -} - func VariableMutator(mctx BottomUpMutatorContext) { var module Module var ok bool |