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