blob: 6ecf6caa6f6570e50669d1b446d93401bab25eed [file] [log] [blame]
Jingwen Chen30f5aaa2020-11-19 05:38:02 -05001// Copyright 2020 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 bazel
16
Rupert Shuttleworth2e4219b2021-03-12 11:04:21 +000017import (
18 "fmt"
Jingwen Chen63930982021-03-24 10:04:33 -040019 "path/filepath"
Liz Kammera060c452021-03-24 10:14:47 -040020 "regexp"
Rupert Shuttleworth2e4219b2021-03-12 11:04:21 +000021 "sort"
Liz Kammer6fd7b3f2021-05-06 13:54:29 -040022 "strings"
Rupert Shuttleworth2e4219b2021-03-12 11:04:21 +000023)
Jingwen Chen5d864492021-02-24 07:20:12 -050024
Jingwen Chen73850672020-12-14 08:25:34 -050025// BazelTargetModuleProperties contain properties and metadata used for
26// Blueprint to BUILD file conversion.
27type BazelTargetModuleProperties struct {
28 // The Bazel rule class for this target.
Liz Kammerfc46bc12021-02-19 11:06:17 -050029 Rule_class string `blueprint:"mutated"`
Jingwen Chen40067de2021-01-26 21:58:43 -050030
31 // The target label for the bzl file containing the definition of the rule class.
Liz Kammerfc46bc12021-02-19 11:06:17 -050032 Bzl_load_location string `blueprint:"mutated"`
Jingwen Chen73850672020-12-14 08:25:34 -050033}
Liz Kammer356f7d42021-01-26 09:18:53 -050034
Jingwen Chenfb4692a2021-02-07 10:05:16 -050035const BazelTargetModuleNamePrefix = "__bp2build__"
36
Liz Kammera060c452021-03-24 10:14:47 -040037var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)")
38
Jingwen Chen38e62642021-04-19 05:00:15 +000039// Label is used to represent a Bazel compatible Label. Also stores the original
40// bp text to support string replacement.
Liz Kammer356f7d42021-01-26 09:18:53 -050041type Label struct {
Jingwen Chen38e62642021-04-19 05:00:15 +000042 // The string representation of a Bazel target label. This can be a relative
43 // or fully qualified label. These labels are used for generating BUILD
44 // files with bp2build.
45 Label string
46
47 // The original Soong/Blueprint module name that the label was derived from.
48 // This is used for replacing references to the original name with the new
49 // label, for example in genrule cmds.
50 //
51 // While there is a reversible 1:1 mapping from the module name to Bazel
52 // label with bp2build that could make computing the original module name
53 // from the label automatic, it is not the case for handcrafted targets,
54 // where modules can have a custom label mapping through the { bazel_module:
55 // { label: <label> } } property.
56 //
57 // With handcrafted labels, those modules don't go through bp2build
58 // conversion, but relies on handcrafted targets in the source tree.
59 OriginalModuleName string
Liz Kammer356f7d42021-01-26 09:18:53 -050060}
61
62// LabelList is used to represent a list of Bazel labels.
63type LabelList struct {
64 Includes []Label
65 Excludes []Label
66}
67
Jingwen Chen63930982021-03-24 10:04:33 -040068// uniqueParentDirectories returns a list of the unique parent directories for
69// all files in ll.Includes.
70func (ll *LabelList) uniqueParentDirectories() []string {
71 dirMap := map[string]bool{}
72 for _, label := range ll.Includes {
73 dirMap[filepath.Dir(label.Label)] = true
74 }
75 dirs := []string{}
76 for dir := range dirMap {
77 dirs = append(dirs, dir)
78 }
79 return dirs
80}
81
Liz Kammer356f7d42021-01-26 09:18:53 -050082// Append appends the fields of other labelList to the corresponding fields of ll.
83func (ll *LabelList) Append(other LabelList) {
84 if len(ll.Includes) > 0 || len(other.Includes) > 0 {
85 ll.Includes = append(ll.Includes, other.Includes...)
86 }
87 if len(ll.Excludes) > 0 || len(other.Excludes) > 0 {
88 ll.Excludes = append(other.Excludes, other.Excludes...)
89 }
90}
Jingwen Chen5d864492021-02-24 07:20:12 -050091
Jingwen Chened9c17d2021-04-13 07:14:55 +000092// UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns
93// the slice in a sorted order.
94func UniqueSortedBazelLabels(originalLabels []Label) []Label {
Rupert Shuttleworth2e4219b2021-03-12 11:04:21 +000095 uniqueLabelsSet := make(map[Label]bool)
96 for _, l := range originalLabels {
97 uniqueLabelsSet[l] = true
98 }
99 var uniqueLabels []Label
100 for l, _ := range uniqueLabelsSet {
101 uniqueLabels = append(uniqueLabels, l)
102 }
103 sort.SliceStable(uniqueLabels, func(i, j int) bool {
104 return uniqueLabels[i].Label < uniqueLabels[j].Label
105 })
106 return uniqueLabels
107}
108
109func UniqueBazelLabelList(originalLabelList LabelList) LabelList {
110 var uniqueLabelList LabelList
Jingwen Chened9c17d2021-04-13 07:14:55 +0000111 uniqueLabelList.Includes = UniqueSortedBazelLabels(originalLabelList.Includes)
112 uniqueLabelList.Excludes = UniqueSortedBazelLabels(originalLabelList.Excludes)
Rupert Shuttleworth2e4219b2021-03-12 11:04:21 +0000113 return uniqueLabelList
114}
115
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000116// Subtract needle from haystack
117func SubtractStrings(haystack []string, needle []string) []string {
118 // This is really a set
119 remainder := make(map[string]bool)
120
121 for _, s := range haystack {
122 remainder[s] = true
123 }
124 for _, s := range needle {
125 delete(remainder, s)
126 }
127
128 var strings []string
129 for s, _ := range remainder {
130 strings = append(strings, s)
131 }
132
133 sort.SliceStable(strings, func(i, j int) bool {
134 return strings[i] < strings[j]
135 })
136
137 return strings
138}
139
Chris Parsons990c4f42021-05-25 12:10:58 -0400140// Return all needles in a given haystack, where needleFn is true for needles.
141func FilterLabelList(haystack LabelList, needleFn func(string) bool) LabelList {
142 var includes []Label
143
144 for _, inc := range haystack.Includes {
145 if needleFn(inc.Label) {
146 includes = append(includes, inc)
147 }
148 }
149 return LabelList{Includes: includes, Excludes: haystack.Excludes}
150}
151
152// Return all needles in a given haystack, where needleFn is true for needles.
153func FilterLabelListAttribute(haystack LabelListAttribute, needleFn func(string) bool) LabelListAttribute {
154 var result LabelListAttribute
155
156 result.Value = FilterLabelList(haystack.Value, needleFn)
157
158 for arch := range PlatformArchMap {
159 result.SetValueForArch(arch, FilterLabelList(haystack.GetValueForArch(arch), needleFn))
160 }
161
162 for os := range PlatformOsMap {
163 result.SetValueForOS(os, FilterLabelList(haystack.GetValueForOS(os), needleFn))
164 }
165
166 return result
167}
168
169// Subtract needle from haystack
170func SubtractBazelLabelListAttribute(haystack LabelListAttribute, needle LabelListAttribute) LabelListAttribute {
171 var result LabelListAttribute
172
173 for arch := range PlatformArchMap {
174 result.SetValueForArch(arch,
175 SubtractBazelLabelList(haystack.GetValueForArch(arch), needle.GetValueForArch(arch)))
176 }
177
178 for os := range PlatformOsMap {
179 result.SetValueForOS(os,
180 SubtractBazelLabelList(haystack.GetValueForOS(os), needle.GetValueForOS(os)))
181 }
182
183 result.Value = SubtractBazelLabelList(haystack.Value, needle.Value)
184
185 return result
186}
187
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000188// Subtract needle from haystack
189func SubtractBazelLabels(haystack []Label, needle []Label) []Label {
190 // This is really a set
191 remainder := make(map[Label]bool)
192
193 for _, label := range haystack {
194 remainder[label] = true
195 }
196 for _, label := range needle {
197 delete(remainder, label)
198 }
199
200 var labels []Label
201 for label, _ := range remainder {
202 labels = append(labels, label)
203 }
204
205 sort.SliceStable(labels, func(i, j int) bool {
206 return labels[i].Label < labels[j].Label
207 })
208
209 return labels
210}
211
Chris Parsons484e50a2021-05-13 15:13:04 -0400212// Appends two LabelLists, returning the combined list.
213func AppendBazelLabelLists(a LabelList, b LabelList) LabelList {
214 var result LabelList
215 result.Includes = append(a.Includes, b.Includes...)
216 result.Excludes = append(a.Excludes, b.Excludes...)
217 return result
218}
219
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000220// Subtract needle from haystack
221func SubtractBazelLabelList(haystack LabelList, needle LabelList) LabelList {
222 var result LabelList
223 result.Includes = SubtractBazelLabels(haystack.Includes, needle.Includes)
224 // NOTE: Excludes are intentionally not subtracted
225 result.Excludes = haystack.Excludes
226 return result
227}
228
Jingwen Chen07027912021-03-15 06:02:43 -0400229const (
Jingwen Chen91220d72021-03-24 02:18:33 -0400230 // ArchType names in arch.go
Jingwen Chen07027912021-03-15 06:02:43 -0400231 ARCH_ARM = "arm"
232 ARCH_ARM64 = "arm64"
Jingwen Chen91220d72021-03-24 02:18:33 -0400233 ARCH_X86 = "x86"
234 ARCH_X86_64 = "x86_64"
235
236 // OsType names in arch.go
237 OS_ANDROID = "android"
238 OS_DARWIN = "darwin"
239 OS_FUCHSIA = "fuchsia"
240 OS_LINUX = "linux_glibc"
241 OS_LINUX_BIONIC = "linux_bionic"
242 OS_WINDOWS = "windows"
Jingwen Chene32e9e02021-04-23 09:17:24 +0000243
244 // This is the string representation of the default condition wherever a
245 // configurable attribute is used in a select statement, i.e.
246 // //conditions:default for Bazel.
247 //
248 // This is consistently named "conditions_default" to mirror the Soong
249 // config variable default key in an Android.bp file, although there's no
250 // integration with Soong config variables (yet).
251 CONDITIONS_DEFAULT = "conditions_default"
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400252
253 ConditionsDefaultSelectKey = "//conditions:default"
254
255 productVariableBazelPackage = "//build/bazel/product_variables"
Jingwen Chen07027912021-03-15 06:02:43 -0400256)
257
258var (
Jingwen Chenc1c26502021-04-05 10:35:13 +0000259 // These are the list of OSes and architectures with a Bazel config_setting
260 // and constraint value equivalent. These exist in arch.go, but the android
261 // package depends on the bazel package, so a cyclic dependency prevents
262 // using those variables here.
Jingwen Chen91220d72021-03-24 02:18:33 -0400263
264 // A map of architectures to the Bazel label of the constraint_value
265 // for the @platforms//cpu:cpu constraint_setting
266 PlatformArchMap = map[string]string{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000267 ARCH_ARM: "//build/bazel/platforms/arch:arm",
268 ARCH_ARM64: "//build/bazel/platforms/arch:arm64",
269 ARCH_X86: "//build/bazel/platforms/arch:x86",
270 ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400271 CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of as arch select map.
Jingwen Chen91220d72021-03-24 02:18:33 -0400272 }
273
274 // A map of target operating systems to the Bazel label of the
275 // constraint_value for the @platforms//os:os constraint_setting
276 PlatformOsMap = map[string]string{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000277 OS_ANDROID: "//build/bazel/platforms/os:android",
278 OS_DARWIN: "//build/bazel/platforms/os:darwin",
279 OS_FUCHSIA: "//build/bazel/platforms/os:fuchsia",
280 OS_LINUX: "//build/bazel/platforms/os:linux",
281 OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
282 OS_WINDOWS: "//build/bazel/platforms/os:windows",
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400283 CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of an os select map.
Jingwen Chen91220d72021-03-24 02:18:33 -0400284 }
Jingwen Chen07027912021-03-15 06:02:43 -0400285)
286
Jingwen Chenc1c26502021-04-05 10:35:13 +0000287type Attribute interface {
288 HasConfigurableValues() bool
289}
290
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200291// Represents an attribute whose value is a single label
292type LabelAttribute struct {
Lukacs T. Berki598dd002021-05-05 09:00:01 +0200293 Value Label
294 X86 Label
295 X86_64 Label
296 Arm Label
297 Arm64 Label
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200298}
299
Lukacs T. Berki598dd002021-05-05 09:00:01 +0200300func (attr *LabelAttribute) GetValueForArch(arch string) Label {
301 switch arch {
302 case ARCH_ARM:
303 return attr.Arm
304 case ARCH_ARM64:
305 return attr.Arm64
306 case ARCH_X86:
307 return attr.X86
308 case ARCH_X86_64:
309 return attr.X86_64
310 case CONDITIONS_DEFAULT:
311 return attr.Value
312 default:
313 panic("Invalid arch type")
314 }
315}
316
317func (attr *LabelAttribute) SetValueForArch(arch string, value Label) {
318 switch arch {
319 case ARCH_ARM:
320 attr.Arm = value
321 case ARCH_ARM64:
322 attr.Arm64 = value
323 case ARCH_X86:
324 attr.X86 = value
325 case ARCH_X86_64:
326 attr.X86_64 = value
327 default:
328 panic("Invalid arch type")
329 }
330}
331
332func (attr LabelAttribute) HasConfigurableValues() bool {
333 return attr.Arm.Label != "" || attr.Arm64.Label != "" || attr.X86.Label != "" || attr.X86_64.Label != ""
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200334}
335
Jingwen Chen07027912021-03-15 06:02:43 -0400336// Arch-specific label_list typed Bazel attribute values. This should correspond
337// to the types of architectures supported for compilation in arch.go.
338type labelListArchValues struct {
339 X86 LabelList
340 X86_64 LabelList
341 Arm LabelList
342 Arm64 LabelList
Jingwen Chen91220d72021-03-24 02:18:33 -0400343 Common LabelList
Jingwen Chene32e9e02021-04-23 09:17:24 +0000344
345 ConditionsDefault LabelList
Jingwen Chen91220d72021-03-24 02:18:33 -0400346}
347
348type labelListOsValues struct {
349 Android LabelList
350 Darwin LabelList
351 Fuchsia LabelList
352 Linux LabelList
353 LinuxBionic LabelList
354 Windows LabelList
Jingwen Chene32e9e02021-04-23 09:17:24 +0000355
356 ConditionsDefault LabelList
Jingwen Chen07027912021-03-15 06:02:43 -0400357}
358
359// LabelListAttribute is used to represent a list of Bazel labels as an
360// attribute.
361type LabelListAttribute struct {
362 // The non-arch specific attribute label list Value. Required.
363 Value LabelList
364
365 // The arch-specific attribute label list values. Optional. If used, these
366 // are generated in a select statement and appended to the non-arch specific
367 // label list Value.
368 ArchValues labelListArchValues
Jingwen Chen91220d72021-03-24 02:18:33 -0400369
370 // The os-specific attribute label list values. Optional. If used, these
371 // are generated in a select statement and appended to the non-os specific
372 // label list Value.
373 OsValues labelListOsValues
Jingwen Chen07027912021-03-15 06:02:43 -0400374}
375
376// MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
377func MakeLabelListAttribute(value LabelList) LabelListAttribute {
378 return LabelListAttribute{Value: UniqueBazelLabelList(value)}
379}
380
Jingwen Chened9c17d2021-04-13 07:14:55 +0000381// Append all values, including os and arch specific ones, from another
Jingwen Chen63930982021-03-24 10:04:33 -0400382// LabelListAttribute to this LabelListAttribute.
383func (attrs *LabelListAttribute) Append(other LabelListAttribute) {
384 for arch := range PlatformArchMap {
385 this := attrs.GetValueForArch(arch)
386 that := other.GetValueForArch(arch)
387 this.Append(that)
388 attrs.SetValueForArch(arch, this)
389 }
390
391 for os := range PlatformOsMap {
392 this := attrs.GetValueForOS(os)
393 that := other.GetValueForOS(os)
394 this.Append(that)
395 attrs.SetValueForOS(os, this)
396 }
397
398 attrs.Value.Append(other.Value)
399}
400
Jingwen Chen07027912021-03-15 06:02:43 -0400401// HasArchSpecificValues returns true if the attribute contains
402// architecture-specific label_list values.
Jingwen Chenc1c26502021-04-05 10:35:13 +0000403func (attrs LabelListAttribute) HasConfigurableValues() bool {
404 for arch := range PlatformArchMap {
Jingwen Chen91220d72021-03-24 02:18:33 -0400405 if len(attrs.GetValueForArch(arch).Includes) > 0 {
406 return true
407 }
408 }
409
Jingwen Chenc1c26502021-04-05 10:35:13 +0000410 for os := range PlatformOsMap {
Jingwen Chen91220d72021-03-24 02:18:33 -0400411 if len(attrs.GetValueForOS(os).Includes) > 0 {
Jingwen Chen07027912021-03-15 06:02:43 -0400412 return true
413 }
414 }
415 return false
416}
417
Jingwen Chen91220d72021-03-24 02:18:33 -0400418func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList {
419 return map[string]*LabelList{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000420 ARCH_X86: &attrs.ArchValues.X86,
421 ARCH_X86_64: &attrs.ArchValues.X86_64,
422 ARCH_ARM: &attrs.ArchValues.Arm,
423 ARCH_ARM64: &attrs.ArchValues.Arm64,
424 CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
Jingwen Chen91220d72021-03-24 02:18:33 -0400425 }
426}
427
Jingwen Chen07027912021-03-15 06:02:43 -0400428// GetValueForArch returns the label_list attribute value for an architecture.
429func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList {
Jingwen Chen91220d72021-03-24 02:18:33 -0400430 var v *LabelList
431 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen07027912021-03-15 06:02:43 -0400432 panic(fmt.Errorf("Unknown arch: %s", arch))
433 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400434 return *v
Jingwen Chen07027912021-03-15 06:02:43 -0400435}
436
437// SetValueForArch sets the label_list attribute value for an architecture.
438func (attrs *LabelListAttribute) SetValueForArch(arch string, value LabelList) {
Jingwen Chen91220d72021-03-24 02:18:33 -0400439 var v *LabelList
440 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen07027912021-03-15 06:02:43 -0400441 panic(fmt.Errorf("Unknown arch: %s", arch))
442 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400443 *v = value
444}
445
446func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList {
447 return map[string]*LabelList{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000448 OS_ANDROID: &attrs.OsValues.Android,
449 OS_DARWIN: &attrs.OsValues.Darwin,
450 OS_FUCHSIA: &attrs.OsValues.Fuchsia,
451 OS_LINUX: &attrs.OsValues.Linux,
452 OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
453 OS_WINDOWS: &attrs.OsValues.Windows,
454 CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
Jingwen Chen91220d72021-03-24 02:18:33 -0400455 }
456}
457
458// GetValueForOS returns the label_list attribute value for an OS target.
459func (attrs *LabelListAttribute) GetValueForOS(os string) LabelList {
460 var v *LabelList
461 if v = attrs.osValuePtrs()[os]; v == nil {
462 panic(fmt.Errorf("Unknown os: %s", os))
463 }
464 return *v
465}
466
467// SetValueForArch sets the label_list attribute value for an OS target.
468func (attrs *LabelListAttribute) SetValueForOS(os string, value LabelList) {
469 var v *LabelList
470 if v = attrs.osValuePtrs()[os]; v == nil {
471 panic(fmt.Errorf("Unknown os: %s", os))
472 }
473 *v = value
Jingwen Chen07027912021-03-15 06:02:43 -0400474}
475
Jingwen Chen5d864492021-02-24 07:20:12 -0500476// StringListAttribute corresponds to the string_list Bazel attribute type with
477// support for additional metadata, like configurations.
478type StringListAttribute struct {
479 // The base value of the string list attribute.
480 Value []string
481
Jingwen Chenc1c26502021-04-05 10:35:13 +0000482 // The arch-specific attribute string list values. Optional. If used, these
483 // are generated in a select statement and appended to the non-arch specific
484 // label list Value.
Jingwen Chen5d864492021-02-24 07:20:12 -0500485 ArchValues stringListArchValues
Jingwen Chenc1c26502021-04-05 10:35:13 +0000486
487 // The os-specific attribute string list values. Optional. If used, these
488 // are generated in a select statement and appended to the non-os specific
489 // label list Value.
490 OsValues stringListOsValues
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400491
492 // list of product-variable string list values. Optional. if used, each will generate a select
493 // statement appended to the label list Value.
494 ProductValues []ProductVariableValues
Jingwen Chen5d864492021-02-24 07:20:12 -0500495}
496
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000497// MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
498func MakeStringListAttribute(value []string) StringListAttribute {
499 // NOTE: These strings are not necessarily unique or sorted.
500 return StringListAttribute{Value: value}
501}
502
Jingwen Chen5d864492021-02-24 07:20:12 -0500503// Arch-specific string_list typed Bazel attribute values. This should correspond
504// to the types of architectures supported for compilation in arch.go.
505type stringListArchValues struct {
Jingwen Chen07027912021-03-15 06:02:43 -0400506 X86 []string
507 X86_64 []string
508 Arm []string
509 Arm64 []string
Jingwen Chen91220d72021-03-24 02:18:33 -0400510 Common []string
Jingwen Chene32e9e02021-04-23 09:17:24 +0000511
512 ConditionsDefault []string
Jingwen Chen5d864492021-02-24 07:20:12 -0500513}
514
Jingwen Chenc1c26502021-04-05 10:35:13 +0000515type stringListOsValues struct {
516 Android []string
517 Darwin []string
518 Fuchsia []string
519 Linux []string
520 LinuxBionic []string
521 Windows []string
Jingwen Chene32e9e02021-04-23 09:17:24 +0000522
523 ConditionsDefault []string
Jingwen Chenc1c26502021-04-05 10:35:13 +0000524}
525
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400526// Product Variable values for StringListAttribute
527type ProductVariableValues struct {
528 ProductVariable string
529
530 Values []string
531}
532
533// SelectKey returns the appropriate select key for the receiving ProductVariableValues.
534func (p ProductVariableValues) SelectKey() string {
535 return fmt.Sprintf("%s:%s", productVariableBazelPackage, strings.ToLower(p.ProductVariable))
536}
537
Jingwen Chen91220d72021-03-24 02:18:33 -0400538// HasConfigurableValues returns true if the attribute contains
Jingwen Chen5d864492021-02-24 07:20:12 -0500539// architecture-specific string_list values.
Jingwen Chenc1c26502021-04-05 10:35:13 +0000540func (attrs StringListAttribute) HasConfigurableValues() bool {
541 for arch := range PlatformArchMap {
Jingwen Chen5d864492021-02-24 07:20:12 -0500542 if len(attrs.GetValueForArch(arch)) > 0 {
543 return true
544 }
545 }
Jingwen Chenc1c26502021-04-05 10:35:13 +0000546
547 for os := range PlatformOsMap {
548 if len(attrs.GetValueForOS(os)) > 0 {
549 return true
550 }
551 }
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400552
553 return len(attrs.ProductValues) > 0
Jingwen Chen5d864492021-02-24 07:20:12 -0500554}
555
Jingwen Chen91220d72021-03-24 02:18:33 -0400556func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
557 return map[string]*[]string{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000558 ARCH_X86: &attrs.ArchValues.X86,
559 ARCH_X86_64: &attrs.ArchValues.X86_64,
560 ARCH_ARM: &attrs.ArchValues.Arm,
561 ARCH_ARM64: &attrs.ArchValues.Arm64,
562 CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
Jingwen Chen91220d72021-03-24 02:18:33 -0400563 }
564}
565
Jingwen Chen5d864492021-02-24 07:20:12 -0500566// GetValueForArch returns the string_list attribute value for an architecture.
567func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
Jingwen Chen91220d72021-03-24 02:18:33 -0400568 var v *[]string
569 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen5d864492021-02-24 07:20:12 -0500570 panic(fmt.Errorf("Unknown arch: %s", arch))
571 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400572 return *v
Jingwen Chen5d864492021-02-24 07:20:12 -0500573}
574
575// SetValueForArch sets the string_list attribute value for an architecture.
576func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) {
Jingwen Chen91220d72021-03-24 02:18:33 -0400577 var v *[]string
578 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen5d864492021-02-24 07:20:12 -0500579 panic(fmt.Errorf("Unknown arch: %s", arch))
580 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400581 *v = value
Jingwen Chen5d864492021-02-24 07:20:12 -0500582}
Liz Kammera060c452021-03-24 10:14:47 -0400583
Jingwen Chenc1c26502021-04-05 10:35:13 +0000584func (attrs *StringListAttribute) osValuePtrs() map[string]*[]string {
585 return map[string]*[]string{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000586 OS_ANDROID: &attrs.OsValues.Android,
587 OS_DARWIN: &attrs.OsValues.Darwin,
588 OS_FUCHSIA: &attrs.OsValues.Fuchsia,
589 OS_LINUX: &attrs.OsValues.Linux,
590 OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
591 OS_WINDOWS: &attrs.OsValues.Windows,
592 CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
Jingwen Chenc1c26502021-04-05 10:35:13 +0000593 }
594}
595
596// GetValueForOS returns the string_list attribute value for an OS target.
597func (attrs *StringListAttribute) GetValueForOS(os string) []string {
598 var v *[]string
599 if v = attrs.osValuePtrs()[os]; v == nil {
600 panic(fmt.Errorf("Unknown os: %s", os))
601 }
602 return *v
603}
604
605// SetValueForArch sets the string_list attribute value for an OS target.
606func (attrs *StringListAttribute) SetValueForOS(os string, value []string) {
607 var v *[]string
608 if v = attrs.osValuePtrs()[os]; v == nil {
609 panic(fmt.Errorf("Unknown os: %s", os))
610 }
611 *v = value
612}
613
Liz Kammere3e4a5f2021-05-10 11:39:53 -0400614func (attrs *StringListAttribute) SortedProductVariables() []ProductVariableValues {
615 vals := attrs.ProductValues[:]
616 sort.Slice(vals, func(i, j int) bool { return vals[i].ProductVariable < vals[j].ProductVariable })
617 return vals
618}
619
Jingwen Chened9c17d2021-04-13 07:14:55 +0000620// Append appends all values, including os and arch specific ones, from another
621// StringListAttribute to this StringListAttribute
622func (attrs *StringListAttribute) Append(other StringListAttribute) {
623 for arch := range PlatformArchMap {
624 this := attrs.GetValueForArch(arch)
625 that := other.GetValueForArch(arch)
626 this = append(this, that...)
627 attrs.SetValueForArch(arch, this)
628 }
629
630 for os := range PlatformOsMap {
631 this := attrs.GetValueForOS(os)
632 that := other.GetValueForOS(os)
633 this = append(this, that...)
634 attrs.SetValueForOS(os, this)
635 }
636
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400637 productValues := make(map[string][]string, 0)
638 for _, pv := range attrs.ProductValues {
639 productValues[pv.ProductVariable] = pv.Values
640 }
641 for _, pv := range other.ProductValues {
642 productValues[pv.ProductVariable] = append(productValues[pv.ProductVariable], pv.Values...)
643 }
644 attrs.ProductValues = make([]ProductVariableValues, 0, len(productValues))
645 for pv, vals := range productValues {
646 attrs.ProductValues = append(attrs.ProductValues, ProductVariableValues{
647 ProductVariable: pv,
648 Values: vals,
649 })
650 }
651
Jingwen Chened9c17d2021-04-13 07:14:55 +0000652 attrs.Value = append(attrs.Value, other.Value...)
653}
654
Liz Kammera060c452021-03-24 10:14:47 -0400655// TryVariableSubstitution, replace string substitution formatting within each string in slice with
656// Starlark string.format compatible tag for productVariable.
657func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
658 ret := make([]string, 0, len(slice))
659 changesMade := false
660 for _, s := range slice {
661 newS, changed := TryVariableSubstitution(s, productVariable)
662 ret = append(ret, newS)
663 changesMade = changesMade || changed
664 }
665 return ret, changesMade
666}
667
668// TryVariableSubstitution, replace string substitution formatting within s with Starlark
669// string.format compatible tag for productVariable.
670func TryVariableSubstitution(s string, productVariable string) (string, bool) {
671 sub := productVariableSubstitutionPattern.ReplaceAllString(s, "{"+productVariable+"}")
672 return sub, s != sub
673}