blob: 43baf98dbe313a6937bea1bb86699258d477f85f [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"
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000024 "strings"
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040025 "testing"
26
Spandan Das5af0bd32022-09-28 20:43:08 +000027 "github.com/google/blueprint/proptools"
28
Liz Kammer2dd9ca42020-11-25 16:06:39 -080029 "android/soong/android"
Sam Delmerico24c56032022-03-28 19:53:03 +000030 "android/soong/android/allowlists"
Jingwen Chen73850672020-12-14 08:25:34 -050031 "android/soong/bazel"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080032)
33
Jingwen Chen91220d72021-03-24 02:18:33 -040034var (
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040035 buildDir string
Jingwen Chen91220d72021-03-24 02:18:33 -040036)
37
Jingwen Chen5146ac02021-09-02 11:44:42 +000038func 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 +000039 t.Helper()
Jingwen Chen5146ac02021-09-02 11:44:42 +000040
Jingwen Chen5146ac02021-09-02 11:44:42 +000041 if len(errs) != 1 {
Liz Kammer6eff3232021-08-26 08:37:59 -040042 return false
Jingwen Chen5146ac02021-09-02 11:44:42 +000043 }
Liz Kammer54309532021-12-14 12:21:22 -050044 if strings.Contains(errs[0].Error(), expectedErr.Error()) {
Jingwen Chen5146ac02021-09-02 11:44:42 +000045 return true
46 }
47
48 return false
49}
50
Sam Delmerico3177a6e2022-06-21 19:28:33 +000051func errored(t *testing.T, tc Bp2buildTestCase, errs []error) bool {
Jingwen Chen5146ac02021-09-02 11:44:42 +000052 t.Helper()
Sam Delmerico3177a6e2022-06-21 19:28:33 +000053 if tc.ExpectedErr != nil {
Jingwen Chen5146ac02021-09-02 11:44:42 +000054 // Rely on checkErrors, as this test case is expected to have an error.
55 return false
56 }
57
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000058 if len(errs) > 0 {
59 for _, err := range errs {
Sam Delmerico3177a6e2022-06-21 19:28:33 +000060 t.Errorf("%s: %s", tc.Description, err)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000061 }
62 return true
63 }
Jingwen Chen5146ac02021-09-02 11:44:42 +000064
65 // All good, continue execution.
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000066 return false
67}
68
Trevor Radcliffe1b4b2d92022-09-01 18:57:01 +000069func RunBp2BuildTestCaseSimple(t *testing.T, tc Bp2buildTestCase) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000070 t.Helper()
Sam Delmerico3177a6e2022-06-21 19:28:33 +000071 RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000072}
73
Sam Delmerico3177a6e2022-06-21 19:28:33 +000074type Bp2buildTestCase struct {
75 Description string
76 ModuleTypeUnderTest string
77 ModuleTypeUnderTestFactory android.ModuleFactory
78 Blueprint string
79 ExpectedBazelTargets []string
80 Filesystem map[string]string
81 Dir string
Trevor Radcliffe58ea4512022-04-07 20:36:39 +000082 // An error with a string contained within the string of the expected error
Sam Delmerico3177a6e2022-06-21 19:28:33 +000083 ExpectedErr error
84 UnconvertedDepsMode unconvertedDepsMode
Jingwen Chen0eeaeb82022-09-21 10:27:42 +000085
86 // For every directory listed here, the BUILD file for that directory will
87 // be merged with the generated BUILD file. This allows custom BUILD targets
88 // to be used in tests, or use BUILD files to draw package boundaries.
89 KeepBuildFileForDirs []string
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000090}
91
Sam Delmerico3177a6e2022-06-21 19:28:33 +000092func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
Liz Kammerffc17e42022-11-23 09:42:05 -050093 t.Helper()
Paul Duffin4c0765a2022-10-29 17:48:00 +010094 bp2buildSetup := android.GroupFixturePreparers(
95 android.FixtureRegisterWithContext(registerModuleTypes),
96 SetBp2BuildTestRunner,
97 )
Spandan Das5af0bd32022-09-28 20:43:08 +000098 runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
99}
100
101func RunApiBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
Liz Kammerffc17e42022-11-23 09:42:05 -0500102 t.Helper()
Paul Duffin4c0765a2022-10-29 17:48:00 +0100103 apiBp2BuildSetup := android.GroupFixturePreparers(
104 android.FixtureRegisterWithContext(registerModuleTypes),
105 SetApiBp2BuildTestRunner,
106 )
Spandan Das5af0bd32022-09-28 20:43:08 +0000107 runBp2BuildTestCaseWithSetup(t, apiBp2BuildSetup, tc)
108}
109
Paul Duffin4c0765a2022-10-29 17:48:00 +0100110func 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 +0000111 t.Helper()
112 dir := "."
113 filesystem := make(map[string][]byte)
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000114 for f, content := range tc.Filesystem {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000115 filesystem[f] = []byte(content)
116 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000117
Paul Duffin4c0765a2022-10-29 17:48:00 +0100118 preparers := []android.FixturePreparer{
119 extraPreparer,
120 android.FixtureMergeMockFs(filesystem),
121 android.FixtureWithRootAndroidBp(tc.Blueprint),
122 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
123 ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
124 }),
125 android.FixtureModifyContext(func(ctx *android.TestContext) {
126 // A default configuration for tests to not have to specify bp2build_available on top level
127 // targets.
128 bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig(
129 allowlists.Bp2BuildConfig{
130 android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
131 },
132 )
133 for _, f := range tc.KeepBuildFileForDirs {
134 bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{
135 f: /*recursive=*/ false,
136 })
137 }
138 ctx.RegisterBp2BuildConfig(bp2buildConfig)
139 }),
140 android.FixtureModifyEnv(func(env map[string]string) {
141 if tc.UnconvertedDepsMode == errorModulesUnconvertedDeps {
142 env["BP2BUILD_ERROR_UNCONVERTED"] = "true"
143 }
144 }),
Jingwen Chen5146ac02021-09-02 11:44:42 +0000145 }
146
Paul Duffin4c0765a2022-10-29 17:48:00 +0100147 preparer := android.GroupFixturePreparers(preparers...)
148 if tc.ExpectedErr != nil {
149 pattern := "\\Q" + tc.ExpectedErr.Error() + "\\E"
150 preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(pattern))
151 }
152 result := preparer.RunTestWithCustomResult(t).(*BazelTestResult)
153 if len(result.Errs) > 0 {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000154 return
155 }
156
157 checkDir := dir
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000158 if tc.Dir != "" {
159 checkDir = tc.Dir
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000160 }
Paul Duffin4c0765a2022-10-29 17:48:00 +0100161 expectedTargets := map[string][]string{
162 checkDir: tc.ExpectedBazelTargets,
Liz Kammer6eff3232021-08-26 08:37:59 -0400163 }
Paul Duffin4c0765a2022-10-29 17:48:00 +0100164
165 result.CompareAllBazelTargets(t, tc.Description, expectedTargets, true)
166}
167
168// SetBp2BuildTestRunner customizes the test fixture mechanism to run tests in Bp2Build mode.
169var SetBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{Bp2Build})
170
171// SetApiBp2BuildTestRunner customizes the test fixture mechanism to run tests in ApiBp2build mode.
172var SetApiBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{ApiBp2build})
173
174// bazelTestRunner customizes the test fixture mechanism to run tests of the bp2build and
175// apiBp2build build modes.
176type bazelTestRunner struct {
177 mode CodegenMode
178}
179
180func (b *bazelTestRunner) FinalPreparer(result *android.TestResult) android.CustomTestResult {
181 ctx := result.TestContext
182 switch b.mode {
183 case Bp2Build:
184 ctx.RegisterForBazelConversion()
185 case ApiBp2build:
186 ctx.RegisterForApiBazelConversion()
187 default:
188 panic(fmt.Errorf("unknown build mode: %d", b.mode))
189 }
190
191 return &BazelTestResult{TestResult: result}
192}
193
194func (b *bazelTestRunner) PostParseProcessor(result android.CustomTestResult) {
195 bazelResult := result.(*BazelTestResult)
196 ctx := bazelResult.TestContext
197 config := bazelResult.Config
198 _, errs := ctx.ResolveDependencies(config)
199 if bazelResult.CollateErrs(errs) {
200 return
201 }
202
Cole Faustb85d1a12022-11-08 18:14:01 -0800203 codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
Paul Duffin4c0765a2022-10-29 17:48:00 +0100204 res, errs := GenerateBazelTargets(codegenCtx, false)
205 if bazelResult.CollateErrs(errs) {
206 return
207 }
208
209 // Store additional data for access by tests.
210 bazelResult.conversionResults = res
211}
212
213// BazelTestResult is a wrapper around android.TestResult to provide type safe access to the bazel
214// specific data stored by the bazelTestRunner.
215type BazelTestResult struct {
216 *android.TestResult
217
218 // The result returned by the GenerateBazelTargets function.
219 conversionResults
220}
221
222// CompareAllBazelTargets compares the BazelTargets produced by the test for all the directories
223// with the supplied set of expected targets.
224//
225// If ignoreUnexpected=false then this enforces an exact match where every BazelTarget produced must
226// have a corresponding expected BazelTarget.
227//
228// If ignoreUnexpected=true then it will ignore directories for which there are no expected targets.
229func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, description string, expectedTargets map[string][]string, ignoreUnexpected bool) {
230 actualTargets := b.buildFileToTargets
231
232 // Generate the sorted set of directories to check.
Cole Faust18994c72023-02-28 16:02:16 -0800233 dirsToCheck := android.SortedKeys(expectedTargets)
Paul Duffin4c0765a2022-10-29 17:48:00 +0100234 if !ignoreUnexpected {
235 // This needs to perform an exact match so add the directories in which targets were
236 // produced to the list of directories to check.
Cole Faust18994c72023-02-28 16:02:16 -0800237 dirsToCheck = append(dirsToCheck, android.SortedKeys(actualTargets)...)
Paul Duffin4c0765a2022-10-29 17:48:00 +0100238 dirsToCheck = android.SortedUniqueStrings(dirsToCheck)
239 }
240
241 for _, dir := range dirsToCheck {
242 expected := expectedTargets[dir]
243 actual := actualTargets[dir]
244
245 if expected == nil {
246 if actual != nil {
247 t.Errorf("did not expect any bazel modules in %q but found %d", dir, len(actual))
248 }
249 } else if actual == nil {
250 expectedCount := len(expected)
251 if expectedCount > 0 {
252 t.Errorf("expected %d bazel modules in %q but did not find any", expectedCount, dir)
253 }
254 } else {
255 b.CompareBazelTargets(t, description, expected, actual)
256 }
257 }
258}
259
260func (b BazelTestResult) CompareBazelTargets(t *testing.T, description string, expectedContents []string, actualTargets BazelTargets) {
Liz Kammer748d7072023-01-25 12:07:43 -0500261 t.Helper()
Paul Duffin4c0765a2022-10-29 17:48:00 +0100262 if actualCount, expectedCount := len(actualTargets), len(expectedContents); actualCount != expectedCount {
Sasha Smundak9d2f1742022-08-04 13:28:38 -0700263 t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
Paul Duffin4c0765a2022-10-29 17:48:00 +0100264 description, expectedCount, expectedContents, actualCount, actualTargets)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000265 } else {
Paul Duffin4c0765a2022-10-29 17:48:00 +0100266 for i, actualTarget := range actualTargets {
267 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 +0000268 t.Errorf(
Paul Duffin4c0765a2022-10-29 17:48:00 +0100269 "%s[%d]: Expected generated Bazel target to be `%s`, got `%s`",
270 description, i, w, g)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000271 }
272 }
273 }
274}
275
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800276type nestedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500277 Nested_prop *string
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800278}
279
Liz Kammer32a03392021-09-14 11:17:21 -0400280type EmbeddedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500281 Embedded_prop *string
Liz Kammer32a03392021-09-14 11:17:21 -0400282}
283
284type OtherEmbeddedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500285 Other_embedded_prop *string
Liz Kammer32a03392021-09-14 11:17:21 -0400286}
287
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800288type customProps struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400289 EmbeddedProps
290 *OtherEmbeddedProps
291
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800292 Bool_prop bool
293 Bool_ptr_prop *bool
294 // 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 +0000295 Int_prop int `blueprint:"mutated"`
296 Int64_ptr_prop *int64
297 String_prop string
298 String_literal_prop *string `android:"arch_variant"`
299 String_ptr_prop *string
300 String_list_prop []string
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800301
302 Nested_props nestedProps
303 Nested_props_ptr *nestedProps
Liz Kammer4562a3b2021-04-21 18:15:34 -0400304
Liz Kammer32b77cf2021-08-04 15:17:02 -0400305 Arch_paths []string `android:"path,arch_variant"`
306 Arch_paths_exclude []string `android:"path,arch_variant"`
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400307
308 // Prop used to indicate this conversion should be 1 module -> multiple targets
309 One_to_many_prop *bool
Spandan Das5af0bd32022-09-28 20:43:08 +0000310
311 Api *string // File describing the APIs of this module
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800312}
313
314type customModule struct {
315 android.ModuleBase
Liz Kammerea6666f2021-02-17 10:17:28 -0500316 android.BazelModuleBase
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800317
318 props customProps
319}
320
321// OutputFiles is needed because some instances of this module use dist with a
322// tag property which requires the module implements OutputFileProducer.
323func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
324 return android.PathsForTesting("path" + tag), nil
325}
326
327func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
328 // nothing for now.
329}
330
331func customModuleFactoryBase() android.Module {
332 module := &customModule{}
333 module.AddProperties(&module.props)
Liz Kammerea6666f2021-02-17 10:17:28 -0500334 android.InitBazelModule(module)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800335 return module
336}
337
Liz Kammerdfeb1202022-05-13 17:20:20 -0400338func customModuleFactoryHostAndDevice() android.Module {
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800339 m := customModuleFactoryBase()
Liz Kammer4562a3b2021-04-21 18:15:34 -0400340 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800341 return m
342}
343
Liz Kammerdfeb1202022-05-13 17:20:20 -0400344func customModuleFactoryDeviceSupported() android.Module {
345 m := customModuleFactoryBase()
346 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibBoth)
347 return m
348}
349
350func customModuleFactoryHostSupported() android.Module {
351 m := customModuleFactoryBase()
352 android.InitAndroidArchModule(m, android.HostSupported, android.MultilibBoth)
353 return m
354}
355
356func customModuleFactoryHostAndDeviceDefault() android.Module {
357 m := customModuleFactoryBase()
358 android.InitAndroidArchModule(m, android.HostAndDeviceDefault, android.MultilibBoth)
359 return m
360}
361
362func customModuleFactoryNeitherHostNorDeviceSupported() android.Module {
363 m := customModuleFactoryBase()
364 android.InitAndroidArchModule(m, android.NeitherHostNorDeviceSupported, android.MultilibBoth)
365 return m
366}
367
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800368type testProps struct {
369 Test_prop struct {
370 Test_string_prop string
371 }
372}
373
374type customTestModule struct {
375 android.ModuleBase
376
377 props customProps
378 test_props testProps
379}
380
381func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
382 // nothing for now.
383}
384
385func customTestModuleFactoryBase() android.Module {
386 m := &customTestModule{}
387 m.AddProperties(&m.props)
388 m.AddProperties(&m.test_props)
389 return m
390}
391
392func customTestModuleFactory() android.Module {
393 m := customTestModuleFactoryBase()
394 android.InitAndroidModule(m)
395 return m
396}
397
398type customDefaultsModule struct {
399 android.ModuleBase
400 android.DefaultsModuleBase
401}
402
403func customDefaultsModuleFactoryBase() android.DefaultsModule {
404 module := &customDefaultsModule{}
405 module.AddProperties(&customProps{})
406 return module
407}
408
409func customDefaultsModuleFactoryBasic() android.Module {
410 return customDefaultsModuleFactoryBase()
411}
412
413func customDefaultsModuleFactory() android.Module {
414 m := customDefaultsModuleFactoryBase()
415 android.InitDefaultsModule(m)
416 return m
417}
Jingwen Chen73850672020-12-14 08:25:34 -0500418
Liz Kammer32a03392021-09-14 11:17:21 -0400419type EmbeddedAttr struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500420 Embedded_attr *string
Liz Kammer32a03392021-09-14 11:17:21 -0400421}
422
423type OtherEmbeddedAttr struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500424 Other_embedded_attr *string
Liz Kammer32a03392021-09-14 11:17:21 -0400425}
426
Jingwen Chen73850672020-12-14 08:25:34 -0500427type customBazelModuleAttributes struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400428 EmbeddedAttr
429 *OtherEmbeddedAttr
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000430 String_literal_prop bazel.StringAttribute
431 String_ptr_prop *string
432 String_list_prop []string
433 Arch_paths bazel.LabelListAttribute
Spandan Das5af0bd32022-09-28 20:43:08 +0000434 Api bazel.LabelAttribute
Jingwen Chen73850672020-12-14 08:25:34 -0500435}
436
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400437func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400438 if p := m.props.One_to_many_prop; p != nil && *p {
439 customBp2buildOneToMany(ctx, m)
440 return
441 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400442
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000443 paths := bazel.LabelListAttribute{}
444 strAttr := bazel.StringAttribute{}
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400445 for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
446 for config, props := range configToProps {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000447 if custProps, ok := props.(*customProps); ok {
448 if custProps.Arch_paths != nil {
449 paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, custProps.Arch_paths, custProps.Arch_paths_exclude))
450 }
451 if custProps.String_literal_prop != nil {
452 strAttr.SetSelectValue(axis, config, custProps.String_literal_prop)
453 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400454 }
455 }
Jingwen Chen73850672020-12-14 08:25:34 -0500456 }
Liz Kammer9d2d4102022-12-21 14:51:37 -0500457 productVariableProps := android.ProductVariableProperties(ctx)
458 if props, ok := productVariableProps["String_literal_prop"]; ok {
459 for c, p := range props {
460 if val, ok := p.(*string); ok {
461 strAttr.SetSelectValue(c.ConfigurationAxis(), c.SelectKey(), val)
462 }
463 }
464 }
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400465
466 paths.ResolveExcludes()
467
468 attrs := &customBazelModuleAttributes{
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000469 String_literal_prop: strAttr,
470 String_ptr_prop: m.props.String_ptr_prop,
471 String_list_prop: m.props.String_list_prop,
472 Arch_paths: paths,
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400473 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux3a019a62022-06-23 16:02:44 +0000474
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400475 attrs.Embedded_attr = m.props.Embedded_prop
476 if m.props.OtherEmbeddedProps != nil {
477 attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
478 }
479
480 props := bazel.BazelTargetModuleProperties{
481 Rule_class: "custom",
482 }
483
484 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
Jingwen Chen73850672020-12-14 08:25:34 -0500485}
Jingwen Chen40067de2021-01-26 21:58:43 -0500486
Spandan Das5af0bd32022-09-28 20:43:08 +0000487var _ android.ApiProvider = (*customModule)(nil)
488
489func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
490 props := bazel.BazelTargetModuleProperties{
491 Rule_class: "custom_api_contribution",
492 }
493 apiAttribute := bazel.MakeLabelAttribute(
494 android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label,
495 )
496 attrs := &customBazelModuleAttributes{
497 Api: *apiAttribute,
498 }
499 ctx.CreateBazelTargetModule(props,
500 android.CommonAttributes{Name: c.Name()},
501 attrs)
502}
503
Jingwen Chen40067de2021-01-26 21:58:43 -0500504// A bp2build mutator that uses load statements and creates a 1:M mapping from
505// module to target.
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400506func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500507
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400508 baseName := m.Name()
509 attrs := &customBazelModuleAttributes{}
Jingwen Chen1fd14692021-02-05 03:01:50 -0500510
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400511 myLibraryProps := bazel.BazelTargetModuleProperties{
512 Rule_class: "my_library",
513 Bzl_load_location: "//build/bazel/rules:rules.bzl",
Jingwen Chen40067de2021-01-26 21:58:43 -0500514 }
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400515 ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
516
517 protoLibraryProps := bazel.BazelTargetModuleProperties{
518 Rule_class: "proto_library",
519 Bzl_load_location: "//build/bazel/rules:proto.bzl",
520 }
521 ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
522
523 myProtoLibraryProps := bazel.BazelTargetModuleProperties{
524 Rule_class: "my_proto_library",
525 Bzl_load_location: "//build/bazel/rules:proto.bzl",
526 }
527 ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
Jingwen Chen40067de2021-01-26 21:58:43 -0500528}
Jingwen Chenba369ad2021-02-22 10:19:34 -0500529
530// Helper method for tests to easily access the targets in a dir.
Liz Kammer6eff3232021-08-26 08:37:59 -0400531func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
Rupert Shuttleworth2a4fc3e2021-04-21 07:10:09 -0400532 // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
Liz Kammer6eff3232021-08-26 08:37:59 -0400533 res, err := GenerateBazelTargets(codegenCtx, false)
Alix94e26032022-08-16 20:37:33 +0000534 if err != nil {
535 return BazelTargets{}, err
536 }
Liz Kammer6eff3232021-08-26 08:37:59 -0400537 return res.buildFileToTargets[dir], err
Jingwen Chenba369ad2021-02-22 10:19:34 -0500538}
Liz Kammer32b77cf2021-08-04 15:17:02 -0400539
540func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400541 ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
Liz Kammer32b77cf2021-08-04 15:17:02 -0400542 ctx.RegisterForBazelConversion()
543}
Liz Kammer7a210ac2021-09-22 15:52:58 -0400544
545func simpleModuleDoNotConvertBp2build(typ, name string) string {
546 return fmt.Sprintf(`
547%s {
548 name: "%s",
549 bazel_module: { bp2build_available: false },
550}`, typ, name)
551}
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500552
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000553type AttrNameToString map[string]string
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500554
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000555func (a AttrNameToString) clone() AttrNameToString {
556 newAttrs := make(AttrNameToString, len(a))
Liz Kammerdfeb1202022-05-13 17:20:20 -0400557 for k, v := range a {
558 newAttrs[k] = v
559 }
560 return newAttrs
561}
562
563// makeBazelTargetNoRestrictions returns bazel target build file definition that can be host or
564// device specific, or independent of host/device.
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000565func makeBazelTargetHostOrDevice(typ, name string, attrs AttrNameToString, hod android.HostOrDeviceSupported) string {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400566 if _, ok := attrs["target_compatible_with"]; !ok {
567 switch hod {
568 case android.HostSupported:
569 attrs["target_compatible_with"] = `select({
570 "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
571 "//conditions:default": [],
572 })`
573 case android.DeviceSupported:
574 attrs["target_compatible_with"] = `["//build/bazel/platforms/os:android"]`
575 }
576 }
577
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500578 attrStrings := make([]string, 0, len(attrs)+1)
Sasha Smundakfb589492022-08-04 11:13:27 -0700579 if name != "" {
580 attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
581 }
Cole Faust18994c72023-02-28 16:02:16 -0800582 for _, k := range android.SortedKeys(attrs) {
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500583 attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
584 }
585 return fmt.Sprintf(`%s(
586%s
587)`, typ, strings.Join(attrStrings, "\n"))
588}
Liz Kammerdfeb1202022-05-13 17:20:20 -0400589
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000590// MakeBazelTargetNoRestrictions returns bazel target build file definition that does not add a
Liz Kammerdfeb1202022-05-13 17:20:20 -0400591// target_compatible_with. This is useful for module types like filegroup and genrule that arch not
592// arch variant
Sam Delmerico3177a6e2022-06-21 19:28:33 +0000593func MakeBazelTargetNoRestrictions(typ, name string, attrs AttrNameToString) string {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400594 return makeBazelTargetHostOrDevice(typ, name, attrs, android.HostAndDeviceDefault)
595}
596
597// makeBazelTargetNoRestrictions returns bazel target build file definition that is device specific
598// as this is the most common default in Soong.
Alixe06d75b2022-08-31 18:28:19 +0000599func MakeBazelTarget(typ, name string, attrs AttrNameToString) string {
Liz Kammerdfeb1202022-05-13 17:20:20 -0400600 return makeBazelTargetHostOrDevice(typ, name, attrs, android.DeviceSupported)
601}
Sasha Smundak9d2f1742022-08-04 13:28:38 -0700602
603type ExpectedRuleTarget struct {
604 Rule string
605 Name string
606 Attrs AttrNameToString
607 Hod android.HostOrDeviceSupported
608}
609
610func (ebr ExpectedRuleTarget) String() string {
611 return makeBazelTargetHostOrDevice(ebr.Rule, ebr.Name, ebr.Attrs, ebr.Hod)
612}
Trevor Radcliffe087af542022-09-16 15:36:10 +0000613
614func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string {
615 if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs {
616 return ""
617 }
618 STUB_SUITE_ATTRS := map[string]string{
619 "stubs_symbol_file": "symbol_file",
620 "stubs_versions": "versions",
621 "soname": "soname",
622 "source_library": "source_library",
623 }
624
625 stubSuiteAttrs := AttrNameToString{}
626 for key, _ := range attrs {
627 if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
628 stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
629 }
630 }
631 return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
632}
Alix341484b2022-10-31 19:08:18 +0000633
634func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
635 return MakeBazelTarget(moduleType, name+"-neverlink", AttrNameToString{
636 "neverlink": `True`,
637 "exports": `[":` + name + `"]`,
638 })
639}