blob: fd2969ea6527298e401cbf37cb34556cd9fa2453 [file] [log] [blame]
Colin Cross3f40fa42015-01-30 17:27:36 -08001// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package common
16
17import (
Colin Cross3f40fa42015-01-30 17:27:36 -080018 "fmt"
19 "reflect"
20 "runtime"
21 "strings"
Colin Crossf6566ed2015-03-24 11:13:38 -070022
23 "github.com/google/blueprint"
24 "github.com/google/blueprint/proptools"
Colin Cross3f40fa42015-01-30 17:27:36 -080025)
26
Colin Cross463a90e2015-06-17 14:20:06 -070027func init() {
Colin Crosscfad1192015-11-02 16:43:11 -080028 RegisterBottomUpMutator("defaults_deps", defaultsDepsMutator)
29 RegisterTopDownMutator("defaults", defaultsMutator)
30
Colin Cross6362e272015-10-29 15:25:03 -070031 RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator)
32 RegisterBottomUpMutator("arch", ArchMutator)
Colin Cross463a90e2015-06-17 14:20:06 -070033}
34
Colin Cross3f40fa42015-01-30 17:27:36 -080035var (
Colin Crossec193632015-07-06 17:49:43 -070036 Arm = newArch("arm", "lib32")
37 Arm64 = newArch("arm64", "lib64")
38 Mips = newArch("mips", "lib32")
39 Mips64 = newArch("mips64", "lib64")
40 X86 = newArch("x86", "lib32")
41 X86_64 = newArch("x86_64", "lib64")
Colin Cross2fe66872015-03-30 17:20:39 -070042
43 Common = ArchType{
44 Name: "common",
45 }
Colin Cross3f40fa42015-01-30 17:27:36 -080046)
47
Colin Cross4225f652015-09-17 14:33:42 -070048var archTypeMap = map[string]ArchType{
49 "arm": Arm,
50 "arm64": Arm64,
51 "mips": Mips,
52 "misp64": Mips64,
53 "x86": X86,
54 "x86_64": X86_64,
55}
56
Colin Cross3f40fa42015-01-30 17:27:36 -080057/*
58Example blueprints file containing all variant property groups, with comment listing what type
59of variants get properties in that group:
60
61module {
62 arch: {
63 arm: {
64 // Host or device variants with arm architecture
65 },
66 arm64: {
67 // Host or device variants with arm64 architecture
68 },
69 mips: {
70 // Host or device variants with mips architecture
71 },
72 mips64: {
73 // Host or device variants with mips64 architecture
74 },
75 x86: {
76 // Host or device variants with x86 architecture
77 },
78 x86_64: {
79 // Host or device variants with x86_64 architecture
80 },
81 },
82 multilib: {
83 lib32: {
84 // Host or device variants for 32-bit architectures
85 },
86 lib64: {
87 // Host or device variants for 64-bit architectures
88 },
89 },
90 target: {
91 android: {
92 // Device variants
93 },
94 host: {
95 // Host variants
96 },
97 linux: {
98 // Linux host variants
99 },
100 darwin: {
101 // Darwin host variants
102 },
103 windows: {
104 // Windows host variants
105 },
106 not_windows: {
107 // Non-windows host variants
108 },
109 },
110}
111*/
Colin Cross7d5136f2015-05-11 13:39:40 -0700112
Colin Cross85a88972015-11-23 13:29:51 -0800113type Embed interface{}
114
Colin Cross3f40fa42015-01-30 17:27:36 -0800115type archProperties struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700116 // Properties to vary by target architecture
Colin Cross3f40fa42015-01-30 17:27:36 -0800117 Arch struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700118 // Properties for module variants being built to run on arm (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800119 Arm struct {
120 Embed `blueprint:"filter(android:\"arch_variant\")"`
121
122 // Arm arch variants
123 Armv5te interface{} `blueprint:"filter(android:\"arch_variant\")"`
124 Armv7_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
125 Armv7_a_neon interface{} `blueprint:"filter(android:\"arch_variant\")"`
126
127 // Arm cpu variants
128 Cortex_a7 interface{} `blueprint:"filter(android:\"arch_variant\")"`
129 Cortex_a8 interface{} `blueprint:"filter(android:\"arch_variant\")"`
130 Cortex_a9 interface{} `blueprint:"filter(android:\"arch_variant\")"`
131 Cortex_a15 interface{} `blueprint:"filter(android:\"arch_variant\")"`
132 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
133 Cortex_a53_a57 interface{} `blueprint:"filter(android:\"arch_variant\")"`
134 Krait interface{} `blueprint:"filter(android:\"arch_variant\")"`
135 Denver interface{} `blueprint:"filter(android:\"arch_variant\")"`
136 }
137
Colin Cross7d5136f2015-05-11 13:39:40 -0700138 // Properties for module variants being built to run on arm64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800139 Arm64 struct {
140 Embed `blueprint:"filter(android:\"arch_variant\")"`
141
142 // Arm64 arch variants
143 Armv8_a interface{} `blueprint:"filter(android:\"arch_variant\")"`
144
145 // Arm64 cpu variants
146 Cortex_a53 interface{} `blueprint:"filter(android:\"arch_variant\")"`
147 Denver64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
148 }
149
Colin Cross7d5136f2015-05-11 13:39:40 -0700150 // Properties for module variants being built to run on mips (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800151 Mips struct {
152 Embed `blueprint:"filter(android:\"arch_variant\")"`
153
154 // Mips arch variants
Colin Cross023f1e82015-11-23 16:15:10 -0800155 Mips32_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
156 Mips32r2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
157 Mips32r2_fp_xburst interface{} `blueprint:"filter(android:\"arch_variant\")"`
158 Mips32r2dsp_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
159 Mips32r2dspr2_fp interface{} `blueprint:"filter(android:\"arch_variant\")"`
160 Mips32r6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
161
162 // Mips arch features
Colin Cross85a88972015-11-23 13:29:51 -0800163 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
164 }
165
Colin Cross7d5136f2015-05-11 13:39:40 -0700166 // Properties for module variants being built to run on mips64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800167 Mips64 struct {
168 Embed `blueprint:"filter(android:\"arch_variant\")"`
169
170 // Mips64 arch variants
171 Rev6 interface{} `blueprint:"filter(android:\"arch_variant\")"`
172 }
173
Colin Cross7d5136f2015-05-11 13:39:40 -0700174 // Properties for module variants being built to run on x86 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800175 X86 struct {
176 Embed `blueprint:"filter(android:\"arch_variant\")"`
177
178 // X86 arch variants
Colin Crossb0cba6a2015-11-20 15:35:26 -0800179 Atom interface{} `blueprint:"filter(android:\"arch_variant\")"`
180 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
181 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
182 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
183 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800184
185 // X86 arch features
Colin Crossb0cba6a2015-11-20 15:35:26 -0800186 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
187 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
188 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
189 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
190 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
191 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
192 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
193 Movbe interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800194 }
195
Colin Cross7d5136f2015-05-11 13:39:40 -0700196 // Properties for module variants being built to run on x86_64 (host or device)
Colin Cross85a88972015-11-23 13:29:51 -0800197 X86_64 struct {
198 Embed `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross6371b382015-11-23 14:53:57 -0800199
200 // X86 arch variants
201 Haswell interface{} `blueprint:"filter(android:\"arch_variant\")"`
202 Ivybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
203 Sandybridge interface{} `blueprint:"filter(android:\"arch_variant\")"`
204 Silvermont interface{} `blueprint:"filter(android:\"arch_variant\")"`
205
206 // X86 arch features
207 Ssse3 interface{} `blueprint:"filter(android:\"arch_variant\")"`
208 Sse4 interface{} `blueprint:"filter(android:\"arch_variant\")"`
209 Sse4_1 interface{} `blueprint:"filter(android:\"arch_variant\")"`
210 Sse4_2 interface{} `blueprint:"filter(android:\"arch_variant\")"`
211 Aes_ni interface{} `blueprint:"filter(android:\"arch_variant\")"`
212 Avx interface{} `blueprint:"filter(android:\"arch_variant\")"`
213 Popcnt interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross85a88972015-11-23 13:29:51 -0800214 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800215 }
Colin Crossec193632015-07-06 17:49:43 -0700216
Colin Cross7d5136f2015-05-11 13:39:40 -0700217 // Properties to vary by 32-bit or 64-bit
Colin Cross3f40fa42015-01-30 17:27:36 -0800218 Multilib struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700219 // Properties for module variants being built to run on 32-bit devices
220 Lib32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
221 // Properties for module variants being built to run on 64-bit devices
222 Lib64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800223 }
Colin Cross7d5136f2015-05-11 13:39:40 -0700224 // Properties to vary by build target (host or device, os, os+archictecture)
Colin Cross3f40fa42015-01-30 17:27:36 -0800225 Target struct {
Colin Cross7d5136f2015-05-11 13:39:40 -0700226 // Properties for module variants being built to run on the host
227 Host interface{} `blueprint:"filter(android:\"arch_variant\")"`
228 // Properties for module variants being built to run on the device
229 Android interface{} `blueprint:"filter(android:\"arch_variant\")"`
230 // Properties for module variants being built to run on arm devices
231 Android_arm interface{} `blueprint:"filter(android:\"arch_variant\")"`
232 // Properties for module variants being built to run on arm64 devices
233 Android_arm64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
234 // Properties for module variants being built to run on mips devices
235 Android_mips interface{} `blueprint:"filter(android:\"arch_variant\")"`
236 // Properties for module variants being built to run on mips64 devices
237 Android_mips64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
238 // Properties for module variants being built to run on x86 devices
239 Android_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
240 // Properties for module variants being built to run on x86_64 devices
241 Android_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
242 // Properties for module variants being built to run on devices that support 64-bit
243 Android64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
244 // Properties for module variants being built to run on devices that do not support 64-bit
245 Android32 interface{} `blueprint:"filter(android:\"arch_variant\")"`
246 // Properties for module variants being built to run on linux hosts
247 Linux interface{} `blueprint:"filter(android:\"arch_variant\")"`
248 // Properties for module variants being built to run on linux x86 hosts
249 Linux_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
250 // Properties for module variants being built to run on linux x86_64 hosts
251 Linux_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
252 // Properties for module variants being built to run on darwin hosts
253 Darwin interface{} `blueprint:"filter(android:\"arch_variant\")"`
254 // Properties for module variants being built to run on darwin x86 hosts
255 Darwin_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"`
256 // Properties for module variants being built to run on darwin x86_64 hosts
257 Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"`
258 // Properties for module variants being built to run on windows hosts
259 Windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
260 // Properties for module variants being built to run on linux or darwin hosts
261 Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800262 }
263}
264
Colin Crossc5c24ad2015-11-20 15:35:00 -0800265var archFeatureMap = map[ArchType]map[string][]string{}
266
267func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
Colin Cross85a88972015-11-23 13:29:51 -0800268 archField := proptools.FieldNameForProperty(arch.Name)
269 variantField := proptools.FieldNameForProperty(variant)
270 archStruct := reflect.ValueOf(archProperties{}.Arch).FieldByName(archField)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800271 if variant != "" {
Colin Cross85a88972015-11-23 13:29:51 -0800272 if !archStruct.FieldByName(variantField).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800273 panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
274 }
275 }
276 for _, feature := range features {
277 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800278 if !archStruct.FieldByName(field).IsValid() {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800279 panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
280 }
281 }
282 if archFeatureMap[arch] == nil {
283 archFeatureMap[arch] = make(map[string][]string)
284 }
285 archFeatureMap[arch][variant] = features
286}
287
Colin Cross3f40fa42015-01-30 17:27:36 -0800288// An Arch indicates a single CPU architecture.
289type Arch struct {
Colin Crossc5c24ad2015-11-20 15:35:00 -0800290 ArchType ArchType
291 ArchVariant string
292 CpuVariant string
293 Abi []string
294 ArchFeatures []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800295}
296
297func (a Arch) String() string {
Colin Crossd3ba0392015-05-07 14:11:29 -0700298 s := a.ArchType.String()
Colin Cross3f40fa42015-01-30 17:27:36 -0800299 if a.ArchVariant != "" {
300 s += "_" + a.ArchVariant
301 }
302 if a.CpuVariant != "" {
303 s += "_" + a.CpuVariant
304 }
305 return s
306}
307
308type ArchType struct {
Colin Crossec193632015-07-06 17:49:43 -0700309 Name string
310 Multilib string
Colin Cross3f40fa42015-01-30 17:27:36 -0800311}
312
Colin Crossec193632015-07-06 17:49:43 -0700313func newArch(name, multilib string) ArchType {
Colin Cross3f40fa42015-01-30 17:27:36 -0800314 return ArchType{
Colin Crossec193632015-07-06 17:49:43 -0700315 Name: name,
316 Multilib: multilib,
Colin Cross3f40fa42015-01-30 17:27:36 -0800317 }
318}
319
320func (a ArchType) String() string {
321 return a.Name
322}
323
324type HostOrDeviceSupported int
325
326const (
327 _ HostOrDeviceSupported = iota
328 HostSupported
329 DeviceSupported
330 HostAndDeviceSupported
331)
332
333type HostOrDevice int
334
335const (
336 _ HostOrDevice = iota
337 Host
338 Device
339)
340
341func (hod HostOrDevice) String() string {
342 switch hod {
343 case Device:
344 return "device"
345 case Host:
346 return "host"
347 default:
348 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
349 }
350}
351
Colin Crossec193632015-07-06 17:49:43 -0700352func (hod HostOrDevice) Property() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800353 switch hod {
354 case Device:
355 return "android"
356 case Host:
357 return "host"
358 default:
359 panic(fmt.Sprintf("unexpected HostOrDevice value %d", hod))
360 }
361}
362
Colin Cross3f40fa42015-01-30 17:27:36 -0800363func (hod HostOrDevice) Host() bool {
364 if hod == 0 {
365 panic("HostOrDevice unset")
366 }
367 return hod == Host
368}
369
370func (hod HostOrDevice) Device() bool {
371 if hod == 0 {
372 panic("HostOrDevice unset")
373 }
374 return hod == Device
375}
376
377var hostOrDeviceName = map[HostOrDevice]string{
378 Device: "device",
379 Host: "host",
380}
381
382var (
Colin Crossd3ba0392015-05-07 14:11:29 -0700383 commonArch = Arch{
384 ArchType: Common,
Colin Cross2fe66872015-03-30 17:20:39 -0700385 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800386)
387
Colin Cross6362e272015-10-29 15:25:03 -0700388func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700389 var module AndroidModule
390 var ok bool
391 if module, ok = mctx.Module().(AndroidModule); !ok {
392 return
393 }
394
395 hods := []HostOrDevice{}
396
397 if module.base().HostSupported() {
398 hods = append(hods, Host)
399 }
400
401 if module.base().DeviceSupported() {
402 hods = append(hods, Device)
403 }
404
405 if len(hods) == 0 {
406 return
407 }
408
409 hodNames := []string{}
410 for _, hod := range hods {
411 hodNames = append(hodNames, hod.String())
412 }
413
414 modules := mctx.CreateVariations(hodNames...)
415 for i, m := range modules {
416 m.(AndroidModule).base().SetHostOrDevice(hods[i])
417 }
418}
419
Colin Cross6362e272015-10-29 15:25:03 -0700420func ArchMutator(mctx AndroidBottomUpMutatorContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800421 var module AndroidModule
422 var ok bool
423 if module, ok = mctx.Module().(AndroidModule); !ok {
424 return
425 }
426
Colin Cross4225f652015-09-17 14:33:42 -0700427 hostArches, deviceArches, err := decodeArchProductVariables(mctx.Config().(Config).ProductVariables)
428 if err != nil {
429 mctx.ModuleErrorf("%s", err.Error())
430 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800431
Colin Cross4225f652015-09-17 14:33:42 -0700432 moduleArches := []Arch{}
433 multilib := module.base().commonProperties.Compile_multilib
Colin Cross3f40fa42015-01-30 17:27:36 -0800434
Colin Crossd3ba0392015-05-07 14:11:29 -0700435 if module.base().HostSupported() && module.base().HostOrDevice().Host() {
Colin Cross4225f652015-09-17 14:33:42 -0700436 hostModuleArches, err := decodeMultilib(multilib, hostArches)
437 if err != nil {
438 mctx.ModuleErrorf("%s", err.Error())
Colin Cross2fe66872015-03-30 17:20:39 -0700439 }
Colin Cross4225f652015-09-17 14:33:42 -0700440
441 moduleArches = append(moduleArches, hostModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800442 }
443
Colin Crossd3ba0392015-05-07 14:11:29 -0700444 if module.base().DeviceSupported() && module.base().HostOrDevice().Device() {
Colin Cross4225f652015-09-17 14:33:42 -0700445 deviceModuleArches, err := decodeMultilib(multilib, deviceArches)
446 if err != nil {
447 mctx.ModuleErrorf("%s", err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800448 }
Colin Cross4225f652015-09-17 14:33:42 -0700449
450 moduleArches = append(moduleArches, deviceModuleArches...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800451 }
452
Colin Cross4225f652015-09-17 14:33:42 -0700453 if len(moduleArches) == 0 {
Colin Cross5049f022015-03-18 13:28:46 -0700454 return
455 }
456
Colin Cross3f40fa42015-01-30 17:27:36 -0800457 archNames := []string{}
Colin Cross4225f652015-09-17 14:33:42 -0700458 for _, arch := range moduleArches {
Colin Cross3f40fa42015-01-30 17:27:36 -0800459 archNames = append(archNames, arch.String())
460 }
461
462 modules := mctx.CreateVariations(archNames...)
463
464 for i, m := range modules {
Colin Cross4225f652015-09-17 14:33:42 -0700465 m.(AndroidModule).base().SetArch(moduleArches[i])
Colin Crossd3ba0392015-05-07 14:11:29 -0700466 m.(AndroidModule).base().setArchProperties(mctx)
Colin Cross3f40fa42015-01-30 17:27:36 -0800467 }
468}
469
Colin Crosscfad1192015-11-02 16:43:11 -0800470func InitArchModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800471 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
472
473 base := m.base()
474
Colin Cross3f40fa42015-01-30 17:27:36 -0800475 base.generalProperties = append(base.generalProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800476 propertyStructs...)
477
478 for _, properties := range base.generalProperties {
479 propertiesValue := reflect.ValueOf(properties)
480 if propertiesValue.Kind() != reflect.Ptr {
481 panic("properties must be a pointer to a struct")
482 }
483
484 propertiesValue = propertiesValue.Elem()
485 if propertiesValue.Kind() != reflect.Struct {
486 panic("properties must be a pointer to a struct")
487 }
488
489 archProperties := &archProperties{}
490 forEachInterface(reflect.ValueOf(archProperties), func(v reflect.Value) {
Colin Cross3ab7d882015-05-19 13:03:01 -0700491 newValue := proptools.CloneEmptyProperties(propertiesValue)
Colin Cross3f40fa42015-01-30 17:27:36 -0800492 v.Set(newValue)
493 })
494
495 base.archProperties = append(base.archProperties, archProperties)
496 }
497
498 var allProperties []interface{}
499 allProperties = append(allProperties, base.generalProperties...)
500 for _, asp := range base.archProperties {
501 allProperties = append(allProperties, asp)
502 }
503
504 return m, allProperties
505}
506
Colin Crossec193632015-07-06 17:49:43 -0700507var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
508
Colin Cross6362e272015-10-29 15:25:03 -0700509func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
Colin Cross85a88972015-11-23 13:29:51 -0800510 dst, src interface{}, field, srcPrefix string) interface{} {
Colin Cross06a931b2015-10-28 17:23:31 -0700511
Colin Crosseeabb892015-11-20 13:07:51 -0800512 srcField := reflect.ValueOf(src).FieldByName(field)
513 if !srcField.IsValid() {
514 ctx.ModuleErrorf("field %q does not exist", srcPrefix)
Colin Cross85a88972015-11-23 13:29:51 -0800515 return nil
516 }
517
518 ret := srcField
519
520 if srcField.Kind() == reflect.Struct {
521 srcField = srcField.FieldByName("Embed")
Colin Crosseeabb892015-11-20 13:07:51 -0800522 }
523
524 src = srcField.Elem().Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700525
526 filter := func(property string,
527 dstField, srcField reflect.StructField,
528 dstValue, srcValue interface{}) (bool, error) {
529
530 srcProperty := srcPrefix + "." + property
531
532 if !proptools.HasTag(dstField, "android", "arch_variant") {
533 if ctx.ContainsProperty(srcProperty) {
534 return false, fmt.Errorf("can't be specific to a build variant")
535 } else {
536 return false, nil
537 }
538 }
539
540 return true, nil
541 }
542
543 err := proptools.AppendProperties(dst, src, filter)
544 if err != nil {
545 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
546 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
547 } else {
548 panic(err)
549 }
550 }
Colin Cross85a88972015-11-23 13:29:51 -0800551
552 return ret.Interface()
Colin Cross06a931b2015-10-28 17:23:31 -0700553}
554
Colin Cross3f40fa42015-01-30 17:27:36 -0800555// Rewrite the module's properties structs to contain arch-specific values.
Colin Cross6362e272015-10-29 15:25:03 -0700556func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
Colin Crossd3ba0392015-05-07 14:11:29 -0700557 arch := a.commonProperties.CompileArch
558 hod := a.commonProperties.CompileHostOrDevice
559
Colin Cross2fe66872015-03-30 17:20:39 -0700560 if arch.ArchType == Common {
561 return
562 }
563
Colin Cross3f40fa42015-01-30 17:27:36 -0800564 for i := range a.generalProperties {
Colin Cross06a931b2015-10-28 17:23:31 -0700565 genProps := a.generalProperties[i]
566 archProps := a.archProperties[i]
Colin Cross3f40fa42015-01-30 17:27:36 -0800567 // Handle arch-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700568 // arch: {
569 // arm64: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800570 // key: value,
571 // },
572 // },
573 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700574
Colin Crossec193632015-07-06 17:49:43 -0700575 field := proptools.FieldNameForProperty(t.Name)
Colin Cross06a931b2015-10-28 17:23:31 -0700576 prefix := "arch." + t.Name
Colin Cross85a88972015-11-23 13:29:51 -0800577 archStruct := a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700578
579 // Handle arch-variant-specific properties in the form:
580 // arch: {
581 // variant: {
582 // key: value,
583 // },
584 // },
585 v := dashToUnderscoreReplacer.Replace(arch.ArchVariant)
586 if v != "" {
587 field := proptools.FieldNameForProperty(v)
Colin Cross85a88972015-11-23 13:29:51 -0800588 prefix := "arch." + t.Name + "." + v
589 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700590 }
591
592 // Handle cpu-variant-specific properties in the form:
593 // arch: {
594 // variant: {
595 // key: value,
596 // },
597 // },
598 c := dashToUnderscoreReplacer.Replace(arch.CpuVariant)
599 if c != "" {
600 field := proptools.FieldNameForProperty(c)
Colin Cross85a88972015-11-23 13:29:51 -0800601 prefix := "arch." + t.Name + "." + c
602 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossec193632015-07-06 17:49:43 -0700603 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800604
Colin Crossc5c24ad2015-11-20 15:35:00 -0800605 // Handle arch-feature-specific properties in the form:
606 // arch: {
607 // feature: {
608 // key: value,
609 // },
610 // },
611 for _, feature := range arch.ArchFeatures {
612 field := proptools.FieldNameForProperty(feature)
Colin Cross85a88972015-11-23 13:29:51 -0800613 prefix := "arch." + t.Name + "." + feature
614 a.appendProperties(ctx, genProps, archStruct, field, prefix)
Colin Crossc5c24ad2015-11-20 15:35:00 -0800615 }
616
Colin Cross3f40fa42015-01-30 17:27:36 -0800617 // Handle multilib-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700618 // multilib: {
619 // lib32: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800620 // key: value,
621 // },
622 // },
Colin Cross06a931b2015-10-28 17:23:31 -0700623 field = proptools.FieldNameForProperty(t.Multilib)
624 prefix = "multilib." + t.Multilib
625 a.appendProperties(ctx, genProps, archProps.Multilib, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800626
627 // Handle host-or-device-specific properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700628 // target: {
629 // host: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800630 // key: value,
631 // },
632 // },
Colin Crossec193632015-07-06 17:49:43 -0700633 hodProperty := hod.Property()
Colin Cross06a931b2015-10-28 17:23:31 -0700634 field = proptools.FieldNameForProperty(hodProperty)
635 prefix = "target." + hodProperty
636 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800637
638 // Handle host target properties in the form:
Colin Crossb05bff22015-04-30 15:08:04 -0700639 // target: {
640 // linux: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800641 // key: value,
642 // },
Colin Crossb05bff22015-04-30 15:08:04 -0700643 // not_windows: {
644 // key: value,
645 // },
646 // linux_x86: {
647 // key: value,
648 // },
649 // linux_arm: {
Colin Cross3f40fa42015-01-30 17:27:36 -0800650 // key: value,
651 // },
652 // },
653 var osList = []struct {
654 goos string
655 field string
656 }{
657 {"darwin", "Darwin"},
658 {"linux", "Linux"},
659 {"windows", "Windows"},
660 }
661
662 if hod.Host() {
663 for _, v := range osList {
664 if v.goos == runtime.GOOS {
Colin Cross06a931b2015-10-28 17:23:31 -0700665 field := v.field
666 prefix := "target." + v.goos
667 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700668 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700669 field = v.field + "_" + t.Name
670 prefix = "target." + v.goos + "_" + t.Name
671 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800672 }
673 }
Colin Cross06a931b2015-10-28 17:23:31 -0700674 field := "Not_windows"
675 prefix := "target.not_windows"
676 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Cross3f40fa42015-01-30 17:27:36 -0800677 }
678
Colin Crossf8209412015-03-26 14:44:26 -0700679 // Handle 64-bit device properties in the form:
680 // target {
681 // android64 {
682 // key: value,
683 // },
684 // android32 {
685 // key: value,
686 // },
687 // },
688 // WARNING: this is probably not what you want to use in your blueprints file, it selects
689 // options for all targets on a device that supports 64-bit binaries, not just the targets
690 // that are being compiled for 64-bit. Its expected use case is binaries like linker and
691 // debuggerd that need to know when they are a 32-bit process running on a 64-bit device
692 if hod.Device() {
693 if true /* && target_is_64_bit */ {
Colin Cross06a931b2015-10-28 17:23:31 -0700694 field := "Android64"
695 prefix := "target.android64"
696 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700697 } else {
Colin Cross06a931b2015-10-28 17:23:31 -0700698 field := "Android32"
699 prefix := "target.android32"
700 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossf8209412015-03-26 14:44:26 -0700701 }
702 }
Colin Crossb05bff22015-04-30 15:08:04 -0700703
704 // Handle device architecture properties in the form:
705 // target {
706 // android_arm {
707 // key: value,
708 // },
709 // android_x86 {
710 // key: value,
711 // },
712 // },
713 if hod.Device() {
714 t := arch.ArchType
Colin Cross06a931b2015-10-28 17:23:31 -0700715 field := "Android_" + t.Name
716 prefix := "target.android_" + t.Name
717 a.appendProperties(ctx, genProps, archProps.Target, field, prefix)
Colin Crossb05bff22015-04-30 15:08:04 -0700718 }
719
Colin Cross3f40fa42015-01-30 17:27:36 -0800720 if ctx.Failed() {
721 return
722 }
723 }
724}
725
726func forEachInterface(v reflect.Value, f func(reflect.Value)) {
727 switch v.Kind() {
728 case reflect.Interface:
729 f(v)
730 case reflect.Struct:
731 for i := 0; i < v.NumField(); i++ {
732 forEachInterface(v.Field(i), f)
733 }
734 case reflect.Ptr:
735 forEachInterface(v.Elem(), f)
736 default:
737 panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
738 }
739}
Colin Cross4225f652015-09-17 14:33:42 -0700740
741// Convert the arch product variables into a list of host and device Arch structs
742func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) {
743 if variables.HostArch == nil {
744 return nil, nil, fmt.Errorf("No host primary architecture set")
745 }
746
747 hostArch, err := decodeArch(*variables.HostArch, nil, nil, nil)
748 if err != nil {
749 return nil, nil, err
750 }
751
752 hostArches := []Arch{hostArch}
753
Colin Crosseeabb892015-11-20 13:07:51 -0800754 if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700755 hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
756 if err != nil {
757 return nil, nil, err
758 }
759 hostArches = append(hostArches, hostSecondaryArch)
760 }
761
762 if variables.DeviceArch == nil {
763 return nil, nil, fmt.Errorf("No device primary architecture set")
764 }
765
766 deviceArch, err := decodeArch(*variables.DeviceArch, variables.DeviceArchVariant,
767 variables.DeviceCpuVariant, variables.DeviceAbi)
768 if err != nil {
769 return nil, nil, err
770 }
771
772 deviceArches := []Arch{deviceArch}
773
Colin Crosseeabb892015-11-20 13:07:51 -0800774 if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
Colin Cross4225f652015-09-17 14:33:42 -0700775 deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
776 variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
777 variables.DeviceSecondaryAbi)
778 if err != nil {
779 return nil, nil, err
780 }
781 deviceArches = append(deviceArches, deviceSecondaryArch)
782 }
783
784 return hostArches, deviceArches, nil
785}
786
787// Convert a set of strings from product variables into a single Arch struct
788func decodeArch(arch string, archVariant, cpuVariant *string, abi *[]string) (Arch, error) {
789 stringPtr := func(p *string) string {
790 if p != nil {
791 return *p
792 }
793 return ""
794 }
795
796 slicePtr := func(p *[]string) []string {
797 if p != nil {
798 return *p
799 }
800 return nil
801 }
802
Colin Crosseeabb892015-11-20 13:07:51 -0800803 archType, ok := archTypeMap[arch]
804 if !ok {
805 return Arch{}, fmt.Errorf("unknown arch %q", arch)
806 }
Colin Cross4225f652015-09-17 14:33:42 -0700807
Colin Crosseeabb892015-11-20 13:07:51 -0800808 a := Arch{
Colin Cross4225f652015-09-17 14:33:42 -0700809 ArchType: archType,
810 ArchVariant: stringPtr(archVariant),
811 CpuVariant: stringPtr(cpuVariant),
812 Abi: slicePtr(abi),
Colin Crosseeabb892015-11-20 13:07:51 -0800813 }
814
815 if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
816 a.ArchVariant = ""
817 }
818
819 if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
820 a.CpuVariant = ""
821 }
822
823 for i := 0; i < len(a.Abi); i++ {
824 if a.Abi[i] == "" {
825 a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
826 i--
827 }
828 }
829
Colin Crossc5c24ad2015-11-20 15:35:00 -0800830 if featureMap, ok := archFeatureMap[archType]; ok {
831 a.ArchFeatures = featureMap[stringPtr(archVariant)]
832 }
833
Colin Crosseeabb892015-11-20 13:07:51 -0800834 return a, nil
Colin Cross4225f652015-09-17 14:33:42 -0700835}
836
837// Use the module multilib setting to select one or more arches from an arch list
838func decodeMultilib(multilib string, arches []Arch) ([]Arch, error) {
839 buildArches := []Arch{}
840 switch multilib {
841 case "common":
842 buildArches = append(buildArches, commonArch)
843 case "both":
844 buildArches = append(buildArches, arches...)
845 case "first":
846 buildArches = append(buildArches, arches[0])
847 case "32":
848 for _, a := range arches {
849 if a.ArchType.Multilib == "lib32" {
850 buildArches = append(buildArches, a)
851 }
852 }
853 case "64":
854 for _, a := range arches {
855 if a.ArchType.Multilib == "lib64" {
856 buildArches = append(buildArches, a)
857 }
858 }
859 default:
860 return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
861 multilib)
862 //buildArches = append(buildArches, arches[0])
863 }
864
865 return buildArches, nil
866}