blob: 6a148a8a392e4e4dada44490236e709fe969715c [file] [log] [blame]
Jingwen Chen63930982021-03-24 10:04:33 -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"
20 "strings"
21 "testing"
22)
23
24const (
25 // See cc/testing.go for more context
26 soongCcLibraryPreamble = `
27cc_defaults {
28 name: "linux_bionic_supported",
29}
30
31toolchain_library {
32 name: "libclang_rt.builtins-x86_64-android",
33 defaults: ["linux_bionic_supported"],
34 vendor_available: true,
35 vendor_ramdisk_available: true,
36 product_available: true,
37 recovery_available: true,
38 native_bridge_supported: true,
39 src: "",
40}`
41)
42
43func TestCcLibraryBp2Build(t *testing.T) {
44 testCases := []struct {
45 description string
46 moduleTypeUnderTest string
47 moduleTypeUnderTestFactory android.ModuleFactory
48 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
49 bp string
50 expectedBazelTargets []string
51 filesystem map[string]string
52 dir string
53 }{
54 {
55 description: "cc_library - simple example",
56 moduleTypeUnderTest: "cc_library",
57 moduleTypeUnderTestFactory: cc.LibraryFactory,
58 moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
59 filesystem: map[string]string{
60 "android.cpp": "",
61 "darwin.cpp": "",
62 // Refer to cc.headerExts for the supported header extensions in Soong.
63 "header.h": "",
64 "header.hh": "",
65 "header.hpp": "",
66 "header.hxx": "",
67 "header.h++": "",
68 "header.inl": "",
69 "header.inc": "",
70 "header.ipp": "",
71 "header.h.generic": "",
72 "impl.cpp": "",
73 "linux.cpp": "",
74 "x86.cpp": "",
75 "x86_64.cpp": "",
76 "foo-dir/a.h": "",
77 },
78 bp: soongCcLibraryPreamble + `
79cc_library_headers { name: "some-headers" }
80cc_library {
81 name: "foo-lib",
82 srcs: ["impl.cpp"],
83 cflags: ["-Wall"],
84 header_libs: ["some-headers"],
85 export_include_dirs: ["foo-dir"],
86 ldflags: ["-Wl,--exclude-libs=bar.a"],
87 arch: {
88 x86: {
89 ldflags: ["-Wl,--exclude-libs=baz.a"],
90 srcs: ["x86.cpp"],
91 },
92 x86_64: {
93 ldflags: ["-Wl,--exclude-libs=qux.a"],
94 srcs: ["x86_64.cpp"],
95 },
96 },
97 target: {
98 android: {
99 srcs: ["android.cpp"],
100 },
101 linux_glibc: {
102 srcs: ["linux.cpp"],
103 },
104 darwin: {
105 srcs: ["darwin.cpp"],
106 },
107 },
108}
109`,
110 expectedBazelTargets: []string{`cc_library(
111 name = "foo-lib",
112 copts = [
113 "-Wall",
114 ],
115 deps = [
116 ":some-headers",
117 ],
118 hdrs = [
119 "header.h",
120 "header.hh",
121 "header.hpp",
122 "header.hxx",
123 "header.h++",
124 "header.inl",
125 "header.inc",
126 "header.ipp",
127 "header.h.generic",
128 "foo-dir/a.h",
129 ],
130 includes = [
131 "foo-dir",
132 ],
133 linkopts = [
134 "-Wl,--exclude-libs=bar.a",
135 ] + select({
136 "//build/bazel/platforms/arch:x86": [
137 "-Wl,--exclude-libs=baz.a",
138 ],
139 "//build/bazel/platforms/arch:x86_64": [
140 "-Wl,--exclude-libs=qux.a",
141 ],
142 "//conditions:default": [],
143 }),
144 srcs = [
145 "impl.cpp",
146 ] + select({
147 "//build/bazel/platforms/arch:x86": [
148 "x86.cpp",
149 ],
150 "//build/bazel/platforms/arch:x86_64": [
151 "x86_64.cpp",
152 ],
153 "//conditions:default": [],
154 }) + select({
155 "//build/bazel/platforms/os:android": [
156 "android.cpp",
157 ],
158 "//build/bazel/platforms/os:darwin": [
159 "darwin.cpp",
160 ],
161 "//build/bazel/platforms/os:linux": [
162 "linux.cpp",
163 ],
164 "//conditions:default": [],
165 }),
166)`},
167 },
168 {
169 description: "cc_library - trimmed example of //bionic/linker:ld-android",
170 moduleTypeUnderTest: "cc_library",
171 moduleTypeUnderTestFactory: cc.LibraryFactory,
172 moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
173 filesystem: map[string]string{
174 "ld-android.cpp": "",
175 "linked_list.h": "",
176 "linker.h": "",
177 "linker_block_allocator.h": "",
178 "linker_cfi.h": "",
179 },
180 bp: soongCcLibraryPreamble + `
181cc_library_headers { name: "libc_headers" }
182cc_library {
183 name: "fake-ld-android",
184 srcs: ["ld_android.cpp"],
185 cflags: [
186 "-Wall",
187 "-Wextra",
188 "-Wunused",
189 "-Werror",
190 ],
191 header_libs: ["libc_headers"],
192 ldflags: [
193 "-Wl,--exclude-libs=libgcc.a",
194 "-Wl,--exclude-libs=libgcc_stripped.a",
195 "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
196 "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
197 "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
198 "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
199 ],
200 arch: {
201 x86: {
202 ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
203 },
204 x86_64: {
205 ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
206 },
207 },
208}
209`,
210 expectedBazelTargets: []string{`cc_library(
211 name = "fake-ld-android",
212 copts = [
213 "-Wall",
214 "-Wextra",
215 "-Wunused",
216 "-Werror",
217 ],
218 deps = [
219 ":libc_headers",
220 ],
221 hdrs = [
222 "linked_list.h",
223 "linker.h",
224 "linker_block_allocator.h",
225 "linker_cfi.h",
226 ],
227 linkopts = [
228 "-Wl,--exclude-libs=libgcc.a",
229 "-Wl,--exclude-libs=libgcc_stripped.a",
230 "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
231 "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
232 "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
233 "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
234 ] + select({
235 "//build/bazel/platforms/arch:x86": [
236 "-Wl,--exclude-libs=libgcc_eh.a",
237 ],
238 "//build/bazel/platforms/arch:x86_64": [
239 "-Wl,--exclude-libs=libgcc_eh.a",
240 ],
241 "//conditions:default": [],
242 }),
243 srcs = [
244 "ld_android.cpp",
245 ],
246)`},
247 },
248 }
249
250 dir := "."
251 for _, testCase := range testCases {
252 filesystem := make(map[string][]byte)
253 toParse := []string{
254 "Android.bp",
255 }
256 for f, content := range testCase.filesystem {
257 if strings.HasSuffix(f, "Android.bp") {
258 toParse = append(toParse, f)
259 }
260 filesystem[f] = []byte(content)
261 }
262 config := android.TestConfig(buildDir, nil, testCase.bp, filesystem)
263 ctx := android.NewTestContext(config)
264
265 cc.RegisterCCBuildComponents(ctx)
266 ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
267 ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
268 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
269 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
270 ctx.RegisterBp2BuildConfig(bp2buildConfig) // TODO(jingwen): make this the default for all tests
271 ctx.RegisterForBazelConversion()
272
273 _, errs := ctx.ParseFileList(dir, toParse)
274 if Errored(t, testCase.description, errs) {
275 continue
276 }
277 _, errs = ctx.ResolveDependencies(config)
278 if Errored(t, testCase.description, errs) {
279 continue
280 }
281
282 checkDir := dir
283 if testCase.dir != "" {
284 checkDir = testCase.dir
285 }
286 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
287 bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
288 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
289 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
290 } else {
291 for i, target := range bazelTargets {
292 if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
293 t.Errorf(
294 "%s: Expected generated Bazel target to be '%s', got '%s'",
295 testCase.description,
296 w,
297 g,
298 )
299 }
300 }
301 }
302 }
303}