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