blob: 4753f5a32b9fa46396e468dfee6709c183b99dbc [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\")"`
Colin Cross6371b382015-11-23 14:53:57 -0800191
192 // X86 arch variants
193 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
194 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
195 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
197
198 // X86 arch features
199 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
200 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
201 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
202 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
203 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
204 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
205 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800206 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800207 }
Colin Crossec193632015-07-06 17:49:43 -0700208
Colin Cross7d5136f2015-05-11 13:39:40 -0700209 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800210 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700211 // Properties for module variants being built to run on 32-bit devices
212 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
213 // Properties for module variants being built to run on 64-bit devices
214 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800215 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700216 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800217 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700218 // Properties for module variants being built to run on the host
219 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
220 // Properties for module variants being built to run on the device
221 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
222 // Properties for module variants being built to run on arm devices
223 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
224 // Properties for module variants being built to run on arm64 devices
225 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
226 // Properties for module variants being built to run on mips devices
227 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
228 // Properties for module variants being built to run on mips64 devices
229 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
230 // Properties for module variants being built to run on x86 devices
231 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
232 // Properties for module variants being built to run on x86_64 devices
233 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
234 // Properties for module variants being built to run on devices that support 64-bit
235 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
236 // Properties for module variants being built to run on devices that do not support 64-bit
237 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
238 // Properties for module variants being built to run on linux hosts
239 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
240 // Properties for module variants being built to run on linux x86 hosts
241 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
242 // Properties for module variants being built to run on linux x86_64 hosts
243 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
244 // Properties for module variants being built to run on darwin hosts
245 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
246 // Properties for module variants being built to run on darwin x86 hosts
247 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
248 // Properties for module variants being built to run on darwin x86_64 hosts
249 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
250 // Properties for module variants being built to run on windows hosts
251 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
252 // Properties for module variants being built to run on linux or darwin hosts
253 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800254 }
255}
256
Colin Crossc5c24ad2015-11-20 15:35:00 -0800257var archFeatureMap = map[ArchType]map[string][]string{}
258
259func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800260 archField := proptools.FieldNameForProperty(arch.Name)
261 variantField := proptools.FieldNameForProperty(variant)
262 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800263 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800264 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800265 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
266 }
267 }
268 for _, feature := range features {
269 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800270 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800271 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
272 }
273 }
274 if archFeatureMap[arch] == nil {
275 archFeatureMap[arch] = make(map[string][]string)
276 }
277 archFeatureMap[arch][variant] = features
278}
279
Colin Cross3f40fa42015-01-30 17:27:36 -0800280// An Arch indicates a single CPU architecture.
281type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800282 ArchType ArchType
283 ArchVariant string
284 CpuVariant string
285 Abi []string
286 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800287}
288
289func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700290 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800291 if a.ArchVariant != "" {
292 s += "_" + a.ArchVariant
293 }
294 if a.CpuVariant != "" {
295 s += "_" + a.CpuVariant
296 }
297 return s
298}
299
300type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700301 Name string
302 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800303}
304
Colin Crossec193632015-07-06 17:49:43 -0700305func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800306 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700307 Name: name,
308 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800309 }
310}
311
312func (a ArchType) String() string {
313 return a.Name
314}
315
316type HostOrDeviceSupported int
317
318const (
319 _ HostOrDeviceSupported = iota
320 HostSupported
321 DeviceSupported
322 HostAndDeviceSupported
323)
324
325type HostOrDevice int
326
327const (
328 _ HostOrDevice = iota
329 Host
330 Device
331)
332
333func (hod HostOrDevice) String() string {
334 switch hod {
335 case Device:
336 return "device"
337 case Host:
338 return "host"
339 default:
340 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
341 }
342}
343
Colin Crossec193632015-07-06 17:49:43 -0700344func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800345 switch hod {
346 case Device:
347 return "android"
348 case Host:
349 return "host"
350 default:
351 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
352 }
353}
354
Colin Cross3f40fa42015-01-30 17:27:36 -0800355func (hod HostOrDevice) Host() bool {
356 if hod == 0 {
357 panic("HostOrDevice unset")
358 }
359 return hod == Host
360}
361
362func (hod HostOrDevice) Device() bool {
363 if hod == 0 {
364 panic("HostOrDevice unset")
365 }
366 return hod == Device
367}
368
369var hostOrDeviceName = map[HostOrDevice]string{
370 Device: "device",
371 Host: "host",
372}
373
374var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700375 commonArch = Arch{
376 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700377 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800378)
379
Colin Cross6362e272015-10-29 15:25:03 -0700380func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700381 var module AndroidModule
382 var ok bool
383 if module, ok = mctx.Module().(AndroidModule); !ok {
384 return
385 }
386
387 hods := []HostOrDevice{}
388
389 if module.base().HostSupported() {
390 hods = append(hods, Host)
391 }
392
393 if module.base().DeviceSupported() {
394 hods = append(hods, Device)
395 }
396
397 if len(hods) == 0 {
398 return
399 }
400
401 hodNames := []string{}
402 for _, hod := range hods {
403 hodNames = append(hodNames, hod.String())
404 }
405
406 modules := mctx.CreateVariations(hodNames...)
407 for i, m := range modules {
408 m.(AndroidModule).base().SetHostOrDevice(hods[i])
409 }
410}
411
Colin Cross6362e272015-10-29 15:25:03 -0700412func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800413 var module AndroidModule
414 var ok bool
415 if module, ok = mctx.Module().(AndroidModule); !ok {
416 return
417 }
418
Colin Cross4225f652015-09-17 14:33:42 -0700419 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
420 if err != nil {
421 mctx.ModuleErrorf("%s", err.Error())
422 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800423
Colin Cross4225f652015-09-17 14:33:42 -0700424 moduleArches := []Arch{}
425 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800426
Colin Crossd3ba0392015-05-07 14:11:29 -0700427 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700428 hostModuleArches, err := decodeMultilib(multilib, hostArches)
429 if err != nil {
430 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700431 }
Colin Cross4225f652015-09-17 14:33:42 -0700432
433 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800434 }
435
Colin Crossd3ba0392015-05-07 14:11:29 -0700436 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700437 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
438 if err != nil {
439 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800440 }
Colin Cross4225f652015-09-17 14:33:42 -0700441
442 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800443 }
444
Colin Cross4225f652015-09-17 14:33:42 -0700445 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700446 return
447 }
448
Colin Cross3f40fa42015-01-30 17:27:36 -0800449 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700450 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800451 archNames = append(archNames, arch.String())
452 }
453
454 modules := mctx.CreateVariations(archNames...)
455
456 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700457 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700458 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800459 }
460}
461
Colin Crosscfad1192015-11-02 16:43:11 -0800462func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800463 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
464
465 base := m.base()
466
Colin Cross3f40fa42015-01-30 17:27:36 -0800467 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800468 propertyStructs...)
469
470 for _, properties := range base.generalProperties {
471 propertiesValue := reflect.ValueOf(properties)
472 if propertiesValue.Kind() != reflect.Ptr {
473 panic("properties must be a pointer to a struct")
474 }
475
476 propertiesValue = propertiesValue.Elem()
477 if propertiesValue.Kind() != reflect.Struct {
478 panic("properties must be a pointer to a struct")
479 }
480
481 archProperties := &archProperties{}
482 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700483 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800484 v.Set(newValue)
485 })
486
487 base.archProperties = append(base.archProperties, archProperties)
488 }
489
490 var allProperties []interface{}
491 allProperties = append(allProperties, base.generalProperties...)
492 for _, asp := range base.archProperties {
493 allProperties = append(allProperties, asp)
494 }
495
496 return m, allProperties
497}
498
Colin Crossec193632015-07-06 17:49:43 -0700499var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
500
Colin Cross6362e272015-10-29 15:25:03 -0700501func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800502 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700503
Colin Crosseeabb892015-11-20 13:07:51 -0800504 srcField := reflect.ValueOf(src).FieldByName(field)
505 if !srcField.IsValid() {
506 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800507 return nil
508 }
509
510 ret := srcField
511
512 if srcField.Kind() == reflect.Struct {
513 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800514 }
515
516 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700517
518 filter := func(property string,
519 dstField, srcField reflect.StructField,
520 dstValue, srcValue interface{}) (bool, error) {
521
522 srcProperty := srcPrefix + "." + property
523
524 if !proptools.HasTag(dstField, "android", "arch_variant") {
525 if ctx.ContainsProperty(srcProperty) {
526 return false, fmt.Errorf("can't be specific to a build variant")
527 } else {
528 return false, nil
529 }
530 }
531
532 return true, nil
533 }
534
535 err := proptools.AppendProperties(dst, src, filter)
536 if err != nil {
537 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
538 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
539 } else {
540 panic(err)
541 }
542 }
Colin Cross85a88972015-11-23 13:29:51 -0800543
544 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700545}
546
Colin Cross3f40fa42015-01-30 17:27:36 -0800547// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700548func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700549 arch := a.commonProperties.CompileArch
550 hod := a.commonProperties.CompileHostOrDevice
551
Colin Cross2fe66872015-03-30 17:20:39 -0700552 if arch.ArchType == Common {
553 return
554 }
555
Colin Cross3f40fa42015-01-30 17:27:36 -0800556 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700557 genProps := a.generalProperties[i]
558 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800559 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700560 // arch: {
561 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800562 // key: value,
563 // },
564 // },
565 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700566
Colin Crossec193632015-07-06 17:49:43 -0700567 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700568 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800569 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700570
571 // Handle arch-variant-specific properties in the form:
572 // arch: {
573 // variant: {
574 // key: value,
575 // },
576 // },
577 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
578 if v != "" {
579 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800580 prefix := "arch." + t.Name + "." + v
581 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700582 }
583
584 // Handle cpu-variant-specific properties in the form:
585 // arch: {
586 // variant: {
587 // key: value,
588 // },
589 // },
590 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
591 if c != "" {
592 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800593 prefix := "arch." + t.Name + "." + c
594 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700595 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800596
Colin Crossc5c24ad2015-11-20 15:35:00 -0800597 // Handle arch-feature-specific properties in the form:
598 // arch: {
599 // feature: {
600 // key: value,
601 // },
602 // },
603 for _, feature := range arch.ArchFeatures {
604 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800605 prefix := "arch." + t.Name + "." + feature
606 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800607 }
608
Colin Cross3f40fa42015-01-30 17:27:36 -0800609 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700610 // multilib: {
611 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800612 // key: value,
613 // },
614 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700615 field = proptools.FieldNameForProperty(t.Multilib)
616 prefix = "multilib." + t.Multilib
617 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800618
619 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700620 // target: {
621 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800622 // key: value,
623 // },
624 // },
Colin Crossec193632015-07-06 17:49:43 -0700625 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700626 field = proptools.FieldNameForProperty(hodProperty)
627 prefix = "target." + hodProperty
628 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800629
630 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700631 // target: {
632 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800633 // key: value,
634 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700635 // not_windows: {
636 // key: value,
637 // },
638 // linux_x86: {
639 // key: value,
640 // },
641 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800642 // key: value,
643 // },
644 // },
645 var osList = []struct {
646 goos string
647 field string
648 }{
649 {"darwin", "Darwin"},
650 {"linux", "Linux"},
651 {"windows", "Windows"},
652 }
653
654 if hod.Host() {
655 for _, v := range osList {
656 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700657 field := v.field
658 prefix := "target." + v.goos
659 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700660 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700661 field = v.field + "_" + t.Name
662 prefix = "target." + v.goos + "_" + t.Name
663 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800664 }
665 }
Colin Cross06a931b2015-10-28 17:23:31 -0700666 field := "Not_windows"
667 prefix := "target.not_windows"
668 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800669 }
670
Colin Crossf8209412015-03-26 14:44:26 -0700671 // Handle 64-bit device properties in the form:
672 // target {
673 // android64 {
674 // key: value,
675 // },
676 // android32 {
677 // key: value,
678 // },
679 // },
680 // WARNING: this is probably not what you want to use in your blueprints file, it selects
681 // options for all targets on a device that supports 64-bit binaries, not just the targets
682 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
683 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
684 if hod.Device() {
685 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700686 field := "Android64"
687 prefix := "target.android64"
688 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700689 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700690 field := "Android32"
691 prefix := "target.android32"
692 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700693 }
694 }
Colin Crossb05bff22015-04-30 15:08:04 -0700695
696 // Handle device architecture properties in the form:
697 // target {
698 // android_arm {
699 // key: value,
700 // },
701 // android_x86 {
702 // key: value,
703 // },
704 // },
705 if hod.Device() {
706 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700707 field := "Android_" + t.Name
708 prefix := "target.android_" + t.Name
709 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700710 }
711
Colin Cross3f40fa42015-01-30 17:27:36 -0800712 if ctx.Failed() {
713 return
714 }
715 }
716}
717
718func forEachInterface(v reflect.Value, f func(reflect.Value)) {
719 switch v.Kind() {
720 case reflect.Interface:
721 f(v)
722 case reflect.Struct:
723 for i := 0; i < v.NumField(); i++ {
724 forEachInterface(v.Field(i), f)
725 }
726 case reflect.Ptr:
727 forEachInterface(v.Elem(), f)
728 default:
729 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
730 }
731}
Colin Cross4225f652015-09-17 14:33:42 -0700732
733// Convert the arch product variables into a list of host and device Arch structs
734func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
735 if variables.HostArch == nil {
736 return nil, nil, fmt.Errorf("No host primary architecture set")
737 }
738
739 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
740 if err != nil {
741 return nil, nil, err
742 }
743
744 hostArches := []Arch{hostArch}
745
Colin Crosseeabb892015-11-20 13:07:51 -0800746 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700747 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
748 if err != nil {
749 return nil, nil, err
750 }
751 hostArches = append(hostArches, hostSecondaryArch)
752 }
753
754 if variables.DeviceArch == nil {
755 return nil, nil, fmt.Errorf("No device primary architecture set")
756 }
757
758 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
759 variables.DeviceCpuVariant, variables.DeviceAbi)
760 if err != nil {
761 return nil, nil, err
762 }
763
764 deviceArches := []Arch{deviceArch}
765
Colin Crosseeabb892015-11-20 13:07:51 -0800766 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700767 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
768 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
769 variables.DeviceSecondaryAbi)
770 if err != nil {
771 return nil, nil, err
772 }
773 deviceArches = append(deviceArches, deviceSecondaryArch)
774 }
775
776 return hostArches, deviceArches, nil
777}
778
779// Convert a set of strings from product variables into a single Arch struct
780func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
781 stringPtr := func(p *string) string {
782 if p != nil {
783 return *p
784 }
785 return ""
786 }
787
788 slicePtr := func(p *[]string) []string {
789 if p != nil {
790 return *p
791 }
792 return nil
793 }
794
Colin Crosseeabb892015-11-20 13:07:51 -0800795 archType, ok := archTypeMap[arch]
796 if !ok {
797 return Arch{}, fmt.Errorf("unknown arch %q", arch)
798 }
Colin Cross4225f652015-09-17 14:33:42 -0700799
Colin Crosseeabb892015-11-20 13:07:51 -0800800 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700801 ArchType: archType,
802 ArchVariant: stringPtr(archVariant),
803 CpuVariant: stringPtr(cpuVariant),
804 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800805 }
806
807 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
808 a.ArchVariant = ""
809 }
810
811 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
812 a.CpuVariant = ""
813 }
814
815 for i := 0; i < len(a.Abi); i++ {
816 if a.Abi[i] == "" {
817 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
818 i--
819 }
820 }
821
Colin Crossc5c24ad2015-11-20 15:35:00 -0800822 if featureMap, ok := archFeatureMap[archType]; ok {
823 a.ArchFeatures = featureMap[stringPtr(archVariant)]
824 }
825
Colin Crosseeabb892015-11-20 13:07:51 -0800826 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -0700827}
828
829// Use the module multilib setting to select one or more arches from an arch list
830func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
831 buildArches := []Arch{}
832 switch multilib {
833 case "common":
834 buildArches = append(buildArches, commonArch)
835 case "both":
836 buildArches = append(buildArches, arches...)
837 case "first":
838 buildArches = append(buildArches, arches[0])
839 case "32":
840 for _, a := range arches {
841 if a.ArchType.Multilib == "lib32" {
842 buildArches = append(buildArches, a)
843 }
844 }
845 case "64":
846 for _, a := range arches {
847 if a.ArchType.Multilib == "lib64" {
848 buildArches = append(buildArches, a)
849 }
850 }
851 default:
852 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
853 multilib)
854 //buildArches = append(buildArches, arches[0])
855 }
856
857 return buildArches, nil
858}