blob: e9edf2e64ad1e0e8f0f13d409f0ef01482f69647 [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
134 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 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
139 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
140
141 // Arm64 cpu variants
Dan Willemsen00faa6d2015-09-11 17:38:13 -0700142 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
143 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700144
145 // Mips arch variants
146 Mips_rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
147
Colin Cross01432f62015-07-09 17:56:26 -0700148 // X86 arch variants
149 X86_sse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
150 X86_sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
151
Colin Crossec193632015-07-06 17:49:43 -0700152 // X86 cpu variants
153 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
154 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800155 }
Colin Crossec193632015-07-06 17:49:43 -0700156
Colin Cross7d5136f2015-05-11 13:39:40 -0700157 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800158 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700159 // Properties for module variants being built to run on 32-bit devices
160 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
161 // Properties for module variants being built to run on 64-bit devices
162 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800163 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700164 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800165 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700166 // Properties for module variants being built to run on the host
167 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
168 // Properties for module variants being built to run on the device
169 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
170 // Properties for module variants being built to run on arm devices
171 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
172 // Properties for module variants being built to run on arm64 devices
173 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
174 // Properties for module variants being built to run on mips devices
175 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
176 // Properties for module variants being built to run on mips64 devices
177 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
178 // Properties for module variants being built to run on x86 devices
179 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
180 // Properties for module variants being built to run on x86_64 devices
181 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
182 // Properties for module variants being built to run on devices that support 64-bit
183 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
184 // Properties for module variants being built to run on devices that do not support 64-bit
185 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
186 // Properties for module variants being built to run on linux hosts
187 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
188 // Properties for module variants being built to run on linux x86 hosts
189 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
190 // Properties for module variants being built to run on linux x86_64 hosts
191 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
192 // Properties for module variants being built to run on darwin hosts
193 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
194 // Properties for module variants being built to run on darwin x86 hosts
195 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 // Properties for module variants being built to run on darwin x86_64 hosts
197 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
198 // Properties for module variants being built to run on windows hosts
199 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
200 // Properties for module variants being built to run on linux or darwin hosts
201 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800202 }
203}
204
205// An Arch indicates a single CPU architecture.
206type Arch struct {
Colin Crossd3ba0392015-05-07 14:11:29 -0700207 ArchType ArchType
208 ArchVariant string
209 CpuVariant string
Colin Cross4225f652015-09-17 14:33:42 -0700210 Abi []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800211}
212
213func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700214 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800215 if a.ArchVariant != "" {
216 s += "_" + a.ArchVariant
217 }
218 if a.CpuVariant != "" {
219 s += "_" + a.CpuVariant
220 }
221 return s
222}
223
224type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700225 Name string
226 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800227}
228
Colin Crossec193632015-07-06 17:49:43 -0700229func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800230 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700231 Name: name,
232 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800233 }
234}
235
236func (a ArchType) String() string {
237 return a.Name
238}
239
240type HostOrDeviceSupported int
241
242const (
243 _ HostOrDeviceSupported = iota
244 HostSupported
245 DeviceSupported
246 HostAndDeviceSupported
247)
248
249type HostOrDevice int
250
251const (
252 _ HostOrDevice = iota
253 Host
254 Device
255)
256
257func (hod HostOrDevice) String() string {
258 switch hod {
259 case Device:
260 return "device"
261 case Host:
262 return "host"
263 default:
264 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
265 }
266}
267
Colin Crossec193632015-07-06 17:49:43 -0700268func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800269 switch hod {
270 case Device:
271 return "android"
272 case Host:
273 return "host"
274 default:
275 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
276 }
277}
278
Colin Cross3f40fa42015-01-30 17:27:36 -0800279func (hod HostOrDevice) Host() bool {
280 if hod == 0 {
281 panic("HostOrDevice unset")
282 }
283 return hod == Host
284}
285
286func (hod HostOrDevice) Device() bool {
287 if hod == 0 {
288 panic("HostOrDevice unset")
289 }
290 return hod == Device
291}
292
293var hostOrDeviceName = map[HostOrDevice]string{
294 Device: "device",
295 Host: "host",
296}
297
298var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700299 commonArch = Arch{
300 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700301 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800302)
303
Colin Crossd3ba0392015-05-07 14:11:29 -0700304func HostOrDeviceMutator(mctx blueprint.EarlyMutatorContext) {
305 var module AndroidModule
306 var ok bool
307 if module, ok = mctx.Module().(AndroidModule); !ok {
308 return
309 }
310
311 hods := []HostOrDevice{}
312
313 if module.base().HostSupported() {
314 hods = append(hods, Host)
315 }
316
317 if module.base().DeviceSupported() {
318 hods = append(hods, Device)
319 }
320
321 if len(hods) == 0 {
322 return
323 }
324
325 hodNames := []string{}
326 for _, hod := range hods {
327 hodNames = append(hodNames, hod.String())
328 }
329
330 modules := mctx.CreateVariations(hodNames...)
331 for i, m := range modules {
332 m.(AndroidModule).base().SetHostOrDevice(hods[i])
333 }
334}
335
Colin Cross3f40fa42015-01-30 17:27:36 -0800336func ArchMutator(mctx blueprint.EarlyMutatorContext) {
337 var module AndroidModule
338 var ok bool
339 if module, ok = mctx.Module().(AndroidModule); !ok {
340 return
341 }
342
Colin Cross4225f652015-09-17 14:33:42 -0700343 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
344 if err != nil {
345 mctx.ModuleErrorf("%s", err.Error())
346 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800347
Colin Cross4225f652015-09-17 14:33:42 -0700348 moduleArches := []Arch{}
349 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800350
Colin Crossd3ba0392015-05-07 14:11:29 -0700351 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700352 hostModuleArches, err := decodeMultilib(multilib, hostArches)
353 if err != nil {
354 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700355 }
Colin Cross4225f652015-09-17 14:33:42 -0700356
357 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800358 }
359
Colin Crossd3ba0392015-05-07 14:11:29 -0700360 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700361 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
362 if err != nil {
363 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800364 }
Colin Cross4225f652015-09-17 14:33:42 -0700365
366 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800367 }
368
Colin Cross4225f652015-09-17 14:33:42 -0700369 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700370 return
371 }
372
Colin Cross3f40fa42015-01-30 17:27:36 -0800373 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700374 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800375 archNames = append(archNames, arch.String())
376 }
377
378 modules := mctx.CreateVariations(archNames...)
379
380 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700381 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700382 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800383 }
384}
385
Colin Crossc472d572015-03-17 15:06:21 -0700386func InitArchModule(m AndroidModule, defaultMultilib Multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800387 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
388
389 base := m.base()
390
Colin Crossc472d572015-03-17 15:06:21 -0700391 base.commonProperties.Compile_multilib = string(defaultMultilib)
Colin Cross3f40fa42015-01-30 17:27:36 -0800392
393 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800394 propertyStructs...)
395
396 for _, properties := range base.generalProperties {
397 propertiesValue := reflect.ValueOf(properties)
398 if propertiesValue.Kind() != reflect.Ptr {
399 panic("properties must be a pointer to a struct")
400 }
401
402 propertiesValue = propertiesValue.Elem()
403 if propertiesValue.Kind() != reflect.Struct {
404 panic("properties must be a pointer to a struct")
405 }
406
407 archProperties := &archProperties{}
408 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700409 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800410 v.Set(newValue)
411 })
412
413 base.archProperties = append(base.archProperties, archProperties)
414 }
415
416 var allProperties []interface{}
417 allProperties = append(allProperties, base.generalProperties...)
418 for _, asp := range base.archProperties {
419 allProperties = append(allProperties, asp)
420 }
421
422 return m, allProperties
423}
424
Colin Crossec193632015-07-06 17:49:43 -0700425var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
426
Colin Cross3f40fa42015-01-30 17:27:36 -0800427// Rewrite the module's properties structs to contain arch-specific values.
Colin Crossd3ba0392015-05-07 14:11:29 -0700428func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) {
429 arch := a.commonProperties.CompileArch
430 hod := a.commonProperties.CompileHostOrDevice
431
Colin Cross2fe66872015-03-30 17:20:39 -0700432 if arch.ArchType == Common {
433 return
434 }
435
Colin Cross7f64b6d2015-07-09 13:57:48 -0700436 callback := func(srcPropertyName, dstPropertyName string) {
437 a.extendedProperties[dstPropertyName] = struct{}{}
438 }
439
Colin Cross3f40fa42015-01-30 17:27:36 -0800440 for i := range a.generalProperties {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700441 generalPropsValue := []reflect.Value{reflect.ValueOf(a.generalProperties[i]).Elem()}
Colin Cross3f40fa42015-01-30 17:27:36 -0800442
443 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700444 // arch: {
445 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800446 // key: value,
447 // },
448 // },
449 t := arch.ArchType
Colin Crossec193632015-07-06 17:49:43 -0700450 field := proptools.FieldNameForProperty(t.Name)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700451 extendProperties(ctx, "arch_variant", "arch."+t.Name, generalPropsValue,
452 reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback)
Colin Crossec193632015-07-06 17:49:43 -0700453
454 // Handle arch-variant-specific properties in the form:
455 // arch: {
456 // variant: {
457 // key: value,
458 // },
459 // },
460 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
461 if v != "" {
462 field := proptools.FieldNameForProperty(v)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700463 extendProperties(ctx, "arch_variant", "arch."+v, generalPropsValue,
464 reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback)
Colin Crossec193632015-07-06 17:49:43 -0700465 }
466
467 // Handle cpu-variant-specific properties in the form:
468 // arch: {
469 // variant: {
470 // key: value,
471 // },
472 // },
473 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
474 if c != "" {
475 field := proptools.FieldNameForProperty(c)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700476 extendProperties(ctx, "arch_variant", "arch."+c, generalPropsValue,
477 reflect.ValueOf(a.archProperties[i].Arch).FieldByName(field).Elem().Elem(), callback)
Colin Crossec193632015-07-06 17:49:43 -0700478 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800479
480 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700481 // multilib: {
482 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800483 // key: value,
484 // },
485 // },
Colin Crossec193632015-07-06 17:49:43 -0700486 multilibField := proptools.FieldNameForProperty(t.Multilib)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700487 extendProperties(ctx, "arch_variant", "multilib."+t.Multilib, generalPropsValue,
488 reflect.ValueOf(a.archProperties[i].Multilib).FieldByName(multilibField).Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800489
490 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700491 // target: {
492 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800493 // key: value,
494 // },
495 // },
Colin Crossec193632015-07-06 17:49:43 -0700496 hodProperty := hod.Property()
497 hodField := proptools.FieldNameForProperty(hodProperty)
Colin Cross7f64b6d2015-07-09 13:57:48 -0700498 extendProperties(ctx, "arch_variant", "target."+hodProperty, generalPropsValue,
499 reflect.ValueOf(a.archProperties[i].Target).FieldByName(hodField).Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800500
501 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700502 // target: {
503 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800504 // key: value,
505 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700506 // not_windows: {
507 // key: value,
508 // },
509 // linux_x86: {
510 // key: value,
511 // },
512 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800513 // key: value,
514 // },
515 // },
516 var osList = []struct {
517 goos string
518 field string
519 }{
520 {"darwin", "Darwin"},
521 {"linux", "Linux"},
522 {"windows", "Windows"},
523 }
524
525 if hod.Host() {
526 for _, v := range osList {
527 if v.goos == runtime.GOOS {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700528 extendProperties(ctx, "arch_variant", "target."+v.goos, generalPropsValue,
529 reflect.ValueOf(a.archProperties[i].Target).FieldByName(v.field).Elem().Elem(), callback)
Colin Crossb05bff22015-04-30 15:08:04 -0700530 t := arch.ArchType
Colin Cross7f64b6d2015-07-09 13:57:48 -0700531 extendProperties(ctx, "arch_variant", "target."+v.goos+"_"+t.Name, generalPropsValue,
532 reflect.ValueOf(a.archProperties[i].Target).FieldByName(v.field+"_"+t.Name).Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800533 }
534 }
Colin Cross7f64b6d2015-07-09 13:57:48 -0700535 extendProperties(ctx, "arch_variant", "target.not_windows", generalPropsValue,
536 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Not_windows").Elem().Elem(), callback)
Colin Cross3f40fa42015-01-30 17:27:36 -0800537 }
538
Colin Crossf8209412015-03-26 14:44:26 -0700539 // Handle 64-bit device properties in the form:
540 // target {
541 // android64 {
542 // key: value,
543 // },
544 // android32 {
545 // key: value,
546 // },
547 // },
548 // WARNING: this is probably not what you want to use in your blueprints file, it selects
549 // options for all targets on a device that supports 64-bit binaries, not just the targets
550 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
551 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
552 if hod.Device() {
553 if true /* && target_is_64_bit */ {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700554 extendProperties(ctx, "arch_variant", "target.android64", generalPropsValue,
555 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android64").Elem().Elem(), callback)
Colin Crossf8209412015-03-26 14:44:26 -0700556 } else {
Colin Cross7f64b6d2015-07-09 13:57:48 -0700557 extendProperties(ctx, "arch_variant", "target.android32", generalPropsValue,
558 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android32").Elem().Elem(), callback)
Colin Crossf8209412015-03-26 14:44:26 -0700559 }
560 }
Colin Crossb05bff22015-04-30 15:08:04 -0700561
562 // Handle device architecture properties in the form:
563 // target {
564 // android_arm {
565 // key: value,
566 // },
567 // android_x86 {
568 // key: value,
569 // },
570 // },
571 if hod.Device() {
572 t := arch.ArchType
Colin Cross7f64b6d2015-07-09 13:57:48 -0700573 extendProperties(ctx, "arch_variant", "target.android_"+t.Name, generalPropsValue,
574 reflect.ValueOf(a.archProperties[i].Target).FieldByName("Android_"+t.Name).Elem().Elem(), callback)
Colin Crossb05bff22015-04-30 15:08:04 -0700575 }
576
Colin Cross3f40fa42015-01-30 17:27:36 -0800577 if ctx.Failed() {
578 return
579 }
580 }
581}
582
583func forEachInterface(v reflect.Value, f func(reflect.Value)) {
584 switch v.Kind() {
585 case reflect.Interface:
586 f(v)
587 case reflect.Struct:
588 for i := 0; i < v.NumField(); i++ {
589 forEachInterface(v.Field(i), f)
590 }
591 case reflect.Ptr:
592 forEachInterface(v.Elem(), f)
593 default:
594 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
595 }
596}
Colin Cross4225f652015-09-17 14:33:42 -0700597
598// Convert the arch product variables into a list of host and device Arch structs
599func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
600 if variables.HostArch == nil {
601 return nil, nil, fmt.Errorf("No host primary architecture set")
602 }
603
604 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
605 if err != nil {
606 return nil, nil, err
607 }
608
609 hostArches := []Arch{hostArch}
610
611 if variables.HostSecondaryArch != nil {
612 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
613 if err != nil {
614 return nil, nil, err
615 }
616 hostArches = append(hostArches, hostSecondaryArch)
617 }
618
619 if variables.DeviceArch == nil {
620 return nil, nil, fmt.Errorf("No device primary architecture set")
621 }
622
623 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
624 variables.DeviceCpuVariant, variables.DeviceAbi)
625 if err != nil {
626 return nil, nil, err
627 }
628
629 deviceArches := []Arch{deviceArch}
630
631 if variables.DeviceSecondaryArch != nil {
632 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
633 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
634 variables.DeviceSecondaryAbi)
635 if err != nil {
636 return nil, nil, err
637 }
638 deviceArches = append(deviceArches, deviceSecondaryArch)
639 }
640
641 return hostArches, deviceArches, nil
642}
643
644// Convert a set of strings from product variables into a single Arch struct
645func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
646 stringPtr := func(p *string) string {
647 if p != nil {
648 return *p
649 }
650 return ""
651 }
652
653 slicePtr := func(p *[]string) []string {
654 if p != nil {
655 return *p
656 }
657 return nil
658 }
659
660 archType := archTypeMap[arch]
661
662 return Arch{
663 ArchType: archType,
664 ArchVariant: stringPtr(archVariant),
665 CpuVariant: stringPtr(cpuVariant),
666 Abi: slicePtr(abi),
667 }, nil
668}
669
670// Use the module multilib setting to select one or more arches from an arch list
671func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
672 buildArches := []Arch{}
673 switch multilib {
674 case "common":
675 buildArches = append(buildArches, commonArch)
676 case "both":
677 buildArches = append(buildArches, arches...)
678 case "first":
679 buildArches = append(buildArches, arches[0])
680 case "32":
681 for _, a := range arches {
682 if a.ArchType.Multilib == "lib32" {
683 buildArches = append(buildArches, a)
684 }
685 }
686 case "64":
687 for _, a := range arches {
688 if a.ArchType.Multilib == "lib64" {
689 buildArches = append(buildArches, a)
690 }
691 }
692 default:
693 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
694 multilib)
695 //buildArches = append(buildArches, arches[0])
696 }
697
698 return buildArches, nil
699}