blob: 6ca0d6db142f38e459211cde01bb58377444eed5 [file] [log] [blame]
Jingwen Chen5d864492021-02-24 07:20:12 -05001package bp2build
2
Jingwen Chen91220d72021-03-24 02:18:33 -04003import (
4 "android/soong/android"
5 "android/soong/bazel"
6 "fmt"
7 "reflect"
8)
Jingwen Chen5d864492021-02-24 07:20:12 -05009
10// Configurability support for bp2build.
11
Jingwen Chen91220d72021-03-24 02:18:33 -040012// prettyPrintStringListAttribute converts a StringListAttribute to its Bazel
13// syntax. May contain a select statement.
14func prettyPrintStringListAttribute(stringList bazel.StringListAttribute, indent int) (string, error) {
15 ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent)
16 if err != nil {
17 return ret, err
Jingwen Chen5d864492021-02-24 07:20:12 -050018 }
Jingwen Chen91220d72021-03-24 02:18:33 -040019
20 if !stringList.HasConfigurableValues() {
21 // Select statement not needed.
22 return ret, nil
23 }
24
25 // Create the selects for arch specific values.
26 selects := map[string]reflect.Value{}
27 for arch, selectKey := range bazel.PlatformArchMap {
28 selects[selectKey] = reflect.ValueOf(stringList.GetValueForArch(arch))
29 }
30
31 selectMap, err := prettyPrintSelectMap(selects, "[]", indent)
32 return ret + selectMap, err
33}
34
35// prettyPrintLabelListAttribute converts a LabelListAttribute to its Bazel
36// syntax. May contain select statements.
37func prettyPrintLabelListAttribute(labels bazel.LabelListAttribute, indent int) (string, error) {
38 // TODO(b/165114590): convert glob syntax
39 ret, err := prettyPrint(reflect.ValueOf(labels.Value.Includes), indent)
40 if err != nil {
41 return ret, err
42 }
43
44 if !labels.HasConfigurableValues() {
45 // Select statements not needed.
46 return ret, nil
47 }
48
49 // Create the selects for arch specific values.
50 archSelects := map[string]reflect.Value{}
51 for arch, selectKey := range bazel.PlatformArchMap {
52 archSelects[selectKey] = reflect.ValueOf(labels.GetValueForArch(arch).Includes)
53 }
54 selectMap, err := prettyPrintSelectMap(archSelects, "[]", indent)
55 if err != nil {
56 return "", err
57 }
58 ret += selectMap
59
60 // Create the selects for target os specific values.
61 osSelects := map[string]reflect.Value{}
62 for os, selectKey := range bazel.PlatformOsMap {
63 osSelects[selectKey] = reflect.ValueOf(labels.GetValueForOS(os).Includes)
64 }
65 selectMap, err = prettyPrintSelectMap(osSelects, "[]", indent)
66 return ret + selectMap, err
67}
68
69// prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
70// to construct a select map for any kind of attribute type.
71func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue string, indent int) (string, error) {
72 var selects string
73 for _, selectKey := range android.SortedStringKeys(selectMap) {
74 value := selectMap[selectKey]
75 if isZero(value) {
76 // Ignore zero values to not generate empty lists.
77 continue
78 }
79 s, err := prettyPrintSelectEntry(value, selectKey, indent)
80 if err != nil {
81 return "", err
82 }
83 selects += s + ",\n"
84 }
85
86 if len(selects) == 0 {
87 // No conditions (or all values are empty lists), so no need for a map.
88 return "", nil
89 }
90
91 // Create the map.
92 ret := " + select({\n"
93 ret += selects
94 // default condition comes last.
95 ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue)
96 ret += makeIndent(indent)
97 ret += "})"
98
99 return ret, nil
100}
101
102// prettyPrintSelectEntry converts a reflect.Value into an entry in a select map
103// with a provided key.
104func prettyPrintSelectEntry(value reflect.Value, key string, indent int) (string, error) {
105 s := makeIndent(indent + 1)
106 v, err := prettyPrint(value, indent+1)
107 if err != nil {
108 return "", err
109 }
110 s += fmt.Sprintf("\"%s\": %s", key, v)
111 return s, nil
112}