blob: 7fe1b18b1470dbcdb3ee314744f29009114e2a4c [file] [log] [blame]
Colin Cross3f40fa42015-01-30 17:27:36 -08001// 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
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Colin Cross3f40fa42015-01-30 17:27:36 -080016
17import (
Colin Cross3f40fa42015-01-30 17:27:36 -080018 "fmt"
19 "reflect"
20 "runtime"
21 "strings"
Colin Crossf6566ed2015-03-24 11:13:38 -070022
Colin Crossf6566ed2015-03-24 11:13:38 -070023 "github.com/google/blueprint/proptools"
Colin Cross3f40fa42015-01-30 17:27:36 -080024)
25
26var (
Dan Willemsenb1957a52016-06-23 23:44:54 -070027 archTypeList []ArchType
28
Colin Crossec193632015-07-06 17:49:43 -070029 Arm = newArch("arm", "lib32")
30 Arm64 = newArch("arm64", "lib64")
31 Mips = newArch("mips", "lib32")
32 Mips64 = newArch("mips64", "lib64")
33 X86 = newArch("x86", "lib32")
34 X86_64 = newArch("x86_64", "lib64")
Colin Cross2fe66872015-03-30 17:20:39 -070035
36 Common = ArchType{
37 Name: "common",
38 }
Colin Cross3f40fa42015-01-30 17:27:36 -080039)
40
Colin Cross4225f652015-09-17 14:33:42 -070041var archTypeMap = map[string]ArchType{
42 "arm": Arm,
43 "arm64": Arm64,
44 "mips": Mips,
Colin Cross3b336c22015-11-23 16:28:31 -080045 "mips64": Mips64,
Colin Cross4225f652015-09-17 14:33:42 -070046 "x86": X86,
47 "x86_64": X86_64,
48}
49
Colin Cross3f40fa42015-01-30 17:27:36 -080050/*
51Example blueprints file containing all variant property groups, with comment listing what type
52of variants get properties in that group:
53
54module {
55 arch: {
56 arm: {
57 // Host or device variants with arm architecture
58 },
59 arm64: {
60 // Host or device variants with arm64 architecture
61 },
62 mips: {
63 // Host or device variants with mips architecture
64 },
65 mips64: {
66 // Host or device variants with mips64 architecture
67 },
68 x86: {
69 // Host or device variants with x86 architecture
70 },
71 x86_64: {
72 // Host or device variants with x86_64 architecture
73 },
74 },
75 multilib: {
76 lib32: {
77 // Host or device variants for 32-bit architectures
78 },
79 lib64: {
80 // Host or device variants for 64-bit architectures
81 },
82 },
83 target: {
84 android: {
85 // Device variants
86 },
87 host: {
88 // Host variants
89 },
Dan Willemsen5746bd42017-10-02 19:42:01 -070090 linux_glibc: {
Colin Cross3f40fa42015-01-30 17:27:36 -080091 // Linux host variants
92 },
93 darwin: {
94 // Darwin host variants
95 },
96 windows: {
97 // Windows host variants
98 },
99 not_windows: {
100 // Non-windows host variants
101 },
102 },
103}
104*/
Colin Cross7d5136f2015-05-11 13:39:40 -0700105
Dan Willemsenb1957a52016-06-23 23:44:54 -0700106var archVariants = map[ArchType][]string{}
107var archFeatures = map[ArchType][]string{}
Colin Crossc5c24ad2015-11-20 15:35:00 -0800108var archFeatureMap = map[ArchType]map[string][]string{}
109
Dan Willemsenb1957a52016-06-23 23:44:54 -0700110func RegisterArchVariants(arch ArchType, variants ...string) {
111 checkCalledFromInit()
112 archVariants[arch] = append(archVariants[arch], variants...)
113}
114
115func RegisterArchFeatures(arch ArchType, features ...string) {
116 checkCalledFromInit()
117 archFeatures[arch] = append(archFeatures[arch], features...)
118}
119
120func RegisterArchVariantFeatures(arch ArchType, variant string, features ...string) {
121 checkCalledFromInit()
Colin Crossb4330e22017-12-22 15:47:09 -0800122 if variant != "" && !InList(variant, archVariants[arch]) {
Dan Willemsenb1957a52016-06-23 23:44:54 -0700123 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
Colin Crossc5c24ad2015-11-20 15:35:00 -0800124 }
Dan Willemsenb1957a52016-06-23 23:44:54 -0700125
Colin Crossc5c24ad2015-11-20 15:35:00 -0800126 for _, feature := range features {
Colin Crossb4330e22017-12-22 15:47:09 -0800127 if !InList(feature, archFeatures[arch]) {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800128 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
129 }
130 }
Dan Willemsenb1957a52016-06-23 23:44:54 -0700131
Colin Crossc5c24ad2015-11-20 15:35:00 -0800132 if archFeatureMap[arch] == nil {
133 archFeatureMap[arch] = make(map[string][]string)
134 }
135 archFeatureMap[arch][variant] = features
136}
137
Colin Cross3f40fa42015-01-30 17:27:36 -0800138// An Arch indicates a single CPU architecture.
139type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800140 ArchType ArchType
141 ArchVariant string
142 CpuVariant string
143 Abi []string
144 ArchFeatures []string
Dan Willemsen17f05262016-05-31 16:27:00 -0700145 Native bool
Colin Cross3f40fa42015-01-30 17:27:36 -0800146}
147
148func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700149 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800150 if a.ArchVariant != "" {
151 s += "_" + a.ArchVariant
152 }
153 if a.CpuVariant != "" {
154 s += "_" + a.CpuVariant
155 }
156 return s
157}
158
159type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700160 Name string
Dan Willemsenb1957a52016-06-23 23:44:54 -0700161 Field string
Colin Crossec193632015-07-06 17:49:43 -0700162 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800163}
164
Colin Crossec193632015-07-06 17:49:43 -0700165func newArch(name, multilib string) ArchType {
Dan Willemsenb1957a52016-06-23 23:44:54 -0700166 archType := ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700167 Name: name,
Dan Willemsenb1957a52016-06-23 23:44:54 -0700168 Field: proptools.FieldNameForProperty(name),
Colin Crossec193632015-07-06 17:49:43 -0700169 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800170 }
Dan Willemsenb1957a52016-06-23 23:44:54 -0700171 archTypeList = append(archTypeList, archType)
172 return archType
Colin Cross3f40fa42015-01-30 17:27:36 -0800173}
174
175func (a ArchType) String() string {
176 return a.Name
177}
178
Colin Crossa1ad8d12016-06-01 17:09:44 -0700179var BuildOs = func() OsType {
Dan Willemsen490fd492015-11-24 17:53:15 -0800180 switch runtime.GOOS {
181 case "linux":
182 return Linux
183 case "darwin":
184 return Darwin
185 default:
186 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
187 }
Colin Crossa1ad8d12016-06-01 17:09:44 -0700188}()
189
190var (
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800191 osTypeList []OsType
192 commonTargetMap = make(map[string]Target)
Colin Crossa1ad8d12016-06-01 17:09:44 -0700193
Dan Willemsen00fcbde2016-11-17 00:25:59 -0800194 NoOsType OsType
Dan Willemsen866b5632017-09-22 12:28:24 -0700195 Linux = NewOsType("linux_glibc", Host, false)
Dan Willemsen00fcbde2016-11-17 00:25:59 -0800196 Darwin = NewOsType("darwin", Host, false)
Dan Willemsen9ff34c02018-10-10 17:58:19 -0700197 LinuxBionic = NewOsType("linux_bionic", Host, false)
Dan Willemsen00fcbde2016-11-17 00:25:59 -0800198 Windows = NewOsType("windows", HostCross, true)
199 Android = NewOsType("android", Device, false)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700200
201 osArchTypeMap = map[OsType][]ArchType{
Dan Willemsen00fcbde2016-11-17 00:25:59 -0800202 Linux: []ArchType{X86, X86_64},
203 LinuxBionic: []ArchType{X86_64},
Dan Willemsene97e68a2018-08-28 17:12:56 -0700204 Darwin: []ArchType{X86_64},
Dan Willemsen00fcbde2016-11-17 00:25:59 -0800205 Windows: []ArchType{X86, X86_64},
206 Android: []ArchType{Arm, Arm64, Mips, Mips64, X86, X86_64},
Dan Willemsenb1957a52016-06-23 23:44:54 -0700207 }
Colin Crossa1ad8d12016-06-01 17:09:44 -0700208)
209
210type OsType struct {
211 Name, Field string
212 Class OsClass
Dan Willemsen0a37a2a2016-11-13 10:16:05 -0800213
214 DefaultDisabled bool
Dan Willemsen490fd492015-11-24 17:53:15 -0800215}
216
Colin Crossa1ad8d12016-06-01 17:09:44 -0700217type OsClass int
218
219const (
Dan Willemsen0e2d97b2016-11-28 17:50:06 -0800220 Generic OsClass = iota
221 Device
Colin Crossa1ad8d12016-06-01 17:09:44 -0700222 Host
223 HostCross
224)
225
Colin Cross67a5c132017-05-09 13:45:28 -0700226func (class OsClass) String() string {
227 switch class {
228 case Generic:
229 return "generic"
230 case Device:
231 return "device"
232 case Host:
233 return "host"
234 case HostCross:
235 return "host cross"
236 default:
237 panic(fmt.Errorf("unknown class %d", class))
238 }
239}
240
Colin Crossa1ad8d12016-06-01 17:09:44 -0700241func (os OsType) String() string {
242 return os.Name
Colin Cross54c71122016-06-01 17:09:44 -0700243}
244
Dan Willemsen866b5632017-09-22 12:28:24 -0700245func (os OsType) Bionic() bool {
246 return os == Android || os == LinuxBionic
247}
248
249func (os OsType) Linux() bool {
250 return os == Android || os == Linux || os == LinuxBionic
251}
252
Dan Willemsen0a37a2a2016-11-13 10:16:05 -0800253func NewOsType(name string, class OsClass, defDisabled bool) OsType {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700254 os := OsType{
255 Name: name,
256 Field: strings.Title(name),
257 Class: class,
Dan Willemsen0a37a2a2016-11-13 10:16:05 -0800258
259 DefaultDisabled: defDisabled,
Colin Cross54c71122016-06-01 17:09:44 -0700260 }
Colin Crossa1ad8d12016-06-01 17:09:44 -0700261 osTypeList = append(osTypeList, os)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800262
263 if _, found := commonTargetMap[name]; found {
264 panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
265 } else {
266 commonTargetMap[name] = Target{Os: os, Arch: Arch{ArchType: Common}}
267 }
268
Colin Crossa1ad8d12016-06-01 17:09:44 -0700269 return os
270}
271
272func osByName(name string) OsType {
273 for _, os := range osTypeList {
274 if os.Name == name {
275 return os
276 }
277 }
278
279 return NoOsType
Dan Willemsen490fd492015-11-24 17:53:15 -0800280}
281
Colin Crossa1ad8d12016-06-01 17:09:44 -0700282type Target struct {
283 Os OsType
284 Arch Arch
Colin Crossd3ba0392015-05-07 14:11:29 -0700285}
286
Colin Crossa1ad8d12016-06-01 17:09:44 -0700287func (target Target) String() string {
288 return target.Os.String() + "_" + target.Arch.String()
Dan Willemsen490fd492015-11-24 17:53:15 -0800289}
290
Colin Crossee0bc3b2018-10-02 22:01:37 -0700291// archMutator splits a module into a variant for each Target requested by the module. Target selection
292// for a module is in three levels, OsClass, mulitlib, and then Target.
293// OsClass selection is determined by:
294// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
295// whether the module type can compile for host, device or both.
296// - The host_supported and device_supported properties on the module.
297// If host is supported for the module, the Host and HostCross OsClasses are are selected. If device is supported
298// for the module, the Device OsClass is selected.
299// Within each selected OsClass, the multilib selection is determined by:
300// - The compile_multilib property if it set (which may be overriden by target.android.compile_multlib or
301// target.host.compile_multilib).
302// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set.
303// Valid multilib values include:
304// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm).
305// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64,
306// but may be arm for a 32-bit only build or a build with TARGET_PREFER_32_BIT=true set.
307// "32": compile for only a single 32-bit Target supported by the OsClass.
308// "64": compile for only a single 64-bit Target supported by the OsClass.
309// "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java).
310//
311// Once the list of Targets is determined, the module is split into a variant for each Target.
312//
313// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
314// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
Colin Cross1e676be2016-10-12 14:38:15 -0700315func archMutator(mctx BottomUpMutatorContext) {
Colin Cross635c3b02016-05-18 15:37:25 -0700316 var module Module
Colin Cross3f40fa42015-01-30 17:27:36 -0800317 var ok bool
Colin Cross635c3b02016-05-18 15:37:25 -0700318 if module, ok = mctx.Module().(Module); !ok {
Colin Cross3f40fa42015-01-30 17:27:36 -0800319 return
320 }
321
Colin Cross5eca7cb2018-10-02 14:02:10 -0700322 base := module.base()
323
324 if !base.ArchSpecific() {
Colin Crossb9db4802016-06-03 01:50:47 +0000325 return
326 }
327
Colin Crossa1ad8d12016-06-01 17:09:44 -0700328 var moduleTargets []Target
Colin Crossee0bc3b2018-10-02 22:01:37 -0700329 moduleMultiTargets := make(map[int][]Target)
Colin Cross8b74d172016-09-13 09:59:14 -0700330 primaryModules := make(map[int]bool)
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700331 osClasses := base.OsClassSupported()
Colin Crossa1ad8d12016-06-01 17:09:44 -0700332
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700333 for _, os := range osTypeList {
334 supportedClass := false
335 for _, osClass := range osClasses {
336 if os.Class == osClass {
337 supportedClass = true
338 }
339 }
340 if !supportedClass {
341 continue
342 }
343
344 osTargets := mctx.Config().Targets[os]
345 if len(osTargets) == 0 {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700346 continue
347 }
Colin Crossee0bc3b2018-10-02 22:01:37 -0700348
Colin Cross5eca7cb2018-10-02 14:02:10 -0700349 // only the primary arch in the recovery partition
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700350 if os == Android && module.InstallInRecovery() {
351 osTargets = []Target{osTargets[0]}
Colin Cross5eca7cb2018-10-02 14:02:10 -0700352 }
353
Colin Crossa9d8bee2018-10-02 13:59:46 -0700354 prefer32 := false
355 if base.prefer32 != nil {
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700356 prefer32 = base.prefer32(mctx, base, os.Class)
Colin Cross8b74d172016-09-13 09:59:14 -0700357 }
Colin Crossa9d8bee2018-10-02 13:59:46 -0700358
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700359 multilib, extraMultilib := decodeMultilib(base, os.Class)
360 targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
Colin Crossa1ad8d12016-06-01 17:09:44 -0700361 if err != nil {
362 mctx.ModuleErrorf("%s", err.Error())
363 }
Colin Crossee0bc3b2018-10-02 22:01:37 -0700364
365 var multiTargets []Target
366 if extraMultilib != "" {
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700367 multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
Colin Crossee0bc3b2018-10-02 22:01:37 -0700368 if err != nil {
369 mctx.ModuleErrorf("%s", err.Error())
370 }
371 }
372
Colin Cross8b74d172016-09-13 09:59:14 -0700373 if len(targets) > 0 {
374 primaryModules[len(moduleTargets)] = true
Colin Crossee0bc3b2018-10-02 22:01:37 -0700375 moduleMultiTargets[len(moduleTargets)] = multiTargets
Colin Cross8b74d172016-09-13 09:59:14 -0700376 moduleTargets = append(moduleTargets, targets...)
377 }
Colin Crossb9db4802016-06-03 01:50:47 +0000378 }
379
Dan Willemsen3f32f032016-07-11 14:36:48 -0700380 if len(moduleTargets) == 0 {
Colin Cross5eca7cb2018-10-02 14:02:10 -0700381 base.commonProperties.Enabled = boolPtr(false)
Dan Willemsen3f32f032016-07-11 14:36:48 -0700382 return
383 }
384
Colin Crossa1ad8d12016-06-01 17:09:44 -0700385 targetNames := make([]string, len(moduleTargets))
Colin Crossb9db4802016-06-03 01:50:47 +0000386
Colin Crossa1ad8d12016-06-01 17:09:44 -0700387 for i, target := range moduleTargets {
388 targetNames[i] = target.String()
389 }
390
391 modules := mctx.CreateVariations(targetNames...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800392 for i, m := range modules {
Colin Crossee0bc3b2018-10-02 22:01:37 -0700393 m.(Module).base().SetTarget(moduleTargets[i], moduleMultiTargets[i], primaryModules[i])
Colin Cross635c3b02016-05-18 15:37:25 -0700394 m.(Module).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800395 }
396}
397
Colin Crossee0bc3b2018-10-02 22:01:37 -0700398func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
399 switch class {
400 case Device:
401 multilib = String(base.commonProperties.Target.Android.Compile_multilib)
402 case Host, HostCross:
403 multilib = String(base.commonProperties.Target.Host.Compile_multilib)
404 }
405 if multilib == "" {
406 multilib = String(base.commonProperties.Compile_multilib)
407 }
408 if multilib == "" {
409 multilib = base.commonProperties.Default_multilib
410 }
411
412 if base.commonProperties.UseTargetVariants {
413 return multilib, ""
414 } else {
415 // For app modules a single arch variant will be created per OS class which is expected to handle all the
416 // selected arches. Return the common-type as multilib and any Android.bp provided multilib as extraMultilib
417 if multilib == base.commonProperties.Default_multilib {
418 multilib = "first"
419 }
420 return base.commonProperties.Default_multilib, multilib
421 }
422}
423
Colin Crossc17727d2018-10-24 12:42:09 -0700424func filterArchStructFields(fields []reflect.StructField) []reflect.StructField {
425 var ret []reflect.StructField
426 for _, field := range fields {
Dan Willemsenb1957a52016-06-23 23:44:54 -0700427 if !proptools.HasTag(field, "android", "arch_variant") {
428 continue
429 }
430
431 // The arch_variant field isn't necessary past this point
432 // Instead of wasting space, just remove it. Go also has a
433 // 16-bit limit on structure name length. The name is constructed
434 // based on the Go source representation of the structure, so
435 // the tag names count towards that length.
436 //
437 // TODO: handle the uncommon case of other tags being involved
438 if field.Tag == `android:"arch_variant"` {
439 field.Tag = ""
440 }
441
442 // Recurse into structs
443 switch field.Type.Kind() {
444 case reflect.Struct:
445 var ok bool
446 field.Type, ok = filterArchStruct(field.Type)
447 if !ok {
448 continue
449 }
450 case reflect.Ptr:
451 if field.Type.Elem().Kind() == reflect.Struct {
452 nestedType, ok := filterArchStruct(field.Type.Elem())
453 if !ok {
454 continue
455 }
456 field.Type = reflect.PtrTo(nestedType)
457 }
458 case reflect.Interface:
459 panic("Interfaces are not supported in arch_variant properties")
460 }
461
Colin Crossc17727d2018-10-24 12:42:09 -0700462 ret = append(ret, field)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700463 }
Colin Crossc17727d2018-10-24 12:42:09 -0700464
465 return ret
466}
467
468func filterArchStruct(prop reflect.Type) (reflect.Type, bool) {
469 var fields []reflect.StructField
470
471 ptr := prop.Kind() == reflect.Ptr
472 if ptr {
473 prop = prop.Elem()
474 }
475
476 for i := 0; i < prop.NumField(); i++ {
477 fields = append(fields, prop.Field(i))
478 }
479
480 fields = filterArchStructFields(fields)
481
Dan Willemsenb1957a52016-06-23 23:44:54 -0700482 if len(fields) == 0 {
483 return nil, false
484 }
485
486 ret := reflect.StructOf(fields)
487 if ptr {
488 ret = reflect.PtrTo(ret)
489 }
Colin Crossc17727d2018-10-24 12:42:09 -0700490
Dan Willemsenb1957a52016-06-23 23:44:54 -0700491 return ret, true
492}
493
Colin Crossc17727d2018-10-24 12:42:09 -0700494func filterArchStructSharded(prop reflect.Type) ([]reflect.Type, bool) {
495 var fields []reflect.StructField
496
497 ptr := prop.Kind() == reflect.Ptr
498 if ptr {
499 prop = prop.Elem()
500 }
501
502 for i := 0; i < prop.NumField(); i++ {
503 fields = append(fields, prop.Field(i))
504 }
505
506 fields = filterArchStructFields(fields)
507
508 if len(fields) == 0 {
509 return nil, false
510 }
511
512 shards := shardFields(fields, 10)
513
514 var ret []reflect.Type
515 for _, shard := range shards {
516 s := reflect.StructOf(shard)
517 if ptr {
518 s = reflect.PtrTo(s)
519 }
520 ret = append(ret, s)
521 }
522
523 return ret, true
524}
525
526func shardFields(fields []reflect.StructField, shardSize int) [][]reflect.StructField {
527 ret := make([][]reflect.StructField, 0, (len(fields)+shardSize-1)/shardSize)
528 for len(fields) > shardSize {
529 ret = append(ret, fields[0:shardSize])
530 fields = fields[shardSize:]
531 }
532 if len(fields) > 0 {
533 ret = append(ret, fields)
534 }
535 return ret
536}
537
538func createArchType(props reflect.Type) []reflect.Type {
539 propShards, ok := filterArchStructSharded(props)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700540 if !ok {
541 return nil
542 }
543
Colin Crossc17727d2018-10-24 12:42:09 -0700544 var ret []reflect.Type
545 for _, props := range propShards {
Dan Willemsenb1957a52016-06-23 23:44:54 -0700546
Colin Crossc17727d2018-10-24 12:42:09 -0700547 variantFields := func(names []string) []reflect.StructField {
548 ret := make([]reflect.StructField, len(names))
Dan Willemsenb1957a52016-06-23 23:44:54 -0700549
Colin Crossc17727d2018-10-24 12:42:09 -0700550 for i, name := range names {
551 ret[i].Name = name
552 ret[i].Type = props
Dan Willemsen866b5632017-09-22 12:28:24 -0700553 }
Colin Crossc17727d2018-10-24 12:42:09 -0700554
555 return ret
556 }
557
558 archFields := make([]reflect.StructField, len(archTypeList))
559 for i, arch := range archTypeList {
560 variants := []string{}
561
562 for _, archVariant := range archVariants[arch] {
563 archVariant := variantReplacer.Replace(archVariant)
564 variants = append(variants, proptools.FieldNameForProperty(archVariant))
565 }
566 for _, feature := range archFeatures[arch] {
567 feature := variantReplacer.Replace(feature)
568 variants = append(variants, proptools.FieldNameForProperty(feature))
569 }
570
571 fields := variantFields(variants)
572
573 fields = append([]reflect.StructField{{
574 Name: "BlueprintEmbed",
575 Type: props,
576 Anonymous: true,
577 }}, fields...)
578
579 archFields[i] = reflect.StructField{
580 Name: arch.Field,
581 Type: reflect.StructOf(fields),
582 }
583 }
584 archType := reflect.StructOf(archFields)
585
586 multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"}))
587
588 targets := []string{
589 "Host",
590 "Android64",
591 "Android32",
592 "Bionic",
593 "Linux",
594 "Not_windows",
595 "Arm_on_x86",
596 "Arm_on_x86_64",
597 }
598 for _, os := range osTypeList {
599 targets = append(targets, os.Field)
600
601 for _, archType := range osArchTypeMap[os] {
602 targets = append(targets, os.Field+"_"+archType.Name)
603
604 if os.Linux() {
605 target := "Linux_" + archType.Name
606 if !InList(target, targets) {
607 targets = append(targets, target)
608 }
609 }
610 if os.Bionic() {
611 target := "Bionic_" + archType.Name
612 if !InList(target, targets) {
613 targets = append(targets, target)
614 }
Dan Willemsen866b5632017-09-22 12:28:24 -0700615 }
616 }
Dan Willemsenb1957a52016-06-23 23:44:54 -0700617 }
Dan Willemsenb1957a52016-06-23 23:44:54 -0700618
Colin Crossc17727d2018-10-24 12:42:09 -0700619 targetType := reflect.StructOf(variantFields(targets))
620 ret = append(ret, reflect.StructOf([]reflect.StructField{
621 {
622 Name: "Arch",
623 Type: archType,
624 },
625 {
626 Name: "Multilib",
627 Type: multilibType,
628 },
629 {
630 Name: "Target",
631 Type: targetType,
632 },
633 }))
634 }
635 return ret
Dan Willemsenb1957a52016-06-23 23:44:54 -0700636}
637
638var archPropTypeMap OncePer
639
Colin Cross36242852017-06-23 15:06:31 -0700640func InitArchModule(m Module) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800641
642 base := m.base()
643
Colin Cross36242852017-06-23 15:06:31 -0700644 base.generalProperties = m.GetProperties()
Colin Cross3f40fa42015-01-30 17:27:36 -0800645
646 for _, properties := range base.generalProperties {
647 propertiesValue := reflect.ValueOf(properties)
Colin Cross62496a02016-08-08 15:49:17 -0700648 t := propertiesValue.Type()
Colin Cross3f40fa42015-01-30 17:27:36 -0800649 if propertiesValue.Kind() != reflect.Ptr {
Colin Crossca860ac2016-01-04 14:34:37 -0800650 panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
651 propertiesValue.Interface()))
Colin Cross3f40fa42015-01-30 17:27:36 -0800652 }
653
654 propertiesValue = propertiesValue.Elem()
655 if propertiesValue.Kind() != reflect.Struct {
Colin Crossca860ac2016-01-04 14:34:37 -0800656 panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
657 propertiesValue.Interface()))
Colin Cross3f40fa42015-01-30 17:27:36 -0800658 }
659
Colin Crossc17727d2018-10-24 12:42:09 -0700660 archPropTypes := archPropTypeMap.Once(t, func() interface{} {
Dan Willemsenb1957a52016-06-23 23:44:54 -0700661 return createArchType(t)
Colin Crossc17727d2018-10-24 12:42:09 -0700662 }).([]reflect.Type)
Colin Cross3f40fa42015-01-30 17:27:36 -0800663
Colin Crossc17727d2018-10-24 12:42:09 -0700664 var archProperties []interface{}
665 for _, t := range archPropTypes {
666 archProperties = append(archProperties, reflect.New(t).Interface())
Dan Willemsenb1957a52016-06-23 23:44:54 -0700667 }
Colin Crossc17727d2018-10-24 12:42:09 -0700668 base.archProperties = append(base.archProperties, archProperties)
669 m.AddProperties(archProperties...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800670 }
671
Colin Cross36242852017-06-23 15:06:31 -0700672 base.customizableProperties = m.GetProperties()
Colin Cross3f40fa42015-01-30 17:27:36 -0800673}
674
Colin Crossa716add2015-12-16 11:07:39 -0800675var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
Colin Crossec193632015-07-06 17:49:43 -0700676
Colin Cross635c3b02016-05-18 15:37:25 -0700677func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
Dan Willemsenb1957a52016-06-23 23:44:54 -0700678 dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value {
Colin Cross06a931b2015-10-28 17:23:31 -0700679
Dan Willemsenb1957a52016-06-23 23:44:54 -0700680 src = src.FieldByName(field)
681 if !src.IsValid() {
Colin Crosseeabb892015-11-20 13:07:51 -0800682 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700683 return src
Colin Cross85a88972015-11-23 13:29:51 -0800684 }
685
Dan Willemsenb1957a52016-06-23 23:44:54 -0700686 ret := src
Colin Cross85a88972015-11-23 13:29:51 -0800687
Dan Willemsenb1957a52016-06-23 23:44:54 -0700688 if src.Kind() == reflect.Struct {
689 src = src.FieldByName("BlueprintEmbed")
Colin Cross06a931b2015-10-28 17:23:31 -0700690 }
691
Colin Cross6ee75b62016-05-05 15:57:15 -0700692 order := func(property string,
693 dstField, srcField reflect.StructField,
694 dstValue, srcValue interface{}) (proptools.Order, error) {
695 if proptools.HasTag(dstField, "android", "variant_prepend") {
696 return proptools.Prepend, nil
697 } else {
698 return proptools.Append, nil
699 }
700 }
701
Dan Willemsenb1957a52016-06-23 23:44:54 -0700702 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, order)
Colin Cross06a931b2015-10-28 17:23:31 -0700703 if err != nil {
704 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
705 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
706 } else {
707 panic(err)
708 }
709 }
Colin Cross85a88972015-11-23 13:29:51 -0800710
Dan Willemsenb1957a52016-06-23 23:44:54 -0700711 return ret
Colin Cross06a931b2015-10-28 17:23:31 -0700712}
713
Colin Cross3f40fa42015-01-30 17:27:36 -0800714// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross635c3b02016-05-18 15:37:25 -0700715func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700716 arch := a.Arch()
717 os := a.Os()
Colin Crossd3ba0392015-05-07 14:11:29 -0700718
Colin Cross3f40fa42015-01-30 17:27:36 -0800719 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700720 genProps := a.generalProperties[i]
Dan Willemsenb1957a52016-06-23 23:44:54 -0700721 if a.archProperties[i] == nil {
722 continue
723 }
Colin Crossc17727d2018-10-24 12:42:09 -0700724 for _, archProperties := range a.archProperties[i] {
725 archPropValues := reflect.ValueOf(archProperties).Elem()
Dan Willemsenb1957a52016-06-23 23:44:54 -0700726
Colin Crossc17727d2018-10-24 12:42:09 -0700727 archProp := archPropValues.FieldByName("Arch")
728 multilibProp := archPropValues.FieldByName("Multilib")
729 targetProp := archPropValues.FieldByName("Target")
Dan Willemsenb1957a52016-06-23 23:44:54 -0700730
Colin Crossc17727d2018-10-24 12:42:09 -0700731 var field string
732 var prefix string
Colin Crossd5934c82017-10-02 13:55:26 -0700733
Colin Crossc17727d2018-10-24 12:42:09 -0700734 // Handle arch-specific properties in the form:
Colin Crossd5934c82017-10-02 13:55:26 -0700735 // arch: {
Colin Crossc17727d2018-10-24 12:42:09 -0700736 // arm64: {
Colin Crossd5934c82017-10-02 13:55:26 -0700737 // key: value,
738 // },
739 // },
Colin Crossc17727d2018-10-24 12:42:09 -0700740 t := arch.ArchType
741
742 if arch.ArchType != Common {
743 field := proptools.FieldNameForProperty(t.Name)
744 prefix := "arch." + t.Name
745 archStruct := a.appendProperties(ctx, genProps, archProp, field, prefix)
746
747 // Handle arch-variant-specific properties in the form:
748 // arch: {
749 // variant: {
750 // key: value,
751 // },
752 // },
753 v := variantReplacer.Replace(arch.ArchVariant)
754 if v != "" {
755 field := proptools.FieldNameForProperty(v)
756 prefix := "arch." + t.Name + "." + v
757 a.appendProperties(ctx, genProps, archStruct, field, prefix)
758 }
759
760 // Handle cpu-variant-specific properties in the form:
761 // arch: {
762 // variant: {
763 // key: value,
764 // },
765 // },
766 if arch.CpuVariant != arch.ArchVariant {
767 c := variantReplacer.Replace(arch.CpuVariant)
768 if c != "" {
769 field := proptools.FieldNameForProperty(c)
770 prefix := "arch." + t.Name + "." + c
771 a.appendProperties(ctx, genProps, archStruct, field, prefix)
772 }
773 }
774
775 // Handle arch-feature-specific properties in the form:
776 // arch: {
777 // feature: {
778 // key: value,
779 // },
780 // },
781 for _, feature := range arch.ArchFeatures {
782 field := proptools.FieldNameForProperty(feature)
783 prefix := "arch." + t.Name + "." + feature
784 a.appendProperties(ctx, genProps, archStruct, field, prefix)
785 }
786
787 // Handle multilib-specific properties in the form:
788 // multilib: {
789 // lib32: {
790 // key: value,
791 // },
792 // },
793 field = proptools.FieldNameForProperty(t.Multilib)
794 prefix = "multilib." + t.Multilib
795 a.appendProperties(ctx, genProps, multilibProp, field, prefix)
Colin Cross08016332016-12-20 09:53:14 -0800796 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800797
Colin Crossc17727d2018-10-24 12:42:09 -0700798 // Handle host-specific properties in the form:
799 // target: {
800 // host: {
Colin Crossd5934c82017-10-02 13:55:26 -0700801 // key: value,
802 // },
803 // },
Colin Crossc17727d2018-10-24 12:42:09 -0700804 if os.Class == Host || os.Class == HostCross {
805 field = "Host"
806 prefix = "target.host"
807 a.appendProperties(ctx, genProps, targetProp, field, prefix)
808 }
809
810 // Handle target OS generalities of the form:
811 // target: {
812 // bionic: {
813 // key: value,
814 // },
815 // bionic_x86: {
816 // key: value,
817 // },
818 // }
819 if os.Linux() {
820 field = "Linux"
821 prefix = "target.linux"
822 a.appendProperties(ctx, genProps, targetProp, field, prefix)
823
824 if arch.ArchType != Common {
825 field = "Linux_" + arch.ArchType.Name
826 prefix = "target.linux_" + arch.ArchType.Name
827 a.appendProperties(ctx, genProps, targetProp, field, prefix)
Colin Crossd5934c82017-10-02 13:55:26 -0700828 }
829 }
Colin Crossc5c24ad2015-11-20 15:35:00 -0800830
Colin Crossc17727d2018-10-24 12:42:09 -0700831 if os.Bionic() {
832 field = "Bionic"
833 prefix = "target.bionic"
834 a.appendProperties(ctx, genProps, targetProp, field, prefix)
835
836 if arch.ArchType != Common {
837 field = "Bionic_" + t.Name
838 prefix = "target.bionic_" + t.Name
839 a.appendProperties(ctx, genProps, targetProp, field, prefix)
840 }
841 }
842
843 // Handle target OS properties in the form:
844 // target: {
845 // linux_glibc: {
846 // key: value,
847 // },
848 // not_windows: {
849 // key: value,
850 // },
851 // linux_glibc_x86: {
852 // key: value,
853 // },
854 // linux_glibc_arm: {
855 // key: value,
856 // },
857 // android {
858 // key: value,
859 // },
860 // android_arm {
861 // key: value,
862 // },
863 // android_x86 {
Colin Crossd5934c82017-10-02 13:55:26 -0700864 // key: value,
865 // },
866 // },
Colin Crossc17727d2018-10-24 12:42:09 -0700867 field = os.Field
868 prefix = "target." + os.Name
869 a.appendProperties(ctx, genProps, targetProp, field, prefix)
870
871 if arch.ArchType != Common {
872 field = os.Field + "_" + t.Name
873 prefix = "target." + os.Name + "_" + t.Name
874 a.appendProperties(ctx, genProps, targetProp, field, prefix)
Colin Crossd5934c82017-10-02 13:55:26 -0700875 }
876
Colin Crossc17727d2018-10-24 12:42:09 -0700877 if (os.Class == Host || os.Class == HostCross) && os != Windows {
878 field := "Not_windows"
879 prefix := "target.not_windows"
880 a.appendProperties(ctx, genProps, targetProp, field, prefix)
881 }
882
883 // Handle 64-bit device properties in the form:
884 // target {
885 // android64 {
886 // key: value,
887 // },
888 // android32 {
Colin Crossd5934c82017-10-02 13:55:26 -0700889 // key: value,
890 // },
891 // },
Colin Crossc17727d2018-10-24 12:42:09 -0700892 // WARNING: this is probably not what you want to use in your blueprints file, it selects
893 // options for all targets on a device that supports 64-bit binaries, not just the targets
894 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
895 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
896 if os.Class == Device {
897 if ctx.Config().Android64() {
898 field := "Android64"
899 prefix := "target.android64"
900 a.appendProperties(ctx, genProps, targetProp, field, prefix)
901 } else {
902 field := "Android32"
903 prefix := "target.android32"
904 a.appendProperties(ctx, genProps, targetProp, field, prefix)
905 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800906
Colin Crossc17727d2018-10-24 12:42:09 -0700907 if (arch.ArchType == X86 && (hasArmAbi(arch) ||
908 hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
909 (arch.ArchType == Arm &&
910 hasX86AndroidArch(ctx.Config().Targets[Android])) {
911 field := "Arm_on_x86"
912 prefix := "target.arm_on_x86"
913 a.appendProperties(ctx, genProps, targetProp, field, prefix)
914 }
915 if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
916 hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
917 (arch.ArchType == Arm &&
918 hasX8664AndroidArch(ctx.Config().Targets[Android])) {
919 field := "Arm_on_x86_64"
920 prefix := "target.arm_on_x86_64"
921 a.appendProperties(ctx, genProps, targetProp, field, prefix)
922 }
Colin Cross4247f0d2017-04-13 16:56:14 -0700923 }
Colin Crossbb2e2b72016-12-08 17:23:53 -0800924 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800925 }
926}
927
928func forEachInterface(v reflect.Value, f func(reflect.Value)) {
929 switch v.Kind() {
930 case reflect.Interface:
931 f(v)
932 case reflect.Struct:
933 for i := 0; i < v.NumField(); i++ {
934 forEachInterface(v.Field(i), f)
935 }
936 case reflect.Ptr:
937 forEachInterface(v.Elem(), f)
938 default:
939 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
940 }
941}
Colin Cross4225f652015-09-17 14:33:42 -0700942
Colin Crossa1ad8d12016-06-01 17:09:44 -0700943// Convert the arch product variables into a list of targets for each os class structs
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700944func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
Dan Willemsen45133ac2018-03-09 21:22:06 -0800945 variables := config.productVariables
Dan Willemsen490fd492015-11-24 17:53:15 -0800946
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700947 targets := make(map[OsType][]Target)
Colin Crossa1ad8d12016-06-01 17:09:44 -0700948 var targetErr error
949
950 addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi *[]string) {
951 if targetErr != nil {
952 return
Dan Willemsen490fd492015-11-24 17:53:15 -0800953 }
Colin Crossa1ad8d12016-06-01 17:09:44 -0700954
955 arch, err := decodeArch(archName, archVariant, cpuVariant, abi)
956 if err != nil {
957 targetErr = err
958 return
959 }
960
Dan Willemsen0ef639b2018-10-10 17:02:29 -0700961 targets[os] = append(targets[os],
Colin Crossa1ad8d12016-06-01 17:09:44 -0700962 Target{
963 Os: os,
964 Arch: arch,
965 })
Dan Willemsen490fd492015-11-24 17:53:15 -0800966 }
967
Colin Cross4225f652015-09-17 14:33:42 -0700968 if variables.HostArch == nil {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700969 return nil, fmt.Errorf("No host primary architecture set")
Colin Cross4225f652015-09-17 14:33:42 -0700970 }
971
Colin Crossa1ad8d12016-06-01 17:09:44 -0700972 addTarget(BuildOs, *variables.HostArch, nil, nil, nil)
Colin Cross4225f652015-09-17 14:33:42 -0700973
Colin Crosseeabb892015-11-20 13:07:51 -0800974 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700975 addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil)
Dan Willemsen490fd492015-11-24 17:53:15 -0800976 }
977
Colin Crossff3ae9d2018-04-10 16:15:18 -0700978 if Bool(config.Host_bionic) {
Dan Willemsen01a405a2016-06-13 17:19:03 -0700979 addTarget(LinuxBionic, "x86_64", nil, nil, nil)
980 }
981
Colin Crossff3ae9d2018-04-10 16:15:18 -0700982 if String(variables.CrossHost) != "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700983 crossHostOs := osByName(*variables.CrossHost)
984 if crossHostOs == NoOsType {
985 return nil, fmt.Errorf("Unknown cross host OS %q", *variables.CrossHost)
986 }
987
Colin Crossff3ae9d2018-04-10 16:15:18 -0700988 if String(variables.CrossHostArch) == "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700989 return nil, fmt.Errorf("No cross-host primary architecture set")
Dan Willemsen490fd492015-11-24 17:53:15 -0800990 }
991
Colin Crossa1ad8d12016-06-01 17:09:44 -0700992 addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil)
Dan Willemsen490fd492015-11-24 17:53:15 -0800993
994 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700995 addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil)
Dan Willemsen490fd492015-11-24 17:53:15 -0800996 }
997 }
998
Dan Willemsen3f32f032016-07-11 14:36:48 -0700999 if variables.DeviceArch != nil && *variables.DeviceArch != "" {
1000 addTarget(Android, *variables.DeviceArch, variables.DeviceArchVariant,
1001 variables.DeviceCpuVariant, variables.DeviceAbi)
Colin Cross4225f652015-09-17 14:33:42 -07001002
Dan Willemsen3f32f032016-07-11 14:36:48 -07001003 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
1004 addTarget(Android, *variables.DeviceSecondaryArch,
1005 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
1006 variables.DeviceSecondaryAbi)
Colin Cross4225f652015-09-17 14:33:42 -07001007
Dan Willemsen0ef639b2018-10-10 17:02:29 -07001008 deviceArches := targets[Android]
Dan Willemsen3f32f032016-07-11 14:36:48 -07001009 if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
1010 deviceArches[1].Arch.Native = false
1011 }
Colin Cross4225f652015-09-17 14:33:42 -07001012 }
Colin Cross4225f652015-09-17 14:33:42 -07001013 }
1014
Colin Crossa1ad8d12016-06-01 17:09:44 -07001015 if targetErr != nil {
1016 return nil, targetErr
1017 }
1018
1019 return targets, nil
Colin Cross4225f652015-09-17 14:33:42 -07001020}
1021
Colin Crossbb2e2b72016-12-08 17:23:53 -08001022// hasArmAbi returns true if arch has at least one arm ABI
1023func hasArmAbi(arch Arch) bool {
1024 for _, abi := range arch.Abi {
1025 if strings.HasPrefix(abi, "arm") {
1026 return true
1027 }
1028 }
1029 return false
1030}
1031
Colin Cross4247f0d2017-04-13 16:56:14 -07001032// hasArmArch returns true if targets has at least arm Android arch
1033func hasArmAndroidArch(targets []Target) bool {
1034 for _, target := range targets {
1035 if target.Os == Android && target.Arch.ArchType == Arm {
1036 return true
1037 }
1038 }
1039 return false
1040}
1041
Victor Khimenko5eb8ec12018-03-21 20:30:54 +01001042// hasX86Arch returns true if targets has at least x86 Android arch
1043func hasX86AndroidArch(targets []Target) bool {
1044 for _, target := range targets {
1045 if target.Os == Android && target.Arch.ArchType == X86 {
1046 return true
1047 }
1048 }
1049 return false
1050}
1051
1052// hasX8664Arch returns true if targets has at least x86_64 Android arch
1053func hasX8664AndroidArch(targets []Target) bool {
1054 for _, target := range targets {
1055 if target.Os == Android && target.Arch.ArchType == X86_64 {
1056 return true
1057 }
1058 }
1059 return false
1060}
1061
Dan Albert4098deb2016-10-19 14:04:41 -07001062type archConfig struct {
1063 arch string
1064 archVariant string
1065 cpuVariant string
1066 abi []string
1067}
1068
1069func getMegaDeviceConfig() []archConfig {
1070 return []archConfig{
Dan Willemsen110a89d2016-01-14 15:17:19 -08001071 {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
1072 {"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001073 {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
1074 {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -08001075 {"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001076 {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}},
1077 {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}},
1078 {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}},
Richard Fungeb37ed32018-09-24 16:33:45 -07001079 {"arm", "armv7-a-neon", "cortex-a72", []string{"armeabi-v7a"}},
Jake Weinstein6600a442017-05-15 18:27:12 -04001080 {"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}},
Christopher Ferrisba14a8f2018-04-23 18:15:25 -07001081 {"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}},
Haibo Huanga31e2bd2018-10-09 14:27:28 -07001082 {"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001083 {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
1084 {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
Alex Naidisae4fc182016-08-20 00:14:56 +02001085 {"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
Junmo Park8ea49592017-07-24 07:14:55 +09001086 {"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}},
Junmo Parkd86c9022017-07-21 09:07:47 +09001087 {"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -08001088 {"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
Richard Fungeb37ed32018-09-24 16:33:45 -07001089 {"arm64", "armv8-a", "cortex-a72", []string{"arm64-v8a"}},
Jake Weinstein6600a442017-05-15 18:27:12 -04001090 {"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -08001091 {"arm64", "armv8-a", "denver64", []string{"arm64-v8a"}},
Alex Naidisac01ff52016-08-30 15:56:33 +02001092 {"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}},
Junmo Park8ea49592017-07-24 07:14:55 +09001093 {"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}},
Junmo Parkd86c9022017-07-21 09:07:47 +09001094 {"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
Christopher Ferrisba14a8f2018-04-23 18:15:25 -07001095 {"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
Haibo Huanga31e2bd2018-10-09 14:27:28 -07001096 {"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
Dan Willemsen468cc312016-01-13 23:25:19 -08001097 {"mips", "mips32-fp", "", []string{"mips"}},
1098 {"mips", "mips32r2-fp", "", []string{"mips"}},
1099 {"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
Dan Willemsen65fb9812016-07-19 21:37:28 -07001100 //{"mips", "mips32r6", "", []string{"mips"}},
Colin Cross1837b802017-04-26 19:10:34 -07001101 {"mips", "mips32r2dsp-fp", "", []string{"mips"}},
1102 {"mips", "mips32r2dspr2-fp", "", []string{"mips"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001103 // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc
1104 //{"mips64", "mips64r2", "", []string{"mips64"}},
1105 {"mips64", "mips64r6", "", []string{"mips64"}},
1106 {"x86", "", "", []string{"x86"}},
1107 {"x86", "atom", "", []string{"x86"}},
1108 {"x86", "haswell", "", []string{"x86"}},
1109 {"x86", "ivybridge", "", []string{"x86"}},
1110 {"x86", "sandybridge", "", []string{"x86"}},
1111 {"x86", "silvermont", "", []string{"x86"}},
Dan Willemsen8a354052016-05-10 14:30:51 -07001112 {"x86", "x86_64", "", []string{"x86"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001113 {"x86_64", "", "", []string{"x86_64"}},
1114 {"x86_64", "haswell", "", []string{"x86_64"}},
1115 {"x86_64", "ivybridge", "", []string{"x86_64"}},
1116 {"x86_64", "sandybridge", "", []string{"x86_64"}},
1117 {"x86_64", "silvermont", "", []string{"x86_64"}},
1118 }
Dan Albert4098deb2016-10-19 14:04:41 -07001119}
Dan Willemsen322acaf2016-01-12 23:07:05 -08001120
Dan Albert4098deb2016-10-19 14:04:41 -07001121func getNdkAbisConfig() []archConfig {
1122 return []archConfig{
Dan Albertd3c8ca42017-12-20 14:48:39 -08001123 {"arm", "armv7-a", "", []string{"armeabi"}},
Dan Albert4098deb2016-10-19 14:04:41 -07001124 {"arm64", "armv8-a", "", []string{"arm64-v8a"}},
Dan Albert4098deb2016-10-19 14:04:41 -07001125 {"x86", "", "", []string{"x86"}},
1126 {"x86_64", "", "", []string{"x86_64"}},
1127 }
1128}
1129
1130func decodeArchSettings(archConfigs []archConfig) ([]Target, error) {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001131 var ret []Target
Dan Willemsen322acaf2016-01-12 23:07:05 -08001132
Dan Albert4098deb2016-10-19 14:04:41 -07001133 for _, config := range archConfigs {
Dan Willemsen322acaf2016-01-12 23:07:05 -08001134 arch, err := decodeArch(config.arch, &config.archVariant,
1135 &config.cpuVariant, &config.abi)
1136 if err != nil {
1137 return nil, err
1138 }
Dan Willemsen17f05262016-05-31 16:27:00 -07001139 arch.Native = false
Colin Crossa1ad8d12016-06-01 17:09:44 -07001140 ret = append(ret, Target{
1141 Os: Android,
1142 Arch: arch,
1143 })
Dan Willemsen322acaf2016-01-12 23:07:05 -08001144 }
1145
1146 return ret, nil
1147}
1148
Colin Cross4225f652015-09-17 14:33:42 -07001149// Convert a set of strings from product variables into a single Arch struct
1150func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
1151 stringPtr := func(p *string) string {
1152 if p != nil {
1153 return *p
1154 }
1155 return ""
1156 }
1157
1158 slicePtr := func(p *[]string) []string {
1159 if p != nil {
1160 return *p
1161 }
1162 return nil
1163 }
1164
Colin Crosseeabb892015-11-20 13:07:51 -08001165 archType, ok := archTypeMap[arch]
1166 if !ok {
1167 return Arch{}, fmt.Errorf("unknown arch %q", arch)
1168 }
Colin Cross4225f652015-09-17 14:33:42 -07001169
Colin Crosseeabb892015-11-20 13:07:51 -08001170 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -07001171 ArchType: archType,
1172 ArchVariant: stringPtr(archVariant),
1173 CpuVariant: stringPtr(cpuVariant),
1174 Abi: slicePtr(abi),
Dan Willemsen17f05262016-05-31 16:27:00 -07001175 Native: true,
Colin Crosseeabb892015-11-20 13:07:51 -08001176 }
1177
1178 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
1179 a.ArchVariant = ""
1180 }
1181
1182 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
1183 a.CpuVariant = ""
1184 }
1185
1186 for i := 0; i < len(a.Abi); i++ {
1187 if a.Abi[i] == "" {
1188 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
1189 i--
1190 }
1191 }
1192
Colin Crossc5c24ad2015-11-20 15:35:00 -08001193 if featureMap, ok := archFeatureMap[archType]; ok {
Dan Willemsenb4850992016-05-06 17:21:20 -07001194 a.ArchFeatures = featureMap[a.ArchVariant]
Colin Crossc5c24ad2015-11-20 15:35:00 -08001195 }
1196
Colin Crosseeabb892015-11-20 13:07:51 -08001197 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -07001198}
1199
Colin Cross69617d32016-09-06 10:39:07 -07001200func filterMultilibTargets(targets []Target, multilib string) []Target {
1201 var ret []Target
1202 for _, t := range targets {
1203 if t.Arch.ArchType.Multilib == multilib {
1204 ret = append(ret, t)
1205 }
1206 }
1207 return ret
1208}
1209
Nan Zhangdb0b9a32017-02-27 10:12:13 -08001210func getCommonTargets(targets []Target) []Target {
1211 var ret []Target
1212 set := make(map[string]bool)
1213
1214 for _, t := range targets {
1215 if _, found := set[t.Os.String()]; !found {
1216 set[t.Os.String()] = true
1217 ret = append(ret, commonTargetMap[t.Os.String()])
1218 }
1219 }
1220
1221 return ret
1222}
1223
Colin Cross3dceee32018-09-06 10:19:57 -07001224func firstTarget(targets []Target, filters ...string) []Target {
Colin Cross6b4a32d2017-12-05 13:42:45 -08001225 for _, filter := range filters {
1226 buildTargets := filterMultilibTargets(targets, filter)
1227 if len(buildTargets) > 0 {
Colin Cross3dceee32018-09-06 10:19:57 -07001228 return buildTargets[:1]
Colin Cross6b4a32d2017-12-05 13:42:45 -08001229 }
1230 }
1231 return nil
1232}
1233
Colin Crossa1ad8d12016-06-01 17:09:44 -07001234// Use the module multilib setting to select one or more targets from a target list
Colin Crossee0bc3b2018-10-02 22:01:37 -07001235func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001236 buildTargets := []Target{}
Colin Cross6b4a32d2017-12-05 13:42:45 -08001237
Colin Cross4225f652015-09-17 14:33:42 -07001238 switch multilib {
1239 case "common":
Colin Cross6b4a32d2017-12-05 13:42:45 -08001240 buildTargets = getCommonTargets(targets)
1241 case "common_first":
1242 buildTargets = getCommonTargets(targets)
1243 if prefer32 {
Colin Cross3dceee32018-09-06 10:19:57 -07001244 buildTargets = append(buildTargets, firstTarget(targets, "lib32", "lib64")...)
Colin Cross6b4a32d2017-12-05 13:42:45 -08001245 } else {
Colin Cross3dceee32018-09-06 10:19:57 -07001246 buildTargets = append(buildTargets, firstTarget(targets, "lib64", "lib32")...)
Colin Cross6b4a32d2017-12-05 13:42:45 -08001247 }
Colin Cross4225f652015-09-17 14:33:42 -07001248 case "both":
Colin Cross8b74d172016-09-13 09:59:14 -07001249 if prefer32 {
1250 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
1251 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
1252 } else {
1253 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
1254 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
1255 }
Colin Cross4225f652015-09-17 14:33:42 -07001256 case "32":
Colin Cross69617d32016-09-06 10:39:07 -07001257 buildTargets = filterMultilibTargets(targets, "lib32")
Colin Cross4225f652015-09-17 14:33:42 -07001258 case "64":
Colin Cross69617d32016-09-06 10:39:07 -07001259 buildTargets = filterMultilibTargets(targets, "lib64")
Colin Cross6b4a32d2017-12-05 13:42:45 -08001260 case "first":
1261 if prefer32 {
Colin Cross3dceee32018-09-06 10:19:57 -07001262 buildTargets = firstTarget(targets, "lib32", "lib64")
Colin Cross6b4a32d2017-12-05 13:42:45 -08001263 } else {
Colin Cross3dceee32018-09-06 10:19:57 -07001264 buildTargets = firstTarget(targets, "lib64", "lib32")
Colin Cross6b4a32d2017-12-05 13:42:45 -08001265 }
Colin Cross69617d32016-09-06 10:39:07 -07001266 case "prefer32":
Colin Cross3dceee32018-09-06 10:19:57 -07001267 buildTargets = filterMultilibTargets(targets, "lib32")
1268 if len(buildTargets) == 0 {
1269 buildTargets = filterMultilibTargets(targets, "lib64")
1270 }
Colin Cross4225f652015-09-17 14:33:42 -07001271 default:
Colin Cross69617d32016-09-06 10:39:07 -07001272 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", or "prefer32" found %q`,
Colin Cross4225f652015-09-17 14:33:42 -07001273 multilib)
Colin Cross4225f652015-09-17 14:33:42 -07001274 }
1275
Colin Crossa1ad8d12016-06-01 17:09:44 -07001276 return buildTargets, nil
Colin Cross4225f652015-09-17 14:33:42 -07001277}