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