blob: b0070330152b81bf6843c3733258df73dca6c625 [file] [log] [blame]
Jingwen Chen8c1b97e2021-02-18 03:21:34 -05001// 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
15package bp2build
16
17import (
18 "android/soong/android"
19 "android/soong/cc"
20 "fmt"
21 "strings"
22 "testing"
23)
24
25func TestCcObjectBp2Build(t *testing.T) {
26 testCases := []struct {
27 description string
28 moduleTypeUnderTest string
29 moduleTypeUnderTestFactory android.ModuleFactory
30 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
31 blueprint string
32 expectedBazelTargets []string
33 filesystem map[string]string
34 }{
35 {
36 description: "simple cc_object generates cc_object with include header dep",
37 moduleTypeUnderTest: "cc_object",
38 moduleTypeUnderTestFactory: cc.ObjectFactory,
39 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
40 filesystem: map[string]string{
Jingwen Chendb120242021-02-23 00:46:47 -050041 "a/b/foo.h": "",
42 "a/b/bar.h": "",
43 "a/b/exclude.c": "",
44 "a/b/c.c": "",
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050045 },
46 blueprint: `cc_object {
47 name: "foo",
48 local_include_dirs: ["include"],
49 cflags: [
50 "-Wno-gcc-compat",
51 "-Wall",
52 "-Werror",
53 ],
54 srcs: [
55 "a/b/*.h",
Jingwen Chendb120242021-02-23 00:46:47 -050056 "a/b/*.c"
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050057 ],
Jingwen Chendb120242021-02-23 00:46:47 -050058 exclude_srcs: ["a/b/exclude.c"],
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050059
60 bazel_module: { bp2build_available: true },
61}
62`,
63 expectedBazelTargets: []string{`cc_object(
64 name = "foo",
65 copts = [
66 "-fno-addrsig",
67 "-Wno-gcc-compat",
68 "-Wall",
69 "-Werror",
70 ],
71 local_include_dirs = [
72 "include",
Liz Kammera4aa4302021-03-18 16:56:36 -040073 ".",
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050074 ],
75 srcs = [
76 "a/b/bar.h",
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050077 "a/b/c.c",
Jingwen Chen07027912021-03-15 06:02:43 -040078 "a/b/foo.h",
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050079 ],
80)`,
81 },
82 },
83 {
84 description: "simple cc_object with defaults",
85 moduleTypeUnderTest: "cc_object",
86 moduleTypeUnderTestFactory: cc.ObjectFactory,
87 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
88 blueprint: `cc_object {
89 name: "foo",
90 local_include_dirs: ["include"],
91 srcs: [
92 "a/b/*.h",
93 "a/b/c.c"
94 ],
95
96 defaults: ["foo_defaults"],
97 bazel_module: { bp2build_available: true },
98}
99
100cc_defaults {
101 name: "foo_defaults",
102 defaults: ["foo_bar_defaults"],
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500103}
104
105cc_defaults {
106 name: "foo_bar_defaults",
107 cflags: [
108 "-Wno-gcc-compat",
109 "-Wall",
110 "-Werror",
111 ],
112}
113`,
114 expectedBazelTargets: []string{`cc_object(
115 name = "foo",
116 copts = [
117 "-Wno-gcc-compat",
118 "-Wall",
119 "-Werror",
120 "-fno-addrsig",
121 ],
122 local_include_dirs = [
123 "include",
Liz Kammera4aa4302021-03-18 16:56:36 -0400124 ".",
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500125 ],
126 srcs = [
127 "a/b/c.c",
128 ],
129)`,
130 },
131 },
Jingwen Chendb120242021-02-23 00:46:47 -0500132 {
133 description: "cc_object with cc_object deps in objs props",
134 moduleTypeUnderTest: "cc_object",
135 moduleTypeUnderTestFactory: cc.ObjectFactory,
136 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
137 filesystem: map[string]string{
138 "a/b/c.c": "",
139 "x/y/z.c": "",
140 },
141 blueprint: `cc_object {
142 name: "foo",
143 srcs: ["a/b/c.c"],
144 objs: ["bar"],
145
146 bazel_module: { bp2build_available: true },
147}
148
149cc_object {
150 name: "bar",
151 srcs: ["x/y/z.c"],
152
153 bazel_module: { bp2build_available: true },
154}
155`,
156 expectedBazelTargets: []string{`cc_object(
157 name = "bar",
158 copts = [
159 "-fno-addrsig",
160 ],
Liz Kammera4aa4302021-03-18 16:56:36 -0400161 local_include_dirs = [
162 ".",
163 ],
Jingwen Chendb120242021-02-23 00:46:47 -0500164 srcs = [
165 "x/y/z.c",
166 ],
167)`, `cc_object(
168 name = "foo",
169 copts = [
170 "-fno-addrsig",
171 ],
172 deps = [
173 ":bar",
174 ],
Liz Kammera4aa4302021-03-18 16:56:36 -0400175 local_include_dirs = [
176 ".",
177 ],
178 srcs = [
179 "a/b/c.c",
180 ],
181)`,
182 },
183 },
184 {
185 description: "cc_object with include_build_dir: false",
186 moduleTypeUnderTest: "cc_object",
187 moduleTypeUnderTestFactory: cc.ObjectFactory,
188 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
189 filesystem: map[string]string{
190 "a/b/c.c": "",
191 "x/y/z.c": "",
192 },
193 blueprint: `cc_object {
194 name: "foo",
195 srcs: ["a/b/c.c"],
196 include_build_directory: false,
197
198 bazel_module: { bp2build_available: true },
199}
200`,
201 expectedBazelTargets: []string{`cc_object(
202 name = "foo",
203 copts = [
204 "-fno-addrsig",
205 ],
Jingwen Chendb120242021-02-23 00:46:47 -0500206 srcs = [
207 "a/b/c.c",
208 ],
209)`,
210 },
211 },
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500212 }
213
214 dir := "."
215 for _, testCase := range testCases {
216 filesystem := make(map[string][]byte)
217 toParse := []string{
218 "Android.bp",
219 }
220 for f, content := range testCase.filesystem {
221 if strings.HasSuffix(f, "Android.bp") {
222 toParse = append(toParse, f)
223 }
224 filesystem[f] = []byte(content)
225 }
226 config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
227 ctx := android.NewTestContext(config)
228 // Always register cc_defaults module factory
229 ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
230
231 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
232 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
233 ctx.RegisterForBazelConversion()
234
235 _, errs := ctx.ParseFileList(dir, toParse)
236 if Errored(t, testCase.description, errs) {
237 continue
238 }
239 _, errs = ctx.ResolveDependencies(config)
240 if Errored(t, testCase.description, errs) {
241 continue
242 }
243
Jingwen Chen164e0862021-02-19 00:48:40 -0500244 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
Jingwen Chenba369ad2021-02-22 10:19:34 -0500245 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500246 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
247 fmt.Println(bazelTargets)
248 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
249 } else {
250 for i, target := range bazelTargets {
251 if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
252 t.Errorf(
253 "%s: Expected generated Bazel target to be '%s', got '%s'",
254 testCase.description,
255 w,
256 g,
257 )
258 }
259 }
260 }
261 }
262}
Jingwen Chen5d864492021-02-24 07:20:12 -0500263
264func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
265 testCases := []struct {
266 description string
267 moduleTypeUnderTest string
268 moduleTypeUnderTestFactory android.ModuleFactory
269 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
270 blueprint string
271 expectedBazelTargets []string
272 filesystem map[string]string
273 }{
274 {
275 description: "cc_object setting cflags for one arch",
276 moduleTypeUnderTest: "cc_object",
277 moduleTypeUnderTestFactory: cc.ObjectFactory,
278 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
279 blueprint: `cc_object {
280 name: "foo",
Jingwen Chen07027912021-03-15 06:02:43 -0400281 srcs: ["a.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500282 arch: {
283 x86: {
Jingwen Chen07027912021-03-15 06:02:43 -0400284 cflags: ["-fPIC"], // string list
285 },
286 arm: {
287 srcs: ["arch/arm/file.S"], // label list
Jingwen Chen5d864492021-02-24 07:20:12 -0500288 },
289 },
290 bazel_module: { bp2build_available: true },
291}
292`,
293 expectedBazelTargets: []string{
294 `cc_object(
295 name = "foo",
296 copts = [
297 "-fno-addrsig",
298 ] + select({
299 "@bazel_tools//platforms:x86_32": [
300 "-fPIC",
301 ],
Jingwen Chen07027912021-03-15 06:02:43 -0400302 "//conditions:default": [],
Jingwen Chen5d864492021-02-24 07:20:12 -0500303 }),
Liz Kammera4aa4302021-03-18 16:56:36 -0400304 local_include_dirs = [
305 ".",
306 ],
Jingwen Chen07027912021-03-15 06:02:43 -0400307 srcs = [
308 "a.cpp",
309 ] + select({
310 "@bazel_tools//platforms:arm": [
311 "arch/arm/file.S",
312 ],
313 "//conditions:default": [],
314 }),
Jingwen Chen5d864492021-02-24 07:20:12 -0500315)`,
316 },
317 },
318 {
319 description: "cc_object setting cflags for 4 architectures",
320 moduleTypeUnderTest: "cc_object",
321 moduleTypeUnderTestFactory: cc.ObjectFactory,
322 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
323 blueprint: `cc_object {
324 name: "foo",
Jingwen Chen07027912021-03-15 06:02:43 -0400325 srcs: ["base.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500326 arch: {
327 x86: {
Jingwen Chen07027912021-03-15 06:02:43 -0400328 srcs: ["x86.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500329 cflags: ["-fPIC"],
330 },
331 x86_64: {
Jingwen Chen07027912021-03-15 06:02:43 -0400332 srcs: ["x86_64.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500333 cflags: ["-fPIC"],
334 },
335 arm: {
Jingwen Chen07027912021-03-15 06:02:43 -0400336 srcs: ["arm.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500337 cflags: ["-Wall"],
338 },
339 arm64: {
Jingwen Chen07027912021-03-15 06:02:43 -0400340 srcs: ["arm64.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500341 cflags: ["-Wall"],
342 },
343 },
344 bazel_module: { bp2build_available: true },
345}
346`,
347 expectedBazelTargets: []string{
348 `cc_object(
349 name = "foo",
350 copts = [
351 "-fno-addrsig",
352 ] + select({
353 "@bazel_tools//platforms:arm": [
354 "-Wall",
355 ],
356 "@bazel_tools//platforms:aarch64": [
357 "-Wall",
358 ],
359 "@bazel_tools//platforms:x86_32": [
360 "-fPIC",
361 ],
362 "@bazel_tools//platforms:x86_64": [
363 "-fPIC",
364 ],
Jingwen Chen07027912021-03-15 06:02:43 -0400365 "//conditions:default": [],
Jingwen Chen5d864492021-02-24 07:20:12 -0500366 }),
Liz Kammera4aa4302021-03-18 16:56:36 -0400367 local_include_dirs = [
368 ".",
369 ],
Jingwen Chen07027912021-03-15 06:02:43 -0400370 srcs = [
371 "base.cpp",
372 ] + select({
373 "@bazel_tools//platforms:arm": [
374 "arm.cpp",
375 ],
376 "@bazel_tools//platforms:aarch64": [
377 "arm64.cpp",
378 ],
379 "@bazel_tools//platforms:x86_32": [
380 "x86.cpp",
381 ],
382 "@bazel_tools//platforms:x86_64": [
383 "x86_64.cpp",
384 ],
385 "//conditions:default": [],
386 }),
Jingwen Chen5d864492021-02-24 07:20:12 -0500387)`,
388 },
389 },
390 }
391
392 dir := "."
393 for _, testCase := range testCases {
394 filesystem := make(map[string][]byte)
395 toParse := []string{
396 "Android.bp",
397 }
398 config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
399 ctx := android.NewTestContext(config)
400 // Always register cc_defaults module factory
401 ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
402
403 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
404 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
405 ctx.RegisterForBazelConversion()
406
407 _, errs := ctx.ParseFileList(dir, toParse)
408 if Errored(t, testCase.description, errs) {
409 continue
410 }
411 _, errs = ctx.ResolveDependencies(config)
412 if Errored(t, testCase.description, errs) {
413 continue
414 }
415
416 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
417 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
418 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
419 fmt.Println(bazelTargets)
420 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
421 } else {
422 for i, target := range bazelTargets {
423 if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
424 t.Errorf(
425 "%s: Expected generated Bazel target to be '%s', got '%s'",
426 testCase.description,
427 w,
428 g,
429 )
430 }
431 }
432 }
433 }
434}