1// Copyright 2015 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package android 16 17import ( 18 "fmt" 19 "reflect" 20 "runtime" 21 "strings" 22 23 "github.com/google/blueprint/proptools" 24) 25 26var ( 27 archTypeList []ArchType 28 29 Arm = newArch("arm", "lib32") 30 Arm64 = newArch("arm64", "lib64") 31 Mips = newArch("mips", "lib32") 32 Mips64 = newArch("mips64", "lib64") 33 X86 = newArch("x86", "lib32") 34 X86_64 = newArch("x86_64", "lib64") 35 36 Common = ArchType{ 37 Name: "common", 38 } 39) 40 41var archTypeMap = map[string]ArchType{ 42 "arm": Arm, 43 "arm64": Arm64, 44 "mips": Mips, 45 "mips64": Mips64, 46 "x86": X86, 47 "x86_64": X86_64, 48} 49 50/* 51Example blueprints file containing all variant property groups, with comment listing what type 52of variants get properties in that group: 53 54module { 55 arch: { 56 arm: { 57 // Host or device variants with arm architecture 58 }, 59 arm64: { 60 // Host or device variants with arm64 architecture 61 }, 62 mips: { 63 // Host or device variants with mips architecture 64 }, 65 mips64: { 66 // Host or device variants with mips64 architecture 67 }, 68 x86: { 69 // Host or device variants with x86 architecture 70 }, 71 x86_64: { 72 // Host or device variants with x86_64 architecture 73 }, 74 }, 75 multilib: { 76 lib32: { 77 // Host or device variants for 32-bit architectures 78 }, 79 lib64: { 80 // Host or device variants for 64-bit architectures 81 }, 82 }, 83 target: { 84 android: { 85 // Device variants 86 }, 87 host: { 88 // Host variants 89 }, 90 linux: { 91 // Linux host variants 92 }, 93 darwin: { 94 // Darwin host variants 95 }, 96 windows: { 97 // Windows host variants 98 }, 99 not_windows: { 100 // Non-windows host variants 101 }, 102 }, 103} 104*/ 105 106var archVariants = map[ArchType][]string{} 107var archFeatures = map[ArchType][]string{} 108var archFeatureMap = map[ArchType]map[string][]string{} 109 110func RegisterArchVariants(arch ArchType, variants ...string) { 111 checkCalledFromInit() 112 archVariants[arch] = append(archVariants[arch], variants...) 113} 114 115func RegisterArchFeatures(arch ArchType, features ...string) { 116 checkCalledFromInit() 117 archFeatures[arch] = append(archFeatures[arch], features...) 118} 119 120func RegisterArchVariantFeatures(arch ArchType, variant string, features ...string) { 121 checkCalledFromInit() 122 if variant != "" && !inList(variant, archVariants[arch]) { 123 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch)) 124 } 125 126 for _, feature := range features { 127 if !inList(feature, archFeatures[arch]) { 128 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant)) 129 } 130 } 131 132 if archFeatureMap[arch] == nil { 133 archFeatureMap[arch] = make(map[string][]string) 134 } 135 archFeatureMap[arch][variant] = features 136} 137 138// An Arch indicates a single CPU architecture. 139type Arch struct { 140 ArchType ArchType 141 ArchVariant string 142 CpuVariant string 143 Abi []string 144 ArchFeatures []string 145 Native bool 146} 147 148func (a Arch) String() string { 149 s := a.ArchType.String() 150 if a.ArchVariant != "" { 151 s += "_" + a.ArchVariant 152 } 153 if a.CpuVariant != "" { 154 s += "_" + a.CpuVariant 155 } 156 return s 157} 158 159type ArchType struct { 160 Name string 161 Field string 162 Multilib string 163} 164 165func newArch(name, multilib string) ArchType { 166 archType := ArchType{ 167 Name: name, 168 Field: proptools.FieldNameForProperty(name), 169 Multilib: multilib, 170 } 171 archTypeList = append(archTypeList, archType) 172 return archType 173} 174 175func (a ArchType) String() string { 176 return a.Name 177} 178 179var BuildOs = func() OsType { 180 switch runtime.GOOS { 181 case "linux": 182 return Linux 183 case "darwin": 184 return Darwin 185 default: 186 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS)) 187 } 188}() 189 190var ( 191 osTypeList []OsType 192 commonTargetMap = make(map[string]Target) 193 194 NoOsType OsType 195 Linux = NewOsType("linux", Host, false) 196 Darwin = NewOsType("darwin", Host, false) 197 LinuxBionic = NewOsType("linux_bionic", Host, true) 198 Windows = NewOsType("windows", HostCross, true) 199 Android = NewOsType("android", Device, false) 200 201 osArchTypeMap = map[OsType][]ArchType{ 202 Linux: []ArchType{X86, X86_64}, 203 LinuxBionic: []ArchType{X86_64}, 204 Darwin: []ArchType{X86, X86_64}, 205 Windows: []ArchType{X86, X86_64}, 206 Android: []ArchType{Arm, Arm64, Mips, Mips64, X86, X86_64}, 207 } 208) 209 210type OsType struct { 211 Name, Field string 212 Class OsClass 213 214 DefaultDisabled bool 215} 216 217type OsClass int 218 219const ( 220 Generic OsClass = iota 221 Device 222 Host 223 HostCross 224) 225 226func (class OsClass) String() string { 227 switch class { 228 case Generic: 229 return "generic" 230 case Device: 231 return "device" 232 case Host: 233 return "host" 234 case HostCross: 235 return "host cross" 236 default: 237 panic(fmt.Errorf("unknown class %d", class)) 238 } 239} 240 241func (os OsType) String() string { 242 return os.Name 243} 244 245func NewOsType(name string, class OsClass, defDisabled bool) OsType { 246 os := OsType{ 247 Name: name, 248 Field: strings.Title(name), 249 Class: class, 250 251 DefaultDisabled: defDisabled, 252 } 253 osTypeList = append(osTypeList, os) 254 255 if _, found := commonTargetMap[name]; found { 256 panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name)) 257 } else { 258 commonTargetMap[name] = Target{Os: os, Arch: Arch{ArchType: Common}} 259 } 260 261 return os 262} 263 264func osByName(name string) OsType { 265 for _, os := range osTypeList { 266 if os.Name == name { 267 return os 268 } 269 } 270 271 return NoOsType 272} 273 274type Target struct { 275 Os OsType 276 Arch Arch 277} 278 279func (target Target) String() string { 280 return target.Os.String() + "_" + target.Arch.String() 281} 282 283func archMutator(mctx BottomUpMutatorContext) { 284 var module Module 285 var ok bool 286 if module, ok = mctx.Module().(Module); !ok { 287 return 288 } 289 290 if !module.base().ArchSpecific() { 291 return 292 } 293 294 osClasses := module.base().OsClassSupported() 295 296 var moduleTargets []Target 297 primaryModules := make(map[int]bool) 298 299 for _, class := range osClasses { 300 targets := mctx.AConfig().Targets[class] 301 if len(targets) == 0 { 302 continue 303 } 304 var multilib string 305 switch class { 306 case Device: 307 multilib = module.base().commonProperties.Target.Android.Compile_multilib 308 case Host, HostCross: 309 multilib = module.base().commonProperties.Target.Host.Compile_multilib 310 } 311 if multilib == "" { 312 multilib = module.base().commonProperties.Compile_multilib 313 } 314 if multilib == "" { 315 multilib = module.base().commonProperties.Default_multilib 316 } 317 var prefer32 bool 318 switch class { 319 case Device: 320 prefer32 = mctx.AConfig().DevicePrefer32BitExecutables() 321 case HostCross: 322 // Windows builds always prefer 32-bit 323 prefer32 = true 324 } 325 targets, err := decodeMultilib(multilib, targets, prefer32) 326 if err != nil { 327 mctx.ModuleErrorf("%s", err.Error()) 328 } 329 if len(targets) > 0 { 330 primaryModules[len(moduleTargets)] = true 331 moduleTargets = append(moduleTargets, targets...) 332 } 333 } 334 335 if len(moduleTargets) == 0 { 336 module.base().commonProperties.Enabled = boolPtr(false) 337 return 338 } 339 340 targetNames := make([]string, len(moduleTargets)) 341 342 for i, target := range moduleTargets { 343 targetNames[i] = target.String() 344 } 345 346 modules := mctx.CreateVariations(targetNames...) 347 for i, m := range modules { 348 m.(Module).base().SetTarget(moduleTargets[i], primaryModules[i]) 349 m.(Module).base().setArchProperties(mctx) 350 } 351} 352 353func filterArchStruct(prop reflect.Type) (reflect.Type, bool) { 354 var fields []reflect.StructField 355 356 ptr := prop.Kind() == reflect.Ptr 357 if ptr { 358 prop = prop.Elem() 359 } 360 361 for i := 0; i < prop.NumField(); i++ { 362 field := prop.Field(i) 363 if !proptools.HasTag(field, "android", "arch_variant") { 364 continue 365 } 366 367 // The arch_variant field isn't necessary past this point 368 // Instead of wasting space, just remove it. Go also has a 369 // 16-bit limit on structure name length. The name is constructed 370 // based on the Go source representation of the structure, so 371 // the tag names count towards that length. 372 // 373 // TODO: handle the uncommon case of other tags being involved 374 if field.Tag == `android:"arch_variant"` { 375 field.Tag = "" 376 } 377 378 // Recurse into structs 379 switch field.Type.Kind() { 380 case reflect.Struct: 381 var ok bool 382 field.Type, ok = filterArchStruct(field.Type) 383 if !ok { 384 continue 385 } 386 case reflect.Ptr: 387 if field.Type.Elem().Kind() == reflect.Struct { 388 nestedType, ok := filterArchStruct(field.Type.Elem()) 389 if !ok { 390 continue 391 } 392 field.Type = reflect.PtrTo(nestedType) 393 } 394 case reflect.Interface: 395 panic("Interfaces are not supported in arch_variant properties") 396 } 397 398 fields = append(fields, field) 399 } 400 if len(fields) == 0 { 401 return nil, false 402 } 403 404 ret := reflect.StructOf(fields) 405 if ptr { 406 ret = reflect.PtrTo(ret) 407 } 408 return ret, true 409} 410 411func createArchType(props reflect.Type) reflect.Type { 412 props, ok := filterArchStruct(props) 413 if !ok { 414 return nil 415 } 416 417 variantFields := func(names []string) []reflect.StructField { 418 ret := make([]reflect.StructField, len(names)) 419 420 for i, name := range names { 421 ret[i].Name = name 422 ret[i].Type = props 423 } 424 425 return ret 426 } 427 428 archFields := make([]reflect.StructField, len(archTypeList)) 429 for i, arch := range archTypeList { 430 variants := []string{} 431 432 for _, archVariant := range archVariants[arch] { 433 archVariant := variantReplacer.Replace(archVariant) 434 variants = append(variants, proptools.FieldNameForProperty(archVariant)) 435 } 436 for _, feature := range archFeatures[arch] { 437 feature := variantReplacer.Replace(feature) 438 variants = append(variants, proptools.FieldNameForProperty(feature)) 439 } 440 441 fields := variantFields(variants) 442 443 fields = append([]reflect.StructField{reflect.StructField{ 444 Name: "BlueprintEmbed", 445 Type: props, 446 Anonymous: true, 447 }}, fields...) 448 449 archFields[i] = reflect.StructField{ 450 Name: arch.Field, 451 Type: reflect.StructOf(fields), 452 } 453 } 454 archType := reflect.StructOf(archFields) 455 456 multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"})) 457 458 targets := []string{ 459 "Host", 460 "Android64", 461 "Android32", 462 "Not_windows", 463 "Arm_on_x86", 464 "Arm_on_x86_64", 465 } 466 for _, os := range osTypeList { 467 targets = append(targets, os.Field) 468 469 for _, archType := range osArchTypeMap[os] { 470 targets = append(targets, os.Field+"_"+archType.Name) 471 } 472 } 473 474 targetType := reflect.StructOf(variantFields(targets)) 475 return reflect.StructOf([]reflect.StructField{ 476 reflect.StructField{ 477 Name: "Arch", 478 Type: archType, 479 }, 480 reflect.StructField{ 481 Name: "Multilib", 482 Type: multilibType, 483 }, 484 reflect.StructField{ 485 Name: "Target", 486 Type: targetType, 487 }, 488 }) 489} 490 491var archPropTypeMap OncePer 492 493func InitArchModule(m Module) { 494 495 base := m.base() 496 497 base.generalProperties = m.GetProperties() 498 499 for _, properties := range base.generalProperties { 500 propertiesValue := reflect.ValueOf(properties) 501 t := propertiesValue.Type() 502 if propertiesValue.Kind() != reflect.Ptr { 503 panic(fmt.Errorf("properties must be a pointer to a struct, got %T", 504 propertiesValue.Interface())) 505 } 506 507 propertiesValue = propertiesValue.Elem() 508 if propertiesValue.Kind() != reflect.Struct { 509 panic(fmt.Errorf("properties must be a pointer to a struct, got %T", 510 propertiesValue.Interface())) 511 } 512 513 archPropType := archPropTypeMap.Once(t, func() interface{} { 514 return createArchType(t) 515 }) 516 517 if archPropType != nil { 518 base.archProperties = append(base.archProperties, reflect.New(archPropType.(reflect.Type)).Interface()) 519 } else { 520 base.archProperties = append(base.archProperties, nil) 521 } 522 } 523 524 for _, asp := range base.archProperties { 525 if asp != nil { 526 m.AddProperties(asp) 527 } 528 } 529 530 base.customizableProperties = m.GetProperties() 531} 532 533var variantReplacer = strings.NewReplacer("-", "_", ".", "_") 534 535func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext, 536 dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value { 537 538 src = src.FieldByName(field) 539 if !src.IsValid() { 540 ctx.ModuleErrorf("field %q does not exist", srcPrefix) 541 return src 542 } 543 544 ret := src 545 546 if src.Kind() == reflect.Struct { 547 src = src.FieldByName("BlueprintEmbed") 548 } 549 550 order := func(property string, 551 dstField, srcField reflect.StructField, 552 dstValue, srcValue interface{}) (proptools.Order, error) { 553 if proptools.HasTag(dstField, "android", "variant_prepend") { 554 return proptools.Prepend, nil 555 } else { 556 return proptools.Append, nil 557 } 558 } 559 560 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, order) 561 if err != nil { 562 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { 563 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) 564 } else { 565 panic(err) 566 } 567 } 568 569 return ret 570} 571 572// Rewrite the module's properties structs to contain arch-specific values. 573func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) { 574 arch := a.Arch() 575 os := a.Os() 576 577 if arch.ArchType == Common { 578 return 579 } 580 581 for i := range a.generalProperties { 582 genProps := a.generalProperties[i] 583 if a.archProperties[i] == nil { 584 continue 585 } 586 archProps := reflect.ValueOf(a.archProperties[i]).Elem() 587 588 archProp := archProps.FieldByName("Arch") 589 multilibProp := archProps.FieldByName("Multilib") 590 targetProp := archProps.FieldByName("Target") 591 592 // Handle arch-specific properties in the form: 593 // arch: { 594 // arm64: { 595 // key: value, 596 // }, 597 // }, 598 t := arch.ArchType 599 600 field := proptools.FieldNameForProperty(t.Name) 601 prefix := "arch." + t.Name 602 archStruct := a.appendProperties(ctx, genProps, archProp, field, prefix) 603 604 // Handle arch-variant-specific properties in the form: 605 // arch: { 606 // variant: { 607 // key: value, 608 // }, 609 // }, 610 v := variantReplacer.Replace(arch.ArchVariant) 611 if v != "" { 612 field := proptools.FieldNameForProperty(v) 613 prefix := "arch." + t.Name + "." + v 614 a.appendProperties(ctx, genProps, archStruct, field, prefix) 615 } 616 617 // Handle cpu-variant-specific properties in the form: 618 // arch: { 619 // variant: { 620 // key: value, 621 // }, 622 // }, 623 if arch.CpuVariant != arch.ArchVariant { 624 c := variantReplacer.Replace(arch.CpuVariant) 625 if c != "" { 626 field := proptools.FieldNameForProperty(c) 627 prefix := "arch." + t.Name + "." + c 628 a.appendProperties(ctx, genProps, archStruct, field, prefix) 629 } 630 } 631 632 // Handle arch-feature-specific properties in the form: 633 // arch: { 634 // feature: { 635 // key: value, 636 // }, 637 // }, 638 for _, feature := range arch.ArchFeatures { 639 field := proptools.FieldNameForProperty(feature) 640 prefix := "arch." + t.Name + "." + feature 641 a.appendProperties(ctx, genProps, archStruct, field, prefix) 642 } 643 644 // Handle multilib-specific properties in the form: 645 // multilib: { 646 // lib32: { 647 // key: value, 648 // }, 649 // }, 650 field = proptools.FieldNameForProperty(t.Multilib) 651 prefix = "multilib." + t.Multilib 652 a.appendProperties(ctx, genProps, multilibProp, field, prefix) 653 654 // Handle host-specific properties in the form: 655 // target: { 656 // host: { 657 // key: value, 658 // }, 659 // }, 660 if os.Class == Host || os.Class == HostCross { 661 field = "Host" 662 prefix = "target.host" 663 a.appendProperties(ctx, genProps, targetProp, field, prefix) 664 } 665 666 // Handle target OS properties in the form: 667 // target: { 668 // linux: { 669 // key: value, 670 // }, 671 // not_windows: { 672 // key: value, 673 // }, 674 // linux_x86: { 675 // key: value, 676 // }, 677 // linux_arm: { 678 // key: value, 679 // }, 680 // android { 681 // key: value, 682 // }, 683 // android_arm { 684 // key: value, 685 // }, 686 // android_x86 { 687 // key: value, 688 // }, 689 // }, 690 // }, 691 field = os.Field 692 prefix = "target." + os.Name 693 a.appendProperties(ctx, genProps, targetProp, field, prefix) 694 695 field = os.Field + "_" + t.Name 696 prefix = "target." + os.Name + "_" + t.Name 697 a.appendProperties(ctx, genProps, targetProp, field, prefix) 698 699 if (os.Class == Host || os.Class == HostCross) && os != Windows { 700 field := "Not_windows" 701 prefix := "target.not_windows" 702 a.appendProperties(ctx, genProps, targetProp, field, prefix) 703 } 704 705 // Handle 64-bit device properties in the form: 706 // target { 707 // android64 { 708 // key: value, 709 // }, 710 // android32 { 711 // key: value, 712 // }, 713 // }, 714 // WARNING: this is probably not what you want to use in your blueprints file, it selects 715 // options for all targets on a device that supports 64-bit binaries, not just the targets 716 // that are being compiled for 64-bit. Its expected use case is binaries like linker and 717 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device 718 if os.Class == Device { 719 if ctx.AConfig().Android64() { 720 field := "Android64" 721 prefix := "target.android64" 722 a.appendProperties(ctx, genProps, targetProp, field, prefix) 723 } else { 724 field := "Android32" 725 prefix := "target.android32" 726 a.appendProperties(ctx, genProps, targetProp, field, prefix) 727 } 728 729 if arch.ArchType == X86 && (hasArmAbi(arch) || 730 hasArmAndroidArch(ctx.AConfig().Targets[Device])) { 731 field := "Arm_on_x86" 732 prefix := "target.arm_on_x86" 733 a.appendProperties(ctx, genProps, targetProp, field, prefix) 734 } 735 if arch.ArchType == X86_64 && (hasArmAbi(arch) || 736 hasArmAndroidArch(ctx.AConfig().Targets[Device])) { 737 field := "Arm_on_x86_64" 738 prefix := "target.arm_on_x86_64" 739 a.appendProperties(ctx, genProps, targetProp, field, prefix) 740 } 741 } 742 } 743} 744 745func forEachInterface(v reflect.Value, f func(reflect.Value)) { 746 switch v.Kind() { 747 case reflect.Interface: 748 f(v) 749 case reflect.Struct: 750 for i := 0; i < v.NumField(); i++ { 751 forEachInterface(v.Field(i), f) 752 } 753 case reflect.Ptr: 754 forEachInterface(v.Elem(), f) 755 default: 756 panic(fmt.Errorf("Unsupported kind %s", v.Kind())) 757 } 758} 759 760// Convert the arch product variables into a list of targets for each os class structs 761func decodeTargetProductVariables(config *config) (map[OsClass][]Target, error) { 762 variables := config.ProductVariables 763 764 targets := make(map[OsClass][]Target) 765 var targetErr error 766 767 addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi *[]string) { 768 if targetErr != nil { 769 return 770 } 771 772 arch, err := decodeArch(archName, archVariant, cpuVariant, abi) 773 if err != nil { 774 targetErr = err 775 return 776 } 777 778 targets[os.Class] = append(targets[os.Class], 779 Target{ 780 Os: os, 781 Arch: arch, 782 }) 783 } 784 785 if variables.HostArch == nil { 786 return nil, fmt.Errorf("No host primary architecture set") 787 } 788 789 addTarget(BuildOs, *variables.HostArch, nil, nil, nil) 790 791 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" { 792 addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil) 793 } 794 795 if config.Host_bionic != nil && *config.Host_bionic { 796 addTarget(LinuxBionic, "x86_64", nil, nil, nil) 797 } 798 799 if variables.CrossHost != nil && *variables.CrossHost != "" { 800 crossHostOs := osByName(*variables.CrossHost) 801 if crossHostOs == NoOsType { 802 return nil, fmt.Errorf("Unknown cross host OS %q", *variables.CrossHost) 803 } 804 805 if variables.CrossHostArch == nil || *variables.CrossHostArch == "" { 806 return nil, fmt.Errorf("No cross-host primary architecture set") 807 } 808 809 addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil) 810 811 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" { 812 addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil) 813 } 814 } 815 816 if variables.DeviceArch != nil && *variables.DeviceArch != "" { 817 addTarget(Android, *variables.DeviceArch, variables.DeviceArchVariant, 818 variables.DeviceCpuVariant, variables.DeviceAbi) 819 820 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" { 821 addTarget(Android, *variables.DeviceSecondaryArch, 822 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant, 823 variables.DeviceSecondaryAbi) 824 825 deviceArches := targets[Device] 826 if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib { 827 deviceArches[1].Arch.Native = false 828 } 829 } 830 } 831 832 if targetErr != nil { 833 return nil, targetErr 834 } 835 836 return targets, nil 837} 838 839// hasArmAbi returns true if arch has at least one arm ABI 840func hasArmAbi(arch Arch) bool { 841 for _, abi := range arch.Abi { 842 if strings.HasPrefix(abi, "arm") { 843 return true 844 } 845 } 846 return false 847} 848 849// hasArmArch returns true if targets has at least arm Android arch 850func hasArmAndroidArch(targets []Target) bool { 851 for _, target := range targets { 852 if target.Os == Android && target.Arch.ArchType == Arm { 853 return true 854 } 855 } 856 return false 857} 858 859type archConfig struct { 860 arch string 861 archVariant string 862 cpuVariant string 863 abi []string 864} 865 866func getMegaDeviceConfig() []archConfig { 867 return []archConfig{ 868 // armv5 is only used for unbundled apps 869 //{"arm", "armv5te", "", []string{"armeabi"}}, 870 {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}}, 871 {"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}}, 872 {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}}, 873 {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}}, 874 {"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}}, 875 {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}}, 876 {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}}, 877 {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}}, 878 {"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}}, 879 {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}}, 880 {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}}, 881 {"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}}, 882 {"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}}, 883 {"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}}, 884 {"arm64", "armv8-a", "denver64", []string{"arm64-v8a"}}, 885 {"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}}, 886 {"mips", "mips32-fp", "", []string{"mips"}}, 887 {"mips", "mips32r2-fp", "", []string{"mips"}}, 888 {"mips", "mips32r2-fp-xburst", "", []string{"mips"}}, 889 //{"mips", "mips32r6", "", []string{"mips"}}, 890 {"mips", "mips32r2dsp-fp", "", []string{"mips"}}, 891 {"mips", "mips32r2dspr2-fp", "", []string{"mips"}}, 892 // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc 893 //{"mips64", "mips64r2", "", []string{"mips64"}}, 894 {"mips64", "mips64r6", "", []string{"mips64"}}, 895 {"x86", "", "", []string{"x86"}}, 896 {"x86", "atom", "", []string{"x86"}}, 897 {"x86", "haswell", "", []string{"x86"}}, 898 {"x86", "ivybridge", "", []string{"x86"}}, 899 {"x86", "sandybridge", "", []string{"x86"}}, 900 {"x86", "silvermont", "", []string{"x86"}}, 901 {"x86", "x86_64", "", []string{"x86"}}, 902 {"x86_64", "", "", []string{"x86_64"}}, 903 {"x86_64", "haswell", "", []string{"x86_64"}}, 904 {"x86_64", "ivybridge", "", []string{"x86_64"}}, 905 {"x86_64", "sandybridge", "", []string{"x86_64"}}, 906 {"x86_64", "silvermont", "", []string{"x86_64"}}, 907 } 908} 909 910func getNdkAbisConfig() []archConfig { 911 return []archConfig{ 912 {"arm", "armv5te", "", []string{"armeabi"}}, 913 {"arm64", "armv8-a", "", []string{"arm64-v8a"}}, 914 {"mips", "mips32-fp", "", []string{"mips"}}, 915 {"mips64", "mips64r6", "", []string{"mips64"}}, 916 {"x86", "", "", []string{"x86"}}, 917 {"x86_64", "", "", []string{"x86_64"}}, 918 } 919} 920 921func decodeArchSettings(archConfigs []archConfig) ([]Target, error) { 922 var ret []Target 923 924 for _, config := range archConfigs { 925 arch, err := decodeArch(config.arch, &config.archVariant, 926 &config.cpuVariant, &config.abi) 927 if err != nil { 928 return nil, err 929 } 930 arch.Native = false 931 ret = append(ret, Target{ 932 Os: Android, 933 Arch: arch, 934 }) 935 } 936 937 return ret, nil 938} 939 940// Convert a set of strings from product variables into a single Arch struct 941func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) { 942 stringPtr := func(p *string) string { 943 if p != nil { 944 return *p 945 } 946 return "" 947 } 948 949 slicePtr := func(p *[]string) []string { 950 if p != nil { 951 return *p 952 } 953 return nil 954 } 955 956 archType, ok := archTypeMap[arch] 957 if !ok { 958 return Arch{}, fmt.Errorf("unknown arch %q", arch) 959 } 960 961 a := Arch{ 962 ArchType: archType, 963 ArchVariant: stringPtr(archVariant), 964 CpuVariant: stringPtr(cpuVariant), 965 Abi: slicePtr(abi), 966 Native: true, 967 } 968 969 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" { 970 a.ArchVariant = "" 971 } 972 973 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" { 974 a.CpuVariant = "" 975 } 976 977 for i := 0; i < len(a.Abi); i++ { 978 if a.Abi[i] == "" { 979 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...) 980 i-- 981 } 982 } 983 984 if featureMap, ok := archFeatureMap[archType]; ok { 985 a.ArchFeatures = featureMap[a.ArchVariant] 986 } 987 988 return a, nil 989} 990 991func filterMultilibTargets(targets []Target, multilib string) []Target { 992 var ret []Target 993 for _, t := range targets { 994 if t.Arch.ArchType.Multilib == multilib { 995 ret = append(ret, t) 996 } 997 } 998 return ret 999} 1000 1001func getCommonTargets(targets []Target) []Target { 1002 var ret []Target 1003 set := make(map[string]bool) 1004 1005 for _, t := range targets { 1006 if _, found := set[t.Os.String()]; !found { 1007 set[t.Os.String()] = true 1008 ret = append(ret, commonTargetMap[t.Os.String()]) 1009 } 1010 } 1011 1012 return ret 1013} 1014 1015// Use the module multilib setting to select one or more targets from a target list 1016func decodeMultilib(multilib string, targets []Target, prefer32 bool) ([]Target, error) { 1017 buildTargets := []Target{} 1018 if multilib == "first" { 1019 if prefer32 { 1020 multilib = "prefer32" 1021 } else { 1022 multilib = "prefer64" 1023 } 1024 } 1025 switch multilib { 1026 case "common": 1027 buildTargets = append(buildTargets, getCommonTargets(targets)...) 1028 case "both": 1029 if prefer32 { 1030 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...) 1031 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...) 1032 } else { 1033 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...) 1034 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...) 1035 } 1036 case "32": 1037 buildTargets = filterMultilibTargets(targets, "lib32") 1038 case "64": 1039 buildTargets = filterMultilibTargets(targets, "lib64") 1040 case "prefer32": 1041 buildTargets = filterMultilibTargets(targets, "lib32") 1042 if len(buildTargets) == 0 { 1043 buildTargets = filterMultilibTargets(targets, "lib64") 1044 } 1045 case "prefer64": 1046 buildTargets = filterMultilibTargets(targets, "lib64") 1047 if len(buildTargets) == 0 { 1048 buildTargets = filterMultilibTargets(targets, "lib32") 1049 } 1050 default: 1051 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", or "prefer32" found %q`, 1052 multilib) 1053 } 1054 1055 return buildTargets, nil 1056} 1057