blob: e524dd51e4c3535f4c19dcdf3e1f4a2c5a47e76b [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 Crosscfad1192015-11-02 16:43:11 -080028 RegisterBottomUpMutator("defaults_deps", defaultsDepsMutator)
29 RegisterTopDownMutator("defaults", defaultsMutator)
30
Colin Cross6362e272015-10-29 15:25:03 -070031 RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator)
32 RegisterBottomUpMutator("arch", ArchMutator)
Colin Cross463a90e2015-06-17 14:20:06 -070033}
34
Colin Cross3f40fa42015-01-30 17:27:36 -080035var (
Colin Crossec193632015-07-06 17:49:43 -070036 Arm = newArch("arm", "lib32")
37 Arm64 = newArch("arm64", "lib64")
38 Mips = newArch("mips", "lib32")
39 Mips64 = newArch("mips64", "lib64")
40 X86 = newArch("x86", "lib32")
41 X86_64 = newArch("x86_64", "lib64")
Colin Cross2fe66872015-03-30 17:20:39 -070042
43 Common = ArchType{
44 Name: "common",
45 }
Colin Cross3f40fa42015-01-30 17:27:36 -080046)
47
Colin Cross4225f652015-09-17 14:33:42 -070048var archTypeMap = map[string]ArchType{
49 "arm": Arm,
50 "arm64": Arm64,
51 "mips": Mips,
52 "misp64": Mips64,
53 "x86": X86,
54 "x86_64": X86_64,
55}
56
Colin Cross3f40fa42015-01-30 17:27:36 -080057/*
58Example blueprints file containing all variant property groups, with comment listing what type
59of variants get properties in that group:
60
61module {
62 arch: {
63 arm: {
64 // Host or device variants with arm architecture
65 },
66 arm64: {
67 // Host or device variants with arm64 architecture
68 },
69 mips: {
70 // Host or device variants with mips architecture
71 },
72 mips64: {
73 // Host or device variants with mips64 architecture
74 },
75 x86: {
76 // Host or device variants with x86 architecture
77 },
78 x86_64: {
79 // Host or device variants with x86_64 architecture
80 },
81 },
82 multilib: {
83 lib32: {
84 // Host or device variants for 32-bit architectures
85 },
86 lib64: {
87 // Host or device variants for 64-bit architectures
88 },
89 },
90 target: {
91 android: {
92 // Device variants
93 },
94 host: {
95 // Host variants
96 },
97 linux: {
98 // Linux host variants
99 },
100 darwin: {
101 // Darwin host variants
102 },
103 windows: {
104 // Windows host variants
105 },
106 not_windows: {
107 // Non-windows host variants
108 },
109 },
110}
111*/
Colin Cross7d5136f2015-05-11 13:39:40 -0700112
Colin Cross3f40fa42015-01-30 17:27:36 -0800113type archProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700114 // Properties to vary by target architecture
Colin Cross3f40fa42015-01-30 17:27:36 -0800115 Arch struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700116 // Properties for module variants being built to run on arm (host or device)
117 Arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
118 // Properties for module variants being built to run on arm64 (host or device)
119 Arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
120 // Properties for module variants being built to run on mips (host or device)
121 Mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
122 // Properties for module variants being built to run on mips64 (host or device)
123 Mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
124 // Properties for module variants being built to run on x86 (host or device)
125 X86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
126 // Properties for module variants being built to run on x86_64 (host or device)
127 X86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700128
129 // Arm arch variants
130 Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"`
131 Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
132 Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"`
133
134 // Arm cpu variants
Dan Willemsen60c3dfb2015-10-16 17:29:12 -0700135 Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"`
136 Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"`
137 Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"`
138 Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"`
139 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
140 Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"`
141 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
142 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700143
144 // Arm64 cpu variants
Dan Willemsen60c3dfb2015-10-16 17:29:12 -0700145 Cortex_a53_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
146 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700147
148 // Mips arch variants
149 Mips_rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
150
Colin Cross01432f62015-07-09 17:56:26 -0700151 // X86 arch variants
Dan Willemsen96dc9f32015-10-16 16:31:15 -0700152 X86_ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6d27f342015-10-28 17:23:16 -0700153 X86_sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross01432f62015-07-09 17:56:26 -0700154
Colin Crossec193632015-07-06 17:49:43 -0700155 // X86 cpu variants
156 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
157 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800158 }
Colin Crossec193632015-07-06 17:49:43 -0700159
Colin Cross7d5136f2015-05-11 13:39:40 -0700160 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800161 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700162 // Properties for module variants being built to run on 32-bit devices
163 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
164 // Properties for module variants being built to run on 64-bit devices
165 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800166 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700167 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800168 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700169 // Properties for module variants being built to run on the host
170 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
171 // Properties for module variants being built to run on the device
172 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
173 // Properties for module variants being built to run on arm devices
174 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
175 // Properties for module variants being built to run on arm64 devices
176 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
177 // Properties for module variants being built to run on mips devices
178 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
179 // Properties for module variants being built to run on mips64 devices
180 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
181 // Properties for module variants being built to run on x86 devices
182 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
183 // Properties for module variants being built to run on x86_64 devices
184 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
185 // Properties for module variants being built to run on devices that support 64-bit
186 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
187 // Properties for module variants being built to run on devices that do not support 64-bit
188 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
189 // Properties for module variants being built to run on linux hosts
190 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
191 // Properties for module variants being built to run on linux x86 hosts
192 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
193 // Properties for module variants being built to run on linux x86_64 hosts
194 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
195 // Properties for module variants being built to run on darwin hosts
196 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
197 // Properties for module variants being built to run on darwin x86 hosts
198 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
199 // Properties for module variants being built to run on darwin x86_64 hosts
200 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
201 // Properties for module variants being built to run on windows hosts
202 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
203 // Properties for module variants being built to run on linux or darwin hosts
204 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800205 }
206}
207
208// An Arch indicates a single CPU architecture.
209type Arch struct {
Colin Crossd3ba0392015-05-07 14:11:29 -0700210 ArchType ArchType
211 ArchVariant string
212 CpuVariant string
Colin Cross4225f652015-09-17 14:33:42 -0700213 Abi []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800214}
215
216func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700217 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800218 if a.ArchVariant != "" {
219 s += "_" + a.ArchVariant
220 }
221 if a.CpuVariant != "" {
222 s += "_" + a.CpuVariant
223 }
224 return s
225}
226
227type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700228 Name string
229 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800230}
231
Colin Crossec193632015-07-06 17:49:43 -0700232func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800233 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700234 Name: name,
235 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800236 }
237}
238
239func (a ArchType) String() string {
240 return a.Name
241}
242
243type HostOrDeviceSupported int
244
245const (
246 _ HostOrDeviceSupported = iota
247 HostSupported
248 DeviceSupported
249 HostAndDeviceSupported
250)
251
252type HostOrDevice int
253
254const (
255 _ HostOrDevice = iota
256 Host
257 Device
258)
259
260func (hod HostOrDevice) String() string {
261 switch hod {
262 case Device:
263 return "device"
264 case Host:
265 return "host"
266 default:
267 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
268 }
269}
270
Colin Crossec193632015-07-06 17:49:43 -0700271func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800272 switch hod {
273 case Device:
274 return "android"
275 case Host:
276 return "host"
277 default:
278 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
279 }
280}
281
Colin Cross3f40fa42015-01-30 17:27:36 -0800282func (hod HostOrDevice) Host() bool {
283 if hod == 0 {
284 panic("HostOrDevice unset")
285 }
286 return hod == Host
287}
288
289func (hod HostOrDevice) Device() bool {
290 if hod == 0 {
291 panic("HostOrDevice unset")
292 }
293 return hod == Device
294}
295
296var hostOrDeviceName = map[HostOrDevice]string{
297 Device: "device",
298 Host: "host",
299}
300
301var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700302 commonArch = Arch{
303 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700304 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800305)
306
Colin Cross6362e272015-10-29 15:25:03 -0700307func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700308 var module AndroidModule
309 var ok bool
310 if module, ok = mctx.Module().(AndroidModule); !ok {
311 return
312 }
313
314 hods := []HostOrDevice{}
315
316 if module.base().HostSupported() {
317 hods = append(hods, Host)
318 }
319
320 if module.base().DeviceSupported() {
321 hods = append(hods, Device)
322 }
323
324 if len(hods) == 0 {
325 return
326 }
327
328 hodNames := []string{}
329 for _, hod := range hods {
330 hodNames = append(hodNames, hod.String())
331 }
332
333 modules := mctx.CreateVariations(hodNames...)
334 for i, m := range modules {
335 m.(AndroidModule).base().SetHostOrDevice(hods[i])
336 }
337}
338
Colin Cross6362e272015-10-29 15:25:03 -0700339func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800340 var module AndroidModule
341 var ok bool
342 if module, ok = mctx.Module().(AndroidModule); !ok {
343 return
344 }
345
Colin Cross4225f652015-09-17 14:33:42 -0700346 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
347 if err != nil {
348 mctx.ModuleErrorf("%s", err.Error())
349 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800350
Colin Cross4225f652015-09-17 14:33:42 -0700351 moduleArches := []Arch{}
352 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800353
Colin Crossd3ba0392015-05-07 14:11:29 -0700354 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700355 hostModuleArches, err := decodeMultilib(multilib, hostArches)
356 if err != nil {
357 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700358 }
Colin Cross4225f652015-09-17 14:33:42 -0700359
360 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800361 }
362
Colin Crossd3ba0392015-05-07 14:11:29 -0700363 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700364 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
365 if err != nil {
366 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800367 }
Colin Cross4225f652015-09-17 14:33:42 -0700368
369 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800370 }
371
Colin Cross4225f652015-09-17 14:33:42 -0700372 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700373 return
374 }
375
Colin Cross3f40fa42015-01-30 17:27:36 -0800376 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700377 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800378 archNames = append(archNames, arch.String())
379 }
380
381 modules := mctx.CreateVariations(archNames...)
382
383 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700384 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700385 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800386 }
387}
388
Colin Crosscfad1192015-11-02 16:43:11 -0800389func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800390 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
391
392 base := m.base()
393
Colin Cross3f40fa42015-01-30 17:27:36 -0800394 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800395 propertyStructs...)
396
397 for _, properties := range base.generalProperties {
398 propertiesValue := reflect.ValueOf(properties)
399 if propertiesValue.Kind() != reflect.Ptr {
400 panic("properties must be a pointer to a struct")
401 }
402
403 propertiesValue = propertiesValue.Elem()
404 if propertiesValue.Kind() != reflect.Struct {
405 panic("properties must be a pointer to a struct")
406 }
407
408 archProperties := &archProperties{}
409 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700410 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800411 v.Set(newValue)
412 })
413
414 base.archProperties = append(base.archProperties, archProperties)
415 }
416
417 var allProperties []interface{}
418 allProperties = append(allProperties, base.generalProperties...)
419 for _, asp := range base.archProperties {
420 allProperties = append(allProperties, asp)
421 }
422
423 return m, allProperties
424}
425
Colin Crossec193632015-07-06 17:49:43 -0700426var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
427
Colin Cross6362e272015-10-29 15:25:03 -0700428func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross06a931b2015-10-28 17:23:31 -0700429 dst, src interface{}, field, srcPrefix string) {
430
431 src = reflect.ValueOf(src).FieldByName(field).Elem().Interface()
432
433 filter := func(property string,
434 dstField, srcField reflect.StructField,
435 dstValue, srcValue interface{}) (bool, error) {
436
437 srcProperty := srcPrefix + "." + property
438
439 if !proptools.HasTag(dstField, "android", "arch_variant") {
440 if ctx.ContainsProperty(srcProperty) {
441 return false, fmt.Errorf("can't be specific to a build variant")
442 } else {
443 return false, nil
444 }
445 }
446
447 return true, nil
448 }
449
450 err := proptools.AppendProperties(dst, src, filter)
451 if err != nil {
452 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
453 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
454 } else {
455 panic(err)
456 }
457 }
458}
459
Colin Cross3f40fa42015-01-30 17:27:36 -0800460// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700461func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700462 arch := a.commonProperties.CompileArch
463 hod := a.commonProperties.CompileHostOrDevice
464
Colin Cross2fe66872015-03-30 17:20:39 -0700465 if arch.ArchType == Common {
466 return
467 }
468
Colin Cross3f40fa42015-01-30 17:27:36 -0800469 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700470 genProps := a.generalProperties[i]
471 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800472 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700473 // arch: {
474 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800475 // key: value,
476 // },
477 // },
478 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700479
Colin Crossec193632015-07-06 17:49:43 -0700480 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700481 prefix := "arch." + t.Name
482 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700483
484 // Handle arch-variant-specific properties in the form:
485 // arch: {
486 // variant: {
487 // key: value,
488 // },
489 // },
490 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
491 if v != "" {
492 field := proptools.FieldNameForProperty(v)
Colin Cross06a931b2015-10-28 17:23:31 -0700493 prefix := "arch." + v
494 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700495 }
496
497 // Handle cpu-variant-specific properties in the form:
498 // arch: {
499 // variant: {
500 // key: value,
501 // },
502 // },
503 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
504 if c != "" {
505 field := proptools.FieldNameForProperty(c)
Colin Cross06a931b2015-10-28 17:23:31 -0700506 prefix := "arch." + c
507 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700508 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800509
510 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700511 // multilib: {
512 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800513 // key: value,
514 // },
515 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700516 field = proptools.FieldNameForProperty(t.Multilib)
517 prefix = "multilib." + t.Multilib
518 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800519
520 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700521 // target: {
522 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800523 // key: value,
524 // },
525 // },
Colin Crossec193632015-07-06 17:49:43 -0700526 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700527 field = proptools.FieldNameForProperty(hodProperty)
528 prefix = "target." + hodProperty
529 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800530
531 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700532 // target: {
533 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800534 // key: value,
535 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700536 // not_windows: {
537 // key: value,
538 // },
539 // linux_x86: {
540 // key: value,
541 // },
542 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800543 // key: value,
544 // },
545 // },
546 var osList = []struct {
547 goos string
548 field string
549 }{
550 {"darwin", "Darwin"},
551 {"linux", "Linux"},
552 {"windows", "Windows"},
553 }
554
555 if hod.Host() {
556 for _, v := range osList {
557 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700558 field := v.field
559 prefix := "target." + v.goos
560 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700561 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700562 field = v.field + "_" + t.Name
563 prefix = "target." + v.goos + "_" + t.Name
564 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800565 }
566 }
Colin Cross06a931b2015-10-28 17:23:31 -0700567 field := "Not_windows"
568 prefix := "target.not_windows"
569 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800570 }
571
Colin Crossf8209412015-03-26 14:44:26 -0700572 // Handle 64-bit device properties in the form:
573 // target {
574 // android64 {
575 // key: value,
576 // },
577 // android32 {
578 // key: value,
579 // },
580 // },
581 // WARNING: this is probably not what you want to use in your blueprints file, it selects
582 // options for all targets on a device that supports 64-bit binaries, not just the targets
583 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
584 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
585 if hod.Device() {
586 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700587 field := "Android64"
588 prefix := "target.android64"
589 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700590 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700591 field := "Android32"
592 prefix := "target.android32"
593 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700594 }
595 }
Colin Crossb05bff22015-04-30 15:08:04 -0700596
597 // Handle device architecture properties in the form:
598 // target {
599 // android_arm {
600 // key: value,
601 // },
602 // android_x86 {
603 // key: value,
604 // },
605 // },
606 if hod.Device() {
607 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700608 field := "Android_" + t.Name
609 prefix := "target.android_" + t.Name
610 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700611 }
612
Colin Cross3f40fa42015-01-30 17:27:36 -0800613 if ctx.Failed() {
614 return
615 }
616 }
617}
618
619func forEachInterface(v reflect.Value, f func(reflect.Value)) {
620 switch v.Kind() {
621 case reflect.Interface:
622 f(v)
623 case reflect.Struct:
624 for i := 0; i < v.NumField(); i++ {
625 forEachInterface(v.Field(i), f)
626 }
627 case reflect.Ptr:
628 forEachInterface(v.Elem(), f)
629 default:
630 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
631 }
632}
Colin Cross4225f652015-09-17 14:33:42 -0700633
634// Convert the arch product variables into a list of host and device Arch structs
635func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
636 if variables.HostArch == nil {
637 return nil, nil, fmt.Errorf("No host primary architecture set")
638 }
639
640 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
641 if err != nil {
642 return nil, nil, err
643 }
644
645 hostArches := []Arch{hostArch}
646
647 if variables.HostSecondaryArch != nil {
648 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
649 if err != nil {
650 return nil, nil, err
651 }
652 hostArches = append(hostArches, hostSecondaryArch)
653 }
654
655 if variables.DeviceArch == nil {
656 return nil, nil, fmt.Errorf("No device primary architecture set")
657 }
658
659 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
660 variables.DeviceCpuVariant, variables.DeviceAbi)
661 if err != nil {
662 return nil, nil, err
663 }
664
665 deviceArches := []Arch{deviceArch}
666
667 if variables.DeviceSecondaryArch != nil {
668 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
669 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
670 variables.DeviceSecondaryAbi)
671 if err != nil {
672 return nil, nil, err
673 }
674 deviceArches = append(deviceArches, deviceSecondaryArch)
675 }
676
677 return hostArches, deviceArches, nil
678}
679
680// Convert a set of strings from product variables into a single Arch struct
681func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
682 stringPtr := func(p *string) string {
683 if p != nil {
684 return *p
685 }
686 return ""
687 }
688
689 slicePtr := func(p *[]string) []string {
690 if p != nil {
691 return *p
692 }
693 return nil
694 }
695
696 archType := archTypeMap[arch]
697
698 return Arch{
699 ArchType: archType,
700 ArchVariant: stringPtr(archVariant),
701 CpuVariant: stringPtr(cpuVariant),
702 Abi: slicePtr(abi),
703 }, nil
704}
705
706// Use the module multilib setting to select one or more arches from an arch list
707func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
708 buildArches := []Arch{}
709 switch multilib {
710 case "common":
711 buildArches = append(buildArches, commonArch)
712 case "both":
713 buildArches = append(buildArches, arches...)
714 case "first":
715 buildArches = append(buildArches, arches[0])
716 case "32":
717 for _, a := range arches {
718 if a.ArchType.Multilib == "lib32" {
719 buildArches = append(buildArches, a)
720 }
721 }
722 case "64":
723 for _, a := range arches {
724 if a.ArchType.Multilib == "lib64" {
725 buildArches = append(buildArches, a)
726 }
727 }
728 default:
729 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
730 multilib)
731 //buildArches = append(buildArches, arches[0])
732 }
733
734 return buildArches, nil
735}