Loading android/arch.go +0 −425 Original line number Diff line number Diff line Loading @@ -16,16 +16,11 @@ package android import ( "encoding" "encoding/json" "fmt" "reflect" "runtime" "sort" "strings" "android/soong/bazel" "android/soong/starlark_fmt" "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/proptools" Loading Loading @@ -1899,428 +1894,8 @@ func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([] return buildTargets, nil } func (m *ModuleBase) getArchPropertySet(propertySet interface{}, archType ArchType) interface{} { archString := archType.Field for i := range m.archProperties { if m.archProperties[i] == nil { // Skip over nil properties continue } // Not archProperties are usable; this function looks for properties of a very specific // form, and ignores the rest. for _, archProperty := range m.archProperties[i] { // archPropValue is a property struct, we are looking for the form: // `arch: { arm: { key: value, ... }}` archPropValue := reflect.ValueOf(archProperty).Elem() // Unwrap src so that it should looks like a pointer to `arm: { key: value, ... }` src := archPropValue.FieldByName("Arch").Elem() // Step into non-nil pointers to structs in the src value. if src.Kind() == reflect.Ptr { if src.IsNil() { continue } src = src.Elem() } // Find the requested field (e.g. arm, x86) in the src struct. src = src.FieldByName(archString) // We only care about structs. if !src.IsValid() || src.Kind() != reflect.Struct { continue } // If the value of the field is a struct then step into the // BlueprintEmbed field. The special "BlueprintEmbed" name is // used by createArchPropTypeDesc to embed the arch properties // in the parent struct, so the src arch prop should be in this // field. // // See createArchPropTypeDesc for more details on how Arch-specific // module properties are processed from the nested props and written // into the module's archProperties. src = src.FieldByName("BlueprintEmbed") // Clone the destination prop, since we want a unique prop struct per arch. propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() // Copy the located property struct into the cloned destination property struct. err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace) if err != nil { // This is fine, it just means the src struct doesn't match the type of propertySet. continue } return propertySetClone } } // No property set was found specific to the given arch, so return an empty // property set. return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() } // getMultilibPropertySet returns a property set struct matching the type of // `propertySet`, containing multilib-specific module properties for the given architecture. // If no multilib-specific properties exist for the given architecture, returns an empty property // set matching `propertySet`'s type. func (m *ModuleBase) getMultilibPropertySet(propertySet interface{}, archType ArchType) interface{} { // archType.Multilib is lowercase (for example, lib32) but property struct field is // capitalized, such as Lib32, so use strings.Title to capitalize it. multiLibString := strings.Title(archType.Multilib) for i := range m.archProperties { if m.archProperties[i] == nil { // Skip over nil properties continue } // Not archProperties are usable; this function looks for properties of a very specific // form, and ignores the rest. for _, archProperties := range m.archProperties[i] { // archPropValue is a property struct, we are looking for the form: // `multilib: { lib32: { key: value, ... }}` archPropValue := reflect.ValueOf(archProperties).Elem() // Unwrap src so that it should looks like a pointer to `lib32: { key: value, ... }` src := archPropValue.FieldByName("Multilib").Elem() // Step into non-nil pointers to structs in the src value. if src.Kind() == reflect.Ptr { if src.IsNil() { // Ignore nil pointers. continue } src = src.Elem() } // Find the requested field (e.g. lib32) in the src struct. src = src.FieldByName(multiLibString) // We only care about valid struct pointers. if !src.IsValid() || src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct { continue } // Get the zero value for the requested property set. propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() // Copy the located property struct into the "zero" property set struct. err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace) if err != nil { // This is fine, it just means the src struct doesn't match. continue } return propertySetClone } } // There were no multilib properties specifically matching the given archtype. // Return zeroed value. return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() } // ArchVariantContext defines the limited context necessary to retrieve arch_variant properties. type ArchVariantContext interface { ModuleErrorf(fmt string, args ...interface{}) PropertyErrorf(property, fmt string, args ...interface{}) } // ArchVariantProperties represents a map of arch-variant config strings to a property interface{}. type ArchVariantProperties map[string]interface{} // ConfigurationAxisToArchVariantProperties represents a map of bazel.ConfigurationAxis to // ArchVariantProperties, such that each independent arch-variant axis maps to the // configs/properties for that axis. type ConfigurationAxisToArchVariantProperties map[bazel.ConfigurationAxis]ArchVariantProperties // GetArchVariantProperties returns a ConfigurationAxisToArchVariantProperties where the // arch-variant properties correspond to the values of the properties of the 'propertySet' struct // that are specific to that axis/configuration. Each axis is independent, containing // non-overlapping configs that correspond to the various "arch-variant" support, at this time: // // arches (including multilib) // oses // arch+os combinations // // For example, passing a struct { Foo bool, Bar string } will return an interface{} that can be // type asserted back into the same struct, containing the config-specific property value specified // by the module if defined. // // Arch-specific properties may come from an arch stanza or a multilib stanza; properties // in these stanzas are combined. // For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }` // will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given // propertyset contains `Foo []string`. func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySet interface{}) ConfigurationAxisToArchVariantProperties { // Return value of the arch types to the prop values for that arch. axisToProps := ConfigurationAxisToArchVariantProperties{} // Nothing to do for non-arch-specific modules. if !m.ArchSpecific() { return axisToProps } dstType := reflect.ValueOf(propertySet).Type() var archProperties []interface{} // First find the property set in the module that corresponds to the requested // one. m.archProperties[i] corresponds to m.GetProperties()[i]. for i, generalProp := range m.GetProperties() { srcType := reflect.ValueOf(generalProp).Type() if srcType == dstType { archProperties = m.archProperties[i] axisToProps[bazel.NoConfigAxis] = ArchVariantProperties{"": generalProp} break } } if archProperties == nil { // This module does not have the property set requested return axisToProps } archToProp := ArchVariantProperties{} // For each arch type (x86, arm64, etc.) for _, arch := range ArchTypeList() { // Arch properties are sometimes sharded (see createArchPropTypeDesc() ). // Iterate over every shard and extract a struct with the same type as the // input one that contains the data specific to that arch. propertyStructs := make([]reflect.Value, 0) archFeaturePropertyStructs := make(map[string][]reflect.Value, 0) for _, archProperty := range archProperties { archTypeStruct, ok := getArchTypeStruct(ctx, archProperty, arch) if ok { propertyStructs = append(propertyStructs, archTypeStruct) // For each feature this arch supports (arm: neon, x86: ssse3, sse4, ...) for _, feature := range archFeatures[arch] { prefix := "arch." + arch.Name + "." + feature if featureProperties, ok := getChildPropertyStruct(ctx, archTypeStruct, feature, prefix); ok { archFeaturePropertyStructs[feature] = append(archFeaturePropertyStructs[feature], featureProperties) } } } multilibStruct, ok := getMultilibStruct(ctx, archProperty, arch) if ok { propertyStructs = append(propertyStructs, multilibStruct) } } archToProp[arch.Name] = mergeStructs(ctx, propertyStructs, propertySet) // In soong, if multiple features match the current configuration, they're // all used. In bazel, we have to have unambiguous select() statements, so // we can't have two features that are both active in the same select(). // One alternative is to split out each feature into a separate select(), // but then it's difficult to support exclude_srcs, which may need to // exclude things from the regular arch select() statement if a certain // feature is active. Instead, keep the features in the same select // statement as the arches, but emit the power set of all possible // combinations of features, so that bazel can match the most precise one. allFeatures := make([]string, 0, len(archFeaturePropertyStructs)) for feature := range archFeaturePropertyStructs { allFeatures = append(allFeatures, feature) } for _, features := range bazel.PowerSetWithoutEmptySet(allFeatures) { sort.Strings(features) propsForCurrentFeatureSet := make([]reflect.Value, 0) propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, propertyStructs...) for _, feature := range features { propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, archFeaturePropertyStructs[feature]...) } archToProp[arch.Name+"-"+strings.Join(features, "-")] = mergeStructs(ctx, propsForCurrentFeatureSet, propertySet) } } axisToProps[bazel.ArchConfigurationAxis] = archToProp osToProp := ArchVariantProperties{} archOsToProp := ArchVariantProperties{} linuxStructs := getTargetStructs(ctx, archProperties, "Linux") bionicStructs := getTargetStructs(ctx, archProperties, "Bionic") hostStructs := getTargetStructs(ctx, archProperties, "Host") hostLinuxStructs := getTargetStructs(ctx, archProperties, "Host_linux") hostNotWindowsStructs := getTargetStructs(ctx, archProperties, "Not_windows") // For android, linux, ... for _, os := range osTypeList { if os == CommonOS { // It looks like this OS value is not used in Blueprint files continue } osStructs := make([]reflect.Value, 0) osSpecificStructs := getTargetStructs(ctx, archProperties, os.Field) if os.Class == Host { osStructs = append(osStructs, hostStructs...) } if os.Linux() { osStructs = append(osStructs, linuxStructs...) } if os.Bionic() { osStructs = append(osStructs, bionicStructs...) } if os.Linux() && os.Class == Host { osStructs = append(osStructs, hostLinuxStructs...) } if os == LinuxMusl { osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Musl")...) } if os == Linux { osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Glibc")...) } osStructs = append(osStructs, osSpecificStructs...) if os.Class == Host && os != Windows { osStructs = append(osStructs, hostNotWindowsStructs...) } osToProp[os.Name] = mergeStructs(ctx, osStructs, propertySet) // For arm, x86, ... for _, arch := range osArchTypeMap[os] { osArchStructs := make([]reflect.Value, 0) // Auto-combine with Linux_ and Bionic_ targets. This potentially results in // repetition and select() bloat, but use of Linux_* and Bionic_* targets is rare. // TODO(b/201423152): Look into cleanup. if os.Linux() { targetField := "Linux_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } if os.Bionic() { targetField := "Bionic_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } if os == LinuxMusl { targetField := "Musl_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } if os == Linux { targetField := "Glibc_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } targetField := GetCompoundTargetField(os, arch) targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name) targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) archOsToProp[targetName] = mergeStructs(ctx, osArchStructs, propertySet) } } axisToProps[bazel.OsConfigurationAxis] = osToProp axisToProps[bazel.OsArchConfigurationAxis] = archOsToProp return axisToProps } // Returns a struct matching the propertySet interface, containing properties specific to the targetName // For example, given these arguments: // // propertySet = BaseCompilerProperties // targetName = "android_arm" // // And given this Android.bp fragment: // // target: // android_arm: { // srcs: ["foo.c"], // } // android_arm64: { // srcs: ["bar.c"], // } // } // // This would return a BaseCompilerProperties with BaseCompilerProperties.Srcs = ["foo.c"] func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) []reflect.Value { var propertyStructs []reflect.Value for _, archProperty := range archProperties { archPropValues := reflect.ValueOf(archProperty).Elem() targetProp := archPropValues.FieldByName("Target").Elem() targetStruct, ok := getChildPropertyStruct(ctx, targetProp, targetName, targetName) if ok { propertyStructs = append(propertyStructs, targetStruct) } else { return []reflect.Value{} } } return propertyStructs } func mergeStructs(ctx ArchVariantContext, propertyStructs []reflect.Value, propertySet interface{}) interface{} { // Create a new instance of the requested property set value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() // Merge all the structs together for _, propertyStruct := range propertyStructs { mergePropertyStruct(ctx, value, propertyStruct) } return value } func printArchTypeStarlarkDict(dict map[ArchType][]string) string { valDict := make(map[string]string, len(dict)) for k, v := range dict { valDict[k.String()] = starlark_fmt.PrintStringList(v, 1) } return starlark_fmt.PrintDict(valDict, 0) } func printArchTypeNestedStarlarkDict(dict map[ArchType]map[string][]string) string { valDict := make(map[string]string, len(dict)) for k, v := range dict { valDict[k.String()] = starlark_fmt.PrintStringListDict(v, 1) } return starlark_fmt.PrintDict(valDict, 0) } func printArchConfigList(arches []archConfig) string { jsonOut, err := json.MarshalIndent(arches, "", starlark_fmt.Indention(1)) if err != nil { panic(fmt.Errorf("Error converting arch configs %#v to json: %q", arches, err)) } return fmt.Sprintf("json.decode('''%s''')", string(jsonOut)) } func StarlarkArchConfigurations() string { return fmt.Sprintf(` _arch_to_variants = %s _arch_to_cpu_variants = %s _arch_to_features = %s _android_arch_feature_for_arch_variant = %s _aml_arches = %s _ndk_arches = %s arch_to_variants = _arch_to_variants arch_to_cpu_variants = _arch_to_cpu_variants arch_to_features = _arch_to_features android_arch_feature_for_arch_variants = _android_arch_feature_for_arch_variant aml_arches = _aml_arches ndk_arches = _ndk_arches `, printArchTypeStarlarkDict(archVariants), printArchTypeStarlarkDict(cpuVariants), printArchTypeStarlarkDict(archFeatures), printArchTypeNestedStarlarkDict(androidArchFeatureMap), printArchConfigList(getAmlAbisConfig()), printArchConfigList(getNdkAbisConfig()), ) } android/variable.go +0 −387 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
android/arch.go +0 −425 Original line number Diff line number Diff line Loading @@ -16,16 +16,11 @@ package android import ( "encoding" "encoding/json" "fmt" "reflect" "runtime" "sort" "strings" "android/soong/bazel" "android/soong/starlark_fmt" "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/proptools" Loading Loading @@ -1899,428 +1894,8 @@ func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([] return buildTargets, nil } func (m *ModuleBase) getArchPropertySet(propertySet interface{}, archType ArchType) interface{} { archString := archType.Field for i := range m.archProperties { if m.archProperties[i] == nil { // Skip over nil properties continue } // Not archProperties are usable; this function looks for properties of a very specific // form, and ignores the rest. for _, archProperty := range m.archProperties[i] { // archPropValue is a property struct, we are looking for the form: // `arch: { arm: { key: value, ... }}` archPropValue := reflect.ValueOf(archProperty).Elem() // Unwrap src so that it should looks like a pointer to `arm: { key: value, ... }` src := archPropValue.FieldByName("Arch").Elem() // Step into non-nil pointers to structs in the src value. if src.Kind() == reflect.Ptr { if src.IsNil() { continue } src = src.Elem() } // Find the requested field (e.g. arm, x86) in the src struct. src = src.FieldByName(archString) // We only care about structs. if !src.IsValid() || src.Kind() != reflect.Struct { continue } // If the value of the field is a struct then step into the // BlueprintEmbed field. The special "BlueprintEmbed" name is // used by createArchPropTypeDesc to embed the arch properties // in the parent struct, so the src arch prop should be in this // field. // // See createArchPropTypeDesc for more details on how Arch-specific // module properties are processed from the nested props and written // into the module's archProperties. src = src.FieldByName("BlueprintEmbed") // Clone the destination prop, since we want a unique prop struct per arch. propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() // Copy the located property struct into the cloned destination property struct. err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace) if err != nil { // This is fine, it just means the src struct doesn't match the type of propertySet. continue } return propertySetClone } } // No property set was found specific to the given arch, so return an empty // property set. return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() } // getMultilibPropertySet returns a property set struct matching the type of // `propertySet`, containing multilib-specific module properties for the given architecture. // If no multilib-specific properties exist for the given architecture, returns an empty property // set matching `propertySet`'s type. func (m *ModuleBase) getMultilibPropertySet(propertySet interface{}, archType ArchType) interface{} { // archType.Multilib is lowercase (for example, lib32) but property struct field is // capitalized, such as Lib32, so use strings.Title to capitalize it. multiLibString := strings.Title(archType.Multilib) for i := range m.archProperties { if m.archProperties[i] == nil { // Skip over nil properties continue } // Not archProperties are usable; this function looks for properties of a very specific // form, and ignores the rest. for _, archProperties := range m.archProperties[i] { // archPropValue is a property struct, we are looking for the form: // `multilib: { lib32: { key: value, ... }}` archPropValue := reflect.ValueOf(archProperties).Elem() // Unwrap src so that it should looks like a pointer to `lib32: { key: value, ... }` src := archPropValue.FieldByName("Multilib").Elem() // Step into non-nil pointers to structs in the src value. if src.Kind() == reflect.Ptr { if src.IsNil() { // Ignore nil pointers. continue } src = src.Elem() } // Find the requested field (e.g. lib32) in the src struct. src = src.FieldByName(multiLibString) // We only care about valid struct pointers. if !src.IsValid() || src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct { continue } // Get the zero value for the requested property set. propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() // Copy the located property struct into the "zero" property set struct. err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace) if err != nil { // This is fine, it just means the src struct doesn't match. continue } return propertySetClone } } // There were no multilib properties specifically matching the given archtype. // Return zeroed value. return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() } // ArchVariantContext defines the limited context necessary to retrieve arch_variant properties. type ArchVariantContext interface { ModuleErrorf(fmt string, args ...interface{}) PropertyErrorf(property, fmt string, args ...interface{}) } // ArchVariantProperties represents a map of arch-variant config strings to a property interface{}. type ArchVariantProperties map[string]interface{} // ConfigurationAxisToArchVariantProperties represents a map of bazel.ConfigurationAxis to // ArchVariantProperties, such that each independent arch-variant axis maps to the // configs/properties for that axis. type ConfigurationAxisToArchVariantProperties map[bazel.ConfigurationAxis]ArchVariantProperties // GetArchVariantProperties returns a ConfigurationAxisToArchVariantProperties where the // arch-variant properties correspond to the values of the properties of the 'propertySet' struct // that are specific to that axis/configuration. Each axis is independent, containing // non-overlapping configs that correspond to the various "arch-variant" support, at this time: // // arches (including multilib) // oses // arch+os combinations // // For example, passing a struct { Foo bool, Bar string } will return an interface{} that can be // type asserted back into the same struct, containing the config-specific property value specified // by the module if defined. // // Arch-specific properties may come from an arch stanza or a multilib stanza; properties // in these stanzas are combined. // For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }` // will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given // propertyset contains `Foo []string`. func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySet interface{}) ConfigurationAxisToArchVariantProperties { // Return value of the arch types to the prop values for that arch. axisToProps := ConfigurationAxisToArchVariantProperties{} // Nothing to do for non-arch-specific modules. if !m.ArchSpecific() { return axisToProps } dstType := reflect.ValueOf(propertySet).Type() var archProperties []interface{} // First find the property set in the module that corresponds to the requested // one. m.archProperties[i] corresponds to m.GetProperties()[i]. for i, generalProp := range m.GetProperties() { srcType := reflect.ValueOf(generalProp).Type() if srcType == dstType { archProperties = m.archProperties[i] axisToProps[bazel.NoConfigAxis] = ArchVariantProperties{"": generalProp} break } } if archProperties == nil { // This module does not have the property set requested return axisToProps } archToProp := ArchVariantProperties{} // For each arch type (x86, arm64, etc.) for _, arch := range ArchTypeList() { // Arch properties are sometimes sharded (see createArchPropTypeDesc() ). // Iterate over every shard and extract a struct with the same type as the // input one that contains the data specific to that arch. propertyStructs := make([]reflect.Value, 0) archFeaturePropertyStructs := make(map[string][]reflect.Value, 0) for _, archProperty := range archProperties { archTypeStruct, ok := getArchTypeStruct(ctx, archProperty, arch) if ok { propertyStructs = append(propertyStructs, archTypeStruct) // For each feature this arch supports (arm: neon, x86: ssse3, sse4, ...) for _, feature := range archFeatures[arch] { prefix := "arch." + arch.Name + "." + feature if featureProperties, ok := getChildPropertyStruct(ctx, archTypeStruct, feature, prefix); ok { archFeaturePropertyStructs[feature] = append(archFeaturePropertyStructs[feature], featureProperties) } } } multilibStruct, ok := getMultilibStruct(ctx, archProperty, arch) if ok { propertyStructs = append(propertyStructs, multilibStruct) } } archToProp[arch.Name] = mergeStructs(ctx, propertyStructs, propertySet) // In soong, if multiple features match the current configuration, they're // all used. In bazel, we have to have unambiguous select() statements, so // we can't have two features that are both active in the same select(). // One alternative is to split out each feature into a separate select(), // but then it's difficult to support exclude_srcs, which may need to // exclude things from the regular arch select() statement if a certain // feature is active. Instead, keep the features in the same select // statement as the arches, but emit the power set of all possible // combinations of features, so that bazel can match the most precise one. allFeatures := make([]string, 0, len(archFeaturePropertyStructs)) for feature := range archFeaturePropertyStructs { allFeatures = append(allFeatures, feature) } for _, features := range bazel.PowerSetWithoutEmptySet(allFeatures) { sort.Strings(features) propsForCurrentFeatureSet := make([]reflect.Value, 0) propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, propertyStructs...) for _, feature := range features { propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, archFeaturePropertyStructs[feature]...) } archToProp[arch.Name+"-"+strings.Join(features, "-")] = mergeStructs(ctx, propsForCurrentFeatureSet, propertySet) } } axisToProps[bazel.ArchConfigurationAxis] = archToProp osToProp := ArchVariantProperties{} archOsToProp := ArchVariantProperties{} linuxStructs := getTargetStructs(ctx, archProperties, "Linux") bionicStructs := getTargetStructs(ctx, archProperties, "Bionic") hostStructs := getTargetStructs(ctx, archProperties, "Host") hostLinuxStructs := getTargetStructs(ctx, archProperties, "Host_linux") hostNotWindowsStructs := getTargetStructs(ctx, archProperties, "Not_windows") // For android, linux, ... for _, os := range osTypeList { if os == CommonOS { // It looks like this OS value is not used in Blueprint files continue } osStructs := make([]reflect.Value, 0) osSpecificStructs := getTargetStructs(ctx, archProperties, os.Field) if os.Class == Host { osStructs = append(osStructs, hostStructs...) } if os.Linux() { osStructs = append(osStructs, linuxStructs...) } if os.Bionic() { osStructs = append(osStructs, bionicStructs...) } if os.Linux() && os.Class == Host { osStructs = append(osStructs, hostLinuxStructs...) } if os == LinuxMusl { osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Musl")...) } if os == Linux { osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Glibc")...) } osStructs = append(osStructs, osSpecificStructs...) if os.Class == Host && os != Windows { osStructs = append(osStructs, hostNotWindowsStructs...) } osToProp[os.Name] = mergeStructs(ctx, osStructs, propertySet) // For arm, x86, ... for _, arch := range osArchTypeMap[os] { osArchStructs := make([]reflect.Value, 0) // Auto-combine with Linux_ and Bionic_ targets. This potentially results in // repetition and select() bloat, but use of Linux_* and Bionic_* targets is rare. // TODO(b/201423152): Look into cleanup. if os.Linux() { targetField := "Linux_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } if os.Bionic() { targetField := "Bionic_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } if os == LinuxMusl { targetField := "Musl_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } if os == Linux { targetField := "Glibc_" + arch.Name targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) } targetField := GetCompoundTargetField(os, arch) targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name) targetStructs := getTargetStructs(ctx, archProperties, targetField) osArchStructs = append(osArchStructs, targetStructs...) archOsToProp[targetName] = mergeStructs(ctx, osArchStructs, propertySet) } } axisToProps[bazel.OsConfigurationAxis] = osToProp axisToProps[bazel.OsArchConfigurationAxis] = archOsToProp return axisToProps } // Returns a struct matching the propertySet interface, containing properties specific to the targetName // For example, given these arguments: // // propertySet = BaseCompilerProperties // targetName = "android_arm" // // And given this Android.bp fragment: // // target: // android_arm: { // srcs: ["foo.c"], // } // android_arm64: { // srcs: ["bar.c"], // } // } // // This would return a BaseCompilerProperties with BaseCompilerProperties.Srcs = ["foo.c"] func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) []reflect.Value { var propertyStructs []reflect.Value for _, archProperty := range archProperties { archPropValues := reflect.ValueOf(archProperty).Elem() targetProp := archPropValues.FieldByName("Target").Elem() targetStruct, ok := getChildPropertyStruct(ctx, targetProp, targetName, targetName) if ok { propertyStructs = append(propertyStructs, targetStruct) } else { return []reflect.Value{} } } return propertyStructs } func mergeStructs(ctx ArchVariantContext, propertyStructs []reflect.Value, propertySet interface{}) interface{} { // Create a new instance of the requested property set value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() // Merge all the structs together for _, propertyStruct := range propertyStructs { mergePropertyStruct(ctx, value, propertyStruct) } return value } func printArchTypeStarlarkDict(dict map[ArchType][]string) string { valDict := make(map[string]string, len(dict)) for k, v := range dict { valDict[k.String()] = starlark_fmt.PrintStringList(v, 1) } return starlark_fmt.PrintDict(valDict, 0) } func printArchTypeNestedStarlarkDict(dict map[ArchType]map[string][]string) string { valDict := make(map[string]string, len(dict)) for k, v := range dict { valDict[k.String()] = starlark_fmt.PrintStringListDict(v, 1) } return starlark_fmt.PrintDict(valDict, 0) } func printArchConfigList(arches []archConfig) string { jsonOut, err := json.MarshalIndent(arches, "", starlark_fmt.Indention(1)) if err != nil { panic(fmt.Errorf("Error converting arch configs %#v to json: %q", arches, err)) } return fmt.Sprintf("json.decode('''%s''')", string(jsonOut)) } func StarlarkArchConfigurations() string { return fmt.Sprintf(` _arch_to_variants = %s _arch_to_cpu_variants = %s _arch_to_features = %s _android_arch_feature_for_arch_variant = %s _aml_arches = %s _ndk_arches = %s arch_to_variants = _arch_to_variants arch_to_cpu_variants = _arch_to_cpu_variants arch_to_features = _arch_to_features android_arch_feature_for_arch_variants = _android_arch_feature_for_arch_variant aml_arches = _aml_arches ndk_arches = _ndk_arches `, printArchTypeStarlarkDict(archVariants), printArchTypeStarlarkDict(cpuVariants), printArchTypeStarlarkDict(archFeatures), printArchTypeNestedStarlarkDict(androidArchFeatureMap), printArchConfigList(getAmlAbisConfig()), printArchConfigList(getNdkAbisConfig()), ) }
android/variable.go +0 −387 File changed.Preview size limit exceeded, changes collapsed. Show changes