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 "encoding" 19 "fmt" 20 "reflect" 21 "runtime" 22 "strconv" 23 "strings" 24 25 "github.com/google/blueprint" 26 "github.com/google/blueprint/proptools" 27) 28 29const COMMON_VARIANT = "common" 30 31var ( 32 archTypeList []ArchType 33 34 Arm = newArch("arm", "lib32") 35 Arm64 = newArch("arm64", "lib64") 36 X86 = newArch("x86", "lib32") 37 X86_64 = newArch("x86_64", "lib64") 38 39 Common = ArchType{ 40 Name: COMMON_VARIANT, 41 } 42) 43 44var archTypeMap = map[string]ArchType{ 45 "arm": Arm, 46 "arm64": Arm64, 47 "x86": X86, 48 "x86_64": X86_64, 49} 50 51/* 52Example blueprints file containing all variant property groups, with comment listing what type 53of variants get properties in that group: 54 55module { 56 arch: { 57 arm: { 58 // Host or device variants with arm architecture 59 }, 60 arm64: { 61 // Host or device variants with arm64 architecture 62 }, 63 x86: { 64 // Host or device variants with x86 architecture 65 }, 66 x86_64: { 67 // Host or device variants with x86_64 architecture 68 }, 69 }, 70 multilib: { 71 lib32: { 72 // Host or device variants for 32-bit architectures 73 }, 74 lib64: { 75 // Host or device variants for 64-bit architectures 76 }, 77 }, 78 target: { 79 android: { 80 // Device variants 81 }, 82 host: { 83 // Host variants 84 }, 85 linux_glibc: { 86 // Linux host variants 87 }, 88 darwin: { 89 // Darwin host variants 90 }, 91 windows: { 92 // Windows host variants 93 }, 94 not_windows: { 95 // Non-windows host variants 96 }, 97 }, 98} 99*/ 100 101var archVariants = map[ArchType][]string{ 102 Arm: { 103 "armv7-a", 104 "armv7-a-neon", 105 "armv8-a", 106 "armv8-2a", 107 "cortex-a7", 108 "cortex-a8", 109 "cortex-a9", 110 "cortex-a15", 111 "cortex-a53", 112 "cortex-a53-a57", 113 "cortex-a55", 114 "cortex-a72", 115 "cortex-a73", 116 "cortex-a75", 117 "cortex-a76", 118 "krait", 119 "kryo", 120 "kryo385", 121 "exynos-m1", 122 "exynos-m2", 123 }, 124 Arm64: { 125 "armv8_a", 126 "armv8_2a", 127 "cortex-a53", 128 "cortex-a55", 129 "cortex-a72", 130 "cortex-a73", 131 "cortex-a75", 132 "cortex-a76", 133 "kryo", 134 "kryo385", 135 "exynos-m1", 136 "exynos-m2", 137 }, 138 X86: { 139 "amberlake", 140 "atom", 141 "broadwell", 142 "haswell", 143 "icelake", 144 "ivybridge", 145 "kabylake", 146 "sandybridge", 147 "silvermont", 148 "skylake", 149 "stoneyridge", 150 "tigerlake", 151 "whiskeylake", 152 "x86_64", 153 }, 154 X86_64: { 155 "amberlake", 156 "broadwell", 157 "haswell", 158 "icelake", 159 "ivybridge", 160 "kabylake", 161 "sandybridge", 162 "silvermont", 163 "skylake", 164 "stoneyridge", 165 "tigerlake", 166 "whiskeylake", 167 }, 168} 169 170var archFeatures = map[ArchType][]string{ 171 Arm: { 172 "neon", 173 }, 174 X86: { 175 "ssse3", 176 "sse4", 177 "sse4_1", 178 "sse4_2", 179 "aes_ni", 180 "avx", 181 "avx2", 182 "avx512", 183 "popcnt", 184 "movbe", 185 }, 186 X86_64: { 187 "ssse3", 188 "sse4", 189 "sse4_1", 190 "sse4_2", 191 "aes_ni", 192 "avx", 193 "avx2", 194 "avx512", 195 "popcnt", 196 }, 197} 198 199var archFeatureMap = map[ArchType]map[string][]string{ 200 Arm: { 201 "armv7-a-neon": { 202 "neon", 203 }, 204 "armv8-a": { 205 "neon", 206 }, 207 "armv8-2a": { 208 "neon", 209 }, 210 }, 211 X86: { 212 "amberlake": { 213 "ssse3", 214 "sse4", 215 "sse4_1", 216 "sse4_2", 217 "avx", 218 "avx2", 219 "aes_ni", 220 "popcnt", 221 }, 222 "atom": { 223 "ssse3", 224 "movbe", 225 }, 226 "broadwell": { 227 "ssse3", 228 "sse4", 229 "sse4_1", 230 "sse4_2", 231 "avx", 232 "avx2", 233 "aes_ni", 234 "popcnt", 235 }, 236 "haswell": { 237 "ssse3", 238 "sse4", 239 "sse4_1", 240 "sse4_2", 241 "aes_ni", 242 "avx", 243 "popcnt", 244 "movbe", 245 }, 246 "icelake": { 247 "ssse3", 248 "sse4", 249 "sse4_1", 250 "sse4_2", 251 "avx", 252 "avx2", 253 "avx512", 254 "aes_ni", 255 "popcnt", 256 }, 257 "ivybridge": { 258 "ssse3", 259 "sse4", 260 "sse4_1", 261 "sse4_2", 262 "aes_ni", 263 "avx", 264 "popcnt", 265 }, 266 "kabylake": { 267 "ssse3", 268 "sse4", 269 "sse4_1", 270 "sse4_2", 271 "avx", 272 "avx2", 273 "aes_ni", 274 "popcnt", 275 }, 276 "sandybridge": { 277 "ssse3", 278 "sse4", 279 "sse4_1", 280 "sse4_2", 281 "popcnt", 282 }, 283 "silvermont": { 284 "ssse3", 285 "sse4", 286 "sse4_1", 287 "sse4_2", 288 "aes_ni", 289 "popcnt", 290 "movbe", 291 }, 292 "skylake": { 293 "ssse3", 294 "sse4", 295 "sse4_1", 296 "sse4_2", 297 "avx", 298 "avx2", 299 "avx512", 300 "aes_ni", 301 "popcnt", 302 }, 303 "stoneyridge": { 304 "ssse3", 305 "sse4", 306 "sse4_1", 307 "sse4_2", 308 "aes_ni", 309 "avx", 310 "avx2", 311 "popcnt", 312 "movbe", 313 }, 314 "tigerlake": { 315 "ssse3", 316 "sse4", 317 "sse4_1", 318 "sse4_2", 319 "avx", 320 "avx2", 321 "avx512", 322 "aes_ni", 323 "popcnt", 324 }, 325 "whiskeylake": { 326 "ssse3", 327 "sse4", 328 "sse4_1", 329 "sse4_2", 330 "avx", 331 "avx2", 332 "avx512", 333 "aes_ni", 334 "popcnt", 335 }, 336 "x86_64": { 337 "ssse3", 338 "sse4", 339 "sse4_1", 340 "sse4_2", 341 "popcnt", 342 }, 343 }, 344 X86_64: { 345 "amberlake": { 346 "ssse3", 347 "sse4", 348 "sse4_1", 349 "sse4_2", 350 "avx", 351 "avx2", 352 "aes_ni", 353 "popcnt", 354 }, 355 "broadwell": { 356 "ssse3", 357 "sse4", 358 "sse4_1", 359 "sse4_2", 360 "avx", 361 "avx2", 362 "aes_ni", 363 "popcnt", 364 }, 365 "haswell": { 366 "ssse3", 367 "sse4", 368 "sse4_1", 369 "sse4_2", 370 "aes_ni", 371 "avx", 372 "popcnt", 373 }, 374 "icelake": { 375 "ssse3", 376 "sse4", 377 "sse4_1", 378 "sse4_2", 379 "avx", 380 "avx2", 381 "avx512", 382 "aes_ni", 383 "popcnt", 384 }, 385 "ivybridge": { 386 "ssse3", 387 "sse4", 388 "sse4_1", 389 "sse4_2", 390 "aes_ni", 391 "avx", 392 "popcnt", 393 }, 394 "kabylake": { 395 "ssse3", 396 "sse4", 397 "sse4_1", 398 "sse4_2", 399 "avx", 400 "avx2", 401 "aes_ni", 402 "popcnt", 403 }, 404 "sandybridge": { 405 "ssse3", 406 "sse4", 407 "sse4_1", 408 "sse4_2", 409 "popcnt", 410 }, 411 "silvermont": { 412 "ssse3", 413 "sse4", 414 "sse4_1", 415 "sse4_2", 416 "aes_ni", 417 "popcnt", 418 }, 419 "skylake": { 420 "ssse3", 421 "sse4", 422 "sse4_1", 423 "sse4_2", 424 "avx", 425 "avx2", 426 "avx512", 427 "aes_ni", 428 "popcnt", 429 }, 430 "stoneyridge": { 431 "ssse3", 432 "sse4", 433 "sse4_1", 434 "sse4_2", 435 "aes_ni", 436 "avx", 437 "avx2", 438 "popcnt", 439 }, 440 "tigerlake": { 441 "ssse3", 442 "sse4", 443 "sse4_1", 444 "sse4_2", 445 "avx", 446 "avx2", 447 "avx512", 448 "aes_ni", 449 "popcnt", 450 }, 451 "whiskeylake": { 452 "ssse3", 453 "sse4", 454 "sse4_1", 455 "sse4_2", 456 "avx", 457 "avx2", 458 "avx512", 459 "aes_ni", 460 "popcnt", 461 }, 462 }, 463} 464 465var defaultArchFeatureMap = map[OsType]map[ArchType][]string{} 466 467func RegisterDefaultArchVariantFeatures(os OsType, arch ArchType, features ...string) { 468 checkCalledFromInit() 469 470 for _, feature := range features { 471 if !InList(feature, archFeatures[arch]) { 472 panic(fmt.Errorf("Invalid feature %q for arch %q variant \"\"", feature, arch)) 473 } 474 } 475 476 if defaultArchFeatureMap[os] == nil { 477 defaultArchFeatureMap[os] = make(map[ArchType][]string) 478 } 479 defaultArchFeatureMap[os][arch] = features 480} 481 482// An Arch indicates a single CPU architecture. 483type Arch struct { 484 ArchType ArchType 485 ArchVariant string 486 CpuVariant string 487 Abi []string 488 ArchFeatures []string 489} 490 491func (a Arch) String() string { 492 s := a.ArchType.String() 493 if a.ArchVariant != "" { 494 s += "_" + a.ArchVariant 495 } 496 if a.CpuVariant != "" { 497 s += "_" + a.CpuVariant 498 } 499 return s 500} 501 502type ArchType struct { 503 Name string 504 Field string 505 Multilib string 506} 507 508func newArch(name, multilib string) ArchType { 509 archType := ArchType{ 510 Name: name, 511 Field: proptools.FieldNameForProperty(name), 512 Multilib: multilib, 513 } 514 archTypeList = append(archTypeList, archType) 515 return archType 516} 517 518func ArchTypeList() []ArchType { 519 return append([]ArchType(nil), archTypeList...) 520} 521 522func (a ArchType) String() string { 523 return a.Name 524} 525 526var _ encoding.TextMarshaler = ArchType{} 527 528func (a ArchType) MarshalText() ([]byte, error) { 529 return []byte(strconv.Quote(a.String())), nil 530} 531 532var _ encoding.TextUnmarshaler = &ArchType{} 533 534func (a *ArchType) UnmarshalText(text []byte) error { 535 if u, ok := archTypeMap[string(text)]; ok { 536 *a = u 537 return nil 538 } 539 540 return fmt.Errorf("unknown ArchType %q", text) 541} 542 543var BuildOs = func() OsType { 544 switch runtime.GOOS { 545 case "linux": 546 return Linux 547 case "darwin": 548 return Darwin 549 default: 550 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS)) 551 } 552}() 553 554var ( 555 OsTypeList []OsType 556 commonTargetMap = make(map[string]Target) 557 558 NoOsType OsType 559 Linux = NewOsType("linux_glibc", Host, false) 560 Darwin = NewOsType("darwin", Host, false) 561 LinuxBionic = NewOsType("linux_bionic", Host, false) 562 Windows = NewOsType("windows", HostCross, true) 563 Android = NewOsType("android", Device, false) 564 Fuchsia = NewOsType("fuchsia", Device, false) 565 566 // A pseudo OSType for a common os variant, which is OSType agnostic and which 567 // has dependencies on all the OS variants. 568 CommonOS = NewOsType("common_os", Generic, false) 569 570 osArchTypeMap = map[OsType][]ArchType{ 571 Linux: []ArchType{X86, X86_64}, 572 LinuxBionic: []ArchType{X86_64}, 573 Darwin: []ArchType{X86_64}, 574 Windows: []ArchType{X86, X86_64}, 575 Android: []ArchType{Arm, Arm64, X86, X86_64}, 576 Fuchsia: []ArchType{Arm64, X86_64}, 577 } 578) 579 580type OsType struct { 581 Name, Field string 582 Class OsClass 583 584 DefaultDisabled bool 585} 586 587type OsClass int 588 589const ( 590 Generic OsClass = iota 591 Device 592 Host 593 HostCross 594) 595 596func (class OsClass) String() string { 597 switch class { 598 case Generic: 599 return "generic" 600 case Device: 601 return "device" 602 case Host: 603 return "host" 604 case HostCross: 605 return "host cross" 606 default: 607 panic(fmt.Errorf("unknown class %d", class)) 608 } 609} 610 611func (os OsType) String() string { 612 return os.Name 613} 614 615func (os OsType) Bionic() bool { 616 return os == Android || os == LinuxBionic 617} 618 619func (os OsType) Linux() bool { 620 return os == Android || os == Linux || os == LinuxBionic 621} 622 623func NewOsType(name string, class OsClass, defDisabled bool) OsType { 624 os := OsType{ 625 Name: name, 626 Field: strings.Title(name), 627 Class: class, 628 629 DefaultDisabled: defDisabled, 630 } 631 OsTypeList = append(OsTypeList, os) 632 633 if _, found := commonTargetMap[name]; found { 634 panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name)) 635 } else { 636 commonTargetMap[name] = Target{Os: os, Arch: Arch{ArchType: Common}} 637 } 638 639 return os 640} 641 642func osByName(name string) OsType { 643 for _, os := range OsTypeList { 644 if os.Name == name { 645 return os 646 } 647 } 648 649 return NoOsType 650} 651 652type NativeBridgeSupport bool 653 654const ( 655 NativeBridgeDisabled NativeBridgeSupport = false 656 NativeBridgeEnabled NativeBridgeSupport = true 657) 658 659type Target struct { 660 Os OsType 661 Arch Arch 662 NativeBridge NativeBridgeSupport 663 NativeBridgeHostArchName string 664 NativeBridgeRelativePath string 665} 666 667func (target Target) String() string { 668 return target.OsVariation() + "_" + target.ArchVariation() 669} 670 671func (target Target) OsVariation() string { 672 return target.Os.String() 673} 674 675func (target Target) ArchVariation() string { 676 var variation string 677 if target.NativeBridge { 678 variation = "native_bridge_" 679 } 680 variation += target.Arch.String() 681 682 return variation 683} 684 685func (target Target) Variations() []blueprint.Variation { 686 return []blueprint.Variation{ 687 {Mutator: "os", Variation: target.OsVariation()}, 688 {Mutator: "arch", Variation: target.ArchVariation()}, 689 } 690} 691 692func osMutator(mctx BottomUpMutatorContext) { 693 var module Module 694 var ok bool 695 if module, ok = mctx.Module().(Module); !ok { 696 return 697 } 698 699 base := module.base() 700 701 if !base.ArchSpecific() { 702 return 703 } 704 705 osClasses := base.OsClassSupported() 706 707 var moduleOSList []OsType 708 709 for _, os := range OsTypeList { 710 supportedClass := false 711 for _, osClass := range osClasses { 712 if os.Class == osClass { 713 supportedClass = true 714 } 715 } 716 if !supportedClass { 717 continue 718 } 719 720 if len(mctx.Config().Targets[os]) == 0 { 721 continue 722 } 723 724 moduleOSList = append(moduleOSList, os) 725 } 726 727 if len(moduleOSList) == 0 { 728 base.Disable() 729 return 730 } 731 732 osNames := make([]string, len(moduleOSList)) 733 734 for i, os := range moduleOSList { 735 osNames[i] = os.String() 736 } 737 738 createCommonOSVariant := base.commonProperties.CreateCommonOSVariant 739 if createCommonOSVariant { 740 // A CommonOS variant was requested so add it to the list of OS's variants to 741 // create. It needs to be added to the end because it needs to depend on the 742 // the other variants in the list returned by CreateVariations(...) and inter 743 // variant dependencies can only be created from a later variant in that list to 744 // an earlier one. That is because variants are always processed in the order in 745 // which they are returned from CreateVariations(...). 746 osNames = append(osNames, CommonOS.Name) 747 moduleOSList = append(moduleOSList, CommonOS) 748 } 749 750 modules := mctx.CreateVariations(osNames...) 751 for i, m := range modules { 752 m.base().commonProperties.CompileOS = moduleOSList[i] 753 m.base().setOSProperties(mctx) 754 } 755 756 if createCommonOSVariant { 757 // A CommonOS variant was requested so add dependencies from it (the last one in 758 // the list) to the OS type specific variants. 759 last := len(modules) - 1 760 commonOSVariant := modules[last] 761 commonOSVariant.base().commonProperties.CommonOSVariant = true 762 for _, module := range modules[0:last] { 763 // Ignore modules that are enabled. Note, this will only avoid adding 764 // dependencies on OsType variants that are explicitly disabled in their 765 // properties. The CommonOS variant will still depend on disabled variants 766 // if they are disabled afterwards, e.g. in archMutator if 767 if module.Enabled() { 768 mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module) 769 } 770 } 771 } 772} 773 774// Identifies the dependency from CommonOS variant to the os specific variants. 775type commonOSTag struct{ blueprint.BaseDependencyTag } 776 777var commonOsToOsSpecificVariantTag = commonOSTag{} 778 779// Get the OsType specific variants for the current CommonOS variant. 780// 781// The returned list will only contain enabled OsType specific variants of the 782// module referenced in the supplied context. An empty list is returned if there 783// are no enabled variants or the supplied context is not for an CommonOS 784// variant. 785func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module { 786 var variants []Module 787 mctx.VisitDirectDeps(func(m Module) { 788 if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag { 789 if m.Enabled() { 790 variants = append(variants, m) 791 } 792 } 793 }) 794 795 return variants 796} 797 798// archMutator splits a module into a variant for each Target requested by the module. Target selection 799// for a module is in three levels, OsClass, mulitlib, and then Target. 800// OsClass selection is determined by: 801// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects 802// whether the module type can compile for host, device or both. 803// - The host_supported and device_supported properties on the module. 804// If host is supported for the module, the Host and HostCross OsClasses are selected. If device is supported 805// for the module, the Device OsClass is selected. 806// Within each selected OsClass, the multilib selection is determined by: 807// - The compile_multilib property if it set (which may be overridden by target.android.compile_multilib or 808// target.host.compile_multilib). 809// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set. 810// Valid multilib values include: 811// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm). 812// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64, 813// but may be arm for a 32-bit only build. 814// "32": compile for only a single 32-bit Target supported by the OsClass. 815// "64": compile for only a single 64-bit Target supported by the OsClass. 816// "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java). 817// 818// Once the list of Targets is determined, the module is split into a variant for each Target. 819// 820// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass, 821// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets(). 822func archMutator(mctx BottomUpMutatorContext) { 823 var module Module 824 var ok bool 825 if module, ok = mctx.Module().(Module); !ok { 826 return 827 } 828 829 base := module.base() 830 831 if !base.ArchSpecific() { 832 return 833 } 834 835 os := base.commonProperties.CompileOS 836 if os == CommonOS { 837 // Make sure that the target related properties are initialized for the 838 // CommonOS variant. 839 addTargetProperties(module, commonTargetMap[os.Name], nil, true) 840 841 // Do not create arch specific variants for the CommonOS variant. 842 return 843 } 844 845 osTargets := mctx.Config().Targets[os] 846 image := base.commonProperties.ImageVariation 847 // Filter NativeBridge targets unless they are explicitly supported 848 // Skip creating native bridge variants for vendor modules 849 if os == Android && 850 !(Bool(base.commonProperties.Native_bridge_supported) && image == CoreVariation) { 851 852 var targets []Target 853 for _, t := range osTargets { 854 if !t.NativeBridge { 855 targets = append(targets, t) 856 } 857 } 858 859 osTargets = targets 860 } 861 862 // only the primary arch in the ramdisk / recovery partition 863 if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk()) { 864 osTargets = []Target{osTargets[0]} 865 } 866 867 prefer32 := false 868 if base.prefer32 != nil { 869 prefer32 = base.prefer32(mctx, base, os.Class) 870 } 871 872 multilib, extraMultilib := decodeMultilib(base, os.Class) 873 targets, err := decodeMultilibTargets(multilib, osTargets, prefer32) 874 if err != nil { 875 mctx.ModuleErrorf("%s", err.Error()) 876 } 877 878 var multiTargets []Target 879 if extraMultilib != "" { 880 multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32) 881 if err != nil { 882 mctx.ModuleErrorf("%s", err.Error()) 883 } 884 } 885 886 if image == RecoveryVariation { 887 primaryArch := mctx.Config().DevicePrimaryArchType() 888 targets = filterToArch(targets, primaryArch) 889 multiTargets = filterToArch(multiTargets, primaryArch) 890 } 891 892 if len(targets) == 0 { 893 base.Disable() 894 return 895 } 896 897 targetNames := make([]string, len(targets)) 898 899 for i, target := range targets { 900 targetNames[i] = target.ArchVariation() 901 } 902 903 modules := mctx.CreateVariations(targetNames...) 904 for i, m := range modules { 905 addTargetProperties(m, targets[i], multiTargets, i == 0) 906 m.(Module).base().setArchProperties(mctx) 907 } 908} 909 910func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) { 911 m.base().commonProperties.CompileTarget = target 912 m.base().commonProperties.CompileMultiTargets = multiTargets 913 m.base().commonProperties.CompilePrimary = primaryTarget 914} 915 916func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) { 917 switch class { 918 case Device: 919 multilib = String(base.commonProperties.Target.Android.Compile_multilib) 920 case Host, HostCross: 921 multilib = String(base.commonProperties.Target.Host.Compile_multilib) 922 } 923 if multilib == "" { 924 multilib = String(base.commonProperties.Compile_multilib) 925 } 926 if multilib == "" { 927 multilib = base.commonProperties.Default_multilib 928 } 929 930 if base.commonProperties.UseTargetVariants { 931 return multilib, "" 932 } else { 933 // For app modules a single arch variant will be created per OS class which is expected to handle all the 934 // selected arches. Return the common-type as multilib and any Android.bp provided multilib as extraMultilib 935 if multilib == base.commonProperties.Default_multilib { 936 multilib = "first" 937 } 938 return base.commonProperties.Default_multilib, multilib 939 } 940} 941 942func filterToArch(targets []Target, arch ArchType) []Target { 943 for i := 0; i < len(targets); i++ { 944 if targets[i].Arch.ArchType != arch { 945 targets = append(targets[:i], targets[i+1:]...) 946 i-- 947 } 948 } 949 return targets 950} 951 952type archPropTypeDesc struct { 953 arch, multilib, target reflect.Type 954} 955 956type archPropRoot struct { 957 Arch, Multilib, Target interface{} 958} 959 960// createArchPropTypeDesc takes a reflect.Type that is either a struct or a pointer to a struct, and 961// returns lists of reflect.Types that contains the arch-variant properties inside structs for each 962// arch, multilib and target property. 963func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc { 964 // Each property struct shard will be nested many times under the runtime generated arch struct, 965 // which can hit the limit of 64kB for the name of runtime generated structs. They are nested 966 // 97 times now, which may grow in the future, plus there is some overhead for the containing 967 // type. This number may need to be reduced if too many are added, but reducing it too far 968 // could cause problems if a single deeply nested property no longer fits in the name. 969 const maxArchTypeNameSize = 500 970 971 propShards, _ := proptools.FilterPropertyStructSharded(props, maxArchTypeNameSize, filterArchStruct) 972 if len(propShards) == 0 { 973 return nil 974 } 975 976 var ret []archPropTypeDesc 977 for _, props := range propShards { 978 979 variantFields := func(names []string) []reflect.StructField { 980 ret := make([]reflect.StructField, len(names)) 981 982 for i, name := range names { 983 ret[i].Name = name 984 ret[i].Type = props 985 } 986 987 return ret 988 } 989 990 archFields := make([]reflect.StructField, len(archTypeList)) 991 for i, arch := range archTypeList { 992 variants := []string{} 993 994 for _, archVariant := range archVariants[arch] { 995 archVariant := variantReplacer.Replace(archVariant) 996 variants = append(variants, proptools.FieldNameForProperty(archVariant)) 997 } 998 for _, feature := range archFeatures[arch] { 999 feature := variantReplacer.Replace(feature) 1000 variants = append(variants, proptools.FieldNameForProperty(feature)) 1001 } 1002 1003 fields := variantFields(variants) 1004 1005 fields = append([]reflect.StructField{{ 1006 Name: "BlueprintEmbed", 1007 Type: props, 1008 Anonymous: true, 1009 }}, fields...) 1010 1011 archFields[i] = reflect.StructField{ 1012 Name: arch.Field, 1013 Type: reflect.StructOf(fields), 1014 } 1015 } 1016 archType := reflect.StructOf(archFields) 1017 1018 multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"})) 1019 1020 targets := []string{ 1021 "Host", 1022 "Android64", 1023 "Android32", 1024 "Bionic", 1025 "Linux", 1026 "Not_windows", 1027 "Arm_on_x86", 1028 "Arm_on_x86_64", 1029 "Native_bridge", 1030 } 1031 for _, os := range OsTypeList { 1032 targets = append(targets, os.Field) 1033 1034 for _, archType := range osArchTypeMap[os] { 1035 targets = append(targets, os.Field+"_"+archType.Name) 1036 1037 if os.Linux() { 1038 target := "Linux_" + archType.Name 1039 if !InList(target, targets) { 1040 targets = append(targets, target) 1041 } 1042 } 1043 if os.Bionic() { 1044 target := "Bionic_" + archType.Name 1045 if !InList(target, targets) { 1046 targets = append(targets, target) 1047 } 1048 } 1049 } 1050 } 1051 1052 targetType := reflect.StructOf(variantFields(targets)) 1053 1054 ret = append(ret, archPropTypeDesc{ 1055 arch: reflect.PtrTo(archType), 1056 multilib: reflect.PtrTo(multilibType), 1057 target: reflect.PtrTo(targetType), 1058 }) 1059 } 1060 return ret 1061} 1062 1063func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.StructField) { 1064 if proptools.HasTag(field, "android", "arch_variant") { 1065 // The arch_variant field isn't necessary past this point 1066 // Instead of wasting space, just remove it. Go also has a 1067 // 16-bit limit on structure name length. The name is constructed 1068 // based on the Go source representation of the structure, so 1069 // the tag names count towards that length. 1070 1071 androidTag := field.Tag.Get("android") 1072 values := strings.Split(androidTag, ",") 1073 1074 if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` { 1075 panic(fmt.Errorf("unexpected tag format %q", field.Tag)) 1076 } 1077 // these tags don't need to be present in the runtime generated struct type. 1078 values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"}) 1079 if len(values) > 0 { 1080 panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name)) 1081 } 1082 1083 field.Tag = "" 1084 return true, field 1085 } 1086 return false, field 1087} 1088 1089var archPropTypeMap OncePer 1090 1091func InitArchModule(m Module) { 1092 1093 base := m.base() 1094 1095 base.generalProperties = m.GetProperties() 1096 1097 for _, properties := range base.generalProperties { 1098 propertiesValue := reflect.ValueOf(properties) 1099 t := propertiesValue.Type() 1100 if propertiesValue.Kind() != reflect.Ptr { 1101 panic(fmt.Errorf("properties must be a pointer to a struct, got %T", 1102 propertiesValue.Interface())) 1103 } 1104 1105 propertiesValue = propertiesValue.Elem() 1106 if propertiesValue.Kind() != reflect.Struct { 1107 panic(fmt.Errorf("properties must be a pointer to a struct, got %T", 1108 propertiesValue.Interface())) 1109 } 1110 1111 archPropTypes := archPropTypeMap.Once(NewCustomOnceKey(t), func() interface{} { 1112 return createArchPropTypeDesc(t) 1113 }).([]archPropTypeDesc) 1114 1115 var archProperties []interface{} 1116 for _, t := range archPropTypes { 1117 archProperties = append(archProperties, &archPropRoot{ 1118 Arch: reflect.Zero(t.arch).Interface(), 1119 Multilib: reflect.Zero(t.multilib).Interface(), 1120 Target: reflect.Zero(t.target).Interface(), 1121 }) 1122 } 1123 base.archProperties = append(base.archProperties, archProperties) 1124 m.AddProperties(archProperties...) 1125 } 1126 1127 base.customizableProperties = m.GetProperties() 1128} 1129 1130var variantReplacer = strings.NewReplacer("-", "_", ".", "_") 1131 1132func (m *ModuleBase) appendProperties(ctx BottomUpMutatorContext, 1133 dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value { 1134 1135 if src.Kind() == reflect.Ptr { 1136 if src.IsNil() { 1137 return src 1138 } 1139 src = src.Elem() 1140 } 1141 1142 src = src.FieldByName(field) 1143 if !src.IsValid() { 1144 ctx.ModuleErrorf("field %q does not exist", srcPrefix) 1145 return src 1146 } 1147 1148 ret := src 1149 1150 if src.Kind() == reflect.Struct { 1151 src = src.FieldByName("BlueprintEmbed") 1152 } 1153 1154 order := func(property string, 1155 dstField, srcField reflect.StructField, 1156 dstValue, srcValue interface{}) (proptools.Order, error) { 1157 if proptools.HasTag(dstField, "android", "variant_prepend") { 1158 return proptools.Prepend, nil 1159 } else { 1160 return proptools.Append, nil 1161 } 1162 } 1163 1164 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, order) 1165 if err != nil { 1166 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { 1167 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) 1168 } else { 1169 panic(err) 1170 } 1171 } 1172 1173 return ret 1174} 1175 1176// Rewrite the module's properties structs to contain os-specific values. 1177func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { 1178 os := m.commonProperties.CompileOS 1179 1180 for i := range m.generalProperties { 1181 genProps := m.generalProperties[i] 1182 if m.archProperties[i] == nil { 1183 continue 1184 } 1185 for _, archProperties := range m.archProperties[i] { 1186 archPropValues := reflect.ValueOf(archProperties).Elem() 1187 1188 targetProp := archPropValues.FieldByName("Target").Elem() 1189 1190 // Handle host-specific properties in the form: 1191 // target: { 1192 // host: { 1193 // key: value, 1194 // }, 1195 // }, 1196 if os.Class == Host || os.Class == HostCross { 1197 field := "Host" 1198 prefix := "target.host" 1199 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1200 } 1201 1202 // Handle target OS generalities of the form: 1203 // target: { 1204 // bionic: { 1205 // key: value, 1206 // }, 1207 // } 1208 if os.Linux() { 1209 field := "Linux" 1210 prefix := "target.linux" 1211 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1212 } 1213 1214 if os.Bionic() { 1215 field := "Bionic" 1216 prefix := "target.bionic" 1217 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1218 } 1219 1220 // Handle target OS properties in the form: 1221 // target: { 1222 // linux_glibc: { 1223 // key: value, 1224 // }, 1225 // not_windows: { 1226 // key: value, 1227 // }, 1228 // android { 1229 // key: value, 1230 // }, 1231 // }, 1232 field := os.Field 1233 prefix := "target." + os.Name 1234 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1235 1236 if (os.Class == Host || os.Class == HostCross) && os != Windows { 1237 field := "Not_windows" 1238 prefix := "target.not_windows" 1239 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1240 } 1241 1242 // Handle 64-bit device properties in the form: 1243 // target { 1244 // android64 { 1245 // key: value, 1246 // }, 1247 // android32 { 1248 // key: value, 1249 // }, 1250 // }, 1251 // WARNING: this is probably not what you want to use in your blueprints file, it selects 1252 // options for all targets on a device that supports 64-bit binaries, not just the targets 1253 // that are being compiled for 64-bit. Its expected use case is binaries like linker and 1254 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device 1255 if os.Class == Device { 1256 if ctx.Config().Android64() { 1257 field := "Android64" 1258 prefix := "target.android64" 1259 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1260 } else { 1261 field := "Android32" 1262 prefix := "target.android32" 1263 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1264 } 1265 } 1266 } 1267 } 1268} 1269 1270// Rewrite the module's properties structs to contain arch-specific values. 1271func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) { 1272 arch := m.Arch() 1273 os := m.Os() 1274 1275 for i := range m.generalProperties { 1276 genProps := m.generalProperties[i] 1277 if m.archProperties[i] == nil { 1278 continue 1279 } 1280 for _, archProperties := range m.archProperties[i] { 1281 archPropValues := reflect.ValueOf(archProperties).Elem() 1282 1283 archProp := archPropValues.FieldByName("Arch").Elem() 1284 multilibProp := archPropValues.FieldByName("Multilib").Elem() 1285 targetProp := archPropValues.FieldByName("Target").Elem() 1286 1287 // Handle arch-specific properties in the form: 1288 // arch: { 1289 // arm64: { 1290 // key: value, 1291 // }, 1292 // }, 1293 t := arch.ArchType 1294 1295 if arch.ArchType != Common { 1296 field := proptools.FieldNameForProperty(t.Name) 1297 prefix := "arch." + t.Name 1298 archStruct := m.appendProperties(ctx, genProps, archProp, field, prefix) 1299 1300 // Handle arch-variant-specific properties in the form: 1301 // arch: { 1302 // variant: { 1303 // key: value, 1304 // }, 1305 // }, 1306 v := variantReplacer.Replace(arch.ArchVariant) 1307 if v != "" { 1308 field := proptools.FieldNameForProperty(v) 1309 prefix := "arch." + t.Name + "." + v 1310 m.appendProperties(ctx, genProps, archStruct, field, prefix) 1311 } 1312 1313 // Handle cpu-variant-specific properties in the form: 1314 // arch: { 1315 // variant: { 1316 // key: value, 1317 // }, 1318 // }, 1319 if arch.CpuVariant != arch.ArchVariant { 1320 c := variantReplacer.Replace(arch.CpuVariant) 1321 if c != "" { 1322 field := proptools.FieldNameForProperty(c) 1323 prefix := "arch." + t.Name + "." + c 1324 m.appendProperties(ctx, genProps, archStruct, field, prefix) 1325 } 1326 } 1327 1328 // Handle arch-feature-specific properties in the form: 1329 // arch: { 1330 // feature: { 1331 // key: value, 1332 // }, 1333 // }, 1334 for _, feature := range arch.ArchFeatures { 1335 field := proptools.FieldNameForProperty(feature) 1336 prefix := "arch." + t.Name + "." + feature 1337 m.appendProperties(ctx, genProps, archStruct, field, prefix) 1338 } 1339 1340 // Handle multilib-specific properties in the form: 1341 // multilib: { 1342 // lib32: { 1343 // key: value, 1344 // }, 1345 // }, 1346 field = proptools.FieldNameForProperty(t.Multilib) 1347 prefix = "multilib." + t.Multilib 1348 m.appendProperties(ctx, genProps, multilibProp, field, prefix) 1349 } 1350 1351 // Handle combined OS-feature and arch specific properties in the form: 1352 // target: { 1353 // bionic_x86: { 1354 // key: value, 1355 // }, 1356 // } 1357 if os.Linux() && arch.ArchType != Common { 1358 field := "Linux_" + arch.ArchType.Name 1359 prefix := "target.linux_" + arch.ArchType.Name 1360 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1361 } 1362 1363 if os.Bionic() && arch.ArchType != Common { 1364 field := "Bionic_" + t.Name 1365 prefix := "target.bionic_" + t.Name 1366 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1367 } 1368 1369 // Handle combined OS and arch specific properties in the form: 1370 // target: { 1371 // linux_glibc_x86: { 1372 // key: value, 1373 // }, 1374 // linux_glibc_arm: { 1375 // key: value, 1376 // }, 1377 // android_arm { 1378 // key: value, 1379 // }, 1380 // android_x86 { 1381 // key: value, 1382 // }, 1383 // }, 1384 if arch.ArchType != Common { 1385 field := os.Field + "_" + t.Name 1386 prefix := "target." + os.Name + "_" + t.Name 1387 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1388 } 1389 1390 // Handle arm on x86 properties in the form: 1391 // target { 1392 // arm_on_x86 { 1393 // key: value, 1394 // }, 1395 // arm_on_x86_64 { 1396 // key: value, 1397 // }, 1398 // }, 1399 // TODO(ccross): is this still necessary with native bridge? 1400 if os.Class == Device { 1401 if (arch.ArchType == X86 && (hasArmAbi(arch) || 1402 hasArmAndroidArch(ctx.Config().Targets[Android]))) || 1403 (arch.ArchType == Arm && 1404 hasX86AndroidArch(ctx.Config().Targets[Android])) { 1405 field := "Arm_on_x86" 1406 prefix := "target.arm_on_x86" 1407 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1408 } 1409 if (arch.ArchType == X86_64 && (hasArmAbi(arch) || 1410 hasArmAndroidArch(ctx.Config().Targets[Android]))) || 1411 (arch.ArchType == Arm && 1412 hasX8664AndroidArch(ctx.Config().Targets[Android])) { 1413 field := "Arm_on_x86_64" 1414 prefix := "target.arm_on_x86_64" 1415 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1416 } 1417 if os == Android && m.Target().NativeBridge == NativeBridgeEnabled { 1418 field := "Native_bridge" 1419 prefix := "target.native_bridge" 1420 m.appendProperties(ctx, genProps, targetProp, field, prefix) 1421 } 1422 } 1423 } 1424 } 1425} 1426 1427func forEachInterface(v reflect.Value, f func(reflect.Value)) { 1428 switch v.Kind() { 1429 case reflect.Interface: 1430 f(v) 1431 case reflect.Struct: 1432 for i := 0; i < v.NumField(); i++ { 1433 forEachInterface(v.Field(i), f) 1434 } 1435 case reflect.Ptr: 1436 forEachInterface(v.Elem(), f) 1437 default: 1438 panic(fmt.Errorf("Unsupported kind %s", v.Kind())) 1439 } 1440} 1441 1442// Convert the arch product variables into a list of targets for each os class structs 1443func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) { 1444 variables := config.productVariables 1445 1446 targets := make(map[OsType][]Target) 1447 var targetErr error 1448 1449 addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string, 1450 nativeBridgeEnabled NativeBridgeSupport, nativeBridgeHostArchName *string, 1451 nativeBridgeRelativePath *string) { 1452 if targetErr != nil { 1453 return 1454 } 1455 1456 arch, err := decodeArch(os, archName, archVariant, cpuVariant, abi) 1457 if err != nil { 1458 targetErr = err 1459 return 1460 } 1461 nativeBridgeRelativePathStr := String(nativeBridgeRelativePath) 1462 nativeBridgeHostArchNameStr := String(nativeBridgeHostArchName) 1463 1464 // Use guest arch as relative install path by default 1465 if nativeBridgeEnabled && nativeBridgeRelativePathStr == "" { 1466 nativeBridgeRelativePathStr = arch.ArchType.String() 1467 } 1468 1469 targets[os] = append(targets[os], 1470 Target{ 1471 Os: os, 1472 Arch: arch, 1473 NativeBridge: nativeBridgeEnabled, 1474 NativeBridgeHostArchName: nativeBridgeHostArchNameStr, 1475 NativeBridgeRelativePath: nativeBridgeRelativePathStr, 1476 }) 1477 } 1478 1479 if variables.HostArch == nil { 1480 return nil, fmt.Errorf("No host primary architecture set") 1481 } 1482 1483 addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil) 1484 1485 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" { 1486 addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil) 1487 } 1488 1489 if Bool(config.Host_bionic) { 1490 addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil) 1491 } 1492 1493 if String(variables.CrossHost) != "" { 1494 crossHostOs := osByName(*variables.CrossHost) 1495 if crossHostOs == NoOsType { 1496 return nil, fmt.Errorf("Unknown cross host OS %q", *variables.CrossHost) 1497 } 1498 1499 if String(variables.CrossHostArch) == "" { 1500 return nil, fmt.Errorf("No cross-host primary architecture set") 1501 } 1502 1503 addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil) 1504 1505 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" { 1506 addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil) 1507 } 1508 } 1509 1510 if variables.DeviceArch != nil && *variables.DeviceArch != "" { 1511 var target = Android 1512 if Bool(variables.Fuchsia) { 1513 target = Fuchsia 1514 } 1515 1516 addTarget(target, *variables.DeviceArch, variables.DeviceArchVariant, 1517 variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled, nil, nil) 1518 1519 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" { 1520 addTarget(Android, *variables.DeviceSecondaryArch, 1521 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant, 1522 variables.DeviceSecondaryAbi, NativeBridgeDisabled, nil, nil) 1523 } 1524 1525 if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" { 1526 addTarget(Android, *variables.NativeBridgeArch, 1527 variables.NativeBridgeArchVariant, variables.NativeBridgeCpuVariant, 1528 variables.NativeBridgeAbi, NativeBridgeEnabled, variables.DeviceArch, 1529 variables.NativeBridgeRelativePath) 1530 } 1531 1532 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" && 1533 variables.NativeBridgeSecondaryArch != nil && *variables.NativeBridgeSecondaryArch != "" { 1534 addTarget(Android, *variables.NativeBridgeSecondaryArch, 1535 variables.NativeBridgeSecondaryArchVariant, 1536 variables.NativeBridgeSecondaryCpuVariant, 1537 variables.NativeBridgeSecondaryAbi, 1538 NativeBridgeEnabled, 1539 variables.DeviceSecondaryArch, 1540 variables.NativeBridgeSecondaryRelativePath) 1541 } 1542 } 1543 1544 if targetErr != nil { 1545 return nil, targetErr 1546 } 1547 1548 return targets, nil 1549} 1550 1551// hasArmAbi returns true if arch has at least one arm ABI 1552func hasArmAbi(arch Arch) bool { 1553 return PrefixInList(arch.Abi, "arm") 1554} 1555 1556// hasArmArch returns true if targets has at least non-native_bridge arm Android arch 1557func hasArmAndroidArch(targets []Target) bool { 1558 for _, target := range targets { 1559 if target.Os == Android && target.Arch.ArchType == Arm && target.NativeBridge == NativeBridgeDisabled { 1560 return true 1561 } 1562 } 1563 return false 1564} 1565 1566// hasX86Arch returns true if targets has at least x86 Android arch 1567func hasX86AndroidArch(targets []Target) bool { 1568 for _, target := range targets { 1569 if target.Os == Android && target.Arch.ArchType == X86 { 1570 return true 1571 } 1572 } 1573 return false 1574} 1575 1576// hasX8664Arch returns true if targets has at least x86_64 Android arch 1577func hasX8664AndroidArch(targets []Target) bool { 1578 for _, target := range targets { 1579 if target.Os == Android && target.Arch.ArchType == X86_64 { 1580 return true 1581 } 1582 } 1583 return false 1584} 1585 1586type archConfig struct { 1587 arch string 1588 archVariant string 1589 cpuVariant string 1590 abi []string 1591} 1592 1593func getMegaDeviceConfig() []archConfig { 1594 return []archConfig{ 1595 {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}}, 1596 {"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}}, 1597 {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}}, 1598 {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}}, 1599 {"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}}, 1600 {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}}, 1601 {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}}, 1602 {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}}, 1603 {"arm", "armv7-a-neon", "cortex-a72", []string{"armeabi-v7a"}}, 1604 {"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}}, 1605 {"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}}, 1606 {"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}}, 1607 {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}}, 1608 {"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}}, 1609 {"arm", "armv7-a-neon", "kryo385", []string{"armeabi-v7a"}}, 1610 {"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}}, 1611 {"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}}, 1612 {"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}}, 1613 {"arm64", "armv8-a", "cortex-a72", []string{"arm64-v8a"}}, 1614 {"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}}, 1615 {"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}}, 1616 {"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}}, 1617 {"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}}, 1618 {"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}}, 1619 {"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}}, 1620 {"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}}, 1621 {"x86", "", "", []string{"x86"}}, 1622 {"x86", "atom", "", []string{"x86"}}, 1623 {"x86", "haswell", "", []string{"x86"}}, 1624 {"x86", "ivybridge", "", []string{"x86"}}, 1625 {"x86", "sandybridge", "", []string{"x86"}}, 1626 {"x86", "silvermont", "", []string{"x86"}}, 1627 {"x86", "stoneyridge", "", []string{"x86"}}, 1628 {"x86", "x86_64", "", []string{"x86"}}, 1629 {"x86_64", "", "", []string{"x86_64"}}, 1630 {"x86_64", "haswell", "", []string{"x86_64"}}, 1631 {"x86_64", "ivybridge", "", []string{"x86_64"}}, 1632 {"x86_64", "sandybridge", "", []string{"x86_64"}}, 1633 {"x86_64", "silvermont", "", []string{"x86_64"}}, 1634 {"x86_64", "stoneyridge", "", []string{"x86_64"}}, 1635 } 1636} 1637 1638func getNdkAbisConfig() []archConfig { 1639 return []archConfig{ 1640 {"arm", "armv7-a", "", []string{"armeabi-v7a"}}, 1641 {"arm64", "armv8-a", "", []string{"arm64-v8a"}}, 1642 {"x86", "", "", []string{"x86"}}, 1643 {"x86_64", "", "", []string{"x86_64"}}, 1644 } 1645} 1646 1647func getAmlAbisConfig() []archConfig { 1648 return []archConfig{ 1649 {"arm", "armv7-a", "", []string{"armeabi-v7a"}}, 1650 {"arm64", "armv8-a", "", []string{"arm64-v8a"}}, 1651 {"x86", "", "", []string{"x86"}}, 1652 {"x86_64", "", "", []string{"x86_64"}}, 1653 } 1654} 1655 1656func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) { 1657 var ret []Target 1658 1659 for _, config := range archConfigs { 1660 arch, err := decodeArch(os, config.arch, &config.archVariant, 1661 &config.cpuVariant, config.abi) 1662 if err != nil { 1663 return nil, err 1664 } 1665 1666 ret = append(ret, Target{ 1667 Os: Android, 1668 Arch: arch, 1669 }) 1670 } 1671 1672 return ret, nil 1673} 1674 1675// Convert a set of strings from product variables into a single Arch struct 1676func decodeArch(os OsType, arch string, archVariant, cpuVariant *string, abi []string) (Arch, error) { 1677 stringPtr := func(p *string) string { 1678 if p != nil { 1679 return *p 1680 } 1681 return "" 1682 } 1683 1684 archType, ok := archTypeMap[arch] 1685 if !ok { 1686 return Arch{}, fmt.Errorf("unknown arch %q", arch) 1687 } 1688 1689 a := Arch{ 1690 ArchType: archType, 1691 ArchVariant: stringPtr(archVariant), 1692 CpuVariant: stringPtr(cpuVariant), 1693 Abi: abi, 1694 } 1695 1696 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" { 1697 a.ArchVariant = "" 1698 } 1699 1700 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" { 1701 a.CpuVariant = "" 1702 } 1703 1704 for i := 0; i < len(a.Abi); i++ { 1705 if a.Abi[i] == "" { 1706 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...) 1707 i-- 1708 } 1709 } 1710 1711 if a.ArchVariant == "" { 1712 if featureMap, ok := defaultArchFeatureMap[os]; ok { 1713 a.ArchFeatures = featureMap[archType] 1714 } 1715 } else { 1716 if featureMap, ok := archFeatureMap[archType]; ok { 1717 a.ArchFeatures = featureMap[a.ArchVariant] 1718 } 1719 } 1720 1721 return a, nil 1722} 1723 1724func filterMultilibTargets(targets []Target, multilib string) []Target { 1725 var ret []Target 1726 for _, t := range targets { 1727 if t.Arch.ArchType.Multilib == multilib { 1728 ret = append(ret, t) 1729 } 1730 } 1731 return ret 1732} 1733 1734// Return the set of Os specific common architecture targets for each Os in a list of 1735// targets. 1736func getCommonTargets(targets []Target) []Target { 1737 var ret []Target 1738 set := make(map[string]bool) 1739 1740 for _, t := range targets { 1741 if _, found := set[t.Os.String()]; !found { 1742 set[t.Os.String()] = true 1743 ret = append(ret, commonTargetMap[t.Os.String()]) 1744 } 1745 } 1746 1747 return ret 1748} 1749 1750func firstTarget(targets []Target, filters ...string) []Target { 1751 for _, filter := range filters { 1752 buildTargets := filterMultilibTargets(targets, filter) 1753 if len(buildTargets) > 0 { 1754 return buildTargets[:1] 1755 } 1756 } 1757 return nil 1758} 1759 1760// Use the module multilib setting to select one or more targets from a target list 1761func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) { 1762 buildTargets := []Target{} 1763 1764 switch multilib { 1765 case "common": 1766 buildTargets = getCommonTargets(targets) 1767 case "common_first": 1768 buildTargets = getCommonTargets(targets) 1769 if prefer32 { 1770 buildTargets = append(buildTargets, firstTarget(targets, "lib32", "lib64")...) 1771 } else { 1772 buildTargets = append(buildTargets, firstTarget(targets, "lib64", "lib32")...) 1773 } 1774 case "both": 1775 if prefer32 { 1776 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...) 1777 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...) 1778 } else { 1779 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...) 1780 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...) 1781 } 1782 case "32": 1783 buildTargets = filterMultilibTargets(targets, "lib32") 1784 case "64": 1785 buildTargets = filterMultilibTargets(targets, "lib64") 1786 case "first": 1787 if prefer32 { 1788 buildTargets = firstTarget(targets, "lib32", "lib64") 1789 } else { 1790 buildTargets = firstTarget(targets, "lib64", "lib32") 1791 } 1792 case "prefer32": 1793 buildTargets = filterMultilibTargets(targets, "lib32") 1794 if len(buildTargets) == 0 { 1795 buildTargets = filterMultilibTargets(targets, "lib64") 1796 } 1797 default: 1798 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", or "prefer32" found %q`, 1799 multilib) 1800 } 1801 1802 return buildTargets, nil 1803} 1804