blob: ee1cfae635e8a89e8a3577cc93ba6b25cefe35aa [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\")"`
Dan Willemsen07cd0512016-02-03 23:16:33 -0800267 // Properties for module variants being built to run on windows x86_64 hosts
268 Windows_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross7d5136f2015-05-11 13:39:40 -0700269 // Properties for module variants being built to run on linux or darwin hosts
270 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800271 }
272}
273
Colin Crossc5c24ad2015-11-20 15:35:00 -0800274var archFeatureMap = map[ArchType]map[string][]string{}
275
276func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800277 archField := proptools.FieldNameForProperty(arch.Name)
278 variantField := proptools.FieldNameForProperty(variant)
279 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800280 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800281 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800282 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
283 }
284 }
285 for _, feature := range features {
286 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800287 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800288 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
289 }
290 }
291 if archFeatureMap[arch] == nil {
292 archFeatureMap[arch] = make(map[string][]string)
293 }
294 archFeatureMap[arch][variant] = features
295}
296
Colin Cross3f40fa42015-01-30 17:27:36 -0800297// An Arch indicates a single CPU architecture.
298type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800299 ArchType ArchType
300 ArchVariant string
301 CpuVariant string
302 Abi []string
303 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800304}
305
306func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700307 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800308 if a.ArchVariant != "" {
309 s += "_" + a.ArchVariant
310 }
311 if a.CpuVariant != "" {
312 s += "_" + a.CpuVariant
313 }
314 return s
315}
316
317type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700318 Name string
319 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800320}
321
Colin Crossec193632015-07-06 17:49:43 -0700322func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800323 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700324 Name: name,
325 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800326 }
327}
328
329func (a ArchType) String() string {
330 return a.Name
331}
332
333type HostOrDeviceSupported int
334
335const (
336 _ HostOrDeviceSupported = iota
337 HostSupported
338 DeviceSupported
339 HostAndDeviceSupported
Dan Willemsen218f6562015-07-08 18:13:11 -0700340 HostAndDeviceDefault
Colin Cross3f40fa42015-01-30 17:27:36 -0800341)
342
343type HostOrDevice int
344
345const (
346 _ HostOrDevice = iota
347 Host
348 Device
349)
350
351func (hod HostOrDevice) String() string {
352 switch hod {
353 case Device:
354 return "device"
355 case Host:
356 return "host"
357 default:
358 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
359 }
360}
361
Colin Crossec193632015-07-06 17:49:43 -0700362func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800363 switch hod {
364 case Device:
365 return "android"
366 case Host:
367 return "host"
368 default:
369 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
370 }
371}
372
Colin Cross3f40fa42015-01-30 17:27:36 -0800373func (hod HostOrDevice) Host() bool {
374 if hod == 0 {
375 panic("HostOrDevice unset")
376 }
377 return hod == Host
378}
379
380func (hod HostOrDevice) Device() bool {
381 if hod == 0 {
382 panic("HostOrDevice unset")
383 }
384 return hod == Device
385}
386
387var hostOrDeviceName = map[HostOrDevice]string{
388 Device: "device",
389 Host: "host",
390}
391
Dan Willemsen490fd492015-11-24 17:53:15 -0800392type HostType int
393
394const (
395 NoHostType HostType = iota
396 Linux
397 Darwin
398 Windows
399)
400
401func CurrentHostType() HostType {
402 switch runtime.GOOS {
403 case "linux":
404 return Linux
405 case "darwin":
406 return Darwin
407 default:
408 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
409 }
410}
411
412func (ht HostType) String() string {
413 switch ht {
414 case Linux:
415 return "linux"
416 case Darwin:
417 return "darwin"
418 case Windows:
419 return "windows"
420 default:
421 panic(fmt.Sprintf("unexpected HostType value %d", ht))
422 }
423}
424
425func (ht HostType) Field() string {
426 switch ht {
427 case Linux:
428 return "Linux"
429 case Darwin:
430 return "Darwin"
431 case Windows:
432 return "Windows"
433 default:
434 panic(fmt.Sprintf("unexpected HostType value %d", ht))
435 }
436}
437
Colin Cross3f40fa42015-01-30 17:27:36 -0800438var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700439 commonArch = Arch{
440 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700441 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800442)
443
Colin Cross6362e272015-10-29 15:25:03 -0700444func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700445 var module AndroidModule
446 var ok bool
447 if module, ok = mctx.Module().(AndroidModule); !ok {
448 return
449 }
450
451 hods := []HostOrDevice{}
452
453 if module.base().HostSupported() {
454 hods = append(hods, Host)
455 }
456
457 if module.base().DeviceSupported() {
458 hods = append(hods, Device)
459 }
460
461 if len(hods) == 0 {
462 return
463 }
464
465 hodNames := []string{}
466 for _, hod := range hods {
467 hodNames = append(hodNames, hod.String())
468 }
469
470 modules := mctx.CreateVariations(hodNames...)
471 for i, m := range modules {
472 m.(AndroidModule).base().SetHostOrDevice(hods[i])
473 }
474}
475
Dan Willemsen490fd492015-11-24 17:53:15 -0800476func HostTypeMutator(mctx AndroidBottomUpMutatorContext) {
477 var module AndroidModule
478 var ok bool
479 if module, ok = mctx.Module().(AndroidModule); !ok {
480 return
481 }
482
483 if !module.base().HostSupported() || !module.base().HostOrDevice().Host() {
484 return
485 }
486
487 buildTypes, err := decodeHostTypesProductVariables(mctx.Config().(Config).ProductVariables)
488 if err != nil {
489 mctx.ModuleErrorf("%s", err.Error())
490 return
491 }
492
493 typeNames := []string{}
494 for _, ht := range buildTypes {
495 typeNames = append(typeNames, ht.String())
496 }
497
498 modules := mctx.CreateVariations(typeNames...)
499 for i, m := range modules {
500 m.(AndroidModule).base().SetHostType(buildTypes[i])
501 }
502}
503
Colin Cross6362e272015-10-29 15:25:03 -0700504func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800505 var module AndroidModule
506 var ok bool
507 if module, ok = mctx.Module().(AndroidModule); !ok {
508 return
509 }
510
Colin Cross4225f652015-09-17 14:33:42 -0700511 moduleArches := []Arch{}
512 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800513
Colin Crossd3ba0392015-05-07 14:11:29 -0700514 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Dan Willemsen218f6562015-07-08 18:13:11 -0700515 hostModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).HostArches[module.base().HostType()])
Colin Cross4225f652015-09-17 14:33:42 -0700516 if err != nil {
517 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700518 }
Colin Cross4225f652015-09-17 14:33:42 -0700519
520 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800521 }
522
Colin Crossd3ba0392015-05-07 14:11:29 -0700523 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Dan Willemsen218f6562015-07-08 18:13:11 -0700524 deviceModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).DeviceArches)
Colin Cross4225f652015-09-17 14:33:42 -0700525 if err != nil {
526 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800527 }
Colin Cross4225f652015-09-17 14:33:42 -0700528
529 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800530 }
531
Colin Cross4225f652015-09-17 14:33:42 -0700532 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700533 return
534 }
535
Colin Cross3f40fa42015-01-30 17:27:36 -0800536 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700537 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800538 archNames = append(archNames, arch.String())
539 }
540
541 modules := mctx.CreateVariations(archNames...)
542
543 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700544 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700545 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800546 }
547}
548
Colin Crosscfad1192015-11-02 16:43:11 -0800549func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800550 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
551
552 base := m.base()
553
Colin Cross3f40fa42015-01-30 17:27:36 -0800554 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800555 propertyStructs...)
556
557 for _, properties := range base.generalProperties {
558 propertiesValue := reflect.ValueOf(properties)
559 if propertiesValue.Kind() != reflect.Ptr {
560 panic("properties must be a pointer to a struct")
561 }
562
563 propertiesValue = propertiesValue.Elem()
564 if propertiesValue.Kind() != reflect.Struct {
565 panic("properties must be a pointer to a struct")
566 }
567
568 archProperties := &archProperties{}
569 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700570 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800571 v.Set(newValue)
572 })
573
574 base.archProperties = append(base.archProperties, archProperties)
575 }
576
577 var allProperties []interface{}
578 allProperties = append(allProperties, base.generalProperties...)
579 for _, asp := range base.archProperties {
580 allProperties = append(allProperties, asp)
581 }
582
583 return m, allProperties
584}
585
Colin Crossa716add2015-12-16 11:07:39 -0800586var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
Colin Crossec193632015-07-06 17:49:43 -0700587
Colin Cross6362e272015-10-29 15:25:03 -0700588func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800589 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700590
Colin Crosseeabb892015-11-20 13:07:51 -0800591 srcField := reflect.ValueOf(src).FieldByName(field)
592 if !srcField.IsValid() {
593 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800594 return nil
595 }
596
597 ret := srcField
598
599 if srcField.Kind() == reflect.Struct {
600 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800601 }
602
603 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700604
605 filter := func(property string,
606 dstField, srcField reflect.StructField,
607 dstValue, srcValue interface{}) (bool, error) {
608
609 srcProperty := srcPrefix + "." + property
610
611 if !proptools.HasTag(dstField, "android", "arch_variant") {
612 if ctx.ContainsProperty(srcProperty) {
613 return false, fmt.Errorf("can't be specific to a build variant")
614 } else {
615 return false, nil
616 }
617 }
618
619 return true, nil
620 }
621
622 err := proptools.AppendProperties(dst, src, filter)
623 if err != nil {
624 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
625 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
626 } else {
627 panic(err)
628 }
629 }
Colin Cross85a88972015-11-23 13:29:51 -0800630
631 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700632}
633
Colin Cross3f40fa42015-01-30 17:27:36 -0800634// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700635func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700636 arch := a.commonProperties.CompileArch
637 hod := a.commonProperties.CompileHostOrDevice
Dan Willemsen490fd492015-11-24 17:53:15 -0800638 ht := a.commonProperties.CompileHostType
Colin Crossd3ba0392015-05-07 14:11:29 -0700639
Colin Cross2fe66872015-03-30 17:20:39 -0700640 if arch.ArchType == Common {
641 return
642 }
643
Colin Cross3f40fa42015-01-30 17:27:36 -0800644 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700645 genProps := a.generalProperties[i]
646 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800647 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700648 // arch: {
649 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800650 // key: value,
651 // },
652 // },
653 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700654
Colin Crossec193632015-07-06 17:49:43 -0700655 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700656 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800657 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700658
659 // Handle arch-variant-specific properties in the form:
660 // arch: {
661 // variant: {
662 // key: value,
663 // },
664 // },
Colin Crossa716add2015-12-16 11:07:39 -0800665 v := variantReplacer.Replace(arch.ArchVariant)
Colin Crossec193632015-07-06 17:49:43 -0700666 if v != "" {
667 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800668 prefix := "arch." + t.Name + "." + v
669 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700670 }
671
672 // Handle cpu-variant-specific properties in the form:
673 // arch: {
674 // variant: {
675 // key: value,
676 // },
677 // },
Colin Crossa716add2015-12-16 11:07:39 -0800678 c := variantReplacer.Replace(arch.CpuVariant)
Colin Crossec193632015-07-06 17:49:43 -0700679 if c != "" {
680 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800681 prefix := "arch." + t.Name + "." + c
682 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700683 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800684
Colin Crossc5c24ad2015-11-20 15:35:00 -0800685 // Handle arch-feature-specific properties in the form:
686 // arch: {
687 // feature: {
688 // key: value,
689 // },
690 // },
691 for _, feature := range arch.ArchFeatures {
692 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800693 prefix := "arch." + t.Name + "." + feature
694 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800695 }
696
Colin Cross3f40fa42015-01-30 17:27:36 -0800697 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700698 // multilib: {
699 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800700 // key: value,
701 // },
702 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700703 field = proptools.FieldNameForProperty(t.Multilib)
704 prefix = "multilib." + t.Multilib
705 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800706
707 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700708 // target: {
709 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800710 // key: value,
711 // },
712 // },
Colin Crossec193632015-07-06 17:49:43 -0700713 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700714 field = proptools.FieldNameForProperty(hodProperty)
715 prefix = "target." + hodProperty
716 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800717
718 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700719 // target: {
720 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800721 // key: value,
722 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700723 // not_windows: {
724 // key: value,
725 // },
726 // linux_x86: {
727 // key: value,
728 // },
729 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800730 // key: value,
731 // },
732 // },
Colin Cross3f40fa42015-01-30 17:27:36 -0800733 if hod.Host() {
Dan Willemsen490fd492015-11-24 17:53:15 -0800734 field := ht.Field()
735 prefix := "target." + ht.String()
Colin Cross06a931b2015-10-28 17:23:31 -0700736 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Dan Willemsen490fd492015-11-24 17:53:15 -0800737
738 t := arch.ArchType
739 field = ht.Field() + "_" + t.Name
740 prefix = "target." + ht.String() + "_" + t.Name
741 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
742
743 if ht != Windows {
744 field := "Not_windows"
745 prefix := "target.not_windows"
746 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
747 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800748 }
749
Colin Crossf8209412015-03-26 14:44:26 -0700750 // Handle 64-bit device properties in the form:
751 // target {
752 // android64 {
753 // key: value,
754 // },
755 // android32 {
756 // key: value,
757 // },
758 // },
759 // WARNING: this is probably not what you want to use in your blueprints file, it selects
760 // options for all targets on a device that supports 64-bit binaries, not just the targets
761 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
762 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
763 if hod.Device() {
764 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700765 field := "Android64"
766 prefix := "target.android64"
767 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700768 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700769 field := "Android32"
770 prefix := "target.android32"
771 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700772 }
773 }
Colin Crossb05bff22015-04-30 15:08:04 -0700774
775 // Handle device architecture properties in the form:
776 // target {
777 // android_arm {
778 // key: value,
779 // },
780 // android_x86 {
781 // key: value,
782 // },
783 // },
784 if hod.Device() {
785 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700786 field := "Android_" + t.Name
787 prefix := "target.android_" + t.Name
788 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700789 }
790
Colin Cross3f40fa42015-01-30 17:27:36 -0800791 if ctx.Failed() {
792 return
793 }
794 }
795}
796
797func forEachInterface(v reflect.Value, f func(reflect.Value)) {
798 switch v.Kind() {
799 case reflect.Interface:
800 f(v)
801 case reflect.Struct:
802 for i := 0; i < v.NumField(); i++ {
803 forEachInterface(v.Field(i), f)
804 }
805 case reflect.Ptr:
806 forEachInterface(v.Elem(), f)
807 default:
808 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
809 }
810}
Colin Cross4225f652015-09-17 14:33:42 -0700811
Dan Willemsen490fd492015-11-24 17:53:15 -0800812// Get a list of HostTypes from the product variables
813func decodeHostTypesProductVariables(variables productVariables) ([]HostType, error) {
814 ret := []HostType{CurrentHostType()}
815
816 if variables.CrossHost != nil && *variables.CrossHost != "" {
817 switch *variables.CrossHost {
818 case "windows":
819 ret = append(ret, Windows)
820 default:
821 return nil, fmt.Errorf("Unsupported secondary host: %s", *variables.CrossHost)
822 }
823 }
824
825 return ret, nil
826}
827
Colin Cross4225f652015-09-17 14:33:42 -0700828// Convert the arch product variables into a list of host and device Arch structs
Dan Willemsen490fd492015-11-24 17:53:15 -0800829func decodeArchProductVariables(variables productVariables) (map[HostType][]Arch, []Arch, error) {
Colin Cross4225f652015-09-17 14:33:42 -0700830 if variables.HostArch == nil {
831 return nil, nil, fmt.Errorf("No host primary architecture set")
832 }
833
834 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
835 if err != nil {
836 return nil, nil, err
837 }
838
839 hostArches := []Arch{hostArch}
840
Colin Crosseeabb892015-11-20 13:07:51 -0800841 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700842 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
843 if err != nil {
844 return nil, nil, err
845 }
846 hostArches = append(hostArches, hostSecondaryArch)
847 }
848
Dan Willemsen490fd492015-11-24 17:53:15 -0800849 hostTypeArches := map[HostType][]Arch{
850 CurrentHostType(): hostArches,
851 }
852
853 if variables.CrossHost != nil && *variables.CrossHost != "" {
854 if variables.CrossHostArch == nil || *variables.CrossHostArch == "" {
855 return nil, nil, fmt.Errorf("No cross-host primary architecture set")
856 }
857
858 crossHostArch, err := decodeArch(*variables.CrossHostArch, nil, nil, nil)
859 if err != nil {
860 return nil, nil, err
861 }
862
863 crossHostArches := []Arch{crossHostArch}
864
865 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
866 crossHostSecondaryArch, err := decodeArch(*variables.CrossHostSecondaryArch, nil, nil, nil)
867 if err != nil {
868 return nil, nil, err
869 }
870 crossHostArches = append(crossHostArches, crossHostSecondaryArch)
871 }
872
873 switch *variables.CrossHost {
874 case "windows":
875 hostTypeArches[Windows] = crossHostArches
876 default:
877 return nil, nil, fmt.Errorf("Unsupported cross-host: %s", *variables.CrossHost)
878 }
879 }
880
Colin Cross4225f652015-09-17 14:33:42 -0700881 if variables.DeviceArch == nil {
882 return nil, nil, fmt.Errorf("No device primary architecture set")
883 }
884
885 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
886 variables.DeviceCpuVariant, variables.DeviceAbi)
887 if err != nil {
888 return nil, nil, err
889 }
890
891 deviceArches := []Arch{deviceArch}
892
Colin Crosseeabb892015-11-20 13:07:51 -0800893 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700894 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
895 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
896 variables.DeviceSecondaryAbi)
897 if err != nil {
898 return nil, nil, err
899 }
900 deviceArches = append(deviceArches, deviceSecondaryArch)
901 }
902
Dan Willemsen490fd492015-11-24 17:53:15 -0800903 return hostTypeArches, deviceArches, nil
Colin Cross4225f652015-09-17 14:33:42 -0700904}
905
Dan Willemsen322acaf2016-01-12 23:07:05 -0800906func decodeMegaDevice() ([]Arch, error) {
907 archSettings := []struct {
908 arch string
909 archVariant string
910 cpuVariant string
911 abi []string
912 }{
913 {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
914 {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
915 // gtest_all_test.cc fails to build:
916 // error in backend: Unsupported library call operation!
917 //{"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}},
918 {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}},
919 {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}},
920 {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}},
921 {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
922 {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
923 {"arm64", "", "cortex-a53", []string{"arm64-v8a"}},
924 {"arm64", "", "denver64", []string{"arm64-v8a"}},
Dan Willemsen468cc312016-01-13 23:25:19 -0800925 {"mips", "mips32-fp", "", []string{"mips"}},
926 {"mips", "mips32r2-fp", "", []string{"mips"}},
927 {"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
928 {"mips", "mips32r6", "", []string{"mips32r6"}},
929 // mips32r2dsp[r2]-fp fails in the assembler for divdf3.c in compiler-rt:
930 // (same errors in make and soong)
931 // Error: invalid operands `mtlo $ac0,$11'
932 // Error: invalid operands `mthi $ac0,$12'
Dan Willemsen322acaf2016-01-12 23:07:05 -0800933 //{"mips", "mips32r2dsp-fp", "", []string{"mips"}},
934 //{"mips", "mips32r2dspr2-fp", "", []string{"mips"}},
935 // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc
936 //{"mips64", "mips64r2", "", []string{"mips64"}},
937 {"mips64", "mips64r6", "", []string{"mips64"}},
938 {"x86", "", "", []string{"x86"}},
939 {"x86", "atom", "", []string{"x86"}},
940 {"x86", "haswell", "", []string{"x86"}},
941 {"x86", "ivybridge", "", []string{"x86"}},
942 {"x86", "sandybridge", "", []string{"x86"}},
943 {"x86", "silvermont", "", []string{"x86"}},
944 {"x86_64", "", "", []string{"x86_64"}},
945 {"x86_64", "haswell", "", []string{"x86_64"}},
946 {"x86_64", "ivybridge", "", []string{"x86_64"}},
947 {"x86_64", "sandybridge", "", []string{"x86_64"}},
948 {"x86_64", "silvermont", "", []string{"x86_64"}},
949 }
950
951 var ret []Arch
952
953 for _, config := range archSettings {
954 arch, err := decodeArch(config.arch, &config.archVariant,
955 &config.cpuVariant, &config.abi)
956 if err != nil {
957 return nil, err
958 }
959 ret = append(ret, arch)
960 }
961
962 return ret, nil
963}
964
Colin Cross4225f652015-09-17 14:33:42 -0700965// Convert a set of strings from product variables into a single Arch struct
966func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
967 stringPtr := func(p *string) string {
968 if p != nil {
969 return *p
970 }
971 return ""
972 }
973
974 slicePtr := func(p *[]string) []string {
975 if p != nil {
976 return *p
977 }
978 return nil
979 }
980
Colin Crosseeabb892015-11-20 13:07:51 -0800981 archType, ok := archTypeMap[arch]
982 if !ok {
983 return Arch{}, fmt.Errorf("unknown arch %q", arch)
984 }
Colin Cross4225f652015-09-17 14:33:42 -0700985
Colin Crosseeabb892015-11-20 13:07:51 -0800986 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700987 ArchType: archType,
988 ArchVariant: stringPtr(archVariant),
989 CpuVariant: stringPtr(cpuVariant),
990 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800991 }
992
993 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
994 a.ArchVariant = ""
995 }
996
997 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
998 a.CpuVariant = ""
999 }
1000
1001 for i := 0; i < len(a.Abi); i++ {
1002 if a.Abi[i] == "" {
1003 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
1004 i--
1005 }
1006 }
1007
Colin Crossc5c24ad2015-11-20 15:35:00 -08001008 if featureMap, ok := archFeatureMap[archType]; ok {
1009 a.ArchFeatures = featureMap[stringPtr(archVariant)]
1010 }
1011
Colin Crosseeabb892015-11-20 13:07:51 -08001012 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -07001013}
1014
1015// Use the module multilib setting to select one or more arches from an arch list
1016func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
1017 buildArches := []Arch{}
1018 switch multilib {
1019 case "common":
1020 buildArches = append(buildArches, commonArch)
1021 case "both":
1022 buildArches = append(buildArches, arches...)
1023 case "first":
1024 buildArches = append(buildArches, arches[0])
1025 case "32":
1026 for _, a := range arches {
1027 if a.ArchType.Multilib == "lib32" {
1028 buildArches = append(buildArches, a)
1029 }
1030 }
1031 case "64":
1032 for _, a := range arches {
1033 if a.ArchType.Multilib == "lib64" {
1034 buildArches = append(buildArches, a)
1035 }
1036 }
1037 default:
1038 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
1039 multilib)
1040 //buildArches = append(buildArches, arches[0])
1041 }
1042
1043 return buildArches, nil
1044}