blob: 33783170b749eddd313788346d5ae50235b83345 [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)
197 LinuxBionic = NewOsType("linux_bionic", Host, true)
198 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 Cross5eca7cb2018-10-02 14:02:10 -0700328 osClasses := base.OsClassSupported()
Dan Willemsen0b24c742016-10-04 15:13:37 -0700329
Colin Crossa1ad8d12016-06-01 17:09:44 -0700330 var moduleTargets []Target
Colin Crossee0bc3b2018-10-02 22:01:37 -0700331 moduleMultiTargets := make(map[int][]Target)
Colin Cross8b74d172016-09-13 09:59:14 -0700332 primaryModules := make(map[int]bool)
Colin Crossa1ad8d12016-06-01 17:09:44 -0700333
334 for _, class := range osClasses {
Colin Cross5eca7cb2018-10-02 14:02:10 -0700335 classTargets := mctx.Config().Targets[class]
336 if len(classTargets) == 0 {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700337 continue
338 }
Colin Crossee0bc3b2018-10-02 22:01:37 -0700339
Colin Cross5eca7cb2018-10-02 14:02:10 -0700340 // only the primary arch in the recovery partition
341 if module.InstallInRecovery() {
342 classTargets = []Target{mctx.Config().Targets[Device][0]}
343 }
344
Colin Crossa9d8bee2018-10-02 13:59:46 -0700345 prefer32 := false
346 if base.prefer32 != nil {
347 prefer32 = base.prefer32(mctx, base, class)
Colin Cross8b74d172016-09-13 09:59:14 -0700348 }
Colin Crossa9d8bee2018-10-02 13:59:46 -0700349
Colin Crossee0bc3b2018-10-02 22:01:37 -0700350 multilib, extraMultilib := decodeMultilib(base, class)
351 targets, err := decodeMultilibTargets(multilib, classTargets, prefer32)
Colin Crossa1ad8d12016-06-01 17:09:44 -0700352 if err != nil {
353 mctx.ModuleErrorf("%s", err.Error())
354 }
Colin Crossee0bc3b2018-10-02 22:01:37 -0700355
356 var multiTargets []Target
357 if extraMultilib != "" {
358 multiTargets, err = decodeMultilibTargets(extraMultilib, classTargets, prefer32)
359 if err != nil {
360 mctx.ModuleErrorf("%s", err.Error())
361 }
362 }
363
Colin Cross8b74d172016-09-13 09:59:14 -0700364 if len(targets) > 0 {
365 primaryModules[len(moduleTargets)] = true
Colin Crossee0bc3b2018-10-02 22:01:37 -0700366 moduleMultiTargets[len(moduleTargets)] = multiTargets
Colin Cross8b74d172016-09-13 09:59:14 -0700367 moduleTargets = append(moduleTargets, targets...)
368 }
Colin Crossb9db4802016-06-03 01:50:47 +0000369 }
370
Dan Willemsen3f32f032016-07-11 14:36:48 -0700371 if len(moduleTargets) == 0 {
Colin Cross5eca7cb2018-10-02 14:02:10 -0700372 base.commonProperties.Enabled = boolPtr(false)
Dan Willemsen3f32f032016-07-11 14:36:48 -0700373 return
374 }
375
Colin Crossa1ad8d12016-06-01 17:09:44 -0700376 targetNames := make([]string, len(moduleTargets))
Colin Crossb9db4802016-06-03 01:50:47 +0000377
Colin Crossa1ad8d12016-06-01 17:09:44 -0700378 for i, target := range moduleTargets {
379 targetNames[i] = target.String()
380 }
381
382 modules := mctx.CreateVariations(targetNames...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800383 for i, m := range modules {
Colin Crossee0bc3b2018-10-02 22:01:37 -0700384 m.(Module).base().SetTarget(moduleTargets[i], moduleMultiTargets[i], primaryModules[i])
Colin Cross635c3b02016-05-18 15:37:25 -0700385 m.(Module).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800386 }
387}
388
Colin Crossee0bc3b2018-10-02 22:01:37 -0700389func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
390 switch class {
391 case Device:
392 multilib = String(base.commonProperties.Target.Android.Compile_multilib)
393 case Host, HostCross:
394 multilib = String(base.commonProperties.Target.Host.Compile_multilib)
395 }
396 if multilib == "" {
397 multilib = String(base.commonProperties.Compile_multilib)
398 }
399 if multilib == "" {
400 multilib = base.commonProperties.Default_multilib
401 }
402
403 if base.commonProperties.UseTargetVariants {
404 return multilib, ""
405 } else {
406 // For app modules a single arch variant will be created per OS class which is expected to handle all the
407 // selected arches. Return the common-type as multilib and any Android.bp provided multilib as extraMultilib
408 if multilib == base.commonProperties.Default_multilib {
409 multilib = "first"
410 }
411 return base.commonProperties.Default_multilib, multilib
412 }
413}
414
Dan Willemsenb1957a52016-06-23 23:44:54 -0700415func filterArchStruct(prop reflect.Type) (reflect.Type, bool) {
416 var fields []reflect.StructField
417
418 ptr := prop.Kind() == reflect.Ptr
419 if ptr {
420 prop = prop.Elem()
421 }
422
423 for i := 0; i < prop.NumField(); i++ {
424 field := prop.Field(i)
425 if !proptools.HasTag(field, "android", "arch_variant") {
426 continue
427 }
428
429 // The arch_variant field isn't necessary past this point
430 // Instead of wasting space, just remove it. Go also has a
431 // 16-bit limit on structure name length. The name is constructed
432 // based on the Go source representation of the structure, so
433 // the tag names count towards that length.
434 //
435 // TODO: handle the uncommon case of other tags being involved
436 if field.Tag == `android:"arch_variant"` {
437 field.Tag = ""
438 }
439
440 // Recurse into structs
441 switch field.Type.Kind() {
442 case reflect.Struct:
443 var ok bool
444 field.Type, ok = filterArchStruct(field.Type)
445 if !ok {
446 continue
447 }
448 case reflect.Ptr:
449 if field.Type.Elem().Kind() == reflect.Struct {
450 nestedType, ok := filterArchStruct(field.Type.Elem())
451 if !ok {
452 continue
453 }
454 field.Type = reflect.PtrTo(nestedType)
455 }
456 case reflect.Interface:
457 panic("Interfaces are not supported in arch_variant properties")
458 }
459
460 fields = append(fields, field)
461 }
462 if len(fields) == 0 {
463 return nil, false
464 }
465
466 ret := reflect.StructOf(fields)
467 if ptr {
468 ret = reflect.PtrTo(ret)
469 }
470 return ret, true
471}
472
473func createArchType(props reflect.Type) reflect.Type {
474 props, ok := filterArchStruct(props)
475 if !ok {
476 return nil
477 }
478
479 variantFields := func(names []string) []reflect.StructField {
480 ret := make([]reflect.StructField, len(names))
481
482 for i, name := range names {
483 ret[i].Name = name
484 ret[i].Type = props
485 }
486
487 return ret
488 }
489
490 archFields := make([]reflect.StructField, len(archTypeList))
491 for i, arch := range archTypeList {
492 variants := []string{}
493
494 for _, archVariant := range archVariants[arch] {
Colin Cross0906f172017-04-26 14:00:43 -0700495 archVariant := variantReplacer.Replace(archVariant)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700496 variants = append(variants, proptools.FieldNameForProperty(archVariant))
497 }
498 for _, feature := range archFeatures[arch] {
Colin Cross0906f172017-04-26 14:00:43 -0700499 feature := variantReplacer.Replace(feature)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700500 variants = append(variants, proptools.FieldNameForProperty(feature))
501 }
502
503 fields := variantFields(variants)
504
505 fields = append([]reflect.StructField{reflect.StructField{
506 Name: "BlueprintEmbed",
507 Type: props,
508 Anonymous: true,
509 }}, fields...)
510
511 archFields[i] = reflect.StructField{
512 Name: arch.Field,
513 Type: reflect.StructOf(fields),
514 }
515 }
516 archType := reflect.StructOf(archFields)
517
518 multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"}))
519
520 targets := []string{
521 "Host",
522 "Android64",
523 "Android32",
Dan Willemsen866b5632017-09-22 12:28:24 -0700524 "Bionic",
Dan Willemsen86fc1eb2017-10-02 20:32:35 -0700525 "Linux",
Dan Willemsenb1957a52016-06-23 23:44:54 -0700526 "Not_windows",
Colin Crossbb2e2b72016-12-08 17:23:53 -0800527 "Arm_on_x86",
528 "Arm_on_x86_64",
Dan Willemsenb1957a52016-06-23 23:44:54 -0700529 }
530 for _, os := range osTypeList {
531 targets = append(targets, os.Field)
532
533 for _, archType := range osArchTypeMap[os] {
534 targets = append(targets, os.Field+"_"+archType.Name)
Dan Willemsen866b5632017-09-22 12:28:24 -0700535
Dan Willemsen86fc1eb2017-10-02 20:32:35 -0700536 if os.Linux() {
Dan Willemsen866b5632017-09-22 12:28:24 -0700537 target := "Linux_" + archType.Name
Colin Crossb4330e22017-12-22 15:47:09 -0800538 if !InList(target, targets) {
Dan Willemsen866b5632017-09-22 12:28:24 -0700539 targets = append(targets, target)
540 }
541 }
542 if os.Bionic() {
543 target := "Bionic_" + archType.Name
Colin Crossb4330e22017-12-22 15:47:09 -0800544 if !InList(target, targets) {
Dan Willemsen866b5632017-09-22 12:28:24 -0700545 targets = append(targets, target)
546 }
547 }
Dan Willemsenb1957a52016-06-23 23:44:54 -0700548 }
549 }
550
551 targetType := reflect.StructOf(variantFields(targets))
552 return reflect.StructOf([]reflect.StructField{
553 reflect.StructField{
554 Name: "Arch",
555 Type: archType,
556 },
557 reflect.StructField{
558 Name: "Multilib",
559 Type: multilibType,
560 },
561 reflect.StructField{
562 Name: "Target",
563 Type: targetType,
564 },
565 })
566}
567
568var archPropTypeMap OncePer
569
Colin Cross36242852017-06-23 15:06:31 -0700570func InitArchModule(m Module) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800571
572 base := m.base()
573
Colin Cross36242852017-06-23 15:06:31 -0700574 base.generalProperties = m.GetProperties()
Colin Cross3f40fa42015-01-30 17:27:36 -0800575
576 for _, properties := range base.generalProperties {
577 propertiesValue := reflect.ValueOf(properties)
Colin Cross62496a02016-08-08 15:49:17 -0700578 t := propertiesValue.Type()
Colin Cross3f40fa42015-01-30 17:27:36 -0800579 if propertiesValue.Kind() != reflect.Ptr {
Colin Crossca860ac2016-01-04 14:34:37 -0800580 panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
581 propertiesValue.Interface()))
Colin Cross3f40fa42015-01-30 17:27:36 -0800582 }
583
584 propertiesValue = propertiesValue.Elem()
585 if propertiesValue.Kind() != reflect.Struct {
Colin Crossca860ac2016-01-04 14:34:37 -0800586 panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
587 propertiesValue.Interface()))
Colin Cross3f40fa42015-01-30 17:27:36 -0800588 }
589
Dan Willemsenb1957a52016-06-23 23:44:54 -0700590 archPropType := archPropTypeMap.Once(t, func() interface{} {
591 return createArchType(t)
Colin Cross3f40fa42015-01-30 17:27:36 -0800592 })
593
Dan Willemsenb1957a52016-06-23 23:44:54 -0700594 if archPropType != nil {
595 base.archProperties = append(base.archProperties, reflect.New(archPropType.(reflect.Type)).Interface())
596 } else {
597 base.archProperties = append(base.archProperties, nil)
598 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800599 }
600
Colin Cross3f40fa42015-01-30 17:27:36 -0800601 for _, asp := range base.archProperties {
Dan Willemsenb1957a52016-06-23 23:44:54 -0700602 if asp != nil {
Colin Cross36242852017-06-23 15:06:31 -0700603 m.AddProperties(asp)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700604 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800605 }
606
Colin Cross36242852017-06-23 15:06:31 -0700607 base.customizableProperties = m.GetProperties()
Colin Cross3f40fa42015-01-30 17:27:36 -0800608}
609
Colin Crossa716add2015-12-16 11:07:39 -0800610var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
Colin Crossec193632015-07-06 17:49:43 -0700611
Colin Cross635c3b02016-05-18 15:37:25 -0700612func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
Dan Willemsenb1957a52016-06-23 23:44:54 -0700613 dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value {
Colin Cross06a931b2015-10-28 17:23:31 -0700614
Dan Willemsenb1957a52016-06-23 23:44:54 -0700615 src = src.FieldByName(field)
616 if !src.IsValid() {
Colin Crosseeabb892015-11-20 13:07:51 -0800617 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Dan Willemsenb1957a52016-06-23 23:44:54 -0700618 return src
Colin Cross85a88972015-11-23 13:29:51 -0800619 }
620
Dan Willemsenb1957a52016-06-23 23:44:54 -0700621 ret := src
Colin Cross85a88972015-11-23 13:29:51 -0800622
Dan Willemsenb1957a52016-06-23 23:44:54 -0700623 if src.Kind() == reflect.Struct {
624 src = src.FieldByName("BlueprintEmbed")
Colin Cross06a931b2015-10-28 17:23:31 -0700625 }
626
Colin Cross6ee75b62016-05-05 15:57:15 -0700627 order := func(property string,
628 dstField, srcField reflect.StructField,
629 dstValue, srcValue interface{}) (proptools.Order, error) {
630 if proptools.HasTag(dstField, "android", "variant_prepend") {
631 return proptools.Prepend, nil
632 } else {
633 return proptools.Append, nil
634 }
635 }
636
Dan Willemsenb1957a52016-06-23 23:44:54 -0700637 err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, order)
Colin Cross06a931b2015-10-28 17:23:31 -0700638 if err != nil {
639 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
640 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
641 } else {
642 panic(err)
643 }
644 }
Colin Cross85a88972015-11-23 13:29:51 -0800645
Dan Willemsenb1957a52016-06-23 23:44:54 -0700646 return ret
Colin Cross06a931b2015-10-28 17:23:31 -0700647}
648
Colin Cross3f40fa42015-01-30 17:27:36 -0800649// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross635c3b02016-05-18 15:37:25 -0700650func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700651 arch := a.Arch()
652 os := a.Os()
Colin Crossd3ba0392015-05-07 14:11:29 -0700653
Colin Cross3f40fa42015-01-30 17:27:36 -0800654 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700655 genProps := a.generalProperties[i]
Dan Willemsenb1957a52016-06-23 23:44:54 -0700656 if a.archProperties[i] == nil {
657 continue
658 }
659 archProps := reflect.ValueOf(a.archProperties[i]).Elem()
660
661 archProp := archProps.FieldByName("Arch")
662 multilibProp := archProps.FieldByName("Multilib")
663 targetProp := archProps.FieldByName("Target")
664
Colin Crossd5934c82017-10-02 13:55:26 -0700665 var field string
666 var prefix string
667
Colin Cross3f40fa42015-01-30 17:27:36 -0800668 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700669 // arch: {
670 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800671 // key: value,
672 // },
673 // },
674 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700675
Colin Crossd5934c82017-10-02 13:55:26 -0700676 if arch.ArchType != Common {
677 field := proptools.FieldNameForProperty(t.Name)
678 prefix := "arch." + t.Name
679 archStruct := a.appendProperties(ctx, genProps, archProp, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700680
Colin Crossd5934c82017-10-02 13:55:26 -0700681 // Handle arch-variant-specific properties in the form:
682 // arch: {
683 // variant: {
684 // key: value,
685 // },
686 // },
687 v := variantReplacer.Replace(arch.ArchVariant)
688 if v != "" {
689 field := proptools.FieldNameForProperty(v)
690 prefix := "arch." + t.Name + "." + v
Colin Cross08016332016-12-20 09:53:14 -0800691 a.appendProperties(ctx, genProps, archStruct, field, prefix)
692 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800693
Colin Crossd5934c82017-10-02 13:55:26 -0700694 // Handle cpu-variant-specific properties in the form:
695 // arch: {
696 // variant: {
697 // key: value,
698 // },
699 // },
700 if arch.CpuVariant != arch.ArchVariant {
701 c := variantReplacer.Replace(arch.CpuVariant)
702 if c != "" {
703 field := proptools.FieldNameForProperty(c)
704 prefix := "arch." + t.Name + "." + c
705 a.appendProperties(ctx, genProps, archStruct, field, prefix)
706 }
707 }
Colin Crossc5c24ad2015-11-20 15:35:00 -0800708
Colin Crossd5934c82017-10-02 13:55:26 -0700709 // Handle arch-feature-specific properties in the form:
710 // arch: {
711 // feature: {
712 // key: value,
713 // },
714 // },
715 for _, feature := range arch.ArchFeatures {
716 field := proptools.FieldNameForProperty(feature)
717 prefix := "arch." + t.Name + "." + feature
718 a.appendProperties(ctx, genProps, archStruct, field, prefix)
719 }
720
721 // Handle multilib-specific properties in the form:
722 // multilib: {
723 // lib32: {
724 // key: value,
725 // },
726 // },
727 field = proptools.FieldNameForProperty(t.Multilib)
728 prefix = "multilib." + t.Multilib
729 a.appendProperties(ctx, genProps, multilibProp, field, prefix)
730 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800731
Colin Crossa1ad8d12016-06-01 17:09:44 -0700732 // Handle host-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700733 // target: {
734 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800735 // key: value,
736 // },
737 // },
Colin Crossa1ad8d12016-06-01 17:09:44 -0700738 if os.Class == Host || os.Class == HostCross {
739 field = "Host"
740 prefix = "target.host"
Dan Willemsenb1957a52016-06-23 23:44:54 -0700741 a.appendProperties(ctx, genProps, targetProp, field, prefix)
Colin Crossa1ad8d12016-06-01 17:09:44 -0700742 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800743
Dan Willemsen866b5632017-09-22 12:28:24 -0700744 // Handle target OS generalities of the form:
745 // target: {
746 // bionic: {
747 // key: value,
748 // },
749 // bionic_x86: {
750 // key: value,
751 // },
752 // }
Dan Willemsen86fc1eb2017-10-02 20:32:35 -0700753 if os.Linux() {
Dan Willemsen866b5632017-09-22 12:28:24 -0700754 field = "Linux"
755 prefix = "target.linux"
756 a.appendProperties(ctx, genProps, targetProp, field, prefix)
757
Colin Crossd5934c82017-10-02 13:55:26 -0700758 if arch.ArchType != Common {
759 field = "Linux_" + arch.ArchType.Name
760 prefix = "target.linux_" + arch.ArchType.Name
761 a.appendProperties(ctx, genProps, targetProp, field, prefix)
762 }
Dan Willemsen866b5632017-09-22 12:28:24 -0700763 }
764
765 if os.Bionic() {
766 field = "Bionic"
767 prefix = "target.bionic"
768 a.appendProperties(ctx, genProps, targetProp, field, prefix)
769
Colin Crossd5934c82017-10-02 13:55:26 -0700770 if arch.ArchType != Common {
771 field = "Bionic_" + t.Name
772 prefix = "target.bionic_" + t.Name
773 a.appendProperties(ctx, genProps, targetProp, field, prefix)
774 }
Dan Willemsen866b5632017-09-22 12:28:24 -0700775 }
776
Colin Crossa1ad8d12016-06-01 17:09:44 -0700777 // Handle target OS properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700778 // target: {
Dan Willemsen866b5632017-09-22 12:28:24 -0700779 // linux_glibc: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800780 // key: value,
781 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700782 // not_windows: {
783 // key: value,
784 // },
Dan Willemsen866b5632017-09-22 12:28:24 -0700785 // linux_glibc_x86: {
Colin Crossb05bff22015-04-30 15:08:04 -0700786 // key: value,
787 // },
Dan Willemsen866b5632017-09-22 12:28:24 -0700788 // linux_glibc_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800789 // key: value,
790 // },
Colin Crossa1ad8d12016-06-01 17:09:44 -0700791 // android {
792 // key: value,
793 // },
794 // android_arm {
795 // key: value,
796 // },
797 // android_x86 {
798 // key: value,
799 // },
Colin Cross3f40fa42015-01-30 17:27:36 -0800800 // },
Colin Crossa1ad8d12016-06-01 17:09:44 -0700801 field = os.Field
802 prefix = "target." + os.Name
Dan Willemsenb1957a52016-06-23 23:44:54 -0700803 a.appendProperties(ctx, genProps, targetProp, field, prefix)
Colin Crossb9db4802016-06-03 01:50:47 +0000804
Colin Crossd5934c82017-10-02 13:55:26 -0700805 if arch.ArchType != Common {
806 field = os.Field + "_" + t.Name
807 prefix = "target." + os.Name + "_" + t.Name
808 a.appendProperties(ctx, genProps, targetProp, field, prefix)
809 }
Colin Crossb9db4802016-06-03 01:50:47 +0000810
Colin Crossa1ad8d12016-06-01 17:09:44 -0700811 if (os.Class == Host || os.Class == HostCross) && os != Windows {
812 field := "Not_windows"
813 prefix := "target.not_windows"
Dan Willemsenb1957a52016-06-23 23:44:54 -0700814 a.appendProperties(ctx, genProps, targetProp, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800815 }
816
Colin Crossf8209412015-03-26 14:44:26 -0700817 // Handle 64-bit device properties in the form:
818 // target {
819 // android64 {
820 // key: value,
821 // },
822 // android32 {
823 // key: value,
824 // },
825 // },
826 // WARNING: this is probably not what you want to use in your blueprints file, it selects
827 // options for all targets on a device that supports 64-bit binaries, not just the targets
828 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
829 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
Colin Crossa1ad8d12016-06-01 17:09:44 -0700830 if os.Class == Device {
Colin Cross6510f912017-11-29 00:27:14 -0800831 if ctx.Config().Android64() {
Colin Cross06a931b2015-10-28 17:23:31 -0700832 field := "Android64"
833 prefix := "target.android64"
Dan Willemsenb1957a52016-06-23 23:44:54 -0700834 a.appendProperties(ctx, genProps, targetProp, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700835 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700836 field := "Android32"
837 prefix := "target.android32"
Dan Willemsenb1957a52016-06-23 23:44:54 -0700838 a.appendProperties(ctx, genProps, targetProp, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700839 }
Colin Crossbb2e2b72016-12-08 17:23:53 -0800840
Victor Khimenko5eb8ec12018-03-21 20:30:54 +0100841 if (arch.ArchType == X86 && (hasArmAbi(arch) ||
842 hasArmAndroidArch(ctx.Config().Targets[Device]))) ||
843 (arch.ArchType == Arm &&
844 hasX86AndroidArch(ctx.Config().Targets[Device])) {
Colin Cross4247f0d2017-04-13 16:56:14 -0700845 field := "Arm_on_x86"
846 prefix := "target.arm_on_x86"
847 a.appendProperties(ctx, genProps, targetProp, field, prefix)
848 }
Victor Khimenko5eb8ec12018-03-21 20:30:54 +0100849 if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
850 hasArmAndroidArch(ctx.Config().Targets[Device]))) ||
851 (arch.ArchType == Arm &&
852 hasX8664AndroidArch(ctx.Config().Targets[Device])) {
Colin Cross4247f0d2017-04-13 16:56:14 -0700853 field := "Arm_on_x86_64"
854 prefix := "target.arm_on_x86_64"
855 a.appendProperties(ctx, genProps, targetProp, field, prefix)
856 }
Colin Crossbb2e2b72016-12-08 17:23:53 -0800857 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800858 }
859}
860
861func forEachInterface(v reflect.Value, f func(reflect.Value)) {
862 switch v.Kind() {
863 case reflect.Interface:
864 f(v)
865 case reflect.Struct:
866 for i := 0; i < v.NumField(); i++ {
867 forEachInterface(v.Field(i), f)
868 }
869 case reflect.Ptr:
870 forEachInterface(v.Elem(), f)
871 default:
872 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
873 }
874}
Colin Cross4225f652015-09-17 14:33:42 -0700875
Colin Crossa1ad8d12016-06-01 17:09:44 -0700876// Convert the arch product variables into a list of targets for each os class structs
Colin Cross9272ade2016-08-17 15:24:12 -0700877func decodeTargetProductVariables(config *config) (map[OsClass][]Target, error) {
Dan Willemsen45133ac2018-03-09 21:22:06 -0800878 variables := config.productVariables
Dan Willemsen490fd492015-11-24 17:53:15 -0800879
Colin Crossa1ad8d12016-06-01 17:09:44 -0700880 targets := make(map[OsClass][]Target)
881 var targetErr error
882
883 addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi *[]string) {
884 if targetErr != nil {
885 return
Dan Willemsen490fd492015-11-24 17:53:15 -0800886 }
Colin Crossa1ad8d12016-06-01 17:09:44 -0700887
888 arch, err := decodeArch(archName, archVariant, cpuVariant, abi)
889 if err != nil {
890 targetErr = err
891 return
892 }
893
894 targets[os.Class] = append(targets[os.Class],
895 Target{
896 Os: os,
897 Arch: arch,
898 })
Dan Willemsen490fd492015-11-24 17:53:15 -0800899 }
900
Colin Cross4225f652015-09-17 14:33:42 -0700901 if variables.HostArch == nil {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700902 return nil, fmt.Errorf("No host primary architecture set")
Colin Cross4225f652015-09-17 14:33:42 -0700903 }
904
Colin Crossa1ad8d12016-06-01 17:09:44 -0700905 addTarget(BuildOs, *variables.HostArch, nil, nil, nil)
Colin Cross4225f652015-09-17 14:33:42 -0700906
Colin Crosseeabb892015-11-20 13:07:51 -0800907 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700908 addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil)
Dan Willemsen490fd492015-11-24 17:53:15 -0800909 }
910
Colin Crossff3ae9d2018-04-10 16:15:18 -0700911 if Bool(config.Host_bionic) {
Dan Willemsen01a405a2016-06-13 17:19:03 -0700912 addTarget(LinuxBionic, "x86_64", nil, nil, nil)
913 }
914
Colin Crossff3ae9d2018-04-10 16:15:18 -0700915 if String(variables.CrossHost) != "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700916 crossHostOs := osByName(*variables.CrossHost)
917 if crossHostOs == NoOsType {
918 return nil, fmt.Errorf("Unknown cross host OS %q", *variables.CrossHost)
919 }
920
Colin Crossff3ae9d2018-04-10 16:15:18 -0700921 if String(variables.CrossHostArch) == "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700922 return nil, fmt.Errorf("No cross-host primary architecture set")
Dan Willemsen490fd492015-11-24 17:53:15 -0800923 }
924
Colin Crossa1ad8d12016-06-01 17:09:44 -0700925 addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil)
Dan Willemsen490fd492015-11-24 17:53:15 -0800926
927 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700928 addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil)
Dan Willemsen490fd492015-11-24 17:53:15 -0800929 }
930 }
931
Dan Willemsen3f32f032016-07-11 14:36:48 -0700932 if variables.DeviceArch != nil && *variables.DeviceArch != "" {
933 addTarget(Android, *variables.DeviceArch, variables.DeviceArchVariant,
934 variables.DeviceCpuVariant, variables.DeviceAbi)
Colin Cross4225f652015-09-17 14:33:42 -0700935
Dan Willemsen3f32f032016-07-11 14:36:48 -0700936 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
937 addTarget(Android, *variables.DeviceSecondaryArch,
938 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
939 variables.DeviceSecondaryAbi)
Colin Cross4225f652015-09-17 14:33:42 -0700940
Dan Willemsen3f32f032016-07-11 14:36:48 -0700941 deviceArches := targets[Device]
942 if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
943 deviceArches[1].Arch.Native = false
944 }
Colin Cross4225f652015-09-17 14:33:42 -0700945 }
Colin Cross4225f652015-09-17 14:33:42 -0700946 }
947
Colin Crossa1ad8d12016-06-01 17:09:44 -0700948 if targetErr != nil {
949 return nil, targetErr
950 }
951
952 return targets, nil
Colin Cross4225f652015-09-17 14:33:42 -0700953}
954
Colin Crossbb2e2b72016-12-08 17:23:53 -0800955// hasArmAbi returns true if arch has at least one arm ABI
956func hasArmAbi(arch Arch) bool {
957 for _, abi := range arch.Abi {
958 if strings.HasPrefix(abi, "arm") {
959 return true
960 }
961 }
962 return false
963}
964
Colin Cross4247f0d2017-04-13 16:56:14 -0700965// hasArmArch returns true if targets has at least arm Android arch
966func hasArmAndroidArch(targets []Target) bool {
967 for _, target := range targets {
968 if target.Os == Android && target.Arch.ArchType == Arm {
969 return true
970 }
971 }
972 return false
973}
974
Victor Khimenko5eb8ec12018-03-21 20:30:54 +0100975// hasX86Arch returns true if targets has at least x86 Android arch
976func hasX86AndroidArch(targets []Target) bool {
977 for _, target := range targets {
978 if target.Os == Android && target.Arch.ArchType == X86 {
979 return true
980 }
981 }
982 return false
983}
984
985// hasX8664Arch returns true if targets has at least x86_64 Android arch
986func hasX8664AndroidArch(targets []Target) bool {
987 for _, target := range targets {
988 if target.Os == Android && target.Arch.ArchType == X86_64 {
989 return true
990 }
991 }
992 return false
993}
994
Dan Albert4098deb2016-10-19 14:04:41 -0700995type archConfig struct {
996 arch string
997 archVariant string
998 cpuVariant string
999 abi []string
1000}
1001
1002func getMegaDeviceConfig() []archConfig {
1003 return []archConfig{
Dan Willemsen110a89d2016-01-14 15:17:19 -08001004 {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
1005 {"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001006 {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
1007 {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -08001008 {"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001009 {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}},
1010 {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}},
1011 {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}},
Richard Fungeb37ed32018-09-24 16:33:45 -07001012 {"arm", "armv7-a-neon", "cortex-a72", []string{"armeabi-v7a"}},
Jake Weinstein6600a442017-05-15 18:27:12 -04001013 {"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}},
Christopher Ferrisba14a8f2018-04-23 18:15:25 -07001014 {"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}},
Haibo Huanga31e2bd2018-10-09 14:27:28 -07001015 {"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001016 {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
1017 {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
Alex Naidisae4fc182016-08-20 00:14:56 +02001018 {"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
Junmo Park8ea49592017-07-24 07:14:55 +09001019 {"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}},
Junmo Parkd86c9022017-07-21 09:07:47 +09001020 {"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -08001021 {"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
Richard Fungeb37ed32018-09-24 16:33:45 -07001022 {"arm64", "armv8-a", "cortex-a72", []string{"arm64-v8a"}},
Jake Weinstein6600a442017-05-15 18:27:12 -04001023 {"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -08001024 {"arm64", "armv8-a", "denver64", []string{"arm64-v8a"}},
Alex Naidisac01ff52016-08-30 15:56:33 +02001025 {"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}},
Junmo Park8ea49592017-07-24 07:14:55 +09001026 {"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}},
Junmo Parkd86c9022017-07-21 09:07:47 +09001027 {"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
Christopher Ferrisba14a8f2018-04-23 18:15:25 -07001028 {"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
Haibo Huanga31e2bd2018-10-09 14:27:28 -07001029 {"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
Dan Willemsen468cc312016-01-13 23:25:19 -08001030 {"mips", "mips32-fp", "", []string{"mips"}},
1031 {"mips", "mips32r2-fp", "", []string{"mips"}},
1032 {"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
Dan Willemsen65fb9812016-07-19 21:37:28 -07001033 //{"mips", "mips32r6", "", []string{"mips"}},
Colin Cross1837b802017-04-26 19:10:34 -07001034 {"mips", "mips32r2dsp-fp", "", []string{"mips"}},
1035 {"mips", "mips32r2dspr2-fp", "", []string{"mips"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001036 // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc
1037 //{"mips64", "mips64r2", "", []string{"mips64"}},
1038 {"mips64", "mips64r6", "", []string{"mips64"}},
1039 {"x86", "", "", []string{"x86"}},
1040 {"x86", "atom", "", []string{"x86"}},
1041 {"x86", "haswell", "", []string{"x86"}},
1042 {"x86", "ivybridge", "", []string{"x86"}},
1043 {"x86", "sandybridge", "", []string{"x86"}},
1044 {"x86", "silvermont", "", []string{"x86"}},
Dan Willemsen8a354052016-05-10 14:30:51 -07001045 {"x86", "x86_64", "", []string{"x86"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -08001046 {"x86_64", "", "", []string{"x86_64"}},
1047 {"x86_64", "haswell", "", []string{"x86_64"}},
1048 {"x86_64", "ivybridge", "", []string{"x86_64"}},
1049 {"x86_64", "sandybridge", "", []string{"x86_64"}},
1050 {"x86_64", "silvermont", "", []string{"x86_64"}},
1051 }
Dan Albert4098deb2016-10-19 14:04:41 -07001052}
Dan Willemsen322acaf2016-01-12 23:07:05 -08001053
Dan Albert4098deb2016-10-19 14:04:41 -07001054func getNdkAbisConfig() []archConfig {
1055 return []archConfig{
Dan Albertd3c8ca42017-12-20 14:48:39 -08001056 {"arm", "armv7-a", "", []string{"armeabi"}},
Dan Albert4098deb2016-10-19 14:04:41 -07001057 {"arm64", "armv8-a", "", []string{"arm64-v8a"}},
Dan Albert4098deb2016-10-19 14:04:41 -07001058 {"x86", "", "", []string{"x86"}},
1059 {"x86_64", "", "", []string{"x86_64"}},
1060 }
1061}
1062
1063func decodeArchSettings(archConfigs []archConfig) ([]Target, error) {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001064 var ret []Target
Dan Willemsen322acaf2016-01-12 23:07:05 -08001065
Dan Albert4098deb2016-10-19 14:04:41 -07001066 for _, config := range archConfigs {
Dan Willemsen322acaf2016-01-12 23:07:05 -08001067 arch, err := decodeArch(config.arch, &config.archVariant,
1068 &config.cpuVariant, &config.abi)
1069 if err != nil {
1070 return nil, err
1071 }
Dan Willemsen17f05262016-05-31 16:27:00 -07001072 arch.Native = false
Colin Crossa1ad8d12016-06-01 17:09:44 -07001073 ret = append(ret, Target{
1074 Os: Android,
1075 Arch: arch,
1076 })
Dan Willemsen322acaf2016-01-12 23:07:05 -08001077 }
1078
1079 return ret, nil
1080}
1081
Colin Cross4225f652015-09-17 14:33:42 -07001082// Convert a set of strings from product variables into a single Arch struct
1083func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
1084 stringPtr := func(p *string) string {
1085 if p != nil {
1086 return *p
1087 }
1088 return ""
1089 }
1090
1091 slicePtr := func(p *[]string) []string {
1092 if p != nil {
1093 return *p
1094 }
1095 return nil
1096 }
1097
Colin Crosseeabb892015-11-20 13:07:51 -08001098 archType, ok := archTypeMap[arch]
1099 if !ok {
1100 return Arch{}, fmt.Errorf("unknown arch %q", arch)
1101 }
Colin Cross4225f652015-09-17 14:33:42 -07001102
Colin Crosseeabb892015-11-20 13:07:51 -08001103 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -07001104 ArchType: archType,
1105 ArchVariant: stringPtr(archVariant),
1106 CpuVariant: stringPtr(cpuVariant),
1107 Abi: slicePtr(abi),
Dan Willemsen17f05262016-05-31 16:27:00 -07001108 Native: true,
Colin Crosseeabb892015-11-20 13:07:51 -08001109 }
1110
1111 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
1112 a.ArchVariant = ""
1113 }
1114
1115 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
1116 a.CpuVariant = ""
1117 }
1118
1119 for i := 0; i < len(a.Abi); i++ {
1120 if a.Abi[i] == "" {
1121 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
1122 i--
1123 }
1124 }
1125
Colin Crossc5c24ad2015-11-20 15:35:00 -08001126 if featureMap, ok := archFeatureMap[archType]; ok {
Dan Willemsenb4850992016-05-06 17:21:20 -07001127 a.ArchFeatures = featureMap[a.ArchVariant]
Colin Crossc5c24ad2015-11-20 15:35:00 -08001128 }
1129
Colin Crosseeabb892015-11-20 13:07:51 -08001130 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -07001131}
1132
Colin Cross69617d32016-09-06 10:39:07 -07001133func filterMultilibTargets(targets []Target, multilib string) []Target {
1134 var ret []Target
1135 for _, t := range targets {
1136 if t.Arch.ArchType.Multilib == multilib {
1137 ret = append(ret, t)
1138 }
1139 }
1140 return ret
1141}
1142
Nan Zhangdb0b9a32017-02-27 10:12:13 -08001143func getCommonTargets(targets []Target) []Target {
1144 var ret []Target
1145 set := make(map[string]bool)
1146
1147 for _, t := range targets {
1148 if _, found := set[t.Os.String()]; !found {
1149 set[t.Os.String()] = true
1150 ret = append(ret, commonTargetMap[t.Os.String()])
1151 }
1152 }
1153
1154 return ret
1155}
1156
Colin Cross3dceee32018-09-06 10:19:57 -07001157func firstTarget(targets []Target, filters ...string) []Target {
Colin Cross6b4a32d2017-12-05 13:42:45 -08001158 for _, filter := range filters {
1159 buildTargets := filterMultilibTargets(targets, filter)
1160 if len(buildTargets) > 0 {
Colin Cross3dceee32018-09-06 10:19:57 -07001161 return buildTargets[:1]
Colin Cross6b4a32d2017-12-05 13:42:45 -08001162 }
1163 }
1164 return nil
1165}
1166
Colin Crossa1ad8d12016-06-01 17:09:44 -07001167// Use the module multilib setting to select one or more targets from a target list
Colin Crossee0bc3b2018-10-02 22:01:37 -07001168func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001169 buildTargets := []Target{}
Colin Cross6b4a32d2017-12-05 13:42:45 -08001170
Colin Cross4225f652015-09-17 14:33:42 -07001171 switch multilib {
1172 case "common":
Colin Cross6b4a32d2017-12-05 13:42:45 -08001173 buildTargets = getCommonTargets(targets)
1174 case "common_first":
1175 buildTargets = getCommonTargets(targets)
1176 if prefer32 {
Colin Cross3dceee32018-09-06 10:19:57 -07001177 buildTargets = append(buildTargets, firstTarget(targets, "lib32", "lib64")...)
Colin Cross6b4a32d2017-12-05 13:42:45 -08001178 } else {
Colin Cross3dceee32018-09-06 10:19:57 -07001179 buildTargets = append(buildTargets, firstTarget(targets, "lib64", "lib32")...)
Colin Cross6b4a32d2017-12-05 13:42:45 -08001180 }
Colin Cross4225f652015-09-17 14:33:42 -07001181 case "both":
Colin Cross8b74d172016-09-13 09:59:14 -07001182 if prefer32 {
1183 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
1184 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
1185 } else {
1186 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
1187 buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
1188 }
Colin Cross4225f652015-09-17 14:33:42 -07001189 case "32":
Colin Cross69617d32016-09-06 10:39:07 -07001190 buildTargets = filterMultilibTargets(targets, "lib32")
Colin Cross4225f652015-09-17 14:33:42 -07001191 case "64":
Colin Cross69617d32016-09-06 10:39:07 -07001192 buildTargets = filterMultilibTargets(targets, "lib64")
Colin Cross6b4a32d2017-12-05 13:42:45 -08001193 case "first":
1194 if prefer32 {
Colin Cross3dceee32018-09-06 10:19:57 -07001195 buildTargets = firstTarget(targets, "lib32", "lib64")
Colin Cross6b4a32d2017-12-05 13:42:45 -08001196 } else {
Colin Cross3dceee32018-09-06 10:19:57 -07001197 buildTargets = firstTarget(targets, "lib64", "lib32")
Colin Cross6b4a32d2017-12-05 13:42:45 -08001198 }
Colin Cross69617d32016-09-06 10:39:07 -07001199 case "prefer32":
Colin Cross3dceee32018-09-06 10:19:57 -07001200 buildTargets = filterMultilibTargets(targets, "lib32")
1201 if len(buildTargets) == 0 {
1202 buildTargets = filterMultilibTargets(targets, "lib64")
1203 }
Colin Cross4225f652015-09-17 14:33:42 -07001204 default:
Colin Cross69617d32016-09-06 10:39:07 -07001205 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", or "prefer32" found %q`,
Colin Cross4225f652015-09-17 14:33:42 -07001206 multilib)
Colin Cross4225f652015-09-17 14:33:42 -07001207 }
1208
Colin Crossa1ad8d12016-06-01 17:09:44 -07001209 return buildTargets, nil
Colin Cross4225f652015-09-17 14:33:42 -07001210}