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 15 package common 16 17 import ( 18 "fmt" 19 "reflect" 20 "runtime" 21 "strings" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/proptools" 25 ) 26 27 func init() { 28 RegisterBottomUpMutator("defaults_deps", defaultsDepsMutator) 29 RegisterTopDownMutator("defaults", defaultsMutator) 30 31 RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator) 32 RegisterBottomUpMutator("host_type", HostTypeMutator) 33 RegisterBottomUpMutator("arch", ArchMutator) 34 } 35 36 var ( 37 Arm = newArch("arm", "lib32") 38 Arm64 = newArch("arm64", "lib64") 39 Mips = newArch("mips", "lib32") 40 Mips64 = newArch("mips64", "lib64") 41 X86 = newArch("x86", "lib32") 42 X86_64 = newArch("x86_64", "lib64") 43 44 Common = ArchType{ 45 Name: "common", 46 } 47 ) 48 49 var archTypeMap = map[string]ArchType{ 50 "arm": Arm, 51 "arm64": Arm64, 52 "mips": Mips, 53 "mips64": Mips64, 54 "x86": X86, 55 "x86_64": X86_64, 56 } 57 58 /* 59 Example blueprints file containing all variant property groups, with comment listing what type 60 of variants get properties in that group: 61 62 module { 63 arch: { 64 arm: { 65 // Host or device variants with arm architecture 66 }, 67 arm64: { 68 // Host or device variants with arm64 architecture 69 }, 70 mips: { 71 // Host or device variants with mips architecture 72 }, 73 mips64: { 74 // Host or device variants with mips64 architecture 75 }, 76 x86: { 77 // Host or device variants with x86 architecture 78 }, 79 x86_64: { 80 // Host or device variants with x86_64 architecture 81 }, 82 }, 83 multilib: { 84 lib32: { 85 // Host or device variants for 32-bit architectures 86 }, 87 lib64: { 88 // Host or device variants for 64-bit architectures 89 }, 90 }, 91 target: { 92 android: { 93 // Device variants 94 }, 95 host: { 96 // Host variants 97 }, 98 linux: { 99 // Linux host variants 100 }, 101 darwin: { 102 // Darwin host variants 103 }, 104 windows: { 105 // Windows host variants 106 }, 107 not_windows: { 108 // Non-windows host variants 109 }, 110 }, 111 } 112 */ 113 114 type Embed interface{} 115 116 type archProperties struct { 117 // Properties to vary by target architecture 118 Arch struct { 119 // Properties for module variants being built to run on arm (host or device) 120 Arm struct { 121 Embed `blueprint:"filter(android:\"arch_variant\")"` 122 123 // Arm arch variants 124 Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"` 125 Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"` 126 Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"` 127 128 // Arm cpu variants 129 Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"` 130 Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"` 131 Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"` 132 Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"` 133 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"` 134 Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"` 135 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"` 136 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"` 137 } 138 139 // Properties for module variants being built to run on arm64 (host or device) 140 Arm64 struct { 141 Embed `blueprint:"filter(android:\"arch_variant\")"` 142 143 // Arm64 arch variants 144 Armv8_a interface{} `blueprint:"filter(android:\"arch_variant\")"` 145 146 // Arm64 cpu variants 147 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"` 148 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 149 } 150 151 // Properties for module variants being built to run on mips (host or device) 152 Mips struct { 153 Embed `blueprint:"filter(android:\"arch_variant\")"` 154 155 // Mips arch variants 156 Mips32_fp interface{} `blueprint:"filter(android:\"arch_variant\")"` 157 Mips32r2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"` 158 Mips32r2_fp_xburst interface{} `blueprint:"filter(android:\"arch_variant\")"` 159 Mips32r2dsp_fp interface{} `blueprint:"filter(android:\"arch_variant\")"` 160 Mips32r2dspr2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"` 161 Mips32r6 interface{} `blueprint:"filter(android:\"arch_variant\")"` 162 163 // Mips arch features 164 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"` 165 } 166 167 // Properties for module variants being built to run on mips64 (host or device) 168 Mips64 struct { 169 Embed `blueprint:"filter(android:\"arch_variant\")"` 170 171 // Mips64 arch variants 172 Mips64r2 interface{} `blueprint:"filter(android:\"arch_variant\")"` 173 Mips64r6 interface{} `blueprint:"filter(android:\"arch_variant\")"` 174 175 // Mips64 arch features 176 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"` 177 } 178 179 // Properties for module variants being built to run on x86 (host or device) 180 X86 struct { 181 Embed `blueprint:"filter(android:\"arch_variant\")"` 182 183 // X86 arch variants 184 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"` 185 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"` 186 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"` 187 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"` 188 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"` 189 190 // X86 arch features 191 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"` 192 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"` 193 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"` 194 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"` 195 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"` 196 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"` 197 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"` 198 Movbe interface{} `blueprint:"filter(android:\"arch_variant\")"` 199 } 200 201 // Properties for module variants being built to run on x86_64 (host or device) 202 X86_64 struct { 203 Embed `blueprint:"filter(android:\"arch_variant\")"` 204 205 // X86 arch variants 206 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"` 207 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"` 208 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"` 209 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"` 210 211 // X86 arch features 212 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"` 213 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"` 214 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"` 215 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"` 216 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"` 217 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"` 218 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"` 219 } 220 } 221 222 // Properties to vary by 32-bit or 64-bit 223 Multilib struct { 224 // Properties for module variants being built to run on 32-bit devices 225 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"` 226 // Properties for module variants being built to run on 64-bit devices 227 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 228 } 229 // Properties to vary by build target (host or device, os, os+archictecture) 230 Target struct { 231 // Properties for module variants being built to run on the host 232 Host interface{} `blueprint:"filter(android:\"arch_variant\")"` 233 // Properties for module variants being built to run on the device 234 Android interface{} `blueprint:"filter(android:\"arch_variant\")"` 235 // Properties for module variants being built to run on arm devices 236 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"` 237 // Properties for module variants being built to run on arm64 devices 238 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 239 // Properties for module variants being built to run on mips devices 240 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"` 241 // Properties for module variants being built to run on mips64 devices 242 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 243 // Properties for module variants being built to run on x86 devices 244 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"` 245 // Properties for module variants being built to run on x86_64 devices 246 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 247 // Properties for module variants being built to run on devices that support 64-bit 248 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 249 // Properties for module variants being built to run on devices that do not support 64-bit 250 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"` 251 // Properties for module variants being built to run on linux hosts 252 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"` 253 // Properties for module variants being built to run on linux x86 hosts 254 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"` 255 // Properties for module variants being built to run on linux x86_64 hosts 256 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 257 // Properties for module variants being built to run on darwin hosts 258 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"` 259 // Properties for module variants being built to run on darwin x86 hosts 260 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"` 261 // Properties for module variants being built to run on darwin x86_64 hosts 262 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 263 // Properties for module variants being built to run on windows hosts 264 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"` 265 // Properties for module variants being built to run on windows x86 hosts 266 Windows_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"` 267 // Properties for module variants being built to run on windows x86_64 hosts 268 Windows_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"` 269 // Properties for module variants being built to run on linux or darwin hosts 270 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"` 271 } 272 } 273 274 var archFeatureMap = map[ArchType]map[string][]string{} 275 276 func RegisterArchFeatures(arch ArchType, variant string, features ...string) { 277 archField := proptools.FieldNameForProperty(arch.Name) 278 variantField := proptools.FieldNameForProperty(variant) 279 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField) 280 if variant != "" { 281 if !archStruct.FieldByName(variantField).IsValid() { 282 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch)) 283 } 284 } 285 for _, feature := range features { 286 field := proptools.FieldNameForProperty(feature) 287 if !archStruct.FieldByName(field).IsValid() { 288 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant)) 289 } 290 } 291 if archFeatureMap[arch] == nil { 292 archFeatureMap[arch] = make(map[string][]string) 293 } 294 archFeatureMap[arch][variant] = features 295 } 296 297 // An Arch indicates a single CPU architecture. 298 type Arch struct { 299 ArchType ArchType 300 ArchVariant string 301 CpuVariant string 302 Abi []string 303 ArchFeatures []string 304 } 305 306 func (a Arch) String() string { 307 s := a.ArchType.String() 308 if a.ArchVariant != "" { 309 s += "_" + a.ArchVariant 310 } 311 if a.CpuVariant != "" { 312 s += "_" + a.CpuVariant 313 } 314 return s 315 } 316 317 type ArchType struct { 318 Name string 319 Multilib string 320 } 321 322 func newArch(name, multilib string) ArchType { 323 return ArchType{ 324 Name: name, 325 Multilib: multilib, 326 } 327 } 328 329 func (a ArchType) String() string { 330 return a.Name 331 } 332 333 type HostOrDeviceSupported int 334 335 const ( 336 _ HostOrDeviceSupported = iota 337 HostSupported 338 DeviceSupported 339 HostAndDeviceSupported 340 HostAndDeviceDefault 341 ) 342 343 type HostOrDevice int 344 345 const ( 346 _ HostOrDevice = iota 347 Host 348 Device 349 ) 350 351 func (hod HostOrDevice) String() string { 352 switch hod { 353 case Device: 354 return "device" 355 case Host: 356 return "host" 357 default: 358 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod)) 359 } 360 } 361 362 func (hod HostOrDevice) Property() string { 363 switch hod { 364 case Device: 365 return "android" 366 case Host: 367 return "host" 368 default: 369 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod)) 370 } 371 } 372 373 func (hod HostOrDevice) Host() bool { 374 if hod == 0 { 375 panic("HostOrDevice unset") 376 } 377 return hod == Host 378 } 379 380 func (hod HostOrDevice) Device() bool { 381 if hod == 0 { 382 panic("HostOrDevice unset") 383 } 384 return hod == Device 385 } 386 387 var hostOrDeviceName = map[HostOrDevice]string{ 388 Device: "device", 389 Host: "host", 390 } 391 392 type HostType int 393 394 const ( 395 NoHostType HostType = iota 396 Linux 397 Darwin 398 Windows 399 ) 400 401 func CurrentHostType() HostType { 402 switch runtime.GOOS { 403 case "linux": 404 return Linux 405 case "darwin": 406 return Darwin 407 default: 408 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS)) 409 } 410 } 411 412 func (ht HostType) String() string { 413 switch ht { 414 case Linux: 415 return "linux" 416 case Darwin: 417 return "darwin" 418 case Windows: 419 return "windows" 420 default: 421 panic(fmt.Sprintf("unexpected HostType value %d", ht)) 422 } 423 } 424 425 func (ht HostType) Field() string { 426 switch ht { 427 case Linux: 428 return "Linux" 429 case Darwin: 430 return "Darwin" 431 case Windows: 432 return "Windows" 433 default: 434 panic(fmt.Sprintf("unexpected HostType value %d", ht)) 435 } 436 } 437 438 var ( 439 commonArch = Arch{ 440 ArchType: Common, 441 } 442 ) 443 444 func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) { 445 var module AndroidModule 446 var ok bool 447 if module, ok = mctx.Module().(AndroidModule); !ok { 448 return 449 } 450 451 hods := []HostOrDevice{} 452 453 if module.base().HostSupported() { 454 hods = append(hods, Host) 455 } 456 457 if module.base().DeviceSupported() { 458 hods = append(hods, Device) 459 } 460 461 if len(hods) == 0 { 462 return 463 } 464 465 hodNames := []string{} 466 for _, hod := range hods { 467 hodNames = append(hodNames, hod.String()) 468 } 469 470 modules := mctx.CreateVariations(hodNames...) 471 for i, m := range modules { 472 m.(AndroidModule).base().SetHostOrDevice(hods[i]) 473 } 474 } 475 476 func HostTypeMutator(mctx AndroidBottomUpMutatorContext) { 477 var module AndroidModule 478 var ok bool 479 if module, ok = mctx.Module().(AndroidModule); !ok { 480 return 481 } 482 483 if !module.base().HostSupported() || !module.base().HostOrDevice().Host() { 484 return 485 } 486 487 buildTypes, err := decodeHostTypesProductVariables(mctx.Config().(Config).ProductVariables) 488 if err != nil { 489 mctx.ModuleErrorf("%s", err.Error()) 490 return 491 } 492 493 typeNames := []string{} 494 for _, ht := range buildTypes { 495 typeNames = append(typeNames, ht.String()) 496 } 497 498 modules := mctx.CreateVariations(typeNames...) 499 for i, m := range modules { 500 m.(AndroidModule).base().SetHostType(buildTypes[i]) 501 } 502 } 503 504 func ArchMutator(mctx AndroidBottomUpMutatorContext) { 505 var module AndroidModule 506 var ok bool 507 if module, ok = mctx.Module().(AndroidModule); !ok { 508 return 509 } 510 511 moduleArches := []Arch{} 512 multilib := module.base().commonProperties.Compile_multilib 513 514 if module.base().HostSupported() && module.base().HostOrDevice().Host() { 515 hostModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).HostArches[module.base().HostType()]) 516 if err != nil { 517 mctx.ModuleErrorf("%s", err.Error()) 518 } 519 520 moduleArches = append(moduleArches, hostModuleArches...) 521 } 522 523 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() { 524 deviceModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).DeviceArches) 525 if err != nil { 526 mctx.ModuleErrorf("%s", err.Error()) 527 } 528 529 moduleArches = append(moduleArches, deviceModuleArches...) 530 } 531 532 if len(moduleArches) == 0 { 533 return 534 } 535 536 archNames := []string{} 537 for _, arch := range moduleArches { 538 archNames = append(archNames, arch.String()) 539 } 540 541 modules := mctx.CreateVariations(archNames...) 542 543 for i, m := range modules { 544 m.(AndroidModule).base().SetArch(moduleArches[i]) 545 m.(AndroidModule).base().setArchProperties(mctx) 546 } 547 } 548 549 func InitArchModule(m AndroidModule, 550 propertyStructs ...interface{}) (blueprint.Module, []interface{}) { 551 552 base := m.base() 553 554 base.generalProperties = append(base.generalProperties, 555 propertyStructs...) 556 557 for _, properties := range base.generalProperties { 558 propertiesValue := reflect.ValueOf(properties) 559 if propertiesValue.Kind() != reflect.Ptr { 560 panic(fmt.Errorf("properties must be a pointer to a struct, got %T", 561 propertiesValue.Interface())) 562 } 563 564 propertiesValue = propertiesValue.Elem() 565 if propertiesValue.Kind() != reflect.Struct { 566 panic(fmt.Errorf("properties must be a pointer to a struct, got %T", 567 propertiesValue.Interface())) 568 } 569 570 archProperties := &archProperties{} 571 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) { 572 newValue := proptools.CloneEmptyProperties(propertiesValue) 573 v.Set(newValue) 574 }) 575 576 base.archProperties = append(base.archProperties, archProperties) 577 } 578 579 var allProperties []interface{} 580 allProperties = append(allProperties, base.generalProperties...) 581 for _, asp := range base.archProperties { 582 allProperties = append(allProperties, asp) 583 } 584 585 return m, allProperties 586 } 587 588 var variantReplacer = strings.NewReplacer("-", "_", ".", "_") 589 590 func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext, 591 dst, src interface{}, field, srcPrefix string) interface{} { 592 593 srcField := reflect.ValueOf(src).FieldByName(field) 594 if !srcField.IsValid() { 595 ctx.ModuleErrorf("field %q does not exist", srcPrefix) 596 return nil 597 } 598 599 ret := srcField 600 601 if srcField.Kind() == reflect.Struct { 602 srcField = srcField.FieldByName("Embed") 603 } 604 605 src = srcField.Elem().Interface() 606 607 filter := func(property string, 608 dstField, srcField reflect.StructField, 609 dstValue, srcValue interface{}) (bool, error) { 610 611 srcProperty := srcPrefix + "." + property 612 613 if !proptools.HasTag(dstField, "android", "arch_variant") { 614 if ctx.ContainsProperty(srcProperty) { 615 return false, fmt.Errorf("can't be specific to a build variant") 616 } else { 617 return false, nil 618 } 619 } 620 621 return true, nil 622 } 623 624 err := proptools.AppendProperties(dst, src, filter) 625 if err != nil { 626 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { 627 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) 628 } else { 629 panic(err) 630 } 631 } 632 633 return ret.Interface() 634 } 635 636 // Rewrite the module's properties structs to contain arch-specific values. 637 func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) { 638 arch := a.commonProperties.CompileArch 639 hod := a.commonProperties.CompileHostOrDevice 640 ht := a.commonProperties.CompileHostType 641 642 if arch.ArchType == Common { 643 return 644 } 645 646 for i := range a.generalProperties { 647 genProps := a.generalProperties[i] 648 archProps := a.archProperties[i] 649 // Handle arch-specific properties in the form: 650 // arch: { 651 // arm64: { 652 // key: value, 653 // }, 654 // }, 655 t := arch.ArchType 656 657 field := proptools.FieldNameForProperty(t.Name) 658 prefix := "arch." + t.Name 659 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix) 660 661 // Handle arch-variant-specific properties in the form: 662 // arch: { 663 // variant: { 664 // key: value, 665 // }, 666 // }, 667 v := variantReplacer.Replace(arch.ArchVariant) 668 if v != "" { 669 field := proptools.FieldNameForProperty(v) 670 prefix := "arch." + t.Name + "." + v 671 a.appendProperties(ctx, genProps, archStruct, field, prefix) 672 } 673 674 // Handle cpu-variant-specific properties in the form: 675 // arch: { 676 // variant: { 677 // key: value, 678 // }, 679 // }, 680 c := variantReplacer.Replace(arch.CpuVariant) 681 if c != "" { 682 field := proptools.FieldNameForProperty(c) 683 prefix := "arch." + t.Name + "." + c 684 a.appendProperties(ctx, genProps, archStruct, field, prefix) 685 } 686 687 // Handle arch-feature-specific properties in the form: 688 // arch: { 689 // feature: { 690 // key: value, 691 // }, 692 // }, 693 for _, feature := range arch.ArchFeatures { 694 field := proptools.FieldNameForProperty(feature) 695 prefix := "arch." + t.Name + "." + feature 696 a.appendProperties(ctx, genProps, archStruct, field, prefix) 697 } 698 699 // Handle multilib-specific properties in the form: 700 // multilib: { 701 // lib32: { 702 // key: value, 703 // }, 704 // }, 705 field = proptools.FieldNameForProperty(t.Multilib) 706 prefix = "multilib." + t.Multilib 707 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix) 708 709 // Handle host-or-device-specific properties in the form: 710 // target: { 711 // host: { 712 // key: value, 713 // }, 714 // }, 715 hodProperty := hod.Property() 716 field = proptools.FieldNameForProperty(hodProperty) 717 prefix = "target." + hodProperty 718 a.appendProperties(ctx, genProps, archProps.Target, field, prefix) 719 720 // Handle host target properties in the form: 721 // target: { 722 // linux: { 723 // key: value, 724 // }, 725 // not_windows: { 726 // key: value, 727 // }, 728 // linux_x86: { 729 // key: value, 730 // }, 731 // linux_arm: { 732 // key: value, 733 // }, 734 // }, 735 if hod.Host() { 736 field := ht.Field() 737 prefix := "target." + ht.String() 738 a.appendProperties(ctx, genProps, archProps.Target, field, prefix) 739 740 t := arch.ArchType 741 field = ht.Field() + "_" + t.Name 742 prefix = "target." + ht.String() + "_" + t.Name 743 a.appendProperties(ctx, genProps, archProps.Target, field, prefix) 744 745 if ht != Windows { 746 field := "Not_windows" 747 prefix := "target.not_windows" 748 a.appendProperties(ctx, genProps, archProps.Target, field, prefix) 749 } 750 } 751 752 // Handle 64-bit device properties in the form: 753 // target { 754 // android64 { 755 // key: value, 756 // }, 757 // android32 { 758 // key: value, 759 // }, 760 // }, 761 // WARNING: this is probably not what you want to use in your blueprints file, it selects 762 // options for all targets on a device that supports 64-bit binaries, not just the targets 763 // that are being compiled for 64-bit. Its expected use case is binaries like linker and 764 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device 765 if hod.Device() { 766 if true /* && target_is_64_bit */ { 767 field := "Android64" 768 prefix := "target.android64" 769 a.appendProperties(ctx, genProps, archProps.Target, field, prefix) 770 } else { 771 field := "Android32" 772 prefix := "target.android32" 773 a.appendProperties(ctx, genProps, archProps.Target, field, prefix) 774 } 775 } 776 777 // Handle device architecture properties in the form: 778 // target { 779 // android_arm { 780 // key: value, 781 // }, 782 // android_x86 { 783 // key: value, 784 // }, 785 // }, 786 if hod.Device() { 787 t := arch.ArchType 788 field := "Android_" + t.Name 789 prefix := "target.android_" + t.Name 790 a.appendProperties(ctx, genProps, archProps.Target, field, prefix) 791 } 792 793 if ctx.Failed() { 794 return 795 } 796 } 797 } 798 799 func forEachInterface(v reflect.Value, f func(reflect.Value)) { 800 switch v.Kind() { 801 case reflect.Interface: 802 f(v) 803 case reflect.Struct: 804 for i := 0; i < v.NumField(); i++ { 805 forEachInterface(v.Field(i), f) 806 } 807 case reflect.Ptr: 808 forEachInterface(v.Elem(), f) 809 default: 810 panic(fmt.Errorf("Unsupported kind %s", v.Kind())) 811 } 812 } 813 814 // Get a list of HostTypes from the product variables 815 func decodeHostTypesProductVariables(variables productVariables) ([]HostType, error) { 816 ret := []HostType{CurrentHostType()} 817 818 if variables.CrossHost != nil && *variables.CrossHost != "" { 819 switch *variables.CrossHost { 820 case "windows": 821 ret = append(ret, Windows) 822 default: 823 return nil, fmt.Errorf("Unsupported secondary host: %s", *variables.CrossHost) 824 } 825 } 826 827 return ret, nil 828 } 829 830 // Convert the arch product variables into a list of host and device Arch structs 831 func decodeArchProductVariables(variables productVariables) (map[HostType][]Arch, []Arch, error) { 832 if variables.HostArch == nil { 833 return nil, nil, fmt.Errorf("No host primary architecture set") 834 } 835 836 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil) 837 if err != nil { 838 return nil, nil, err 839 } 840 841 hostArches := []Arch{hostArch} 842 843 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" { 844 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil) 845 if err != nil { 846 return nil, nil, err 847 } 848 hostArches = append(hostArches, hostSecondaryArch) 849 } 850 851 hostTypeArches := map[HostType][]Arch{ 852 CurrentHostType(): hostArches, 853 } 854 855 if variables.CrossHost != nil && *variables.CrossHost != "" { 856 if variables.CrossHostArch == nil || *variables.CrossHostArch == "" { 857 return nil, nil, fmt.Errorf("No cross-host primary architecture set") 858 } 859 860 crossHostArch, err := decodeArch(*variables.CrossHostArch, nil, nil, nil) 861 if err != nil { 862 return nil, nil, err 863 } 864 865 crossHostArches := []Arch{crossHostArch} 866 867 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" { 868 crossHostSecondaryArch, err := decodeArch(*variables.CrossHostSecondaryArch, nil, nil, nil) 869 if err != nil { 870 return nil, nil, err 871 } 872 crossHostArches = append(crossHostArches, crossHostSecondaryArch) 873 } 874 875 switch *variables.CrossHost { 876 case "windows": 877 hostTypeArches[Windows] = crossHostArches 878 default: 879 return nil, nil, fmt.Errorf("Unsupported cross-host: %s", *variables.CrossHost) 880 } 881 } 882 883 if variables.DeviceArch == nil { 884 return nil, nil, fmt.Errorf("No device primary architecture set") 885 } 886 887 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant, 888 variables.DeviceCpuVariant, variables.DeviceAbi) 889 if err != nil { 890 return nil, nil, err 891 } 892 893 deviceArches := []Arch{deviceArch} 894 895 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" { 896 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch, 897 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant, 898 variables.DeviceSecondaryAbi) 899 if err != nil { 900 return nil, nil, err 901 } 902 deviceArches = append(deviceArches, deviceSecondaryArch) 903 } 904 905 return hostTypeArches, deviceArches, nil 906 } 907 908 func decodeMegaDevice() ([]Arch, error) { 909 archSettings := []struct { 910 arch string 911 archVariant string 912 cpuVariant string 913 abi []string 914 }{ 915 {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}}, 916 {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}}, 917 // gtest_all_test.cc fails to build: 918 // error in backend: Unsupported library call operation! 919 //{"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}}, 920 {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}}, 921 {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}}, 922 {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}}, 923 {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}}, 924 {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}}, 925 {"arm64", "", "cortex-a53", []string{"arm64-v8a"}}, 926 {"arm64", "", "denver64", []string{"arm64-v8a"}}, 927 {"mips", "mips32-fp", "", []string{"mips"}}, 928 {"mips", "mips32r2-fp", "", []string{"mips"}}, 929 {"mips", "mips32r2-fp-xburst", "", []string{"mips"}}, 930 {"mips", "mips32r6", "", []string{"mips32r6"}}, 931 // mips32r2dsp[r2]-fp fails in the assembler for divdf3.c in compiler-rt: 932 // (same errors in make and soong) 933 // Error: invalid operands `mtlo $ac0,$11' 934 // Error: invalid operands `mthi $ac0,$12' 935 //{"mips", "mips32r2dsp-fp", "", []string{"mips"}}, 936 //{"mips", "mips32r2dspr2-fp", "", []string{"mips"}}, 937 // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc 938 //{"mips64", "mips64r2", "", []string{"mips64"}}, 939 {"mips64", "mips64r6", "", []string{"mips64"}}, 940 {"x86", "", "", []string{"x86"}}, 941 {"x86", "atom", "", []string{"x86"}}, 942 {"x86", "haswell", "", []string{"x86"}}, 943 {"x86", "ivybridge", "", []string{"x86"}}, 944 {"x86", "sandybridge", "", []string{"x86"}}, 945 {"x86", "silvermont", "", []string{"x86"}}, 946 {"x86_64", "", "", []string{"x86_64"}}, 947 {"x86_64", "haswell", "", []string{"x86_64"}}, 948 {"x86_64", "ivybridge", "", []string{"x86_64"}}, 949 {"x86_64", "sandybridge", "", []string{"x86_64"}}, 950 {"x86_64", "silvermont", "", []string{"x86_64"}}, 951 } 952 953 var ret []Arch 954 955 for _, config := range archSettings { 956 arch, err := decodeArch(config.arch, &config.archVariant, 957 &config.cpuVariant, &config.abi) 958 if err != nil { 959 return nil, err 960 } 961 ret = append(ret, arch) 962 } 963 964 return ret, nil 965 } 966 967 // Convert a set of strings from product variables into a single Arch struct 968 func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) { 969 stringPtr := func(p *string) string { 970 if p != nil { 971 return *p 972 } 973 return "" 974 } 975 976 slicePtr := func(p *[]string) []string { 977 if p != nil { 978 return *p 979 } 980 return nil 981 } 982 983 archType, ok := archTypeMap[arch] 984 if !ok { 985 return Arch{}, fmt.Errorf("unknown arch %q", arch) 986 } 987 988 a := Arch{ 989 ArchType: archType, 990 ArchVariant: stringPtr(archVariant), 991 CpuVariant: stringPtr(cpuVariant), 992 Abi: slicePtr(abi), 993 } 994 995 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" { 996 a.ArchVariant = "" 997 } 998 999 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" { 1000 a.CpuVariant = "" 1001 } 1002 1003 for i := 0; i < len(a.Abi); i++ { 1004 if a.Abi[i] == "" { 1005 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...) 1006 i-- 1007 } 1008 } 1009 1010 if featureMap, ok := archFeatureMap[archType]; ok { 1011 a.ArchFeatures = featureMap[stringPtr(archVariant)] 1012 } 1013 1014 return a, nil 1015 } 1016 1017 // Use the module multilib setting to select one or more arches from an arch list 1018 func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) { 1019 buildArches := []Arch{} 1020 switch multilib { 1021 case "common": 1022 buildArches = append(buildArches, commonArch) 1023 case "both": 1024 buildArches = append(buildArches, arches...) 1025 case "first": 1026 buildArches = append(buildArches, arches[0]) 1027 case "32": 1028 for _, a := range arches { 1029 if a.ArchType.Multilib == "lib32" { 1030 buildArches = append(buildArches, a) 1031 } 1032 } 1033 case "64": 1034 for _, a := range arches { 1035 if a.ArchType.Multilib == "lib64" { 1036 buildArches = append(buildArches, a) 1037 } 1038 } 1039 default: 1040 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`, 1041 multilib) 1042 //buildArches = append(buildArches, arches[0]) 1043 } 1044 1045 return buildArches, nil 1046 } 1047