blob: a9d24ace08583b592555c5f93594e9b7319e3b11 [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: [
Jingwen Chendb120242021-02-23 00:46:47 -050055 "a/b/*.c"
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050056 ],
Jingwen Chendb120242021-02-23 00:46:47 -050057 exclude_srcs: ["a/b/exclude.c"],
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050058
59 bazel_module: { bp2build_available: true },
60}
61`,
62 expectedBazelTargets: []string{`cc_object(
63 name = "foo",
64 copts = [
65 "-fno-addrsig",
66 "-Wno-gcc-compat",
67 "-Wall",
68 "-Werror",
69 ],
Jingwen Chen63930982021-03-24 10:04:33 -040070 hdrs = [
71 "a/b/bar.h",
72 "a/b/foo.h",
73 ],
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050074 local_include_dirs = [
75 "include",
Liz Kammera4aa4302021-03-18 16:56:36 -040076 ".",
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050077 ],
Jingwen Chenb4628eb2021-04-08 14:40:57 +000078 srcs = ["a/b/c.c"],
Jingwen Chen8c1b97e2021-02-18 03:21:34 -050079)`,
80 },
81 },
82 {
83 description: "simple cc_object with defaults",
84 moduleTypeUnderTest: "cc_object",
85 moduleTypeUnderTestFactory: cc.ObjectFactory,
86 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
87 blueprint: `cc_object {
88 name: "foo",
89 local_include_dirs: ["include"],
90 srcs: [
91 "a/b/*.h",
92 "a/b/c.c"
93 ],
94
95 defaults: ["foo_defaults"],
96 bazel_module: { bp2build_available: true },
97}
98
99cc_defaults {
100 name: "foo_defaults",
101 defaults: ["foo_bar_defaults"],
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500102}
103
104cc_defaults {
105 name: "foo_bar_defaults",
106 cflags: [
107 "-Wno-gcc-compat",
108 "-Wall",
109 "-Werror",
110 ],
111}
112`,
113 expectedBazelTargets: []string{`cc_object(
114 name = "foo",
115 copts = [
116 "-Wno-gcc-compat",
117 "-Wall",
118 "-Werror",
119 "-fno-addrsig",
120 ],
121 local_include_dirs = [
122 "include",
Liz Kammera4aa4302021-03-18 16:56:36 -0400123 ".",
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500124 ],
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000125 srcs = ["a/b/c.c"],
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500126)`,
127 },
128 },
Jingwen Chendb120242021-02-23 00:46:47 -0500129 {
130 description: "cc_object with cc_object deps in objs props",
131 moduleTypeUnderTest: "cc_object",
132 moduleTypeUnderTestFactory: cc.ObjectFactory,
133 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
134 filesystem: map[string]string{
135 "a/b/c.c": "",
136 "x/y/z.c": "",
137 },
138 blueprint: `cc_object {
139 name: "foo",
140 srcs: ["a/b/c.c"],
141 objs: ["bar"],
142
143 bazel_module: { bp2build_available: true },
144}
145
146cc_object {
147 name: "bar",
148 srcs: ["x/y/z.c"],
149
150 bazel_module: { bp2build_available: true },
151}
152`,
153 expectedBazelTargets: []string{`cc_object(
154 name = "bar",
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000155 copts = ["-fno-addrsig"],
156 local_include_dirs = ["."],
157 srcs = ["x/y/z.c"],
Jingwen Chendb120242021-02-23 00:46:47 -0500158)`, `cc_object(
159 name = "foo",
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000160 copts = ["-fno-addrsig"],
161 deps = [":bar"],
162 local_include_dirs = ["."],
163 srcs = ["a/b/c.c"],
Liz Kammera4aa4302021-03-18 16:56:36 -0400164)`,
165 },
166 },
167 {
168 description: "cc_object with include_build_dir: false",
169 moduleTypeUnderTest: "cc_object",
170 moduleTypeUnderTestFactory: cc.ObjectFactory,
171 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
172 filesystem: map[string]string{
173 "a/b/c.c": "",
174 "x/y/z.c": "",
175 },
176 blueprint: `cc_object {
177 name: "foo",
178 srcs: ["a/b/c.c"],
179 include_build_directory: false,
180
181 bazel_module: { bp2build_available: true },
182}
183`,
184 expectedBazelTargets: []string{`cc_object(
185 name = "foo",
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000186 copts = ["-fno-addrsig"],
187 srcs = ["a/b/c.c"],
Jingwen Chendb120242021-02-23 00:46:47 -0500188)`,
189 },
190 },
Liz Kammera060c452021-03-24 10:14:47 -0400191 {
192 description: "cc_object with product variable",
193 moduleTypeUnderTest: "cc_object",
194 moduleTypeUnderTestFactory: cc.ObjectFactory,
195 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
196 blueprint: `cc_object {
197 name: "foo",
198 include_build_directory: false,
199 product_variables: {
200 platform_sdk_version: {
201 asflags: ["-DPLATFORM_SDK_VERSION=%d"],
202 },
203 },
204
205 bazel_module: { bp2build_available: true },
206}
207`,
208 expectedBazelTargets: []string{`cc_object(
209 name = "foo",
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000210 asflags = ["-DPLATFORM_SDK_VERSION={Platform_sdk_version}"],
211 copts = ["-fno-addrsig"],
Liz Kammera060c452021-03-24 10:14:47 -0400212)`,
213 },
214 },
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500215 }
216
217 dir := "."
218 for _, testCase := range testCases {
219 filesystem := make(map[string][]byte)
220 toParse := []string{
221 "Android.bp",
222 }
223 for f, content := range testCase.filesystem {
224 if strings.HasSuffix(f, "Android.bp") {
225 toParse = append(toParse, f)
226 }
227 filesystem[f] = []byte(content)
228 }
229 config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
230 ctx := android.NewTestContext(config)
231 // Always register cc_defaults module factory
232 ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
233
234 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
235 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
236 ctx.RegisterForBazelConversion()
237
238 _, errs := ctx.ParseFileList(dir, toParse)
239 if Errored(t, testCase.description, errs) {
240 continue
241 }
242 _, errs = ctx.ResolveDependencies(config)
243 if Errored(t, testCase.description, errs) {
244 continue
245 }
246
Jingwen Chen164e0862021-02-19 00:48:40 -0500247 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
Jingwen Chenba369ad2021-02-22 10:19:34 -0500248 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
Jingwen Chen8c1b97e2021-02-18 03:21:34 -0500249 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
250 fmt.Println(bazelTargets)
251 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
252 } else {
253 for i, target := range bazelTargets {
254 if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
255 t.Errorf(
256 "%s: Expected generated Bazel target to be '%s', got '%s'",
257 testCase.description,
258 w,
259 g,
260 )
261 }
262 }
263 }
264 }
265}
Jingwen Chen5d864492021-02-24 07:20:12 -0500266
267func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
268 testCases := []struct {
269 description string
270 moduleTypeUnderTest string
271 moduleTypeUnderTestFactory android.ModuleFactory
272 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
273 blueprint string
274 expectedBazelTargets []string
275 filesystem map[string]string
276 }{
277 {
278 description: "cc_object setting cflags for one arch",
279 moduleTypeUnderTest: "cc_object",
280 moduleTypeUnderTestFactory: cc.ObjectFactory,
281 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
282 blueprint: `cc_object {
283 name: "foo",
Jingwen Chen07027912021-03-15 06:02:43 -0400284 srcs: ["a.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500285 arch: {
286 x86: {
Jingwen Chen07027912021-03-15 06:02:43 -0400287 cflags: ["-fPIC"], // string list
288 },
289 arm: {
290 srcs: ["arch/arm/file.S"], // label list
Jingwen Chen5d864492021-02-24 07:20:12 -0500291 },
292 },
293 bazel_module: { bp2build_available: true },
294}
295`,
296 expectedBazelTargets: []string{
297 `cc_object(
298 name = "foo",
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000299 copts = ["-fno-addrsig"] + select({
300 "//build/bazel/platforms/arch:x86": ["-fPIC"],
Jingwen Chen07027912021-03-15 06:02:43 -0400301 "//conditions:default": [],
Jingwen Chen5d864492021-02-24 07:20:12 -0500302 }),
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000303 local_include_dirs = ["."],
304 srcs = ["a.cpp"] + select({
305 "//build/bazel/platforms/arch:arm": ["arch/arm/file.S"],
Jingwen Chen07027912021-03-15 06:02:43 -0400306 "//conditions:default": [],
307 }),
Jingwen Chen5d864492021-02-24 07:20:12 -0500308)`,
309 },
310 },
311 {
312 description: "cc_object setting cflags for 4 architectures",
313 moduleTypeUnderTest: "cc_object",
314 moduleTypeUnderTestFactory: cc.ObjectFactory,
315 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
316 blueprint: `cc_object {
317 name: "foo",
Jingwen Chen07027912021-03-15 06:02:43 -0400318 srcs: ["base.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500319 arch: {
320 x86: {
Jingwen Chen07027912021-03-15 06:02:43 -0400321 srcs: ["x86.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500322 cflags: ["-fPIC"],
323 },
324 x86_64: {
Jingwen Chen07027912021-03-15 06:02:43 -0400325 srcs: ["x86_64.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500326 cflags: ["-fPIC"],
327 },
328 arm: {
Jingwen Chen07027912021-03-15 06:02:43 -0400329 srcs: ["arm.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500330 cflags: ["-Wall"],
331 },
332 arm64: {
Jingwen Chen07027912021-03-15 06:02:43 -0400333 srcs: ["arm64.cpp"],
Jingwen Chen5d864492021-02-24 07:20:12 -0500334 cflags: ["-Wall"],
335 },
336 },
337 bazel_module: { bp2build_available: true },
338}
339`,
340 expectedBazelTargets: []string{
341 `cc_object(
342 name = "foo",
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000343 copts = ["-fno-addrsig"] + select({
344 "//build/bazel/platforms/arch:arm": ["-Wall"],
345 "//build/bazel/platforms/arch:arm64": ["-Wall"],
346 "//build/bazel/platforms/arch:x86": ["-fPIC"],
347 "//build/bazel/platforms/arch:x86_64": ["-fPIC"],
Jingwen Chen07027912021-03-15 06:02:43 -0400348 "//conditions:default": [],
Jingwen Chen5d864492021-02-24 07:20:12 -0500349 }),
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000350 local_include_dirs = ["."],
351 srcs = ["base.cpp"] + select({
352 "//build/bazel/platforms/arch:arm": ["arm.cpp"],
353 "//build/bazel/platforms/arch:arm64": ["arm64.cpp"],
354 "//build/bazel/platforms/arch:x86": ["x86.cpp"],
355 "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
Jingwen Chen07027912021-03-15 06:02:43 -0400356 "//conditions:default": [],
357 }),
Jingwen Chen5d864492021-02-24 07:20:12 -0500358)`,
359 },
360 },
Jingwen Chenc1c26502021-04-05 10:35:13 +0000361 {
362 description: "cc_object setting cflags for multiple OSes",
363 moduleTypeUnderTest: "cc_object",
364 moduleTypeUnderTestFactory: cc.ObjectFactory,
365 moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
366 blueprint: `cc_object {
367 name: "foo",
368 srcs: ["base.cpp"],
369 target: {
370 android: {
371 cflags: ["-fPIC"],
372 },
373 windows: {
374 cflags: ["-fPIC"],
375 },
376 darwin: {
377 cflags: ["-Wall"],
378 },
379 },
380 bazel_module: { bp2build_available: true },
381}
382`,
383 expectedBazelTargets: []string{
384 `cc_object(
385 name = "foo",
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000386 copts = ["-fno-addrsig"] + select({
387 "//build/bazel/platforms/os:android": ["-fPIC"],
388 "//build/bazel/platforms/os:darwin": ["-Wall"],
389 "//build/bazel/platforms/os:windows": ["-fPIC"],
Jingwen Chenc1c26502021-04-05 10:35:13 +0000390 "//conditions:default": [],
391 }),
Jingwen Chenb4628eb2021-04-08 14:40:57 +0000392 local_include_dirs = ["."],
393 srcs = ["base.cpp"],
Jingwen Chenc1c26502021-04-05 10:35:13 +0000394)`,
395 },
396 },
Jingwen Chen5d864492021-02-24 07:20:12 -0500397 }
398
399 dir := "."
400 for _, testCase := range testCases {
401 filesystem := make(map[string][]byte)
402 toParse := []string{
403 "Android.bp",
404 }
405 config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
406 ctx := android.NewTestContext(config)
407 // Always register cc_defaults module factory
408 ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
409
410 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
411 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
412 ctx.RegisterForBazelConversion()
413
414 _, errs := ctx.ParseFileList(dir, toParse)
415 if Errored(t, testCase.description, errs) {
416 continue
417 }
418 _, errs = ctx.ResolveDependencies(config)
419 if Errored(t, testCase.description, errs) {
420 continue
421 }
422
423 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
424 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
425 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
426 fmt.Println(bazelTargets)
427 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
428 } else {
429 for i, target := range bazelTargets {
430 if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
431 t.Errorf(
432 "%s: Expected generated Bazel target to be '%s', got '%s'",
433 testCase.description,
434 w,
435 g,
436 )
437 }
438 }
439 }
440 }
441}