blob: 3669e801825b0b8fab4c54f910957ec6e2d78bad [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
Colin Cross5602b582015-11-10 16:18:47 -0800144 // Arm64 arch variants
145 Armv8_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
146
Colin Crossec193632015-07-06 17:49:43 -0700147 // Arm64 cpu variants
Dan Willemsen60c3dfb2015-10-16 17:29:12 -0700148 Cortex_a53_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
149 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Crossec193632015-07-06 17:49:43 -0700150
151 // Mips arch variants
152 Mips_rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
153
Colin Cross01432f62015-07-09 17:56:26 -0700154 // X86 arch variants
Dan Willemsen96dc9f32015-10-16 16:31:15 -0700155 X86_ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6d27f342015-10-28 17:23:16 -0700156 X86_sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross01432f62015-07-09 17:56:26 -0700157
Colin Crossec193632015-07-06 17:49:43 -0700158 // X86 cpu variants
159 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
160 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800161 }
Colin Crossec193632015-07-06 17:49:43 -0700162
Colin Cross7d5136f2015-05-11 13:39:40 -0700163 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800164 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700165 // Properties for module variants being built to run on 32-bit devices
166 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
167 // Properties for module variants being built to run on 64-bit devices
168 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800169 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700170 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800171 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700172 // Properties for module variants being built to run on the host
173 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
174 // Properties for module variants being built to run on the device
175 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
176 // Properties for module variants being built to run on arm devices
177 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
178 // Properties for module variants being built to run on arm64 devices
179 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
180 // Properties for module variants being built to run on mips devices
181 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
182 // Properties for module variants being built to run on mips64 devices
183 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
184 // Properties for module variants being built to run on x86 devices
185 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
186 // Properties for module variants being built to run on x86_64 devices
187 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
188 // Properties for module variants being built to run on devices that support 64-bit
189 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
190 // Properties for module variants being built to run on devices that do not support 64-bit
191 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
192 // Properties for module variants being built to run on linux hosts
193 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
194 // Properties for module variants being built to run on linux x86 hosts
195 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 // Properties for module variants being built to run on linux x86_64 hosts
197 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
198 // Properties for module variants being built to run on darwin hosts
199 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
200 // Properties for module variants being built to run on darwin x86 hosts
201 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
202 // Properties for module variants being built to run on darwin x86_64 hosts
203 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
204 // Properties for module variants being built to run on windows hosts
205 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
206 // Properties for module variants being built to run on linux or darwin hosts
207 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800208 }
209}
210
Colin Crossc5c24ad2015-11-20 15:35:00 -0800211var archFeatureMap = map[ArchType]map[string][]string{}
212
213func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
214 field := proptools.FieldNameForProperty(variant)
215 if variant != "" {
216 if !reflect.ValueOf(archProperties{}.Arch).FieldByName(field).IsValid() {
217 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
218 }
219 }
220 for _, feature := range features {
221 field := proptools.FieldNameForProperty(feature)
222 if !reflect.ValueOf(archProperties{}.Arch).FieldByName(field).IsValid() {
223 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
224 }
225 }
226 if archFeatureMap[arch] == nil {
227 archFeatureMap[arch] = make(map[string][]string)
228 }
229 archFeatureMap[arch][variant] = features
230}
231
Colin Cross3f40fa42015-01-30 17:27:36 -0800232// An Arch indicates a single CPU architecture.
233type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800234 ArchType ArchType
235 ArchVariant string
236 CpuVariant string
237 Abi []string
238 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800239}
240
241func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700242 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800243 if a.ArchVariant != "" {
244 s += "_" + a.ArchVariant
245 }
246 if a.CpuVariant != "" {
247 s += "_" + a.CpuVariant
248 }
249 return s
250}
251
252type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700253 Name string
254 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800255}
256
Colin Crossec193632015-07-06 17:49:43 -0700257func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800258 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700259 Name: name,
260 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800261 }
262}
263
264func (a ArchType) String() string {
265 return a.Name
266}
267
268type HostOrDeviceSupported int
269
270const (
271 _ HostOrDeviceSupported = iota
272 HostSupported
273 DeviceSupported
274 HostAndDeviceSupported
275)
276
277type HostOrDevice int
278
279const (
280 _ HostOrDevice = iota
281 Host
282 Device
283)
284
285func (hod HostOrDevice) String() string {
286 switch hod {
287 case Device:
288 return "device"
289 case Host:
290 return "host"
291 default:
292 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
293 }
294}
295
Colin Crossec193632015-07-06 17:49:43 -0700296func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800297 switch hod {
298 case Device:
299 return "android"
300 case Host:
301 return "host"
302 default:
303 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
304 }
305}
306
Colin Cross3f40fa42015-01-30 17:27:36 -0800307func (hod HostOrDevice) Host() bool {
308 if hod == 0 {
309 panic("HostOrDevice unset")
310 }
311 return hod == Host
312}
313
314func (hod HostOrDevice) Device() bool {
315 if hod == 0 {
316 panic("HostOrDevice unset")
317 }
318 return hod == Device
319}
320
321var hostOrDeviceName = map[HostOrDevice]string{
322 Device: "device",
323 Host: "host",
324}
325
326var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700327 commonArch = Arch{
328 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700329 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800330)
331
Colin Cross6362e272015-10-29 15:25:03 -0700332func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700333 var module AndroidModule
334 var ok bool
335 if module, ok = mctx.Module().(AndroidModule); !ok {
336 return
337 }
338
339 hods := []HostOrDevice{}
340
341 if module.base().HostSupported() {
342 hods = append(hods, Host)
343 }
344
345 if module.base().DeviceSupported() {
346 hods = append(hods, Device)
347 }
348
349 if len(hods) == 0 {
350 return
351 }
352
353 hodNames := []string{}
354 for _, hod := range hods {
355 hodNames = append(hodNames, hod.String())
356 }
357
358 modules := mctx.CreateVariations(hodNames...)
359 for i, m := range modules {
360 m.(AndroidModule).base().SetHostOrDevice(hods[i])
361 }
362}
363
Colin Cross6362e272015-10-29 15:25:03 -0700364func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800365 var module AndroidModule
366 var ok bool
367 if module, ok = mctx.Module().(AndroidModule); !ok {
368 return
369 }
370
Colin Cross4225f652015-09-17 14:33:42 -0700371 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
372 if err != nil {
373 mctx.ModuleErrorf("%s", err.Error())
374 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800375
Colin Cross4225f652015-09-17 14:33:42 -0700376 moduleArches := []Arch{}
377 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800378
Colin Crossd3ba0392015-05-07 14:11:29 -0700379 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700380 hostModuleArches, err := decodeMultilib(multilib, hostArches)
381 if err != nil {
382 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700383 }
Colin Cross4225f652015-09-17 14:33:42 -0700384
385 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800386 }
387
Colin Crossd3ba0392015-05-07 14:11:29 -0700388 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700389 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
390 if err != nil {
391 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800392 }
Colin Cross4225f652015-09-17 14:33:42 -0700393
394 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800395 }
396
Colin Cross4225f652015-09-17 14:33:42 -0700397 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700398 return
399 }
400
Colin Cross3f40fa42015-01-30 17:27:36 -0800401 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700402 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800403 archNames = append(archNames, arch.String())
404 }
405
406 modules := mctx.CreateVariations(archNames...)
407
408 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700409 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700410 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800411 }
412}
413
Colin Crosscfad1192015-11-02 16:43:11 -0800414func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800415 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
416
417 base := m.base()
418
Colin Cross3f40fa42015-01-30 17:27:36 -0800419 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800420 propertyStructs...)
421
422 for _, properties := range base.generalProperties {
423 propertiesValue := reflect.ValueOf(properties)
424 if propertiesValue.Kind() != reflect.Ptr {
425 panic("properties must be a pointer to a struct")
426 }
427
428 propertiesValue = propertiesValue.Elem()
429 if propertiesValue.Kind() != reflect.Struct {
430 panic("properties must be a pointer to a struct")
431 }
432
433 archProperties := &archProperties{}
434 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700435 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800436 v.Set(newValue)
437 })
438
439 base.archProperties = append(base.archProperties, archProperties)
440 }
441
442 var allProperties []interface{}
443 allProperties = append(allProperties, base.generalProperties...)
444 for _, asp := range base.archProperties {
445 allProperties = append(allProperties, asp)
446 }
447
448 return m, allProperties
449}
450
Colin Crossec193632015-07-06 17:49:43 -0700451var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
452
Colin Cross6362e272015-10-29 15:25:03 -0700453func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross06a931b2015-10-28 17:23:31 -0700454 dst, src interface{}, field, srcPrefix string) {
455
Colin Crosseeabb892015-11-20 13:07:51 -0800456 srcField := reflect.ValueOf(src).FieldByName(field)
457 if !srcField.IsValid() {
458 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
459 return
460 }
461
462 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700463
464 filter := func(property string,
465 dstField, srcField reflect.StructField,
466 dstValue, srcValue interface{}) (bool, error) {
467
468 srcProperty := srcPrefix + "." + property
469
470 if !proptools.HasTag(dstField, "android", "arch_variant") {
471 if ctx.ContainsProperty(srcProperty) {
472 return false, fmt.Errorf("can't be specific to a build variant")
473 } else {
474 return false, nil
475 }
476 }
477
478 return true, nil
479 }
480
481 err := proptools.AppendProperties(dst, src, filter)
482 if err != nil {
483 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
484 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
485 } else {
486 panic(err)
487 }
488 }
489}
490
Colin Cross3f40fa42015-01-30 17:27:36 -0800491// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700492func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700493 arch := a.commonProperties.CompileArch
494 hod := a.commonProperties.CompileHostOrDevice
495
Colin Cross2fe66872015-03-30 17:20:39 -0700496 if arch.ArchType == Common {
497 return
498 }
499
Colin Cross3f40fa42015-01-30 17:27:36 -0800500 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700501 genProps := a.generalProperties[i]
502 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800503 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700504 // arch: {
505 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800506 // key: value,
507 // },
508 // },
509 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700510
Colin Crossec193632015-07-06 17:49:43 -0700511 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700512 prefix := "arch." + t.Name
513 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700514
515 // Handle arch-variant-specific properties in the form:
516 // arch: {
517 // variant: {
518 // key: value,
519 // },
520 // },
521 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
522 if v != "" {
523 field := proptools.FieldNameForProperty(v)
Colin Cross06a931b2015-10-28 17:23:31 -0700524 prefix := "arch." + v
525 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700526 }
527
528 // Handle cpu-variant-specific properties in the form:
529 // arch: {
530 // variant: {
531 // key: value,
532 // },
533 // },
534 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
535 if c != "" {
536 field := proptools.FieldNameForProperty(c)
Colin Cross06a931b2015-10-28 17:23:31 -0700537 prefix := "arch." + c
538 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700539 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800540
Colin Crossc5c24ad2015-11-20 15:35:00 -0800541 // Handle arch-feature-specific properties in the form:
542 // arch: {
543 // feature: {
544 // key: value,
545 // },
546 // },
547 for _, feature := range arch.ArchFeatures {
548 field := proptools.FieldNameForProperty(feature)
549 prefix := "arch." + feature
550 a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
551 }
552
Colin Cross3f40fa42015-01-30 17:27:36 -0800553 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700554 // multilib: {
555 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800556 // key: value,
557 // },
558 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700559 field = proptools.FieldNameForProperty(t.Multilib)
560 prefix = "multilib." + t.Multilib
561 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800562
563 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700564 // target: {
565 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800566 // key: value,
567 // },
568 // },
Colin Crossec193632015-07-06 17:49:43 -0700569 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700570 field = proptools.FieldNameForProperty(hodProperty)
571 prefix = "target." + hodProperty
572 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800573
574 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700575 // target: {
576 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800577 // key: value,
578 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700579 // not_windows: {
580 // key: value,
581 // },
582 // linux_x86: {
583 // key: value,
584 // },
585 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800586 // key: value,
587 // },
588 // },
589 var osList = []struct {
590 goos string
591 field string
592 }{
593 {"darwin", "Darwin"},
594 {"linux", "Linux"},
595 {"windows", "Windows"},
596 }
597
598 if hod.Host() {
599 for _, v := range osList {
600 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700601 field := v.field
602 prefix := "target." + v.goos
603 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700604 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700605 field = v.field + "_" + t.Name
606 prefix = "target." + v.goos + "_" + t.Name
607 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800608 }
609 }
Colin Cross06a931b2015-10-28 17:23:31 -0700610 field := "Not_windows"
611 prefix := "target.not_windows"
612 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800613 }
614
Colin Crossf8209412015-03-26 14:44:26 -0700615 // Handle 64-bit device properties in the form:
616 // target {
617 // android64 {
618 // key: value,
619 // },
620 // android32 {
621 // key: value,
622 // },
623 // },
624 // WARNING: this is probably not what you want to use in your blueprints file, it selects
625 // options for all targets on a device that supports 64-bit binaries, not just the targets
626 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
627 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
628 if hod.Device() {
629 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700630 field := "Android64"
631 prefix := "target.android64"
632 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700633 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700634 field := "Android32"
635 prefix := "target.android32"
636 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700637 }
638 }
Colin Crossb05bff22015-04-30 15:08:04 -0700639
640 // Handle device architecture properties in the form:
641 // target {
642 // android_arm {
643 // key: value,
644 // },
645 // android_x86 {
646 // key: value,
647 // },
648 // },
649 if hod.Device() {
650 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700651 field := "Android_" + t.Name
652 prefix := "target.android_" + t.Name
653 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700654 }
655
Colin Cross3f40fa42015-01-30 17:27:36 -0800656 if ctx.Failed() {
657 return
658 }
659 }
660}
661
662func forEachInterface(v reflect.Value, f func(reflect.Value)) {
663 switch v.Kind() {
664 case reflect.Interface:
665 f(v)
666 case reflect.Struct:
667 for i := 0; i < v.NumField(); i++ {
668 forEachInterface(v.Field(i), f)
669 }
670 case reflect.Ptr:
671 forEachInterface(v.Elem(), f)
672 default:
673 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
674 }
675}
Colin Cross4225f652015-09-17 14:33:42 -0700676
677// Convert the arch product variables into a list of host and device Arch structs
678func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
679 if variables.HostArch == nil {
680 return nil, nil, fmt.Errorf("No host primary architecture set")
681 }
682
683 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
684 if err != nil {
685 return nil, nil, err
686 }
687
688 hostArches := []Arch{hostArch}
689
Colin Crosseeabb892015-11-20 13:07:51 -0800690 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700691 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
692 if err != nil {
693 return nil, nil, err
694 }
695 hostArches = append(hostArches, hostSecondaryArch)
696 }
697
698 if variables.DeviceArch == nil {
699 return nil, nil, fmt.Errorf("No device primary architecture set")
700 }
701
702 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
703 variables.DeviceCpuVariant, variables.DeviceAbi)
704 if err != nil {
705 return nil, nil, err
706 }
707
708 deviceArches := []Arch{deviceArch}
709
Colin Crosseeabb892015-11-20 13:07:51 -0800710 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700711 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
712 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
713 variables.DeviceSecondaryAbi)
714 if err != nil {
715 return nil, nil, err
716 }
717 deviceArches = append(deviceArches, deviceSecondaryArch)
718 }
719
720 return hostArches, deviceArches, nil
721}
722
723// Convert a set of strings from product variables into a single Arch struct
724func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
725 stringPtr := func(p *string) string {
726 if p != nil {
727 return *p
728 }
729 return ""
730 }
731
732 slicePtr := func(p *[]string) []string {
733 if p != nil {
734 return *p
735 }
736 return nil
737 }
738
Colin Crosseeabb892015-11-20 13:07:51 -0800739 archType, ok := archTypeMap[arch]
740 if !ok {
741 return Arch{}, fmt.Errorf("unknown arch %q", arch)
742 }
Colin Cross4225f652015-09-17 14:33:42 -0700743
Colin Crosseeabb892015-11-20 13:07:51 -0800744 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700745 ArchType: archType,
746 ArchVariant: stringPtr(archVariant),
747 CpuVariant: stringPtr(cpuVariant),
748 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800749 }
750
751 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
752 a.ArchVariant = ""
753 }
754
755 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
756 a.CpuVariant = ""
757 }
758
759 for i := 0; i < len(a.Abi); i++ {
760 if a.Abi[i] == "" {
761 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
762 i--
763 }
764 }
765
Colin Crossc5c24ad2015-11-20 15:35:00 -0800766 if featureMap, ok := archFeatureMap[archType]; ok {
767 a.ArchFeatures = featureMap[stringPtr(archVariant)]
768 }
769
Colin Crosseeabb892015-11-20 13:07:51 -0800770 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -0700771}
772
773// Use the module multilib setting to select one or more arches from an arch list
774func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
775 buildArches := []Arch{}
776 switch multilib {
777 case "common":
778 buildArches = append(buildArches, commonArch)
779 case "both":
780 buildArches = append(buildArches, arches...)
781 case "first":
782 buildArches = append(buildArches, arches[0])
783 case "32":
784 for _, a := range arches {
785 if a.ArchType.Multilib == "lib32" {
786 buildArches = append(buildArches, a)
787 }
788 }
789 case "64":
790 for _, a := range arches {
791 if a.ArchType.Multilib == "lib64" {
792 buildArches = append(buildArches, a)
793 }
794 }
795 default:
796 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
797 multilib)
798 //buildArches = append(buildArches, arches[0])
799 }
800
801 return buildArches, nil
802}