blob: 4cddc00e1c99abde9d92f3c1a3d5fde9f904ba83 [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)
Dan Willemsen490fd492015-11-24 17:53:15 -080032 RegisterBottomUpMutator("host_type", HostTypeMutator)
Colin Cross6362e272015-10-29 15:25:03 -070033 RegisterBottomUpMutator("arch", ArchMutator)
Colin Cross463a90e2015-06-17 14:20:06 -070034}
35
Colin Cross3f40fa42015-01-30 17:27:36 -080036var (
Colin Crossec193632015-07-06 17:49:43 -070037 Arm = newArch("arm", "lib32")
38 Arm64 = newArch("arm64", "lib64")
39 Mips = newArch("mips", "lib32")
40 Mips64 = newArch("mips64", "lib64")
41 X86 = newArch("x86", "lib32")
42 X86_64 = newArch("x86_64", "lib64")
Colin Cross2fe66872015-03-30 17:20:39 -070043
44 Common = ArchType{
45 Name: "common",
46 }
Colin Cross3f40fa42015-01-30 17:27:36 -080047)
48
Colin Cross4225f652015-09-17 14:33:42 -070049var archTypeMap = map[string]ArchType{
50 "arm": Arm,
51 "arm64": Arm64,
52 "mips": Mips,
Colin Cross3b336c22015-11-23 16:28:31 -080053 "mips64": Mips64,
Colin Cross4225f652015-09-17 14:33:42 -070054 "x86": X86,
55 "x86_64": X86_64,
56}
57
Colin Cross3f40fa42015-01-30 17:27:36 -080058/*
59Example blueprints file containing all variant property groups, with comment listing what type
60of variants get properties in that group:
61
62module {
63 arch: {
64 arm: {
65 // Host or device variants with arm architecture
66 },
67 arm64: {
68 // Host or device variants with arm64 architecture
69 },
70 mips: {
71 // Host or device variants with mips architecture
72 },
73 mips64: {
74 // Host or device variants with mips64 architecture
75 },
76 x86: {
77 // Host or device variants with x86 architecture
78 },
79 x86_64: {
80 // Host or device variants with x86_64 architecture
81 },
82 },
83 multilib: {
84 lib32: {
85 // Host or device variants for 32-bit architectures
86 },
87 lib64: {
88 // Host or device variants for 64-bit architectures
89 },
90 },
91 target: {
92 android: {
93 // Device variants
94 },
95 host: {
96 // Host variants
97 },
98 linux: {
99 // Linux host variants
100 },
101 darwin: {
102 // Darwin host variants
103 },
104 windows: {
105 // Windows host variants
106 },
107 not_windows: {
108 // Non-windows host variants
109 },
110 },
111}
112*/
Colin Cross7d5136f2015-05-11 13:39:40 -0700113
Colin Cross85a88972015-11-23 13:29:51 -0800114type Embed interface{}
115
Colin Cross3f40fa42015-01-30 17:27:36 -0800116type archProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700117 // Properties to vary by target architecture
Colin Cross3f40fa42015-01-30 17:27:36 -0800118 Arch struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700119 // Properties for module variants being built to run on arm (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800120 Arm struct {
121 Embed `blueprint:"filter(android:\"arch_variant\")"`
122
123 // Arm arch variants
124 Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"`
125 Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
126 Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"`
127
128 // Arm cpu variants
129 Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"`
130 Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"`
131 Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"`
132 Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"`
133 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
134 Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"`
135 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
136 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
137 }
138
Colin Cross7d5136f2015-05-11 13:39:40 -0700139 // Properties for module variants being built to run on arm64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800140 Arm64 struct {
141 Embed `blueprint:"filter(android:\"arch_variant\")"`
142
143 // Arm64 arch variants
144 Armv8_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
145
146 // Arm64 cpu variants
147 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
148 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
149 }
150
Colin Cross7d5136f2015-05-11 13:39:40 -0700151 // Properties for module variants being built to run on mips (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800152 Mips struct {
153 Embed `blueprint:"filter(android:\"arch_variant\")"`
154
155 // Mips arch variants
Colin Cross023f1e82015-11-23 16:15:10 -0800156 Mips32_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
157 Mips32r2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
158 Mips32r2_fp_xburst interface{} `blueprint:"filter(android:\"arch_variant\")"`
159 Mips32r2dsp_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
160 Mips32r2dspr2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
161 Mips32r6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
162
163 // Mips arch features
Colin Cross85a88972015-11-23 13:29:51 -0800164 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
165 }
166
Colin Cross7d5136f2015-05-11 13:39:40 -0700167 // Properties for module variants being built to run on mips64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800168 Mips64 struct {
169 Embed `blueprint:"filter(android:\"arch_variant\")"`
170
171 // Mips64 arch variants
Colin Cross3b336c22015-11-23 16:28:31 -0800172 Mips64r2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
173 Mips64r6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
174
175 // Mips64 arch features
Colin Cross85a88972015-11-23 13:29:51 -0800176 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
177 }
178
Colin Cross7d5136f2015-05-11 13:39:40 -0700179 // Properties for module variants being built to run on x86 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800180 X86 struct {
181 Embed `blueprint:"filter(android:\"arch_variant\")"`
182
183 // X86 arch variants
Colin Crossb0cba6a2015-11-20 15:35:26 -0800184 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
185 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
186 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
187 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
188 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800189
190 // X86 arch features
Colin Crossb0cba6a2015-11-20 15:35:26 -0800191 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
192 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
193 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
194 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
195 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
197 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
198 Movbe interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800199 }
200
Colin Cross7d5136f2015-05-11 13:39:40 -0700201 // Properties for module variants being built to run on x86_64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800202 X86_64 struct {
203 Embed `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6371b382015-11-23 14:53:57 -0800204
205 // X86 arch variants
206 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
207 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
208 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
209 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
210
211 // X86 arch features
212 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
213 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
214 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
215 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
216 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
217 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
218 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800219 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800220 }
Colin Crossec193632015-07-06 17:49:43 -0700221
Colin Cross7d5136f2015-05-11 13:39:40 -0700222 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800223 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700224 // Properties for module variants being built to run on 32-bit devices
225 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
226 // Properties for module variants being built to run on 64-bit devices
227 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800228 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700229 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800230 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700231 // Properties for module variants being built to run on the host
232 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
233 // Properties for module variants being built to run on the device
234 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
235 // Properties for module variants being built to run on arm devices
236 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
237 // Properties for module variants being built to run on arm64 devices
238 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
239 // Properties for module variants being built to run on mips devices
240 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
241 // Properties for module variants being built to run on mips64 devices
242 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
243 // Properties for module variants being built to run on x86 devices
244 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
245 // Properties for module variants being built to run on x86_64 devices
246 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
247 // Properties for module variants being built to run on devices that support 64-bit
248 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
249 // Properties for module variants being built to run on devices that do not support 64-bit
250 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
251 // Properties for module variants being built to run on linux hosts
252 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
253 // Properties for module variants being built to run on linux x86 hosts
254 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
255 // Properties for module variants being built to run on linux x86_64 hosts
256 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
257 // Properties for module variants being built to run on darwin hosts
258 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
259 // Properties for module variants being built to run on darwin x86 hosts
260 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
261 // Properties for module variants being built to run on darwin x86_64 hosts
262 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
263 // Properties for module variants being built to run on windows hosts
264 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Dan Willemsen490fd492015-11-24 17:53:15 -0800265 // Properties for module variants being built to run on windows x86 hosts
266 Windows_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross7d5136f2015-05-11 13:39:40 -0700267 // Properties for module variants being built to run on linux or darwin hosts
268 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800269 }
270}
271
Colin Crossc5c24ad2015-11-20 15:35:00 -0800272var archFeatureMap = map[ArchType]map[string][]string{}
273
274func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800275 archField := proptools.FieldNameForProperty(arch.Name)
276 variantField := proptools.FieldNameForProperty(variant)
277 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800278 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800279 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800280 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
281 }
282 }
283 for _, feature := range features {
284 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800285 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800286 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
287 }
288 }
289 if archFeatureMap[arch] == nil {
290 archFeatureMap[arch] = make(map[string][]string)
291 }
292 archFeatureMap[arch][variant] = features
293}
294
Colin Cross3f40fa42015-01-30 17:27:36 -0800295// An Arch indicates a single CPU architecture.
296type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800297 ArchType ArchType
298 ArchVariant string
299 CpuVariant string
300 Abi []string
301 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800302}
303
304func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700305 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800306 if a.ArchVariant != "" {
307 s += "_" + a.ArchVariant
308 }
309 if a.CpuVariant != "" {
310 s += "_" + a.CpuVariant
311 }
312 return s
313}
314
315type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700316 Name string
317 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800318}
319
Colin Crossec193632015-07-06 17:49:43 -0700320func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800321 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700322 Name: name,
323 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800324 }
325}
326
327func (a ArchType) String() string {
328 return a.Name
329}
330
331type HostOrDeviceSupported int
332
333const (
334 _ HostOrDeviceSupported = iota
335 HostSupported
336 DeviceSupported
337 HostAndDeviceSupported
338)
339
340type HostOrDevice int
341
342const (
343 _ HostOrDevice = iota
344 Host
345 Device
346)
347
348func (hod HostOrDevice) String() string {
349 switch hod {
350 case Device:
351 return "device"
352 case Host:
353 return "host"
354 default:
355 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
356 }
357}
358
Colin Crossec193632015-07-06 17:49:43 -0700359func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800360 switch hod {
361 case Device:
362 return "android"
363 case Host:
364 return "host"
365 default:
366 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
367 }
368}
369
Colin Cross3f40fa42015-01-30 17:27:36 -0800370func (hod HostOrDevice) Host() bool {
371 if hod == 0 {
372 panic("HostOrDevice unset")
373 }
374 return hod == Host
375}
376
377func (hod HostOrDevice) Device() bool {
378 if hod == 0 {
379 panic("HostOrDevice unset")
380 }
381 return hod == Device
382}
383
384var hostOrDeviceName = map[HostOrDevice]string{
385 Device: "device",
386 Host: "host",
387}
388
Dan Willemsen490fd492015-11-24 17:53:15 -0800389type HostType int
390
391const (
392 NoHostType HostType = iota
393 Linux
394 Darwin
395 Windows
396)
397
398func CurrentHostType() HostType {
399 switch runtime.GOOS {
400 case "linux":
401 return Linux
402 case "darwin":
403 return Darwin
404 default:
405 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
406 }
407}
408
409func (ht HostType) String() string {
410 switch ht {
411 case Linux:
412 return "linux"
413 case Darwin:
414 return "darwin"
415 case Windows:
416 return "windows"
417 default:
418 panic(fmt.Sprintf("unexpected HostType value %d", ht))
419 }
420}
421
422func (ht HostType) Field() string {
423 switch ht {
424 case Linux:
425 return "Linux"
426 case Darwin:
427 return "Darwin"
428 case Windows:
429 return "Windows"
430 default:
431 panic(fmt.Sprintf("unexpected HostType value %d", ht))
432 }
433}
434
Colin Cross3f40fa42015-01-30 17:27:36 -0800435var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700436 commonArch = Arch{
437 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700438 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800439)
440
Colin Cross6362e272015-10-29 15:25:03 -0700441func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700442 var module AndroidModule
443 var ok bool
444 if module, ok = mctx.Module().(AndroidModule); !ok {
445 return
446 }
447
448 hods := []HostOrDevice{}
449
450 if module.base().HostSupported() {
451 hods = append(hods, Host)
452 }
453
454 if module.base().DeviceSupported() {
455 hods = append(hods, Device)
456 }
457
458 if len(hods) == 0 {
459 return
460 }
461
462 hodNames := []string{}
463 for _, hod := range hods {
464 hodNames = append(hodNames, hod.String())
465 }
466
467 modules := mctx.CreateVariations(hodNames...)
468 for i, m := range modules {
469 m.(AndroidModule).base().SetHostOrDevice(hods[i])
470 }
471}
472
Dan Willemsen490fd492015-11-24 17:53:15 -0800473func HostTypeMutator(mctx AndroidBottomUpMutatorContext) {
474 var module AndroidModule
475 var ok bool
476 if module, ok = mctx.Module().(AndroidModule); !ok {
477 return
478 }
479
480 if !module.base().HostSupported() || !module.base().HostOrDevice().Host() {
481 return
482 }
483
484 buildTypes, err := decodeHostTypesProductVariables(mctx.Config().(Config).ProductVariables)
485 if err != nil {
486 mctx.ModuleErrorf("%s", err.Error())
487 return
488 }
489
490 typeNames := []string{}
491 for _, ht := range buildTypes {
492 typeNames = append(typeNames, ht.String())
493 }
494
495 modules := mctx.CreateVariations(typeNames...)
496 for i, m := range modules {
497 m.(AndroidModule).base().SetHostType(buildTypes[i])
498 }
499}
500
Colin Cross6362e272015-10-29 15:25:03 -0700501func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800502 var module AndroidModule
503 var ok bool
504 if module, ok = mctx.Module().(AndroidModule); !ok {
505 return
506 }
507
Colin Cross4225f652015-09-17 14:33:42 -0700508 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
509 if err != nil {
510 mctx.ModuleErrorf("%s", err.Error())
511 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800512
Colin Cross4225f652015-09-17 14:33:42 -0700513 moduleArches := []Arch{}
514 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800515
Colin Crossd3ba0392015-05-07 14:11:29 -0700516 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Dan Willemsen490fd492015-11-24 17:53:15 -0800517 hostModuleArches, err := decodeMultilib(multilib, hostArches[module.base().HostType()])
Colin Cross4225f652015-09-17 14:33:42 -0700518 if err != nil {
519 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700520 }
Colin Cross4225f652015-09-17 14:33:42 -0700521
522 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800523 }
524
Colin Crossd3ba0392015-05-07 14:11:29 -0700525 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700526 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
527 if err != nil {
528 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800529 }
Colin Cross4225f652015-09-17 14:33:42 -0700530
531 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800532 }
533
Colin Cross4225f652015-09-17 14:33:42 -0700534 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700535 return
536 }
537
Colin Cross3f40fa42015-01-30 17:27:36 -0800538 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700539 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800540 archNames = append(archNames, arch.String())
541 }
542
543 modules := mctx.CreateVariations(archNames...)
544
545 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700546 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700547 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800548 }
549}
550
Colin Crosscfad1192015-11-02 16:43:11 -0800551func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800552 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
553
554 base := m.base()
555
Colin Cross3f40fa42015-01-30 17:27:36 -0800556 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800557 propertyStructs...)
558
559 for _, properties := range base.generalProperties {
560 propertiesValue := reflect.ValueOf(properties)
561 if propertiesValue.Kind() != reflect.Ptr {
562 panic("properties must be a pointer to a struct")
563 }
564
565 propertiesValue = propertiesValue.Elem()
566 if propertiesValue.Kind() != reflect.Struct {
567 panic("properties must be a pointer to a struct")
568 }
569
570 archProperties := &archProperties{}
571 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700572 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800573 v.Set(newValue)
574 })
575
576 base.archProperties = append(base.archProperties, archProperties)
577 }
578
579 var allProperties []interface{}
580 allProperties = append(allProperties, base.generalProperties...)
581 for _, asp := range base.archProperties {
582 allProperties = append(allProperties, asp)
583 }
584
585 return m, allProperties
586}
587
Colin Crossec193632015-07-06 17:49:43 -0700588var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
589
Colin Cross6362e272015-10-29 15:25:03 -0700590func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800591 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700592
Colin Crosseeabb892015-11-20 13:07:51 -0800593 srcField := reflect.ValueOf(src).FieldByName(field)
594 if !srcField.IsValid() {
595 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800596 return nil
597 }
598
599 ret := srcField
600
601 if srcField.Kind() == reflect.Struct {
602 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800603 }
604
605 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700606
607 filter := func(property string,
608 dstField, srcField reflect.StructField,
609 dstValue, srcValue interface{}) (bool, error) {
610
611 srcProperty := srcPrefix + "." + property
612
613 if !proptools.HasTag(dstField, "android", "arch_variant") {
614 if ctx.ContainsProperty(srcProperty) {
615 return false, fmt.Errorf("can't be specific to a build variant")
616 } else {
617 return false, nil
618 }
619 }
620
621 return true, nil
622 }
623
624 err := proptools.AppendProperties(dst, src, filter)
625 if err != nil {
626 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
627 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
628 } else {
629 panic(err)
630 }
631 }
Colin Cross85a88972015-11-23 13:29:51 -0800632
633 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700634}
635
Colin Cross3f40fa42015-01-30 17:27:36 -0800636// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700637func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700638 arch := a.commonProperties.CompileArch
639 hod := a.commonProperties.CompileHostOrDevice
Dan Willemsen490fd492015-11-24 17:53:15 -0800640 ht := a.commonProperties.CompileHostType
Colin Crossd3ba0392015-05-07 14:11:29 -0700641
Colin Cross2fe66872015-03-30 17:20:39 -0700642 if arch.ArchType == Common {
643 return
644 }
645
Colin Cross3f40fa42015-01-30 17:27:36 -0800646 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700647 genProps := a.generalProperties[i]
648 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800649 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700650 // arch: {
651 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800652 // key: value,
653 // },
654 // },
655 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700656
Colin Crossec193632015-07-06 17:49:43 -0700657 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700658 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800659 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700660
661 // Handle arch-variant-specific properties in the form:
662 // arch: {
663 // variant: {
664 // key: value,
665 // },
666 // },
667 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
668 if v != "" {
669 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800670 prefix := "arch." + t.Name + "." + v
671 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700672 }
673
674 // Handle cpu-variant-specific properties in the form:
675 // arch: {
676 // variant: {
677 // key: value,
678 // },
679 // },
680 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
681 if c != "" {
682 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800683 prefix := "arch." + t.Name + "." + c
684 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700685 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800686
Colin Crossc5c24ad2015-11-20 15:35:00 -0800687 // Handle arch-feature-specific properties in the form:
688 // arch: {
689 // feature: {
690 // key: value,
691 // },
692 // },
693 for _, feature := range arch.ArchFeatures {
694 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800695 prefix := "arch." + t.Name + "." + feature
696 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800697 }
698
Colin Cross3f40fa42015-01-30 17:27:36 -0800699 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700700 // multilib: {
701 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800702 // key: value,
703 // },
704 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700705 field = proptools.FieldNameForProperty(t.Multilib)
706 prefix = "multilib." + t.Multilib
707 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800708
709 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700710 // target: {
711 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800712 // key: value,
713 // },
714 // },
Colin Crossec193632015-07-06 17:49:43 -0700715 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700716 field = proptools.FieldNameForProperty(hodProperty)
717 prefix = "target." + hodProperty
718 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800719
720 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700721 // target: {
722 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800723 // key: value,
724 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700725 // not_windows: {
726 // key: value,
727 // },
728 // linux_x86: {
729 // key: value,
730 // },
731 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800732 // key: value,
733 // },
734 // },
Colin Cross3f40fa42015-01-30 17:27:36 -0800735 if hod.Host() {
Dan Willemsen490fd492015-11-24 17:53:15 -0800736 field := ht.Field()
737 prefix := "target." + ht.String()
Colin Cross06a931b2015-10-28 17:23:31 -0700738 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Dan Willemsen490fd492015-11-24 17:53:15 -0800739
740 t := arch.ArchType
741 field = ht.Field() + "_" + t.Name
742 prefix = "target." + ht.String() + "_" + t.Name
743 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
744
745 if ht != Windows {
746 field := "Not_windows"
747 prefix := "target.not_windows"
748 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
749 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800750 }
751
Colin Crossf8209412015-03-26 14:44:26 -0700752 // Handle 64-bit device properties in the form:
753 // target {
754 // android64 {
755 // key: value,
756 // },
757 // android32 {
758 // key: value,
759 // },
760 // },
761 // WARNING: this is probably not what you want to use in your blueprints file, it selects
762 // options for all targets on a device that supports 64-bit binaries, not just the targets
763 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
764 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
765 if hod.Device() {
766 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700767 field := "Android64"
768 prefix := "target.android64"
769 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700770 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700771 field := "Android32"
772 prefix := "target.android32"
773 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700774 }
775 }
Colin Crossb05bff22015-04-30 15:08:04 -0700776
777 // Handle device architecture properties in the form:
778 // target {
779 // android_arm {
780 // key: value,
781 // },
782 // android_x86 {
783 // key: value,
784 // },
785 // },
786 if hod.Device() {
787 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700788 field := "Android_" + t.Name
789 prefix := "target.android_" + t.Name
790 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700791 }
792
Colin Cross3f40fa42015-01-30 17:27:36 -0800793 if ctx.Failed() {
794 return
795 }
796 }
797}
798
799func forEachInterface(v reflect.Value, f func(reflect.Value)) {
800 switch v.Kind() {
801 case reflect.Interface:
802 f(v)
803 case reflect.Struct:
804 for i := 0; i < v.NumField(); i++ {
805 forEachInterface(v.Field(i), f)
806 }
807 case reflect.Ptr:
808 forEachInterface(v.Elem(), f)
809 default:
810 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
811 }
812}
Colin Cross4225f652015-09-17 14:33:42 -0700813
Dan Willemsen490fd492015-11-24 17:53:15 -0800814// Get a list of HostTypes from the product variables
815func decodeHostTypesProductVariables(variables productVariables) ([]HostType, error) {
816 ret := []HostType{CurrentHostType()}
817
818 if variables.CrossHost != nil && *variables.CrossHost != "" {
819 switch *variables.CrossHost {
820 case "windows":
821 ret = append(ret, Windows)
822 default:
823 return nil, fmt.Errorf("Unsupported secondary host: %s", *variables.CrossHost)
824 }
825 }
826
827 return ret, nil
828}
829
Colin Cross4225f652015-09-17 14:33:42 -0700830// Convert the arch product variables into a list of host and device Arch structs
Dan Willemsen490fd492015-11-24 17:53:15 -0800831func decodeArchProductVariables(variables productVariables) (map[HostType][]Arch, []Arch, error) {
Colin Cross4225f652015-09-17 14:33:42 -0700832 if variables.HostArch == nil {
833 return nil, nil, fmt.Errorf("No host primary architecture set")
834 }
835
836 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
837 if err != nil {
838 return nil, nil, err
839 }
840
841 hostArches := []Arch{hostArch}
842
Colin Crosseeabb892015-11-20 13:07:51 -0800843 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700844 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
845 if err != nil {
846 return nil, nil, err
847 }
848 hostArches = append(hostArches, hostSecondaryArch)
849 }
850
Dan Willemsen490fd492015-11-24 17:53:15 -0800851 hostTypeArches := map[HostType][]Arch{
852 CurrentHostType(): hostArches,
853 }
854
855 if variables.CrossHost != nil && *variables.CrossHost != "" {
856 if variables.CrossHostArch == nil || *variables.CrossHostArch == "" {
857 return nil, nil, fmt.Errorf("No cross-host primary architecture set")
858 }
859
860 crossHostArch, err := decodeArch(*variables.CrossHostArch, nil, nil, nil)
861 if err != nil {
862 return nil, nil, err
863 }
864
865 crossHostArches := []Arch{crossHostArch}
866
867 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
868 crossHostSecondaryArch, err := decodeArch(*variables.CrossHostSecondaryArch, nil, nil, nil)
869 if err != nil {
870 return nil, nil, err
871 }
872 crossHostArches = append(crossHostArches, crossHostSecondaryArch)
873 }
874
875 switch *variables.CrossHost {
876 case "windows":
877 hostTypeArches[Windows] = crossHostArches
878 default:
879 return nil, nil, fmt.Errorf("Unsupported cross-host: %s", *variables.CrossHost)
880 }
881 }
882
Colin Cross4225f652015-09-17 14:33:42 -0700883 if variables.DeviceArch == nil {
884 return nil, nil, fmt.Errorf("No device primary architecture set")
885 }
886
887 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
888 variables.DeviceCpuVariant, variables.DeviceAbi)
889 if err != nil {
890 return nil, nil, err
891 }
892
893 deviceArches := []Arch{deviceArch}
894
Colin Crosseeabb892015-11-20 13:07:51 -0800895 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700896 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
897 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
898 variables.DeviceSecondaryAbi)
899 if err != nil {
900 return nil, nil, err
901 }
902 deviceArches = append(deviceArches, deviceSecondaryArch)
903 }
904
Dan Willemsen490fd492015-11-24 17:53:15 -0800905 return hostTypeArches, deviceArches, nil
Colin Cross4225f652015-09-17 14:33:42 -0700906}
907
908// Convert a set of strings from product variables into a single Arch struct
909func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
910 stringPtr := func(p *string) string {
911 if p != nil {
912 return *p
913 }
914 return ""
915 }
916
917 slicePtr := func(p *[]string) []string {
918 if p != nil {
919 return *p
920 }
921 return nil
922 }
923
Colin Crosseeabb892015-11-20 13:07:51 -0800924 archType, ok := archTypeMap[arch]
925 if !ok {
926 return Arch{}, fmt.Errorf("unknown arch %q", arch)
927 }
Colin Cross4225f652015-09-17 14:33:42 -0700928
Colin Crosseeabb892015-11-20 13:07:51 -0800929 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700930 ArchType: archType,
931 ArchVariant: stringPtr(archVariant),
932 CpuVariant: stringPtr(cpuVariant),
933 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800934 }
935
936 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
937 a.ArchVariant = ""
938 }
939
940 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
941 a.CpuVariant = ""
942 }
943
944 for i := 0; i < len(a.Abi); i++ {
945 if a.Abi[i] == "" {
946 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
947 i--
948 }
949 }
950
Colin Crossc5c24ad2015-11-20 15:35:00 -0800951 if featureMap, ok := archFeatureMap[archType]; ok {
952 a.ArchFeatures = featureMap[stringPtr(archVariant)]
953 }
954
Colin Crosseeabb892015-11-20 13:07:51 -0800955 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -0700956}
957
958// Use the module multilib setting to select one or more arches from an arch list
959func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
960 buildArches := []Arch{}
961 switch multilib {
962 case "common":
963 buildArches = append(buildArches, commonArch)
964 case "both":
965 buildArches = append(buildArches, arches...)
966 case "first":
967 buildArches = append(buildArches, arches[0])
968 case "32":
969 for _, a := range arches {
970 if a.ArchType.Multilib == "lib32" {
971 buildArches = append(buildArches, a)
972 }
973 }
974 case "64":
975 for _, a := range arches {
976 if a.ArchType.Multilib == "lib64" {
977 buildArches = append(buildArches, a)
978 }
979 }
980 default:
981 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
982 multilib)
983 //buildArches = append(buildArches, arches[0])
984 }
985
986 return buildArches, nil
987}