blob: 7ed8f2689a9a71b27d4bee93a677294b5a61f065 [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 Cross85a88972015-11-23 13:29:51 -0800113type Embed interface{}
114
Colin Cross3f40fa42015-01-30 17:27:36 -0800115type archProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700116 // Properties to vary by target architecture
Colin Cross3f40fa42015-01-30 17:27:36 -0800117 Arch struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700118 // Properties for module variants being built to run on arm (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800119 Arm struct {
120 Embed `blueprint:"filter(android:\"arch_variant\")"`
121
122 // Arm arch variants
123 Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"`
124 Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
125 Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"`
126
127 // Arm cpu variants
128 Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"`
129 Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"`
130 Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"`
131 Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"`
132 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
133 Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"`
134 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
135 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
136 }
137
Colin Cross7d5136f2015-05-11 13:39:40 -0700138 // Properties for module variants being built to run on arm64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800139 Arm64 struct {
140 Embed `blueprint:"filter(android:\"arch_variant\")"`
141
142 // Arm64 arch variants
143 Armv8_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
144
145 // Arm64 cpu variants
146 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
147 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
148 }
149
Colin Cross7d5136f2015-05-11 13:39:40 -0700150 // Properties for module variants being built to run on mips (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800151 Mips struct {
152 Embed `blueprint:"filter(android:\"arch_variant\")"`
153
154 // Mips arch variants
155 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
156 }
157
Colin Cross7d5136f2015-05-11 13:39:40 -0700158 // Properties for module variants being built to run on mips64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800159 Mips64 struct {
160 Embed `blueprint:"filter(android:\"arch_variant\")"`
161
162 // Mips64 arch variants
163 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
164 }
165
Colin Cross7d5136f2015-05-11 13:39:40 -0700166 // Properties for module variants being built to run on x86 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800167 X86 struct {
168 Embed `blueprint:"filter(android:\"arch_variant\")"`
169
170 // X86 arch variants
171 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
172 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
173
174 // X86 arch features
175 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
176 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
177 }
178
Colin Cross7d5136f2015-05-11 13:39:40 -0700179 // Properties for module variants being built to run on x86_64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800180 X86_64 struct {
181 Embed `blueprint:"filter(android:\"arch_variant\")"`
182 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800183 }
Colin Crossec193632015-07-06 17:49:43 -0700184
Colin Cross7d5136f2015-05-11 13:39:40 -0700185 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800186 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700187 // Properties for module variants being built to run on 32-bit devices
188 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
189 // Properties for module variants being built to run on 64-bit devices
190 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800191 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700192 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800193 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700194 // Properties for module variants being built to run on the host
195 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 // Properties for module variants being built to run on the device
197 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
198 // Properties for module variants being built to run on arm devices
199 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
200 // Properties for module variants being built to run on arm64 devices
201 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
202 // Properties for module variants being built to run on mips devices
203 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
204 // Properties for module variants being built to run on mips64 devices
205 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
206 // Properties for module variants being built to run on x86 devices
207 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
208 // Properties for module variants being built to run on x86_64 devices
209 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
210 // Properties for module variants being built to run on devices that support 64-bit
211 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
212 // Properties for module variants being built to run on devices that do not support 64-bit
213 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
214 // Properties for module variants being built to run on linux hosts
215 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
216 // Properties for module variants being built to run on linux x86 hosts
217 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
218 // Properties for module variants being built to run on linux x86_64 hosts
219 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
220 // Properties for module variants being built to run on darwin hosts
221 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
222 // Properties for module variants being built to run on darwin x86 hosts
223 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
224 // Properties for module variants being built to run on darwin x86_64 hosts
225 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
226 // Properties for module variants being built to run on windows hosts
227 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
228 // Properties for module variants being built to run on linux or darwin hosts
229 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800230 }
231}
232
Colin Crossc5c24ad2015-11-20 15:35:00 -0800233var archFeatureMap = map[ArchType]map[string][]string{}
234
235func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800236 archField := proptools.FieldNameForProperty(arch.Name)
237 variantField := proptools.FieldNameForProperty(variant)
238 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800239 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800240 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800241 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
242 }
243 }
244 for _, feature := range features {
245 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800246 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800247 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
248 }
249 }
250 if archFeatureMap[arch] == nil {
251 archFeatureMap[arch] = make(map[string][]string)
252 }
253 archFeatureMap[arch][variant] = features
254}
255
Colin Cross3f40fa42015-01-30 17:27:36 -0800256// An Arch indicates a single CPU architecture.
257type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800258 ArchType ArchType
259 ArchVariant string
260 CpuVariant string
261 Abi []string
262 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800263}
264
265func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700266 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800267 if a.ArchVariant != "" {
268 s += "_" + a.ArchVariant
269 }
270 if a.CpuVariant != "" {
271 s += "_" + a.CpuVariant
272 }
273 return s
274}
275
276type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700277 Name string
278 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800279}
280
Colin Crossec193632015-07-06 17:49:43 -0700281func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800282 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700283 Name: name,
284 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800285 }
286}
287
288func (a ArchType) String() string {
289 return a.Name
290}
291
292type HostOrDeviceSupported int
293
294const (
295 _ HostOrDeviceSupported = iota
296 HostSupported
297 DeviceSupported
298 HostAndDeviceSupported
299)
300
301type HostOrDevice int
302
303const (
304 _ HostOrDevice = iota
305 Host
306 Device
307)
308
309func (hod HostOrDevice) String() string {
310 switch hod {
311 case Device:
312 return "device"
313 case Host:
314 return "host"
315 default:
316 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
317 }
318}
319
Colin Crossec193632015-07-06 17:49:43 -0700320func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800321 switch hod {
322 case Device:
323 return "android"
324 case Host:
325 return "host"
326 default:
327 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
328 }
329}
330
Colin Cross3f40fa42015-01-30 17:27:36 -0800331func (hod HostOrDevice) Host() bool {
332 if hod == 0 {
333 panic("HostOrDevice unset")
334 }
335 return hod == Host
336}
337
338func (hod HostOrDevice) Device() bool {
339 if hod == 0 {
340 panic("HostOrDevice unset")
341 }
342 return hod == Device
343}
344
345var hostOrDeviceName = map[HostOrDevice]string{
346 Device: "device",
347 Host: "host",
348}
349
350var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700351 commonArch = Arch{
352 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700353 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800354)
355
Colin Cross6362e272015-10-29 15:25:03 -0700356func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700357 var module AndroidModule
358 var ok bool
359 if module, ok = mctx.Module().(AndroidModule); !ok {
360 return
361 }
362
363 hods := []HostOrDevice{}
364
365 if module.base().HostSupported() {
366 hods = append(hods, Host)
367 }
368
369 if module.base().DeviceSupported() {
370 hods = append(hods, Device)
371 }
372
373 if len(hods) == 0 {
374 return
375 }
376
377 hodNames := []string{}
378 for _, hod := range hods {
379 hodNames = append(hodNames, hod.String())
380 }
381
382 modules := mctx.CreateVariations(hodNames...)
383 for i, m := range modules {
384 m.(AndroidModule).base().SetHostOrDevice(hods[i])
385 }
386}
387
Colin Cross6362e272015-10-29 15:25:03 -0700388func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800389 var module AndroidModule
390 var ok bool
391 if module, ok = mctx.Module().(AndroidModule); !ok {
392 return
393 }
394
Colin Cross4225f652015-09-17 14:33:42 -0700395 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
396 if err != nil {
397 mctx.ModuleErrorf("%s", err.Error())
398 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800399
Colin Cross4225f652015-09-17 14:33:42 -0700400 moduleArches := []Arch{}
401 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800402
Colin Crossd3ba0392015-05-07 14:11:29 -0700403 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700404 hostModuleArches, err := decodeMultilib(multilib, hostArches)
405 if err != nil {
406 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700407 }
Colin Cross4225f652015-09-17 14:33:42 -0700408
409 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800410 }
411
Colin Crossd3ba0392015-05-07 14:11:29 -0700412 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700413 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
414 if err != nil {
415 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800416 }
Colin Cross4225f652015-09-17 14:33:42 -0700417
418 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800419 }
420
Colin Cross4225f652015-09-17 14:33:42 -0700421 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700422 return
423 }
424
Colin Cross3f40fa42015-01-30 17:27:36 -0800425 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700426 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800427 archNames = append(archNames, arch.String())
428 }
429
430 modules := mctx.CreateVariations(archNames...)
431
432 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700433 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700434 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800435 }
436}
437
Colin Crosscfad1192015-11-02 16:43:11 -0800438func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800439 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
440
441 base := m.base()
442
Colin Cross3f40fa42015-01-30 17:27:36 -0800443 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800444 propertyStructs...)
445
446 for _, properties := range base.generalProperties {
447 propertiesValue := reflect.ValueOf(properties)
448 if propertiesValue.Kind() != reflect.Ptr {
449 panic("properties must be a pointer to a struct")
450 }
451
452 propertiesValue = propertiesValue.Elem()
453 if propertiesValue.Kind() != reflect.Struct {
454 panic("properties must be a pointer to a struct")
455 }
456
457 archProperties := &archProperties{}
458 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700459 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800460 v.Set(newValue)
461 })
462
463 base.archProperties = append(base.archProperties, archProperties)
464 }
465
466 var allProperties []interface{}
467 allProperties = append(allProperties, base.generalProperties...)
468 for _, asp := range base.archProperties {
469 allProperties = append(allProperties, asp)
470 }
471
472 return m, allProperties
473}
474
Colin Crossec193632015-07-06 17:49:43 -0700475var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
476
Colin Cross6362e272015-10-29 15:25:03 -0700477func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800478 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700479
Colin Crosseeabb892015-11-20 13:07:51 -0800480 srcField := reflect.ValueOf(src).FieldByName(field)
481 if !srcField.IsValid() {
482 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800483 return nil
484 }
485
486 ret := srcField
487
488 if srcField.Kind() == reflect.Struct {
489 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800490 }
491
492 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700493
494 filter := func(property string,
495 dstField, srcField reflect.StructField,
496 dstValue, srcValue interface{}) (bool, error) {
497
498 srcProperty := srcPrefix + "." + property
499
500 if !proptools.HasTag(dstField, "android", "arch_variant") {
501 if ctx.ContainsProperty(srcProperty) {
502 return false, fmt.Errorf("can't be specific to a build variant")
503 } else {
504 return false, nil
505 }
506 }
507
508 return true, nil
509 }
510
511 err := proptools.AppendProperties(dst, src, filter)
512 if err != nil {
513 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
514 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
515 } else {
516 panic(err)
517 }
518 }
Colin Cross85a88972015-11-23 13:29:51 -0800519
520 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700521}
522
Colin Cross3f40fa42015-01-30 17:27:36 -0800523// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700524func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700525 arch := a.commonProperties.CompileArch
526 hod := a.commonProperties.CompileHostOrDevice
527
Colin Cross2fe66872015-03-30 17:20:39 -0700528 if arch.ArchType == Common {
529 return
530 }
531
Colin Cross3f40fa42015-01-30 17:27:36 -0800532 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700533 genProps := a.generalProperties[i]
534 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800535 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700536 // arch: {
537 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800538 // key: value,
539 // },
540 // },
541 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700542
Colin Crossec193632015-07-06 17:49:43 -0700543 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700544 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800545 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700546
547 // Handle arch-variant-specific properties in the form:
548 // arch: {
549 // variant: {
550 // key: value,
551 // },
552 // },
553 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
554 if v != "" {
555 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800556 prefix := "arch." + t.Name + "." + v
557 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700558 }
559
560 // Handle cpu-variant-specific properties in the form:
561 // arch: {
562 // variant: {
563 // key: value,
564 // },
565 // },
566 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
567 if c != "" {
568 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800569 prefix := "arch." + t.Name + "." + c
570 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700571 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800572
Colin Crossc5c24ad2015-11-20 15:35:00 -0800573 // Handle arch-feature-specific properties in the form:
574 // arch: {
575 // feature: {
576 // key: value,
577 // },
578 // },
579 for _, feature := range arch.ArchFeatures {
580 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800581 prefix := "arch." + t.Name + "." + feature
582 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800583 }
584
Colin Cross3f40fa42015-01-30 17:27:36 -0800585 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700586 // multilib: {
587 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800588 // key: value,
589 // },
590 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700591 field = proptools.FieldNameForProperty(t.Multilib)
592 prefix = "multilib." + t.Multilib
593 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800594
595 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700596 // target: {
597 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800598 // key: value,
599 // },
600 // },
Colin Crossec193632015-07-06 17:49:43 -0700601 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700602 field = proptools.FieldNameForProperty(hodProperty)
603 prefix = "target." + hodProperty
604 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800605
606 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700607 // target: {
608 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800609 // key: value,
610 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700611 // not_windows: {
612 // key: value,
613 // },
614 // linux_x86: {
615 // key: value,
616 // },
617 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800618 // key: value,
619 // },
620 // },
621 var osList = []struct {
622 goos string
623 field string
624 }{
625 {"darwin", "Darwin"},
626 {"linux", "Linux"},
627 {"windows", "Windows"},
628 }
629
630 if hod.Host() {
631 for _, v := range osList {
632 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700633 field := v.field
634 prefix := "target." + v.goos
635 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700636 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700637 field = v.field + "_" + t.Name
638 prefix = "target." + v.goos + "_" + t.Name
639 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800640 }
641 }
Colin Cross06a931b2015-10-28 17:23:31 -0700642 field := "Not_windows"
643 prefix := "target.not_windows"
644 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800645 }
646
Colin Crossf8209412015-03-26 14:44:26 -0700647 // Handle 64-bit device properties in the form:
648 // target {
649 // android64 {
650 // key: value,
651 // },
652 // android32 {
653 // key: value,
654 // },
655 // },
656 // WARNING: this is probably not what you want to use in your blueprints file, it selects
657 // options for all targets on a device that supports 64-bit binaries, not just the targets
658 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
659 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
660 if hod.Device() {
661 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700662 field := "Android64"
663 prefix := "target.android64"
664 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700665 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700666 field := "Android32"
667 prefix := "target.android32"
668 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700669 }
670 }
Colin Crossb05bff22015-04-30 15:08:04 -0700671
672 // Handle device architecture properties in the form:
673 // target {
674 // android_arm {
675 // key: value,
676 // },
677 // android_x86 {
678 // key: value,
679 // },
680 // },
681 if hod.Device() {
682 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700683 field := "Android_" + t.Name
684 prefix := "target.android_" + t.Name
685 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700686 }
687
Colin Cross3f40fa42015-01-30 17:27:36 -0800688 if ctx.Failed() {
689 return
690 }
691 }
692}
693
694func forEachInterface(v reflect.Value, f func(reflect.Value)) {
695 switch v.Kind() {
696 case reflect.Interface:
697 f(v)
698 case reflect.Struct:
699 for i := 0; i < v.NumField(); i++ {
700 forEachInterface(v.Field(i), f)
701 }
702 case reflect.Ptr:
703 forEachInterface(v.Elem(), f)
704 default:
705 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
706 }
707}
Colin Cross4225f652015-09-17 14:33:42 -0700708
709// Convert the arch product variables into a list of host and device Arch structs
710func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
711 if variables.HostArch == nil {
712 return nil, nil, fmt.Errorf("No host primary architecture set")
713 }
714
715 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
716 if err != nil {
717 return nil, nil, err
718 }
719
720 hostArches := []Arch{hostArch}
721
Colin Crosseeabb892015-11-20 13:07:51 -0800722 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700723 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
724 if err != nil {
725 return nil, nil, err
726 }
727 hostArches = append(hostArches, hostSecondaryArch)
728 }
729
730 if variables.DeviceArch == nil {
731 return nil, nil, fmt.Errorf("No device primary architecture set")
732 }
733
734 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
735 variables.DeviceCpuVariant, variables.DeviceAbi)
736 if err != nil {
737 return nil, nil, err
738 }
739
740 deviceArches := []Arch{deviceArch}
741
Colin Crosseeabb892015-11-20 13:07:51 -0800742 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700743 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
744 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
745 variables.DeviceSecondaryAbi)
746 if err != nil {
747 return nil, nil, err
748 }
749 deviceArches = append(deviceArches, deviceSecondaryArch)
750 }
751
752 return hostArches, deviceArches, nil
753}
754
755// Convert a set of strings from product variables into a single Arch struct
756func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
757 stringPtr := func(p *string) string {
758 if p != nil {
759 return *p
760 }
761 return ""
762 }
763
764 slicePtr := func(p *[]string) []string {
765 if p != nil {
766 return *p
767 }
768 return nil
769 }
770
Colin Crosseeabb892015-11-20 13:07:51 -0800771 archType, ok := archTypeMap[arch]
772 if !ok {
773 return Arch{}, fmt.Errorf("unknown arch %q", arch)
774 }
Colin Cross4225f652015-09-17 14:33:42 -0700775
Colin Crosseeabb892015-11-20 13:07:51 -0800776 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700777 ArchType: archType,
778 ArchVariant: stringPtr(archVariant),
779 CpuVariant: stringPtr(cpuVariant),
780 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800781 }
782
783 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
784 a.ArchVariant = ""
785 }
786
787 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
788 a.CpuVariant = ""
789 }
790
791 for i := 0; i < len(a.Abi); i++ {
792 if a.Abi[i] == "" {
793 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
794 i--
795 }
796 }
797
Colin Crossc5c24ad2015-11-20 15:35:00 -0800798 if featureMap, ok := archFeatureMap[archType]; ok {
799 a.ArchFeatures = featureMap[stringPtr(archVariant)]
800 }
801
Colin Crosseeabb892015-11-20 13:07:51 -0800802 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -0700803}
804
805// Use the module multilib setting to select one or more arches from an arch list
806func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
807 buildArches := []Arch{}
808 switch multilib {
809 case "common":
810 buildArches = append(buildArches, commonArch)
811 case "both":
812 buildArches = append(buildArches, arches...)
813 case "first":
814 buildArches = append(buildArches, arches[0])
815 case "32":
816 for _, a := range arches {
817 if a.ArchType.Multilib == "lib32" {
818 buildArches = append(buildArches, a)
819 }
820 }
821 case "64":
822 for _, a := range arches {
823 if a.ArchType.Multilib == "lib64" {
824 buildArches = append(buildArches, a)
825 }
826 }
827 default:
828 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
829 multilib)
830 //buildArches = append(buildArches, arches[0])
831 }
832
833 return buildArches, nil
834}