blob: 8a8405526e2534a8a060f09e86bc595f9c33edd5 [file] [log] [blame]
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxf5a3eac2021-08-23 17:05:17 +00001// 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
Liz Kammer2dd9ca42020-11-25 16:06:39 -080015package bp2build
16
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux0da7ce62021-08-23 17:04:20 +000017/*
18For shareable/common bp2build testing functionality and dumping ground for
19specific-but-shared functionality among tests in package
20*/
21
Liz Kammer2dd9ca42020-11-25 16:06:39 -080022import (
Liz Kammer7a210ac2021-09-22 15:52:58 -040023 "fmt"
Zi Wangfba0a212023-03-07 16:48:19 -080024 "sort"
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000025 "strings"
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040026 "testing"
27
Spandan Das5af0bd32022-09-28 20:43:08 +000028 "github.com/google/blueprint/proptools"
29
Liz Kammer2dd9ca42020-11-25 16:06:39 -080030 "android/soong/android"
Sam Delmerico24c56032022-03-28 19:53:03 +000031 "android/soong/android/allowlists"
Jingwen Chen73850672020-12-14 08:25:34 -050032 "android/soong/bazel"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080033)
34
Jingwen Chen91220d72021-03-24 02:18:33 -040035var (
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040036 buildDir string
Jingwen Chen91220d72021-03-24 02:18:33 -040037)
38
Jingwen Chen5146ac02021-09-02 11:44:42 +000039func checkError(t *testing.T, errs []error, expectedErr error) bool {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000040 t.Helper()
Jingwen Chen5146ac02021-09-02 11:44:42 +000041
Jingwen Chen5146ac02021-09-02 11:44:42 +000042 if len(errs) != 1 {
Liz Kammer6eff3232021-08-26 08:37:59 -040043 return false
Jingwen Chen5146ac02021-09-02 11:44:42 +000044 }
Liz Kammer54309532021-12-14 12:21:22 -050045 if strings.Contains(errs[0].Error(), expectedErr.Error()) {
Jingwen Chen5146ac02021-09-02 11:44:42 +000046 return true
47 }
48
49 return false
50}
51
Sam Delmerico3177a6e2022-06-21 19:28:33 +000052func errored(t *testing.T, tc Bp2buildTestCase, errs []error) bool {
Jingwen Chen5146ac02021-09-02 11:44:42 +000053 t.Helper()
Sam Delmerico3177a6e2022-06-21 19:28:33 +000054 if tc.ExpectedErr != nil {
Jingwen Chen5146ac02021-09-02 11:44:42 +000055 // Rely on checkErrors, as this test case is expected to have an error.
56 return false
57 }
58
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000059 if len(errs) > 0 {
60 for _, err := range errs {
Sam Delmerico3177a6e2022-06-21 19:28:33 +000061 t.Errorf("%s: %s", tc.Description, err)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000062 }
63 return true
64 }
Jingwen Chen5146ac02021-09-02 11:44:42 +000065
66 // All good, continue execution.
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000067 return false
68}
69
Trevor Radcliffe1b4b2d92022-09-01 18:57:01 +000070func RunBp2BuildTestCaseSimple(t *testing.T, tc Bp2buildTestCase) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000071 t.Helper()
Sam Delmerico3177a6e2022-06-21 19:28:33 +000072 RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000073}
74
Sam Delmerico3177a6e2022-06-21 19:28:33 +000075type Bp2buildTestCase struct {
76 Description string
77 ModuleTypeUnderTest string
78 ModuleTypeUnderTestFactory android.ModuleFactory
79 Blueprint string
80 ExpectedBazelTargets []string
81 Filesystem map[string]string
82 Dir string
Trevor Radcliffe58ea4512022-04-07 20:36:39 +000083 // An error with a string contained within the string of the expected error
Sam Delmerico3177a6e2022-06-21 19:28:33 +000084 ExpectedErr error
85 UnconvertedDepsMode unconvertedDepsMode
Jingwen Chen0eeaeb82022-09-21 10:27:42 +000086
87 // For every directory listed here, the BUILD file for that directory will
88 // be merged with the generated BUILD file. This allows custom BUILD targets
89 // to be used in tests, or use BUILD files to draw package boundaries.
90 KeepBuildFileForDirs []string
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000091}
92
Sam Delmerico3177a6e2022-06-21 19:28:33 +000093func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
Liz Kammerffc17e42022-11-23 09:42:05 -050094 t.Helper()
Paul Duffin4c0765a2022-10-29 17:48:00 +010095 bp2buildSetup := android.GroupFixturePreparers(
96 android.FixtureRegisterWithContext(registerModuleTypes),
97 SetBp2BuildTestRunner,
98 )
Spandan Das5af0bd32022-09-28 20:43:08 +000099 runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
100}
101
102func RunApiBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
Liz Kammerffc17e42022-11-23 09:42:05 -0500103 t.Helper()
Paul Duffin4c0765a2022-10-29 17:48:00 +0100104 apiBp2BuildSetup := android.GroupFixturePreparers(
105 android.FixtureRegisterWithContext(registerModuleTypes),
106 SetApiBp2BuildTestRunner,
107 )
Spandan Das5af0bd32022-09-28 20:43:08 +0000108 runBp2BuildTestCaseWithSetup(t, apiBp2BuildSetup, tc)
109}
110
Paul Duffin4c0765a2022-10-29 17:48:00 +0100111func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePreparer, tc Bp2buildTestCase) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000112 t.Helper()
113 dir := "."
114 filesystem := make(map[string][]byte)
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000115 for f, content := range tc.Filesystem {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000116 filesystem[f] = []byte(content)
117 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000118
Paul Duffin4c0765a2022-10-29 17:48:00 +0100119 preparers := []android.FixturePreparer{
120 extraPreparer,
121 android.FixtureMergeMockFs(filesystem),
122 android.FixtureWithRootAndroidBp(tc.Blueprint),
123 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
124 ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
125 }),
126 android.FixtureModifyContext(func(ctx *android.TestContext) {
127 // A default configuration for tests to not have to specify bp2build_available on top level
128 // targets.
129 bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig(
130 allowlists.Bp2BuildConfig{
131 android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
132 },
133 )
134 for _, f := range tc.KeepBuildFileForDirs {
135 bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{
136 f: /*recursive=*/ false,
137 })
138 }
139 ctx.RegisterBp2BuildConfig(bp2buildConfig)
140 }),
141 android.FixtureModifyEnv(func(env map[string]string) {
142 if tc.UnconvertedDepsMode == errorModulesUnconvertedDeps {
143 env["BP2BUILD_ERROR_UNCONVERTED"] = "true"
144 }
145 }),
Jingwen Chen5146ac02021-09-02 11:44:42 +0000146 }
147
Paul Duffin4c0765a2022-10-29 17:48:00 +0100148 preparer := android.GroupFixturePreparers(preparers...)
149 if tc.ExpectedErr != nil {
150 pattern := "\\Q" + tc.ExpectedErr.Error() + "\\E"
151 preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(pattern))
152 }
153 result := preparer.RunTestWithCustomResult(t).(*BazelTestResult)
154 if len(result.Errs) > 0 {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000155 return
156 }
157
158 checkDir := dir
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000159 if tc.Dir != "" {
160 checkDir = tc.Dir
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000161 }
Paul Duffin4c0765a2022-10-29 17:48:00 +0100162 expectedTargets := map[string][]string{
163 checkDir: tc.ExpectedBazelTargets,
Liz Kammer6eff3232021-08-26 08:37:59 -0400164 }
Paul Duffin4c0765a2022-10-29 17:48:00 +0100165
166 result.CompareAllBazelTargets(t, tc.Description, expectedTargets, true)
167}
168
169// SetBp2BuildTestRunner customizes the test fixture mechanism to run tests in Bp2Build mode.
170var SetBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{Bp2Build})
171
172// SetApiBp2BuildTestRunner customizes the test fixture mechanism to run tests in ApiBp2build mode.
173var SetApiBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{ApiBp2build})
174
175// bazelTestRunner customizes the test fixture mechanism to run tests of the bp2build and
176// apiBp2build build modes.
177type bazelTestRunner struct {
178 mode CodegenMode
179}
180
181func (b *bazelTestRunner) FinalPreparer(result *android.TestResult) android.CustomTestResult {
182 ctx := result.TestContext
183 switch b.mode {
184 case Bp2Build:
185 ctx.RegisterForBazelConversion()
186 case ApiBp2build:
187 ctx.RegisterForApiBazelConversion()
188 default:
189 panic(fmt.Errorf("unknown build mode: %d", b.mode))
190 }
191
192 return &BazelTestResult{TestResult: result}
193}
194
195func (b *bazelTestRunner) PostParseProcessor(result android.CustomTestResult) {
196 bazelResult := result.(*BazelTestResult)
197 ctx := bazelResult.TestContext
198 config := bazelResult.Config
199 _, errs := ctx.ResolveDependencies(config)
200 if bazelResult.CollateErrs(errs) {
201 return
202 }
203
Cole Faustb85d1a12022-11-08 18:14:01 -0800204 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
Paul Duffin4c0765a2022-10-29 17:48:00 +0100205 res, errs := GenerateBazelTargets(codegenCtx, false)
206 if bazelResult.CollateErrs(errs) {
207 return
208 }
209
210 // Store additional data for access by tests.
211 bazelResult.conversionResults = res
212}
213
214// BazelTestResult is a wrapper around android.TestResult to provide type safe access to the bazel
215// specific data stored by the bazelTestRunner.
216type BazelTestResult struct {
217 *android.TestResult
218
219 // The result returned by the GenerateBazelTargets function.
220 conversionResults
221}
222
223// CompareAllBazelTargets compares the BazelTargets produced by the test for all the directories
224// with the supplied set of expected targets.
225//
226// If ignoreUnexpected=false then this enforces an exact match where every BazelTarget produced must
227// have a corresponding expected BazelTarget.
228//
229// If ignoreUnexpected=true then it will ignore directories for which there are no expected targets.
230func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, description string, expectedTargets map[string][]string, ignoreUnexpected bool) {
231 actualTargets := b.buildFileToTargets
232
233 // Generate the sorted set of directories to check.
Cole Faust18994c72023-02-28 16:02:16 -0800234 dirsToCheck := android.SortedKeys(expectedTargets)
Paul Duffin4c0765a2022-10-29 17:48:00 +0100235 if !ignoreUnexpected {
236 // This needs to perform an exact match so add the directories in which targets were
237 // produced to the list of directories to check.
Cole Faust18994c72023-02-28 16:02:16 -0800238 dirsToCheck = append(dirsToCheck, android.SortedKeys(actualTargets)...)
Paul Duffin4c0765a2022-10-29 17:48:00 +0100239 dirsToCheck = android.SortedUniqueStrings(dirsToCheck)
240 }
241
242 for _, dir := range dirsToCheck {
243 expected := expectedTargets[dir]
244 actual := actualTargets[dir]
245
246 if expected == nil {
247 if actual != nil {
248 t.Errorf("did not expect any bazel modules in %q but found %d", dir, len(actual))
249 }
250 } else if actual == nil {
251 expectedCount := len(expected)
252 if expectedCount > 0 {
253 t.Errorf("expected %d bazel modules in %q but did not find any", expectedCount, dir)
254 }
255 } else {
256 b.CompareBazelTargets(t, description, expected, actual)
257 }
258 }
259}
260
261func (b BazelTestResult) CompareBazelTargets(t *testing.T, description string, expectedContents []string, actualTargets BazelTargets) {
Liz Kammer748d7072023-01-25 12:07:43 -0500262 t.Helper()
Paul Duffin4c0765a2022-10-29 17:48:00 +0100263 if actualCount, expectedCount := len(actualTargets), len(expectedContents); actualCount != expectedCount {
Sasha Smundak9d2f1742022-08-04 13:28:38 -0700264 t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
Paul Duffin4c0765a2022-10-29 17:48:00 +0100265 description, expectedCount, expectedContents, actualCount, actualTargets)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000266 } else {
Zi Wangfba0a212023-03-07 16:48:19 -0800267 sort.SliceStable(actualTargets, func(i, j int) bool {
268 return actualTargets[i].name < actualTargets[j].name
269 })
270 sort.SliceStable(expectedContents, func(i, j int) bool {
271 return getTargetName(expectedContents[i]) < getTargetName(expectedContents[j])
272 })
Paul Duffin4c0765a2022-10-29 17:48:00 +0100273 for i, actualTarget := range actualTargets {
274 if w, g := expectedContents[i], actualTarget.content; w != g {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000275 t.Errorf(
Paul Duffin4c0765a2022-10-29 17:48:00 +0100276 "%s[%d]: Expected generated Bazel target to be `%s`, got `%s`",
277 description, i, w, g)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000278 }
279 }
280 }
281}
282
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800283type nestedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500284 Nested_prop *string
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800285}
286
Liz Kammer32a03392021-09-14 11:17:21 -0400287type EmbeddedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500288 Embedded_prop *string
Liz Kammer32a03392021-09-14 11:17:21 -0400289}
290
291type OtherEmbeddedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500292 Other_embedded_prop *string
Liz Kammer32a03392021-09-14 11:17:21 -0400293}
294
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800295type customProps struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400296 EmbeddedProps
297 *OtherEmbeddedProps
298
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800299 Bool_prop bool
300 Bool_ptr_prop *bool
301 // Ensure that properties tagged `blueprint:mutated` are omitted
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000302 Int_prop int `blueprint:"mutated"`
303 Int64_ptr_prop *int64
304 String_prop string
305 String_literal_prop *string `android:"arch_variant"`
306 String_ptr_prop *string
307 String_list_prop []string
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800308
309 Nested_props nestedProps
310 Nested_props_ptr *nestedProps
Liz Kammer4562a3b2021-04-21 18:15:34 -0400311
Liz Kammer32b77cf2021-08-04 15:17:02 -0400312 Arch_paths []string `android:"path,arch_variant"`
313 Arch_paths_exclude []string `android:"path,arch_variant"`
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400314
315 // Prop used to indicate this conversion should be 1 module -> multiple targets
316 One_to_many_prop *bool
Spandan Das5af0bd32022-09-28 20:43:08 +0000317
318 Api *string // File describing the APIs of this module
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800319}
320
321type customModule struct {
322 android.ModuleBase
Liz Kammerea6666f2021-02-17 10:17:28 -0500323 android.BazelModuleBase
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800324
325 props customProps
326}
327
328// OutputFiles is needed because some instances of this module use dist with a
329// tag property which requires the module implements OutputFileProducer.
330func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
331 return android.PathsForTesting("path" + tag), nil
332}
333
334func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
335 // nothing for now.
336}
337
338func customModuleFactoryBase() android.Module {
339 module := &customModule{}
340 module.AddProperties(&module.props)
Liz Kammerea6666f2021-02-17 10:17:28 -0500341 android.InitBazelModule(module)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800342 return module
343}
344
Liz Kammerdfeb1202022-05-13 17:20:20 -0400345func customModuleFactoryHostAndDevice() android.Module {
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800346 m := customModuleFactoryBase()
Liz Kammer4562a3b2021-04-21 18:15:34 -0400347 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800348 return m
349}
350
Liz Kammerdfeb1202022-05-13 17:20:20 -0400351func customModuleFactoryDeviceSupported() android.Module {
352 m := customModuleFactoryBase()
353 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibBoth)
354 return m
355}
356
357func customModuleFactoryHostSupported() android.Module {
358 m := customModuleFactoryBase()
359 android.InitAndroidArchModule(m, android.HostSupported, android.MultilibBoth)
360 return m
361}
362
363func customModuleFactoryHostAndDeviceDefault() android.Module {
364 m := customModuleFactoryBase()
365 android.InitAndroidArchModule(m, android.HostAndDeviceDefault, android.MultilibBoth)
366 return m
367}
368
369func customModuleFactoryNeitherHostNorDeviceSupported() android.Module {
370 m := customModuleFactoryBase()
371 android.InitAndroidArchModule(m, android.NeitherHostNorDeviceSupported, android.MultilibBoth)
372 return m
373}
374
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800375type testProps struct {
376 Test_prop struct {
377 Test_string_prop string
378 }
379}
380
381type customTestModule struct {
382 android.ModuleBase
383
384 props customProps
385 test_props testProps
386}
387
388func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
389 // nothing for now.
390}
391
392func customTestModuleFactoryBase() android.Module {
393 m := &customTestModule{}
394 m.AddProperties(&m.props)
395 m.AddProperties(&m.test_props)
396 return m
397}
398
399func customTestModuleFactory() android.Module {
400 m := customTestModuleFactoryBase()
401 android.InitAndroidModule(m)
402 return m
403}
404
405type customDefaultsModule struct {
406 android.ModuleBase
407 android.DefaultsModuleBase
408}
409
410func customDefaultsModuleFactoryBase() android.DefaultsModule {
411 module := &customDefaultsModule{}
412 module.AddProperties(&customProps{})
413 return module
414}
415
416func customDefaultsModuleFactoryBasic() android.Module {
417 return customDefaultsModuleFactoryBase()
418}
419
420func customDefaultsModuleFactory() android.Module {
421 m := customDefaultsModuleFactoryBase()
422 android.InitDefaultsModule(m)
423 return m
424}
Jingwen Chen73850672020-12-14 08:25:34 -0500425
Liz Kammer32a03392021-09-14 11:17:21 -0400426type EmbeddedAttr struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500427 Embedded_attr *string
Liz Kammer32a03392021-09-14 11:17:21 -0400428}
429
430type OtherEmbeddedAttr struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500431 Other_embedded_attr *string
Liz Kammer32a03392021-09-14 11:17:21 -0400432}
433
Jingwen Chen73850672020-12-14 08:25:34 -0500434type customBazelModuleAttributes struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400435 EmbeddedAttr
436 *OtherEmbeddedAttr
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000437 String_literal_prop bazel.StringAttribute
438 String_ptr_prop *string
439 String_list_prop []string
440 Arch_paths bazel.LabelListAttribute
Spandan Das5af0bd32022-09-28 20:43:08 +0000441 Api bazel.LabelAttribute
Jingwen Chen73850672020-12-14 08:25:34 -0500442}
443
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400444func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400445 if p := m.props.One_to_many_prop; p != nil && *p {
446 customBp2buildOneToMany(ctx, m)
447 return
448 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400449
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000450 paths := bazel.LabelListAttribute{}
451 strAttr := bazel.StringAttribute{}
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400452 for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
453 for config, props := range configToProps {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000454 if custProps, ok := props.(*customProps); ok {
455 if custProps.Arch_paths != nil {
456 paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, custProps.Arch_paths, custProps.Arch_paths_exclude))
457 }
458 if custProps.String_literal_prop != nil {
459 strAttr.SetSelectValue(axis, config, custProps.String_literal_prop)
460 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400461 }
462 }
Jingwen Chen73850672020-12-14 08:25:34 -0500463 }
Liz Kammer9d2d4102022-12-21 14:51:37 -0500464 productVariableProps := android.ProductVariableProperties(ctx)
465 if props, ok := productVariableProps["String_literal_prop"]; ok {
466 for c, p := range props {
467 if val, ok := p.(*string); ok {
468 strAttr.SetSelectValue(c.ConfigurationAxis(), c.SelectKey(), val)
469 }
470 }
471 }
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400472
473 paths.ResolveExcludes()
474
475 attrs := &customBazelModuleAttributes{
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000476 String_literal_prop: strAttr,
477 String_ptr_prop: m.props.String_ptr_prop,
478 String_list_prop: m.props.String_list_prop,
479 Arch_paths: paths,
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400480 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000481
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400482 attrs.Embedded_attr = m.props.Embedded_prop
483 if m.props.OtherEmbeddedProps != nil {
484 attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
485 }
486
487 props := bazel.BazelTargetModuleProperties{
488 Rule_class: "custom",
489 }
490
491 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
Jingwen Chen73850672020-12-14 08:25:34 -0500492}
Jingwen Chen40067de2021-01-26 21:58:43 -0500493
Spandan Das5af0bd32022-09-28 20:43:08 +0000494var _ android.ApiProvider = (*customModule)(nil)
495
496func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
497 props := bazel.BazelTargetModuleProperties{
498 Rule_class: "custom_api_contribution",
499 }
500 apiAttribute := bazel.MakeLabelAttribute(
501 android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label,
502 )
503 attrs := &customBazelModuleAttributes{
504 Api: *apiAttribute,
505 }
506 ctx.CreateBazelTargetModule(props,
507 android.CommonAttributes{Name: c.Name()},
508 attrs)
509}
510
Jingwen Chen40067de2021-01-26 21:58:43 -0500511// A bp2build mutator that uses load statements and creates a 1:M mapping from
512// module to target.
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400513func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500514
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400515 baseName := m.Name()
516 attrs := &customBazelModuleAttributes{}
Jingwen Chen1fd14692021-02-05 03:01:50 -0500517
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400518 myLibraryProps := bazel.BazelTargetModuleProperties{
519 Rule_class: "my_library",
520 Bzl_load_location: "//build/bazel/rules:rules.bzl",
Jingwen Chen40067de2021-01-26 21:58:43 -0500521 }
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400522 ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
523
524 protoLibraryProps := bazel.BazelTargetModuleProperties{
525 Rule_class: "proto_library",
526 Bzl_load_location: "//build/bazel/rules:proto.bzl",
527 }
528 ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
529
530 myProtoLibraryProps := bazel.BazelTargetModuleProperties{
531 Rule_class: "my_proto_library",
532 Bzl_load_location: "//build/bazel/rules:proto.bzl",
533 }
534 ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
Jingwen Chen40067de2021-01-26 21:58:43 -0500535}
Jingwen Chenba369ad2021-02-22 10:19:34 -0500536
537// Helper method for tests to easily access the targets in a dir.
Liz Kammer6eff3232021-08-26 08:37:59 -0400538func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
Rupert Shuttleworth2a4fc3e2021-04-21 07:10:09 -0400539 // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
Liz Kammer6eff3232021-08-26 08:37:59 -0400540 res, err := GenerateBazelTargets(codegenCtx, false)
Alix94e26032022-08-16 20:37:33 +0000541 if err != nil {
542 return BazelTargets{}, err
543 }
Liz Kammer6eff3232021-08-26 08:37:59 -0400544 return res.buildFileToTargets[dir], err
Jingwen Chenba369ad2021-02-22 10:19:34 -0500545}
Liz Kammer32b77cf2021-08-04 15:17:02 -0400546
547func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400548 ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
Liz Kammer32b77cf2021-08-04 15:17:02 -0400549 ctx.RegisterForBazelConversion()
550}
Liz Kammer7a210ac2021-09-22 15:52:58 -0400551
552func simpleModuleDoNotConvertBp2build(typ, name string) string {
553 return fmt.Sprintf(`
554%s {
555 name: "%s",
556 bazel_module: { bp2build_available: false },
557}`, typ, name)
558}
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500559
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000560type AttrNameToString map[string]string
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500561
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000562func (a AttrNameToString) clone() AttrNameToString {
563 newAttrs := make(AttrNameToString, len(a))
Liz Kammerdfeb1202022-05-13 17:20:20 -0400564 for k, v := range a {
565 newAttrs[k] = v
566 }
567 return newAttrs
568}
569
570// makeBazelTargetNoRestrictions returns bazel target build file definition that can be host or
571// device specific, or independent of host/device.
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000572func makeBazelTargetHostOrDevice(typ, name string, attrs AttrNameToString, hod android.HostOrDeviceSupported) string {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400573 if _, ok := attrs["target_compatible_with"]; !ok {
574 switch hod {
575 case android.HostSupported:
576 attrs["target_compatible_with"] = `select({
577 "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
578 "//conditions:default": [],
579 })`
580 case android.DeviceSupported:
581 attrs["target_compatible_with"] = `["//build/bazel/platforms/os:android"]`
582 }
583 }
584
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500585 attrStrings := make([]string, 0, len(attrs)+1)
Sasha Smundakfb589492022-08-04 11:13:27 -0700586 if name != "" {
587 attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
588 }
Cole Faust18994c72023-02-28 16:02:16 -0800589 for _, k := range android.SortedKeys(attrs) {
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500590 attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
591 }
592 return fmt.Sprintf(`%s(
593%s
594)`, typ, strings.Join(attrStrings, "\n"))
595}
Liz Kammerdfeb1202022-05-13 17:20:20 -0400596
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000597// MakeBazelTargetNoRestrictions returns bazel target build file definition that does not add a
Liz Kammerdfeb1202022-05-13 17:20:20 -0400598// target_compatible_with. This is useful for module types like filegroup and genrule that arch not
599// arch variant
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000600func MakeBazelTargetNoRestrictions(typ, name string, attrs AttrNameToString) string {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400601 return makeBazelTargetHostOrDevice(typ, name, attrs, android.HostAndDeviceDefault)
602}
603
604// makeBazelTargetNoRestrictions returns bazel target build file definition that is device specific
605// as this is the most common default in Soong.
Alixe06d75b2022-08-31 18:28:19 +0000606func MakeBazelTarget(typ, name string, attrs AttrNameToString) string {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400607 return makeBazelTargetHostOrDevice(typ, name, attrs, android.DeviceSupported)
608}
Sasha Smundak9d2f1742022-08-04 13:28:38 -0700609
610type ExpectedRuleTarget struct {
611 Rule string
612 Name string
613 Attrs AttrNameToString
614 Hod android.HostOrDeviceSupported
615}
616
617func (ebr ExpectedRuleTarget) String() string {
618 return makeBazelTargetHostOrDevice(ebr.Rule, ebr.Name, ebr.Attrs, ebr.Hod)
619}
Trevor Radcliffe087af542022-09-16 15:36:10 +0000620
621func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string {
622 if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs {
623 return ""
624 }
625 STUB_SUITE_ATTRS := map[string]string{
626 "stubs_symbol_file": "symbol_file",
627 "stubs_versions": "versions",
628 "soname": "soname",
629 "source_library": "source_library",
630 }
631
632 stubSuiteAttrs := AttrNameToString{}
633 for key, _ := range attrs {
634 if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
635 stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
636 }
637 }
638 return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
639}
Alix341484b2022-10-31 19:08:18 +0000640
641func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
642 return MakeBazelTarget(moduleType, name+"-neverlink", AttrNameToString{
643 "neverlink": `True`,
644 "exports": `[":` + name + `"]`,
645 })
646}
Zi Wangfba0a212023-03-07 16:48:19 -0800647
648func getTargetName(targetContent string) string {
649 data := strings.Split(targetContent, "name = \"")
650 if len(data) < 2 {
651 return ""
652 } else {
653 endIndex := strings.Index(data[1], "\"")
654 return data[1][:endIndex]
655 }
656}