properties.go 47 KB

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