xref: /aosp_15_r20/build/soong/android/arch.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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