blob: 8ac52e6602dc9091bd81d79fcfa80f42e275917e [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,
Colin Cross3b336c22015-11-23 16:28:31 -080052 "mips64": Mips64,
Colin Cross4225f652015-09-17 14:33:42 -070053 "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
Colin Cross023f1e82015-11-23 16:15:10 -0800155 Mips32_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
156 Mips32r2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
157 Mips32r2_fp_xburst interface{} `blueprint:"filter(android:\"arch_variant\")"`
158 Mips32r2dsp_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
159 Mips32r2dspr2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
160 Mips32r6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
161
162 // Mips arch features
Colin Cross85a88972015-11-23 13:29:51 -0800163 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 mips64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800167 Mips64 struct {
168 Embed `blueprint:"filter(android:\"arch_variant\")"`
169
170 // Mips64 arch variants
Colin Cross3b336c22015-11-23 16:28:31 -0800171 Mips64r2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
172 Mips64r6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
173
174 // Mips64 arch features
Colin Cross85a88972015-11-23 13:29:51 -0800175 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
176 }
177
Colin Cross7d5136f2015-05-11 13:39:40 -0700178 // Properties for module variants being built to run on x86 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800179 X86 struct {
180 Embed `blueprint:"filter(android:\"arch_variant\")"`
181
182 // X86 arch variants
Colin Crossb0cba6a2015-11-20 15:35:26 -0800183 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
184 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
185 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
186 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
187 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800188
189 // X86 arch features
Colin Crossb0cba6a2015-11-20 15:35:26 -0800190 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
191 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
192 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
193 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
194 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
195 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
197 Movbe interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800198 }
199
Colin Cross7d5136f2015-05-11 13:39:40 -0700200 // Properties for module variants being built to run on x86_64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800201 X86_64 struct {
202 Embed `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6371b382015-11-23 14:53:57 -0800203
204 // X86 arch variants
205 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
206 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
207 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
208 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
209
210 // X86 arch features
211 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
212 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
213 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
214 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
215 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
216 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
217 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800218 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800219 }
Colin Crossec193632015-07-06 17:49:43 -0700220
Colin Cross7d5136f2015-05-11 13:39:40 -0700221 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800222 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700223 // Properties for module variants being built to run on 32-bit devices
224 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
225 // Properties for module variants being built to run on 64-bit devices
226 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800227 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700228 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800229 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700230 // Properties for module variants being built to run on the host
231 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
232 // Properties for module variants being built to run on the device
233 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
234 // Properties for module variants being built to run on arm devices
235 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
236 // Properties for module variants being built to run on arm64 devices
237 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
238 // Properties for module variants being built to run on mips devices
239 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
240 // Properties for module variants being built to run on mips64 devices
241 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
242 // Properties for module variants being built to run on x86 devices
243 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
244 // Properties for module variants being built to run on x86_64 devices
245 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
246 // Properties for module variants being built to run on devices that support 64-bit
247 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
248 // Properties for module variants being built to run on devices that do not support 64-bit
249 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
250 // Properties for module variants being built to run on linux hosts
251 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
252 // Properties for module variants being built to run on linux x86 hosts
253 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
254 // Properties for module variants being built to run on linux x86_64 hosts
255 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
256 // Properties for module variants being built to run on darwin hosts
257 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
258 // Properties for module variants being built to run on darwin x86 hosts
259 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
260 // Properties for module variants being built to run on darwin x86_64 hosts
261 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
262 // Properties for module variants being built to run on windows hosts
263 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
264 // Properties for module variants being built to run on linux or darwin hosts
265 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800266 }
267}
268
Colin Crossc5c24ad2015-11-20 15:35:00 -0800269var archFeatureMap = map[ArchType]map[string][]string{}
270
271func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800272 archField := proptools.FieldNameForProperty(arch.Name)
273 variantField := proptools.FieldNameForProperty(variant)
274 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800275 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800276 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800277 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
278 }
279 }
280 for _, feature := range features {
281 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800282 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800283 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
284 }
285 }
286 if archFeatureMap[arch] == nil {
287 archFeatureMap[arch] = make(map[string][]string)
288 }
289 archFeatureMap[arch][variant] = features
290}
291
Colin Cross3f40fa42015-01-30 17:27:36 -0800292// An Arch indicates a single CPU architecture.
293type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800294 ArchType ArchType
295 ArchVariant string
296 CpuVariant string
297 Abi []string
298 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800299}
300
301func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700302 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800303 if a.ArchVariant != "" {
304 s += "_" + a.ArchVariant
305 }
306 if a.CpuVariant != "" {
307 s += "_" + a.CpuVariant
308 }
309 return s
310}
311
312type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700313 Name string
314 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800315}
316
Colin Crossec193632015-07-06 17:49:43 -0700317func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800318 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700319 Name: name,
320 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800321 }
322}
323
324func (a ArchType) String() string {
325 return a.Name
326}
327
328type HostOrDeviceSupported int
329
330const (
331 _ HostOrDeviceSupported = iota
332 HostSupported
333 DeviceSupported
334 HostAndDeviceSupported
335)
336
337type HostOrDevice int
338
339const (
340 _ HostOrDevice = iota
341 Host
342 Device
343)
344
345func (hod HostOrDevice) String() string {
346 switch hod {
347 case Device:
348 return "device"
349 case Host:
350 return "host"
351 default:
352 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
353 }
354}
355
Colin Crossec193632015-07-06 17:49:43 -0700356func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800357 switch hod {
358 case Device:
359 return "android"
360 case Host:
361 return "host"
362 default:
363 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
364 }
365}
366
Colin Cross3f40fa42015-01-30 17:27:36 -0800367func (hod HostOrDevice) Host() bool {
368 if hod == 0 {
369 panic("HostOrDevice unset")
370 }
371 return hod == Host
372}
373
374func (hod HostOrDevice) Device() bool {
375 if hod == 0 {
376 panic("HostOrDevice unset")
377 }
378 return hod == Device
379}
380
381var hostOrDeviceName = map[HostOrDevice]string{
382 Device: "device",
383 Host: "host",
384}
385
386var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700387 commonArch = Arch{
388 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700389 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800390)
391
Colin Cross6362e272015-10-29 15:25:03 -0700392func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700393 var module AndroidModule
394 var ok bool
395 if module, ok = mctx.Module().(AndroidModule); !ok {
396 return
397 }
398
399 hods := []HostOrDevice{}
400
401 if module.base().HostSupported() {
402 hods = append(hods, Host)
403 }
404
405 if module.base().DeviceSupported() {
406 hods = append(hods, Device)
407 }
408
409 if len(hods) == 0 {
410 return
411 }
412
413 hodNames := []string{}
414 for _, hod := range hods {
415 hodNames = append(hodNames, hod.String())
416 }
417
418 modules := mctx.CreateVariations(hodNames...)
419 for i, m := range modules {
420 m.(AndroidModule).base().SetHostOrDevice(hods[i])
421 }
422}
423
Colin Cross6362e272015-10-29 15:25:03 -0700424func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800425 var module AndroidModule
426 var ok bool
427 if module, ok = mctx.Module().(AndroidModule); !ok {
428 return
429 }
430
Colin Cross4225f652015-09-17 14:33:42 -0700431 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
432 if err != nil {
433 mctx.ModuleErrorf("%s", err.Error())
434 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800435
Colin Cross4225f652015-09-17 14:33:42 -0700436 moduleArches := []Arch{}
437 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800438
Colin Crossd3ba0392015-05-07 14:11:29 -0700439 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700440 hostModuleArches, err := decodeMultilib(multilib, hostArches)
441 if err != nil {
442 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700443 }
Colin Cross4225f652015-09-17 14:33:42 -0700444
445 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800446 }
447
Colin Crossd3ba0392015-05-07 14:11:29 -0700448 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700449 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
450 if err != nil {
451 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800452 }
Colin Cross4225f652015-09-17 14:33:42 -0700453
454 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800455 }
456
Colin Cross4225f652015-09-17 14:33:42 -0700457 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700458 return
459 }
460
Colin Cross3f40fa42015-01-30 17:27:36 -0800461 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700462 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800463 archNames = append(archNames, arch.String())
464 }
465
466 modules := mctx.CreateVariations(archNames...)
467
468 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700469 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700470 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800471 }
472}
473
Colin Crosscfad1192015-11-02 16:43:11 -0800474func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800475 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
476
477 base := m.base()
478
Colin Cross3f40fa42015-01-30 17:27:36 -0800479 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800480 propertyStructs...)
481
482 for _, properties := range base.generalProperties {
483 propertiesValue := reflect.ValueOf(properties)
484 if propertiesValue.Kind() != reflect.Ptr {
485 panic("properties must be a pointer to a struct")
486 }
487
488 propertiesValue = propertiesValue.Elem()
489 if propertiesValue.Kind() != reflect.Struct {
490 panic("properties must be a pointer to a struct")
491 }
492
493 archProperties := &archProperties{}
494 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700495 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800496 v.Set(newValue)
497 })
498
499 base.archProperties = append(base.archProperties, archProperties)
500 }
501
502 var allProperties []interface{}
503 allProperties = append(allProperties, base.generalProperties...)
504 for _, asp := range base.archProperties {
505 allProperties = append(allProperties, asp)
506 }
507
508 return m, allProperties
509}
510
Colin Crossec193632015-07-06 17:49:43 -0700511var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
512
Colin Cross6362e272015-10-29 15:25:03 -0700513func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800514 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700515
Colin Crosseeabb892015-11-20 13:07:51 -0800516 srcField := reflect.ValueOf(src).FieldByName(field)
517 if !srcField.IsValid() {
518 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800519 return nil
520 }
521
522 ret := srcField
523
524 if srcField.Kind() == reflect.Struct {
525 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800526 }
527
528 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700529
530 filter := func(property string,
531 dstField, srcField reflect.StructField,
532 dstValue, srcValue interface{}) (bool, error) {
533
534 srcProperty := srcPrefix + "." + property
535
536 if !proptools.HasTag(dstField, "android", "arch_variant") {
537 if ctx.ContainsProperty(srcProperty) {
538 return false, fmt.Errorf("can't be specific to a build variant")
539 } else {
540 return false, nil
541 }
542 }
543
544 return true, nil
545 }
546
547 err := proptools.AppendProperties(dst, src, filter)
548 if err != nil {
549 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
550 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
551 } else {
552 panic(err)
553 }
554 }
Colin Cross85a88972015-11-23 13:29:51 -0800555
556 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700557}
558
Colin Cross3f40fa42015-01-30 17:27:36 -0800559// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700560func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700561 arch := a.commonProperties.CompileArch
562 hod := a.commonProperties.CompileHostOrDevice
563
Colin Cross2fe66872015-03-30 17:20:39 -0700564 if arch.ArchType == Common {
565 return
566 }
567
Colin Cross3f40fa42015-01-30 17:27:36 -0800568 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700569 genProps := a.generalProperties[i]
570 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800571 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700572 // arch: {
573 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800574 // key: value,
575 // },
576 // },
577 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700578
Colin Crossec193632015-07-06 17:49:43 -0700579 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700580 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800581 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700582
583 // Handle arch-variant-specific properties in the form:
584 // arch: {
585 // variant: {
586 // key: value,
587 // },
588 // },
589 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
590 if v != "" {
591 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800592 prefix := "arch." + t.Name + "." + v
593 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700594 }
595
596 // Handle cpu-variant-specific properties in the form:
597 // arch: {
598 // variant: {
599 // key: value,
600 // },
601 // },
602 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
603 if c != "" {
604 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800605 prefix := "arch." + t.Name + "." + c
606 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700607 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800608
Colin Crossc5c24ad2015-11-20 15:35:00 -0800609 // Handle arch-feature-specific properties in the form:
610 // arch: {
611 // feature: {
612 // key: value,
613 // },
614 // },
615 for _, feature := range arch.ArchFeatures {
616 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800617 prefix := "arch." + t.Name + "." + feature
618 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800619 }
620
Colin Cross3f40fa42015-01-30 17:27:36 -0800621 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700622 // multilib: {
623 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800624 // key: value,
625 // },
626 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700627 field = proptools.FieldNameForProperty(t.Multilib)
628 prefix = "multilib." + t.Multilib
629 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800630
631 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700632 // target: {
633 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800634 // key: value,
635 // },
636 // },
Colin Crossec193632015-07-06 17:49:43 -0700637 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700638 field = proptools.FieldNameForProperty(hodProperty)
639 prefix = "target." + hodProperty
640 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800641
642 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700643 // target: {
644 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800645 // key: value,
646 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700647 // not_windows: {
648 // key: value,
649 // },
650 // linux_x86: {
651 // key: value,
652 // },
653 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800654 // key: value,
655 // },
656 // },
657 var osList = []struct {
658 goos string
659 field string
660 }{
661 {"darwin", "Darwin"},
662 {"linux", "Linux"},
663 {"windows", "Windows"},
664 }
665
666 if hod.Host() {
667 for _, v := range osList {
668 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700669 field := v.field
670 prefix := "target." + v.goos
671 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700672 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700673 field = v.field + "_" + t.Name
674 prefix = "target." + v.goos + "_" + t.Name
675 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800676 }
677 }
Colin Cross06a931b2015-10-28 17:23:31 -0700678 field := "Not_windows"
679 prefix := "target.not_windows"
680 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800681 }
682
Colin Crossf8209412015-03-26 14:44:26 -0700683 // Handle 64-bit device properties in the form:
684 // target {
685 // android64 {
686 // key: value,
687 // },
688 // android32 {
689 // key: value,
690 // },
691 // },
692 // WARNING: this is probably not what you want to use in your blueprints file, it selects
693 // options for all targets on a device that supports 64-bit binaries, not just the targets
694 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
695 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
696 if hod.Device() {
697 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700698 field := "Android64"
699 prefix := "target.android64"
700 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700701 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700702 field := "Android32"
703 prefix := "target.android32"
704 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700705 }
706 }
Colin Crossb05bff22015-04-30 15:08:04 -0700707
708 // Handle device architecture properties in the form:
709 // target {
710 // android_arm {
711 // key: value,
712 // },
713 // android_x86 {
714 // key: value,
715 // },
716 // },
717 if hod.Device() {
718 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700719 field := "Android_" + t.Name
720 prefix := "target.android_" + t.Name
721 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700722 }
723
Colin Cross3f40fa42015-01-30 17:27:36 -0800724 if ctx.Failed() {
725 return
726 }
727 }
728}
729
730func forEachInterface(v reflect.Value, f func(reflect.Value)) {
731 switch v.Kind() {
732 case reflect.Interface:
733 f(v)
734 case reflect.Struct:
735 for i := 0; i < v.NumField(); i++ {
736 forEachInterface(v.Field(i), f)
737 }
738 case reflect.Ptr:
739 forEachInterface(v.Elem(), f)
740 default:
741 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
742 }
743}
Colin Cross4225f652015-09-17 14:33:42 -0700744
745// Convert the arch product variables into a list of host and device Arch structs
746func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
747 if variables.HostArch == nil {
748 return nil, nil, fmt.Errorf("No host primary architecture set")
749 }
750
751 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
752 if err != nil {
753 return nil, nil, err
754 }
755
756 hostArches := []Arch{hostArch}
757
Colin Crosseeabb892015-11-20 13:07:51 -0800758 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700759 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
760 if err != nil {
761 return nil, nil, err
762 }
763 hostArches = append(hostArches, hostSecondaryArch)
764 }
765
766 if variables.DeviceArch == nil {
767 return nil, nil, fmt.Errorf("No device primary architecture set")
768 }
769
770 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
771 variables.DeviceCpuVariant, variables.DeviceAbi)
772 if err != nil {
773 return nil, nil, err
774 }
775
776 deviceArches := []Arch{deviceArch}
777
Colin Crosseeabb892015-11-20 13:07:51 -0800778 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700779 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
780 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
781 variables.DeviceSecondaryAbi)
782 if err != nil {
783 return nil, nil, err
784 }
785 deviceArches = append(deviceArches, deviceSecondaryArch)
786 }
787
788 return hostArches, deviceArches, nil
789}
790
791// Convert a set of strings from product variables into a single Arch struct
792func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
793 stringPtr := func(p *string) string {
794 if p != nil {
795 return *p
796 }
797 return ""
798 }
799
800 slicePtr := func(p *[]string) []string {
801 if p != nil {
802 return *p
803 }
804 return nil
805 }
806
Colin Crosseeabb892015-11-20 13:07:51 -0800807 archType, ok := archTypeMap[arch]
808 if !ok {
809 return Arch{}, fmt.Errorf("unknown arch %q", arch)
810 }
Colin Cross4225f652015-09-17 14:33:42 -0700811
Colin Crosseeabb892015-11-20 13:07:51 -0800812 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700813 ArchType: archType,
814 ArchVariant: stringPtr(archVariant),
815 CpuVariant: stringPtr(cpuVariant),
816 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800817 }
818
819 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
820 a.ArchVariant = ""
821 }
822
823 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
824 a.CpuVariant = ""
825 }
826
827 for i := 0; i < len(a.Abi); i++ {
828 if a.Abi[i] == "" {
829 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
830 i--
831 }
832 }
833
Colin Crossc5c24ad2015-11-20 15:35:00 -0800834 if featureMap, ok := archFeatureMap[archType]; ok {
835 a.ArchFeatures = featureMap[stringPtr(archVariant)]
836 }
837
Colin Crosseeabb892015-11-20 13:07:51 -0800838 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -0700839}
840
841// Use the module multilib setting to select one or more arches from an arch list
842func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
843 buildArches := []Arch{}
844 switch multilib {
845 case "common":
846 buildArches = append(buildArches, commonArch)
847 case "both":
848 buildArches = append(buildArches, arches...)
849 case "first":
850 buildArches = append(buildArches, arches[0])
851 case "32":
852 for _, a := range arches {
853 if a.ArchType.Multilib == "lib32" {
854 buildArches = append(buildArches, a)
855 }
856 }
857 case "64":
858 for _, a := range arches {
859 if a.ArchType.Multilib == "lib64" {
860 buildArches = append(buildArches, a)
861 }
862 }
863 default:
864 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
865 multilib)
866 //buildArches = append(buildArches, arches[0])
867 }
868
869 return buildArches, nil
870}