blob: 0b71d89c483981cd3401b2af516cfe8cd24c7a8a [file] [log] [blame]
Liz Kammer2b8004b2021-10-04 13:55:44 -04001// 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"
Liz Kammere6583482021-10-19 13:56:10 -040020 "android/soong/genrule"
Liz Kammer2b8004b2021-10-04 13:55:44 -040021 "fmt"
22 "strings"
23 "testing"
24)
25
26const (
27 ccBinaryTypePlaceHolder = "{rule_name}"
28 compatibleWithPlaceHolder = "{target_compatible_with}"
29)
30
31func registerCcBinaryModuleTypes(ctx android.RegistrationContext) {
32 cc.RegisterCCBuildComponents(ctx)
33 ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
34 ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
35 ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
Liz Kammere6583482021-10-19 13:56:10 -040036 ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
Liz Kammer2b8004b2021-10-04 13:55:44 -040037}
38
39var binaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary", compatibleWithPlaceHolder, "")
40var hostBinaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary_host", compatibleWithPlaceHolder, `
41 target_compatible_with = select({
42 "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
43 "//conditions:default": [],
44 }),`)
45
46func runCcBinaryTests(t *testing.T, tc bp2buildTestCase) {
47 t.Helper()
48 runCcBinaryTestCase(t, tc)
49 runCcHostBinaryTestCase(t, tc)
50}
51
52func runCcBinaryTestCase(t *testing.T, tc bp2buildTestCase) {
53 t.Helper()
54 testCase := tc
55 testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...)
56 testCase.moduleTypeUnderTest = "cc_binary"
57 testCase.moduleTypeUnderTestFactory = cc.BinaryFactory
58 testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryBp2build
59 testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description)
60 testCase.blueprint = binaryReplacer.Replace(testCase.blueprint)
61 for i, et := range testCase.expectedBazelTargets {
62 testCase.expectedBazelTargets[i] = binaryReplacer.Replace(et)
63 }
64 t.Run(testCase.description, func(t *testing.T) {
65 runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase)
66 })
67}
68
69func runCcHostBinaryTestCase(t *testing.T, tc bp2buildTestCase) {
70 t.Helper()
71 testCase := tc
72 testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...)
73 testCase.moduleTypeUnderTest = "cc_binary_host"
74 testCase.moduleTypeUnderTestFactory = cc.BinaryHostFactory
75 testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryHostBp2build
76 testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description)
77 testCase.blueprint = hostBinaryReplacer.Replace(testCase.blueprint)
78 for i, et := range testCase.expectedBazelTargets {
79 testCase.expectedBazelTargets[i] = hostBinaryReplacer.Replace(et)
80 }
81 t.Run(testCase.description, func(t *testing.T) {
82 runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase)
83 })
84}
85
86func TestBasicCcBinary(t *testing.T) {
87 runCcBinaryTests(t, bp2buildTestCase{
88 description: "basic -- properties -> attrs with little/no transformation",
89 blueprint: `
90{rule_name} {
91 name: "foo",
92 srcs: ["a.cc"],
93 local_include_dirs: ["dir"],
94 include_dirs: ["absolute_dir"],
95 cflags: ["-Dcopt"],
96 cppflags: ["-Dcppflag"],
97 conlyflags: ["-Dconlyflag"],
98 asflags: ["-Dasflag"],
99 ldflags: ["ld-flag"],
100 rtti: true,
101 strip: {
102 all: true,
103 keep_symbols: true,
104 keep_symbols_and_debug_frame: true,
105 keep_symbols_list: ["symbol"],
106 none: true,
107 },
108}
109`,
110 expectedBazelTargets: []string{`cc_binary(
111 name = "foo",
112 absolute_includes = ["absolute_dir"],
113 asflags = ["-Dasflag"],
114 conlyflags = ["-Dconlyflag"],
115 copts = ["-Dcopt"],
116 cppflags = ["-Dcppflag"],
117 linkopts = ["ld-flag"],
118 local_includes = [
119 "dir",
120 ".",
121 ],
122 rtti = True,
123 srcs = ["a.cc"],
124 strip = {
125 "all": True,
126 "keep_symbols": True,
127 "keep_symbols_and_debug_frame": True,
128 "keep_symbols_list": ["symbol"],
129 "none": True,
130 },{target_compatible_with}
131)`},
132 })
133}
134
135func TestCcBinaryWithSharedLdflagDisableFeature(t *testing.T) {
136 runCcBinaryTests(t, bp2buildTestCase{
137 description: `ldflag "-shared" disables static_flag feature`,
138 blueprint: `
139{rule_name} {
140 name: "foo",
141 ldflags: ["-shared"],
142 include_build_directory: false,
143}
144`,
145 expectedBazelTargets: []string{`cc_binary(
146 name = "foo",
147 features = ["-static_flag"],
148 linkopts = ["-shared"],{target_compatible_with}
149)`},
150 })
151}
152
153func TestCcBinaryWithLinkStatic(t *testing.T) {
154 runCcBinaryTests(t, bp2buildTestCase{
155 description: "link static",
156 blueprint: `
157{rule_name} {
158 name: "foo",
159 static_executable: true,
160 include_build_directory: false,
161}
162`,
163 expectedBazelTargets: []string{`cc_binary(
164 name = "foo",
165 linkshared = False,{target_compatible_with}
166)`},
167 })
168}
169
170func TestCcBinaryVersionScript(t *testing.T) {
171 runCcBinaryTests(t, bp2buildTestCase{
172 description: `version script`,
173 blueprint: `
174{rule_name} {
175 name: "foo",
176 include_build_directory: false,
177 version_script: "vs",
178}
179`,
180 expectedBazelTargets: []string{`cc_binary(
181 name = "foo",
182 additional_linker_inputs = ["vs"],
183 linkopts = ["-Wl,--version-script,$(location vs)"],{target_compatible_with}
184)`},
185 })
186}
187
188func TestCcBinarySplitSrcsByLang(t *testing.T) {
189 runCcHostBinaryTestCase(t, bp2buildTestCase{
190 description: "split srcs by lang",
191 blueprint: `
192{rule_name} {
193 name: "foo",
194 srcs: [
195 "asonly.S",
196 "conly.c",
197 "cpponly.cpp",
198 ":fg_foo",
199 ],
200 include_build_directory: false,
201}
202` + simpleModuleDoNotConvertBp2build("filegroup", "fg_foo"),
203 expectedBazelTargets: []string{`cc_binary(
204 name = "foo",
205 srcs = [
206 "cpponly.cpp",
207 ":fg_foo_cpp_srcs",
208 ],
209 srcs_as = [
210 "asonly.S",
211 ":fg_foo_as_srcs",
212 ],
213 srcs_c = [
214 "conly.c",
215 ":fg_foo_c_srcs",
216 ],{target_compatible_with}
217)`},
218 })
219}
220
221func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) {
222 runCcBinaryTestCase(t, bp2buildTestCase{
223 description: "no implementation deps",
224 blueprint: `
Liz Kammere6583482021-10-19 13:56:10 -0400225genrule {
226 name: "generated_hdr",
227 cmd: "nothing to see here",
228}
229
230genrule {
231 name: "export_generated_hdr",
232 cmd: "nothing to see here",
233}
234
Liz Kammer2b8004b2021-10-04 13:55:44 -0400235{rule_name} {
236 name: "foo",
Liz Kammere6583482021-10-19 13:56:10 -0400237 srcs: ["foo.cpp"],
Liz Kammer2b8004b2021-10-04 13:55:44 -0400238 shared_libs: ["implementation_shared_dep", "shared_dep"],
239 export_shared_lib_headers: ["shared_dep"],
240 static_libs: ["implementation_static_dep", "static_dep"],
241 export_static_lib_headers: ["static_dep", "whole_static_dep"],
242 whole_static_libs: ["not_explicitly_exported_whole_static_dep", "whole_static_dep"],
243 include_build_directory: false,
Liz Kammere6583482021-10-19 13:56:10 -0400244 generated_headers: ["generated_hdr", "export_generated_hdr"],
245 export_generated_headers: ["export_generated_hdr"],
Liz Kammer2b8004b2021-10-04 13:55:44 -0400246}
247` +
248 simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep") +
249 simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep") +
250 simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep") +
251 simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") +
252 simpleModuleDoNotConvertBp2build("cc_library", "shared_dep") +
253 simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"),
254 expectedBazelTargets: []string{`cc_binary(
255 name = "foo",
256 deps = [
257 ":implementation_static_dep",
258 ":static_dep",
259 ],
260 dynamic_deps = [
261 ":implementation_shared_dep",
262 ":shared_dep",
Liz Kammere6583482021-10-19 13:56:10 -0400263 ],
264 srcs = [
265 "foo.cpp",
266 ":generated_hdr",
267 ":export_generated_hdr",
Liz Kammer2b8004b2021-10-04 13:55:44 -0400268 ],{target_compatible_with}
269 whole_archive_deps = [
270 ":not_explicitly_exported_whole_static_dep",
271 ":whole_static_dep",
272 ],
273)`},
274 })
275}
276
277func TestCcBinaryNocrtTests(t *testing.T) {
278 baseTestCases := []struct {
279 description string
280 soongProperty string
281 bazelAttr string
282 }{
283 {
284 description: "nocrt: true",
285 soongProperty: `nocrt: true,`,
286 bazelAttr: ` link_crt = False,`,
287 },
288 {
289 description: "nocrt: false",
290 soongProperty: `nocrt: false,`,
291 },
292 {
293 description: "nocrt: not set",
294 },
295 }
296
297 baseBlueprint := `{rule_name} {
298 name: "foo",%s
299 include_build_directory: false,
300}
301`
302
303 baseBazelTarget := `cc_binary(
304 name = "foo",%s{target_compatible_with}
305)`
306
307 for _, btc := range baseTestCases {
308 prop := btc.soongProperty
309 if len(prop) > 0 {
310 prop = "\n" + prop
311 }
312 attr := btc.bazelAttr
313 if len(attr) > 0 {
314 attr = "\n" + attr
315 }
316 runCcBinaryTests(t, bp2buildTestCase{
317 description: btc.description,
318 blueprint: fmt.Sprintf(baseBlueprint, prop),
319 expectedBazelTargets: []string{
320 fmt.Sprintf(baseBazelTarget, attr),
321 },
322 })
323 }
324}
325
326func TestCcBinaryNo_libcrtTests(t *testing.T) {
327 baseTestCases := []struct {
328 description string
329 soongProperty string
330 bazelAttr string
331 }{
332 {
333 description: "no_libcrt: true",
334 soongProperty: `no_libcrt: true,`,
335 bazelAttr: ` use_libcrt = False,`,
336 },
337 {
338 description: "no_libcrt: false",
339 soongProperty: `no_libcrt: false,`,
340 bazelAttr: ` use_libcrt = True,`,
341 },
342 {
343 description: "no_libcrt: not set",
344 },
345 }
346
347 baseBlueprint := `{rule_name} {
348 name: "foo",%s
349 include_build_directory: false,
350}
351`
352
353 baseBazelTarget := `cc_binary(
354 name = "foo",{target_compatible_with}%s
355)`
356
357 for _, btc := range baseTestCases {
358 prop := btc.soongProperty
359 if len(prop) > 0 {
360 prop = "\n" + prop
361 }
362 attr := btc.bazelAttr
363 if len(attr) > 0 {
364 attr = "\n" + attr
365 }
366 runCcBinaryTests(t, bp2buildTestCase{
367 description: btc.description,
368 blueprint: fmt.Sprintf(baseBlueprint, prop),
369 expectedBazelTargets: []string{
370 fmt.Sprintf(baseBazelTarget, attr),
371 },
372 })
373 }
374}
375
376func TestCcBinaryPropertiesToFeatures(t *testing.T) {
377 baseTestCases := []struct {
378 description string
379 soongProperty string
380 bazelAttr string
381 }{
382 {
383 description: "pack_relocation: true",
384 soongProperty: `pack_relocations: true,`,
385 },
386 {
387 description: "pack_relocations: false",
388 soongProperty: `pack_relocations: false,`,
389 bazelAttr: ` features = ["disable_pack_relocations"],`,
390 },
391 {
392 description: "pack_relocations: not set",
393 },
394 {
395 description: "pack_relocation: true",
396 soongProperty: `allow_undefined_symbols: true,`,
397 bazelAttr: ` features = ["-no_undefined_symbols"],`,
398 },
399 {
400 description: "allow_undefined_symbols: false",
401 soongProperty: `allow_undefined_symbols: false,`,
402 },
403 {
404 description: "allow_undefined_symbols: not set",
405 },
406 }
407
408 baseBlueprint := `{rule_name} {
409 name: "foo",%s
410 include_build_directory: false,
411}
412`
413
414 baseBazelTarget := `cc_binary(
415 name = "foo",%s{target_compatible_with}
416)`
417
418 for _, btc := range baseTestCases {
419 prop := btc.soongProperty
420 if len(prop) > 0 {
421 prop = "\n" + prop
422 }
423 attr := btc.bazelAttr
424 if len(attr) > 0 {
425 attr = "\n" + attr
426 }
427 runCcBinaryTests(t, bp2buildTestCase{
428 description: btc.description,
429 blueprint: fmt.Sprintf(baseBlueprint, prop),
430 expectedBazelTargets: []string{
431 fmt.Sprintf(baseBazelTarget, attr),
432 },
433 })
434 }
435}