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