blob: 62d6980b0f9a25285cc2603cd95dd05edb5babb9 [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
Colin Crossb0cba6a2015-11-20 15:35:26 -0800171 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
172 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
173 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
174 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
175 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800176
177 // X86 arch features
Colin Crossb0cba6a2015-11-20 15:35:26 -0800178 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
179 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
180 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
181 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
182 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
183 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
184 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
185 Movbe interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800186 }
187
Colin Cross7d5136f2015-05-11 13:39:40 -0700188 // Properties for module variants being built to run on x86_64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800189 X86_64 struct {
190 Embed `blueprint:"filter(android:\"arch_variant\")"`
191 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800192 }
Colin Crossec193632015-07-06 17:49:43 -0700193
Colin Cross7d5136f2015-05-11 13:39:40 -0700194 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800195 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700196 // Properties for module variants being built to run on 32-bit devices
197 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
198 // Properties for module variants being built to run on 64-bit devices
199 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800200 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700201 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800202 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700203 // Properties for module variants being built to run on the host
204 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
205 // Properties for module variants being built to run on the device
206 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
207 // Properties for module variants being built to run on arm devices
208 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
209 // Properties for module variants being built to run on arm64 devices
210 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
211 // Properties for module variants being built to run on mips devices
212 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
213 // Properties for module variants being built to run on mips64 devices
214 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
215 // Properties for module variants being built to run on x86 devices
216 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
217 // Properties for module variants being built to run on x86_64 devices
218 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
219 // Properties for module variants being built to run on devices that support 64-bit
220 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
221 // Properties for module variants being built to run on devices that do not support 64-bit
222 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
223 // Properties for module variants being built to run on linux hosts
224 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
225 // Properties for module variants being built to run on linux x86 hosts
226 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
227 // Properties for module variants being built to run on linux x86_64 hosts
228 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
229 // Properties for module variants being built to run on darwin hosts
230 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
231 // Properties for module variants being built to run on darwin x86 hosts
232 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
233 // Properties for module variants being built to run on darwin x86_64 hosts
234 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
235 // Properties for module variants being built to run on windows hosts
236 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
237 // Properties for module variants being built to run on linux or darwin hosts
238 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800239 }
240}
241
Colin Crossc5c24ad2015-11-20 15:35:00 -0800242var archFeatureMap = map[ArchType]map[string][]string{}
243
244func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800245 archField := proptools.FieldNameForProperty(arch.Name)
246 variantField := proptools.FieldNameForProperty(variant)
247 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800248 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800249 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800250 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
251 }
252 }
253 for _, feature := range features {
254 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800255 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800256 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
257 }
258 }
259 if archFeatureMap[arch] == nil {
260 archFeatureMap[arch] = make(map[string][]string)
261 }
262 archFeatureMap[arch][variant] = features
263}
264
Colin Cross3f40fa42015-01-30 17:27:36 -0800265// An Arch indicates a single CPU architecture.
266type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800267 ArchType ArchType
268 ArchVariant string
269 CpuVariant string
270 Abi []string
271 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800272}
273
274func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700275 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800276 if a.ArchVariant != "" {
277 s += "_" + a.ArchVariant
278 }
279 if a.CpuVariant != "" {
280 s += "_" + a.CpuVariant
281 }
282 return s
283}
284
285type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700286 Name string
287 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800288}
289
Colin Crossec193632015-07-06 17:49:43 -0700290func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800291 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700292 Name: name,
293 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800294 }
295}
296
297func (a ArchType) String() string {
298 return a.Name
299}
300
301type HostOrDeviceSupported int
302
303const (
304 _ HostOrDeviceSupported = iota
305 HostSupported
306 DeviceSupported
307 HostAndDeviceSupported
308)
309
310type HostOrDevice int
311
312const (
313 _ HostOrDevice = iota
314 Host
315 Device
316)
317
318func (hod HostOrDevice) String() string {
319 switch hod {
320 case Device:
321 return "device"
322 case Host:
323 return "host"
324 default:
325 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
326 }
327}
328
Colin Crossec193632015-07-06 17:49:43 -0700329func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800330 switch hod {
331 case Device:
332 return "android"
333 case Host:
334 return "host"
335 default:
336 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
337 }
338}
339
Colin Cross3f40fa42015-01-30 17:27:36 -0800340func (hod HostOrDevice) Host() bool {
341 if hod == 0 {
342 panic("HostOrDevice unset")
343 }
344 return hod == Host
345}
346
347func (hod HostOrDevice) Device() bool {
348 if hod == 0 {
349 panic("HostOrDevice unset")
350 }
351 return hod == Device
352}
353
354var hostOrDeviceName = map[HostOrDevice]string{
355 Device: "device",
356 Host: "host",
357}
358
359var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700360 commonArch = Arch{
361 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700362 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800363)
364
Colin Cross6362e272015-10-29 15:25:03 -0700365func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700366 var module AndroidModule
367 var ok bool
368 if module, ok = mctx.Module().(AndroidModule); !ok {
369 return
370 }
371
372 hods := []HostOrDevice{}
373
374 if module.base().HostSupported() {
375 hods = append(hods, Host)
376 }
377
378 if module.base().DeviceSupported() {
379 hods = append(hods, Device)
380 }
381
382 if len(hods) == 0 {
383 return
384 }
385
386 hodNames := []string{}
387 for _, hod := range hods {
388 hodNames = append(hodNames, hod.String())
389 }
390
391 modules := mctx.CreateVariations(hodNames...)
392 for i, m := range modules {
393 m.(AndroidModule).base().SetHostOrDevice(hods[i])
394 }
395}
396
Colin Cross6362e272015-10-29 15:25:03 -0700397func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800398 var module AndroidModule
399 var ok bool
400 if module, ok = mctx.Module().(AndroidModule); !ok {
401 return
402 }
403
Colin Cross4225f652015-09-17 14:33:42 -0700404 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
405 if err != nil {
406 mctx.ModuleErrorf("%s", err.Error())
407 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800408
Colin Cross4225f652015-09-17 14:33:42 -0700409 moduleArches := []Arch{}
410 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800411
Colin Crossd3ba0392015-05-07 14:11:29 -0700412 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700413 hostModuleArches, err := decodeMultilib(multilib, hostArches)
414 if err != nil {
415 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700416 }
Colin Cross4225f652015-09-17 14:33:42 -0700417
418 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800419 }
420
Colin Crossd3ba0392015-05-07 14:11:29 -0700421 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700422 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
423 if err != nil {
424 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800425 }
Colin Cross4225f652015-09-17 14:33:42 -0700426
427 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800428 }
429
Colin Cross4225f652015-09-17 14:33:42 -0700430 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700431 return
432 }
433
Colin Cross3f40fa42015-01-30 17:27:36 -0800434 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700435 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800436 archNames = append(archNames, arch.String())
437 }
438
439 modules := mctx.CreateVariations(archNames...)
440
441 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700442 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700443 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800444 }
445}
446
Colin Crosscfad1192015-11-02 16:43:11 -0800447func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800448 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
449
450 base := m.base()
451
Colin Cross3f40fa42015-01-30 17:27:36 -0800452 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800453 propertyStructs...)
454
455 for _, properties := range base.generalProperties {
456 propertiesValue := reflect.ValueOf(properties)
457 if propertiesValue.Kind() != reflect.Ptr {
458 panic("properties must be a pointer to a struct")
459 }
460
461 propertiesValue = propertiesValue.Elem()
462 if propertiesValue.Kind() != reflect.Struct {
463 panic("properties must be a pointer to a struct")
464 }
465
466 archProperties := &archProperties{}
467 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700468 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800469 v.Set(newValue)
470 })
471
472 base.archProperties = append(base.archProperties, archProperties)
473 }
474
475 var allProperties []interface{}
476 allProperties = append(allProperties, base.generalProperties...)
477 for _, asp := range base.archProperties {
478 allProperties = append(allProperties, asp)
479 }
480
481 return m, allProperties
482}
483
Colin Crossec193632015-07-06 17:49:43 -0700484var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
485
Colin Cross6362e272015-10-29 15:25:03 -0700486func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800487 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700488
Colin Crosseeabb892015-11-20 13:07:51 -0800489 srcField := reflect.ValueOf(src).FieldByName(field)
490 if !srcField.IsValid() {
491 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800492 return nil
493 }
494
495 ret := srcField
496
497 if srcField.Kind() == reflect.Struct {
498 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800499 }
500
501 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700502
503 filter := func(property string,
504 dstField, srcField reflect.StructField,
505 dstValue, srcValue interface{}) (bool, error) {
506
507 srcProperty := srcPrefix + "." + property
508
509 if !proptools.HasTag(dstField, "android", "arch_variant") {
510 if ctx.ContainsProperty(srcProperty) {
511 return false, fmt.Errorf("can't be specific to a build variant")
512 } else {
513 return false, nil
514 }
515 }
516
517 return true, nil
518 }
519
520 err := proptools.AppendProperties(dst, src, filter)
521 if err != nil {
522 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
523 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
524 } else {
525 panic(err)
526 }
527 }
Colin Cross85a88972015-11-23 13:29:51 -0800528
529 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700530}
531
Colin Cross3f40fa42015-01-30 17:27:36 -0800532// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700533func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700534 arch := a.commonProperties.CompileArch
535 hod := a.commonProperties.CompileHostOrDevice
536
Colin Cross2fe66872015-03-30 17:20:39 -0700537 if arch.ArchType == Common {
538 return
539 }
540
Colin Cross3f40fa42015-01-30 17:27:36 -0800541 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700542 genProps := a.generalProperties[i]
543 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800544 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700545 // arch: {
546 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800547 // key: value,
548 // },
549 // },
550 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700551
Colin Crossec193632015-07-06 17:49:43 -0700552 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700553 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800554 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700555
556 // Handle arch-variant-specific properties in the form:
557 // arch: {
558 // variant: {
559 // key: value,
560 // },
561 // },
562 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
563 if v != "" {
564 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800565 prefix := "arch." + t.Name + "." + v
566 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700567 }
568
569 // Handle cpu-variant-specific properties in the form:
570 // arch: {
571 // variant: {
572 // key: value,
573 // },
574 // },
575 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
576 if c != "" {
577 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800578 prefix := "arch." + t.Name + "." + c
579 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700580 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800581
Colin Crossc5c24ad2015-11-20 15:35:00 -0800582 // Handle arch-feature-specific properties in the form:
583 // arch: {
584 // feature: {
585 // key: value,
586 // },
587 // },
588 for _, feature := range arch.ArchFeatures {
589 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800590 prefix := "arch." + t.Name + "." + feature
591 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800592 }
593
Colin Cross3f40fa42015-01-30 17:27:36 -0800594 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700595 // multilib: {
596 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800597 // key: value,
598 // },
599 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700600 field = proptools.FieldNameForProperty(t.Multilib)
601 prefix = "multilib." + t.Multilib
602 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800603
604 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700605 // target: {
606 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800607 // key: value,
608 // },
609 // },
Colin Crossec193632015-07-06 17:49:43 -0700610 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700611 field = proptools.FieldNameForProperty(hodProperty)
612 prefix = "target." + hodProperty
613 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800614
615 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700616 // target: {
617 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800618 // key: value,
619 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700620 // not_windows: {
621 // key: value,
622 // },
623 // linux_x86: {
624 // key: value,
625 // },
626 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800627 // key: value,
628 // },
629 // },
630 var osList = []struct {
631 goos string
632 field string
633 }{
634 {"darwin", "Darwin"},
635 {"linux", "Linux"},
636 {"windows", "Windows"},
637 }
638
639 if hod.Host() {
640 for _, v := range osList {
641 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700642 field := v.field
643 prefix := "target." + v.goos
644 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700645 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700646 field = v.field + "_" + t.Name
647 prefix = "target." + v.goos + "_" + t.Name
648 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800649 }
650 }
Colin Cross06a931b2015-10-28 17:23:31 -0700651 field := "Not_windows"
652 prefix := "target.not_windows"
653 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800654 }
655
Colin Crossf8209412015-03-26 14:44:26 -0700656 // Handle 64-bit device properties in the form:
657 // target {
658 // android64 {
659 // key: value,
660 // },
661 // android32 {
662 // key: value,
663 // },
664 // },
665 // WARNING: this is probably not what you want to use in your blueprints file, it selects
666 // options for all targets on a device that supports 64-bit binaries, not just the targets
667 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
668 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
669 if hod.Device() {
670 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700671 field := "Android64"
672 prefix := "target.android64"
673 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700674 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700675 field := "Android32"
676 prefix := "target.android32"
677 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700678 }
679 }
Colin Crossb05bff22015-04-30 15:08:04 -0700680
681 // Handle device architecture properties in the form:
682 // target {
683 // android_arm {
684 // key: value,
685 // },
686 // android_x86 {
687 // key: value,
688 // },
689 // },
690 if hod.Device() {
691 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700692 field := "Android_" + t.Name
693 prefix := "target.android_" + t.Name
694 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700695 }
696
Colin Cross3f40fa42015-01-30 17:27:36 -0800697 if ctx.Failed() {
698 return
699 }
700 }
701}
702
703func forEachInterface(v reflect.Value, f func(reflect.Value)) {
704 switch v.Kind() {
705 case reflect.Interface:
706 f(v)
707 case reflect.Struct:
708 for i := 0; i < v.NumField(); i++ {
709 forEachInterface(v.Field(i), f)
710 }
711 case reflect.Ptr:
712 forEachInterface(v.Elem(), f)
713 default:
714 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
715 }
716}
Colin Cross4225f652015-09-17 14:33:42 -0700717
718// Convert the arch product variables into a list of host and device Arch structs
719func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
720 if variables.HostArch == nil {
721 return nil, nil, fmt.Errorf("No host primary architecture set")
722 }
723
724 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
725 if err != nil {
726 return nil, nil, err
727 }
728
729 hostArches := []Arch{hostArch}
730
Colin Crosseeabb892015-11-20 13:07:51 -0800731 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700732 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
733 if err != nil {
734 return nil, nil, err
735 }
736 hostArches = append(hostArches, hostSecondaryArch)
737 }
738
739 if variables.DeviceArch == nil {
740 return nil, nil, fmt.Errorf("No device primary architecture set")
741 }
742
743 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
744 variables.DeviceCpuVariant, variables.DeviceAbi)
745 if err != nil {
746 return nil, nil, err
747 }
748
749 deviceArches := []Arch{deviceArch}
750
Colin Crosseeabb892015-11-20 13:07:51 -0800751 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700752 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
753 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
754 variables.DeviceSecondaryAbi)
755 if err != nil {
756 return nil, nil, err
757 }
758 deviceArches = append(deviceArches, deviceSecondaryArch)
759 }
760
761 return hostArches, deviceArches, nil
762}
763
764// Convert a set of strings from product variables into a single Arch struct
765func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
766 stringPtr := func(p *string) string {
767 if p != nil {
768 return *p
769 }
770 return ""
771 }
772
773 slicePtr := func(p *[]string) []string {
774 if p != nil {
775 return *p
776 }
777 return nil
778 }
779
Colin Crosseeabb892015-11-20 13:07:51 -0800780 archType, ok := archTypeMap[arch]
781 if !ok {
782 return Arch{}, fmt.Errorf("unknown arch %q", arch)
783 }
Colin Cross4225f652015-09-17 14:33:42 -0700784
Colin Crosseeabb892015-11-20 13:07:51 -0800785 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700786 ArchType: archType,
787 ArchVariant: stringPtr(archVariant),
788 CpuVariant: stringPtr(cpuVariant),
789 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800790 }
791
792 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
793 a.ArchVariant = ""
794 }
795
796 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
797 a.CpuVariant = ""
798 }
799
800 for i := 0; i < len(a.Abi); i++ {
801 if a.Abi[i] == "" {
802 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
803 i--
804 }
805 }
806
Colin Crossc5c24ad2015-11-20 15:35:00 -0800807 if featureMap, ok := archFeatureMap[archType]; ok {
808 a.ArchFeatures = featureMap[stringPtr(archVariant)]
809 }
810
Colin Crosseeabb892015-11-20 13:07:51 -0800811 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -0700812}
813
814// Use the module multilib setting to select one or more arches from an arch list
815func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
816 buildArches := []Arch{}
817 switch multilib {
818 case "common":
819 buildArches = append(buildArches, commonArch)
820 case "both":
821 buildArches = append(buildArches, arches...)
822 case "first":
823 buildArches = append(buildArches, arches[0])
824 case "32":
825 for _, a := range arches {
826 if a.ArchType.Multilib == "lib32" {
827 buildArches = append(buildArches, a)
828 }
829 }
830 case "64":
831 for _, a := range arches {
832 if a.ArchType.Multilib == "lib64" {
833 buildArches = append(buildArches, a)
834 }
835 }
836 default:
837 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
838 multilib)
839 //buildArches = append(buildArches, arches[0])
840 }
841
842 return buildArches, nil
843}