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 "slices" 23 "strings" 24 25 "github.com/google/blueprint" 26 "github.com/google/blueprint/proptools" 27) 28 29/* 30Example blueprints file containing all variant property groups, with comment listing what type 31of variants get properties in that group: 32 33module { 34 arch: { 35 arm: { 36 // Host or device variants with arm architecture 37 }, 38 arm64: { 39 // Host or device variants with arm64 architecture 40 }, 41 x86: { 42 // Host or device variants with x86 architecture 43 }, 44 x86_64: { 45 // Host or device variants with x86_64 architecture 46 }, 47 }, 48 multilib: { 49 lib32: { 50 // Host or device variants for 32-bit architectures 51 }, 52 lib64: { 53 // Host or device variants for 64-bit architectures 54 }, 55 }, 56 target: { 57 android: { 58 // Device variants (implies Bionic) 59 }, 60 host: { 61 // Host variants 62 }, 63 bionic: { 64 // Bionic (device and host) variants 65 }, 66 linux_bionic: { 67 // Bionic host variants 68 }, 69 linux: { 70 // Bionic (device and host) and Linux glibc variants 71 }, 72 linux_glibc: { 73 // Linux host variants (using non-Bionic libc) 74 }, 75 darwin: { 76 // Darwin host variants 77 }, 78 windows: { 79 // Windows host variants 80 }, 81 not_windows: { 82 // Non-windows host variants 83 }, 84 android_arm: { 85 // Any <os>_<arch> combination restricts to that os and arch 86 }, 87 }, 88} 89*/ 90 91// An Arch indicates a single CPU architecture. 92type Arch struct { 93 // The type of the architecture (arm, arm64, x86, or x86_64). 94 ArchType ArchType 95 96 // The variant of the architecture, for example "armv7-a" or "armv7-a-neon" for arm. 97 ArchVariant string 98 99 // The variant of the CPU, for example "cortex-a53" for arm64. 100 CpuVariant string 101 102 // The list of Android app ABIs supported by the CPU architecture, for example "arm64-v8a". 103 Abi []string 104 105 // The list of arch-specific features supported by the CPU architecture, for example "neon". 106 ArchFeatures []string 107} 108 109// String returns the Arch as a string. The value is used as the name of the variant created 110// by archMutator. 111func (a Arch) String() string { 112 s := a.ArchType.String() 113 if a.ArchVariant != "" { 114 s += "_" + a.ArchVariant 115 } 116 if a.CpuVariant != "" { 117 s += "_" + a.CpuVariant 118 } 119 return s 120} 121 122// ArchType is used to define the 4 supported architecture types (arm, arm64, x86, x86_64), as 123// well as the "common" architecture used for modules that support multiple architectures, for 124// example Java modules. 125type ArchType struct { 126 // Name is the name of the architecture type, "arm", "arm64", "x86", or "x86_64". 127 Name string 128 129 // Field is the name of the field used in properties that refer to the architecture, e.g. "Arm64". 130 Field string 131 132 // Multilib is either "lib32" or "lib64" for 32-bit or 64-bit architectures. 133 Multilib string 134} 135 136// String returns the name of the ArchType. 137func (a ArchType) String() string { 138 return a.Name 139} 140 141func (a ArchType) Bitness() string { 142 if a.Multilib == "lib32" { 143 return "32" 144 } 145 if a.Multilib == "lib64" { 146 return "64" 147 } 148 panic("Bitness is not defined for the common variant") 149} 150 151const COMMON_VARIANT = "common" 152 153var ( 154 archTypeList []ArchType 155 156 Arm = newArch("arm", "lib32") 157 Arm64 = newArch("arm64", "lib64") 158 Riscv64 = newArch("riscv64", "lib64") 159 X86 = newArch("x86", "lib32") 160 X86_64 = newArch("x86_64", "lib64") 161 162 Common = ArchType{ 163 Name: COMMON_VARIANT, 164 } 165) 166 167var archTypeMap = map[string]ArchType{} 168 169func newArch(name, multilib string) ArchType { 170 archType := ArchType{ 171 Name: name, 172 Field: proptools.FieldNameForProperty(name), 173 Multilib: multilib, 174 } 175 archTypeList = append(archTypeList, archType) 176 archTypeMap[name] = archType 177 return archType 178} 179 180// ArchTypeList returns a slice copy of the 4 supported ArchTypes for arm, 181// arm64, x86 and x86_64. 182func ArchTypeList() []ArchType { 183 return append([]ArchType(nil), archTypeList...) 184} 185 186// MarshalText allows an ArchType to be serialized through any encoder that supports 187// encoding.TextMarshaler. 188func (a ArchType) MarshalText() ([]byte, error) { 189 return []byte(a.String()), nil 190} 191 192var _ encoding.TextMarshaler = ArchType{} 193 194// UnmarshalText allows an ArchType to be deserialized through any decoder that supports 195// encoding.TextUnmarshaler. 196func (a *ArchType) UnmarshalText(text []byte) error { 197 if u, ok := archTypeMap[string(text)]; ok { 198 *a = u 199 return nil 200 } 201 202 return fmt.Errorf("unknown ArchType %q", text) 203} 204 205var _ encoding.TextUnmarshaler = &ArchType{} 206 207// OsClass is an enum that describes whether a variant of a module runs on the host, on the device, 208// or is generic. 209type OsClass int 210 211const ( 212 // Generic is used for variants of modules that are not OS-specific. 213 Generic OsClass = iota 214 // Device is used for variants of modules that run on the device. 215 Device 216 // Host is used for variants of modules that run on the host. 217 Host 218) 219 220// String returns the OsClass as a string. 221func (class OsClass) String() string { 222 switch class { 223 case Generic: 224 return "generic" 225 case Device: 226 return "device" 227 case Host: 228 return "host" 229 default: 230 panic(fmt.Errorf("unknown class %d", class)) 231 } 232} 233 234// OsType describes an OS variant of a module. 235type OsType struct { 236 // Name is the name of the OS. It is also used as the name of the property in Android.bp 237 // files. 238 Name string 239 240 // Field is the name of the OS converted to an exported field name, i.e. with the first 241 // character capitalized. 242 Field string 243 244 // Class is the OsClass of the OS. 245 Class OsClass 246 247 // DefaultDisabled is set when the module variants for the OS should not be created unless 248 // the module explicitly requests them. This is used to limit Windows cross compilation to 249 // only modules that need it. 250 DefaultDisabled bool 251} 252 253// String returns the name of the OsType. 254func (os OsType) String() string { 255 return os.Name 256} 257 258// Bionic returns true if the OS uses the Bionic libc runtime, i.e. if the OS is Android or 259// is Linux with Bionic. 260func (os OsType) Bionic() bool { 261 return os == Android || os == LinuxBionic 262} 263 264// Linux returns true if the OS uses the Linux kernel, i.e. if the OS is Android or is Linux 265// with or without the Bionic libc runtime. 266func (os OsType) Linux() bool { 267 return os == Android || os == Linux || os == LinuxBionic || os == LinuxMusl 268} 269 270// newOsType constructs an OsType and adds it to the global lists. 271func newOsType(name string, class OsClass, defDisabled bool, archTypes ...ArchType) OsType { 272 checkCalledFromInit() 273 os := OsType{ 274 Name: name, 275 Field: proptools.FieldNameForProperty(name), 276 Class: class, 277 278 DefaultDisabled: defDisabled, 279 } 280 osTypeList = append(osTypeList, os) 281 282 if _, found := commonTargetMap[name]; found { 283 panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name)) 284 } else { 285 commonTargetMap[name] = Target{Os: os, Arch: CommonArch} 286 } 287 osArchTypeMap[os] = archTypes 288 289 return os 290} 291 292// osByName returns the OsType that has the given name, or NoOsType if none match. 293func osByName(name string) OsType { 294 for _, os := range osTypeList { 295 if os.Name == name { 296 return os 297 } 298 } 299 300 return NoOsType 301} 302 303var ( 304 // osTypeList contains a list of all the supported OsTypes, including ones not supported 305 // by the current build host or the target device. 306 osTypeList []OsType 307 // commonTargetMap maps names of OsTypes to the corresponding common Target, i.e. the 308 // Target with the same OsType and the common ArchType. 309 commonTargetMap = make(map[string]Target) 310 // osArchTypeMap maps OsTypes to the list of supported ArchTypes for that OS. 311 osArchTypeMap = map[OsType][]ArchType{} 312 313 // NoOsType is a placeholder for when no OS is needed. 314 NoOsType OsType 315 // Linux is the OS for the Linux kernel plus the glibc runtime. 316 Linux = newOsType("linux_glibc", Host, false, X86, X86_64) 317 // LinuxMusl is the OS for the Linux kernel plus the musl runtime. 318 LinuxMusl = newOsType("linux_musl", Host, false, X86, X86_64, Arm64, Arm) 319 // Darwin is the OS for MacOS/Darwin host machines. 320 Darwin = newOsType("darwin", Host, false, Arm64, X86_64) 321 // LinuxBionic is the OS for the Linux kernel plus the Bionic libc runtime, but without the 322 // rest of Android. 323 LinuxBionic = newOsType("linux_bionic", Host, false, Arm64, X86_64) 324 // Windows the OS for Windows host machines. 325 Windows = newOsType("windows", Host, true, X86, X86_64) 326 // Android is the OS for target devices that run all of Android, including the Linux kernel 327 // and the Bionic libc runtime. 328 Android = newOsType("android", Device, false, Arm, Arm64, Riscv64, X86, X86_64) 329 330 // CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which 331 // has dependencies on all the OS variants. 332 CommonOS = newOsType("common_os", Generic, false) 333 334 // CommonArch is the Arch for all modules that are os-specific but not arch specific, 335 // for example most Java modules. 336 CommonArch = Arch{ArchType: Common} 337) 338 339// OsTypeList returns a slice copy of the supported OsTypes. 340func OsTypeList() []OsType { 341 return append([]OsType(nil), osTypeList...) 342} 343 344// Target specifies the OS and architecture that a module is being compiled for. 345type Target struct { 346 // Os the OS that the module is being compiled for (e.g. "linux_glibc", "android"). 347 Os OsType 348 // Arch is the architecture that the module is being compiled for. 349 Arch Arch 350 // NativeBridge is NativeBridgeEnabled if the architecture is supported using NativeBridge 351 // (i.e. arm on x86) for this device. 352 NativeBridge NativeBridgeSupport 353 // NativeBridgeHostArchName is the name of the real architecture that is used to implement 354 // the NativeBridge architecture. For example, for arm on x86 this would be "x86". 355 NativeBridgeHostArchName string 356 // NativeBridgeRelativePath is the name of the subdirectory that will contain NativeBridge 357 // libraries and binaries. 358 NativeBridgeRelativePath string 359 360 // HostCross is true when the target cannot run natively on the current build host. 361 // For example, linux_glibc_x86 returns true on a regular x86/i686/Linux machines, but returns false 362 // on Mac (different OS), or on 64-bit only i686/Linux machines (unsupported arch). 363 HostCross bool 364} 365 366// NativeBridgeSupport is an enum that specifies if a Target supports NativeBridge. 367type NativeBridgeSupport bool 368 369const ( 370 NativeBridgeDisabled NativeBridgeSupport = false 371 NativeBridgeEnabled NativeBridgeSupport = true 372) 373 374// String returns the OS and arch variations used for the Target. 375func (target Target) String() string { 376 return target.OsVariation() + "_" + target.ArchVariation() 377} 378 379// OsVariation returns the name of the variation used by the osMutator for the Target. 380func (target Target) OsVariation() string { 381 return target.Os.String() 382} 383 384// ArchVariation returns the name of the variation used by the archMutator for the Target. 385func (target Target) ArchVariation() string { 386 var variation string 387 if target.NativeBridge { 388 variation = "native_bridge_" 389 } 390 variation += target.Arch.String() 391 392 return variation 393} 394 395// Variations returns a list of blueprint.Variations for the osMutator and archMutator for the 396// Target. 397func (target Target) Variations() []blueprint.Variation { 398 return []blueprint.Variation{ 399 {Mutator: "os", Variation: target.OsVariation()}, 400 {Mutator: "arch", Variation: target.ArchVariation()}, 401 } 402} 403 404// osMutator splits an arch-specific module into a variant for each OS that is enabled for the 405// module. It uses the HostOrDevice value passed to InitAndroidArchModule and the 406// device_supported and host_supported properties to determine which OsTypes are enabled for this 407// module, then searches through the Targets to determine which have enabled Targets for this 408// module. 409type osTransitionMutator struct{} 410 411type allOsInfo struct { 412 Os map[string]OsType 413 Variations []string 414} 415 416var allOsProvider = blueprint.NewMutatorProvider[*allOsInfo]("os_propagate") 417 418// moduleOSList collects a list of OSTypes supported by this module based on the HostOrDevice 419// value passed to InitAndroidArchModule and the device_supported and host_supported properties. 420func moduleOSList(ctx ConfigContext, base *ModuleBase) []OsType { 421 var moduleOSList []OsType 422 for _, os := range osTypeList { 423 for _, t := range ctx.Config().Targets[os] { 424 if base.supportsTarget(t) { 425 moduleOSList = append(moduleOSList, os) 426 break 427 } 428 } 429 } 430 431 if base.commonProperties.CreateCommonOSVariant { 432 // A CommonOS variant was requested so add it to the list of OS variants to 433 // create. It needs to be added to the end because it needs to depend on the 434 // the other variants and inter variant dependencies can only be created from a 435 // later variant in that list to an earlier one. That is because variants are 436 // always processed in the order in which they are created. 437 moduleOSList = append(moduleOSList, CommonOS) 438 } 439 440 return moduleOSList 441} 442 443func (o *osTransitionMutator) Split(ctx BaseModuleContext) []string { 444 module := ctx.Module() 445 base := module.base() 446 447 // Nothing to do for modules that are not architecture specific (e.g. a genrule). 448 if !base.ArchSpecific() { 449 return []string{""} 450 } 451 452 moduleOSList := moduleOSList(ctx, base) 453 454 // If there are no supported OSes then disable the module. 455 if len(moduleOSList) == 0 { 456 base.Disable() 457 return []string{""} 458 } 459 460 // Convert the list of supported OsTypes to the variation names. 461 osNames := make([]string, len(moduleOSList)) 462 osMapping := make(map[string]OsType, len(moduleOSList)) 463 for i, os := range moduleOSList { 464 osNames[i] = os.String() 465 osMapping[osNames[i]] = os 466 } 467 468 SetProvider(ctx, allOsProvider, &allOsInfo{ 469 Os: osMapping, 470 Variations: osNames, 471 }) 472 473 return osNames 474} 475 476func (o *osTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string { 477 return sourceVariation 478} 479 480func (o *osTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string { 481 module := ctx.Module() 482 base := module.base() 483 484 if !base.ArchSpecific() { 485 return "" 486 } 487 488 return incomingVariation 489} 490 491func (o *osTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) { 492 module := ctx.Module() 493 base := module.base() 494 495 if variation == "" { 496 return 497 } 498 499 allOsInfo, ok := ModuleProvider(ctx, allOsProvider) 500 if !ok { 501 panic(fmt.Errorf("missing allOsProvider")) 502 } 503 504 // Annotate this variant with which OS it was created for, and 505 // squash the appropriate OS-specific properties into the top level properties. 506 base.commonProperties.CompileOS = allOsInfo.Os[variation] 507 base.setOSProperties(ctx) 508 509 if variation == CommonOS.String() { 510 // A CommonOS variant was requested so add dependencies from it (the last one in 511 // the list) to the OS type specific variants. 512 osList := allOsInfo.Variations[:len(allOsInfo.Variations)-1] 513 for _, os := range osList { 514 variation := []blueprint.Variation{{"os", os}} 515 ctx.AddVariationDependencies(variation, commonOsToOsSpecificVariantTag, ctx.ModuleName()) 516 } 517 } 518} 519 520type archDepTag struct { 521 blueprint.BaseDependencyTag 522 name string 523} 524 525// Identifies the dependency from CommonOS variant to the os specific variants. 526var commonOsToOsSpecificVariantTag = archDepTag{name: "common os to os specific"} 527 528// Get the OsType specific variants for the current CommonOS variant. 529// 530// The returned list will only contain enabled OsType specific variants of the 531// module referenced in the supplied context. An empty list is returned if there 532// are no enabled variants or the supplied context is not for an CommonOS 533// variant. 534func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module { 535 var variants []Module 536 mctx.VisitDirectDeps(func(m Module) { 537 if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag { 538 if m.Enabled(mctx) { 539 variants = append(variants, m) 540 } 541 } 542 }) 543 return variants 544} 545 546var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"} 547 548// archTransitionMutator splits a module into a variant for each Target requested by the module. Target selection 549// for a module is in three levels, OsClass, multilib, and then Target. 550// OsClass selection is determined by: 551// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects 552// whether the module type can compile for host, device or both. 553// - The host_supported and device_supported properties on the module. 554// 555// If host is supported for the module, the Host and HostCross OsClasses are selected. If device is supported 556// for the module, the Device OsClass is selected. 557// Within each selected OsClass, the multilib selection is determined by: 558// - The compile_multilib property if it set (which may be overridden by target.android.compile_multilib or 559// target.host.compile_multilib). 560// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set. 561// 562// Valid multilib values include: 563// 564// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm). 565// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64, 566// but may be arm for a 32-bit only build. 567// "32": compile for only a single 32-bit Target supported by the OsClass. 568// "64": compile for only a single 64-bit Target supported by the OsClass. 569// "common": compile a for a single Target that will work on all Targets supported by the OsClass (for example Java). 570// 571// Once the list of Targets is determined, the module is split into a variant for each Target. 572// 573// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass, 574// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets(). 575type archTransitionMutator struct{} 576 577type allArchInfo struct { 578 Targets map[string]Target 579 MultiTargets []Target 580 Primary string 581 Multilib string 582} 583 584var allArchProvider = blueprint.NewMutatorProvider[*allArchInfo]("arch_propagate") 585 586func (a *archTransitionMutator) Split(ctx BaseModuleContext) []string { 587 module := ctx.Module() 588 base := module.base() 589 590 if !base.ArchSpecific() { 591 return []string{""} 592 } 593 594 os := base.commonProperties.CompileOS 595 if os == CommonOS { 596 // Do not create arch specific variants for the CommonOS variant. 597 return []string{""} 598 } 599 600 osTargets := ctx.Config().Targets[os] 601 602 image := base.commonProperties.ImageVariation 603 // Filter NativeBridge targets unless they are explicitly supported. 604 // Skip creating native bridge variants for non-core modules. 605 if os == Android && !(base.IsNativeBridgeSupported() && image == CoreVariation) { 606 osTargets = slices.DeleteFunc(slices.Clone(osTargets), func(t Target) bool { 607 return bool(t.NativeBridge) 608 }) 609 } 610 611 // Filter HostCross targets if disabled. 612 if base.HostSupported() && !base.HostCrossSupported() { 613 osTargets = slices.DeleteFunc(slices.Clone(osTargets), func(t Target) bool { 614 return t.HostCross 615 }) 616 } 617 618 // only the primary arch in the ramdisk / vendor_ramdisk / recovery partition 619 if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk() || module.InstallInDebugRamdisk()) { 620 osTargets = []Target{osTargets[0]} 621 } 622 623 // Windows builds always prefer 32-bit 624 prefer32 := os == Windows 625 626 // Determine the multilib selection for this module. 627 multilib, extraMultilib := decodeMultilib(ctx, base) 628 629 // Convert the multilib selection into a list of Targets. 630 targets, err := decodeMultilibTargets(multilib, osTargets, prefer32) 631 if err != nil { 632 ctx.ModuleErrorf("%s", err.Error()) 633 } 634 635 // If there are no supported targets disable the module. 636 if len(targets) == 0 { 637 base.Disable() 638 return []string{""} 639 } 640 641 // If the module is using extraMultilib, decode the extraMultilib selection into 642 // a separate list of Targets. 643 var multiTargets []Target 644 if extraMultilib != "" { 645 multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32) 646 if err != nil { 647 ctx.ModuleErrorf("%s", err.Error()) 648 } 649 multiTargets = filterHostCross(multiTargets, targets[0].HostCross) 650 } 651 652 // Recovery is always the primary architecture, filter out any other architectures. 653 // Common arch is also allowed 654 if image == RecoveryVariation { 655 primaryArch := ctx.Config().DevicePrimaryArchType() 656 targets = filterToArch(targets, primaryArch, Common) 657 multiTargets = filterToArch(multiTargets, primaryArch, Common) 658 } 659 660 // If there are no supported targets disable the module. 661 if len(targets) == 0 { 662 base.Disable() 663 return []string{""} 664 } 665 666 // Convert the targets into a list of arch variation names. 667 targetNames := make([]string, len(targets)) 668 targetMapping := make(map[string]Target, len(targets)) 669 for i, target := range targets { 670 targetNames[i] = target.ArchVariation() 671 targetMapping[targetNames[i]] = targets[i] 672 } 673 674 SetProvider(ctx, allArchProvider, &allArchInfo{ 675 Targets: targetMapping, 676 MultiTargets: multiTargets, 677 Primary: targetNames[0], 678 Multilib: multilib, 679 }) 680 return targetNames 681} 682 683func (a *archTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string { 684 return sourceVariation 685} 686 687func (a *archTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string { 688 module := ctx.Module() 689 base := module.base() 690 691 if !base.ArchSpecific() { 692 return "" 693 } 694 695 os := base.commonProperties.CompileOS 696 if os == CommonOS { 697 // Do not create arch specific variants for the CommonOS variant. 698 return "" 699 } 700 701 multilib, _ := decodeMultilib(ctx, base) 702 if multilib == "common" { 703 return "common" 704 } 705 return incomingVariation 706} 707 708func (a *archTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) { 709 module := ctx.Module() 710 base := module.base() 711 os := base.commonProperties.CompileOS 712 713 if os == CommonOS { 714 // Make sure that the target related properties are initialized for the 715 // CommonOS variant. 716 addTargetProperties(module, commonTargetMap[os.Name], nil, true) 717 return 718 } 719 720 if variation == "" { 721 return 722 } 723 724 if !base.ArchSpecific() { 725 panic(fmt.Errorf("found variation %q for non arch specifc module", variation)) 726 } 727 728 allArchInfo, ok := ModuleProvider(ctx, allArchProvider) 729 if !ok { 730 return 731 } 732 733 target, ok := allArchInfo.Targets[variation] 734 if !ok { 735 panic(fmt.Errorf("missing Target for %q", variation)) 736 } 737 primary := variation == allArchInfo.Primary 738 multiTargets := allArchInfo.MultiTargets 739 740 // Annotate the new variant with which Target it was created for, and 741 // squash the appropriate arch-specific properties into the top level properties. 742 addTargetProperties(ctx.Module(), target, multiTargets, primary) 743 base.setArchProperties(ctx) 744 745 // Install support doesn't understand Darwin+Arm64 746 if os == Darwin && target.HostCross { 747 base.commonProperties.SkipInstall = true 748 } 749 750 // Create a dependency for Darwin Universal binaries from the primary to secondary 751 // architecture. The module itself will be responsible for calling lipo to merge the outputs. 752 if os == Darwin { 753 isUniversalBinary := allArchInfo.Multilib == "darwin_universal" && len(allArchInfo.Targets) == 2 754 isPrimary := variation == ctx.Config().BuildArch.String() 755 hasSecondaryConfigured := len(ctx.Config().Targets[Darwin]) > 1 756 if isUniversalBinary && isPrimary && hasSecondaryConfigured { 757 secondaryArch := ctx.Config().Targets[Darwin][1].Arch.String() 758 variation := []blueprint.Variation{{"arch", secondaryArch}} 759 ctx.AddVariationDependencies(variation, DarwinUniversalVariantTag, ctx.ModuleName()) 760 } 761 } 762 763} 764 765// addTargetProperties annotates a variant with the Target is is being compiled for, the list 766// of additional Targets it is supporting (if any), and whether it is the primary Target for 767// the module. 768func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) { 769 m.base().commonProperties.CompileTarget = target 770 m.base().commonProperties.CompileMultiTargets = multiTargets 771 m.base().commonProperties.CompilePrimary = primaryTarget 772 m.base().commonProperties.ArchReady = true 773} 774 775// decodeMultilib returns the appropriate compile_multilib property for the module, or the default 776// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that 777// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns 778// the actual multilib in extraMultilib. 779func decodeMultilib(ctx ConfigContext, base *ModuleBase) (multilib, extraMultilib string) { 780 os := base.commonProperties.CompileOS 781 ignorePrefer32OnDevice := ctx.Config().IgnorePrefer32OnDevice() 782 // First check the "android.compile_multilib" or "host.compile_multilib" properties. 783 switch os.Class { 784 case Device: 785 multilib = String(base.commonProperties.Target.Android.Compile_multilib) 786 case Host: 787 multilib = String(base.commonProperties.Target.Host.Compile_multilib) 788 } 789 790 // If those aren't set, try the "compile_multilib" property. 791 if multilib == "" { 792 multilib = String(base.commonProperties.Compile_multilib) 793 } 794 795 // If that wasn't set, use the default multilib set by the factory. 796 if multilib == "" { 797 multilib = base.commonProperties.Default_multilib 798 } 799 800 // If a device is configured with multiple targets, this option 801 // force all device targets that prefer32 to be compiled only as 802 // the first target. 803 if ignorePrefer32OnDevice && os.Class == Device && (multilib == "prefer32" || multilib == "first_prefer32") { 804 multilib = "first" 805 } 806 807 if base.commonProperties.UseTargetVariants { 808 // Darwin has the concept of "universal binaries" which is implemented in Soong by 809 // building both x86_64 and arm64 variants, and having select module types know how to 810 // merge the outputs of their corresponding variants together into a final binary. Most 811 // module types don't need to understand this logic, as we only build a small portion 812 // of the tree for Darwin, and only module types writing macho files need to do the 813 // merging. 814 // 815 // This logic is not enabled for: 816 // "common", as it's not an arch-specific variant 817 // "32", as Darwin never has a 32-bit variant 818 // !UseTargetVariants, as the module has opted into handling the arch-specific logic on 819 // its own. 820 if os == Darwin && multilib != "common" && multilib != "32" { 821 multilib = "darwin_universal" 822 } 823 824 return multilib, "" 825 } else { 826 // For app modules a single arch variant will be created per OS class which is expected to handle all the 827 // selected arches. Return the common-type as multilib and any Android.bp provided multilib as extraMultilib 828 if multilib == base.commonProperties.Default_multilib { 829 multilib = "first" 830 } 831 return base.commonProperties.Default_multilib, multilib 832 } 833} 834 835// filterToArch takes a list of Targets and an ArchType, and returns a modified list that contains 836// only Targets that have the specified ArchTypes. 837func filterToArch(targets []Target, archs ...ArchType) []Target { 838 for i := 0; i < len(targets); i++ { 839 found := false 840 for _, arch := range archs { 841 if targets[i].Arch.ArchType == arch { 842 found = true 843 break 844 } 845 } 846 if !found { 847 targets = append(targets[:i], targets[i+1:]...) 848 i-- 849 } 850 } 851 return targets 852} 853 854// filterHostCross takes a list of Targets and a hostCross value, and returns a modified list 855// that contains only Targets that have the specified HostCross. 856func filterHostCross(targets []Target, hostCross bool) []Target { 857 for i := 0; i < len(targets); i++ { 858 if targets[i].HostCross != hostCross { 859 targets = append(targets[:i], targets[i+1:]...) 860 i-- 861 } 862 } 863 return targets 864} 865 866// archPropRoot is a struct type used as the top level of the arch-specific properties. It 867// contains the "arch", "multilib", and "target" property structs. It is used to split up the 868// property structs to limit how much is allocated when a single arch-specific property group is 869// used. The types are interface{} because they will hold instances of runtime-created types. 870type archPropRoot struct { 871 Arch, Multilib, Target interface{} 872} 873 874// archPropTypeDesc holds the runtime-created types for the property structs to instantiate to 875// create an archPropRoot property struct. 876type archPropTypeDesc struct { 877 arch, multilib, target reflect.Type 878} 879 880// createArchPropTypeDesc takes a reflect.Type that is either a struct or a pointer to a struct, and 881// returns lists of reflect.Types that contains the arch-variant properties inside structs for each 882// arch, multilib and target property. 883// 884// This is a relatively expensive operation, so the results are cached in the global 885// archPropTypeMap. It is constructed entirely based on compile-time data, so there is no need 886// to isolate the results between multiple tests running in parallel. 887func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc { 888 // Each property struct shard will be nested many times under the runtime generated arch struct, 889 // which can hit the limit of 64kB for the name of runtime generated structs. They are nested 890 // 97 times now, which may grow in the future, plus there is some overhead for the containing 891 // type. This number may need to be reduced if too many are added, but reducing it too far 892 // could cause problems if a single deeply nested property no longer fits in the name. 893 const maxArchTypeNameSize = 500 894 895 // Convert the type to a new set of types that contains only the arch-specific properties 896 // (those that are tagged with `android:"arch_variant"`), and sharded into multiple types 897 // to keep the runtime-generated names under the limit. 898 propShards, _ := proptools.FilterPropertyStructSharded(props, maxArchTypeNameSize, filterArchStruct) 899 900 // If the type has no arch-specific properties there is nothing to do. 901 if len(propShards) == 0 { 902 return nil 903 } 904 905 var ret []archPropTypeDesc 906 for _, props := range propShards { 907 908 // variantFields takes a list of variant property field names and returns a list the 909 // StructFields with the names and the type of the current shard. 910 variantFields := func(names []string) []reflect.StructField { 911 ret := make([]reflect.StructField, len(names)) 912 913 for i, name := range names { 914 ret[i].Name = name 915 ret[i].Type = props 916 } 917 918 return ret 919 } 920 921 // Create a type that contains the properties in this shard repeated for each 922 // architecture, architecture variant, and architecture feature. 923 archFields := make([]reflect.StructField, len(archTypeList)) 924 for i, arch := range archTypeList { 925 var variants []string 926 927 for _, archVariant := range archVariants[arch] { 928 archVariant := variantReplacer.Replace(archVariant) 929 variants = append(variants, proptools.FieldNameForProperty(archVariant)) 930 } 931 for _, cpuVariant := range cpuVariants[arch] { 932 cpuVariant := variantReplacer.Replace(cpuVariant) 933 variants = append(variants, proptools.FieldNameForProperty(cpuVariant)) 934 } 935 for _, feature := range archFeatures[arch] { 936 feature := variantReplacer.Replace(feature) 937 variants = append(variants, proptools.FieldNameForProperty(feature)) 938 } 939 940 // Create the StructFields for each architecture variant architecture feature 941 // (e.g. "arch.arm.cortex-a53" or "arch.arm.neon"). 942 fields := variantFields(variants) 943 944 // Create the StructField for the architecture itself (e.g. "arch.arm"). The special 945 // "BlueprintEmbed" name is used by Blueprint to put the properties in the 946 // parent struct. 947 fields = append([]reflect.StructField{{ 948 Name: "BlueprintEmbed", 949 Type: props, 950 Anonymous: true, 951 }}, fields...) 952 953 archFields[i] = reflect.StructField{ 954 Name: arch.Field, 955 Type: reflect.StructOf(fields), 956 } 957 } 958 959 // Create the type of the "arch" property struct for this shard. 960 archType := reflect.StructOf(archFields) 961 962 // Create the type for the "multilib" property struct for this shard, containing the 963 // "multilib.lib32" and "multilib.lib64" property structs. 964 multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"})) 965 966 // Start with a list of the special targets 967 targets := []string{ 968 "Host", 969 "Android64", 970 "Android32", 971 "Bionic", 972 "Glibc", 973 "Musl", 974 "Linux", 975 "Host_linux", 976 "Not_windows", 977 "Arm_on_x86", 978 "Arm_on_x86_64", 979 "Native_bridge", 980 } 981 for _, os := range osTypeList { 982 // Add all the OSes. 983 targets = append(targets, os.Field) 984 985 // Add the OS/Arch combinations, e.g. "android_arm64". 986 for _, archType := range osArchTypeMap[os] { 987 targets = append(targets, GetCompoundTargetField(os, archType)) 988 989 // Also add the special "linux_<arch>", "bionic_<arch>" , "glibc_<arch>", and 990 // "musl_<arch>" property structs. 991 if os.Linux() { 992 target := "Linux_" + archType.Name 993 if !InList(target, targets) { 994 targets = append(targets, target) 995 } 996 } 997 if os.Linux() && os.Class == Host { 998 target := "Host_linux_" + archType.Name 999 if !InList(target, targets) { 1000 targets = append(targets, target) 1001 } 1002 } 1003 if os.Bionic() { 1004 target := "Bionic_" + archType.Name 1005 if !InList(target, targets) { 1006 targets = append(targets, target) 1007 } 1008 } 1009 if os == Linux { 1010 target := "Glibc_" + archType.Name 1011 if !InList(target, targets) { 1012 targets = append(targets, target) 1013 } 1014 } 1015 if os == LinuxMusl { 1016 target := "Musl_" + archType.Name 1017 if !InList(target, targets) { 1018 targets = append(targets, target) 1019 } 1020 } 1021 } 1022 } 1023 1024 // Create the type for the "target" property struct for this shard. 1025 targetType := reflect.StructOf(variantFields(targets)) 1026 1027 // Return a descriptor of the 3 runtime-created types. 1028 ret = append(ret, archPropTypeDesc{ 1029 arch: reflect.PtrTo(archType), 1030 multilib: reflect.PtrTo(multilibType), 1031 target: reflect.PtrTo(targetType), 1032 }) 1033 } 1034 return ret 1035} 1036 1037// variantReplacer converts architecture variant or architecture feature names into names that 1038// are valid for an Android.bp file. 1039var variantReplacer = strings.NewReplacer("-", "_", ".", "_") 1040 1041// filterArchStruct returns true if the given field is an architecture specific property. 1042func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.StructField) { 1043 if proptools.HasTag(field, "android", "arch_variant") { 1044 // The arch_variant field isn't necessary past this point 1045 // Instead of wasting space, just remove it. Go also has a 1046 // 16-bit limit on structure name length. The name is constructed 1047 // based on the Go source representation of the structure, so 1048 // the tag names count towards that length. 1049 1050 androidTag := field.Tag.Get("android") 1051 values := strings.Split(androidTag, ",") 1052 1053 if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` { 1054 panic(fmt.Errorf("unexpected tag format %q", field.Tag)) 1055 } 1056 // these tags don't need to be present in the runtime generated struct type. 1057 // However replace_instead_of_append does, because it's read by the blueprint 1058 // property extending util functions, which can operate on these generated arch 1059 // property structs. 1060 values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"}) 1061 if len(values) > 0 { 1062 if values[0] != "replace_instead_of_append" || len(values) > 1 { 1063 panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name)) 1064 } 1065 field.Tag = `android:"replace_instead_of_append"` 1066 } else { 1067 field.Tag = `` 1068 } 1069 return true, field 1070 } 1071 return false, field 1072} 1073 1074// archPropTypeMap contains a cache of the results of createArchPropTypeDesc for each type. It is 1075// shared across all Contexts, but is constructed based only on compile-time information so there 1076// is no risk of contaminating one Context with data from another. 1077var archPropTypeMap OncePer 1078 1079// initArchModule adds the architecture-specific property structs to a Module. 1080func initArchModule(m Module) { 1081 1082 base := m.base() 1083 1084 if len(base.archProperties) != 0 { 1085 panic(fmt.Errorf("module %s already has archProperties", m.Name())) 1086 } 1087 1088 getStructType := func(properties interface{}) reflect.Type { 1089 propertiesValue := reflect.ValueOf(properties) 1090 t := propertiesValue.Type() 1091 if propertiesValue.Kind() != reflect.Ptr { 1092 panic(fmt.Errorf("properties must be a pointer to a struct, got %T", 1093 propertiesValue.Interface())) 1094 } 1095 1096 propertiesValue = propertiesValue.Elem() 1097 if propertiesValue.Kind() != reflect.Struct { 1098 panic(fmt.Errorf("properties must be a pointer to a struct, got a pointer to %T", 1099 propertiesValue.Interface())) 1100 } 1101 return t 1102 } 1103 1104 for _, properties := range m.GetProperties() { 1105 t := getStructType(properties) 1106 // Get or create the arch-specific property struct types for this property struct type. 1107 archPropTypes := archPropTypeMap.Once(NewCustomOnceKey(t), func() interface{} { 1108 return createArchPropTypeDesc(t) 1109 }).([]archPropTypeDesc) 1110 1111 // Instantiate one of each arch-specific property struct type and add it to the 1112 // properties for the Module. 1113 var archProperties []interface{} 1114 for _, t := range archPropTypes { 1115 archProperties = append(archProperties, &archPropRoot{ 1116 Arch: reflect.Zero(t.arch).Interface(), 1117 Multilib: reflect.Zero(t.multilib).Interface(), 1118 Target: reflect.Zero(t.target).Interface(), 1119 }) 1120 } 1121 base.archProperties = append(base.archProperties, archProperties) 1122 m.AddProperties(archProperties...) 1123 } 1124 1125} 1126 1127func maybeBlueprintEmbed(src reflect.Value) reflect.Value { 1128 // If the value of the field is a struct (as opposed to a pointer to a struct) then step 1129 // into the BlueprintEmbed field. 1130 if src.Kind() == reflect.Struct { 1131 return src.FieldByName("BlueprintEmbed") 1132 } else { 1133 return src 1134 } 1135} 1136 1137// Merges the property struct in srcValue into dst. 1138func mergePropertyStruct(ctx ArchVariantContext, dst interface{}, srcValue reflect.Value) { 1139 src := maybeBlueprintEmbed(srcValue).Interface() 1140 1141 // order checks the `android:"variant_prepend"` tag to handle properties where the 1142 // arch-specific value needs to come before the generic value, for example for lists of 1143 // include directories. 1144 order := func(dstField, srcField reflect.StructField) (proptools.Order, error) { 1145 if proptools.HasTag(dstField, "android", "variant_prepend") { 1146 return proptools.Prepend, nil 1147 } else { 1148 return proptools.Append, nil 1149 } 1150 } 1151 1152 // Squash the located property struct into the destination property struct. 1153 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src, nil, order) 1154 if err != nil { 1155 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { 1156 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) 1157 } else { 1158 panic(err) 1159 } 1160 } 1161} 1162 1163// Returns the immediate child of the input property struct that corresponds to 1164// the sub-property "field". 1165func getChildPropertyStruct(ctx ArchVariantContext, 1166 src reflect.Value, field, userFriendlyField string) (reflect.Value, bool) { 1167 1168 // Step into non-nil pointers to structs in the src value. 1169 if src.Kind() == reflect.Ptr { 1170 if src.IsNil() { 1171 return reflect.Value{}, false 1172 } 1173 src = src.Elem() 1174 } 1175 1176 // Find the requested field in the src struct. 1177 child := src.FieldByName(proptools.FieldNameForProperty(field)) 1178 if !child.IsValid() { 1179 ctx.ModuleErrorf("field %q does not exist", userFriendlyField) 1180 return reflect.Value{}, false 1181 } 1182 1183 if child.IsZero() { 1184 return reflect.Value{}, false 1185 } 1186 1187 return child, true 1188} 1189 1190// Squash the appropriate OS-specific property structs into the matching top level property structs 1191// based on the CompileOS value that was annotated on the variant. 1192func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { 1193 os := m.commonProperties.CompileOS 1194 1195 for i := range m.archProperties { 1196 genProps := m.GetProperties()[i] 1197 if m.archProperties[i] == nil { 1198 continue 1199 } 1200 for _, archProperties := range m.archProperties[i] { 1201 archPropValues := reflect.ValueOf(archProperties).Elem() 1202 1203 targetProp := archPropValues.FieldByName("Target").Elem() 1204 1205 // Handle host-specific properties in the form: 1206 // target: { 1207 // host: { 1208 // key: value, 1209 // }, 1210 // }, 1211 if os.Class == Host { 1212 field := "Host" 1213 prefix := "target.host" 1214 if hostProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1215 mergePropertyStruct(ctx, genProps, hostProperties) 1216 } 1217 } 1218 1219 // Handle target OS generalities of the form: 1220 // target: { 1221 // bionic: { 1222 // key: value, 1223 // }, 1224 // } 1225 if os.Linux() { 1226 field := "Linux" 1227 prefix := "target.linux" 1228 if linuxProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1229 mergePropertyStruct(ctx, genProps, linuxProperties) 1230 } 1231 } 1232 1233 if os.Linux() && os.Class == Host { 1234 field := "Host_linux" 1235 prefix := "target.host_linux" 1236 if linuxProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1237 mergePropertyStruct(ctx, genProps, linuxProperties) 1238 } 1239 } 1240 1241 if os.Bionic() { 1242 field := "Bionic" 1243 prefix := "target.bionic" 1244 if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1245 mergePropertyStruct(ctx, genProps, bionicProperties) 1246 } 1247 } 1248 1249 if os == Linux { 1250 field := "Glibc" 1251 prefix := "target.glibc" 1252 if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1253 mergePropertyStruct(ctx, genProps, bionicProperties) 1254 } 1255 } 1256 1257 if os == LinuxMusl { 1258 field := "Musl" 1259 prefix := "target.musl" 1260 if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1261 mergePropertyStruct(ctx, genProps, bionicProperties) 1262 } 1263 } 1264 1265 // Handle target OS properties in the form: 1266 // target: { 1267 // linux_glibc: { 1268 // key: value, 1269 // }, 1270 // not_windows: { 1271 // key: value, 1272 // }, 1273 // android { 1274 // key: value, 1275 // }, 1276 // }, 1277 field := os.Field 1278 prefix := "target." + os.Name 1279 if osProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1280 mergePropertyStruct(ctx, genProps, osProperties) 1281 } 1282 1283 if os.Class == Host && os != Windows { 1284 field := "Not_windows" 1285 prefix := "target.not_windows" 1286 if notWindowsProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1287 mergePropertyStruct(ctx, genProps, notWindowsProperties) 1288 } 1289 } 1290 1291 // Handle 64-bit device properties in the form: 1292 // target { 1293 // android64 { 1294 // key: value, 1295 // }, 1296 // android32 { 1297 // key: value, 1298 // }, 1299 // }, 1300 // WARNING: this is probably not what you want to use in your blueprints file, it selects 1301 // options for all targets on a device that supports 64-bit binaries, not just the targets 1302 // that are being compiled for 64-bit. Its expected use case is binaries like linker and 1303 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device 1304 if os.Class == Device { 1305 if ctx.Config().Android64() { 1306 field := "Android64" 1307 prefix := "target.android64" 1308 if android64Properties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1309 mergePropertyStruct(ctx, genProps, android64Properties) 1310 } 1311 } else { 1312 field := "Android32" 1313 prefix := "target.android32" 1314 if android32Properties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { 1315 mergePropertyStruct(ctx, genProps, android32Properties) 1316 } 1317 } 1318 } 1319 } 1320 } 1321} 1322 1323// Returns the struct containing the properties specific to the given 1324// architecture type. These look like this in Blueprint files: 1325// 1326// arch: { 1327// arm64: { 1328// key: value, 1329// }, 1330// }, 1331// 1332// This struct will also contain sub-structs containing to the architecture/CPU 1333// variants and features that themselves contain properties specific to those. 1334func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) { 1335 archPropValues := reflect.ValueOf(archProperties).Elem() 1336 archProp := archPropValues.FieldByName("Arch").Elem() 1337 prefix := "arch." + archType.Name 1338 return getChildPropertyStruct(ctx, archProp, archType.Name, prefix) 1339} 1340 1341// Returns the struct containing the properties specific to a given multilib 1342// value. These look like this in the Blueprint file: 1343// 1344// multilib: { 1345// lib32: { 1346// key: value, 1347// }, 1348// }, 1349func getMultilibStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) { 1350 archPropValues := reflect.ValueOf(archProperties).Elem() 1351 multilibProp := archPropValues.FieldByName("Multilib").Elem() 1352 return getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib) 1353} 1354 1355func GetCompoundTargetField(os OsType, arch ArchType) string { 1356 return os.Field + "_" + arch.Name 1357} 1358 1359// Returns the structs corresponding to the properties specific to the given 1360// architecture and OS in archProperties. 1361func getArchProperties(ctx BaseModuleContext, archProperties interface{}, arch Arch, os OsType, nativeBridgeEnabled bool) []reflect.Value { 1362 result := make([]reflect.Value, 0) 1363 archPropValues := reflect.ValueOf(archProperties).Elem() 1364 1365 targetProp := archPropValues.FieldByName("Target").Elem() 1366 1367 archType := arch.ArchType 1368 1369 if arch.ArchType != Common { 1370 archStruct, ok := getArchTypeStruct(ctx, archProperties, arch.ArchType) 1371 if ok { 1372 result = append(result, archStruct) 1373 1374 // Handle arch-variant-specific properties in the form: 1375 // arch: { 1376 // arm: { 1377 // variant: { 1378 // key: value, 1379 // }, 1380 // }, 1381 // }, 1382 v := variantReplacer.Replace(arch.ArchVariant) 1383 if v != "" { 1384 prefix := "arch." + archType.Name + "." + v 1385 if variantProperties, ok := getChildPropertyStruct(ctx, archStruct, v, prefix); ok { 1386 result = append(result, variantProperties) 1387 } 1388 } 1389 1390 // Handle cpu-variant-specific properties in the form: 1391 // arch: { 1392 // arm: { 1393 // variant: { 1394 // key: value, 1395 // }, 1396 // }, 1397 // }, 1398 if arch.CpuVariant != arch.ArchVariant { 1399 c := variantReplacer.Replace(arch.CpuVariant) 1400 if c != "" { 1401 prefix := "arch." + archType.Name + "." + c 1402 if cpuVariantProperties, ok := getChildPropertyStruct(ctx, archStruct, c, prefix); ok { 1403 result = append(result, cpuVariantProperties) 1404 } 1405 } 1406 } 1407 1408 // Handle arch-feature-specific properties in the form: 1409 // arch: { 1410 // arm: { 1411 // feature: { 1412 // key: value, 1413 // }, 1414 // }, 1415 // }, 1416 for _, feature := range arch.ArchFeatures { 1417 prefix := "arch." + archType.Name + "." + feature 1418 if featureProperties, ok := getChildPropertyStruct(ctx, archStruct, feature, prefix); ok { 1419 result = append(result, featureProperties) 1420 } 1421 } 1422 } 1423 1424 if multilibProperties, ok := getMultilibStruct(ctx, archProperties, archType); ok { 1425 result = append(result, multilibProperties) 1426 } 1427 1428 // Handle combined OS-feature and arch specific properties in the form: 1429 // target: { 1430 // bionic_x86: { 1431 // key: value, 1432 // }, 1433 // } 1434 if os.Linux() { 1435 field := "Linux_" + arch.ArchType.Name 1436 userFriendlyField := "target.linux_" + arch.ArchType.Name 1437 if linuxProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { 1438 result = append(result, linuxProperties) 1439 } 1440 } 1441 1442 if os.Bionic() { 1443 field := "Bionic_" + archType.Name 1444 userFriendlyField := "target.bionic_" + archType.Name 1445 if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { 1446 result = append(result, bionicProperties) 1447 } 1448 } 1449 1450 // Handle combined OS and arch specific properties in the form: 1451 // target: { 1452 // linux_glibc_x86: { 1453 // key: value, 1454 // }, 1455 // linux_glibc_arm: { 1456 // key: value, 1457 // }, 1458 // android_arm { 1459 // key: value, 1460 // }, 1461 // android_x86 { 1462 // key: value, 1463 // }, 1464 // }, 1465 field := GetCompoundTargetField(os, archType) 1466 userFriendlyField := "target." + os.Name + "_" + archType.Name 1467 if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { 1468 result = append(result, osArchProperties) 1469 } 1470 1471 if os == Linux { 1472 field := "Glibc_" + archType.Name 1473 userFriendlyField := "target.glibc_" + "_" + archType.Name 1474 if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { 1475 result = append(result, osArchProperties) 1476 } 1477 } 1478 1479 if os == LinuxMusl { 1480 field := "Musl_" + archType.Name 1481 userFriendlyField := "target.musl_" + "_" + archType.Name 1482 if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { 1483 result = append(result, osArchProperties) 1484 } 1485 } 1486 } 1487 1488 // Handle arm on x86 properties in the form: 1489 // target { 1490 // arm_on_x86 { 1491 // key: value, 1492 // }, 1493 // arm_on_x86_64 { 1494 // key: value, 1495 // }, 1496 // }, 1497 if os.Class == Device { 1498 if arch.ArchType == X86 && (hasArmAbi(arch) || 1499 hasArmAndroidArch(ctx.Config().Targets[Android])) { 1500 field := "Arm_on_x86" 1501 userFriendlyField := "target.arm_on_x86" 1502 if armOnX86Properties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { 1503 result = append(result, armOnX86Properties) 1504 } 1505 } 1506 if arch.ArchType == X86_64 && (hasArmAbi(arch) || 1507 hasArmAndroidArch(ctx.Config().Targets[Android])) { 1508 field := "Arm_on_x86_64" 1509 userFriendlyField := "target.arm_on_x86_64" 1510 if armOnX8664Properties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { 1511 result = append(result, armOnX8664Properties) 1512 } 1513 } 1514 if os == Android && nativeBridgeEnabled { 1515 userFriendlyField := "Native_bridge" 1516 prefix := "target.native_bridge" 1517 if nativeBridgeProperties, ok := getChildPropertyStruct(ctx, targetProp, userFriendlyField, prefix); ok { 1518 result = append(result, nativeBridgeProperties) 1519 } 1520 } 1521 } 1522 1523 return result 1524} 1525 1526// Squash the appropriate arch-specific property structs into the matching top level property 1527// structs based on the CompileTarget value that was annotated on the variant. 1528func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) { 1529 arch := m.Arch() 1530 os := m.Os() 1531 1532 for i := range m.archProperties { 1533 genProps := m.GetProperties()[i] 1534 if m.archProperties[i] == nil { 1535 continue 1536 } 1537 1538 propStructs := make([]reflect.Value, 0) 1539 for _, archProperty := range m.archProperties[i] { 1540 propStructShard := getArchProperties(ctx, archProperty, arch, os, m.Target().NativeBridge == NativeBridgeEnabled) 1541 propStructs = append(propStructs, propStructShard...) 1542 } 1543 1544 for _, propStruct := range propStructs { 1545 mergePropertyStruct(ctx, genProps, propStruct) 1546 } 1547 } 1548} 1549 1550// determineBuildOS stores the OS and architecture used for host targets used during the build into 1551// config based on the runtime OS and architecture determined by Go and the product configuration. 1552func determineBuildOS(config *config) { 1553 config.BuildOS = func() OsType { 1554 switch runtime.GOOS { 1555 case "linux": 1556 if Bool(config.productVariables.HostMusl) { 1557 return LinuxMusl 1558 } 1559 return Linux 1560 case "darwin": 1561 return Darwin 1562 default: 1563 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS)) 1564 } 1565 }() 1566 1567 config.BuildArch = func() ArchType { 1568 switch runtime.GOARCH { 1569 case "amd64": 1570 return X86_64 1571 default: 1572 panic(fmt.Sprintf("unsupported Arch: %s", runtime.GOARCH)) 1573 } 1574 }() 1575 1576} 1577 1578// Convert the arch product variables into a list of targets for each OsType. 1579func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) { 1580 variables := config.productVariables 1581 1582 targets := make(map[OsType][]Target) 1583 var targetErr error 1584 1585 type targetConfig struct { 1586 os OsType 1587 archName string 1588 archVariant *string 1589 cpuVariant *string 1590 abi []string 1591 nativeBridgeEnabled NativeBridgeSupport 1592 nativeBridgeHostArchName *string 1593 nativeBridgeRelativePath *string 1594 } 1595 1596 addTarget := func(target targetConfig) { 1597 if targetErr != nil { 1598 return 1599 } 1600 1601 arch, err := decodeArch(target.os, target.archName, target.archVariant, target.cpuVariant, target.abi) 1602 if err != nil { 1603 targetErr = err 1604 return 1605 } 1606 nativeBridgeRelativePathStr := String(target.nativeBridgeRelativePath) 1607 nativeBridgeHostArchNameStr := String(target.nativeBridgeHostArchName) 1608 1609 // Use guest arch as relative install path by default 1610 if target.nativeBridgeEnabled && nativeBridgeRelativePathStr == "" { 1611 nativeBridgeRelativePathStr = arch.ArchType.String() 1612 } 1613 1614 // A target is considered as HostCross if it's a host target which can't run natively on 1615 // the currently configured build machine (either because the OS is different or because of 1616 // the unsupported arch) 1617 hostCross := false 1618 if target.os.Class == Host { 1619 var osSupported bool 1620 if target.os == config.BuildOS { 1621 osSupported = true 1622 } else if config.BuildOS.Linux() && target.os.Linux() { 1623 // LinuxBionic and Linux are compatible 1624 osSupported = true 1625 } else { 1626 osSupported = false 1627 } 1628 1629 var archSupported bool 1630 if arch.ArchType == Common { 1631 archSupported = true 1632 } else if arch.ArchType.Name == *variables.HostArch { 1633 archSupported = true 1634 } else if variables.HostSecondaryArch != nil && arch.ArchType.Name == *variables.HostSecondaryArch { 1635 archSupported = true 1636 } else { 1637 archSupported = false 1638 } 1639 if !osSupported || !archSupported { 1640 hostCross = true 1641 } 1642 } 1643 1644 targets[target.os] = append(targets[target.os], 1645 Target{ 1646 Os: target.os, 1647 Arch: arch, 1648 NativeBridge: target.nativeBridgeEnabled, 1649 NativeBridgeHostArchName: nativeBridgeHostArchNameStr, 1650 NativeBridgeRelativePath: nativeBridgeRelativePathStr, 1651 HostCross: hostCross, 1652 }) 1653 } 1654 1655 if variables.HostArch == nil { 1656 return nil, fmt.Errorf("No host primary architecture set") 1657 } 1658 1659 // The primary host target, which must always exist. 1660 addTarget(targetConfig{os: config.BuildOS, archName: *variables.HostArch, nativeBridgeEnabled: NativeBridgeDisabled}) 1661 1662 // An optional secondary host target. 1663 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" { 1664 addTarget(targetConfig{os: config.BuildOS, archName: *variables.HostSecondaryArch, nativeBridgeEnabled: NativeBridgeDisabled}) 1665 } 1666 1667 // Optional cross-compiled host targets, generally Windows. 1668 if String(variables.CrossHost) != "" { 1669 crossHostOs := osByName(*variables.CrossHost) 1670 if crossHostOs == NoOsType { 1671 return nil, fmt.Errorf("Unknown cross host OS %q", *variables.CrossHost) 1672 } 1673 1674 if String(variables.CrossHostArch) == "" { 1675 return nil, fmt.Errorf("No cross-host primary architecture set") 1676 } 1677 1678 // The primary cross-compiled host target. 1679 addTarget(targetConfig{os: crossHostOs, archName: *variables.CrossHostArch, nativeBridgeEnabled: NativeBridgeDisabled}) 1680 1681 // An optional secondary cross-compiled host target. 1682 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" { 1683 addTarget(targetConfig{os: crossHostOs, archName: *variables.CrossHostSecondaryArch, nativeBridgeEnabled: NativeBridgeDisabled}) 1684 } 1685 } 1686 1687 // Optional device targets 1688 if variables.DeviceArch != nil && *variables.DeviceArch != "" { 1689 // The primary device target. 1690 addTarget(targetConfig{ 1691 os: Android, 1692 archName: *variables.DeviceArch, 1693 archVariant: variables.DeviceArchVariant, 1694 cpuVariant: variables.DeviceCpuVariant, 1695 abi: variables.DeviceAbi, 1696 nativeBridgeEnabled: NativeBridgeDisabled, 1697 }) 1698 1699 // An optional secondary device target. 1700 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" { 1701 addTarget(targetConfig{ 1702 os: Android, 1703 archName: *variables.DeviceSecondaryArch, 1704 archVariant: variables.DeviceSecondaryArchVariant, 1705 cpuVariant: variables.DeviceSecondaryCpuVariant, 1706 abi: variables.DeviceSecondaryAbi, 1707 nativeBridgeEnabled: NativeBridgeDisabled, 1708 }) 1709 } 1710 1711 // An optional NativeBridge device target. 1712 if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" { 1713 addTarget(targetConfig{ 1714 os: Android, 1715 archName: *variables.NativeBridgeArch, 1716 archVariant: variables.NativeBridgeArchVariant, 1717 cpuVariant: variables.NativeBridgeCpuVariant, 1718 abi: variables.NativeBridgeAbi, 1719 nativeBridgeEnabled: NativeBridgeEnabled, 1720 nativeBridgeHostArchName: variables.DeviceArch, 1721 nativeBridgeRelativePath: variables.NativeBridgeRelativePath, 1722 }) 1723 } 1724 1725 // An optional secondary NativeBridge device target. 1726 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" && 1727 variables.NativeBridgeSecondaryArch != nil && *variables.NativeBridgeSecondaryArch != "" { 1728 addTarget(targetConfig{ 1729 os: Android, 1730 archName: *variables.NativeBridgeSecondaryArch, 1731 archVariant: variables.NativeBridgeSecondaryArchVariant, 1732 cpuVariant: variables.NativeBridgeSecondaryCpuVariant, 1733 abi: variables.NativeBridgeSecondaryAbi, 1734 nativeBridgeEnabled: NativeBridgeEnabled, 1735 nativeBridgeHostArchName: variables.DeviceSecondaryArch, 1736 nativeBridgeRelativePath: variables.NativeBridgeSecondaryRelativePath, 1737 }) 1738 } 1739 } 1740 1741 if targetErr != nil { 1742 return nil, targetErr 1743 } 1744 1745 return targets, nil 1746} 1747 1748// hasArmAbi returns true if arch has at least one arm ABI 1749func hasArmAbi(arch Arch) bool { 1750 return PrefixInList(arch.Abi, "arm") 1751} 1752 1753// hasArmAndroidArch returns true if targets has at least 1754// one arm Android arch (possibly native bridged) 1755func hasArmAndroidArch(targets []Target) bool { 1756 for _, target := range targets { 1757 if target.Os == Android && 1758 (target.Arch.ArchType == Arm || target.Arch.ArchType == Arm64) { 1759 return true 1760 } 1761 } 1762 return false 1763} 1764 1765// archConfig describes a built-in configuration. 1766type archConfig struct { 1767 Arch string `json:"arch"` 1768 ArchVariant string `json:"arch_variant"` 1769 CpuVariant string `json:"cpu_variant"` 1770 Abi []string `json:"abis"` 1771} 1772 1773// getNdkAbisConfig returns the list of archConfigs that are used for building 1774// the API stubs and static libraries that are included in the NDK. 1775func getNdkAbisConfig() []archConfig { 1776 return []archConfig{ 1777 {"arm64", "armv8-a-branchprot", "", []string{"arm64-v8a"}}, 1778 {"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}}, 1779 {"riscv64", "", "", []string{"riscv64"}}, 1780 {"x86_64", "", "", []string{"x86_64"}}, 1781 {"x86", "", "", []string{"x86"}}, 1782 } 1783} 1784 1785// getAmlAbisConfig returns a list of archConfigs for the ABIs supported by mainline modules. 1786func getAmlAbisConfig() []archConfig { 1787 return []archConfig{ 1788 {"arm64", "armv8-a", "", []string{"arm64-v8a"}}, 1789 {"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}}, 1790 {"x86_64", "", "", []string{"x86_64"}}, 1791 {"x86", "", "", []string{"x86"}}, 1792 } 1793} 1794 1795// decodeArchSettings converts a list of archConfigs into a list of Targets for the given OsType. 1796func decodeAndroidArchSettings(archConfigs []archConfig) ([]Target, error) { 1797 var ret []Target 1798 1799 for _, config := range archConfigs { 1800 arch, err := decodeArch(Android, config.Arch, &config.ArchVariant, 1801 &config.CpuVariant, config.Abi) 1802 if err != nil { 1803 return nil, err 1804 } 1805 1806 ret = append(ret, Target{ 1807 Os: Android, 1808 Arch: arch, 1809 }) 1810 } 1811 1812 return ret, nil 1813} 1814 1815// decodeArch converts a set of strings from product variables into an Arch struct. 1816func decodeArch(os OsType, arch string, archVariant, cpuVariant *string, abi []string) (Arch, error) { 1817 // Verify the arch is valid 1818 archType, ok := archTypeMap[arch] 1819 if !ok { 1820 return Arch{}, fmt.Errorf("unknown arch %q", arch) 1821 } 1822 1823 a := Arch{ 1824 ArchType: archType, 1825 ArchVariant: String(archVariant), 1826 CpuVariant: String(cpuVariant), 1827 Abi: abi, 1828 } 1829 1830 // Convert generic arch variants into the empty string. 1831 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" { 1832 a.ArchVariant = "" 1833 } 1834 1835 // Convert generic CPU variants into the empty string. 1836 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" { 1837 a.CpuVariant = "" 1838 } 1839 1840 if a.ArchVariant != "" { 1841 if validArchVariants := archVariants[archType]; !InList(a.ArchVariant, validArchVariants) { 1842 return Arch{}, fmt.Errorf("[%q] unknown arch variant %q, support variants: %q", archType, a.ArchVariant, validArchVariants) 1843 } 1844 } 1845 1846 if a.CpuVariant != "" { 1847 if validCpuVariants := cpuVariants[archType]; !InList(a.CpuVariant, validCpuVariants) { 1848 return Arch{}, fmt.Errorf("[%q] unknown cpu variant %q, support variants: %q", archType, a.CpuVariant, validCpuVariants) 1849 } 1850 } 1851 1852 // Filter empty ABIs out of the list. 1853 for i := 0; i < len(a.Abi); i++ { 1854 if a.Abi[i] == "" { 1855 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...) 1856 i-- 1857 } 1858 } 1859 1860 // Set ArchFeatures from the arch type. for Android OS, other os-es do not specify features 1861 if os == Android { 1862 if featureMap, ok := androidArchFeatureMap[archType]; ok { 1863 a.ArchFeatures = featureMap[a.ArchVariant] 1864 } 1865 } 1866 1867 return a, nil 1868} 1869 1870// filterMultilibTargets takes a list of Targets and a multilib value and returns a new list of 1871// Targets containing only those that have the given multilib value. 1872func filterMultilibTargets(targets []Target, multilib string) []Target { 1873 var ret []Target 1874 for _, t := range targets { 1875 if t.Arch.ArchType.Multilib == multilib { 1876 ret = append(ret, t) 1877 } 1878 } 1879 return ret 1880} 1881 1882// getCommonTargets returns the set of Os specific common architecture targets for each Os in a list 1883// of targets. 1884func getCommonTargets(targets []Target) []Target { 1885 var ret []Target 1886 set := make(map[string]bool) 1887 1888 for _, t := range targets { 1889 if _, found := set[t.Os.String()]; !found { 1890 set[t.Os.String()] = true 1891 common := commonTargetMap[t.Os.String()] 1892 common.HostCross = t.HostCross 1893 ret = append(ret, common) 1894 } 1895 } 1896 1897 return ret 1898} 1899 1900// FirstTarget takes a list of Targets and a list of multilib values and returns a list of Targets 1901// that contains zero or one Target for each OsType and HostCross, selecting the one that matches 1902// the earliest filter. 1903func FirstTarget(targets []Target, filters ...string) []Target { 1904 // find the first target from each OS 1905 var ret []Target 1906 type osHostCross struct { 1907 os OsType 1908 hostCross bool 1909 } 1910 set := make(map[osHostCross]bool) 1911 1912 for _, filter := range filters { 1913 buildTargets := filterMultilibTargets(targets, filter) 1914 for _, t := range buildTargets { 1915 key := osHostCross{t.Os, t.HostCross} 1916 if _, found := set[key]; !found { 1917 set[key] = true 1918 ret = append(ret, t) 1919 } 1920 } 1921 } 1922 return ret 1923} 1924 1925// decodeMultilibTargets uses the module's multilib setting to select one or more targets from a 1926// list of Targets. 1927func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) { 1928 var buildTargets []Target 1929 1930 switch multilib { 1931 case "common": 1932 buildTargets = getCommonTargets(targets) 1933 case "both": 1934 if prefer32 { 1935 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...) 1936 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...) 1937 } else { 1938 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...) 1939 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...) 1940 } 1941 case "32": 1942 buildTargets = filterMultilibTargets(targets, "lib32") 1943 case "64": 1944 buildTargets = filterMultilibTargets(targets, "lib64") 1945 case "first": 1946 if prefer32 { 1947 buildTargets = FirstTarget(targets, "lib32", "lib64") 1948 } else { 1949 buildTargets = FirstTarget(targets, "lib64", "lib32") 1950 } 1951 case "first_prefer32": 1952 buildTargets = FirstTarget(targets, "lib32", "lib64") 1953 case "prefer32": 1954 buildTargets = filterMultilibTargets(targets, "lib32") 1955 if len(buildTargets) == 0 { 1956 buildTargets = filterMultilibTargets(targets, "lib64") 1957 } 1958 case "darwin_universal": 1959 buildTargets = filterMultilibTargets(targets, "lib64") 1960 // Reverse the targets so that the first architecture can depend on the second 1961 // architecture module in order to merge the outputs. 1962 ReverseSliceInPlace(buildTargets) 1963 default: 1964 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`, 1965 multilib) 1966 } 1967 1968 return buildTargets, nil 1969} 1970 1971// ArchVariantContext defines the limited context necessary to retrieve arch_variant properties. 1972type ArchVariantContext interface { 1973 ModuleErrorf(fmt string, args ...interface{}) 1974 PropertyErrorf(property, fmt string, args ...interface{}) 1975} 1976