aboutsummaryrefslogtreecommitdiffstats
path: root/android/arch.go
diff options
context:
space:
mode:
Diffstat (limited to 'android/arch.go')
-rw-r--r--android/arch.go1061
1 files changed, 1061 insertions, 0 deletions
diff --git a/android/arch.go b/android/arch.go
new file mode 100644
index 00000000..952b7207
--- /dev/null
+++ b/android/arch.go
@@ -0,0 +1,1061 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "fmt"
+ "reflect"
+ "runtime"
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterBottomUpMutator("defaults_deps", defaultsDepsMutator)
+ RegisterTopDownMutator("defaults", defaultsMutator)
+
+ RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator)
+ RegisterBottomUpMutator("host_type", HostTypeMutator)
+ RegisterBottomUpMutator("arch", ArchMutator)
+}
+
+var (
+ Arm = newArch("arm", "lib32")
+ Arm64 = newArch("arm64", "lib64")
+ Mips = newArch("mips", "lib32")
+ Mips64 = newArch("mips64", "lib64")
+ X86 = newArch("x86", "lib32")
+ X86_64 = newArch("x86_64", "lib64")
+
+ Common = ArchType{
+ Name: "common",
+ }
+)
+
+var archTypeMap = map[string]ArchType{
+ "arm": Arm,
+ "arm64": Arm64,
+ "mips": Mips,
+ "mips64": Mips64,
+ "x86": X86,
+ "x86_64": X86_64,
+}
+
+/*
+Example blueprints file containing all variant property groups, with comment listing what type
+of variants get properties in that group:
+
+module {
+ arch: {
+ arm: {
+ // Host or device variants with arm architecture
+ },
+ arm64: {
+ // Host or device variants with arm64 architecture
+ },
+ mips: {
+ // Host or device variants with mips architecture
+ },
+ mips64: {
+ // Host or device variants with mips64 architecture
+ },
+ x86: {
+ // Host or device variants with x86 architecture
+ },
+ x86_64: {
+ // Host or device variants with x86_64 architecture
+ },
+ },
+ multilib: {
+ lib32: {
+ // Host or device variants for 32-bit architectures
+ },
+ lib64: {
+ // Host or device variants for 64-bit architectures
+ },
+ },
+ target: {
+ android: {
+ // Device variants
+ },
+ host: {
+ // Host variants
+ },
+ linux: {
+ // Linux host variants
+ },
+ darwin: {
+ // Darwin host variants
+ },
+ windows: {
+ // Windows host variants
+ },
+ not_windows: {
+ // Non-windows host variants
+ },
+ },
+}
+*/
+
+type Embed interface{}
+
+type archProperties struct {
+ // Properties to vary by target architecture
+ Arch struct {
+ // Properties for module variants being built to run on arm (host or device)
+ Arm struct {
+ Embed `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Arm arch variants
+ Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Arm cpu variants
+ Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+
+ // Properties for module variants being built to run on arm64 (host or device)
+ Arm64 struct {
+ Embed `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Arm64 arch variants
+ Armv8_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Arm64 cpu variants
+ Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+
+ // Properties for module variants being built to run on mips (host or device)
+ Mips struct {
+ Embed `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Mips arch variants
+ Mips32_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Mips32r2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Mips32r2_fp_xburst interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Mips32r2dsp_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Mips32r2dspr2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Mips32r6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Mips arch features
+ Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+
+ // Properties for module variants being built to run on mips64 (host or device)
+ Mips64 struct {
+ Embed `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Mips64 arch variants
+ Mips64r2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Mips64r6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+
+ // Mips64 arch features
+ Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+
+ // Properties for module variants being built to run on x86 (host or device)
+ X86 struct {
+ Embed `blueprint:"filter(android:\"arch_variant\")"`
+
+ // X86 arch variants
+ Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Generic variant for X86 on X86_64
+ X86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+
+ // X86 arch features
+ Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Movbe interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+
+ // Properties for module variants being built to run on x86_64 (host or device)
+ X86_64 struct {
+ Embed `blueprint:"filter(android:\"arch_variant\")"`
+
+ // X86 arch variants
+ Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
+
+ // X86 arch features
+ Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+ }
+
+ // Properties to vary by 32-bit or 64-bit
+ Multilib struct {
+ // Properties for module variants being built to run on 32-bit devices
+ Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on 64-bit devices
+ Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+ // Properties to vary by build target (host or device, os, os+archictecture)
+ Target struct {
+ // Properties for module variants being built to run on the host
+ Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on the device
+ Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on arm devices
+ Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on arm64 devices
+ Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on mips devices
+ Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on mips64 devices
+ Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on x86 devices
+ Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on x86_64 devices
+ Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on devices that support 64-bit
+ Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on devices that do not support 64-bit
+ Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on linux hosts
+ Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on linux x86 hosts
+ Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on linux x86_64 hosts
+ Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on darwin hosts
+ Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on darwin x86 hosts
+ Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on darwin x86_64 hosts
+ Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on windows hosts
+ Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on windows x86 hosts
+ Windows_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on windows x86_64 hosts
+ Windows_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ // Properties for module variants being built to run on linux or darwin hosts
+ Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
+ }
+}
+
+var archFeatureMap = map[ArchType]map[string][]string{}
+
+func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
+ archField := proptools.FieldNameForProperty(arch.Name)
+ variantField := proptools.FieldNameForProperty(variant)
+ archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
+ if variant != "" {
+ if !archStruct.FieldByName(variantField).IsValid() {
+ panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
+ }
+ }
+ for _, feature := range features {
+ field := proptools.FieldNameForProperty(feature)
+ if !archStruct.FieldByName(field).IsValid() {
+ panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
+ }
+ }
+ if archFeatureMap[arch] == nil {
+ archFeatureMap[arch] = make(map[string][]string)
+ }
+ archFeatureMap[arch][variant] = features
+}
+
+// An Arch indicates a single CPU architecture.
+type Arch struct {
+ ArchType ArchType
+ ArchVariant string
+ CpuVariant string
+ Abi []string
+ ArchFeatures []string
+}
+
+func (a Arch) String() string {
+ s := a.ArchType.String()
+ if a.ArchVariant != "" {
+ s += "_" + a.ArchVariant
+ }
+ if a.CpuVariant != "" {
+ s += "_" + a.CpuVariant
+ }
+ return s
+}
+
+type ArchType struct {
+ Name string
+ Multilib string
+}
+
+func newArch(name, multilib string) ArchType {
+ return ArchType{
+ Name: name,
+ Multilib: multilib,
+ }
+}
+
+func (a ArchType) String() string {
+ return a.Name
+}
+
+type HostOrDeviceSupported int
+
+const (
+ _ HostOrDeviceSupported = iota
+ HostSupported
+ DeviceSupported
+ HostAndDeviceSupported
+ HostAndDeviceDefault
+)
+
+type HostOrDevice int
+
+const (
+ _ HostOrDevice = iota
+ Host
+ Device
+)
+
+func (hod HostOrDevice) String() string {
+ switch hod {
+ case Device:
+ return "device"
+ case Host:
+ return "host"
+ default:
+ panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
+ }
+}
+
+func (hod HostOrDevice) Property() string {
+ switch hod {
+ case Device:
+ return "android"
+ case Host:
+ return "host"
+ default:
+ panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
+ }
+}
+
+func (hod HostOrDevice) Host() bool {
+ if hod == 0 {
+ panic("HostOrDevice unset")
+ }
+ return hod == Host
+}
+
+func (hod HostOrDevice) Device() bool {
+ if hod == 0 {
+ panic("HostOrDevice unset")
+ }
+ return hod == Device
+}
+
+var hostOrDeviceName = map[HostOrDevice]string{
+ Device: "device",
+ Host: "host",
+}
+
+type HostType int
+
+const (
+ NoHostType HostType = iota
+ Linux
+ Darwin
+ Windows
+)
+
+func CurrentHostType() HostType {
+ switch runtime.GOOS {
+ case "linux":
+ return Linux
+ case "darwin":
+ return Darwin
+ default:
+ panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
+ }
+}
+
+func (ht HostType) String() string {
+ switch ht {
+ case Linux:
+ return "linux"
+ case Darwin:
+ return "darwin"
+ case Windows:
+ return "windows"
+ default:
+ panic(fmt.Sprintf("unexpected HostType value %d", ht))
+ }
+}
+
+func (ht HostType) Field() string {
+ switch ht {
+ case Linux:
+ return "Linux"
+ case Darwin:
+ return "Darwin"
+ case Windows:
+ return "Windows"
+ default:
+ panic(fmt.Sprintf("unexpected HostType value %d", ht))
+ }
+}
+
+var (
+ commonArch = Arch{
+ ArchType: Common,
+ }
+)
+
+func HostOrDeviceMutator(mctx BottomUpMutatorContext) {
+ var module Module
+ var ok bool
+ if module, ok = mctx.Module().(Module); !ok {
+ return
+ }
+
+ hods := []HostOrDevice{}
+
+ if module.base().HostSupported() {
+ hods = append(hods, Host)
+ }
+
+ if module.base().DeviceSupported() {
+ hods = append(hods, Device)
+ }
+
+ if len(hods) == 0 {
+ return
+ }
+
+ hodNames := []string{}
+ for _, hod := range hods {
+ hodNames = append(hodNames, hod.String())
+ }
+
+ modules := mctx.CreateVariations(hodNames...)
+ for i, m := range modules {
+ m.(Module).base().SetHostOrDevice(hods[i])
+ }
+}
+
+func HostTypeMutator(mctx BottomUpMutatorContext) {
+ var module Module
+ var ok bool
+ if module, ok = mctx.Module().(Module); !ok {
+ return
+ }
+
+ if !module.base().HostSupported() || !module.base().HostOrDevice().Host() {
+ return
+ }
+
+ buildTypes, err := decodeHostTypesProductVariables(mctx.Config().(Config).ProductVariables)
+ if err != nil {
+ mctx.ModuleErrorf("%s", err.Error())
+ return
+ }
+
+ typeNames := []string{}
+ for _, ht := range buildTypes {
+ typeNames = append(typeNames, ht.String())
+ }
+
+ modules := mctx.CreateVariations(typeNames...)
+ for i, m := range modules {
+ m.(Module).base().SetHostType(buildTypes[i])
+ }
+}
+
+func ArchMutator(mctx BottomUpMutatorContext) {
+ var module Module
+ var ok bool
+ if module, ok = mctx.Module().(Module); !ok {
+ return
+ }
+
+ moduleArches := []Arch{}
+ multilib := module.base().commonProperties.Compile_multilib
+
+ if module.base().HostSupported() && module.base().HostOrDevice().Host() {
+ hostModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).HostArches[module.base().HostType()])
+ if err != nil {
+ mctx.ModuleErrorf("%s", err.Error())
+ }
+
+ moduleArches = append(moduleArches, hostModuleArches...)
+ }
+
+ if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
+ deviceModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).DeviceArches)
+ if err != nil {
+ mctx.ModuleErrorf("%s", err.Error())
+ }
+
+ moduleArches = append(moduleArches, deviceModuleArches...)
+ }
+
+ if len(moduleArches) == 0 {
+ return
+ }
+
+ archNames := []string{}
+ for _, arch := range moduleArches {
+ archNames = append(archNames, arch.String())
+ }
+
+ modules := mctx.CreateVariations(archNames...)
+
+ for i, m := range modules {
+ m.(Module).base().SetArch(moduleArches[i])
+ m.(Module).base().setArchProperties(mctx)
+ }
+}
+
+func InitArchModule(m Module,
+ propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
+
+ base := m.base()
+
+ base.generalProperties = append(base.generalProperties,
+ propertyStructs...)
+
+ for _, properties := range base.generalProperties {
+ propertiesValue := reflect.ValueOf(properties)
+ if propertiesValue.Kind() != reflect.Ptr {
+ panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
+ propertiesValue.Interface()))
+ }
+
+ propertiesValue = propertiesValue.Elem()
+ if propertiesValue.Kind() != reflect.Struct {
+ panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
+ propertiesValue.Interface()))
+ }
+
+ archProperties := &archProperties{}
+ forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
+ newValue := proptools.CloneEmptyProperties(propertiesValue)
+ v.Set(newValue)
+ })
+
+ base.archProperties = append(base.archProperties, archProperties)
+ }
+
+ var allProperties []interface{}
+ allProperties = append(allProperties, base.generalProperties...)
+ for _, asp := range base.archProperties {
+ allProperties = append(allProperties, asp)
+ }
+
+ return m, allProperties
+}
+
+var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
+
+func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
+ dst, src interface{}, field, srcPrefix string) interface{} {
+
+ srcField := reflect.ValueOf(src).FieldByName(field)
+ if !srcField.IsValid() {
+ ctx.ModuleErrorf("field %q does not exist", srcPrefix)
+ return nil
+ }
+
+ ret := srcField
+
+ if srcField.Kind() == reflect.Struct {
+ srcField = srcField.FieldByName("Embed")
+ }
+
+ src = srcField.Elem().Interface()
+
+ filter := func(property string,
+ dstField, srcField reflect.StructField,
+ dstValue, srcValue interface{}) (bool, error) {
+
+ srcProperty := srcPrefix + "." + property
+
+ if !proptools.HasTag(dstField, "android", "arch_variant") {
+ if ctx.ContainsProperty(srcProperty) {
+ return false, fmt.Errorf("can't be specific to a build variant")
+ } else {
+ return false, nil
+ }
+ }
+
+ return true, nil
+ }
+
+ order := func(property string,
+ dstField, srcField reflect.StructField,
+ dstValue, srcValue interface{}) (proptools.Order, error) {
+ if proptools.HasTag(dstField, "android", "variant_prepend") {
+ return proptools.Prepend, nil
+ } else {
+ return proptools.Append, nil
+ }
+ }
+
+ err := proptools.ExtendProperties(dst, src, filter, order)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
+ }
+ }
+
+ return ret.Interface()
+}
+
+// Rewrite the module's properties structs to contain arch-specific values.
+func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
+ arch := a.commonProperties.CompileArch
+ hod := a.commonProperties.CompileHostOrDevice
+ ht := a.commonProperties.CompileHostType
+
+ if arch.ArchType == Common {
+ return
+ }
+
+ for i := range a.generalProperties {
+ genProps := a.generalProperties[i]
+ archProps := a.archProperties[i]
+ // Handle arch-specific properties in the form:
+ // arch: {
+ // arm64: {
+ // key: value,
+ // },
+ // },
+ t := arch.ArchType
+
+ field := proptools.FieldNameForProperty(t.Name)
+ prefix := "arch." + t.Name
+ archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
+
+ // Handle arch-variant-specific properties in the form:
+ // arch: {
+ // variant: {
+ // key: value,
+ // },
+ // },
+ v := variantReplacer.Replace(arch.ArchVariant)
+ if v != "" {
+ field := proptools.FieldNameForProperty(v)
+ prefix := "arch." + t.Name + "." + v
+ a.appendProperties(ctx, genProps, archStruct, field, prefix)
+ }
+
+ // Handle cpu-variant-specific properties in the form:
+ // arch: {
+ // variant: {
+ // key: value,
+ // },
+ // },
+ c := variantReplacer.Replace(arch.CpuVariant)
+ if c != "" {
+ field := proptools.FieldNameForProperty(c)
+ prefix := "arch." + t.Name + "." + c
+ a.appendProperties(ctx, genProps, archStruct, field, prefix)
+ }
+
+ // Handle arch-feature-specific properties in the form:
+ // arch: {
+ // feature: {
+ // key: value,
+ // },
+ // },
+ for _, feature := range arch.ArchFeatures {
+ field := proptools.FieldNameForProperty(feature)
+ prefix := "arch." + t.Name + "." + feature
+ a.appendProperties(ctx, genProps, archStruct, field, prefix)
+ }
+
+ // Handle multilib-specific properties in the form:
+ // multilib: {
+ // lib32: {
+ // key: value,
+ // },
+ // },
+ field = proptools.FieldNameForProperty(t.Multilib)
+ prefix = "multilib." + t.Multilib
+ a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
+
+ // Handle host-or-device-specific properties in the form:
+ // target: {
+ // host: {
+ // key: value,
+ // },
+ // },
+ hodProperty := hod.Property()
+ field = proptools.FieldNameForProperty(hodProperty)
+ prefix = "target." + hodProperty
+ a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
+
+ // Handle host target properties in the form:
+ // target: {
+ // linux: {
+ // key: value,
+ // },
+ // not_windows: {
+ // key: value,
+ // },
+ // linux_x86: {
+ // key: value,
+ // },
+ // linux_arm: {
+ // key: value,
+ // },
+ // },
+ if hod.Host() {
+ field := ht.Field()
+ prefix := "target." + ht.String()
+ a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
+
+ t := arch.ArchType
+ field = ht.Field() + "_" + t.Name
+ prefix = "target." + ht.String() + "_" + t.Name
+ a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
+
+ if ht != Windows {
+ field := "Not_windows"
+ prefix := "target.not_windows"
+ a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
+ }
+ }
+
+ // Handle 64-bit device properties in the form:
+ // target {
+ // android64 {
+ // key: value,
+ // },
+ // android32 {
+ // key: value,
+ // },
+ // },
+ // WARNING: this is probably not what you want to use in your blueprints file, it selects
+ // options for all targets on a device that supports 64-bit binaries, not just the targets
+ // that are being compiled for 64-bit. Its expected use case is binaries like linker and
+ // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
+ if hod.Device() {
+ if true /* && target_is_64_bit */ {
+ field := "Android64"
+ prefix := "target.android64"
+ a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
+ } else {
+ field := "Android32"
+ prefix := "target.android32"
+ a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
+ }
+ }
+
+ // Handle device architecture properties in the form:
+ // target {
+ // android_arm {
+ // key: value,
+ // },
+ // android_x86 {
+ // key: value,
+ // },
+ // },
+ if hod.Device() {
+ t := arch.ArchType
+ field := "Android_" + t.Name
+ prefix := "target.android_" + t.Name
+ a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
+ }
+
+ if ctx.Failed() {
+ return
+ }
+ }
+}
+
+func forEachInterface(v reflect.Value, f func(reflect.Value)) {
+ switch v.Kind() {
+ case reflect.Interface:
+ f(v)
+ case reflect.Struct:
+ for i := 0; i < v.NumField(); i++ {
+ forEachInterface(v.Field(i), f)
+ }
+ case reflect.Ptr:
+ forEachInterface(v.Elem(), f)
+ default:
+ panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
+ }
+}
+
+// Get a list of HostTypes from the product variables
+func decodeHostTypesProductVariables(variables productVariables) ([]HostType, error) {
+ ret := []HostType{CurrentHostType()}
+
+ if variables.CrossHost != nil && *variables.CrossHost != "" {
+ switch *variables.CrossHost {
+ case "windows":
+ ret = append(ret, Windows)
+ default:
+ return nil, fmt.Errorf("Unsupported secondary host: %s", *variables.CrossHost)
+ }
+ }
+
+ return ret, nil
+}
+
+// Convert the arch product variables into a list of host and device Arch structs
+func decodeArchProductVariables(variables productVariables) (map[HostType][]Arch, []Arch, error) {
+ if variables.HostArch == nil {
+ return nil, nil, fmt.Errorf("No host primary architecture set")
+ }
+
+ hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ hostArches := []Arch{hostArch}
+
+ if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
+ hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ hostArches = append(hostArches, hostSecondaryArch)
+ }
+
+ hostTypeArches := map[HostType][]Arch{
+ CurrentHostType(): hostArches,
+ }
+
+ if variables.CrossHost != nil && *variables.CrossHost != "" {
+ if variables.CrossHostArch == nil || *variables.CrossHostArch == "" {
+ return nil, nil, fmt.Errorf("No cross-host primary architecture set")
+ }
+
+ crossHostArch, err := decodeArch(*variables.CrossHostArch, nil, nil, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ crossHostArches := []Arch{crossHostArch}
+
+ if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
+ crossHostSecondaryArch, err := decodeArch(*variables.CrossHostSecondaryArch, nil, nil, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ crossHostArches = append(crossHostArches, crossHostSecondaryArch)
+ }
+
+ switch *variables.CrossHost {
+ case "windows":
+ hostTypeArches[Windows] = crossHostArches
+ default:
+ return nil, nil, fmt.Errorf("Unsupported cross-host: %s", *variables.CrossHost)
+ }
+ }
+
+ if variables.DeviceArch == nil {
+ return nil, nil, fmt.Errorf("No device primary architecture set")
+ }
+
+ deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
+ variables.DeviceCpuVariant, variables.DeviceAbi)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ deviceArches := []Arch{deviceArch}
+
+ if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
+ deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
+ variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
+ variables.DeviceSecondaryAbi)
+ if err != nil {
+ return nil, nil, err
+ }
+ deviceArches = append(deviceArches, deviceSecondaryArch)
+ }
+
+ return hostTypeArches, deviceArches, nil
+}
+
+func decodeMegaDevice() ([]Arch, error) {
+ archSettings := []struct {
+ arch string
+ archVariant string
+ cpuVariant string
+ abi []string
+ }{
+ // armv5 is only used for unbundled apps
+ //{"arm", "armv5te", "", []string{"armeabi"}},
+ {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
+ {"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
+ {"arm64", "armv8-a", "denver64", []string{"arm64-v8a"}},
+ {"mips", "mips32-fp", "", []string{"mips"}},
+ {"mips", "mips32r2-fp", "", []string{"mips"}},
+ {"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
+ {"mips", "mips32r6", "", []string{"mips"}},
+ // mips32r2dsp[r2]-fp fails in the assembler for divdf3.c in compiler-rt:
+ // (same errors in make and soong)
+ // Error: invalid operands `mtlo $ac0,$11'
+ // Error: invalid operands `mthi $ac0,$12'
+ //{"mips", "mips32r2dsp-fp", "", []string{"mips"}},
+ //{"mips", "mips32r2dspr2-fp", "", []string{"mips"}},
+ // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc
+ //{"mips64", "mips64r2", "", []string{"mips64"}},
+ {"mips64", "mips64r6", "", []string{"mips64"}},
+ {"x86", "", "", []string{"x86"}},
+ {"x86", "atom", "", []string{"x86"}},
+ {"x86", "haswell", "", []string{"x86"}},
+ {"x86", "ivybridge", "", []string{"x86"}},
+ {"x86", "sandybridge", "", []string{"x86"}},
+ {"x86", "silvermont", "", []string{"x86"}},
+ {"x86", "x86_64", "", []string{"x86"}},
+ {"x86_64", "", "", []string{"x86_64"}},
+ {"x86_64", "haswell", "", []string{"x86_64"}},
+ {"x86_64", "ivybridge", "", []string{"x86_64"}},
+ {"x86_64", "sandybridge", "", []string{"x86_64"}},
+ {"x86_64", "silvermont", "", []string{"x86_64"}},
+ }
+
+ var ret []Arch
+
+ for _, config := range archSettings {
+ arch, err := decodeArch(config.arch, &config.archVariant,
+ &config.cpuVariant, &config.abi)
+ if err != nil {
+ return nil, err
+ }
+ ret = append(ret, arch)
+ }
+
+ return ret, nil
+}
+
+// Convert a set of strings from product variables into a single Arch struct
+func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
+ stringPtr := func(p *string) string {
+ if p != nil {
+ return *p
+ }
+ return ""
+ }
+
+ slicePtr := func(p *[]string) []string {
+ if p != nil {
+ return *p
+ }
+ return nil
+ }
+
+ archType, ok := archTypeMap[arch]
+ if !ok {
+ return Arch{}, fmt.Errorf("unknown arch %q", arch)
+ }
+
+ a := Arch{
+ ArchType: archType,
+ ArchVariant: stringPtr(archVariant),
+ CpuVariant: stringPtr(cpuVariant),
+ Abi: slicePtr(abi),
+ }
+
+ if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
+ a.ArchVariant = ""
+ }
+
+ if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
+ a.CpuVariant = ""
+ }
+
+ for i := 0; i < len(a.Abi); i++ {
+ if a.Abi[i] == "" {
+ a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
+ i--
+ }
+ }
+
+ if featureMap, ok := archFeatureMap[archType]; ok {
+ a.ArchFeatures = featureMap[a.ArchVariant]
+ }
+
+ return a, nil
+}
+
+// Use the module multilib setting to select one or more arches from an arch list
+func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
+ buildArches := []Arch{}
+ switch multilib {
+ case "common":
+ buildArches = append(buildArches, commonArch)
+ case "both":
+ buildArches = append(buildArches, arches...)
+ case "first":
+ buildArches = append(buildArches, arches[0])
+ case "32":
+ for _, a := range arches {
+ if a.ArchType.Multilib == "lib32" {
+ buildArches = append(buildArches, a)
+ }
+ }
+ case "64":
+ for _, a := range arches {
+ if a.ArchType.Multilib == "lib64" {
+ buildArches = append(buildArches, a)
+ }
+ }
+ default:
+ return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
+ multilib)
+ //buildArches = append(buildArches, arches[0])
+ }
+
+ return buildArches, nil
+}