blob: 4dd01c30a8da3cd458ff6ab17804e2d1d9b04bfc [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
15package common
16
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 Cross463a90e2015-06-17 14:20:06 -070023 "android/soong"
24
Colin Crossf6566ed2015-03-24 11:13:38 -070025 "github.com/google/blueprint"
26 "github.com/google/blueprint/proptools"
Colin Cross3f40fa42015-01-30 17:27:36 -080027)
28
Colin Cross463a90e2015-06-17 14:20:06 -070029func init() {
30 soong.RegisterEarlyMutator("host_or_device", HostOrDeviceMutator)
31 soong.RegisterEarlyMutator("arch", ArchMutator)
32}
33
Colin Cross3f40fa42015-01-30 17:27:36 -080034var (
Colin Crossec193632015-07-06 17:49:43 -070035 Arm = newArch("arm", "lib32")
36 Arm64 = newArch("arm64", "lib64")
37 Mips = newArch("mips", "lib32")
38 Mips64 = newArch("mips64", "lib64")
39 X86 = newArch("x86", "lib32")
40 X86_64 = newArch("x86_64", "lib64")
Colin Cross2fe66872015-03-30 17:20:39 -070041
42 Common = ArchType{
43 Name: "common",
44 }
Colin Cross3f40fa42015-01-30 17:27:36 -080045)
46
Colin Cross4225f652015-09-17 14:33:42 -070047var archTypeMap = map[string]ArchType{
48 "arm": Arm,
49 "arm64": Arm64,
50 "mips": Mips,
51 "misp64": Mips64,
52 "x86": X86,
53 "x86_64": X86_64,
54}
55
Colin Cross3f40fa42015-01-30 17:27:36 -080056/*
57Example blueprints file containing all variant property groups, with comment listing what type
58of variants get properties in that group:
59
60module {
61 arch: {
62 arm: {
63 // Host or device variants with arm architecture
64 },
65 arm64: {
66 // Host or device variants with arm64 architecture
67 },
68 mips: {
69 // Host or device variants with mips architecture
70 },
71 mips64: {
72 // Host or device variants with mips64 architecture
73 },
74 x86: {
75 // Host or device variants with x86 architecture
76 },
77 x86_64: {
78 // Host or device variants with x86_64 architecture
79 },
80 },
81 multilib: {
82 lib32: {
83 // Host or device variants for 32-bit architectures
84 },
85 lib64: {
86 // Host or device variants for 64-bit architectures
87 },
88 },
89 target: {
90 android: {
91 // Device variants
92 },
93 host: {
94 // Host variants
95 },
96 linux: {
97 // Linux host variants
98 },
99 darwin: {
100 // Darwin host variants
101 },
102 windows: {
103 // Windows host variants
104 },
105 not_windows: {
106 // Non-windows host variants
107 },
108 },
109}
110*/
Colin Cross7d5136f2015-05-11 13:39:40 -0700111
Colin Cross3f40fa42015-01-30 17:27:36 -0800112type archProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700113 // Properties to vary by target architecture
Colin Cross3f40fa42015-01-30 17:27:36 -0800114 Arch struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700115 // Properties for module variants being built to run on arm (host or device)
116 Arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
117 // Properties for module variants being built to run on arm64 (host or device)
118 Arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
119 // Properties for module variants being built to run on mips (host or device)
120 Mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
121 // Properties for module variants being built to run on mips64 (host or device)
122 Mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
123 // Properties for module variants being built to run on x86 (host or device)
124 X86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
125 // Properties for module variants being built to run on x86_64 (host or device)
126 X86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700127
128 // Arm arch variants
129 Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"`
130 Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
131 Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"`
132
133 // Arm cpu variants
Dan Willemsen60c3dfb2015-10-16 17:29:12 -0700134 Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"`
135 Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"`
136 Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"`
137 Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"`
138 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
139 Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"`
140 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
141 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700142
143 // Arm64 cpu variants
Dan Willemsen60c3dfb2015-10-16 17:29:12 -0700144 Cortex_a53_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
145 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700146
147 // Mips arch variants
148 Mips_rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
149
Colin Cross01432f62015-07-09 17:56:26 -0700150 // X86 arch variants
Dan Willemsen96dc9f32015-10-16 16:31:15 -0700151 X86_ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6d27f342015-10-28 17:23:16 -0700152 X86_sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross01432f62015-07-09 17:56:26 -0700153
Colin Crossec193632015-07-06 17:49:43 -0700154 // X86 cpu variants
155 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
156 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800157 }
Colin Crossec193632015-07-06 17:49:43 -0700158
Colin Cross7d5136f2015-05-11 13:39:40 -0700159 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800160 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700161 // Properties for module variants being built to run on 32-bit devices
162 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
163 // Properties for module variants being built to run on 64-bit devices
164 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800165 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700166 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800167 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700168 // Properties for module variants being built to run on the host
169 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
170 // Properties for module variants being built to run on the device
171 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
172 // Properties for module variants being built to run on arm devices
173 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
174 // Properties for module variants being built to run on arm64 devices
175 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
176 // Properties for module variants being built to run on mips devices
177 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
178 // Properties for module variants being built to run on mips64 devices
179 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
180 // Properties for module variants being built to run on x86 devices
181 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
182 // Properties for module variants being built to run on x86_64 devices
183 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
184 // Properties for module variants being built to run on devices that support 64-bit
185 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
186 // Properties for module variants being built to run on devices that do not support 64-bit
187 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
188 // Properties for module variants being built to run on linux hosts
189 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
190 // Properties for module variants being built to run on linux x86 hosts
191 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
192 // Properties for module variants being built to run on linux x86_64 hosts
193 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
194 // Properties for module variants being built to run on darwin hosts
195 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 // Properties for module variants being built to run on darwin x86 hosts
197 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
198 // Properties for module variants being built to run on darwin x86_64 hosts
199 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
200 // Properties for module variants being built to run on windows hosts
201 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
202 // Properties for module variants being built to run on linux or darwin hosts
203 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800204 }
205}
206
207// An Arch indicates a single CPU architecture.
208type Arch struct {
Colin Crossd3ba0392015-05-07 14:11:29 -0700209 ArchType ArchType
210 ArchVariant string
211 CpuVariant string
Colin Cross4225f652015-09-17 14:33:42 -0700212 Abi []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800213}
214
215func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700216 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800217 if a.ArchVariant != "" {
218 s += "_" + a.ArchVariant
219 }
220 if a.CpuVariant != "" {
221 s += "_" + a.CpuVariant
222 }
223 return s
224}
225
226type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700227 Name string
228 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800229}
230
Colin Crossec193632015-07-06 17:49:43 -0700231func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800232 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700233 Name: name,
234 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800235 }
236}
237
238func (a ArchType) String() string {
239 return a.Name
240}
241
242type HostOrDeviceSupported int
243
244const (
245 _ HostOrDeviceSupported = iota
246 HostSupported
247 DeviceSupported
248 HostAndDeviceSupported
249)
250
251type HostOrDevice int
252
253const (
254 _ HostOrDevice = iota
255 Host
256 Device
257)
258
259func (hod HostOrDevice) String() string {
260 switch hod {
261 case Device:
262 return "device"
263 case Host:
264 return "host"
265 default:
266 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
267 }
268}
269
Colin Crossec193632015-07-06 17:49:43 -0700270func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800271 switch hod {
272 case Device:
273 return "android"
274 case Host:
275 return "host"
276 default:
277 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
278 }
279}
280
Colin Cross3f40fa42015-01-30 17:27:36 -0800281func (hod HostOrDevice) Host() bool {
282 if hod == 0 {
283 panic("HostOrDevice unset")
284 }
285 return hod == Host
286}
287
288func (hod HostOrDevice) Device() bool {
289 if hod == 0 {
290 panic("HostOrDevice unset")
291 }
292 return hod == Device
293}
294
295var hostOrDeviceName = map[HostOrDevice]string{
296 Device: "device",
297 Host: "host",
298}
299
300var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700301 commonArch = Arch{
302 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700303 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800304)
305
Colin Crossd3ba0392015-05-07 14:11:29 -0700306func HostOrDeviceMutator(mctx blueprint.EarlyMutatorContext) {
307 var module AndroidModule
308 var ok bool
309 if module, ok = mctx.Module().(AndroidModule); !ok {
310 return
311 }
312
313 hods := []HostOrDevice{}
314
315 if module.base().HostSupported() {
316 hods = append(hods, Host)
317 }
318
319 if module.base().DeviceSupported() {
320 hods = append(hods, Device)
321 }
322
323 if len(hods) == 0 {
324 return
325 }
326
327 hodNames := []string{}
328 for _, hod := range hods {
329 hodNames = append(hodNames, hod.String())
330 }
331
332 modules := mctx.CreateVariations(hodNames...)
333 for i, m := range modules {
334 m.(AndroidModule).base().SetHostOrDevice(hods[i])
335 }
336}
337
Colin Cross3f40fa42015-01-30 17:27:36 -0800338func ArchMutator(mctx blueprint.EarlyMutatorContext) {
339 var module AndroidModule
340 var ok bool
341 if module, ok = mctx.Module().(AndroidModule); !ok {
342 return
343 }
344
Colin Cross4225f652015-09-17 14:33:42 -0700345 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
346 if err != nil {
347 mctx.ModuleErrorf("%s", err.Error())
348 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800349
Colin Cross4225f652015-09-17 14:33:42 -0700350 moduleArches := []Arch{}
351 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800352
Colin Crossd3ba0392015-05-07 14:11:29 -0700353 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700354 hostModuleArches, err := decodeMultilib(multilib, hostArches)
355 if err != nil {
356 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700357 }
Colin Cross4225f652015-09-17 14:33:42 -0700358
359 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800360 }
361
Colin Crossd3ba0392015-05-07 14:11:29 -0700362 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700363 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
364 if err != nil {
365 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800366 }
Colin Cross4225f652015-09-17 14:33:42 -0700367
368 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800369 }
370
Colin Cross4225f652015-09-17 14:33:42 -0700371 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700372 return
373 }
374
Colin Cross3f40fa42015-01-30 17:27:36 -0800375 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700376 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800377 archNames = append(archNames, arch.String())
378 }
379
380 modules := mctx.CreateVariations(archNames...)
381
382 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700383 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700384 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800385 }
386}
387
Colin Crossc472d572015-03-17 15:06:21 -0700388func InitArchModule(m AndroidModule, defaultMultilib Multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800389 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
390
391 base := m.base()
392
Colin Crossc472d572015-03-17 15:06:21 -0700393 base.commonProperties.Compile_multilib = string(defaultMultilib)
Colin Cross3f40fa42015-01-30 17:27:36 -0800394
395 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800396 propertyStructs...)
397
398 for _, properties := range base.generalProperties {
399 propertiesValue := reflect.ValueOf(properties)
400 if propertiesValue.Kind() != reflect.Ptr {
401 panic("properties must be a pointer to a struct")
402 }
403
404 propertiesValue = propertiesValue.Elem()
405 if propertiesValue.Kind() != reflect.Struct {
406 panic("properties must be a pointer to a struct")
407 }
408
409 archProperties := &archProperties{}
410 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700411 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800412 v.Set(newValue)
413 })
414
415 base.archProperties = append(base.archProperties, archProperties)
416 }
417
418 var allProperties []interface{}
419 allProperties = append(allProperties, base.generalProperties...)
420 for _, asp := range base.archProperties {
421 allProperties = append(allProperties, asp)
422 }
423
424 return m, allProperties
425}
426
Colin Crossec193632015-07-06 17:49:43 -0700427var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
428
Colin Cross3f40fa42015-01-30 17:27:36 -0800429// Rewrite the module's properties structs to contain arch-specific values.
Colin Crossd3ba0392015-05-07 14:11:29 -0700430func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) {
431 arch := a.commonProperties.CompileArch
432 hod := a.commonProperties.CompileHostOrDevice
433
Colin Cross2fe66872015-03-30 17:20:39 -0700434 if arch.ArchType == Common {
435 return
436 }
437
Colin Cross7f64b6d2015-07-09 13:57:48 -0700438 callback := func(srcPropertyName, dstPropertyName string) {
439 a.extendedProperties[dstPropertyName] = struct{}{}
440 }
441
Colin Cross3f40fa42015-01-30 17:27:36 -0800442 for i := range a.generalProperties {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700443 generalPropsValue := []reflect.Value{reflect.ValueOf(a.generalProperties[i]).Elem()}
Colin Cross3f40fa42015-01-30 17:27:36 -0800444
445 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700446 // arch: {
447 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800448 // key: value,
449 // },
450 // },
451 t := arch.ArchType
Colin Crossec193632015-07-06 17:49:43 -0700452 field := proptools.FieldNameForProperty(t.Name)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700453 extendProperties(ctx, "arch_variant", "arch."+t.Name, generalPropsValue,
454 reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback)
Colin Crossec193632015-07-06 17:49:43 -0700455
456 // Handle arch-variant-specific properties in the form:
457 // arch: {
458 // variant: {
459 // key: value,
460 // },
461 // },
462 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
463 if v != "" {
464 field := proptools.FieldNameForProperty(v)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700465 extendProperties(ctx, "arch_variant", "arch."+v, generalPropsValue,
466 reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback)
Colin Crossec193632015-07-06 17:49:43 -0700467 }
468
469 // Handle cpu-variant-specific properties in the form:
470 // arch: {
471 // variant: {
472 // key: value,
473 // },
474 // },
475 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
476 if c != "" {
477 field := proptools.FieldNameForProperty(c)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700478 extendProperties(ctx, "arch_variant", "arch."+c, generalPropsValue,
479 reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback)
Colin Crossec193632015-07-06 17:49:43 -0700480 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800481
482 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700483 // multilib: {
484 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800485 // key: value,
486 // },
487 // },
Colin Crossec193632015-07-06 17:49:43 -0700488 multilibField := proptools.FieldNameForProperty(t.Multilib)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700489 extendProperties(ctx, "arch_variant", "multilib."+t.Multilib, generalPropsValue,
490 reflect.ValueOf(a.archProperties[i].Multilib).FieldByName(multilibField).Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800491
492 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700493 // target: {
494 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800495 // key: value,
496 // },
497 // },
Colin Crossec193632015-07-06 17:49:43 -0700498 hodProperty := hod.Property()
499 hodField := proptools.FieldNameForProperty(hodProperty)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700500 extendProperties(ctx, "arch_variant", "target."+hodProperty, generalPropsValue,
501 reflect.ValueOf(a.archProperties[i].Target).FieldByName(hodField).Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800502
503 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700504 // target: {
505 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800506 // key: value,
507 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700508 // not_windows: {
509 // key: value,
510 // },
511 // linux_x86: {
512 // key: value,
513 // },
514 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800515 // key: value,
516 // },
517 // },
518 var osList = []struct {
519 goos string
520 field string
521 }{
522 {"darwin", "Darwin"},
523 {"linux", "Linux"},
524 {"windows", "Windows"},
525 }
526
527 if hod.Host() {
528 for _, v := range osList {
529 if v.goos == runtime.GOOS {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700530 extendProperties(ctx, "arch_variant", "target."+v.goos, generalPropsValue,
531 reflect.ValueOf(a.archProperties[i].Target).FieldByName(v.field).Elem().Elem(), callback)
Colin Crossb05bff22015-04-30 15:08:04 -0700532 t := arch.ArchType
Colin Cross7f64b6d2015-07-09 13:57:48 -0700533 extendProperties(ctx, "arch_variant", "target."+v.goos+"_"+t.Name, generalPropsValue,
534 reflect.ValueOf(a.archProperties[i].Target).FieldByName(v.field+"_"+t.Name).Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800535 }
536 }
Colin Cross7f64b6d2015-07-09 13:57:48 -0700537 extendProperties(ctx, "arch_variant", "target.not_windows", generalPropsValue,
538 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Not_windows").Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800539 }
540
Colin Crossf8209412015-03-26 14:44:26 -0700541 // Handle 64-bit device properties in the form:
542 // target {
543 // android64 {
544 // key: value,
545 // },
546 // android32 {
547 // key: value,
548 // },
549 // },
550 // WARNING: this is probably not what you want to use in your blueprints file, it selects
551 // options for all targets on a device that supports 64-bit binaries, not just the targets
552 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
553 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
554 if hod.Device() {
555 if true /* && target_is_64_bit */ {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700556 extendProperties(ctx, "arch_variant", "target.android64", generalPropsValue,
557 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android64").Elem().Elem(), callback)
Colin Crossf8209412015-03-26 14:44:26 -0700558 } else {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700559 extendProperties(ctx, "arch_variant", "target.android32", generalPropsValue,
560 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android32").Elem().Elem(), callback)
Colin Crossf8209412015-03-26 14:44:26 -0700561 }
562 }
Colin Crossb05bff22015-04-30 15:08:04 -0700563
564 // Handle device architecture properties in the form:
565 // target {
566 // android_arm {
567 // key: value,
568 // },
569 // android_x86 {
570 // key: value,
571 // },
572 // },
573 if hod.Device() {
574 t := arch.ArchType
Colin Cross7f64b6d2015-07-09 13:57:48 -0700575 extendProperties(ctx, "arch_variant", "target.android_"+t.Name, generalPropsValue,
576 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android_"+t.Name).Elem().Elem(), callback)
Colin Crossb05bff22015-04-30 15:08:04 -0700577 }
578
Colin Cross3f40fa42015-01-30 17:27:36 -0800579 if ctx.Failed() {
580 return
581 }
582 }
583}
584
585func forEachInterface(v reflect.Value, f func(reflect.Value)) {
586 switch v.Kind() {
587 case reflect.Interface:
588 f(v)
589 case reflect.Struct:
590 for i := 0; i < v.NumField(); i++ {
591 forEachInterface(v.Field(i), f)
592 }
593 case reflect.Ptr:
594 forEachInterface(v.Elem(), f)
595 default:
596 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
597 }
598}
Colin Cross4225f652015-09-17 14:33:42 -0700599
600// Convert the arch product variables into a list of host and device Arch structs
601func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
602 if variables.HostArch == nil {
603 return nil, nil, fmt.Errorf("No host primary architecture set")
604 }
605
606 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
607 if err != nil {
608 return nil, nil, err
609 }
610
611 hostArches := []Arch{hostArch}
612
613 if variables.HostSecondaryArch != nil {
614 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
615 if err != nil {
616 return nil, nil, err
617 }
618 hostArches = append(hostArches, hostSecondaryArch)
619 }
620
621 if variables.DeviceArch == nil {
622 return nil, nil, fmt.Errorf("No device primary architecture set")
623 }
624
625 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
626 variables.DeviceCpuVariant, variables.DeviceAbi)
627 if err != nil {
628 return nil, nil, err
629 }
630
631 deviceArches := []Arch{deviceArch}
632
633 if variables.DeviceSecondaryArch != nil {
634 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
635 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
636 variables.DeviceSecondaryAbi)
637 if err != nil {
638 return nil, nil, err
639 }
640 deviceArches = append(deviceArches, deviceSecondaryArch)
641 }
642
643 return hostArches, deviceArches, nil
644}
645
646// Convert a set of strings from product variables into a single Arch struct
647func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
648 stringPtr := func(p *string) string {
649 if p != nil {
650 return *p
651 }
652 return ""
653 }
654
655 slicePtr := func(p *[]string) []string {
656 if p != nil {
657 return *p
658 }
659 return nil
660 }
661
662 archType := archTypeMap[arch]
663
664 return Arch{
665 ArchType: archType,
666 ArchVariant: stringPtr(archVariant),
667 CpuVariant: stringPtr(cpuVariant),
668 Abi: slicePtr(abi),
669 }, nil
670}
671
672// Use the module multilib setting to select one or more arches from an arch list
673func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
674 buildArches := []Arch{}
675 switch multilib {
676 case "common":
677 buildArches = append(buildArches, commonArch)
678 case "both":
679 buildArches = append(buildArches, arches...)
680 case "first":
681 buildArches = append(buildArches, arches[0])
682 case "32":
683 for _, a := range arches {
684 if a.ArchType.Multilib == "lib32" {
685 buildArches = append(buildArches, a)
686 }
687 }
688 case "64":
689 for _, a := range arches {
690 if a.ArchType.Multilib == "lib64" {
691 buildArches = append(buildArches, a)
692 }
693 }
694 default:
695 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
696 multilib)
697 //buildArches = append(buildArches, arches[0])
698 }
699
700 return buildArches, nil
701}