testing.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. // Copyright 2021 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 bp2build
  15. /*
  16. For shareable/common bp2build testing functionality and dumping ground for
  17. specific-but-shared functionality among tests in package
  18. */
  19. import (
  20. "fmt"
  21. "sort"
  22. "strings"
  23. "testing"
  24. "github.com/google/blueprint/proptools"
  25. "android/soong/android"
  26. "android/soong/android/allowlists"
  27. "android/soong/bazel"
  28. )
  29. var (
  30. buildDir string
  31. )
  32. func checkError(t *testing.T, errs []error, expectedErr error) bool {
  33. t.Helper()
  34. if len(errs) != 1 {
  35. return false
  36. }
  37. if strings.Contains(errs[0].Error(), expectedErr.Error()) {
  38. return true
  39. }
  40. return false
  41. }
  42. func errored(t *testing.T, tc Bp2buildTestCase, errs []error) bool {
  43. t.Helper()
  44. if tc.ExpectedErr != nil {
  45. // Rely on checkErrors, as this test case is expected to have an error.
  46. return false
  47. }
  48. if len(errs) > 0 {
  49. for _, err := range errs {
  50. t.Errorf("%s: %s", tc.Description, err)
  51. }
  52. return true
  53. }
  54. // All good, continue execution.
  55. return false
  56. }
  57. func RunBp2BuildTestCaseSimple(t *testing.T, tc Bp2buildTestCase) {
  58. t.Helper()
  59. RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
  60. }
  61. type Bp2buildTestCase struct {
  62. Description string
  63. ModuleTypeUnderTest string
  64. ModuleTypeUnderTestFactory android.ModuleFactory
  65. // Text to add to the toplevel, root Android.bp file. If Dir is not set, all
  66. // ExpectedBazelTargets are assumed to be generated by this file.
  67. Blueprint string
  68. // ExpectedBazelTargets compares the BazelTargets generated in `Dir` (if not empty).
  69. // Otherwise, it checks the BazelTargets generated by `Blueprint` in the root directory.
  70. ExpectedBazelTargets []string
  71. Filesystem map[string]string
  72. // Dir sets the directory which will be compared against the targets in ExpectedBazelTargets.
  73. // This should used in conjunction with the Filesystem property to check for targets
  74. // generated from a directory that is not the root.
  75. // If not set, all ExpectedBazelTargets are assumed to be generated by the text in the
  76. // Blueprint property.
  77. Dir string
  78. // An error with a string contained within the string of the expected error
  79. ExpectedErr error
  80. UnconvertedDepsMode unconvertedDepsMode
  81. // For every directory listed here, the BUILD file for that directory will
  82. // be merged with the generated BUILD file. This allows custom BUILD targets
  83. // to be used in tests, or use BUILD files to draw package boundaries.
  84. KeepBuildFileForDirs []string
  85. }
  86. func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
  87. t.Helper()
  88. bp2buildSetup := android.GroupFixturePreparers(
  89. android.FixtureRegisterWithContext(registerModuleTypes),
  90. SetBp2BuildTestRunner,
  91. )
  92. runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
  93. }
  94. func RunApiBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
  95. t.Helper()
  96. apiBp2BuildSetup := android.GroupFixturePreparers(
  97. android.FixtureRegisterWithContext(registerModuleTypes),
  98. SetApiBp2BuildTestRunner,
  99. )
  100. runBp2BuildTestCaseWithSetup(t, apiBp2BuildSetup, tc)
  101. }
  102. func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePreparer, tc Bp2buildTestCase) {
  103. t.Helper()
  104. dir := "."
  105. filesystem := make(map[string][]byte)
  106. for f, content := range tc.Filesystem {
  107. filesystem[f] = []byte(content)
  108. }
  109. preparers := []android.FixturePreparer{
  110. extraPreparer,
  111. android.FixtureMergeMockFs(filesystem),
  112. android.FixtureWithRootAndroidBp(tc.Blueprint),
  113. android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
  114. ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
  115. }),
  116. android.FixtureModifyContext(func(ctx *android.TestContext) {
  117. // A default configuration for tests to not have to specify bp2build_available on top level
  118. // targets.
  119. bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig(
  120. allowlists.Bp2BuildConfig{
  121. android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
  122. },
  123. )
  124. for _, f := range tc.KeepBuildFileForDirs {
  125. bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{
  126. f: /*recursive=*/ false,
  127. })
  128. }
  129. ctx.RegisterBp2BuildConfig(bp2buildConfig)
  130. // This setting is added to bp2build invocations. It prevents bp2build
  131. // from cloning modules to their original state after mutators run. This
  132. // would lose some data intentionally set by these mutators.
  133. ctx.SkipCloneModulesAfterMutators = true
  134. }),
  135. android.FixtureModifyEnv(func(env map[string]string) {
  136. if tc.UnconvertedDepsMode == errorModulesUnconvertedDeps {
  137. env["BP2BUILD_ERROR_UNCONVERTED"] = "true"
  138. }
  139. }),
  140. }
  141. preparer := android.GroupFixturePreparers(preparers...)
  142. if tc.ExpectedErr != nil {
  143. pattern := "\\Q" + tc.ExpectedErr.Error() + "\\E"
  144. preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(pattern))
  145. }
  146. result := preparer.RunTestWithCustomResult(t).(*BazelTestResult)
  147. if len(result.Errs) > 0 {
  148. return
  149. }
  150. checkDir := dir
  151. if tc.Dir != "" {
  152. checkDir = tc.Dir
  153. }
  154. expectedTargets := map[string][]string{
  155. checkDir: tc.ExpectedBazelTargets,
  156. }
  157. result.CompareAllBazelTargets(t, tc.Description, expectedTargets, true)
  158. }
  159. // SetBp2BuildTestRunner customizes the test fixture mechanism to run tests in Bp2Build mode.
  160. var SetBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{Bp2Build})
  161. // SetApiBp2BuildTestRunner customizes the test fixture mechanism to run tests in ApiBp2build mode.
  162. var SetApiBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{ApiBp2build})
  163. // bazelTestRunner customizes the test fixture mechanism to run tests of the bp2build and
  164. // apiBp2build build modes.
  165. type bazelTestRunner struct {
  166. mode CodegenMode
  167. }
  168. func (b *bazelTestRunner) FinalPreparer(result *android.TestResult) android.CustomTestResult {
  169. ctx := result.TestContext
  170. switch b.mode {
  171. case Bp2Build:
  172. ctx.RegisterForBazelConversion()
  173. case ApiBp2build:
  174. ctx.RegisterForApiBazelConversion()
  175. default:
  176. panic(fmt.Errorf("unknown build mode: %d", b.mode))
  177. }
  178. return &BazelTestResult{TestResult: result}
  179. }
  180. func (b *bazelTestRunner) PostParseProcessor(result android.CustomTestResult) {
  181. bazelResult := result.(*BazelTestResult)
  182. ctx := bazelResult.TestContext
  183. config := bazelResult.Config
  184. _, errs := ctx.ResolveDependencies(config)
  185. if bazelResult.CollateErrs(errs) {
  186. return
  187. }
  188. codegenMode := Bp2Build
  189. if ctx.Config().BuildMode == android.ApiBp2build {
  190. codegenMode = ApiBp2build
  191. }
  192. codegenCtx := NewCodegenContext(config, ctx.Context, codegenMode, "")
  193. res, errs := GenerateBazelTargets(codegenCtx, false)
  194. if bazelResult.CollateErrs(errs) {
  195. return
  196. }
  197. // Store additional data for access by tests.
  198. bazelResult.conversionResults = res
  199. }
  200. // BazelTestResult is a wrapper around android.TestResult to provide type safe access to the bazel
  201. // specific data stored by the bazelTestRunner.
  202. type BazelTestResult struct {
  203. *android.TestResult
  204. // The result returned by the GenerateBazelTargets function.
  205. conversionResults
  206. }
  207. // CompareAllBazelTargets compares the BazelTargets produced by the test for all the directories
  208. // with the supplied set of expected targets.
  209. //
  210. // If ignoreUnexpected=false then this enforces an exact match where every BazelTarget produced must
  211. // have a corresponding expected BazelTarget.
  212. //
  213. // If ignoreUnexpected=true then it will ignore directories for which there are no expected targets.
  214. func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, description string, expectedTargets map[string][]string, ignoreUnexpected bool) {
  215. t.Helper()
  216. actualTargets := b.buildFileToTargets
  217. // Generate the sorted set of directories to check.
  218. dirsToCheck := android.SortedKeys(expectedTargets)
  219. if !ignoreUnexpected {
  220. // This needs to perform an exact match so add the directories in which targets were
  221. // produced to the list of directories to check.
  222. dirsToCheck = append(dirsToCheck, android.SortedKeys(actualTargets)...)
  223. dirsToCheck = android.SortedUniqueStrings(dirsToCheck)
  224. }
  225. for _, dir := range dirsToCheck {
  226. expected := expectedTargets[dir]
  227. actual := actualTargets[dir]
  228. if expected == nil {
  229. if actual != nil {
  230. t.Errorf("did not expect any bazel modules in %q but found %d", dir, len(actual))
  231. }
  232. } else if actual == nil {
  233. expectedCount := len(expected)
  234. if expectedCount > 0 {
  235. t.Errorf("expected %d bazel modules in %q but did not find any", expectedCount, dir)
  236. }
  237. } else {
  238. b.CompareBazelTargets(t, description, expected, actual)
  239. }
  240. }
  241. }
  242. func (b BazelTestResult) CompareBazelTargets(t *testing.T, description string, expectedContents []string, actualTargets BazelTargets) {
  243. t.Helper()
  244. if actualCount, expectedCount := len(actualTargets), len(expectedContents); actualCount != expectedCount {
  245. t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
  246. description, expectedCount, expectedContents, actualCount, actualTargets)
  247. } else {
  248. sort.SliceStable(actualTargets, func(i, j int) bool {
  249. return actualTargets[i].name < actualTargets[j].name
  250. })
  251. sort.SliceStable(expectedContents, func(i, j int) bool {
  252. return getTargetName(expectedContents[i]) < getTargetName(expectedContents[j])
  253. })
  254. for i, actualTarget := range actualTargets {
  255. if w, g := expectedContents[i], actualTarget.content; w != g {
  256. t.Errorf(
  257. "%s[%d]: Expected generated Bazel target to be `%s`, got `%s`",
  258. description, i, w, g)
  259. }
  260. }
  261. }
  262. }
  263. type nestedProps struct {
  264. Nested_prop *string
  265. }
  266. type EmbeddedProps struct {
  267. Embedded_prop *string
  268. }
  269. type OtherEmbeddedProps struct {
  270. Other_embedded_prop *string
  271. }
  272. type customProps struct {
  273. EmbeddedProps
  274. *OtherEmbeddedProps
  275. Bool_prop bool
  276. Bool_ptr_prop *bool
  277. // Ensure that properties tagged `blueprint:mutated` are omitted
  278. Int_prop int `blueprint:"mutated"`
  279. Int64_ptr_prop *int64
  280. String_prop string
  281. String_literal_prop *string `android:"arch_variant"`
  282. String_ptr_prop *string
  283. String_list_prop []string
  284. Nested_props nestedProps
  285. Nested_props_ptr *nestedProps
  286. Arch_paths []string `android:"path,arch_variant"`
  287. Arch_paths_exclude []string `android:"path,arch_variant"`
  288. // Prop used to indicate this conversion should be 1 module -> multiple targets
  289. One_to_many_prop *bool
  290. Api *string // File describing the APIs of this module
  291. Test_config_setting *bool // Used to test generation of config_setting targets
  292. }
  293. type customModule struct {
  294. android.ModuleBase
  295. android.BazelModuleBase
  296. props customProps
  297. }
  298. // OutputFiles is needed because some instances of this module use dist with a
  299. // tag property which requires the module implements OutputFileProducer.
  300. func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
  301. return android.PathsForTesting("path" + tag), nil
  302. }
  303. func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  304. // nothing for now.
  305. }
  306. func customModuleFactoryBase() android.Module {
  307. module := &customModule{}
  308. module.AddProperties(&module.props)
  309. android.InitBazelModule(module)
  310. return module
  311. }
  312. func customModuleFactoryHostAndDevice() android.Module {
  313. m := customModuleFactoryBase()
  314. android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
  315. return m
  316. }
  317. func customModuleFactoryDeviceSupported() android.Module {
  318. m := customModuleFactoryBase()
  319. android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibBoth)
  320. return m
  321. }
  322. func customModuleFactoryHostSupported() android.Module {
  323. m := customModuleFactoryBase()
  324. android.InitAndroidArchModule(m, android.HostSupported, android.MultilibBoth)
  325. return m
  326. }
  327. func customModuleFactoryHostAndDeviceDefault() android.Module {
  328. m := customModuleFactoryBase()
  329. android.InitAndroidArchModule(m, android.HostAndDeviceDefault, android.MultilibBoth)
  330. return m
  331. }
  332. func customModuleFactoryNeitherHostNorDeviceSupported() android.Module {
  333. m := customModuleFactoryBase()
  334. android.InitAndroidArchModule(m, android.NeitherHostNorDeviceSupported, android.MultilibBoth)
  335. return m
  336. }
  337. type testProps struct {
  338. Test_prop struct {
  339. Test_string_prop string
  340. }
  341. }
  342. type customTestModule struct {
  343. android.ModuleBase
  344. props customProps
  345. test_props testProps
  346. }
  347. func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  348. // nothing for now.
  349. }
  350. func customTestModuleFactoryBase() android.Module {
  351. m := &customTestModule{}
  352. m.AddProperties(&m.props)
  353. m.AddProperties(&m.test_props)
  354. return m
  355. }
  356. func customTestModuleFactory() android.Module {
  357. m := customTestModuleFactoryBase()
  358. android.InitAndroidModule(m)
  359. return m
  360. }
  361. type customDefaultsModule struct {
  362. android.ModuleBase
  363. android.DefaultsModuleBase
  364. }
  365. func customDefaultsModuleFactoryBase() android.DefaultsModule {
  366. module := &customDefaultsModule{}
  367. module.AddProperties(&customProps{})
  368. return module
  369. }
  370. func customDefaultsModuleFactoryBasic() android.Module {
  371. return customDefaultsModuleFactoryBase()
  372. }
  373. func customDefaultsModuleFactory() android.Module {
  374. m := customDefaultsModuleFactoryBase()
  375. android.InitDefaultsModule(m)
  376. return m
  377. }
  378. type EmbeddedAttr struct {
  379. Embedded_attr *string
  380. }
  381. type OtherEmbeddedAttr struct {
  382. Other_embedded_attr *string
  383. }
  384. type customBazelModuleAttributes struct {
  385. EmbeddedAttr
  386. *OtherEmbeddedAttr
  387. String_literal_prop bazel.StringAttribute
  388. String_ptr_prop *string
  389. String_list_prop []string
  390. Arch_paths bazel.LabelListAttribute
  391. Api bazel.LabelAttribute
  392. }
  393. func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
  394. if p := m.props.One_to_many_prop; p != nil && *p {
  395. customBp2buildOneToMany(ctx, m)
  396. return
  397. }
  398. paths := bazel.LabelListAttribute{}
  399. strAttr := bazel.StringAttribute{}
  400. for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
  401. for config, props := range configToProps {
  402. if custProps, ok := props.(*customProps); ok {
  403. if custProps.Arch_paths != nil {
  404. paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, custProps.Arch_paths, custProps.Arch_paths_exclude))
  405. }
  406. if custProps.String_literal_prop != nil {
  407. strAttr.SetSelectValue(axis, config, custProps.String_literal_prop)
  408. }
  409. }
  410. }
  411. }
  412. productVariableProps := android.ProductVariableProperties(ctx, ctx.Module())
  413. if props, ok := productVariableProps["String_literal_prop"]; ok {
  414. for c, p := range props {
  415. if val, ok := p.(*string); ok {
  416. strAttr.SetSelectValue(c.ConfigurationAxis(), c.SelectKey(), val)
  417. }
  418. }
  419. }
  420. paths.ResolveExcludes()
  421. attrs := &customBazelModuleAttributes{
  422. String_literal_prop: strAttr,
  423. String_ptr_prop: m.props.String_ptr_prop,
  424. String_list_prop: m.props.String_list_prop,
  425. Arch_paths: paths,
  426. }
  427. attrs.Embedded_attr = m.props.Embedded_prop
  428. if m.props.OtherEmbeddedProps != nil {
  429. attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
  430. }
  431. props := bazel.BazelTargetModuleProperties{
  432. Rule_class: "custom",
  433. }
  434. ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
  435. if proptools.Bool(m.props.Test_config_setting) {
  436. m.createConfigSetting(ctx)
  437. }
  438. }
  439. func (m *customModule) createConfigSetting(ctx android.TopDownMutatorContext) {
  440. csa := bazel.ConfigSettingAttributes{
  441. Flag_values: bazel.StringMapAttribute{
  442. "//build/bazel/rules/my_string_setting": m.Name(),
  443. },
  444. }
  445. ca := android.CommonAttributes{
  446. Name: m.Name() + "_config_setting",
  447. }
  448. ctx.CreateBazelConfigSetting(
  449. csa,
  450. ca,
  451. ctx.ModuleDir(),
  452. )
  453. }
  454. var _ android.ApiProvider = (*customModule)(nil)
  455. func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
  456. props := bazel.BazelTargetModuleProperties{
  457. Rule_class: "custom_api_contribution",
  458. }
  459. apiAttribute := bazel.MakeLabelAttribute(
  460. android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label,
  461. )
  462. attrs := &customBazelModuleAttributes{
  463. Api: *apiAttribute,
  464. }
  465. ctx.CreateBazelTargetModule(props,
  466. android.CommonAttributes{Name: c.Name()},
  467. attrs)
  468. }
  469. // A bp2build mutator that uses load statements and creates a 1:M mapping from
  470. // module to target.
  471. func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
  472. baseName := m.Name()
  473. attrs := &customBazelModuleAttributes{}
  474. myLibraryProps := bazel.BazelTargetModuleProperties{
  475. Rule_class: "my_library",
  476. Bzl_load_location: "//build/bazel/rules:rules.bzl",
  477. }
  478. ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
  479. protoLibraryProps := bazel.BazelTargetModuleProperties{
  480. Rule_class: "proto_library",
  481. Bzl_load_location: "//build/bazel/rules:proto.bzl",
  482. }
  483. ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
  484. myProtoLibraryProps := bazel.BazelTargetModuleProperties{
  485. Rule_class: "my_proto_library",
  486. Bzl_load_location: "//build/bazel/rules:proto.bzl",
  487. }
  488. ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
  489. }
  490. // Helper method for tests to easily access the targets in a dir.
  491. func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
  492. // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
  493. res, err := GenerateBazelTargets(codegenCtx, false)
  494. if err != nil {
  495. return BazelTargets{}, err
  496. }
  497. return res.buildFileToTargets[dir], err
  498. }
  499. func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
  500. ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
  501. ctx.RegisterForBazelConversion()
  502. }
  503. func simpleModuleDoNotConvertBp2build(typ, name string) string {
  504. return fmt.Sprintf(`
  505. %s {
  506. name: "%s",
  507. bazel_module: { bp2build_available: false },
  508. }`, typ, name)
  509. }
  510. type AttrNameToString map[string]string
  511. func (a AttrNameToString) clone() AttrNameToString {
  512. newAttrs := make(AttrNameToString, len(a))
  513. for k, v := range a {
  514. newAttrs[k] = v
  515. }
  516. return newAttrs
  517. }
  518. // makeBazelTargetNoRestrictions returns bazel target build file definition that can be host or
  519. // device specific, or independent of host/device.
  520. func makeBazelTargetHostOrDevice(typ, name string, attrs AttrNameToString, hod android.HostOrDeviceSupported) string {
  521. if _, ok := attrs["target_compatible_with"]; !ok {
  522. switch hod {
  523. case android.HostSupported:
  524. attrs["target_compatible_with"] = `select({
  525. "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
  526. "//conditions:default": [],
  527. })`
  528. case android.DeviceSupported:
  529. attrs["target_compatible_with"] = `["//build/bazel/platforms/os:android"]`
  530. }
  531. }
  532. attrStrings := make([]string, 0, len(attrs)+1)
  533. if name != "" {
  534. attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
  535. }
  536. for _, k := range android.SortedKeys(attrs) {
  537. attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
  538. }
  539. return fmt.Sprintf(`%s(
  540. %s
  541. )`, typ, strings.Join(attrStrings, "\n"))
  542. }
  543. // MakeBazelTargetNoRestrictions returns bazel target build file definition that does not add a
  544. // target_compatible_with. This is useful for module types like filegroup and genrule that arch not
  545. // arch variant
  546. func MakeBazelTargetNoRestrictions(typ, name string, attrs AttrNameToString) string {
  547. return makeBazelTargetHostOrDevice(typ, name, attrs, android.HostAndDeviceDefault)
  548. }
  549. // makeBazelTargetNoRestrictions returns bazel target build file definition that is device specific
  550. // as this is the most common default in Soong.
  551. func MakeBazelTarget(typ, name string, attrs AttrNameToString) string {
  552. return makeBazelTargetHostOrDevice(typ, name, attrs, android.DeviceSupported)
  553. }
  554. type ExpectedRuleTarget struct {
  555. Rule string
  556. Name string
  557. Attrs AttrNameToString
  558. Hod android.HostOrDeviceSupported
  559. }
  560. func (ebr ExpectedRuleTarget) String() string {
  561. return makeBazelTargetHostOrDevice(ebr.Rule, ebr.Name, ebr.Attrs, ebr.Hod)
  562. }
  563. func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string {
  564. if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs {
  565. return ""
  566. }
  567. STUB_SUITE_ATTRS := map[string]string{
  568. "stubs_symbol_file": "symbol_file",
  569. "stubs_versions": "versions",
  570. "soname": "soname",
  571. "source_library_label": "source_library_label",
  572. }
  573. stubSuiteAttrs := AttrNameToString{}
  574. for key, _ := range attrs {
  575. if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
  576. stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
  577. } else {
  578. panic(fmt.Sprintf("unused cc_stub_suite attr %q\n", key))
  579. }
  580. }
  581. return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
  582. }
  583. func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
  584. return MakeNeverlinkDuplicateTargetWithAttrs(moduleType, name, AttrNameToString{})
  585. }
  586. func MakeNeverlinkDuplicateTargetWithAttrs(moduleType string, name string, extraAttrs AttrNameToString) string {
  587. attrs := extraAttrs
  588. attrs["neverlink"] = `True`
  589. attrs["exports"] = `[":` + name + `"]`
  590. return MakeBazelTarget(moduleType, name+"-neverlink", attrs)
  591. }
  592. func getTargetName(targetContent string) string {
  593. data := strings.Split(targetContent, "name = \"")
  594. if len(data) < 2 {
  595. return ""
  596. } else {
  597. endIndex := strings.Index(data[1], "\"")
  598. return data[1][:endIndex]
  599. }
  600. }