summaryrefslogtreecommitdiff
path: root/android/arch.go
diff options
context:
space:
mode:
Diffstat (limited to 'android/arch.go')
-rw-r--r--android/arch.go804
1 files changed, 473 insertions, 331 deletions
diff --git a/android/arch.go b/android/arch.go
index 957a659c6..d14221f7c 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -22,9 +22,12 @@ import (
"strconv"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
+const COMMON_VARIANT = "common"
+
var (
archTypeList []ArchType
@@ -36,7 +39,7 @@ var (
X86_64 = newArch("x86_64", "lib64")
Common = ArchType{
- Name: "common",
+ Name: COMMON_VARIANT,
}
)
@@ -527,7 +530,6 @@ type Arch struct {
CpuVariant string
Abi []string
ArchFeatures []string
- Native bool
}
func (a Arch) String() string {
@@ -557,6 +559,10 @@ func newArch(name, multilib string) ArchType {
return archType
}
+func ArchTypeList() []ArchType {
+ return append([]ArchType(nil), archTypeList...)
+}
+
func (a ArchType) String() string {
return a.Name
}
@@ -590,7 +596,7 @@ var BuildOs = func() OsType {
}()
var (
- osTypeList []OsType
+ OsTypeList []OsType
commonTargetMap = make(map[string]Target)
NoOsType OsType
@@ -601,6 +607,10 @@ var (
Android = NewOsType("android", Device, false)
Fuchsia = NewOsType("fuchsia", Device, false)
+ // A pseudo OSType for a common os variant, which is OSType agnostic and which
+ // has dependencies on all the OS variants.
+ CommonOS = NewOsType("common_os", Generic, false)
+
osArchTypeMap = map[OsType][]ArchType{
Linux: []ArchType{X86, X86_64},
LinuxBionic: []ArchType{X86_64},
@@ -662,7 +672,7 @@ func NewOsType(name string, class OsClass, defDisabled bool) OsType {
DefaultDisabled: defDisabled,
}
- osTypeList = append(osTypeList, os)
+ OsTypeList = append(OsTypeList, os)
if _, found := commonTargetMap[name]; found {
panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
@@ -674,7 +684,7 @@ func NewOsType(name string, class OsClass, defDisabled bool) OsType {
}
func osByName(name string) OsType {
- for _, os := range osTypeList {
+ for _, os := range OsTypeList {
if os.Name == name {
return os
}
@@ -683,13 +693,150 @@ func osByName(name string) OsType {
return NoOsType
}
+type NativeBridgeSupport bool
+
+const (
+ NativeBridgeDisabled NativeBridgeSupport = false
+ NativeBridgeEnabled NativeBridgeSupport = true
+)
+
type Target struct {
- Os OsType
- Arch Arch
+ Os OsType
+ Arch Arch
+ NativeBridge NativeBridgeSupport
+ NativeBridgeHostArchName string
+ NativeBridgeRelativePath string
}
func (target Target) String() string {
- return target.Os.String() + "_" + target.Arch.String()
+ return target.OsVariation() + "_" + target.ArchVariation()
+}
+
+func (target Target) OsVariation() string {
+ return target.Os.String()
+}
+
+func (target Target) ArchVariation() string {
+ var variation string
+ if target.NativeBridge {
+ variation = "native_bridge_"
+ }
+ variation += target.Arch.String()
+
+ return variation
+}
+
+func (target Target) Variations() []blueprint.Variation {
+ return []blueprint.Variation{
+ {Mutator: "os", Variation: target.OsVariation()},
+ {Mutator: "arch", Variation: target.ArchVariation()},
+ }
+}
+
+func osMutator(mctx BottomUpMutatorContext) {
+ var module Module
+ var ok bool
+ if module, ok = mctx.Module().(Module); !ok {
+ return
+ }
+
+ base := module.base()
+
+ if !base.ArchSpecific() {
+ return
+ }
+
+ osClasses := base.OsClassSupported()
+
+ var moduleOSList []OsType
+
+ for _, os := range OsTypeList {
+ supportedClass := false
+ for _, osClass := range osClasses {
+ if os.Class == osClass {
+ supportedClass = true
+ }
+ }
+ if !supportedClass {
+ continue
+ }
+
+ if len(mctx.Config().Targets[os]) == 0 {
+ continue
+ }
+
+ moduleOSList = append(moduleOSList, os)
+ }
+
+ if len(moduleOSList) == 0 {
+ base.Disable()
+ return
+ }
+
+ osNames := make([]string, len(moduleOSList))
+
+ for i, os := range moduleOSList {
+ osNames[i] = os.String()
+ }
+
+ createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
+ if createCommonOSVariant {
+ // A CommonOS variant was requested so add it to the list of OS's variants to
+ // create. It needs to be added to the end because it needs to depend on the
+ // the other variants in the list returned by CreateVariations(...) and inter
+ // variant dependencies can only be created from a later variant in that list to
+ // an earlier one. That is because variants are always processed in the order in
+ // which they are returned from CreateVariations(...).
+ osNames = append(osNames, CommonOS.Name)
+ moduleOSList = append(moduleOSList, CommonOS)
+ }
+
+ modules := mctx.CreateVariations(osNames...)
+ for i, m := range modules {
+ m.base().commonProperties.CompileOS = moduleOSList[i]
+ m.base().setOSProperties(mctx)
+ }
+
+ if createCommonOSVariant {
+ // A CommonOS variant was requested so add dependencies from it (the last one in
+ // the list) to the OS type specific variants.
+ last := len(modules) - 1
+ commonOSVariant := modules[last]
+ commonOSVariant.base().commonProperties.CommonOSVariant = true
+ for _, module := range modules[0:last] {
+ // Ignore modules that are enabled. Note, this will only avoid adding
+ // dependencies on OsType variants that are explicitly disabled in their
+ // properties. The CommonOS variant will still depend on disabled variants
+ // if they are disabled afterwards, e.g. in archMutator if
+ if module.Enabled() {
+ mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
+ }
+ }
+ }
+}
+
+// Identifies the dependency from CommonOS variant to the os specific variants.
+type commonOSTag struct{ blueprint.BaseDependencyTag }
+
+var commonOsToOsSpecificVariantTag = commonOSTag{}
+
+// Get the OsType specific variants for the current CommonOS variant.
+//
+// The returned list will only contain enabled OsType specific variants of the
+// module referenced in the supplied context. An empty list is returned if there
+// are no enabled variants or the supplied context is not for an CommonOS
+// variant.
+func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module {
+ var variants []Module
+ mctx.VisitDirectDeps(func(m Module) {
+ if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag {
+ if m.Enabled() {
+ variants = append(variants, m)
+ }
+ }
+ })
+
+ return variants
}
// archMutator splits a module into a variant for each Target requested by the module. Target selection
@@ -698,10 +845,10 @@ func (target Target) String() string {
// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
// whether the module type can compile for host, device or both.
// - The host_supported and device_supported properties on the module.
-// If host is supported for the module, the Host and HostCross OsClasses are are selected. If device is supported
+// If host is supported for the module, the Host and HostCross OsClasses are selected. If device is supported
// for the module, the Device OsClass is selected.
// Within each selected OsClass, the multilib selection is determined by:
-// - The compile_multilib property if it set (which may be overriden by target.android.compile_multlib or
+// - The compile_multilib property if it set (which may be overridden by target.android.compile_multilib or
// target.host.compile_multilib).
// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set.
// Valid multilib values include:
@@ -729,76 +876,87 @@ func archMutator(mctx BottomUpMutatorContext) {
return
}
- var moduleTargets []Target
- moduleMultiTargets := make(map[int][]Target)
- primaryModules := make(map[int]bool)
- osClasses := base.OsClassSupported()
+ os := base.commonProperties.CompileOS
+ if os == CommonOS {
+ // Make sure that the target related properties are initialized for the
+ // CommonOS variant.
+ addTargetProperties(module, commonTargetMap[os.Name], nil, true)
- for _, os := range osTypeList {
- supportedClass := false
- for _, osClass := range osClasses {
- if os.Class == osClass {
- supportedClass = true
+ // Do not create arch specific variants for the CommonOS variant.
+ return
+ }
+
+ osTargets := mctx.Config().Targets[os]
+ image := base.commonProperties.ImageVariation
+ // Filter NativeBridge targets unless they are explicitly supported
+ // Skip creating native bridge variants for vendor modules
+ if os == Android &&
+ !(Bool(base.commonProperties.Native_bridge_supported) && image == CoreVariation) {
+
+ var targets []Target
+ for _, t := range osTargets {
+ if !t.NativeBridge {
+ targets = append(targets, t)
}
}
- if !supportedClass {
- continue
- }
- osTargets := mctx.Config().Targets[os]
- if len(osTargets) == 0 {
- continue
- }
+ osTargets = targets
+ }
- // only the primary arch in the recovery partition
- if os == Android && module.InstallInRecovery() {
- osTargets = []Target{osTargets[0]}
- }
+ // only the primary arch in the ramdisk / recovery partition
+ if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk()) {
+ osTargets = []Target{osTargets[0]}
+ }
- prefer32 := false
- if base.prefer32 != nil {
- prefer32 = base.prefer32(mctx, base, os.Class)
- }
+ prefer32 := false
+ if base.prefer32 != nil {
+ prefer32 = base.prefer32(mctx, base, os.Class)
+ }
+
+ multilib, extraMultilib := decodeMultilib(base, os.Class)
+ targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
+ if err != nil {
+ mctx.ModuleErrorf("%s", err.Error())
+ }
- multilib, extraMultilib := decodeMultilib(base, os.Class)
- targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
+ var multiTargets []Target
+ if extraMultilib != "" {
+ multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
if err != nil {
mctx.ModuleErrorf("%s", err.Error())
}
+ }
- var multiTargets []Target
- if extraMultilib != "" {
- multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
- if err != nil {
- mctx.ModuleErrorf("%s", err.Error())
- }
- }
-
- if len(targets) > 0 {
- primaryModules[len(moduleTargets)] = true
- moduleMultiTargets[len(moduleTargets)] = multiTargets
- moduleTargets = append(moduleTargets, targets...)
- }
+ if image == RecoveryVariation {
+ primaryArch := mctx.Config().DevicePrimaryArchType()
+ targets = filterToArch(targets, primaryArch)
+ multiTargets = filterToArch(multiTargets, primaryArch)
}
- if len(moduleTargets) == 0 {
- base.commonProperties.Enabled = boolPtr(false)
+ if len(targets) == 0 {
+ base.Disable()
return
}
- targetNames := make([]string, len(moduleTargets))
+ targetNames := make([]string, len(targets))
- for i, target := range moduleTargets {
- targetNames[i] = target.String()
+ for i, target := range targets {
+ targetNames[i] = target.ArchVariation()
}
modules := mctx.CreateVariations(targetNames...)
for i, m := range modules {
- m.(Module).base().SetTarget(moduleTargets[i], moduleMultiTargets[i], primaryModules[i])
+ addTargetProperties(m, targets[i], multiTargets, i == 0)
m.(Module).base().setArchProperties(mctx)
}
}
+func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
+ m.base().commonProperties.CompileTarget = target
+ m.base().commonProperties.CompileMultiTargets = multiTargets
+ m.base().commonProperties.CompilePrimary = primaryTarget
+}
+
func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
switch class {
case Device:
@@ -825,154 +983,41 @@ func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib st
}
}
-func filterArchStructFields(fields []reflect.StructField) (filteredFields []reflect.StructField, filtered bool) {
- for _, field := range fields {
- if !proptools.HasTag(field, "android", "arch_variant") {
- filtered = true
- continue
- }
-
- // The arch_variant field isn't necessary past this point
- // Instead of wasting space, just remove it. Go also has a
- // 16-bit limit on structure name length. The name is constructed
- // based on the Go source representation of the structure, so
- // the tag names count towards that length.
- //
- // TODO: handle the uncommon case of other tags being involved
- if field.Tag == `android:"arch_variant"` {
- field.Tag = ""
- }
-
- // Recurse into structs
- switch field.Type.Kind() {
- case reflect.Struct:
- var subFiltered bool
- field.Type, subFiltered = filterArchStruct(field.Type)
- filtered = filtered || subFiltered
- if field.Type == nil {
- continue
- }
- case reflect.Ptr:
- if field.Type.Elem().Kind() == reflect.Struct {
- nestedType, subFiltered := filterArchStruct(field.Type.Elem())
- filtered = filtered || subFiltered
- if nestedType == nil {
- continue
- }
- field.Type = reflect.PtrTo(nestedType)
- }
- case reflect.Interface:
- panic("Interfaces are not supported in arch_variant properties")
- }
-
- filteredFields = append(filteredFields, field)
- }
-
- return filteredFields, filtered
-}
-
-// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a reflect.Type
-// that only contains the fields in the original type that have an `android:"arch_variant"` struct tag, and a bool
-// that is true if the new struct type has fewer fields than the original type. If there are no fields in the
-// original type with the struct tag it returns nil and true.
-func filterArchStruct(prop reflect.Type) (filteredProp reflect.Type, filtered bool) {
- var fields []reflect.StructField
-
- ptr := prop.Kind() == reflect.Ptr
- if ptr {
- prop = prop.Elem()
- }
-
- for i := 0; i < prop.NumField(); i++ {
- fields = append(fields, prop.Field(i))
- }
-
- filteredFields, filtered := filterArchStructFields(fields)
-
- if len(filteredFields) == 0 {
- return nil, true
- }
-
- if !filtered {
- if ptr {
- return reflect.PtrTo(prop), false
+func filterToArch(targets []Target, arch ArchType) []Target {
+ for i := 0; i < len(targets); i++ {
+ if targets[i].Arch.ArchType != arch {
+ targets = append(targets[:i], targets[i+1:]...)
+ i--
}
- return prop, false
}
-
- ret := reflect.StructOf(filteredFields)
- if ptr {
- ret = reflect.PtrTo(ret)
- }
-
- return ret, true
+ return targets
}
-// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a list of
-// reflect.Type that only contains the fields in the original type that have an `android:"arch_variant"` struct tag,
-// and a bool that is true if the new struct type has fewer fields than the original type. If there are no fields in
-// the original type with the struct tag it returns nil and true. Each returned struct type will have a maximum of
-// 10 top level fields in it to attempt to avoid hitting the reflect.StructOf name length limit, although the limit
-// can still be reached with a single struct field with many fields in it.
-func filterArchStructSharded(prop reflect.Type) (filteredProp []reflect.Type, filtered bool) {
- var fields []reflect.StructField
-
- ptr := prop.Kind() == reflect.Ptr
- if ptr {
- prop = prop.Elem()
- }
-
- for i := 0; i < prop.NumField(); i++ {
- fields = append(fields, prop.Field(i))
- }
-
- fields, filtered = filterArchStructFields(fields)
- if !filtered {
- if ptr {
- return []reflect.Type{reflect.PtrTo(prop)}, false
- }
- return []reflect.Type{prop}, false
- }
-
- if len(fields) == 0 {
- return nil, true
- }
-
- shards := shardFields(fields, 10)
-
- for _, shard := range shards {
- s := reflect.StructOf(shard)
- if ptr {
- s = reflect.PtrTo(s)
- }
- filteredProp = append(filteredProp, s)
- }
-
- return filteredProp, true
+type archPropTypeDesc struct {
+ arch, multilib, target reflect.Type
}
-func shardFields(fields []reflect.StructField, shardSize int) [][]reflect.StructField {
- ret := make([][]reflect.StructField, 0, (len(fields)+shardSize-1)/shardSize)
- for len(fields) > shardSize {
- ret = append(ret, fields[0:shardSize])
- fields = fields[shardSize:]
- }
- if len(fields) > 0 {
- ret = append(ret, fields)
- }
- return ret
+type archPropRoot struct {
+ Arch, Multilib, Target interface{}
}
-// createArchType takes a reflect.Type that is either a struct or a pointer to a struct, and returns a list of
-// reflect.Type that contains the arch-variant properties inside structs for each architecture, os, target, multilib,
-// etc.
-func createArchType(props reflect.Type) []reflect.Type {
- propShards, _ := filterArchStructSharded(props)
+// createArchPropTypeDesc takes a reflect.Type that is either a struct or a pointer to a struct, and
+// returns lists of reflect.Types that contains the arch-variant properties inside structs for each
+// arch, multilib and target property.
+func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc {
+ // Each property struct shard will be nested many times under the runtime generated arch struct,
+ // which can hit the limit of 64kB for the name of runtime generated structs. They are nested
+ // 97 times now, which may grow in the future, plus there is some overhead for the containing
+ // type. This number may need to be reduced if too many are added, but reducing it too far
+ // could cause problems if a single deeply nested property no longer fits in the name.
+ const maxArchTypeNameSize = 500
+
+ propShards, _ := proptools.FilterPropertyStructSharded(props, maxArchTypeNameSize, filterArchStruct)
if len(propShards) == 0 {
return nil
}
- var ret []reflect.Type
+ var ret []archPropTypeDesc
for _, props := range propShards {
variantFields := func(names []string) []reflect.StructField {
@@ -1025,8 +1070,9 @@ func createArchType(props reflect.Type) []reflect.Type {
"Not_windows",
"Arm_on_x86",
"Arm_on_x86_64",
+ "Native_bridge",
}
- for _, os := range osTypeList {
+ for _, os := range OsTypeList {
targets = append(targets, os.Field)
for _, archType := range osArchTypeMap[os] {
@@ -1048,24 +1094,42 @@ func createArchType(props reflect.Type) []reflect.Type {
}
targetType := reflect.StructOf(variantFields(targets))
- ret = append(ret, reflect.StructOf([]reflect.StructField{
- {
- Name: "Arch",
- Type: archType,
- },
- {
- Name: "Multilib",
- Type: multilibType,
- },
- {
- Name: "Target",
- Type: targetType,
- },
- }))
+
+ ret = append(ret, archPropTypeDesc{
+ arch: reflect.PtrTo(archType),
+ multilib: reflect.PtrTo(multilibType),
+ target: reflect.PtrTo(targetType),
+ })
}
return ret
}
+func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.StructField) {
+ if proptools.HasTag(field, "android", "arch_variant") {
+ // The arch_variant field isn't necessary past this point
+ // Instead of wasting space, just remove it. Go also has a
+ // 16-bit limit on structure name length. The name is constructed
+ // based on the Go source representation of the structure, so
+ // the tag names count towards that length.
+
+ androidTag := field.Tag.Get("android")
+ values := strings.Split(androidTag, ",")
+
+ if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` {
+ panic(fmt.Errorf("unexpected tag format %q", field.Tag))
+ }
+ // these tags don't need to be present in the runtime generated struct type.
+ values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
+ if len(values) > 0 {
+ panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
+ }
+
+ field.Tag = ""
+ return true, field
+ }
+ return false, field
+}
+
var archPropTypeMap OncePer
func InitArchModule(m Module) {
@@ -1089,12 +1153,16 @@ func InitArchModule(m Module) {
}
archPropTypes := archPropTypeMap.Once(NewCustomOnceKey(t), func() interface{} {
- return createArchType(t)
- }).([]reflect.Type)
+ return createArchPropTypeDesc(t)
+ }).([]archPropTypeDesc)
var archProperties []interface{}
for _, t := range archPropTypes {
- archProperties = append(archProperties, reflect.New(t).Interface())
+ archProperties = append(archProperties, &archPropRoot{
+ Arch: reflect.Zero(t.arch).Interface(),
+ Multilib: reflect.Zero(t.multilib).Interface(),
+ Target: reflect.Zero(t.target).Interface(),
+ })
}
base.archProperties = append(base.archProperties, archProperties)
m.AddProperties(archProperties...)
@@ -1105,9 +1173,16 @@ func InitArchModule(m Module) {
var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
-func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
+func (m *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value {
+ if src.Kind() == reflect.Ptr {
+ if src.IsNil() {
+ return src
+ }
+ src = src.Elem()
+ }
+
src = src.FieldByName(field)
if !src.IsValid() {
ctx.ModuleErrorf("field %q does not exist", srcPrefix)
@@ -1142,25 +1217,116 @@ func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
return ret
}
-// Rewrite the module's properties structs to contain arch-specific values.
-func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
- arch := a.Arch()
- os := a.Os()
+// Rewrite the module's properties structs to contain os-specific values.
+func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) {
+ os := m.commonProperties.CompileOS
- for i := range a.generalProperties {
- genProps := a.generalProperties[i]
- if a.archProperties[i] == nil {
+ for i := range m.generalProperties {
+ genProps := m.generalProperties[i]
+ if m.archProperties[i] == nil {
continue
}
- for _, archProperties := range a.archProperties[i] {
+ for _, archProperties := range m.archProperties[i] {
archPropValues := reflect.ValueOf(archProperties).Elem()
- archProp := archPropValues.FieldByName("Arch")
- multilibProp := archPropValues.FieldByName("Multilib")
- targetProp := archPropValues.FieldByName("Target")
+ targetProp := archPropValues.FieldByName("Target").Elem()
+
+ // Handle host-specific properties in the form:
+ // target: {
+ // host: {
+ // key: value,
+ // },
+ // },
+ if os.Class == Host || os.Class == HostCross {
+ field := "Host"
+ prefix := "target.host"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ }
+
+ // Handle target OS generalities of the form:
+ // target: {
+ // bionic: {
+ // key: value,
+ // },
+ // }
+ if os.Linux() {
+ field := "Linux"
+ prefix := "target.linux"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ }
+
+ if os.Bionic() {
+ field := "Bionic"
+ prefix := "target.bionic"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ }
+
+ // Handle target OS properties in the form:
+ // target: {
+ // linux_glibc: {
+ // key: value,
+ // },
+ // not_windows: {
+ // key: value,
+ // },
+ // android {
+ // key: value,
+ // },
+ // },
+ field := os.Field
+ prefix := "target." + os.Name
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+
+ if (os.Class == Host || os.Class == HostCross) && os != Windows {
+ field := "Not_windows"
+ prefix := "target.not_windows"
+ m.appendProperties(ctx, genProps, targetProp, 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 os.Class == Device {
+ if ctx.Config().Android64() {
+ field := "Android64"
+ prefix := "target.android64"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ } else {
+ field := "Android32"
+ prefix := "target.android32"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ }
+ }
+ }
+ }
+}
+
+// Rewrite the module's properties structs to contain arch-specific values.
+func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
+ arch := m.Arch()
+ os := m.Os()
+
+ for i := range m.generalProperties {
+ genProps := m.generalProperties[i]
+ if m.archProperties[i] == nil {
+ continue
+ }
+ for _, archProperties := range m.archProperties[i] {
+ archPropValues := reflect.ValueOf(archProperties).Elem()
- var field string
- var prefix string
+ archProp := archPropValues.FieldByName("Arch").Elem()
+ multilibProp := archPropValues.FieldByName("Multilib").Elem()
+ targetProp := archPropValues.FieldByName("Target").Elem()
// Handle arch-specific properties in the form:
// arch: {
@@ -1173,7 +1339,7 @@ func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
if arch.ArchType != Common {
field := proptools.FieldNameForProperty(t.Name)
prefix := "arch." + t.Name
- archStruct := a.appendProperties(ctx, genProps, archProp, field, prefix)
+ archStruct := m.appendProperties(ctx, genProps, archProp, field, prefix)
// Handle arch-variant-specific properties in the form:
// arch: {
@@ -1185,7 +1351,7 @@ func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
if v != "" {
field := proptools.FieldNameForProperty(v)
prefix := "arch." + t.Name + "." + v
- a.appendProperties(ctx, genProps, archStruct, field, prefix)
+ m.appendProperties(ctx, genProps, archStruct, field, prefix)
}
// Handle cpu-variant-specific properties in the form:
@@ -1199,7 +1365,7 @@ func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
if c != "" {
field := proptools.FieldNameForProperty(c)
prefix := "arch." + t.Name + "." + c
- a.appendProperties(ctx, genProps, archStruct, field, prefix)
+ m.appendProperties(ctx, genProps, archStruct, field, prefix)
}
}
@@ -1212,7 +1378,7 @@ func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
for _, feature := range arch.ArchFeatures {
field := proptools.FieldNameForProperty(feature)
prefix := "arch." + t.Name + "." + feature
- a.appendProperties(ctx, genProps, archStruct, field, prefix)
+ m.appendProperties(ctx, genProps, archStruct, field, prefix)
}
// Handle multilib-specific properties in the form:
@@ -1223,71 +1389,35 @@ func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
// },
field = proptools.FieldNameForProperty(t.Multilib)
prefix = "multilib." + t.Multilib
- a.appendProperties(ctx, genProps, multilibProp, field, prefix)
+ m.appendProperties(ctx, genProps, multilibProp, field, prefix)
}
- // Handle host-specific properties in the form:
- // target: {
- // host: {
- // key: value,
- // },
- // },
- if os.Class == Host || os.Class == HostCross {
- field = "Host"
- prefix = "target.host"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
-
- // Handle target OS generalities of the form:
+ // Handle combined OS-feature and arch specific properties in the form:
// target: {
- // bionic: {
- // key: value,
- // },
// bionic_x86: {
// key: value,
// },
// }
- if os.Linux() {
- field = "Linux"
- prefix = "target.linux"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
-
- if arch.ArchType != Common {
- field = "Linux_" + arch.ArchType.Name
- prefix = "target.linux_" + arch.ArchType.Name
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
+ if os.Linux() && arch.ArchType != Common {
+ field := "Linux_" + arch.ArchType.Name
+ prefix := "target.linux_" + arch.ArchType.Name
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
- if os.Bionic() {
- field = "Bionic"
- prefix = "target.bionic"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
-
- if arch.ArchType != Common {
- field = "Bionic_" + t.Name
- prefix = "target.bionic_" + t.Name
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
+ if os.Bionic() && arch.ArchType != Common {
+ field := "Bionic_" + t.Name
+ prefix := "target.bionic_" + t.Name
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
- // Handle target OS properties in the form:
+ // Handle combined OS and arch specific properties in the form:
// target: {
- // linux_glibc: {
- // key: value,
- // },
- // not_windows: {
- // key: value,
- // },
// linux_glibc_x86: {
// key: value,
// },
// linux_glibc_arm: {
// key: value,
// },
- // android {
- // key: value,
- // },
// android_arm {
// key: value,
// },
@@ -1295,53 +1425,30 @@ func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
// key: value,
// },
// },
- field = os.Field
- prefix = "target." + os.Name
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
-
if arch.ArchType != Common {
- field = os.Field + "_" + t.Name
- prefix = "target." + os.Name + "_" + t.Name
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
-
- if (os.Class == Host || os.Class == HostCross) && os != Windows {
- field := "Not_windows"
- prefix := "target.not_windows"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
+ field := os.Field + "_" + t.Name
+ prefix := "target." + os.Name + "_" + t.Name
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
- // Handle 64-bit device properties in the form:
+ // Handle arm on x86 properties in the form:
// target {
- // android64 {
+ // arm_on_x86 {
// key: value,
// },
- // android32 {
+ // arm_on_x86_64 {
// 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
+ // TODO(ccross): is this still necessary with native bridge?
if os.Class == Device {
- if ctx.Config().Android64() {
- field := "Android64"
- prefix := "target.android64"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
- } else {
- field := "Android32"
- prefix := "target.android32"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
-
if (arch.ArchType == X86 && (hasArmAbi(arch) ||
hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
(arch.ArchType == Arm &&
hasX86AndroidArch(ctx.Config().Targets[Android])) {
field := "Arm_on_x86"
prefix := "target.arm_on_x86"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
@@ -1349,7 +1456,12 @@ func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
hasX8664AndroidArch(ctx.Config().Targets[Android])) {
field := "Arm_on_x86_64"
prefix := "target.arm_on_x86_64"
- a.appendProperties(ctx, genProps, targetProp, field, prefix)
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ }
+ if os == Android && m.Target().NativeBridge == NativeBridgeEnabled {
+ field := "Native_bridge"
+ prefix := "target.native_bridge"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
}
}
@@ -1378,7 +1490,9 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
targets := make(map[OsType][]Target)
var targetErr error
- addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string) {
+ addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string,
+ nativeBridgeEnabled NativeBridgeSupport, nativeBridgeHostArchName *string,
+ nativeBridgeRelativePath *string) {
if targetErr != nil {
return
}
@@ -1388,11 +1502,21 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
targetErr = err
return
}
+ nativeBridgeRelativePathStr := String(nativeBridgeRelativePath)
+ nativeBridgeHostArchNameStr := String(nativeBridgeHostArchName)
+
+ // Use guest arch as relative install path by default
+ if nativeBridgeEnabled && nativeBridgeRelativePathStr == "" {
+ nativeBridgeRelativePathStr = arch.ArchType.String()
+ }
targets[os] = append(targets[os],
Target{
- Os: os,
- Arch: arch,
+ Os: os,
+ Arch: arch,
+ NativeBridge: nativeBridgeEnabled,
+ NativeBridgeHostArchName: nativeBridgeHostArchNameStr,
+ NativeBridgeRelativePath: nativeBridgeRelativePathStr,
})
}
@@ -1400,14 +1524,14 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
return nil, fmt.Errorf("No host primary architecture set")
}
- addTarget(BuildOs, *variables.HostArch, nil, nil, nil)
+ addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
- addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil)
+ addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
if Bool(config.Host_bionic) {
- addTarget(LinuxBionic, "x86_64", nil, nil, nil)
+ addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
if String(variables.CrossHost) != "" {
@@ -1420,10 +1544,10 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
return nil, fmt.Errorf("No cross-host primary architecture set")
}
- addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil)
+ addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
- addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil)
+ addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
}
@@ -1434,17 +1558,30 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
}
addTarget(target, *variables.DeviceArch, variables.DeviceArchVariant,
- variables.DeviceCpuVariant, variables.DeviceAbi)
+ variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled, nil, nil)
if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
addTarget(Android, *variables.DeviceSecondaryArch,
variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
- variables.DeviceSecondaryAbi)
+ variables.DeviceSecondaryAbi, NativeBridgeDisabled, nil, nil)
+ }
- deviceArches := targets[Android]
- if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
- deviceArches[1].Arch.Native = false
- }
+ if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" {
+ addTarget(Android, *variables.NativeBridgeArch,
+ variables.NativeBridgeArchVariant, variables.NativeBridgeCpuVariant,
+ variables.NativeBridgeAbi, NativeBridgeEnabled, variables.DeviceArch,
+ variables.NativeBridgeRelativePath)
+ }
+
+ if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" &&
+ variables.NativeBridgeSecondaryArch != nil && *variables.NativeBridgeSecondaryArch != "" {
+ addTarget(Android, *variables.NativeBridgeSecondaryArch,
+ variables.NativeBridgeSecondaryArchVariant,
+ variables.NativeBridgeSecondaryCpuVariant,
+ variables.NativeBridgeSecondaryAbi,
+ NativeBridgeEnabled,
+ variables.DeviceSecondaryArch,
+ variables.NativeBridgeSecondaryRelativePath)
}
}
@@ -1457,18 +1594,13 @@ func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
// hasArmAbi returns true if arch has at least one arm ABI
func hasArmAbi(arch Arch) bool {
- for _, abi := range arch.Abi {
- if strings.HasPrefix(abi, "arm") {
- return true
- }
- }
- return false
+ return PrefixInList(arch.Abi, "arm")
}
-// hasArmArch returns true if targets has at least arm Android arch
+// hasArmArch returns true if targets has at least non-native_bridge arm Android arch
func hasArmAndroidArch(targets []Target) bool {
for _, target := range targets {
- if target.Os == Android && target.Arch.ArchType == Arm {
+ if target.Os == Android && target.Arch.ArchType == Arm && target.NativeBridge == NativeBridgeDisabled {
return true
}
}
@@ -1558,7 +1690,16 @@ func getMegaDeviceConfig() []archConfig {
func getNdkAbisConfig() []archConfig {
return []archConfig{
- {"arm", "armv7-a", "", []string{"armeabi"}},
+ {"arm", "armv7-a", "", []string{"armeabi-v7a"}},
+ {"arm64", "armv8-a", "", []string{"arm64-v8a"}},
+ {"x86", "", "", []string{"x86"}},
+ {"x86_64", "", "", []string{"x86_64"}},
+ }
+}
+
+func getAmlAbisConfig() []archConfig {
+ return []archConfig{
+ {"arm", "armv7-a", "", []string{"armeabi-v7a"}},
{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
{"x86", "", "", []string{"x86"}},
{"x86_64", "", "", []string{"x86_64"}},
@@ -1574,7 +1715,7 @@ func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) {
if err != nil {
return nil, err
}
- arch.Native = false
+
ret = append(ret, Target{
Os: Android,
Arch: arch,
@@ -1603,7 +1744,6 @@ func decodeArch(os OsType, arch string, archVariant, cpuVariant *string, abi []s
ArchVariant: stringPtr(archVariant),
CpuVariant: stringPtr(cpuVariant),
Abi: abi,
- Native: true,
}
if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
@@ -1644,6 +1784,8 @@ func filterMultilibTargets(targets []Target, multilib string) []Target {
return ret
}
+// Return the set of Os specific common architecture targets for each Os in a list of
+// targets.
func getCommonTargets(targets []Target) []Target {
var ret []Target
set := make(map[string]bool)