1// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18	"encoding"
19	"fmt"
20	"reflect"
21	"runtime"
22	"strconv"
23	"strings"
24
25	"github.com/google/blueprint"
26	"github.com/google/blueprint/proptools"
27)
28
29const COMMON_VARIANT = "common"
30
31var (
32	archTypeList []ArchType
33
34	Arm    = newArch("arm", "lib32")
35	Arm64  = newArch("arm64", "lib64")
36	X86    = newArch("x86", "lib32")
37	X86_64 = newArch("x86_64", "lib64")
38
39	Common = ArchType{
40		Name: COMMON_VARIANT,
41	}
42)
43
44var archTypeMap = map[string]ArchType{
45	"arm":    Arm,
46	"arm64":  Arm64,
47	"x86":    X86,
48	"x86_64": X86_64,
49}
50
51/*
52Example blueprints file containing all variant property groups, with comment listing what type
53of variants get properties in that group:
54
55module {
56    arch: {
57        arm: {
58            // Host or device variants with arm architecture
59        },
60        arm64: {
61            // Host or device variants with arm64 architecture
62        },
63        x86: {
64            // Host or device variants with x86 architecture
65        },
66        x86_64: {
67            // Host or device variants with x86_64 architecture
68        },
69    },
70    multilib: {
71        lib32: {
72            // Host or device variants for 32-bit architectures
73        },
74        lib64: {
75            // Host or device variants for 64-bit architectures
76        },
77    },
78    target: {
79        android: {
80            // Device variants
81        },
82        host: {
83            // Host variants
84        },
85        linux_glibc: {
86            // Linux host variants
87        },
88        darwin: {
89            // Darwin host variants
90        },
91        windows: {
92            // Windows host variants
93        },
94        not_windows: {
95            // Non-windows host variants
96        },
97    },
98}
99*/
100
101var archVariants = map[ArchType][]string{
102	Arm: {
103		"armv7-a",
104		"armv7-a-neon",
105		"armv8-a",
106		"armv8-2a",
107		"cortex-a7",
108		"cortex-a8",
109		"cortex-a9",
110		"cortex-a15",
111		"cortex-a53",
112		"cortex-a53-a57",
113		"cortex-a55",
114		"cortex-a72",
115		"cortex-a73",
116		"cortex-a75",
117		"cortex-a76",
118		"krait",
119		"kryo",
120		"kryo385",
121		"exynos-m1",
122		"exynos-m2",
123	},
124	Arm64: {
125		"armv8_a",
126		"armv8_2a",
127		"cortex-a53",
128		"cortex-a55",
129		"cortex-a72",
130		"cortex-a73",
131		"cortex-a75",
132		"cortex-a76",
133		"kryo",
134		"kryo385",
135		"exynos-m1",
136		"exynos-m2",
137	},
138	X86: {
139		"amberlake",
140		"atom",
141		"broadwell",
142		"haswell",
143		"icelake",
144		"ivybridge",
145		"kabylake",
146		"sandybridge",
147		"silvermont",
148		"skylake",
149		"stoneyridge",
150		"tigerlake",
151		"whiskeylake",
152		"x86_64",
153	},
154	X86_64: {
155		"amberlake",
156		"broadwell",
157		"haswell",
158		"icelake",
159		"ivybridge",
160		"kabylake",
161		"sandybridge",
162		"silvermont",
163		"skylake",
164		"stoneyridge",
165		"tigerlake",
166		"whiskeylake",
167	},
168}
169
170var archFeatures = map[ArchType][]string{
171	Arm: {
172		"neon",
173	},
174	X86: {
175		"ssse3",
176		"sse4",
177		"sse4_1",
178		"sse4_2",
179		"aes_ni",
180		"avx",
181		"avx2",
182		"avx512",
183		"popcnt",
184		"movbe",
185	},
186	X86_64: {
187		"ssse3",
188		"sse4",
189		"sse4_1",
190		"sse4_2",
191		"aes_ni",
192		"avx",
193		"avx2",
194		"avx512",
195		"popcnt",
196	},
197}
198
199var archFeatureMap = map[ArchType]map[string][]string{
200	Arm: {
201		"armv7-a-neon": {
202			"neon",
203		},
204		"armv8-a": {
205			"neon",
206		},
207		"armv8-2a": {
208			"neon",
209		},
210	},
211	X86: {
212		"amberlake": {
213			"ssse3",
214			"sse4",
215			"sse4_1",
216			"sse4_2",
217			"avx",
218			"avx2",
219			"aes_ni",
220			"popcnt",
221		},
222		"atom": {
223			"ssse3",
224			"movbe",
225		},
226		"broadwell": {
227			"ssse3",
228			"sse4",
229			"sse4_1",
230			"sse4_2",
231			"avx",
232			"avx2",
233			"aes_ni",
234			"popcnt",
235		},
236		"haswell": {
237			"ssse3",
238			"sse4",
239			"sse4_1",
240			"sse4_2",
241			"aes_ni",
242			"avx",
243			"popcnt",
244			"movbe",
245		},
246		"icelake": {
247			"ssse3",
248			"sse4",
249			"sse4_1",
250			"sse4_2",
251			"avx",
252			"avx2",
253			"avx512",
254			"aes_ni",
255			"popcnt",
256		},
257		"ivybridge": {
258			"ssse3",
259			"sse4",
260			"sse4_1",
261			"sse4_2",
262			"aes_ni",
263			"avx",
264			"popcnt",
265		},
266		"kabylake": {
267			"ssse3",
268			"sse4",
269			"sse4_1",
270			"sse4_2",
271			"avx",
272			"avx2",
273			"aes_ni",
274			"popcnt",
275		},
276		"sandybridge": {
277			"ssse3",
278			"sse4",
279			"sse4_1",
280			"sse4_2",
281			"popcnt",
282		},
283		"silvermont": {
284			"ssse3",
285			"sse4",
286			"sse4_1",
287			"sse4_2",
288			"aes_ni",
289			"popcnt",
290			"movbe",
291		},
292		"skylake": {
293			"ssse3",
294			"sse4",
295			"sse4_1",
296			"sse4_2",
297			"avx",
298			"avx2",
299			"avx512",
300			"aes_ni",
301			"popcnt",
302		},
303		"stoneyridge": {
304			"ssse3",
305			"sse4",
306			"sse4_1",
307			"sse4_2",
308			"aes_ni",
309			"avx",
310			"avx2",
311			"popcnt",
312			"movbe",
313		},
314		"tigerlake": {
315			"ssse3",
316			"sse4",
317			"sse4_1",
318			"sse4_2",
319			"avx",
320			"avx2",
321			"avx512",
322			"aes_ni",
323			"popcnt",
324		},
325		"whiskeylake": {
326			"ssse3",
327			"sse4",
328			"sse4_1",
329			"sse4_2",
330			"avx",
331			"avx2",
332			"avx512",
333			"aes_ni",
334			"popcnt",
335		},
336		"x86_64": {
337			"ssse3",
338			"sse4",
339			"sse4_1",
340			"sse4_2",
341			"popcnt",
342		},
343	},
344	X86_64: {
345		"amberlake": {
346			"ssse3",
347			"sse4",
348			"sse4_1",
349			"sse4_2",
350			"avx",
351			"avx2",
352			"aes_ni",
353			"popcnt",
354		},
355		"broadwell": {
356			"ssse3",
357			"sse4",
358			"sse4_1",
359			"sse4_2",
360			"avx",
361			"avx2",
362			"aes_ni",
363			"popcnt",
364		},
365		"haswell": {
366			"ssse3",
367			"sse4",
368			"sse4_1",
369			"sse4_2",
370			"aes_ni",
371			"avx",
372			"popcnt",
373		},
374		"icelake": {
375			"ssse3",
376			"sse4",
377			"sse4_1",
378			"sse4_2",
379			"avx",
380			"avx2",
381			"avx512",
382			"aes_ni",
383			"popcnt",
384		},
385		"ivybridge": {
386			"ssse3",
387			"sse4",
388			"sse4_1",
389			"sse4_2",
390			"aes_ni",
391			"avx",
392			"popcnt",
393		},
394		"kabylake": {
395			"ssse3",
396			"sse4",
397			"sse4_1",
398			"sse4_2",
399			"avx",
400			"avx2",
401			"aes_ni",
402			"popcnt",
403		},
404		"sandybridge": {
405			"ssse3",
406			"sse4",
407			"sse4_1",
408			"sse4_2",
409			"popcnt",
410		},
411		"silvermont": {
412			"ssse3",
413			"sse4",
414			"sse4_1",
415			"sse4_2",
416			"aes_ni",
417			"popcnt",
418		},
419		"skylake": {
420			"ssse3",
421			"sse4",
422			"sse4_1",
423			"sse4_2",
424			"avx",
425			"avx2",
426			"avx512",
427			"aes_ni",
428			"popcnt",
429		},
430		"stoneyridge": {
431			"ssse3",
432			"sse4",
433			"sse4_1",
434			"sse4_2",
435			"aes_ni",
436			"avx",
437			"avx2",
438			"popcnt",
439		},
440		"tigerlake": {
441			"ssse3",
442			"sse4",
443			"sse4_1",
444			"sse4_2",
445			"avx",
446			"avx2",
447			"avx512",
448			"aes_ni",
449			"popcnt",
450		},
451		"whiskeylake": {
452			"ssse3",
453			"sse4",
454			"sse4_1",
455			"sse4_2",
456			"avx",
457			"avx2",
458			"avx512",
459			"aes_ni",
460			"popcnt",
461		},
462	},
463}
464
465var defaultArchFeatureMap = map[OsType]map[ArchType][]string{}
466
467func RegisterDefaultArchVariantFeatures(os OsType, arch ArchType, features ...string) {
468	checkCalledFromInit()
469
470	for _, feature := range features {
471		if !InList(feature, archFeatures[arch]) {
472			panic(fmt.Errorf("Invalid feature %q for arch %q variant \"\"", feature, arch))
473		}
474	}
475
476	if defaultArchFeatureMap[os] == nil {
477		defaultArchFeatureMap[os] = make(map[ArchType][]string)
478	}
479	defaultArchFeatureMap[os][arch] = features
480}
481
482// An Arch indicates a single CPU architecture.
483type Arch struct {
484	ArchType     ArchType
485	ArchVariant  string
486	CpuVariant   string
487	Abi          []string
488	ArchFeatures []string
489}
490
491func (a Arch) String() string {
492	s := a.ArchType.String()
493	if a.ArchVariant != "" {
494		s += "_" + a.ArchVariant
495	}
496	if a.CpuVariant != "" {
497		s += "_" + a.CpuVariant
498	}
499	return s
500}
501
502type ArchType struct {
503	Name     string
504	Field    string
505	Multilib string
506}
507
508func newArch(name, multilib string) ArchType {
509	archType := ArchType{
510		Name:     name,
511		Field:    proptools.FieldNameForProperty(name),
512		Multilib: multilib,
513	}
514	archTypeList = append(archTypeList, archType)
515	return archType
516}
517
518func ArchTypeList() []ArchType {
519	return append([]ArchType(nil), archTypeList...)
520}
521
522func (a ArchType) String() string {
523	return a.Name
524}
525
526var _ encoding.TextMarshaler = ArchType{}
527
528func (a ArchType) MarshalText() ([]byte, error) {
529	return []byte(strconv.Quote(a.String())), nil
530}
531
532var _ encoding.TextUnmarshaler = &ArchType{}
533
534func (a *ArchType) UnmarshalText(text []byte) error {
535	if u, ok := archTypeMap[string(text)]; ok {
536		*a = u
537		return nil
538	}
539
540	return fmt.Errorf("unknown ArchType %q", text)
541}
542
543var BuildOs = func() OsType {
544	switch runtime.GOOS {
545	case "linux":
546		return Linux
547	case "darwin":
548		return Darwin
549	default:
550		panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
551	}
552}()
553
554var (
555	OsTypeList      []OsType
556	commonTargetMap = make(map[string]Target)
557
558	NoOsType    OsType
559	Linux       = NewOsType("linux_glibc", Host, false)
560	Darwin      = NewOsType("darwin", Host, false)
561	LinuxBionic = NewOsType("linux_bionic", Host, false)
562	Windows     = NewOsType("windows", HostCross, true)
563	Android     = NewOsType("android", Device, false)
564	Fuchsia     = NewOsType("fuchsia", Device, false)
565
566	// A pseudo OSType for a common os variant, which is OSType agnostic and which
567	// has dependencies on all the OS variants.
568	CommonOS = NewOsType("common_os", Generic, false)
569
570	osArchTypeMap = map[OsType][]ArchType{
571		Linux:       []ArchType{X86, X86_64},
572		LinuxBionic: []ArchType{X86_64},
573		Darwin:      []ArchType{X86_64},
574		Windows:     []ArchType{X86, X86_64},
575		Android:     []ArchType{Arm, Arm64, X86, X86_64},
576		Fuchsia:     []ArchType{Arm64, X86_64},
577	}
578)
579
580type OsType struct {
581	Name, Field string
582	Class       OsClass
583
584	DefaultDisabled bool
585}
586
587type OsClass int
588
589const (
590	Generic OsClass = iota
591	Device
592	Host
593	HostCross
594)
595
596func (class OsClass) String() string {
597	switch class {
598	case Generic:
599		return "generic"
600	case Device:
601		return "device"
602	case Host:
603		return "host"
604	case HostCross:
605		return "host cross"
606	default:
607		panic(fmt.Errorf("unknown class %d", class))
608	}
609}
610
611func (os OsType) String() string {
612	return os.Name
613}
614
615func (os OsType) Bionic() bool {
616	return os == Android || os == LinuxBionic
617}
618
619func (os OsType) Linux() bool {
620	return os == Android || os == Linux || os == LinuxBionic
621}
622
623func NewOsType(name string, class OsClass, defDisabled bool) OsType {
624	os := OsType{
625		Name:  name,
626		Field: strings.Title(name),
627		Class: class,
628
629		DefaultDisabled: defDisabled,
630	}
631	OsTypeList = append(OsTypeList, os)
632
633	if _, found := commonTargetMap[name]; found {
634		panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
635	} else {
636		commonTargetMap[name] = Target{Os: os, Arch: Arch{ArchType: Common}}
637	}
638
639	return os
640}
641
642func osByName(name string) OsType {
643	for _, os := range OsTypeList {
644		if os.Name == name {
645			return os
646		}
647	}
648
649	return NoOsType
650}
651
652type NativeBridgeSupport bool
653
654const (
655	NativeBridgeDisabled NativeBridgeSupport = false
656	NativeBridgeEnabled  NativeBridgeSupport = true
657)
658
659type Target struct {
660	Os                       OsType
661	Arch                     Arch
662	NativeBridge             NativeBridgeSupport
663	NativeBridgeHostArchName string
664	NativeBridgeRelativePath string
665}
666
667func (target Target) String() string {
668	return target.OsVariation() + "_" + target.ArchVariation()
669}
670
671func (target Target) OsVariation() string {
672	return target.Os.String()
673}
674
675func (target Target) ArchVariation() string {
676	var variation string
677	if target.NativeBridge {
678		variation = "native_bridge_"
679	}
680	variation += target.Arch.String()
681
682	return variation
683}
684
685func (target Target) Variations() []blueprint.Variation {
686	return []blueprint.Variation{
687		{Mutator: "os", Variation: target.OsVariation()},
688		{Mutator: "arch", Variation: target.ArchVariation()},
689	}
690}
691
692func osMutator(mctx BottomUpMutatorContext) {
693	var module Module
694	var ok bool
695	if module, ok = mctx.Module().(Module); !ok {
696		return
697	}
698
699	base := module.base()
700
701	if !base.ArchSpecific() {
702		return
703	}
704
705	osClasses := base.OsClassSupported()
706
707	var moduleOSList []OsType
708
709	for _, os := range OsTypeList {
710		supportedClass := false
711		for _, osClass := range osClasses {
712			if os.Class == osClass {
713				supportedClass = true
714			}
715		}
716		if !supportedClass {
717			continue
718		}
719
720		if len(mctx.Config().Targets[os]) == 0 {
721			continue
722		}
723
724		moduleOSList = append(moduleOSList, os)
725	}
726
727	if len(moduleOSList) == 0 {
728		base.Disable()
729		return
730	}
731
732	osNames := make([]string, len(moduleOSList))
733
734	for i, os := range moduleOSList {
735		osNames[i] = os.String()
736	}
737
738	createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
739	if createCommonOSVariant {
740		// A CommonOS variant was requested so add it to the list of OS's variants to
741		// create. It needs to be added to the end because it needs to depend on the
742		// the other variants in the list returned by CreateVariations(...) and inter
743		// variant dependencies can only be created from a later variant in that list to
744		// an earlier one. That is because variants are always processed in the order in
745		// which they are returned from CreateVariations(...).
746		osNames = append(osNames, CommonOS.Name)
747		moduleOSList = append(moduleOSList, CommonOS)
748	}
749
750	modules := mctx.CreateVariations(osNames...)
751	for i, m := range modules {
752		m.base().commonProperties.CompileOS = moduleOSList[i]
753		m.base().setOSProperties(mctx)
754	}
755
756	if createCommonOSVariant {
757		// A CommonOS variant was requested so add dependencies from it (the last one in
758		// the list) to the OS type specific variants.
759		last := len(modules) - 1
760		commonOSVariant := modules[last]
761		commonOSVariant.base().commonProperties.CommonOSVariant = true
762		for _, module := range modules[0:last] {
763			// Ignore modules that are enabled. Note, this will only avoid adding
764			// dependencies on OsType variants that are explicitly disabled in their
765			// properties. The CommonOS variant will still depend on disabled variants
766			// if they are disabled afterwards, e.g. in archMutator if
767			if module.Enabled() {
768				mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
769			}
770		}
771	}
772}
773
774// Identifies the dependency from CommonOS variant to the os specific variants.
775type commonOSTag struct{ blueprint.BaseDependencyTag }
776
777var commonOsToOsSpecificVariantTag = commonOSTag{}
778
779// Get the OsType specific variants for the current CommonOS variant.
780//
781// The returned list will only contain enabled OsType specific variants of the
782// module referenced in the supplied context. An empty list is returned if there
783// are no enabled variants or the supplied context is not for an CommonOS
784// variant.
785func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module {
786	var variants []Module
787	mctx.VisitDirectDeps(func(m Module) {
788		if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag {
789			if m.Enabled() {
790				variants = append(variants, m)
791			}
792		}
793	})
794
795	return variants
796}
797
798// archMutator splits a module into a variant for each Target requested by the module.  Target selection
799// for a module is in three levels, OsClass, mulitlib, and then Target.
800// OsClass selection is determined by:
801//    - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
802//      whether the module type can compile for host, device or both.
803//    - The host_supported and device_supported properties on the module.
804// If host is supported for the module, the Host and HostCross OsClasses are selected.  If device is supported
805// for the module, the Device OsClass is selected.
806// Within each selected OsClass, the multilib selection is determined by:
807//    - The compile_multilib property if it set (which may be overridden by target.android.compile_multilib or
808//      target.host.compile_multilib).
809//    - The default multilib passed to InitAndroidArchModule if compile_multilib was not set.
810// Valid multilib values include:
811//    "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm).
812//    "first": compile for only a single preferred Target supported by the OsClass.  This is generally x86_64 or arm64,
813//        but may be arm for a 32-bit only build.
814//    "32": compile for only a single 32-bit Target supported by the OsClass.
815//    "64": compile for only a single 64-bit Target supported by the OsClass.
816//    "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java).
817//
818// Once the list of Targets is determined, the module is split into a variant for each Target.
819//
820// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
821// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
822func archMutator(mctx BottomUpMutatorContext) {
823	var module Module
824	var ok bool
825	if module, ok = mctx.Module().(Module); !ok {
826		return
827	}
828
829	base := module.base()
830
831	if !base.ArchSpecific() {
832		return
833	}
834
835	os := base.commonProperties.CompileOS
836	if os == CommonOS {
837		// Make sure that the target related properties are initialized for the
838		// CommonOS variant.
839		addTargetProperties(module, commonTargetMap[os.Name], nil, true)
840
841		// Do not create arch specific variants for the CommonOS variant.
842		return
843	}
844
845	osTargets := mctx.Config().Targets[os]
846	image := base.commonProperties.ImageVariation
847	// Filter NativeBridge targets unless they are explicitly supported
848	// Skip creating native bridge variants for vendor modules
849	if os == Android &&
850		!(Bool(base.commonProperties.Native_bridge_supported) && image == CoreVariation) {
851
852		var targets []Target
853		for _, t := range osTargets {
854			if !t.NativeBridge {
855				targets = append(targets, t)
856			}
857		}
858
859		osTargets = targets
860	}
861
862	// only the primary arch in the ramdisk / recovery partition
863	if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk()) {
864		osTargets = []Target{osTargets[0]}
865	}
866
867	prefer32 := false
868	if base.prefer32 != nil {
869		prefer32 = base.prefer32(mctx, base, os.Class)
870	}
871
872	multilib, extraMultilib := decodeMultilib(base, os.Class)
873	targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
874	if err != nil {
875		mctx.ModuleErrorf("%s", err.Error())
876	}
877
878	var multiTargets []Target
879	if extraMultilib != "" {
880		multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
881		if err != nil {
882			mctx.ModuleErrorf("%s", err.Error())
883		}
884	}
885
886	if image == RecoveryVariation {
887		primaryArch := mctx.Config().DevicePrimaryArchType()
888		targets = filterToArch(targets, primaryArch)
889		multiTargets = filterToArch(multiTargets, primaryArch)
890	}
891
892	if len(targets) == 0 {
893		base.Disable()
894		return
895	}
896
897	targetNames := make([]string, len(targets))
898
899	for i, target := range targets {
900		targetNames[i] = target.ArchVariation()
901	}
902
903	modules := mctx.CreateVariations(targetNames...)
904	for i, m := range modules {
905		addTargetProperties(m, targets[i], multiTargets, i == 0)
906		m.(Module).base().setArchProperties(mctx)
907	}
908}
909
910func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
911	m.base().commonProperties.CompileTarget = target
912	m.base().commonProperties.CompileMultiTargets = multiTargets
913	m.base().commonProperties.CompilePrimary = primaryTarget
914}
915
916func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
917	switch class {
918	case Device:
919		multilib = String(base.commonProperties.Target.Android.Compile_multilib)
920	case Host, HostCross:
921		multilib = String(base.commonProperties.Target.Host.Compile_multilib)
922	}
923	if multilib == "" {
924		multilib = String(base.commonProperties.Compile_multilib)
925	}
926	if multilib == "" {
927		multilib = base.commonProperties.Default_multilib
928	}
929
930	if base.commonProperties.UseTargetVariants {
931		return multilib, ""
932	} else {
933		// For app modules a single arch variant will be created per OS class which is expected to handle all the
934		// selected arches.  Return the common-type as multilib and any Android.bp provided multilib as extraMultilib
935		if multilib == base.commonProperties.Default_multilib {
936			multilib = "first"
937		}
938		return base.commonProperties.Default_multilib, multilib
939	}
940}
941
942func filterToArch(targets []Target, arch ArchType) []Target {
943	for i := 0; i < len(targets); i++ {
944		if targets[i].Arch.ArchType != arch {
945			targets = append(targets[:i], targets[i+1:]...)
946			i--
947		}
948	}
949	return targets
950}
951
952type archPropTypeDesc struct {
953	arch, multilib, target reflect.Type
954}
955
956type archPropRoot struct {
957	Arch, Multilib, Target interface{}
958}
959
960// createArchPropTypeDesc takes a reflect.Type that is either a struct or a pointer to a struct, and
961// returns lists of reflect.Types that contains the arch-variant properties inside structs for each
962// arch, multilib and target property.
963func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc {
964	// Each property struct shard will be nested many times under the runtime generated arch struct,
965	// which can hit the limit of 64kB for the name of runtime generated structs.  They are nested
966	// 97 times now, which may grow in the future, plus there is some overhead for the containing
967	// type.  This number may need to be reduced if too many are added, but reducing it too far
968	// could cause problems if a single deeply nested property no longer fits in the name.
969	const maxArchTypeNameSize = 500
970
971	propShards, _ := proptools.FilterPropertyStructSharded(props, maxArchTypeNameSize, filterArchStruct)
972	if len(propShards) == 0 {
973		return nil
974	}
975
976	var ret []archPropTypeDesc
977	for _, props := range propShards {
978
979		variantFields := func(names []string) []reflect.StructField {
980			ret := make([]reflect.StructField, len(names))
981
982			for i, name := range names {
983				ret[i].Name = name
984				ret[i].Type = props
985			}
986
987			return ret
988		}
989
990		archFields := make([]reflect.StructField, len(archTypeList))
991		for i, arch := range archTypeList {
992			variants := []string{}
993
994			for _, archVariant := range archVariants[arch] {
995				archVariant := variantReplacer.Replace(archVariant)
996				variants = append(variants, proptools.FieldNameForProperty(archVariant))
997			}
998			for _, feature := range archFeatures[arch] {
999				feature := variantReplacer.Replace(feature)
1000				variants = append(variants, proptools.FieldNameForProperty(feature))
1001			}
1002
1003			fields := variantFields(variants)
1004
1005			fields = append([]reflect.StructField{{
1006				Name:      "BlueprintEmbed",
1007				Type:      props,
1008				Anonymous: true,
1009			}}, fields...)
1010
1011			archFields[i] = reflect.StructField{
1012				Name: arch.Field,
1013				Type: reflect.StructOf(fields),
1014			}
1015		}
1016		archType := reflect.StructOf(archFields)
1017
1018		multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"}))
1019
1020		targets := []string{
1021			"Host",
1022			"Android64",
1023			"Android32",
1024			"Bionic",
1025			"Linux",
1026			"Not_windows",
1027			"Arm_on_x86",
1028			"Arm_on_x86_64",
1029			"Native_bridge",
1030		}
1031		for _, os := range OsTypeList {
1032			targets = append(targets, os.Field)
1033
1034			for _, archType := range osArchTypeMap[os] {
1035				targets = append(targets, os.Field+"_"+archType.Name)
1036
1037				if os.Linux() {
1038					target := "Linux_" + archType.Name
1039					if !InList(target, targets) {
1040						targets = append(targets, target)
1041					}
1042				}
1043				if os.Bionic() {
1044					target := "Bionic_" + archType.Name
1045					if !InList(target, targets) {
1046						targets = append(targets, target)
1047					}
1048				}
1049			}
1050		}
1051
1052		targetType := reflect.StructOf(variantFields(targets))
1053
1054		ret = append(ret, archPropTypeDesc{
1055			arch:     reflect.PtrTo(archType),
1056			multilib: reflect.PtrTo(multilibType),
1057			target:   reflect.PtrTo(targetType),
1058		})
1059	}
1060	return ret
1061}
1062
1063func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.StructField) {
1064	if proptools.HasTag(field, "android", "arch_variant") {
1065		// The arch_variant field isn't necessary past this point
1066		// Instead of wasting space, just remove it. Go also has a
1067		// 16-bit limit on structure name length. The name is constructed
1068		// based on the Go source representation of the structure, so
1069		// the tag names count towards that length.
1070
1071		androidTag := field.Tag.Get("android")
1072		values := strings.Split(androidTag, ",")
1073
1074		if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` {
1075			panic(fmt.Errorf("unexpected tag format %q", field.Tag))
1076		}
1077		// these tags don't need to be present in the runtime generated struct type.
1078		values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
1079		if len(values) > 0 {
1080			panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
1081		}
1082
1083		field.Tag = ""
1084		return true, field
1085	}
1086	return false, field
1087}
1088
1089var archPropTypeMap OncePer
1090
1091func InitArchModule(m Module) {
1092
1093	base := m.base()
1094
1095	base.generalProperties = m.GetProperties()
1096
1097	for _, properties := range base.generalProperties {
1098		propertiesValue := reflect.ValueOf(properties)
1099		t := propertiesValue.Type()
1100		if propertiesValue.Kind() != reflect.Ptr {
1101			panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
1102				propertiesValue.Interface()))
1103		}
1104
1105		propertiesValue = propertiesValue.Elem()
1106		if propertiesValue.Kind() != reflect.Struct {
1107			panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
1108				propertiesValue.Interface()))
1109		}
1110
1111		archPropTypes := archPropTypeMap.Once(NewCustomOnceKey(t), func() interface{} {
1112			return createArchPropTypeDesc(t)
1113		}).([]archPropTypeDesc)
1114
1115		var archProperties []interface{}
1116		for _, t := range archPropTypes {
1117			archProperties = append(archProperties, &archPropRoot{
1118				Arch:     reflect.Zero(t.arch).Interface(),
1119				Multilib: reflect.Zero(t.multilib).Interface(),
1120				Target:   reflect.Zero(t.target).Interface(),
1121			})
1122		}
1123		base.archProperties = append(base.archProperties, archProperties)
1124		m.AddProperties(archProperties...)
1125	}
1126
1127	base.customizableProperties = m.GetProperties()
1128}
1129
1130var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
1131
1132func (m *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
1133	dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value {
1134
1135	if src.Kind() == reflect.Ptr {
1136		if src.IsNil() {
1137			return src
1138		}
1139		src = src.Elem()
1140	}
1141
1142	src = src.FieldByName(field)
1143	if !src.IsValid() {
1144		ctx.ModuleErrorf("field %q does not exist", srcPrefix)
1145		return src
1146	}
1147
1148	ret := src
1149
1150	if src.Kind() == reflect.Struct {
1151		src = src.FieldByName("BlueprintEmbed")
1152	}
1153
1154	order := func(property string,
1155		dstField, srcField reflect.StructField,
1156		dstValue, srcValue interface{}) (proptools.Order, error) {
1157		if proptools.HasTag(dstField, "android", "variant_prepend") {
1158			return proptools.Prepend, nil
1159		} else {
1160			return proptools.Append, nil
1161		}
1162	}
1163
1164	err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, order)
1165	if err != nil {
1166		if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
1167			ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
1168		} else {
1169			panic(err)
1170		}
1171	}
1172
1173	return ret
1174}
1175
1176// Rewrite the module's properties structs to contain os-specific values.
1177func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) {
1178	os := m.commonProperties.CompileOS
1179
1180	for i := range m.generalProperties {
1181		genProps := m.generalProperties[i]
1182		if m.archProperties[i] == nil {
1183			continue
1184		}
1185		for _, archProperties := range m.archProperties[i] {
1186			archPropValues := reflect.ValueOf(archProperties).Elem()
1187
1188			targetProp := archPropValues.FieldByName("Target").Elem()
1189
1190			// Handle host-specific properties in the form:
1191			// target: {
1192			//     host: {
1193			//         key: value,
1194			//     },
1195			// },
1196			if os.Class == Host || os.Class == HostCross {
1197				field := "Host"
1198				prefix := "target.host"
1199				m.appendProperties(ctx, genProps, targetProp, field, prefix)
1200			}
1201
1202			// Handle target OS generalities of the form:
1203			// target: {
1204			//     bionic: {
1205			//         key: value,
1206			//     },
1207			// }
1208			if os.Linux() {
1209				field := "Linux"
1210				prefix := "target.linux"
1211				m.appendProperties(ctx, genProps, targetProp, field, prefix)
1212			}
1213
1214			if os.Bionic() {
1215				field := "Bionic"
1216				prefix := "target.bionic"
1217				m.appendProperties(ctx, genProps, targetProp, field, prefix)
1218			}
1219
1220			// Handle target OS properties in the form:
1221			// target: {
1222			//     linux_glibc: {
1223			//         key: value,
1224			//     },
1225			//     not_windows: {
1226			//         key: value,
1227			//     },
1228			//     android {
1229			//         key: value,
1230			//     },
1231			// },
1232			field := os.Field
1233			prefix := "target." + os.Name
1234			m.appendProperties(ctx, genProps, targetProp, field, prefix)
1235
1236			if (os.Class == Host || os.Class == HostCross) && os != Windows {
1237				field := "Not_windows"
1238				prefix := "target.not_windows"
1239				m.appendProperties(ctx, genProps, targetProp, field, prefix)
1240			}
1241
1242			// Handle 64-bit device properties in the form:
1243			// target {
1244			//     android64 {
1245			//         key: value,
1246			//     },
1247			//     android32 {
1248			//         key: value,
1249			//     },
1250			// },
1251			// WARNING: this is probably not what you want to use in your blueprints file, it selects
1252			// options for all targets on a device that supports 64-bit binaries, not just the targets
1253			// that are being compiled for 64-bit.  Its expected use case is binaries like linker and
1254			// debuggerd that need to know when they are a 32-bit process running on a 64-bit device
1255			if os.Class == Device {
1256				if ctx.Config().Android64() {
1257					field := "Android64"
1258					prefix := "target.android64"
1259					m.appendProperties(ctx, genProps, targetProp, field, prefix)
1260				} else {
1261					field := "Android32"
1262					prefix := "target.android32"
1263					m.appendProperties(ctx, genProps, targetProp, field, prefix)
1264				}
1265			}
1266		}
1267	}
1268}
1269
1270// Rewrite the module's properties structs to contain arch-specific values.
1271func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
1272	arch := m.Arch()
1273	os := m.Os()
1274
1275	for i := range m.generalProperties {
1276		genProps := m.generalProperties[i]
1277		if m.archProperties[i] == nil {
1278			continue
1279		}
1280		for _, archProperties := range m.archProperties[i] {
1281			archPropValues := reflect.ValueOf(archProperties).Elem()
1282
1283			archProp := archPropValues.FieldByName("Arch").Elem()
1284			multilibProp := archPropValues.FieldByName("Multilib").Elem()
1285			targetProp := archPropValues.FieldByName("Target").Elem()
1286
1287			// Handle arch-specific properties in the form:
1288			// arch: {
1289			//     arm64: {
1290			//         key: value,
1291			//     },
1292			// },
1293			t := arch.ArchType
1294
1295			if arch.ArchType != Common {
1296				field := proptools.FieldNameForProperty(t.Name)
1297				prefix := "arch." + t.Name
1298				archStruct := m.appendProperties(ctx, genProps, archProp, field, prefix)
1299
1300				// Handle arch-variant-specific properties in the form:
1301				// arch: {
1302				//     variant: {
1303				//         key: value,
1304				//     },
1305				// },
1306				v := variantReplacer.Replace(arch.ArchVariant)
1307				if v != "" {
1308					field := proptools.FieldNameForProperty(v)
1309					prefix := "arch." + t.Name + "." + v
1310					m.appendProperties(ctx, genProps, archStruct, field, prefix)
1311				}
1312
1313				// Handle cpu-variant-specific properties in the form:
1314				// arch: {
1315				//     variant: {
1316				//         key: value,
1317				//     },
1318				// },
1319				if arch.CpuVariant != arch.ArchVariant {
1320					c := variantReplacer.Replace(arch.CpuVariant)
1321					if c != "" {
1322						field := proptools.FieldNameForProperty(c)
1323						prefix := "arch." + t.Name + "." + c
1324						m.appendProperties(ctx, genProps, archStruct, field, prefix)
1325					}
1326				}
1327
1328				// Handle arch-feature-specific properties in the form:
1329				// arch: {
1330				//     feature: {
1331				//         key: value,
1332				//     },
1333				// },
1334				for _, feature := range arch.ArchFeatures {
1335					field := proptools.FieldNameForProperty(feature)
1336					prefix := "arch." + t.Name + "." + feature
1337					m.appendProperties(ctx, genProps, archStruct, field, prefix)
1338				}
1339
1340				// Handle multilib-specific properties in the form:
1341				// multilib: {
1342				//     lib32: {
1343				//         key: value,
1344				//     },
1345				// },
1346				field = proptools.FieldNameForProperty(t.Multilib)
1347				prefix = "multilib." + t.Multilib
1348				m.appendProperties(ctx, genProps, multilibProp, field, prefix)
1349			}
1350
1351			// Handle combined OS-feature and arch specific properties in the form:
1352			// target: {
1353			//     bionic_x86: {
1354			//         key: value,
1355			//     },
1356			// }
1357			if os.Linux() && arch.ArchType != Common {
1358				field := "Linux_" + arch.ArchType.Name
1359				prefix := "target.linux_" + arch.ArchType.Name
1360				m.appendProperties(ctx, genProps, targetProp, field, prefix)
1361			}
1362
1363			if os.Bionic() && arch.ArchType != Common {
1364				field := "Bionic_" + t.Name
1365				prefix := "target.bionic_" + t.Name
1366				m.appendProperties(ctx, genProps, targetProp, field, prefix)
1367			}
1368
1369			// Handle combined OS and arch specific properties in the form:
1370			// target: {
1371			//     linux_glibc_x86: {
1372			//         key: value,
1373			//     },
1374			//     linux_glibc_arm: {
1375			//         key: value,
1376			//     },
1377			//     android_arm {
1378			//         key: value,
1379			//     },
1380			//     android_x86 {
1381			//         key: value,
1382			//     },
1383			// },
1384			if arch.ArchType != Common {
1385				field := os.Field + "_" + t.Name
1386				prefix := "target." + os.Name + "_" + t.Name
1387				m.appendProperties(ctx, genProps, targetProp, field, prefix)
1388			}
1389
1390			// Handle arm on x86 properties in the form:
1391			// target {
1392			//     arm_on_x86 {
1393			//         key: value,
1394			//     },
1395			//     arm_on_x86_64 {
1396			//         key: value,
1397			//     },
1398			// },
1399			// TODO(ccross): is this still necessary with native bridge?
1400			if os.Class == Device {
1401				if (arch.ArchType == X86 && (hasArmAbi(arch) ||
1402					hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
1403					(arch.ArchType == Arm &&
1404						hasX86AndroidArch(ctx.Config().Targets[Android])) {
1405					field := "Arm_on_x86"
1406					prefix := "target.arm_on_x86"
1407					m.appendProperties(ctx, genProps, targetProp, field, prefix)
1408				}
1409				if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
1410					hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
1411					(arch.ArchType == Arm &&
1412						hasX8664AndroidArch(ctx.Config().Targets[Android])) {
1413					field := "Arm_on_x86_64"
1414					prefix := "target.arm_on_x86_64"
1415					m.appendProperties(ctx, genProps, targetProp, field, prefix)
1416				}
1417				if os == Android && m.Target().NativeBridge == NativeBridgeEnabled {
1418					field := "Native_bridge"
1419					prefix := "target.native_bridge"
1420					m.appendProperties(ctx, genProps, targetProp, field, prefix)
1421				}
1422			}
1423		}
1424	}
1425}
1426
1427func forEachInterface(v reflect.Value, f func(reflect.Value)) {
1428	switch v.Kind() {
1429	case reflect.Interface:
1430		f(v)
1431	case reflect.Struct:
1432		for i := 0; i < v.NumField(); i++ {
1433			forEachInterface(v.Field(i), f)
1434		}
1435	case reflect.Ptr:
1436		forEachInterface(v.Elem(), f)
1437	default:
1438		panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
1439	}
1440}
1441
1442// Convert the arch product variables into a list of targets for each os class structs
1443func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
1444	variables := config.productVariables
1445
1446	targets := make(map[OsType][]Target)
1447	var targetErr error
1448
1449	addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string,
1450		nativeBridgeEnabled NativeBridgeSupport, nativeBridgeHostArchName *string,
1451		nativeBridgeRelativePath *string) {
1452		if targetErr != nil {
1453			return
1454		}
1455
1456		arch, err := decodeArch(os, archName, archVariant, cpuVariant, abi)
1457		if err != nil {
1458			targetErr = err
1459			return
1460		}
1461		nativeBridgeRelativePathStr := String(nativeBridgeRelativePath)
1462		nativeBridgeHostArchNameStr := String(nativeBridgeHostArchName)
1463
1464		// Use guest arch as relative install path by default
1465		if nativeBridgeEnabled && nativeBridgeRelativePathStr == "" {
1466			nativeBridgeRelativePathStr = arch.ArchType.String()
1467		}
1468
1469		targets[os] = append(targets[os],
1470			Target{
1471				Os:                       os,
1472				Arch:                     arch,
1473				NativeBridge:             nativeBridgeEnabled,
1474				NativeBridgeHostArchName: nativeBridgeHostArchNameStr,
1475				NativeBridgeRelativePath: nativeBridgeRelativePathStr,
1476			})
1477	}
1478
1479	if variables.HostArch == nil {
1480		return nil, fmt.Errorf("No host primary architecture set")
1481	}
1482
1483	addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
1484
1485	if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
1486		addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
1487	}
1488
1489	if Bool(config.Host_bionic) {
1490		addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
1491	}
1492
1493	if String(variables.CrossHost) != "" {
1494		crossHostOs := osByName(*variables.CrossHost)
1495		if crossHostOs == NoOsType {
1496			return nil, fmt.Errorf("Unknown cross host OS %q", *variables.CrossHost)
1497		}
1498
1499		if String(variables.CrossHostArch) == "" {
1500			return nil, fmt.Errorf("No cross-host primary architecture set")
1501		}
1502
1503		addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
1504
1505		if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
1506			addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
1507		}
1508	}
1509
1510	if variables.DeviceArch != nil && *variables.DeviceArch != "" {
1511		var target = Android
1512		if Bool(variables.Fuchsia) {
1513			target = Fuchsia
1514		}
1515
1516		addTarget(target, *variables.DeviceArch, variables.DeviceArchVariant,
1517			variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled, nil, nil)
1518
1519		if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
1520			addTarget(Android, *variables.DeviceSecondaryArch,
1521				variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
1522				variables.DeviceSecondaryAbi, NativeBridgeDisabled, nil, nil)
1523		}
1524
1525		if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" {
1526			addTarget(Android, *variables.NativeBridgeArch,
1527				variables.NativeBridgeArchVariant, variables.NativeBridgeCpuVariant,
1528				variables.NativeBridgeAbi, NativeBridgeEnabled, variables.DeviceArch,
1529				variables.NativeBridgeRelativePath)
1530		}
1531
1532		if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" &&
1533			variables.NativeBridgeSecondaryArch != nil && *variables.NativeBridgeSecondaryArch != "" {
1534			addTarget(Android, *variables.NativeBridgeSecondaryArch,
1535				variables.NativeBridgeSecondaryArchVariant,
1536				variables.NativeBridgeSecondaryCpuVariant,
1537				variables.NativeBridgeSecondaryAbi,
1538				NativeBridgeEnabled,
1539				variables.DeviceSecondaryArch,
1540				variables.NativeBridgeSecondaryRelativePath)
1541		}
1542	}
1543
1544	if targetErr != nil {
1545		return nil, targetErr
1546	}
1547
1548	return targets, nil
1549}
1550
1551// hasArmAbi returns true if arch has at least one arm ABI
1552func hasArmAbi(arch Arch) bool {
1553	return PrefixInList(arch.Abi, "arm")
1554}
1555
1556// hasArmArch returns true if targets has at least non-native_bridge arm Android arch
1557func hasArmAndroidArch(targets []Target) bool {
1558	for _, target := range targets {
1559		if target.Os == Android && target.Arch.ArchType == Arm && target.NativeBridge == NativeBridgeDisabled {
1560			return true
1561		}
1562	}
1563	return false
1564}
1565
1566// hasX86Arch returns true if targets has at least x86 Android arch
1567func hasX86AndroidArch(targets []Target) bool {
1568	for _, target := range targets {
1569		if target.Os == Android && target.Arch.ArchType == X86 {
1570			return true
1571		}
1572	}
1573	return false
1574}
1575
1576// hasX8664Arch returns true if targets has at least x86_64 Android arch
1577func hasX8664AndroidArch(targets []Target) bool {
1578	for _, target := range targets {
1579		if target.Os == Android && target.Arch.ArchType == X86_64 {
1580			return true
1581		}
1582	}
1583	return false
1584}
1585
1586type archConfig struct {
1587	arch        string
1588	archVariant string
1589	cpuVariant  string
1590	abi         []string
1591}
1592
1593func getMegaDeviceConfig() []archConfig {
1594	return []archConfig{
1595		{"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
1596		{"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}},
1597		{"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
1598		{"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
1599		{"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}},
1600		{"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}},
1601		{"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}},
1602		{"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}},
1603		{"arm", "armv7-a-neon", "cortex-a72", []string{"armeabi-v7a"}},
1604		{"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}},
1605		{"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}},
1606		{"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
1607		{"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
1608		{"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
1609		{"arm", "armv7-a-neon", "kryo385", []string{"armeabi-v7a"}},
1610		{"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}},
1611		{"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}},
1612		{"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
1613		{"arm64", "armv8-a", "cortex-a72", []string{"arm64-v8a"}},
1614		{"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}},
1615		{"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}},
1616		{"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}},
1617		{"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
1618		{"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
1619		{"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
1620		{"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}},
1621		{"x86", "", "", []string{"x86"}},
1622		{"x86", "atom", "", []string{"x86"}},
1623		{"x86", "haswell", "", []string{"x86"}},
1624		{"x86", "ivybridge", "", []string{"x86"}},
1625		{"x86", "sandybridge", "", []string{"x86"}},
1626		{"x86", "silvermont", "", []string{"x86"}},
1627		{"x86", "stoneyridge", "", []string{"x86"}},
1628		{"x86", "x86_64", "", []string{"x86"}},
1629		{"x86_64", "", "", []string{"x86_64"}},
1630		{"x86_64", "haswell", "", []string{"x86_64"}},
1631		{"x86_64", "ivybridge", "", []string{"x86_64"}},
1632		{"x86_64", "sandybridge", "", []string{"x86_64"}},
1633		{"x86_64", "silvermont", "", []string{"x86_64"}},
1634		{"x86_64", "stoneyridge", "", []string{"x86_64"}},
1635	}
1636}
1637
1638func getNdkAbisConfig() []archConfig {
1639	return []archConfig{
1640		{"arm", "armv7-a", "", []string{"armeabi-v7a"}},
1641		{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
1642		{"x86", "", "", []string{"x86"}},
1643		{"x86_64", "", "", []string{"x86_64"}},
1644	}
1645}
1646
1647func getAmlAbisConfig() []archConfig {
1648	return []archConfig{
1649		{"arm", "armv7-a", "", []string{"armeabi-v7a"}},
1650		{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
1651		{"x86", "", "", []string{"x86"}},
1652		{"x86_64", "", "", []string{"x86_64"}},
1653	}
1654}
1655
1656func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) {
1657	var ret []Target
1658
1659	for _, config := range archConfigs {
1660		arch, err := decodeArch(os, config.arch, &config.archVariant,
1661			&config.cpuVariant, config.abi)
1662		if err != nil {
1663			return nil, err
1664		}
1665
1666		ret = append(ret, Target{
1667			Os:   Android,
1668			Arch: arch,
1669		})
1670	}
1671
1672	return ret, nil
1673}
1674
1675// Convert a set of strings from product variables into a single Arch struct
1676func decodeArch(os OsType, arch string, archVariant, cpuVariant *string, abi []string) (Arch, error) {
1677	stringPtr := func(p *string) string {
1678		if p != nil {
1679			return *p
1680		}
1681		return ""
1682	}
1683
1684	archType, ok := archTypeMap[arch]
1685	if !ok {
1686		return Arch{}, fmt.Errorf("unknown arch %q", arch)
1687	}
1688
1689	a := Arch{
1690		ArchType:    archType,
1691		ArchVariant: stringPtr(archVariant),
1692		CpuVariant:  stringPtr(cpuVariant),
1693		Abi:         abi,
1694	}
1695
1696	if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
1697		a.ArchVariant = ""
1698	}
1699
1700	if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
1701		a.CpuVariant = ""
1702	}
1703
1704	for i := 0; i < len(a.Abi); i++ {
1705		if a.Abi[i] == "" {
1706			a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
1707			i--
1708		}
1709	}
1710
1711	if a.ArchVariant == "" {
1712		if featureMap, ok := defaultArchFeatureMap[os]; ok {
1713			a.ArchFeatures = featureMap[archType]
1714		}
1715	} else {
1716		if featureMap, ok := archFeatureMap[archType]; ok {
1717			a.ArchFeatures = featureMap[a.ArchVariant]
1718		}
1719	}
1720
1721	return a, nil
1722}
1723
1724func filterMultilibTargets(targets []Target, multilib string) []Target {
1725	var ret []Target
1726	for _, t := range targets {
1727		if t.Arch.ArchType.Multilib == multilib {
1728			ret = append(ret, t)
1729		}
1730	}
1731	return ret
1732}
1733
1734// Return the set of Os specific common architecture targets for each Os in a list of
1735// targets.
1736func getCommonTargets(targets []Target) []Target {
1737	var ret []Target
1738	set := make(map[string]bool)
1739
1740	for _, t := range targets {
1741		if _, found := set[t.Os.String()]; !found {
1742			set[t.Os.String()] = true
1743			ret = append(ret, commonTargetMap[t.Os.String()])
1744		}
1745	}
1746
1747	return ret
1748}
1749
1750func firstTarget(targets []Target, filters ...string) []Target {
1751	for _, filter := range filters {
1752		buildTargets := filterMultilibTargets(targets, filter)
1753		if len(buildTargets) > 0 {
1754			return buildTargets[:1]
1755		}
1756	}
1757	return nil
1758}
1759
1760// Use the module multilib setting to select one or more targets from a target list
1761func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
1762	buildTargets := []Target{}
1763
1764	switch multilib {
1765	case "common":
1766		buildTargets = getCommonTargets(targets)
1767	case "common_first":
1768		buildTargets = getCommonTargets(targets)
1769		if prefer32 {
1770			buildTargets = append(buildTargets, firstTarget(targets, "lib32", "lib64")...)
1771		} else {
1772			buildTargets = append(buildTargets, firstTarget(targets, "lib64", "lib32")...)
1773		}
1774	case "both":
1775		if prefer32 {
1776			buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
1777			buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
1778		} else {
1779			buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
1780			buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
1781		}
1782	case "32":
1783		buildTargets = filterMultilibTargets(targets, "lib32")
1784	case "64":
1785		buildTargets = filterMultilibTargets(targets, "lib64")
1786	case "first":
1787		if prefer32 {
1788			buildTargets = firstTarget(targets, "lib32", "lib64")
1789		} else {
1790			buildTargets = firstTarget(targets, "lib64", "lib32")
1791		}
1792	case "prefer32":
1793		buildTargets = filterMultilibTargets(targets, "lib32")
1794		if len(buildTargets) == 0 {
1795			buildTargets = filterMultilibTargets(targets, "lib64")
1796		}
1797	default:
1798		return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", or "prefer32" found %q`,
1799			multilib)
1800	}
1801
1802	return buildTargets, nil
1803}
1804