blob: 48cc0ab7141d6321349f9b60c40de26019d82b91 [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
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Colin Cross3f40fa42015-01-30 17:27:36 -080016
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 Crossb9db4802016-06-03 01:50:47 +000031 RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator)
32 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\")"`
Dan Willemsen8a354052016-05-10 14:30:51 -0700189 // Generic variant for X86 on X86_64
Colin Cross635c3b02016-05-18 15:37:25 -0700190 X86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800191
192 // X86 arch features
Colin Crossb0cba6a2015-11-20 15:35:26 -0800193 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
194 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
195 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
196 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
197 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
198 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
199 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
200 Movbe interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800201 }
202
Colin Cross7d5136f2015-05-11 13:39:40 -0700203 // Properties for module variants being built to run on x86_64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800204 X86_64 struct {
205 Embed `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6371b382015-11-23 14:53:57 -0800206
207 // X86 arch variants
208 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
209 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
210 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
211 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
212
213 // X86 arch features
214 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
215 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
216 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
217 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
218 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
219 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
220 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800221 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800222 }
Colin Crossec193632015-07-06 17:49:43 -0700223
Colin Cross7d5136f2015-05-11 13:39:40 -0700224 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800225 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700226 // Properties for module variants being built to run on 32-bit devices
227 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
228 // Properties for module variants being built to run on 64-bit devices
229 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800230 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700231 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800232 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700233 // Properties for module variants being built to run on the host
234 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
235 // Properties for module variants being built to run on the device
236 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
237 // Properties for module variants being built to run on arm devices
238 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
239 // Properties for module variants being built to run on arm64 devices
240 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
241 // Properties for module variants being built to run on mips devices
242 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
243 // Properties for module variants being built to run on mips64 devices
244 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
245 // Properties for module variants being built to run on x86 devices
246 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
247 // Properties for module variants being built to run on x86_64 devices
248 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
249 // Properties for module variants being built to run on devices that support 64-bit
250 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
251 // Properties for module variants being built to run on devices that do not support 64-bit
252 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
253 // Properties for module variants being built to run on linux hosts
254 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
255 // Properties for module variants being built to run on linux x86 hosts
256 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
257 // Properties for module variants being built to run on linux x86_64 hosts
258 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
259 // Properties for module variants being built to run on darwin hosts
260 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
261 // Properties for module variants being built to run on darwin x86 hosts
262 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
263 // Properties for module variants being built to run on darwin x86_64 hosts
264 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
265 // Properties for module variants being built to run on windows hosts
266 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Dan Willemsen490fd492015-11-24 17:53:15 -0800267 // Properties for module variants being built to run on windows x86 hosts
268 Windows_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Dan Willemsen07cd0512016-02-03 23:16:33 -0800269 // Properties for module variants being built to run on windows x86_64 hosts
270 Windows_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross7d5136f2015-05-11 13:39:40 -0700271 // Properties for module variants being built to run on linux or darwin hosts
272 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800273 }
274}
275
Colin Crossc5c24ad2015-11-20 15:35:00 -0800276var archFeatureMap = map[ArchType]map[string][]string{}
277
278func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800279 archField := proptools.FieldNameForProperty(arch.Name)
280 variantField := proptools.FieldNameForProperty(variant)
281 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800282 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800283 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800284 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
285 }
286 }
287 for _, feature := range features {
288 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800289 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800290 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
291 }
292 }
293 if archFeatureMap[arch] == nil {
294 archFeatureMap[arch] = make(map[string][]string)
295 }
296 archFeatureMap[arch][variant] = features
297}
298
Colin Cross3f40fa42015-01-30 17:27:36 -0800299// An Arch indicates a single CPU architecture.
300type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800301 ArchType ArchType
302 ArchVariant string
303 CpuVariant string
304 Abi []string
305 ArchFeatures []string
Dan Willemsen17f05262016-05-31 16:27:00 -0700306 Native bool
Colin Cross3f40fa42015-01-30 17:27:36 -0800307}
308
309func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700310 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800311 if a.ArchVariant != "" {
312 s += "_" + a.ArchVariant
313 }
314 if a.CpuVariant != "" {
315 s += "_" + a.CpuVariant
316 }
317 return s
318}
319
320type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700321 Name string
322 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800323}
324
Colin Crossec193632015-07-06 17:49:43 -0700325func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800326 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700327 Name: name,
328 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800329 }
330}
331
332func (a ArchType) String() string {
333 return a.Name
334}
335
Colin Crossb9db4802016-06-03 01:50:47 +0000336type HostOrDeviceSupported int
337
338const (
339 _ HostOrDeviceSupported = iota
340 HostSupported
341 DeviceSupported
342 HostAndDeviceSupported
343 HostAndDeviceDefault
344)
345
346type HostOrDevice int
347
348const (
349 _ HostOrDevice = iota
350 Host
351 Device
352)
353
354func (hod HostOrDevice) String() string {
355 switch hod {
356 case Device:
357 return "device"
358 case Host:
359 return "host"
360 default:
361 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
362 }
363}
364
365func (hod HostOrDevice) Property() string {
366 switch hod {
367 case Device:
368 return "android"
369 case Host:
370 return "host"
371 default:
372 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
373 }
374}
375
376func (hod HostOrDevice) Host() bool {
377 if hod == 0 {
378 panic("HostOrDevice unset")
379 }
380 return hod == Host
381}
382
383func (hod HostOrDevice) Device() bool {
384 if hod == 0 {
385 panic("HostOrDevice unset")
386 }
387 return hod == Device
388}
389
390var hostOrDeviceName = map[HostOrDevice]string{
391 Device: "device",
392 Host: "host",
393}
394
395type HostType int
396
397const (
398 NoHostType HostType = iota
399 Linux
400 Darwin
401 Windows
402)
403
404func CurrentHostType() HostType {
Dan Willemsen490fd492015-11-24 17:53:15 -0800405 switch runtime.GOOS {
406 case "linux":
407 return Linux
408 case "darwin":
409 return Darwin
410 default:
411 panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
412 }
413}
414
Colin Crossb9db4802016-06-03 01:50:47 +0000415func (ht HostType) String() string {
416 switch ht {
417 case Linux:
418 return "linux"
419 case Darwin:
420 return "darwin"
421 case Windows:
422 return "windows"
423 default:
424 panic(fmt.Sprintf("unexpected HostType value %d", ht))
Dan Willemsen490fd492015-11-24 17:53:15 -0800425 }
Colin Cross54c71122016-06-01 17:09:44 -0700426}
427
Colin Crossb9db4802016-06-03 01:50:47 +0000428func (ht HostType) Field() string {
429 switch ht {
430 case Linux:
431 return "Linux"
432 case Darwin:
433 return "Darwin"
434 case Windows:
435 return "Windows"
436 default:
437 panic(fmt.Sprintf("unexpected HostType value %d", ht))
Colin Cross54c71122016-06-01 17:09:44 -0700438 }
Dan Willemsen490fd492015-11-24 17:53:15 -0800439}
440
Colin Cross3f40fa42015-01-30 17:27:36 -0800441var (
Colin Crossb9db4802016-06-03 01:50:47 +0000442 commonArch = Arch{
443 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700444 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800445)
446
Colin Crossb9db4802016-06-03 01:50:47 +0000447func HostOrDeviceMutator(mctx BottomUpMutatorContext) {
448 var module Module
449 var ok bool
450 if module, ok = mctx.Module().(Module); !ok {
451 return
452 }
453
454 hods := []HostOrDevice{}
455
456 if module.base().HostSupported() {
457 hods = append(hods, Host)
458 }
459
460 if module.base().DeviceSupported() {
461 hods = append(hods, Device)
462 }
463
464 if len(hods) == 0 {
465 return
466 }
467
468 hodNames := []string{}
469 for _, hod := range hods {
470 hodNames = append(hodNames, hod.String())
471 }
472
473 modules := mctx.CreateVariations(hodNames...)
474 for i, m := range modules {
475 m.(Module).base().SetHostOrDevice(hods[i])
476 }
Colin Crossd3ba0392015-05-07 14:11:29 -0700477}
478
Colin Crossb9db4802016-06-03 01:50:47 +0000479func HostTypeMutator(mctx BottomUpMutatorContext) {
480 var module Module
481 var ok bool
482 if module, ok = mctx.Module().(Module); !ok {
483 return
484 }
485
486 if !module.base().HostSupported() || !module.base().HostOrDevice().Host() {
487 return
488 }
489
490 buildTypes, err := decodeHostTypesProductVariables(mctx.Config().(Config).ProductVariables)
491 if err != nil {
492 mctx.ModuleErrorf("%s", err.Error())
493 return
494 }
495
496 typeNames := []string{}
497 for _, ht := range buildTypes {
498 typeNames = append(typeNames, ht.String())
499 }
500
501 modules := mctx.CreateVariations(typeNames...)
502 for i, m := range modules {
503 m.(Module).base().SetHostType(buildTypes[i])
504 }
Dan Willemsen490fd492015-11-24 17:53:15 -0800505}
506
Colin Cross635c3b02016-05-18 15:37:25 -0700507func ArchMutator(mctx BottomUpMutatorContext) {
508 var module Module
Colin Cross3f40fa42015-01-30 17:27:36 -0800509 var ok bool
Colin Cross635c3b02016-05-18 15:37:25 -0700510 if module, ok = mctx.Module().(Module); !ok {
Colin Cross3f40fa42015-01-30 17:27:36 -0800511 return
512 }
513
Colin Crossb9db4802016-06-03 01:50:47 +0000514 moduleArches := []Arch{}
515 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800516
Colin Crossb9db4802016-06-03 01:50:47 +0000517 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
518 hostModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).HostArches[module.base().HostType()])
Colin Cross54c71122016-06-01 17:09:44 -0700519 if err != nil {
520 mctx.ModuleErrorf("%s", err.Error())
521 }
Colin Crossb9db4802016-06-03 01:50:47 +0000522
523 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800524 }
525
Colin Crossb9db4802016-06-03 01:50:47 +0000526 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
527 deviceModuleArches, err := decodeMultilib(multilib, mctx.Config().(Config).DeviceArches)
528 if err != nil {
529 mctx.ModuleErrorf("%s", err.Error())
530 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800531
Colin Crossb9db4802016-06-03 01:50:47 +0000532 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross54c71122016-06-01 17:09:44 -0700533 }
534
Colin Crossb9db4802016-06-03 01:50:47 +0000535 if len(moduleArches) == 0 {
536 return
537 }
538
539 archNames := []string{}
540 for _, arch := range moduleArches {
541 archNames = append(archNames, arch.String())
542 }
543
544 modules := mctx.CreateVariations(archNames...)
545
Colin Cross3f40fa42015-01-30 17:27:36 -0800546 for i, m := range modules {
Colin Crossb9db4802016-06-03 01:50:47 +0000547 m.(Module).base().SetArch(moduleArches[i])
Colin Cross635c3b02016-05-18 15:37:25 -0700548 m.(Module).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800549 }
550}
551
Colin Cross635c3b02016-05-18 15:37:25 -0700552func InitArchModule(m Module,
Colin Cross3f40fa42015-01-30 17:27:36 -0800553 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
554
555 base := m.base()
556
Colin Cross3f40fa42015-01-30 17:27:36 -0800557 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800558 propertyStructs...)
559
560 for _, properties := range base.generalProperties {
561 propertiesValue := reflect.ValueOf(properties)
562 if propertiesValue.Kind() != reflect.Ptr {
Colin Crossca860ac2016-01-04 14:34:37 -0800563 panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
564 propertiesValue.Interface()))
Colin Cross3f40fa42015-01-30 17:27:36 -0800565 }
566
567 propertiesValue = propertiesValue.Elem()
568 if propertiesValue.Kind() != reflect.Struct {
Colin Crossca860ac2016-01-04 14:34:37 -0800569 panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
570 propertiesValue.Interface()))
Colin Cross3f40fa42015-01-30 17:27:36 -0800571 }
572
573 archProperties := &archProperties{}
574 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700575 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800576 v.Set(newValue)
577 })
578
579 base.archProperties = append(base.archProperties, archProperties)
580 }
581
582 var allProperties []interface{}
583 allProperties = append(allProperties, base.generalProperties...)
584 for _, asp := range base.archProperties {
585 allProperties = append(allProperties, asp)
586 }
587
588 return m, allProperties
589}
590
Colin Crossa716add2015-12-16 11:07:39 -0800591var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
Colin Crossec193632015-07-06 17:49:43 -0700592
Colin Cross635c3b02016-05-18 15:37:25 -0700593func (a *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800594 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700595
Colin Crosseeabb892015-11-20 13:07:51 -0800596 srcField := reflect.ValueOf(src).FieldByName(field)
597 if !srcField.IsValid() {
598 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800599 return nil
600 }
601
602 ret := srcField
603
604 if srcField.Kind() == reflect.Struct {
605 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800606 }
607
608 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700609
610 filter := func(property string,
611 dstField, srcField reflect.StructField,
612 dstValue, srcValue interface{}) (bool, error) {
613
614 srcProperty := srcPrefix + "." + property
615
616 if !proptools.HasTag(dstField, "android", "arch_variant") {
617 if ctx.ContainsProperty(srcProperty) {
618 return false, fmt.Errorf("can't be specific to a build variant")
619 } else {
620 return false, nil
621 }
622 }
623
624 return true, nil
625 }
626
Colin Cross6ee75b62016-05-05 15:57:15 -0700627 order := func(property string,
628 dstField, srcField reflect.StructField,
629 dstValue, srcValue interface{}) (proptools.Order, error) {
630 if proptools.HasTag(dstField, "android", "variant_prepend") {
631 return proptools.Prepend, nil
632 } else {
633 return proptools.Append, nil
634 }
635 }
636
637 err := proptools.ExtendProperties(dst, src, filter, order)
Colin Cross06a931b2015-10-28 17:23:31 -0700638 if err != nil {
639 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
640 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
641 } else {
642 panic(err)
643 }
644 }
Colin Cross85a88972015-11-23 13:29:51 -0800645
646 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700647}
648
Colin Cross3f40fa42015-01-30 17:27:36 -0800649// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross635c3b02016-05-18 15:37:25 -0700650func (a *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
Colin Crossb9db4802016-06-03 01:50:47 +0000651 arch := a.commonProperties.CompileArch
652 hod := a.commonProperties.CompileHostOrDevice
653 ht := a.commonProperties.CompileHostType
Colin Crossd3ba0392015-05-07 14:11:29 -0700654
Colin Cross2fe66872015-03-30 17:20:39 -0700655 if arch.ArchType == Common {
656 return
657 }
658
Colin Cross3f40fa42015-01-30 17:27:36 -0800659 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700660 genProps := a.generalProperties[i]
661 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800662 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700663 // arch: {
664 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800665 // key: value,
666 // },
667 // },
668 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700669
Colin Crossec193632015-07-06 17:49:43 -0700670 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700671 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800672 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700673
674 // Handle arch-variant-specific properties in the form:
675 // arch: {
676 // variant: {
677 // key: value,
678 // },
679 // },
Colin Crossa716add2015-12-16 11:07:39 -0800680 v := variantReplacer.Replace(arch.ArchVariant)
Colin Crossec193632015-07-06 17:49:43 -0700681 if v != "" {
682 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800683 prefix := "arch." + t.Name + "." + v
684 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700685 }
686
687 // Handle cpu-variant-specific properties in the form:
688 // arch: {
689 // variant: {
690 // key: value,
691 // },
692 // },
Colin Crossa716add2015-12-16 11:07:39 -0800693 c := variantReplacer.Replace(arch.CpuVariant)
Colin Crossec193632015-07-06 17:49:43 -0700694 if c != "" {
695 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800696 prefix := "arch." + t.Name + "." + c
697 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700698 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800699
Colin Crossc5c24ad2015-11-20 15:35:00 -0800700 // Handle arch-feature-specific properties in the form:
701 // arch: {
702 // feature: {
703 // key: value,
704 // },
705 // },
706 for _, feature := range arch.ArchFeatures {
707 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800708 prefix := "arch." + t.Name + "." + feature
709 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800710 }
711
Colin Cross3f40fa42015-01-30 17:27:36 -0800712 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700713 // multilib: {
714 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800715 // key: value,
716 // },
717 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700718 field = proptools.FieldNameForProperty(t.Multilib)
719 prefix = "multilib." + t.Multilib
720 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800721
Colin Crossb9db4802016-06-03 01:50:47 +0000722 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700723 // target: {
724 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800725 // key: value,
726 // },
727 // },
Colin Crossb9db4802016-06-03 01:50:47 +0000728 hodProperty := hod.Property()
729 field = proptools.FieldNameForProperty(hodProperty)
730 prefix = "target." + hodProperty
731 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800732
Colin Crossb9db4802016-06-03 01:50:47 +0000733 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700734 // target: {
735 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800736 // key: value,
737 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700738 // not_windows: {
739 // key: value,
740 // },
741 // linux_x86: {
742 // key: value,
743 // },
744 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800745 // key: value,
746 // },
747 // },
Colin Crossb9db4802016-06-03 01:50:47 +0000748 if hod.Host() {
749 field := ht.Field()
750 prefix := "target." + ht.String()
Colin Cross54c71122016-06-01 17:09:44 -0700751 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb9db4802016-06-03 01:50:47 +0000752
753 t := arch.ArchType
754 field = ht.Field() + "_" + t.Name
755 prefix = "target." + ht.String() + "_" + t.Name
756 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
757
758 if ht != Windows {
759 field := "Not_windows"
760 prefix := "target.not_windows"
761 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
762 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800763 }
764
Colin Crossf8209412015-03-26 14:44:26 -0700765 // Handle 64-bit device properties in the form:
766 // target {
767 // android64 {
768 // key: value,
769 // },
770 // android32 {
771 // key: value,
772 // },
773 // },
774 // WARNING: this is probably not what you want to use in your blueprints file, it selects
775 // options for all targets on a device that supports 64-bit binaries, not just the targets
776 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
777 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
Colin Crossb9db4802016-06-03 01:50:47 +0000778 if hod.Device() {
779 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700780 field := "Android64"
781 prefix := "target.android64"
782 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700783 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700784 field := "Android32"
785 prefix := "target.android32"
786 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700787 }
788 }
Colin Crossb9db4802016-06-03 01:50:47 +0000789
790 // Handle device architecture properties in the form:
791 // target {
792 // android_arm {
793 // key: value,
794 // },
795 // android_x86 {
796 // key: value,
797 // },
798 // },
799 if hod.Device() {
800 t := arch.ArchType
801 field := "Android_" + t.Name
802 prefix := "target.android_" + t.Name
803 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
804 }
805
806 if ctx.Failed() {
807 return
808 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800809 }
810}
811
812func forEachInterface(v reflect.Value, f func(reflect.Value)) {
813 switch v.Kind() {
814 case reflect.Interface:
815 f(v)
816 case reflect.Struct:
817 for i := 0; i < v.NumField(); i++ {
818 forEachInterface(v.Field(i), f)
819 }
820 case reflect.Ptr:
821 forEachInterface(v.Elem(), f)
822 default:
823 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
824 }
825}
Colin Cross4225f652015-09-17 14:33:42 -0700826
Colin Crossb9db4802016-06-03 01:50:47 +0000827// Get a list of HostTypes from the product variables
828func decodeHostTypesProductVariables(variables productVariables) ([]HostType, error) {
829 ret := []HostType{CurrentHostType()}
Dan Willemsen490fd492015-11-24 17:53:15 -0800830
Colin Crossb9db4802016-06-03 01:50:47 +0000831 if variables.CrossHost != nil && *variables.CrossHost != "" {
832 switch *variables.CrossHost {
833 case "windows":
834 ret = append(ret, Windows)
835 default:
836 return nil, fmt.Errorf("Unsupported secondary host: %s", *variables.CrossHost)
Dan Willemsen490fd492015-11-24 17:53:15 -0800837 }
838 }
839
Colin Crossb9db4802016-06-03 01:50:47 +0000840 return ret, nil
841}
842
843// Convert the arch product variables into a list of host and device Arch structs
844func decodeArchProductVariables(variables productVariables) (map[HostType][]Arch, []Arch, error) {
Colin Cross4225f652015-09-17 14:33:42 -0700845 if variables.HostArch == nil {
Colin Crossb9db4802016-06-03 01:50:47 +0000846 return nil, nil, fmt.Errorf("No host primary architecture set")
Colin Cross4225f652015-09-17 14:33:42 -0700847 }
848
Colin Crossb9db4802016-06-03 01:50:47 +0000849 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
850 if err != nil {
851 return nil, nil, err
852 }
853
854 hostArches := []Arch{hostArch}
Colin Cross4225f652015-09-17 14:33:42 -0700855
Colin Crosseeabb892015-11-20 13:07:51 -0800856 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Crossb9db4802016-06-03 01:50:47 +0000857 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
858 if err != nil {
859 return nil, nil, err
860 }
861 hostArches = append(hostArches, hostSecondaryArch)
862 }
863
864 hostTypeArches := map[HostType][]Arch{
865 CurrentHostType(): hostArches,
Dan Willemsen490fd492015-11-24 17:53:15 -0800866 }
867
868 if variables.CrossHost != nil && *variables.CrossHost != "" {
869 if variables.CrossHostArch == nil || *variables.CrossHostArch == "" {
Colin Crossb9db4802016-06-03 01:50:47 +0000870 return nil, nil, fmt.Errorf("No cross-host primary architecture set")
Dan Willemsen490fd492015-11-24 17:53:15 -0800871 }
872
Colin Crossb9db4802016-06-03 01:50:47 +0000873 crossHostArch, err := decodeArch(*variables.CrossHostArch, nil, nil, nil)
874 if err != nil {
875 return nil, nil, err
876 }
877
878 crossHostArches := []Arch{crossHostArch}
Dan Willemsen490fd492015-11-24 17:53:15 -0800879
880 if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
Colin Crossb9db4802016-06-03 01:50:47 +0000881 crossHostSecondaryArch, err := decodeArch(*variables.CrossHostSecondaryArch, nil, nil, nil)
882 if err != nil {
883 return nil, nil, err
884 }
885 crossHostArches = append(crossHostArches, crossHostSecondaryArch)
886 }
887
888 switch *variables.CrossHost {
889 case "windows":
890 hostTypeArches[Windows] = crossHostArches
891 default:
892 return nil, nil, fmt.Errorf("Unsupported cross-host: %s", *variables.CrossHost)
Dan Willemsen490fd492015-11-24 17:53:15 -0800893 }
894 }
895
Colin Cross4225f652015-09-17 14:33:42 -0700896 if variables.DeviceArch == nil {
Colin Crossb9db4802016-06-03 01:50:47 +0000897 return nil, nil, fmt.Errorf("No device primary architecture set")
Colin Cross4225f652015-09-17 14:33:42 -0700898 }
899
Colin Crossb9db4802016-06-03 01:50:47 +0000900 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
Colin Cross4225f652015-09-17 14:33:42 -0700901 variables.DeviceCpuVariant, variables.DeviceAbi)
Colin Crossb9db4802016-06-03 01:50:47 +0000902 if err != nil {
903 return nil, nil, err
904 }
905
906 deviceArches := []Arch{deviceArch}
Colin Cross4225f652015-09-17 14:33:42 -0700907
Colin Crosseeabb892015-11-20 13:07:51 -0800908 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Crossb9db4802016-06-03 01:50:47 +0000909 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
Colin Cross4225f652015-09-17 14:33:42 -0700910 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
911 variables.DeviceSecondaryAbi)
Colin Crossb9db4802016-06-03 01:50:47 +0000912 if err != nil {
913 return nil, nil, err
Colin Cross4225f652015-09-17 14:33:42 -0700914 }
Colin Crossb9db4802016-06-03 01:50:47 +0000915 if deviceArch.ArchType.Multilib == deviceSecondaryArch.ArchType.Multilib {
916 deviceSecondaryArch.Native = false
917 }
918 deviceArches = append(deviceArches, deviceSecondaryArch)
Colin Cross4225f652015-09-17 14:33:42 -0700919 }
920
Colin Crossb9db4802016-06-03 01:50:47 +0000921 return hostTypeArches, deviceArches, nil
Colin Cross4225f652015-09-17 14:33:42 -0700922}
923
Colin Crossb9db4802016-06-03 01:50:47 +0000924func decodeMegaDevice() ([]Arch, error) {
Dan Willemsen322acaf2016-01-12 23:07:05 -0800925 archSettings := []struct {
926 arch string
927 archVariant string
928 cpuVariant string
929 abi []string
930 }{
Dan Willemsen110a89d2016-01-14 15:17:19 -0800931 // armv5 is only used for unbundled apps
932 //{"arm", "armv5te", "", []string{"armeabi"}},
933 {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
934 {"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -0800935 {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
936 {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -0800937 {"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -0800938 {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}},
939 {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}},
940 {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}},
941 {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
942 {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
Dan Willemsen110a89d2016-01-14 15:17:19 -0800943 {"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
944 {"arm64", "armv8-a", "denver64", []string{"arm64-v8a"}},
Dan Willemsen468cc312016-01-13 23:25:19 -0800945 {"mips", "mips32-fp", "", []string{"mips"}},
946 {"mips", "mips32r2-fp", "", []string{"mips"}},
947 {"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
Dan Willemsen66187d92016-05-05 13:15:00 -0700948 {"mips", "mips32r6", "", []string{"mips"}},
Dan Willemsen468cc312016-01-13 23:25:19 -0800949 // mips32r2dsp[r2]-fp fails in the assembler for divdf3.c in compiler-rt:
950 // (same errors in make and soong)
951 // Error: invalid operands `mtlo $ac0,$11'
952 // Error: invalid operands `mthi $ac0,$12'
Dan Willemsen322acaf2016-01-12 23:07:05 -0800953 //{"mips", "mips32r2dsp-fp", "", []string{"mips"}},
954 //{"mips", "mips32r2dspr2-fp", "", []string{"mips"}},
955 // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc
956 //{"mips64", "mips64r2", "", []string{"mips64"}},
957 {"mips64", "mips64r6", "", []string{"mips64"}},
958 {"x86", "", "", []string{"x86"}},
959 {"x86", "atom", "", []string{"x86"}},
960 {"x86", "haswell", "", []string{"x86"}},
961 {"x86", "ivybridge", "", []string{"x86"}},
962 {"x86", "sandybridge", "", []string{"x86"}},
963 {"x86", "silvermont", "", []string{"x86"}},
Dan Willemsen8a354052016-05-10 14:30:51 -0700964 {"x86", "x86_64", "", []string{"x86"}},
Dan Willemsen322acaf2016-01-12 23:07:05 -0800965 {"x86_64", "", "", []string{"x86_64"}},
966 {"x86_64", "haswell", "", []string{"x86_64"}},
967 {"x86_64", "ivybridge", "", []string{"x86_64"}},
968 {"x86_64", "sandybridge", "", []string{"x86_64"}},
969 {"x86_64", "silvermont", "", []string{"x86_64"}},
970 }
971
Colin Crossb9db4802016-06-03 01:50:47 +0000972 var ret []Arch
Dan Willemsen322acaf2016-01-12 23:07:05 -0800973
974 for _, config := range archSettings {
975 arch, err := decodeArch(config.arch, &config.archVariant,
976 &config.cpuVariant, &config.abi)
977 if err != nil {
978 return nil, err
979 }
Dan Willemsen17f05262016-05-31 16:27:00 -0700980 arch.Native = false
Colin Crossb9db4802016-06-03 01:50:47 +0000981 ret = append(ret, arch)
Dan Willemsen322acaf2016-01-12 23:07:05 -0800982 }
983
984 return ret, nil
985}
986
Colin Cross4225f652015-09-17 14:33:42 -0700987// Convert a set of strings from product variables into a single Arch struct
988func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
989 stringPtr := func(p *string) string {
990 if p != nil {
991 return *p
992 }
993 return ""
994 }
995
996 slicePtr := func(p *[]string) []string {
997 if p != nil {
998 return *p
999 }
1000 return nil
1001 }
1002
Colin Crosseeabb892015-11-20 13:07:51 -08001003 archType, ok := archTypeMap[arch]
1004 if !ok {
1005 return Arch{}, fmt.Errorf("unknown arch %q", arch)
1006 }
Colin Cross4225f652015-09-17 14:33:42 -07001007
Colin Crosseeabb892015-11-20 13:07:51 -08001008 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -07001009 ArchType: archType,
1010 ArchVariant: stringPtr(archVariant),
1011 CpuVariant: stringPtr(cpuVariant),
1012 Abi: slicePtr(abi),
Dan Willemsen17f05262016-05-31 16:27:00 -07001013 Native: true,
Colin Crosseeabb892015-11-20 13:07:51 -08001014 }
1015
1016 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
1017 a.ArchVariant = ""
1018 }
1019
1020 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
1021 a.CpuVariant = ""
1022 }
1023
1024 for i := 0; i < len(a.Abi); i++ {
1025 if a.Abi[i] == "" {
1026 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
1027 i--
1028 }
1029 }
1030
Colin Crossc5c24ad2015-11-20 15:35:00 -08001031 if featureMap, ok := archFeatureMap[archType]; ok {
Dan Willemsenb4850992016-05-06 17:21:20 -07001032 a.ArchFeatures = featureMap[a.ArchVariant]
Colin Crossc5c24ad2015-11-20 15:35:00 -08001033 }
1034
Colin Crosseeabb892015-11-20 13:07:51 -08001035 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -07001036}
1037
Colin Crossb9db4802016-06-03 01:50:47 +00001038// Use the module multilib setting to select one or more arches from an arch list
1039func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
1040 buildArches := []Arch{}
Colin Cross4225f652015-09-17 14:33:42 -07001041 switch multilib {
1042 case "common":
Colin Crossb9db4802016-06-03 01:50:47 +00001043 buildArches = append(buildArches, commonArch)
Colin Cross4225f652015-09-17 14:33:42 -07001044 case "both":
Colin Crossb9db4802016-06-03 01:50:47 +00001045 buildArches = append(buildArches, arches...)
Colin Cross4225f652015-09-17 14:33:42 -07001046 case "first":
Colin Crossb9db4802016-06-03 01:50:47 +00001047 buildArches = append(buildArches, arches[0])
Colin Cross4225f652015-09-17 14:33:42 -07001048 case "32":
Colin Crossb9db4802016-06-03 01:50:47 +00001049 for _, a := range arches {
1050 if a.ArchType.Multilib == "lib32" {
1051 buildArches = append(buildArches, a)
Colin Cross4225f652015-09-17 14:33:42 -07001052 }
1053 }
1054 case "64":
Colin Crossb9db4802016-06-03 01:50:47 +00001055 for _, a := range arches {
1056 if a.ArchType.Multilib == "lib64" {
1057 buildArches = append(buildArches, a)
Colin Cross4225f652015-09-17 14:33:42 -07001058 }
1059 }
1060 default:
1061 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
1062 multilib)
Colin Crossb9db4802016-06-03 01:50:47 +00001063 //buildArches = append(buildArches, arches[0])
Colin Cross4225f652015-09-17 14:33:42 -07001064 }
1065
Colin Crossb9db4802016-06-03 01:50:47 +00001066 return buildArches, nil
Colin Cross4225f652015-09-17 14:33:42 -07001067}