blob: 8adc9d07f4d1d8ef15e728017ea828dca9e31c96 [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 {
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400163 result.SetOsValueForTarget(os, FilterLabelList(haystack.GetOsValueForTarget(os), needleFn))
164
165 // TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues)
166 for _, arch := range AllArches {
167 result.SetOsArchValueForTarget(os, arch, FilterLabelList(haystack.GetOsArchValueForTarget(os, arch), needleFn))
168 }
Chris Parsons990c4f42021-05-25 12:10:58 -0400169 }
170
171 return result
172}
173
174// Subtract needle from haystack
175func SubtractBazelLabelListAttribute(haystack LabelListAttribute, needle LabelListAttribute) LabelListAttribute {
176 var result LabelListAttribute
177
178 for arch := range PlatformArchMap {
179 result.SetValueForArch(arch,
180 SubtractBazelLabelList(haystack.GetValueForArch(arch), needle.GetValueForArch(arch)))
181 }
182
183 for os := range PlatformOsMap {
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400184 result.SetOsValueForTarget(os, SubtractBazelLabelList(haystack.GetOsValueForTarget(os), needle.GetOsValueForTarget(os)))
185
186 // TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues)
187 for _, arch := range AllArches {
188 result.SetOsArchValueForTarget(os, arch, SubtractBazelLabelList(haystack.GetOsArchValueForTarget(os, arch), needle.GetOsArchValueForTarget(os, arch)))
189 }
Chris Parsons990c4f42021-05-25 12:10:58 -0400190 }
191
192 result.Value = SubtractBazelLabelList(haystack.Value, needle.Value)
193
194 return result
195}
196
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000197// Subtract needle from haystack
198func SubtractBazelLabels(haystack []Label, needle []Label) []Label {
199 // This is really a set
200 remainder := make(map[Label]bool)
201
202 for _, label := range haystack {
203 remainder[label] = true
204 }
205 for _, label := range needle {
206 delete(remainder, label)
207 }
208
209 var labels []Label
210 for label, _ := range remainder {
211 labels = append(labels, label)
212 }
213
214 sort.SliceStable(labels, func(i, j int) bool {
215 return labels[i].Label < labels[j].Label
216 })
217
218 return labels
219}
220
Chris Parsons484e50a2021-05-13 15:13:04 -0400221// Appends two LabelLists, returning the combined list.
222func AppendBazelLabelLists(a LabelList, b LabelList) LabelList {
223 var result LabelList
224 result.Includes = append(a.Includes, b.Includes...)
225 result.Excludes = append(a.Excludes, b.Excludes...)
226 return result
227}
228
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000229// Subtract needle from haystack
230func SubtractBazelLabelList(haystack LabelList, needle LabelList) LabelList {
231 var result LabelList
232 result.Includes = SubtractBazelLabels(haystack.Includes, needle.Includes)
233 // NOTE: Excludes are intentionally not subtracted
234 result.Excludes = haystack.Excludes
235 return result
236}
237
Jingwen Chen07027912021-03-15 06:02:43 -0400238const (
Jingwen Chen91220d72021-03-24 02:18:33 -0400239 // ArchType names in arch.go
Jingwen Chen07027912021-03-15 06:02:43 -0400240 ARCH_ARM = "arm"
241 ARCH_ARM64 = "arm64"
Jingwen Chen91220d72021-03-24 02:18:33 -0400242 ARCH_X86 = "x86"
243 ARCH_X86_64 = "x86_64"
244
245 // OsType names in arch.go
246 OS_ANDROID = "android"
247 OS_DARWIN = "darwin"
248 OS_FUCHSIA = "fuchsia"
249 OS_LINUX = "linux_glibc"
250 OS_LINUX_BIONIC = "linux_bionic"
251 OS_WINDOWS = "windows"
Jingwen Chene32e9e02021-04-23 09:17:24 +0000252
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400253 // Targets in arch.go
254 TARGET_ANDROID_ARM = "android_arm"
255 TARGET_ANDROID_ARM64 = "android_arm64"
256 TARGET_ANDROID_X86 = "android_x86"
257 TARGET_ANDROID_X86_64 = "android_x86_64"
258 TARGET_DARWIN_X86_64 = "darwin_x86_64"
259 TARGET_FUCHSIA_ARM64 = "fuchsia_arm64"
260 TARGET_FUCHSIA_X86_64 = "fuchsia_x86_64"
261 TARGET_LINUX_X86 = "linux_glibc_x86"
262 TARGET_LINUX_x86_64 = "linux_glibc_x86_64"
263 TARGET_LINUX_BIONIC_ARM64 = "linux_bionic_arm64"
264 TARGET_LINUX_BIONIC_X86_64 = "linux_bionic_x86_64"
265 TARGET_WINDOWS_X86 = "windows_x86"
266 TARGET_WINDOWS_X86_64 = "windows_x86_64"
267
Jingwen Chene32e9e02021-04-23 09:17:24 +0000268 // This is the string representation of the default condition wherever a
269 // configurable attribute is used in a select statement, i.e.
270 // //conditions:default for Bazel.
271 //
272 // This is consistently named "conditions_default" to mirror the Soong
273 // config variable default key in an Android.bp file, although there's no
274 // integration with Soong config variables (yet).
275 CONDITIONS_DEFAULT = "conditions_default"
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400276
277 ConditionsDefaultSelectKey = "//conditions:default"
278
279 productVariableBazelPackage = "//build/bazel/product_variables"
Jingwen Chen07027912021-03-15 06:02:43 -0400280)
281
282var (
Jingwen Chenc1c26502021-04-05 10:35:13 +0000283 // These are the list of OSes and architectures with a Bazel config_setting
284 // and constraint value equivalent. These exist in arch.go, but the android
285 // package depends on the bazel package, so a cyclic dependency prevents
286 // using those variables here.
Jingwen Chen91220d72021-03-24 02:18:33 -0400287
288 // A map of architectures to the Bazel label of the constraint_value
289 // for the @platforms//cpu:cpu constraint_setting
290 PlatformArchMap = map[string]string{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000291 ARCH_ARM: "//build/bazel/platforms/arch:arm",
292 ARCH_ARM64: "//build/bazel/platforms/arch:arm64",
293 ARCH_X86: "//build/bazel/platforms/arch:x86",
294 ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400295 CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of as arch select map.
Jingwen Chen91220d72021-03-24 02:18:33 -0400296 }
297
298 // A map of target operating systems to the Bazel label of the
299 // constraint_value for the @platforms//os:os constraint_setting
300 PlatformOsMap = map[string]string{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000301 OS_ANDROID: "//build/bazel/platforms/os:android",
302 OS_DARWIN: "//build/bazel/platforms/os:darwin",
303 OS_FUCHSIA: "//build/bazel/platforms/os:fuchsia",
304 OS_LINUX: "//build/bazel/platforms/os:linux",
305 OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
306 OS_WINDOWS: "//build/bazel/platforms/os:windows",
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400307 CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of an os select map.
Jingwen Chen91220d72021-03-24 02:18:33 -0400308 }
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400309
310 PlatformTargetMap = map[string]string{
311 TARGET_ANDROID_ARM: "//build/bazel/platforms:android_arm",
312 TARGET_ANDROID_ARM64: "//build/bazel/platforms:android_arm64",
313 TARGET_ANDROID_X86: "//build/bazel/platforms:android_x86",
314 TARGET_ANDROID_X86_64: "//build/bazel/platforms:android_x86_64",
315 TARGET_DARWIN_X86_64: "//build/bazel/platforms:darwin_x86_64",
316 TARGET_FUCHSIA_ARM64: "//build/bazel/platforms:fuchsia_arm64",
317 TARGET_FUCHSIA_X86_64: "//build/bazel/platforms:fuchsia_x86_64",
318 TARGET_LINUX_X86: "//build/bazel/platforms:linux_glibc_x86",
319 TARGET_LINUX_x86_64: "//build/bazel/platforms:linux_glibc_x86_64",
320 TARGET_LINUX_BIONIC_ARM64: "//build/bazel/platforms:linux_bionic_arm64",
321 TARGET_LINUX_BIONIC_X86_64: "//build/bazel/platforms:linux_bionic_x86_64",
322 TARGET_WINDOWS_X86: "//build/bazel/platforms:windows_x86",
323 TARGET_WINDOWS_X86_64: "//build/bazel/platforms:windows_x86_64",
324 CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of an os select map.
325 }
326
327 // TODO(b/187530594): Should we add CONDITIONS_DEFAULT here?
328 AllArches = []string{ARCH_ARM, ARCH_ARM64, ARCH_X86, ARCH_X86_64}
Jingwen Chen07027912021-03-15 06:02:43 -0400329)
330
Jingwen Chenc1c26502021-04-05 10:35:13 +0000331type Attribute interface {
332 HasConfigurableValues() bool
333}
334
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200335// Represents an attribute whose value is a single label
336type LabelAttribute struct {
Lukacs T. Berki598dd002021-05-05 09:00:01 +0200337 Value Label
338 X86 Label
339 X86_64 Label
340 Arm Label
341 Arm64 Label
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200342}
343
Lukacs T. Berki598dd002021-05-05 09:00:01 +0200344func (attr *LabelAttribute) GetValueForArch(arch string) Label {
345 switch arch {
346 case ARCH_ARM:
347 return attr.Arm
348 case ARCH_ARM64:
349 return attr.Arm64
350 case ARCH_X86:
351 return attr.X86
352 case ARCH_X86_64:
353 return attr.X86_64
354 case CONDITIONS_DEFAULT:
355 return attr.Value
356 default:
357 panic("Invalid arch type")
358 }
359}
360
361func (attr *LabelAttribute) SetValueForArch(arch string, value Label) {
362 switch arch {
363 case ARCH_ARM:
364 attr.Arm = value
365 case ARCH_ARM64:
366 attr.Arm64 = value
367 case ARCH_X86:
368 attr.X86 = value
369 case ARCH_X86_64:
370 attr.X86_64 = value
371 default:
372 panic("Invalid arch type")
373 }
374}
375
376func (attr LabelAttribute) HasConfigurableValues() bool {
377 return attr.Arm.Label != "" || attr.Arm64.Label != "" || attr.X86.Label != "" || attr.X86_64.Label != ""
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200378}
379
Jingwen Chen07027912021-03-15 06:02:43 -0400380// Arch-specific label_list typed Bazel attribute values. This should correspond
381// to the types of architectures supported for compilation in arch.go.
382type labelListArchValues struct {
383 X86 LabelList
384 X86_64 LabelList
385 Arm LabelList
386 Arm64 LabelList
Jingwen Chen91220d72021-03-24 02:18:33 -0400387 Common LabelList
Jingwen Chene32e9e02021-04-23 09:17:24 +0000388
389 ConditionsDefault LabelList
Jingwen Chen91220d72021-03-24 02:18:33 -0400390}
391
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400392type labelListTargetValue struct {
393 // E.g. for android
394 OsValue LabelList
Jingwen Chene32e9e02021-04-23 09:17:24 +0000395
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400396 // E.g. for android_arm, android_arm64, ...
397 ArchValues labelListArchValues
398}
399
400func (target *labelListTargetValue) Append(other labelListTargetValue) {
401 target.OsValue.Append(other.OsValue)
402 target.ArchValues.X86.Append(other.ArchValues.X86)
403 target.ArchValues.X86_64.Append(other.ArchValues.X86_64)
404 target.ArchValues.Arm.Append(other.ArchValues.Arm)
405 target.ArchValues.Arm64.Append(other.ArchValues.Arm64)
406 target.ArchValues.ConditionsDefault.Append(other.ArchValues.ConditionsDefault)
407}
408
409type labelListTargetValues struct {
410 Android labelListTargetValue
411 Darwin labelListTargetValue
412 Fuchsia labelListTargetValue
413 Linux labelListTargetValue
414 LinuxBionic labelListTargetValue
415 Windows labelListTargetValue
416
417 ConditionsDefault labelListTargetValue
Jingwen Chen07027912021-03-15 06:02:43 -0400418}
419
420// LabelListAttribute is used to represent a list of Bazel labels as an
421// attribute.
422type LabelListAttribute struct {
423 // The non-arch specific attribute label list Value. Required.
424 Value LabelList
425
426 // The arch-specific attribute label list values. Optional. If used, these
427 // are generated in a select statement and appended to the non-arch specific
428 // label list Value.
429 ArchValues labelListArchValues
Jingwen Chen91220d72021-03-24 02:18:33 -0400430
431 // The os-specific attribute label list values. Optional. If used, these
432 // are generated in a select statement and appended to the non-os specific
433 // label list Value.
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400434 TargetValues labelListTargetValues
Jingwen Chen07027912021-03-15 06:02:43 -0400435}
436
437// MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
438func MakeLabelListAttribute(value LabelList) LabelListAttribute {
439 return LabelListAttribute{Value: UniqueBazelLabelList(value)}
440}
441
Jingwen Chened9c17d2021-04-13 07:14:55 +0000442// Append all values, including os and arch specific ones, from another
Jingwen Chen63930982021-03-24 10:04:33 -0400443// LabelListAttribute to this LabelListAttribute.
444func (attrs *LabelListAttribute) Append(other LabelListAttribute) {
445 for arch := range PlatformArchMap {
446 this := attrs.GetValueForArch(arch)
447 that := other.GetValueForArch(arch)
448 this.Append(that)
449 attrs.SetValueForArch(arch, this)
450 }
451
452 for os := range PlatformOsMap {
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400453 this := attrs.getValueForTarget(os)
454 that := other.getValueForTarget(os)
Jingwen Chen63930982021-03-24 10:04:33 -0400455 this.Append(that)
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400456 attrs.setValueForTarget(os, this)
Jingwen Chen63930982021-03-24 10:04:33 -0400457 }
458
459 attrs.Value.Append(other.Value)
460}
461
Jingwen Chen07027912021-03-15 06:02:43 -0400462// HasArchSpecificValues returns true if the attribute contains
463// architecture-specific label_list values.
Jingwen Chenc1c26502021-04-05 10:35:13 +0000464func (attrs LabelListAttribute) HasConfigurableValues() bool {
465 for arch := range PlatformArchMap {
Jingwen Chen91220d72021-03-24 02:18:33 -0400466 if len(attrs.GetValueForArch(arch).Includes) > 0 {
467 return true
468 }
469 }
470
Jingwen Chenc1c26502021-04-05 10:35:13 +0000471 for os := range PlatformOsMap {
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400472 if len(attrs.GetOsValueForTarget(os).Includes) > 0 {
Jingwen Chen07027912021-03-15 06:02:43 -0400473 return true
474 }
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400475 // TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT (not in AllArches)
476 for _, arch := range AllArches {
477 if len(attrs.GetOsArchValueForTarget(os, arch).Includes) > 0 {
478 return true
479 }
480 }
Jingwen Chen07027912021-03-15 06:02:43 -0400481 }
482 return false
483}
484
Jingwen Chen91220d72021-03-24 02:18:33 -0400485func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList {
486 return map[string]*LabelList{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000487 ARCH_X86: &attrs.ArchValues.X86,
488 ARCH_X86_64: &attrs.ArchValues.X86_64,
489 ARCH_ARM: &attrs.ArchValues.Arm,
490 ARCH_ARM64: &attrs.ArchValues.Arm64,
491 CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
Jingwen Chen91220d72021-03-24 02:18:33 -0400492 }
493}
494
Jingwen Chen07027912021-03-15 06:02:43 -0400495// GetValueForArch returns the label_list attribute value for an architecture.
496func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList {
Jingwen Chen91220d72021-03-24 02:18:33 -0400497 var v *LabelList
498 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen07027912021-03-15 06:02:43 -0400499 panic(fmt.Errorf("Unknown arch: %s", arch))
500 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400501 return *v
Jingwen Chen07027912021-03-15 06:02:43 -0400502}
503
504// SetValueForArch sets the label_list attribute value for an architecture.
505func (attrs *LabelListAttribute) SetValueForArch(arch string, value LabelList) {
Jingwen Chen91220d72021-03-24 02:18:33 -0400506 var v *LabelList
507 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen07027912021-03-15 06:02:43 -0400508 panic(fmt.Errorf("Unknown arch: %s", arch))
509 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400510 *v = value
511}
512
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400513func (attrs *LabelListAttribute) targetValuePtrs() map[string]*labelListTargetValue {
514 return map[string]*labelListTargetValue{
515 OS_ANDROID: &attrs.TargetValues.Android,
516 OS_DARWIN: &attrs.TargetValues.Darwin,
517 OS_FUCHSIA: &attrs.TargetValues.Fuchsia,
518 OS_LINUX: &attrs.TargetValues.Linux,
519 OS_LINUX_BIONIC: &attrs.TargetValues.LinuxBionic,
520 OS_WINDOWS: &attrs.TargetValues.Windows,
521 CONDITIONS_DEFAULT: &attrs.TargetValues.ConditionsDefault,
Jingwen Chen91220d72021-03-24 02:18:33 -0400522 }
523}
524
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400525func (attrs *LabelListAttribute) getValueForTarget(os string) labelListTargetValue {
526 var v *labelListTargetValue
527 if v = attrs.targetValuePtrs()[os]; v == nil {
Jingwen Chen91220d72021-03-24 02:18:33 -0400528 panic(fmt.Errorf("Unknown os: %s", os))
529 }
530 return *v
531}
532
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400533func (attrs *LabelListAttribute) GetOsValueForTarget(os string) LabelList {
534 var v *labelListTargetValue
535 if v = attrs.targetValuePtrs()[os]; v == nil {
536 panic(fmt.Errorf("Unknown os: %s", os))
537 }
538 return v.OsValue
539}
540
541func (attrs *LabelListAttribute) GetOsArchValueForTarget(os string, arch string) LabelList {
542 var v *labelListTargetValue
543 if v = attrs.targetValuePtrs()[os]; v == nil {
544 panic(fmt.Errorf("Unknown os: %s", os))
545 }
546 switch arch {
547 case ARCH_X86:
548 return v.ArchValues.X86
549 case ARCH_X86_64:
550 return v.ArchValues.X86_64
551 case ARCH_ARM:
552 return v.ArchValues.Arm
553 case ARCH_ARM64:
554 return v.ArchValues.Arm64
555 case CONDITIONS_DEFAULT:
556 return v.ArchValues.ConditionsDefault
557 default:
558 panic(fmt.Errorf("Unknown arch: %s\n", arch))
559 }
560}
561
562func (attrs *LabelListAttribute) setValueForTarget(os string, value labelListTargetValue) {
563 var v *labelListTargetValue
564 if v = attrs.targetValuePtrs()[os]; v == nil {
Jingwen Chen91220d72021-03-24 02:18:33 -0400565 panic(fmt.Errorf("Unknown os: %s", os))
566 }
567 *v = value
Jingwen Chen07027912021-03-15 06:02:43 -0400568}
569
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400570func (attrs *LabelListAttribute) SetOsValueForTarget(os string, value LabelList) {
571 var v *labelListTargetValue
572 if v = attrs.targetValuePtrs()[os]; v == nil {
573 panic(fmt.Errorf("Unknown os: %s", os))
574 }
575 v.OsValue = value
576}
577
578func (attrs *LabelListAttribute) SetOsArchValueForTarget(os string, arch string, value LabelList) {
579 var v *labelListTargetValue
580 if v = attrs.targetValuePtrs()[os]; v == nil {
581 panic(fmt.Errorf("Unknown os: %s", os))
582 }
583 switch arch {
584 case ARCH_X86:
585 v.ArchValues.X86 = value
586 case ARCH_X86_64:
587 v.ArchValues.X86_64 = value
588 case ARCH_ARM:
589 v.ArchValues.Arm = value
590 case ARCH_ARM64:
591 v.ArchValues.Arm64 = value
592 case CONDITIONS_DEFAULT:
593 v.ArchValues.ConditionsDefault = value
594 default:
595 panic(fmt.Errorf("Unknown arch: %s\n", arch))
596 }
597}
598
Jingwen Chen5d864492021-02-24 07:20:12 -0500599// StringListAttribute corresponds to the string_list Bazel attribute type with
600// support for additional metadata, like configurations.
601type StringListAttribute struct {
602 // The base value of the string list attribute.
603 Value []string
604
Jingwen Chenc1c26502021-04-05 10:35:13 +0000605 // The arch-specific attribute string list values. Optional. If used, these
606 // are generated in a select statement and appended to the non-arch specific
607 // label list Value.
Jingwen Chen5d864492021-02-24 07:20:12 -0500608 ArchValues stringListArchValues
Jingwen Chenc1c26502021-04-05 10:35:13 +0000609
610 // The os-specific attribute string list values. Optional. If used, these
611 // are generated in a select statement and appended to the non-os specific
612 // label list Value.
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400613 TargetValues stringListTargetValues
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400614
615 // list of product-variable string list values. Optional. if used, each will generate a select
616 // statement appended to the label list Value.
617 ProductValues []ProductVariableValues
Jingwen Chen5d864492021-02-24 07:20:12 -0500618}
619
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000620// MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
621func MakeStringListAttribute(value []string) StringListAttribute {
622 // NOTE: These strings are not necessarily unique or sorted.
623 return StringListAttribute{Value: value}
624}
625
Jingwen Chen5d864492021-02-24 07:20:12 -0500626// Arch-specific string_list typed Bazel attribute values. This should correspond
627// to the types of architectures supported for compilation in arch.go.
628type stringListArchValues struct {
Jingwen Chen07027912021-03-15 06:02:43 -0400629 X86 []string
630 X86_64 []string
631 Arm []string
632 Arm64 []string
Jingwen Chen91220d72021-03-24 02:18:33 -0400633 Common []string
Jingwen Chene32e9e02021-04-23 09:17:24 +0000634
635 ConditionsDefault []string
Jingwen Chen5d864492021-02-24 07:20:12 -0500636}
637
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400638type stringListTargetValue struct {
639 // E.g. for android
640 OsValue []string
Jingwen Chene32e9e02021-04-23 09:17:24 +0000641
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400642 // E.g. for android_arm, android_arm64, ...
643 ArchValues stringListArchValues
644}
645
646func (target *stringListTargetValue) Append(other stringListTargetValue) {
647 target.OsValue = append(target.OsValue, other.OsValue...)
648 target.ArchValues.X86 = append(target.ArchValues.X86, other.ArchValues.X86...)
649 target.ArchValues.X86_64 = append(target.ArchValues.X86_64, other.ArchValues.X86_64...)
650 target.ArchValues.Arm = append(target.ArchValues.Arm, other.ArchValues.Arm...)
651 target.ArchValues.Arm64 = append(target.ArchValues.Arm64, other.ArchValues.Arm64...)
652 target.ArchValues.ConditionsDefault = append(target.ArchValues.ConditionsDefault, other.ArchValues.ConditionsDefault...)
653}
654
655type stringListTargetValues struct {
656 Android stringListTargetValue
657 Darwin stringListTargetValue
658 Fuchsia stringListTargetValue
659 Linux stringListTargetValue
660 LinuxBionic stringListTargetValue
661 Windows stringListTargetValue
662
663 ConditionsDefault stringListTargetValue
Jingwen Chenc1c26502021-04-05 10:35:13 +0000664}
665
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400666// Product Variable values for StringListAttribute
667type ProductVariableValues struct {
668 ProductVariable string
669
670 Values []string
671}
672
673// SelectKey returns the appropriate select key for the receiving ProductVariableValues.
674func (p ProductVariableValues) SelectKey() string {
675 return fmt.Sprintf("%s:%s", productVariableBazelPackage, strings.ToLower(p.ProductVariable))
676}
677
Jingwen Chen91220d72021-03-24 02:18:33 -0400678// HasConfigurableValues returns true if the attribute contains
Jingwen Chen5d864492021-02-24 07:20:12 -0500679// architecture-specific string_list values.
Jingwen Chenc1c26502021-04-05 10:35:13 +0000680func (attrs StringListAttribute) HasConfigurableValues() bool {
681 for arch := range PlatformArchMap {
Jingwen Chen5d864492021-02-24 07:20:12 -0500682 if len(attrs.GetValueForArch(arch)) > 0 {
683 return true
684 }
685 }
Jingwen Chenc1c26502021-04-05 10:35:13 +0000686
687 for os := range PlatformOsMap {
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400688 if len(attrs.GetOsValueForTarget(os)) > 0 {
Jingwen Chenc1c26502021-04-05 10:35:13 +0000689 return true
690 }
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400691 // TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT? (Not in AllArches)
692 for _, arch := range AllArches {
693 if len(attrs.GetOsArchValueForTarget(os, arch)) > 0 {
694 return true
695 }
696
697 }
Jingwen Chenc1c26502021-04-05 10:35:13 +0000698 }
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400699
700 return len(attrs.ProductValues) > 0
Jingwen Chen5d864492021-02-24 07:20:12 -0500701}
702
Jingwen Chen91220d72021-03-24 02:18:33 -0400703func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
704 return map[string]*[]string{
Jingwen Chene32e9e02021-04-23 09:17:24 +0000705 ARCH_X86: &attrs.ArchValues.X86,
706 ARCH_X86_64: &attrs.ArchValues.X86_64,
707 ARCH_ARM: &attrs.ArchValues.Arm,
708 ARCH_ARM64: &attrs.ArchValues.Arm64,
709 CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
Jingwen Chen91220d72021-03-24 02:18:33 -0400710 }
711}
712
Jingwen Chen5d864492021-02-24 07:20:12 -0500713// GetValueForArch returns the string_list attribute value for an architecture.
714func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
Jingwen Chen91220d72021-03-24 02:18:33 -0400715 var v *[]string
716 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen5d864492021-02-24 07:20:12 -0500717 panic(fmt.Errorf("Unknown arch: %s", arch))
718 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400719 return *v
Jingwen Chen5d864492021-02-24 07:20:12 -0500720}
721
722// SetValueForArch sets the string_list attribute value for an architecture.
723func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) {
Jingwen Chen91220d72021-03-24 02:18:33 -0400724 var v *[]string
725 if v = attrs.archValuePtrs()[arch]; v == nil {
Jingwen Chen5d864492021-02-24 07:20:12 -0500726 panic(fmt.Errorf("Unknown arch: %s", arch))
727 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400728 *v = value
Jingwen Chen5d864492021-02-24 07:20:12 -0500729}
Liz Kammera060c452021-03-24 10:14:47 -0400730
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400731func (attrs *StringListAttribute) targetValuePtrs() map[string]*stringListTargetValue {
732 return map[string]*stringListTargetValue{
733 OS_ANDROID: &attrs.TargetValues.Android,
734 OS_DARWIN: &attrs.TargetValues.Darwin,
735 OS_FUCHSIA: &attrs.TargetValues.Fuchsia,
736 OS_LINUX: &attrs.TargetValues.Linux,
737 OS_LINUX_BIONIC: &attrs.TargetValues.LinuxBionic,
738 OS_WINDOWS: &attrs.TargetValues.Windows,
739 CONDITIONS_DEFAULT: &attrs.TargetValues.ConditionsDefault,
Jingwen Chenc1c26502021-04-05 10:35:13 +0000740 }
741}
742
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400743func (attrs *StringListAttribute) getValueForTarget(os string) stringListTargetValue {
744 var v *stringListTargetValue
745 if v = attrs.targetValuePtrs()[os]; v == nil {
Jingwen Chenc1c26502021-04-05 10:35:13 +0000746 panic(fmt.Errorf("Unknown os: %s", os))
747 }
748 return *v
749}
750
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400751func (attrs *StringListAttribute) GetOsValueForTarget(os string) []string {
752 var v *stringListTargetValue
753 if v = attrs.targetValuePtrs()[os]; v == nil {
754 panic(fmt.Errorf("Unknown os: %s", os))
755 }
756 return v.OsValue
757}
758
759func (attrs *StringListAttribute) GetOsArchValueForTarget(os string, arch string) []string {
760 var v *stringListTargetValue
761 if v = attrs.targetValuePtrs()[os]; v == nil {
762 panic(fmt.Errorf("Unknown os: %s", os))
763 }
764 switch arch {
765 case ARCH_X86:
766 return v.ArchValues.X86
767 case ARCH_X86_64:
768 return v.ArchValues.X86_64
769 case ARCH_ARM:
770 return v.ArchValues.Arm
771 case ARCH_ARM64:
772 return v.ArchValues.Arm64
773 case CONDITIONS_DEFAULT:
774 return v.ArchValues.ConditionsDefault
775 default:
776 panic(fmt.Errorf("Unknown arch: %s\n", arch))
777 }
778}
779
780func (attrs *StringListAttribute) setValueForTarget(os string, value stringListTargetValue) {
781 var v *stringListTargetValue
782 if v = attrs.targetValuePtrs()[os]; v == nil {
Jingwen Chenc1c26502021-04-05 10:35:13 +0000783 panic(fmt.Errorf("Unknown os: %s", os))
784 }
785 *v = value
786}
787
Liz Kammere3e4a5f2021-05-10 11:39:53 -0400788func (attrs *StringListAttribute) SortedProductVariables() []ProductVariableValues {
789 vals := attrs.ProductValues[:]
790 sort.Slice(vals, func(i, j int) bool { return vals[i].ProductVariable < vals[j].ProductVariable })
791 return vals
792}
793
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400794func (attrs *StringListAttribute) SetOsValueForTarget(os string, value []string) {
795 var v *stringListTargetValue
796 if v = attrs.targetValuePtrs()[os]; v == nil {
797 panic(fmt.Errorf("Unknown os: %s", os))
798 }
799 v.OsValue = value
800}
801
802func (attrs *StringListAttribute) SetOsArchValueForTarget(os string, arch string, value []string) {
803 var v *stringListTargetValue
804 if v = attrs.targetValuePtrs()[os]; v == nil {
805 panic(fmt.Errorf("Unknown os: %s", os))
806 }
807 switch arch {
808 case ARCH_X86:
809 v.ArchValues.X86 = value
810 case ARCH_X86_64:
811 v.ArchValues.X86_64 = value
812 case ARCH_ARM:
813 v.ArchValues.Arm = value
814 case ARCH_ARM64:
815 v.ArchValues.Arm64 = value
816 case CONDITIONS_DEFAULT:
817 v.ArchValues.ConditionsDefault = value
818 default:
819 panic(fmt.Errorf("Unknown arch: %s\n", arch))
820 }
821}
822
Jingwen Chened9c17d2021-04-13 07:14:55 +0000823// Append appends all values, including os and arch specific ones, from another
824// StringListAttribute to this StringListAttribute
825func (attrs *StringListAttribute) Append(other StringListAttribute) {
826 for arch := range PlatformArchMap {
827 this := attrs.GetValueForArch(arch)
828 that := other.GetValueForArch(arch)
829 this = append(this, that...)
830 attrs.SetValueForArch(arch, this)
831 }
832
833 for os := range PlatformOsMap {
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400834 this := attrs.getValueForTarget(os)
835 that := other.getValueForTarget(os)
836 this.Append(that)
837 attrs.setValueForTarget(os, this)
Jingwen Chened9c17d2021-04-13 07:14:55 +0000838 }
839
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400840 productValues := make(map[string][]string, 0)
841 for _, pv := range attrs.ProductValues {
842 productValues[pv.ProductVariable] = pv.Values
843 }
844 for _, pv := range other.ProductValues {
845 productValues[pv.ProductVariable] = append(productValues[pv.ProductVariable], pv.Values...)
846 }
847 attrs.ProductValues = make([]ProductVariableValues, 0, len(productValues))
848 for pv, vals := range productValues {
849 attrs.ProductValues = append(attrs.ProductValues, ProductVariableValues{
850 ProductVariable: pv,
851 Values: vals,
852 })
853 }
854
Jingwen Chened9c17d2021-04-13 07:14:55 +0000855 attrs.Value = append(attrs.Value, other.Value...)
856}
857
Liz Kammera060c452021-03-24 10:14:47 -0400858// TryVariableSubstitution, replace string substitution formatting within each string in slice with
859// Starlark string.format compatible tag for productVariable.
860func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
861 ret := make([]string, 0, len(slice))
862 changesMade := false
863 for _, s := range slice {
864 newS, changed := TryVariableSubstitution(s, productVariable)
865 ret = append(ret, newS)
866 changesMade = changesMade || changed
867 }
868 return ret, changesMade
869}
870
871// TryVariableSubstitution, replace string substitution formatting within s with Starlark
872// string.format compatible tag for productVariable.
873func TryVariableSubstitution(s string, productVariable string) (string, bool) {
874 sub := productVariableSubstitutionPattern.ReplaceAllString(s, "{"+productVariable+"}")
875 return sub, s != sub
876}