properties.go 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339
  1. // 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. package bazel
  15. import (
  16. "fmt"
  17. "path/filepath"
  18. "regexp"
  19. "sort"
  20. "strings"
  21. "github.com/google/blueprint"
  22. )
  23. // BazelTargetModuleProperties contain properties and metadata used for
  24. // Blueprint to BUILD file conversion.
  25. type BazelTargetModuleProperties struct {
  26. // The Bazel rule class for this target.
  27. Rule_class string `blueprint:"mutated"`
  28. // The target label for the bzl file containing the definition of the rule class.
  29. Bzl_load_location string `blueprint:"mutated"`
  30. }
  31. var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)")
  32. // Label is used to represent a Bazel compatible Label. Also stores the original
  33. // bp text to support string replacement.
  34. type Label struct {
  35. // The string representation of a Bazel target label. This can be a relative
  36. // or fully qualified label. These labels are used for generating BUILD
  37. // files with bp2build.
  38. Label string
  39. // The original Soong/Blueprint module name that the label was derived from.
  40. // This is used for replacing references to the original name with the new
  41. // label, for example in genrule cmds.
  42. //
  43. // While there is a reversible 1:1 mapping from the module name to Bazel
  44. // label with bp2build that could make computing the original module name
  45. // from the label automatic, it is not the case for handcrafted targets,
  46. // where modules can have a custom label mapping through the { bazel_module:
  47. // { label: <label> } } property.
  48. //
  49. // With handcrafted labels, those modules don't go through bp2build
  50. // conversion, but relies on handcrafted targets in the source tree.
  51. OriginalModuleName string
  52. }
  53. // LabelList is used to represent a list of Bazel labels.
  54. type LabelList struct {
  55. Includes []Label
  56. Excludes []Label
  57. }
  58. // MakeLabelList creates a LabelList from a list Label
  59. func MakeLabelList(labels []Label) LabelList {
  60. return LabelList{
  61. Includes: labels,
  62. Excludes: nil,
  63. }
  64. }
  65. func (ll *LabelList) Equals(other LabelList) bool {
  66. if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) {
  67. return false
  68. }
  69. for i, _ := range ll.Includes {
  70. if ll.Includes[i] != other.Includes[i] {
  71. return false
  72. }
  73. }
  74. for i, _ := range ll.Excludes {
  75. if ll.Excludes[i] != other.Excludes[i] {
  76. return false
  77. }
  78. }
  79. return true
  80. }
  81. func (ll *LabelList) IsNil() bool {
  82. return ll.Includes == nil && ll.Excludes == nil
  83. }
  84. func (ll *LabelList) IsEmpty() bool {
  85. return len(ll.Includes) == 0 && len(ll.Excludes) == 0
  86. }
  87. func (ll *LabelList) deepCopy() LabelList {
  88. return LabelList{
  89. Includes: ll.Includes[:],
  90. Excludes: ll.Excludes[:],
  91. }
  92. }
  93. // uniqueParentDirectories returns a list of the unique parent directories for
  94. // all files in ll.Includes.
  95. func (ll *LabelList) uniqueParentDirectories() []string {
  96. dirMap := map[string]bool{}
  97. for _, label := range ll.Includes {
  98. dirMap[filepath.Dir(label.Label)] = true
  99. }
  100. dirs := []string{}
  101. for dir := range dirMap {
  102. dirs = append(dirs, dir)
  103. }
  104. return dirs
  105. }
  106. // Add inserts the label Label at the end of the LabelList.Includes.
  107. func (ll *LabelList) Add(label *Label) {
  108. if label == nil {
  109. return
  110. }
  111. ll.Includes = append(ll.Includes, *label)
  112. }
  113. // AddExclude inserts the label Label at the end of the LabelList.Excludes.
  114. func (ll *LabelList) AddExclude(label *Label) {
  115. if label == nil {
  116. return
  117. }
  118. ll.Excludes = append(ll.Excludes, *label)
  119. }
  120. // Append appends the fields of other labelList to the corresponding fields of ll.
  121. func (ll *LabelList) Append(other LabelList) {
  122. if len(ll.Includes) > 0 || len(other.Includes) > 0 {
  123. ll.Includes = append(ll.Includes, other.Includes...)
  124. }
  125. if len(ll.Excludes) > 0 || len(other.Excludes) > 0 {
  126. ll.Excludes = append(other.Excludes, other.Excludes...)
  127. }
  128. }
  129. // Partition splits a LabelList into two LabelLists depending on the return value
  130. // of the predicate.
  131. // This function preserves the Includes and Excludes, but it does not provide
  132. // that information to the partition function.
  133. func (ll *LabelList) Partition(predicate func(label Label) bool) (LabelList, LabelList) {
  134. predicated := LabelList{}
  135. unpredicated := LabelList{}
  136. for _, include := range ll.Includes {
  137. if predicate(include) {
  138. predicated.Add(&include)
  139. } else {
  140. unpredicated.Add(&include)
  141. }
  142. }
  143. for _, exclude := range ll.Excludes {
  144. if predicate(exclude) {
  145. predicated.AddExclude(&exclude)
  146. } else {
  147. unpredicated.AddExclude(&exclude)
  148. }
  149. }
  150. return predicated, unpredicated
  151. }
  152. // UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns
  153. // the slice in a sorted order.
  154. func UniqueSortedBazelLabels(originalLabels []Label) []Label {
  155. uniqueLabelsSet := make(map[Label]bool)
  156. for _, l := range originalLabels {
  157. uniqueLabelsSet[l] = true
  158. }
  159. var uniqueLabels []Label
  160. for l, _ := range uniqueLabelsSet {
  161. uniqueLabels = append(uniqueLabels, l)
  162. }
  163. sort.SliceStable(uniqueLabels, func(i, j int) bool {
  164. return uniqueLabels[i].Label < uniqueLabels[j].Label
  165. })
  166. return uniqueLabels
  167. }
  168. func FirstUniqueBazelLabels(originalLabels []Label) []Label {
  169. var labels []Label
  170. found := make(map[Label]bool, len(originalLabels))
  171. for _, l := range originalLabels {
  172. if _, ok := found[l]; ok {
  173. continue
  174. }
  175. labels = append(labels, l)
  176. found[l] = true
  177. }
  178. return labels
  179. }
  180. func FirstUniqueBazelLabelList(originalLabelList LabelList) LabelList {
  181. var uniqueLabelList LabelList
  182. uniqueLabelList.Includes = FirstUniqueBazelLabels(originalLabelList.Includes)
  183. uniqueLabelList.Excludes = FirstUniqueBazelLabels(originalLabelList.Excludes)
  184. return uniqueLabelList
  185. }
  186. func UniqueSortedBazelLabelList(originalLabelList LabelList) LabelList {
  187. var uniqueLabelList LabelList
  188. uniqueLabelList.Includes = UniqueSortedBazelLabels(originalLabelList.Includes)
  189. uniqueLabelList.Excludes = UniqueSortedBazelLabels(originalLabelList.Excludes)
  190. return uniqueLabelList
  191. }
  192. // Subtract needle from haystack
  193. func SubtractStrings(haystack []string, needle []string) []string {
  194. // This is really a set
  195. needleMap := make(map[string]bool)
  196. for _, s := range needle {
  197. needleMap[s] = true
  198. }
  199. var strings []string
  200. for _, s := range haystack {
  201. if exclude := needleMap[s]; !exclude {
  202. strings = append(strings, s)
  203. }
  204. }
  205. return strings
  206. }
  207. // Subtract needle from haystack
  208. func SubtractBazelLabels(haystack []Label, needle []Label) []Label {
  209. // This is really a set
  210. needleMap := make(map[Label]bool)
  211. for _, s := range needle {
  212. needleMap[s] = true
  213. }
  214. var labels []Label
  215. for _, label := range haystack {
  216. if exclude := needleMap[label]; !exclude {
  217. labels = append(labels, label)
  218. }
  219. }
  220. return labels
  221. }
  222. // Appends two LabelLists, returning the combined list.
  223. func AppendBazelLabelLists(a LabelList, b LabelList) LabelList {
  224. var result LabelList
  225. result.Includes = append(a.Includes, b.Includes...)
  226. result.Excludes = append(a.Excludes, b.Excludes...)
  227. return result
  228. }
  229. // Subtract needle from haystack
  230. func 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. type Attribute interface {
  238. HasConfigurableValues() bool
  239. }
  240. type labelSelectValues map[string]*Label
  241. type configurableLabels map[ConfigurationAxis]labelSelectValues
  242. func (cl configurableLabels) setValueForAxis(axis ConfigurationAxis, config string, value *Label) {
  243. if cl[axis] == nil {
  244. cl[axis] = make(labelSelectValues)
  245. }
  246. cl[axis][config] = value
  247. }
  248. // Represents an attribute whose value is a single label
  249. type LabelAttribute struct {
  250. Value *Label
  251. ConfigurableValues configurableLabels
  252. }
  253. func (la *LabelAttribute) axisTypes() map[configurationType]bool {
  254. types := map[configurationType]bool{}
  255. for k := range la.ConfigurableValues {
  256. if len(la.ConfigurableValues[k]) > 0 {
  257. types[k.configurationType] = true
  258. }
  259. }
  260. return types
  261. }
  262. // Collapse reduces the configurable axes of the label attribute to a single axis.
  263. // This is necessary for final writing to bp2build, as a configurable label
  264. // attribute can only be comprised by a single select.
  265. func (la *LabelAttribute) Collapse() error {
  266. axisTypes := la.axisTypes()
  267. _, containsOs := axisTypes[os]
  268. _, containsArch := axisTypes[arch]
  269. _, containsOsArch := axisTypes[osArch]
  270. _, containsProductVariables := axisTypes[productVariables]
  271. if containsProductVariables {
  272. if containsOs || containsArch || containsOsArch {
  273. if containsArch {
  274. allProductVariablesAreArchVariant := true
  275. for k := range la.ConfigurableValues {
  276. if k.configurationType == productVariables && k.outerAxisType != arch {
  277. allProductVariablesAreArchVariant = false
  278. }
  279. }
  280. if !allProductVariablesAreArchVariant {
  281. return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
  282. }
  283. } else {
  284. return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
  285. }
  286. }
  287. }
  288. if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
  289. // If a bool attribute has both os and arch configuration axes, the only
  290. // way to successfully union their values is to increase the granularity
  291. // of the configuration criteria to os_arch.
  292. for osType, supportedArchs := range osToArchMap {
  293. for _, supportedArch := range supportedArchs {
  294. osArch := osArchString(osType, supportedArch)
  295. if archOsVal := la.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
  296. // Do nothing, as the arch_os is explicitly defined already.
  297. } else {
  298. archVal := la.SelectValue(ArchConfigurationAxis, supportedArch)
  299. osVal := la.SelectValue(OsConfigurationAxis, osType)
  300. if osVal != nil && archVal != nil {
  301. // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
  302. // runs after os mutator.
  303. la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
  304. } else if osVal != nil && archVal == nil {
  305. la.SetSelectValue(OsArchConfigurationAxis, osArch, *osVal)
  306. } else if osVal == nil && archVal != nil {
  307. la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
  308. }
  309. }
  310. }
  311. }
  312. // All os_arch values are now set. Clear os and arch axes.
  313. delete(la.ConfigurableValues, ArchConfigurationAxis)
  314. delete(la.ConfigurableValues, OsConfigurationAxis)
  315. }
  316. return nil
  317. }
  318. // HasConfigurableValues returns whether there are configurable values set for this label.
  319. func (la LabelAttribute) HasConfigurableValues() bool {
  320. for _, selectValues := range la.ConfigurableValues {
  321. if len(selectValues) > 0 {
  322. return true
  323. }
  324. }
  325. return false
  326. }
  327. // SetValue sets the base, non-configured value for the Label
  328. func (la *LabelAttribute) SetValue(value Label) {
  329. la.SetSelectValue(NoConfigAxis, "", value)
  330. }
  331. // SetSelectValue set a value for a bazel select for the given axis, config and value.
  332. func (la *LabelAttribute) SetSelectValue(axis ConfigurationAxis, config string, value Label) {
  333. axis.validateConfig(config)
  334. switch axis.configurationType {
  335. case noConfig:
  336. la.Value = &value
  337. case arch, os, osArch, productVariables, osAndInApex:
  338. if la.ConfigurableValues == nil {
  339. la.ConfigurableValues = make(configurableLabels)
  340. }
  341. la.ConfigurableValues.setValueForAxis(axis, config, &value)
  342. default:
  343. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  344. }
  345. }
  346. // SelectValue gets a value for a bazel select for the given axis and config.
  347. func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) *Label {
  348. axis.validateConfig(config)
  349. switch axis.configurationType {
  350. case noConfig:
  351. return la.Value
  352. case arch, os, osArch, productVariables, osAndInApex:
  353. return la.ConfigurableValues[axis][config]
  354. default:
  355. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  356. }
  357. }
  358. // SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
  359. func (la *LabelAttribute) SortedConfigurationAxes() []ConfigurationAxis {
  360. keys := make([]ConfigurationAxis, 0, len(la.ConfigurableValues))
  361. for k := range la.ConfigurableValues {
  362. keys = append(keys, k)
  363. }
  364. sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
  365. return keys
  366. }
  367. // MakeLabelAttribute turns a string into a LabelAttribute
  368. func MakeLabelAttribute(label string) *LabelAttribute {
  369. return &LabelAttribute{
  370. Value: &Label{
  371. Label: label,
  372. },
  373. }
  374. }
  375. type configToBools map[string]bool
  376. func (ctb configToBools) setValue(config string, value *bool) {
  377. if value == nil {
  378. if _, ok := ctb[config]; ok {
  379. delete(ctb, config)
  380. }
  381. return
  382. }
  383. ctb[config] = *value
  384. }
  385. type configurableBools map[ConfigurationAxis]configToBools
  386. func (cb configurableBools) setValueForAxis(axis ConfigurationAxis, config string, value *bool) {
  387. if cb[axis] == nil {
  388. cb[axis] = make(configToBools)
  389. }
  390. cb[axis].setValue(config, value)
  391. }
  392. // BoolAttribute represents an attribute whose value is a single bool but may be configurable..
  393. type BoolAttribute struct {
  394. Value *bool
  395. ConfigurableValues configurableBools
  396. }
  397. // HasConfigurableValues returns whether there are configurable values for this attribute.
  398. func (ba BoolAttribute) HasConfigurableValues() bool {
  399. for _, cfgToBools := range ba.ConfigurableValues {
  400. if len(cfgToBools) > 0 {
  401. return true
  402. }
  403. }
  404. return false
  405. }
  406. // SetValue sets value for the no config axis
  407. func (ba *BoolAttribute) SetValue(value *bool) {
  408. ba.SetSelectValue(NoConfigAxis, "", value)
  409. }
  410. // SetSelectValue sets value for the given axis/config.
  411. func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, value *bool) {
  412. axis.validateConfig(config)
  413. switch axis.configurationType {
  414. case noConfig:
  415. ba.Value = value
  416. case arch, os, osArch, productVariables, osAndInApex:
  417. if ba.ConfigurableValues == nil {
  418. ba.ConfigurableValues = make(configurableBools)
  419. }
  420. ba.ConfigurableValues.setValueForAxis(axis, config, value)
  421. default:
  422. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  423. }
  424. }
  425. // ToLabelListAttribute creates and returns a LabelListAttribute from this
  426. // bool attribute, where each bool in this attribute corresponds to a
  427. // label list value in the resultant attribute.
  428. func (ba *BoolAttribute) ToLabelListAttribute(falseVal LabelList, trueVal LabelList) (LabelListAttribute, error) {
  429. getLabelList := func(boolPtr *bool) LabelList {
  430. if boolPtr == nil {
  431. return LabelList{nil, nil}
  432. } else if *boolPtr {
  433. return trueVal
  434. } else {
  435. return falseVal
  436. }
  437. }
  438. mainVal := getLabelList(ba.Value)
  439. if !ba.HasConfigurableValues() {
  440. return MakeLabelListAttribute(mainVal), nil
  441. }
  442. result := LabelListAttribute{}
  443. if err := ba.Collapse(); err != nil {
  444. return result, err
  445. }
  446. for axis, configToBools := range ba.ConfigurableValues {
  447. if len(configToBools) < 1 {
  448. continue
  449. }
  450. for config, boolPtr := range configToBools {
  451. val := getLabelList(&boolPtr)
  452. if !val.Equals(mainVal) {
  453. result.SetSelectValue(axis, config, val)
  454. }
  455. }
  456. result.SetSelectValue(axis, ConditionsDefaultConfigKey, mainVal)
  457. }
  458. return result, nil
  459. }
  460. // Collapse reduces the configurable axes of the boolean attribute to a single axis.
  461. // This is necessary for final writing to bp2build, as a configurable boolean
  462. // attribute can only be comprised by a single select.
  463. func (ba *BoolAttribute) Collapse() error {
  464. axisTypes := ba.axisTypes()
  465. _, containsOs := axisTypes[os]
  466. _, containsArch := axisTypes[arch]
  467. _, containsOsArch := axisTypes[osArch]
  468. _, containsProductVariables := axisTypes[productVariables]
  469. if containsProductVariables {
  470. if containsOs || containsArch || containsOsArch {
  471. return fmt.Errorf("boolean attribute could not be collapsed as it has two or more unrelated axes")
  472. }
  473. }
  474. if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
  475. // If a bool attribute has both os and arch configuration axes, the only
  476. // way to successfully union their values is to increase the granularity
  477. // of the configuration criteria to os_arch.
  478. for osType, supportedArchs := range osToArchMap {
  479. for _, supportedArch := range supportedArchs {
  480. osArch := osArchString(osType, supportedArch)
  481. if archOsVal := ba.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
  482. // Do nothing, as the arch_os is explicitly defined already.
  483. } else {
  484. archVal := ba.SelectValue(ArchConfigurationAxis, supportedArch)
  485. osVal := ba.SelectValue(OsConfigurationAxis, osType)
  486. if osVal != nil && archVal != nil {
  487. // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
  488. // runs after os mutator.
  489. ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
  490. } else if osVal != nil && archVal == nil {
  491. ba.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
  492. } else if osVal == nil && archVal != nil {
  493. ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
  494. }
  495. }
  496. }
  497. }
  498. // All os_arch values are now set. Clear os and arch axes.
  499. delete(ba.ConfigurableValues, ArchConfigurationAxis)
  500. delete(ba.ConfigurableValues, OsConfigurationAxis)
  501. // Verify post-condition; this should never fail, provided no additional
  502. // axes are introduced.
  503. if len(ba.ConfigurableValues) > 1 {
  504. panic(fmt.Errorf("error in collapsing attribute: %#v", ba))
  505. }
  506. }
  507. return nil
  508. }
  509. func (ba *BoolAttribute) axisTypes() map[configurationType]bool {
  510. types := map[configurationType]bool{}
  511. for k := range ba.ConfigurableValues {
  512. if len(ba.ConfigurableValues[k]) > 0 {
  513. types[k.configurationType] = true
  514. }
  515. }
  516. return types
  517. }
  518. // SelectValue gets the value for the given axis/config.
  519. func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool {
  520. axis.validateConfig(config)
  521. switch axis.configurationType {
  522. case noConfig:
  523. return ba.Value
  524. case arch, os, osArch, productVariables, osAndInApex:
  525. if v, ok := ba.ConfigurableValues[axis][config]; ok {
  526. return &v
  527. } else {
  528. return nil
  529. }
  530. default:
  531. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  532. }
  533. }
  534. // SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
  535. func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis {
  536. keys := make([]ConfigurationAxis, 0, len(ba.ConfigurableValues))
  537. for k := range ba.ConfigurableValues {
  538. keys = append(keys, k)
  539. }
  540. sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
  541. return keys
  542. }
  543. // labelListSelectValues supports config-specific label_list typed Bazel attribute values.
  544. type labelListSelectValues map[string]LabelList
  545. func (ll labelListSelectValues) addSelects(label labelSelectValues) {
  546. for k, v := range label {
  547. if label == nil {
  548. continue
  549. }
  550. l := ll[k]
  551. (&l).Add(v)
  552. ll[k] = l
  553. }
  554. }
  555. func (ll labelListSelectValues) appendSelects(other labelListSelectValues, forceSpecifyEmptyList bool) {
  556. for k, v := range other {
  557. l := ll[k]
  558. if forceSpecifyEmptyList && l.IsNil() && !v.IsNil() {
  559. l.Includes = []Label{}
  560. }
  561. (&l).Append(v)
  562. ll[k] = l
  563. }
  564. }
  565. // HasConfigurableValues returns whether there are configurable values within this set of selects.
  566. func (ll labelListSelectValues) HasConfigurableValues() bool {
  567. for _, v := range ll {
  568. if v.Includes != nil {
  569. return true
  570. }
  571. }
  572. return false
  573. }
  574. // LabelListAttribute is used to represent a list of Bazel labels as an
  575. // attribute.
  576. type LabelListAttribute struct {
  577. // The non-configured attribute label list Value. Required.
  578. Value LabelList
  579. // The configured attribute label list Values. Optional
  580. // a map of independent configurability axes
  581. ConfigurableValues configurableLabelLists
  582. // If true, differentiate between "nil" and "empty" list. nil means that
  583. // this attribute should not be specified at all, and "empty" means that
  584. // the attribute should be explicitly specified as an empty list.
  585. // This mode facilitates use of attribute defaults: an empty list should
  586. // override the default.
  587. ForceSpecifyEmptyList bool
  588. // If true, signal the intent to the code generator to emit all select keys,
  589. // even if the Includes list for that key is empty. This mode facilitates
  590. // specific select statements where an empty list for a non-default select
  591. // key has a meaning.
  592. EmitEmptyList bool
  593. }
  594. type configurableLabelLists map[ConfigurationAxis]labelListSelectValues
  595. func (cll configurableLabelLists) setValueForAxis(axis ConfigurationAxis, config string, list LabelList) {
  596. if list.IsNil() {
  597. if _, ok := cll[axis][config]; ok {
  598. delete(cll[axis], config)
  599. }
  600. return
  601. }
  602. if cll[axis] == nil {
  603. cll[axis] = make(labelListSelectValues)
  604. }
  605. cll[axis][config] = list
  606. }
  607. func (cll configurableLabelLists) Append(other configurableLabelLists, forceSpecifyEmptyList bool) {
  608. for axis, otherSelects := range other {
  609. selects := cll[axis]
  610. if selects == nil {
  611. selects = make(labelListSelectValues, len(otherSelects))
  612. }
  613. selects.appendSelects(otherSelects, forceSpecifyEmptyList)
  614. cll[axis] = selects
  615. }
  616. }
  617. func (lla *LabelListAttribute) Clone() *LabelListAttribute {
  618. result := &LabelListAttribute{ForceSpecifyEmptyList: lla.ForceSpecifyEmptyList}
  619. return result.Append(*lla)
  620. }
  621. // MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
  622. func MakeLabelListAttribute(value LabelList) LabelListAttribute {
  623. return LabelListAttribute{
  624. Value: value,
  625. ConfigurableValues: make(configurableLabelLists),
  626. }
  627. }
  628. // MakeSingleLabelListAttribute initializes a LabelListAttribute as a non-arch specific list with 1 element, the given Label.
  629. func MakeSingleLabelListAttribute(value Label) LabelListAttribute {
  630. return MakeLabelListAttribute(MakeLabelList([]Label{value}))
  631. }
  632. func (lla *LabelListAttribute) SetValue(list LabelList) {
  633. lla.SetSelectValue(NoConfigAxis, "", list)
  634. }
  635. // SetSelectValue set a value for a bazel select for the given axis, config and value.
  636. func (lla *LabelListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list LabelList) {
  637. axis.validateConfig(config)
  638. switch axis.configurationType {
  639. case noConfig:
  640. lla.Value = list
  641. case arch, os, osArch, productVariables, osAndInApex:
  642. if lla.ConfigurableValues == nil {
  643. lla.ConfigurableValues = make(configurableLabelLists)
  644. }
  645. lla.ConfigurableValues.setValueForAxis(axis, config, list)
  646. default:
  647. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  648. }
  649. }
  650. // SelectValue gets a value for a bazel select for the given axis and config.
  651. func (lla *LabelListAttribute) SelectValue(axis ConfigurationAxis, config string) LabelList {
  652. axis.validateConfig(config)
  653. switch axis.configurationType {
  654. case noConfig:
  655. return lla.Value
  656. case arch, os, osArch, productVariables, osAndInApex:
  657. return lla.ConfigurableValues[axis][config]
  658. default:
  659. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  660. }
  661. }
  662. // SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
  663. func (lla *LabelListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
  664. keys := make([]ConfigurationAxis, 0, len(lla.ConfigurableValues))
  665. for k := range lla.ConfigurableValues {
  666. keys = append(keys, k)
  667. }
  668. sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
  669. return keys
  670. }
  671. // Append all values, including os and arch specific ones, from another
  672. // LabelListAttribute to this LabelListAttribute. Returns this LabelListAttribute.
  673. func (lla *LabelListAttribute) Append(other LabelListAttribute) *LabelListAttribute {
  674. forceSpecifyEmptyList := lla.ForceSpecifyEmptyList || other.ForceSpecifyEmptyList
  675. if forceSpecifyEmptyList && lla.Value.IsNil() && !other.Value.IsNil() {
  676. lla.Value.Includes = []Label{}
  677. }
  678. lla.Value.Append(other.Value)
  679. if lla.ConfigurableValues == nil {
  680. lla.ConfigurableValues = make(configurableLabelLists)
  681. }
  682. lla.ConfigurableValues.Append(other.ConfigurableValues, forceSpecifyEmptyList)
  683. return lla
  684. }
  685. // Add inserts the labels for each axis of LabelAttribute at the end of corresponding axis's
  686. // LabelList within the LabelListAttribute
  687. func (lla *LabelListAttribute) Add(label *LabelAttribute) {
  688. if label == nil {
  689. return
  690. }
  691. lla.Value.Add(label.Value)
  692. if lla.ConfigurableValues == nil && label.ConfigurableValues != nil {
  693. lla.ConfigurableValues = make(configurableLabelLists)
  694. }
  695. for axis, _ := range label.ConfigurableValues {
  696. if _, exists := lla.ConfigurableValues[axis]; !exists {
  697. lla.ConfigurableValues[axis] = make(labelListSelectValues)
  698. }
  699. lla.ConfigurableValues[axis].addSelects(label.ConfigurableValues[axis])
  700. }
  701. }
  702. // HasConfigurableValues returns true if the attribute contains axis-specific label list values.
  703. func (lla LabelListAttribute) HasConfigurableValues() bool {
  704. for _, selectValues := range lla.ConfigurableValues {
  705. if len(selectValues) > 0 {
  706. return true
  707. }
  708. }
  709. return false
  710. }
  711. // IsEmpty returns true if the attribute has no values under any configuration.
  712. func (lla LabelListAttribute) IsEmpty() bool {
  713. if len(lla.Value.Includes) > 0 {
  714. return false
  715. }
  716. for axis, _ := range lla.ConfigurableValues {
  717. if lla.ConfigurableValues[axis].HasConfigurableValues() {
  718. return false
  719. }
  720. }
  721. return true
  722. }
  723. // IsNil returns true if the attribute has not been set for any configuration.
  724. func (lla LabelListAttribute) IsNil() bool {
  725. if lla.Value.Includes != nil {
  726. return false
  727. }
  728. return !lla.HasConfigurableValues()
  729. }
  730. // Exclude for the given axis, config, removes Includes in labelList from Includes and appends them
  731. // to Excludes. This is to special case any excludes that are not specified in a bp file but need to
  732. // be removed, e.g. if they could cause duplicate element failures.
  733. func (lla *LabelListAttribute) Exclude(axis ConfigurationAxis, config string, labelList LabelList) {
  734. val := lla.SelectValue(axis, config)
  735. newList := SubtractBazelLabelList(val, labelList)
  736. newList.Excludes = append(newList.Excludes, labelList.Includes...)
  737. lla.SetSelectValue(axis, config, newList)
  738. }
  739. // ResolveExcludes handles excludes across the various axes, ensuring that items are removed from
  740. // the base value and included in default values as appropriate.
  741. func (lla *LabelListAttribute) ResolveExcludes() {
  742. for axis, configToLabels := range lla.ConfigurableValues {
  743. baseLabels := lla.Value.deepCopy()
  744. for config, val := range configToLabels {
  745. // Exclude config-specific excludes from base value
  746. lla.Value = SubtractBazelLabelList(lla.Value, LabelList{Includes: val.Excludes})
  747. // add base values to config specific to add labels excluded by others in this axis
  748. // then remove all config-specific excludes
  749. allLabels := baseLabels.deepCopy()
  750. allLabels.Append(val)
  751. lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(allLabels, LabelList{Includes: val.Excludes})
  752. }
  753. // After going through all configs, delete the duplicates in the config
  754. // values that are already in the base Value.
  755. for config, val := range configToLabels {
  756. lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(val, lla.Value)
  757. }
  758. // Now that the Value list is finalized for this axis, compare it with
  759. // the original list, and union the difference with the default
  760. // condition for the axis.
  761. difference := SubtractBazelLabelList(baseLabels, lla.Value)
  762. existingDefaults := lla.ConfigurableValues[axis][ConditionsDefaultConfigKey]
  763. existingDefaults.Append(difference)
  764. lla.ConfigurableValues[axis][ConditionsDefaultConfigKey] = FirstUniqueBazelLabelList(existingDefaults)
  765. // if everything ends up without includes, just delete the axis
  766. if !lla.ConfigurableValues[axis].HasConfigurableValues() {
  767. delete(lla.ConfigurableValues, axis)
  768. }
  769. }
  770. }
  771. // Partition splits a LabelListAttribute into two LabelListAttributes depending
  772. // on the return value of the predicate.
  773. // This function preserves the Includes and Excludes, but it does not provide
  774. // that information to the partition function.
  775. func (lla LabelListAttribute) Partition(predicate func(label Label) bool) (LabelListAttribute, LabelListAttribute) {
  776. predicated := LabelListAttribute{}
  777. unpredicated := LabelListAttribute{}
  778. valuePartitionTrue, valuePartitionFalse := lla.Value.Partition(predicate)
  779. predicated.SetValue(valuePartitionTrue)
  780. unpredicated.SetValue(valuePartitionFalse)
  781. for axis, selectValueLabelLists := range lla.ConfigurableValues {
  782. for config, labelList := range selectValueLabelLists {
  783. configPredicated, configUnpredicated := labelList.Partition(predicate)
  784. predicated.SetSelectValue(axis, config, configPredicated)
  785. unpredicated.SetSelectValue(axis, config, configUnpredicated)
  786. }
  787. }
  788. return predicated, unpredicated
  789. }
  790. // OtherModuleContext is a limited context that has methods with information about other modules.
  791. type OtherModuleContext interface {
  792. ModuleFromName(name string) (blueprint.Module, bool)
  793. OtherModuleType(m blueprint.Module) string
  794. OtherModuleName(m blueprint.Module) string
  795. OtherModuleDir(m blueprint.Module) string
  796. ModuleErrorf(fmt string, args ...interface{})
  797. }
  798. // LabelMapper is a function that takes a OtherModuleContext and returns a (potentially changed)
  799. // label and whether it was changed.
  800. type LabelMapper func(OtherModuleContext, Label) (string, bool)
  801. // LabelPartition contains descriptions of a partition for labels
  802. type LabelPartition struct {
  803. // Extensions to include in this partition
  804. Extensions []string
  805. // LabelMapper is a function that can map a label to a new label, and indicate whether to include
  806. // the mapped label in the partition
  807. LabelMapper LabelMapper
  808. // Whether to store files not included in any other partition in a group of LabelPartitions
  809. // Only one partition in a group of LabelPartitions can enabled Keep_remainder
  810. Keep_remainder bool
  811. }
  812. // LabelPartitions is a map of partition name to a LabelPartition describing the elements of the
  813. // partition
  814. type LabelPartitions map[string]LabelPartition
  815. // filter returns a pointer to a label if the label should be included in the partition or nil if
  816. // not.
  817. func (lf LabelPartition) filter(ctx OtherModuleContext, label Label) *Label {
  818. if lf.LabelMapper != nil {
  819. if newLabel, changed := lf.LabelMapper(ctx, label); changed {
  820. return &Label{newLabel, label.OriginalModuleName}
  821. }
  822. }
  823. for _, ext := range lf.Extensions {
  824. if strings.HasSuffix(label.Label, ext) {
  825. return &label
  826. }
  827. }
  828. return nil
  829. }
  830. // PartitionToLabelListAttribute is map of partition name to a LabelListAttribute
  831. type PartitionToLabelListAttribute map[string]LabelListAttribute
  832. type partitionToLabelList map[string]*LabelList
  833. func (p partitionToLabelList) appendIncludes(partition string, label Label) {
  834. if _, ok := p[partition]; !ok {
  835. p[partition] = &LabelList{}
  836. }
  837. p[partition].Includes = append(p[partition].Includes, label)
  838. }
  839. func (p partitionToLabelList) excludes(partition string, excludes []Label) {
  840. if _, ok := p[partition]; !ok {
  841. p[partition] = &LabelList{}
  842. }
  843. p[partition].Excludes = excludes
  844. }
  845. // PartitionLabelListAttribute partitions a LabelListAttribute into the requested partitions
  846. func PartitionLabelListAttribute(ctx OtherModuleContext, lla *LabelListAttribute, partitions LabelPartitions) PartitionToLabelListAttribute {
  847. ret := PartitionToLabelListAttribute{}
  848. var partitionNames []string
  849. // Stored as a pointer to distinguish nil (no remainder partition) from empty string partition
  850. var remainderPartition *string
  851. for p, f := range partitions {
  852. partitionNames = append(partitionNames, p)
  853. if f.Keep_remainder {
  854. if remainderPartition != nil {
  855. panic("only one partition can store the remainder")
  856. }
  857. // If we take the address of p in a loop, we'll end up with the last value of p in
  858. // remainderPartition, we want the requested partition
  859. capturePartition := p
  860. remainderPartition = &capturePartition
  861. }
  862. }
  863. partitionLabelList := func(axis ConfigurationAxis, config string) {
  864. value := lla.SelectValue(axis, config)
  865. partitionToLabels := partitionToLabelList{}
  866. for _, item := range value.Includes {
  867. wasFiltered := false
  868. var inPartition *string
  869. for partition, f := range partitions {
  870. filtered := f.filter(ctx, item)
  871. if filtered == nil {
  872. // did not match this filter, keep looking
  873. continue
  874. }
  875. wasFiltered = true
  876. partitionToLabels.appendIncludes(partition, *filtered)
  877. // don't need to check other partitions if this filter used the item,
  878. // continue checking if mapped to another name
  879. if *filtered == item {
  880. if inPartition != nil {
  881. ctx.ModuleErrorf("%q was found in multiple partitions: %q, %q", item.Label, *inPartition, partition)
  882. }
  883. capturePartition := partition
  884. inPartition = &capturePartition
  885. }
  886. }
  887. // if not specified in a partition, add to remainder partition if one exists
  888. if !wasFiltered && remainderPartition != nil {
  889. partitionToLabels.appendIncludes(*remainderPartition, item)
  890. }
  891. }
  892. // ensure empty lists are maintained
  893. if value.Excludes != nil {
  894. for _, partition := range partitionNames {
  895. partitionToLabels.excludes(partition, value.Excludes)
  896. }
  897. }
  898. for partition, list := range partitionToLabels {
  899. val := ret[partition]
  900. (&val).SetSelectValue(axis, config, *list)
  901. ret[partition] = val
  902. }
  903. }
  904. partitionLabelList(NoConfigAxis, "")
  905. for axis, configToList := range lla.ConfigurableValues {
  906. for config, _ := range configToList {
  907. partitionLabelList(axis, config)
  908. }
  909. }
  910. return ret
  911. }
  912. // StringAttribute corresponds to the string Bazel attribute type with
  913. // support for additional metadata, like configurations.
  914. type StringAttribute struct {
  915. // The base value of the string attribute.
  916. Value *string
  917. // The configured attribute label list Values. Optional
  918. // a map of independent configurability axes
  919. ConfigurableValues configurableStrings
  920. }
  921. type configurableStrings map[ConfigurationAxis]stringSelectValues
  922. func (cs configurableStrings) setValueForAxis(axis ConfigurationAxis, config string, str *string) {
  923. if cs[axis] == nil {
  924. cs[axis] = make(stringSelectValues)
  925. }
  926. var v = ""
  927. if str != nil {
  928. v = *str
  929. }
  930. cs[axis][config] = v
  931. }
  932. type stringSelectValues map[string]string
  933. // HasConfigurableValues returns true if the attribute contains axis-specific string values.
  934. func (sa StringAttribute) HasConfigurableValues() bool {
  935. for _, selectValues := range sa.ConfigurableValues {
  936. if len(selectValues) > 0 {
  937. return true
  938. }
  939. }
  940. return false
  941. }
  942. // SetSelectValue set a value for a bazel select for the given axis, config and value.
  943. func (sa *StringAttribute) SetSelectValue(axis ConfigurationAxis, config string, str *string) {
  944. axis.validateConfig(config)
  945. switch axis.configurationType {
  946. case noConfig:
  947. sa.Value = str
  948. case arch, os, osArch, productVariables:
  949. if sa.ConfigurableValues == nil {
  950. sa.ConfigurableValues = make(configurableStrings)
  951. }
  952. sa.ConfigurableValues.setValueForAxis(axis, config, str)
  953. default:
  954. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  955. }
  956. }
  957. // SelectValue gets a value for a bazel select for the given axis and config.
  958. func (sa *StringAttribute) SelectValue(axis ConfigurationAxis, config string) *string {
  959. axis.validateConfig(config)
  960. switch axis.configurationType {
  961. case noConfig:
  962. return sa.Value
  963. case arch, os, osArch, productVariables:
  964. if v, ok := sa.ConfigurableValues[axis][config]; ok {
  965. return &v
  966. } else {
  967. return nil
  968. }
  969. default:
  970. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  971. }
  972. }
  973. // SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
  974. func (sa *StringAttribute) SortedConfigurationAxes() []ConfigurationAxis {
  975. keys := make([]ConfigurationAxis, 0, len(sa.ConfigurableValues))
  976. for k := range sa.ConfigurableValues {
  977. keys = append(keys, k)
  978. }
  979. sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
  980. return keys
  981. }
  982. // Collapse reduces the configurable axes of the string attribute to a single axis.
  983. // This is necessary for final writing to bp2build, as a configurable string
  984. // attribute can only be comprised by a single select.
  985. func (sa *StringAttribute) Collapse() error {
  986. axisTypes := sa.axisTypes()
  987. _, containsOs := axisTypes[os]
  988. _, containsArch := axisTypes[arch]
  989. _, containsOsArch := axisTypes[osArch]
  990. _, containsProductVariables := axisTypes[productVariables]
  991. if containsProductVariables {
  992. if containsOs || containsArch || containsOsArch {
  993. return fmt.Errorf("boolean attribute could not be collapsed as it has two or more unrelated axes")
  994. }
  995. }
  996. if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
  997. // If a bool attribute has both os and arch configuration axes, the only
  998. // way to successfully union their values is to increase the granularity
  999. // of the configuration criteria to os_arch.
  1000. for osType, supportedArchs := range osToArchMap {
  1001. for _, supportedArch := range supportedArchs {
  1002. osArch := osArchString(osType, supportedArch)
  1003. if archOsVal := sa.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
  1004. // Do nothing, as the arch_os is explicitly defined already.
  1005. } else {
  1006. archVal := sa.SelectValue(ArchConfigurationAxis, supportedArch)
  1007. osVal := sa.SelectValue(OsConfigurationAxis, osType)
  1008. if osVal != nil && archVal != nil {
  1009. // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
  1010. // runs after os mutator.
  1011. sa.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
  1012. } else if osVal != nil && archVal == nil {
  1013. sa.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
  1014. } else if osVal == nil && archVal != nil {
  1015. sa.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
  1016. }
  1017. }
  1018. }
  1019. }
  1020. // All os_arch values are now set. Clear os and arch axes.
  1021. delete(sa.ConfigurableValues, ArchConfigurationAxis)
  1022. delete(sa.ConfigurableValues, OsConfigurationAxis)
  1023. // Verify post-condition; this should never fail, provided no additional
  1024. // axes are introduced.
  1025. if len(sa.ConfigurableValues) > 1 {
  1026. panic(fmt.Errorf("error in collapsing attribute: %#v", sa))
  1027. }
  1028. }
  1029. return nil
  1030. }
  1031. func (sa *StringAttribute) axisTypes() map[configurationType]bool {
  1032. types := map[configurationType]bool{}
  1033. for k := range sa.ConfigurableValues {
  1034. if strs := sa.ConfigurableValues[k]; len(strs) > 0 {
  1035. types[k.configurationType] = true
  1036. }
  1037. }
  1038. return types
  1039. }
  1040. // StringListAttribute corresponds to the string_list Bazel attribute type with
  1041. // support for additional metadata, like configurations.
  1042. type StringListAttribute struct {
  1043. // The base value of the string list attribute.
  1044. Value []string
  1045. // The configured attribute label list Values. Optional
  1046. // a map of independent configurability axes
  1047. ConfigurableValues configurableStringLists
  1048. }
  1049. type configurableStringLists map[ConfigurationAxis]stringListSelectValues
  1050. func (csl configurableStringLists) Append(other configurableStringLists) {
  1051. for axis, otherSelects := range other {
  1052. selects := csl[axis]
  1053. if selects == nil {
  1054. selects = make(stringListSelectValues, len(otherSelects))
  1055. }
  1056. selects.appendSelects(otherSelects)
  1057. csl[axis] = selects
  1058. }
  1059. }
  1060. func (csl configurableStringLists) setValueForAxis(axis ConfigurationAxis, config string, list []string) {
  1061. if csl[axis] == nil {
  1062. csl[axis] = make(stringListSelectValues)
  1063. }
  1064. csl[axis][config] = list
  1065. }
  1066. type stringListSelectValues map[string][]string
  1067. func (sl stringListSelectValues) appendSelects(other stringListSelectValues) {
  1068. for k, v := range other {
  1069. sl[k] = append(sl[k], v...)
  1070. }
  1071. }
  1072. func (sl stringListSelectValues) hasConfigurableValues(other stringListSelectValues) bool {
  1073. for _, val := range sl {
  1074. if len(val) > 0 {
  1075. return true
  1076. }
  1077. }
  1078. return false
  1079. }
  1080. // MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
  1081. func MakeStringListAttribute(value []string) StringListAttribute {
  1082. // NOTE: These strings are not necessarily unique or sorted.
  1083. return StringListAttribute{
  1084. Value: value,
  1085. ConfigurableValues: make(configurableStringLists),
  1086. }
  1087. }
  1088. // HasConfigurableValues returns true if the attribute contains axis-specific string_list values.
  1089. func (sla StringListAttribute) HasConfigurableValues() bool {
  1090. for _, selectValues := range sla.ConfigurableValues {
  1091. if len(selectValues) > 0 {
  1092. return true
  1093. }
  1094. }
  1095. return false
  1096. }
  1097. // Append appends all values, including os and arch specific ones, from another
  1098. // StringListAttribute to this StringListAttribute
  1099. func (sla *StringListAttribute) Append(other StringListAttribute) *StringListAttribute {
  1100. sla.Value = append(sla.Value, other.Value...)
  1101. if sla.ConfigurableValues == nil {
  1102. sla.ConfigurableValues = make(configurableStringLists)
  1103. }
  1104. sla.ConfigurableValues.Append(other.ConfigurableValues)
  1105. return sla
  1106. }
  1107. func (sla *StringListAttribute) Clone() *StringListAttribute {
  1108. result := &StringListAttribute{}
  1109. return result.Append(*sla)
  1110. }
  1111. // SetSelectValue set a value for a bazel select for the given axis, config and value.
  1112. func (sla *StringListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list []string) {
  1113. axis.validateConfig(config)
  1114. switch axis.configurationType {
  1115. case noConfig:
  1116. sla.Value = list
  1117. case arch, os, osArch, productVariables, osAndInApex:
  1118. if sla.ConfigurableValues == nil {
  1119. sla.ConfigurableValues = make(configurableStringLists)
  1120. }
  1121. sla.ConfigurableValues.setValueForAxis(axis, config, list)
  1122. default:
  1123. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  1124. }
  1125. }
  1126. // SelectValue gets a value for a bazel select for the given axis and config.
  1127. func (sla *StringListAttribute) SelectValue(axis ConfigurationAxis, config string) []string {
  1128. axis.validateConfig(config)
  1129. switch axis.configurationType {
  1130. case noConfig:
  1131. return sla.Value
  1132. case arch, os, osArch, productVariables, osAndInApex:
  1133. return sla.ConfigurableValues[axis][config]
  1134. default:
  1135. panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
  1136. }
  1137. }
  1138. // SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
  1139. func (sla *StringListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
  1140. keys := make([]ConfigurationAxis, 0, len(sla.ConfigurableValues))
  1141. for k := range sla.ConfigurableValues {
  1142. keys = append(keys, k)
  1143. }
  1144. sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
  1145. return keys
  1146. }
  1147. // DeduplicateAxesFromBase ensures no duplication of items between the no-configuration value and
  1148. // configuration-specific values. For example, if we would convert this StringListAttribute as:
  1149. //
  1150. // ["a", "b", "c"] + select({
  1151. // "//condition:one": ["a", "d"],
  1152. // "//conditions:default": [],
  1153. // })
  1154. //
  1155. // after this function, we would convert this StringListAttribute as:
  1156. //
  1157. // ["a", "b", "c"] + select({
  1158. // "//condition:one": ["d"],
  1159. // "//conditions:default": [],
  1160. // })
  1161. func (sla *StringListAttribute) DeduplicateAxesFromBase() {
  1162. base := sla.Value
  1163. for axis, configToList := range sla.ConfigurableValues {
  1164. for config, list := range configToList {
  1165. remaining := SubtractStrings(list, base)
  1166. if len(remaining) == 0 {
  1167. delete(sla.ConfigurableValues[axis], config)
  1168. } else {
  1169. sla.ConfigurableValues[axis][config] = remaining
  1170. }
  1171. }
  1172. }
  1173. }
  1174. // TryVariableSubstitution, replace string substitution formatting within each string in slice with
  1175. // Starlark string.format compatible tag for productVariable.
  1176. func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
  1177. ret := make([]string, 0, len(slice))
  1178. changesMade := false
  1179. for _, s := range slice {
  1180. newS, changed := TryVariableSubstitution(s, productVariable)
  1181. ret = append(ret, newS)
  1182. changesMade = changesMade || changed
  1183. }
  1184. return ret, changesMade
  1185. }
  1186. // TryVariableSubstitution, replace string substitution formatting within s with Starlark
  1187. // string.format compatible tag for productVariable.
  1188. func TryVariableSubstitution(s string, productVariable string) (string, bool) {
  1189. sub := productVariableSubstitutionPattern.ReplaceAllString(s, "$("+productVariable+")")
  1190. return sub, s != sub
  1191. }