blob: f0f4409171ff119a7dc7a32a33fee10078a88451 [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
23 "github.com/google/blueprint"
24 "github.com/google/blueprint/proptools"
Colin Cross3f40fa42015-01-30 17:27:36 -080025)
26
Colin Cross463a90e2015-06-17 14:20:06 -070027func init() {
Colin Cross6362e272015-10-29 15:25:03 -070028 RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator)
29 RegisterBottomUpMutator("arch", ArchMutator)
Colin Cross463a90e2015-06-17 14:20:06 -070030}
31
Colin Cross3f40fa42015-01-30 17:27:36 -080032var (
Colin Crossec193632015-07-06 17:49:43 -070033 Arm = newArch("arm", "lib32")
34 Arm64 = newArch("arm64", "lib64")
35 Mips = newArch("mips", "lib32")
36 Mips64 = newArch("mips64", "lib64")
37 X86 = newArch("x86", "lib32")
38 X86_64 = newArch("x86_64", "lib64")
Colin Cross2fe66872015-03-30 17:20:39 -070039
40 Common = ArchType{
41 Name: "common",
42 }
Colin Cross3f40fa42015-01-30 17:27:36 -080043)
44
Colin Cross4225f652015-09-17 14:33:42 -070045var archTypeMap = map[string]ArchType{
46 "arm": Arm,
47 "arm64": Arm64,
48 "mips": Mips,
49 "misp64": Mips64,
50 "x86": X86,
51 "x86_64": X86_64,
52}
53
Colin Cross3f40fa42015-01-30 17:27:36 -080054/*
55Example blueprints file containing all variant property groups, with comment listing what type
56of variants get properties in that group:
57
58module {
59 arch: {
60 arm: {
61 // Host or device variants with arm architecture
62 },
63 arm64: {
64 // Host or device variants with arm64 architecture
65 },
66 mips: {
67 // Host or device variants with mips architecture
68 },
69 mips64: {
70 // Host or device variants with mips64 architecture
71 },
72 x86: {
73 // Host or device variants with x86 architecture
74 },
75 x86_64: {
76 // Host or device variants with x86_64 architecture
77 },
78 },
79 multilib: {
80 lib32: {
81 // Host or device variants for 32-bit architectures
82 },
83 lib64: {
84 // Host or device variants for 64-bit architectures
85 },
86 },
87 target: {
88 android: {
89 // Device variants
90 },
91 host: {
92 // Host variants
93 },
94 linux: {
95 // Linux host variants
96 },
97 darwin: {
98 // Darwin host variants
99 },
100 windows: {
101 // Windows host variants
102 },
103 not_windows: {
104 // Non-windows host variants
105 },
106 },
107}
108*/
Colin Cross7d5136f2015-05-11 13:39:40 -0700109
Colin Cross3f40fa42015-01-30 17:27:36 -0800110type archProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700111 // Properties to vary by target architecture
Colin Cross3f40fa42015-01-30 17:27:36 -0800112 Arch struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700113 // Properties for module variants being built to run on arm (host or device)
114 Arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
115 // Properties for module variants being built to run on arm64 (host or device)
116 Arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
117 // Properties for module variants being built to run on mips (host or device)
118 Mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
119 // Properties for module variants being built to run on mips64 (host or device)
120 Mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
121 // Properties for module variants being built to run on x86 (host or device)
122 X86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
123 // Properties for module variants being built to run on x86_64 (host or device)
124 X86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700125
126 // Arm arch variants
127 Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"`
128 Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
129 Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"`
130
131 // Arm cpu variants
Dan Willemsen60c3dfb2015-10-16 17:29:12 -0700132 Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"`
133 Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"`
134 Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"`
135 Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"`
136 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
137 Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"`
138 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
139 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700140
141 // Arm64 cpu variants
Dan Willemsen60c3dfb2015-10-16 17:29:12 -0700142 Cortex_a53_64 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
Dan Willemsen96dc9f32015-10-16 16:31:15 -0700149 X86_ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6d27f342015-10-28 17:23:16 -0700150 X86_sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross01432f62015-07-09 17:56:26 -0700151
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 Cross6362e272015-10-29 15:25:03 -0700304func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700305 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 Cross6362e272015-10-29 15:25:03 -0700336func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800337 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 Cross6362e272015-10-29 15:25:03 -0700427func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross06a931b2015-10-28 17:23:31 -0700428 dst, src interface{}, field, srcPrefix string) {
429
430 src = reflect.ValueOf(src).FieldByName(field).Elem().Interface()
431
432 filter := func(property string,
433 dstField, srcField reflect.StructField,
434 dstValue, srcValue interface{}) (bool, error) {
435
436 srcProperty := srcPrefix + "." + property
437
438 if !proptools.HasTag(dstField, "android", "arch_variant") {
439 if ctx.ContainsProperty(srcProperty) {
440 return false, fmt.Errorf("can't be specific to a build variant")
441 } else {
442 return false, nil
443 }
444 }
445
446 return true, nil
447 }
448
449 err := proptools.AppendProperties(dst, src, filter)
450 if err != nil {
451 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
452 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
453 } else {
454 panic(err)
455 }
456 }
457}
458
Colin Cross3f40fa42015-01-30 17:27:36 -0800459// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700460func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700461 arch := a.commonProperties.CompileArch
462 hod := a.commonProperties.CompileHostOrDevice
463
Colin Cross2fe66872015-03-30 17:20:39 -0700464 if arch.ArchType == Common {
465 return
466 }
467
Colin Cross3f40fa42015-01-30 17:27:36 -0800468 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700469 genProps := a.generalProperties[i]
470 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800471 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700472 // arch: {
473 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800474 // key: value,
475 // },
476 // },
477 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700478
Colin Crossec193632015-07-06 17:49:43 -0700479 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700480 prefix := "arch." + t.Name
481 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700482
483 // Handle arch-variant-specific properties in the form:
484 // arch: {
485 // variant: {
486 // key: value,
487 // },
488 // },
489 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
490 if v != "" {
491 field := proptools.FieldNameForProperty(v)
Colin Cross06a931b2015-10-28 17:23:31 -0700492 prefix := "arch." + v
493 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700494 }
495
496 // Handle cpu-variant-specific properties in the form:
497 // arch: {
498 // variant: {
499 // key: value,
500 // },
501 // },
502 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
503 if c != "" {
504 field := proptools.FieldNameForProperty(c)
Colin Cross06a931b2015-10-28 17:23:31 -0700505 prefix := "arch." + c
506 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700507 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800508
509 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700510 // multilib: {
511 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800512 // key: value,
513 // },
514 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700515 field = proptools.FieldNameForProperty(t.Multilib)
516 prefix = "multilib." + t.Multilib
517 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800518
519 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700520 // target: {
521 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800522 // key: value,
523 // },
524 // },
Colin Crossec193632015-07-06 17:49:43 -0700525 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700526 field = proptools.FieldNameForProperty(hodProperty)
527 prefix = "target." + hodProperty
528 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800529
530 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700531 // target: {
532 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800533 // key: value,
534 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700535 // not_windows: {
536 // key: value,
537 // },
538 // linux_x86: {
539 // key: value,
540 // },
541 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800542 // key: value,
543 // },
544 // },
545 var osList = []struct {
546 goos string
547 field string
548 }{
549 {"darwin", "Darwin"},
550 {"linux", "Linux"},
551 {"windows", "Windows"},
552 }
553
554 if hod.Host() {
555 for _, v := range osList {
556 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700557 field := v.field
558 prefix := "target." + v.goos
559 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700560 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700561 field = v.field + "_" + t.Name
562 prefix = "target." + v.goos + "_" + t.Name
563 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800564 }
565 }
Colin Cross06a931b2015-10-28 17:23:31 -0700566 field := "Not_windows"
567 prefix := "target.not_windows"
568 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800569 }
570
Colin Crossf8209412015-03-26 14:44:26 -0700571 // Handle 64-bit device properties in the form:
572 // target {
573 // android64 {
574 // key: value,
575 // },
576 // android32 {
577 // key: value,
578 // },
579 // },
580 // WARNING: this is probably not what you want to use in your blueprints file, it selects
581 // options for all targets on a device that supports 64-bit binaries, not just the targets
582 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
583 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
584 if hod.Device() {
585 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700586 field := "Android64"
587 prefix := "target.android64"
588 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700589 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700590 field := "Android32"
591 prefix := "target.android32"
592 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700593 }
594 }
Colin Crossb05bff22015-04-30 15:08:04 -0700595
596 // Handle device architecture properties in the form:
597 // target {
598 // android_arm {
599 // key: value,
600 // },
601 // android_x86 {
602 // key: value,
603 // },
604 // },
605 if hod.Device() {
606 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700607 field := "Android_" + t.Name
608 prefix := "target.android_" + t.Name
609 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700610 }
611
Colin Cross3f40fa42015-01-30 17:27:36 -0800612 if ctx.Failed() {
613 return
614 }
615 }
616}
617
618func forEachInterface(v reflect.Value, f func(reflect.Value)) {
619 switch v.Kind() {
620 case reflect.Interface:
621 f(v)
622 case reflect.Struct:
623 for i := 0; i < v.NumField(); i++ {
624 forEachInterface(v.Field(i), f)
625 }
626 case reflect.Ptr:
627 forEachInterface(v.Elem(), f)
628 default:
629 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
630 }
631}
Colin Cross4225f652015-09-17 14:33:42 -0700632
633// Convert the arch product variables into a list of host and device Arch structs
634func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
635 if variables.HostArch == nil {
636 return nil, nil, fmt.Errorf("No host primary architecture set")
637 }
638
639 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
640 if err != nil {
641 return nil, nil, err
642 }
643
644 hostArches := []Arch{hostArch}
645
646 if variables.HostSecondaryArch != nil {
647 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
648 if err != nil {
649 return nil, nil, err
650 }
651 hostArches = append(hostArches, hostSecondaryArch)
652 }
653
654 if variables.DeviceArch == nil {
655 return nil, nil, fmt.Errorf("No device primary architecture set")
656 }
657
658 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
659 variables.DeviceCpuVariant, variables.DeviceAbi)
660 if err != nil {
661 return nil, nil, err
662 }
663
664 deviceArches := []Arch{deviceArch}
665
666 if variables.DeviceSecondaryArch != nil {
667 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
668 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
669 variables.DeviceSecondaryAbi)
670 if err != nil {
671 return nil, nil, err
672 }
673 deviceArches = append(deviceArches, deviceSecondaryArch)
674 }
675
676 return hostArches, deviceArches, nil
677}
678
679// Convert a set of strings from product variables into a single Arch struct
680func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
681 stringPtr := func(p *string) string {
682 if p != nil {
683 return *p
684 }
685 return ""
686 }
687
688 slicePtr := func(p *[]string) []string {
689 if p != nil {
690 return *p
691 }
692 return nil
693 }
694
695 archType := archTypeMap[arch]
696
697 return Arch{
698 ArchType: archType,
699 ArchVariant: stringPtr(archVariant),
700 CpuVariant: stringPtr(cpuVariant),
701 Abi: slicePtr(abi),
702 }, nil
703}
704
705// Use the module multilib setting to select one or more arches from an arch list
706func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
707 buildArches := []Arch{}
708 switch multilib {
709 case "common":
710 buildArches = append(buildArches, commonArch)
711 case "both":
712 buildArches = append(buildArches, arches...)
713 case "first":
714 buildArches = append(buildArches, arches[0])
715 case "32":
716 for _, a := range arches {
717 if a.ArchType.Multilib == "lib32" {
718 buildArches = append(buildArches, a)
719 }
720 }
721 case "64":
722 for _, a := range arches {
723 if a.ArchType.Multilib == "lib64" {
724 buildArches = append(buildArches, a)
725 }
726 }
727 default:
728 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
729 multilib)
730 //buildArches = append(buildArches, arches[0])
731 }
732
733 return buildArches, nil
734}