• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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	"testing"
19
20	"android/soong/android"
21	"android/soong/cc"
22)
23
24func registerCcObjectModuleTypes(ctx android.RegistrationContext) {
25	// Always register cc_defaults module factory
26	ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
27	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
28}
29
30func runCcObjectTestCase(t *testing.T, tc Bp2buildTestCase) {
31	t.Helper()
32	(&tc).ModuleTypeUnderTest = "cc_object"
33	(&tc).ModuleTypeUnderTestFactory = cc.ObjectFactory
34	RunBp2BuildTestCase(t, registerCcObjectModuleTypes, tc)
35}
36
37func TestCcObjectSimple(t *testing.T) {
38	runCcObjectTestCase(t, Bp2buildTestCase{
39		Description: "simple cc_object generates cc_object with include header dep",
40		Filesystem: map[string]string{
41			"a/b/foo.h":     "",
42			"a/b/bar.h":     "",
43			"a/b/exclude.c": "",
44			"a/b/c.c":       "",
45		},
46		Blueprint: `cc_object {
47    name: "foo",
48    local_include_dirs: ["include"],
49    system_shared_libs: [],
50    cflags: [
51        "-Wno-gcc-compat",
52        "-Wall",
53        "-Werror",
54    ],
55    srcs: [
56        "a/b/*.c"
57    ],
58    exclude_srcs: ["a/b/exclude.c"],
59    sdk_version: "current",
60    min_sdk_version: "29",
61	crt: true,
62}
63`,
64		ExpectedBazelTargets: []string{
65			MakeBazelTarget("cc_object", "foo", AttrNameToString{
66				"copts": `[
67        "-fno-addrsig",
68        "-Wno-gcc-compat",
69        "-Wall",
70        "-Werror",
71    ]`,
72				"local_includes": `[
73        "include",
74        ".",
75    ]`,
76				"srcs":                `["a/b/c.c"]`,
77				"system_dynamic_deps": `[]`,
78				"sdk_version":         `"current"`,
79				"min_sdk_version":     `"29"`,
80				"crt":                 "True",
81			}),
82		},
83	})
84}
85
86func TestCcObjectDefaults(t *testing.T) {
87	runCcObjectTestCase(t, Bp2buildTestCase{
88		Blueprint: `cc_object {
89    name: "foo",
90    system_shared_libs: [],
91    srcs: [
92        "a/b/*.h",
93        "a/b/c.c"
94    ],
95
96    defaults: ["foo_defaults"],
97}
98
99cc_defaults {
100    name: "foo_defaults",
101    defaults: ["foo_bar_defaults"],
102}
103
104cc_defaults {
105    name: "foo_bar_defaults",
106    cflags: [
107        "-Werror",
108    ],
109}
110`,
111		ExpectedBazelTargets: []string{
112			MakeBazelTarget("cc_object", "foo", AttrNameToString{
113				"copts": `[
114        "-Werror",
115        "-fno-addrsig",
116    ]`,
117				"local_includes":      `["."]`,
118				"srcs":                `["a/b/c.c"]`,
119				"system_dynamic_deps": `[]`,
120			}),
121		}})
122}
123
124func TestCcObjectCcObjetDepsInObjs(t *testing.T) {
125	runCcObjectTestCase(t, Bp2buildTestCase{
126		Description: "cc_object with cc_object deps in objs props",
127		Filesystem: map[string]string{
128			"a/b/c.c": "",
129			"x/y/z.c": "",
130		},
131		Blueprint: `cc_object {
132    name: "foo",
133    system_shared_libs: [],
134    srcs: ["a/b/c.c"],
135    objs: ["bar"],
136    include_build_directory: false,
137}
138
139cc_object {
140    name: "bar",
141    system_shared_libs: [],
142    srcs: ["x/y/z.c"],
143    include_build_directory: false,
144}
145`,
146		ExpectedBazelTargets: []string{
147			MakeBazelTarget("cc_object", "bar", AttrNameToString{
148				"copts":               `["-fno-addrsig"]`,
149				"srcs":                `["x/y/z.c"]`,
150				"system_dynamic_deps": `[]`,
151			}), MakeBazelTarget("cc_object", "foo", AttrNameToString{
152				"copts":               `["-fno-addrsig"]`,
153				"objs":                `[":bar"]`,
154				"srcs":                `["a/b/c.c"]`,
155				"system_dynamic_deps": `[]`,
156			}),
157		},
158	})
159}
160
161func TestCcObjectIncludeBuildDirFalse(t *testing.T) {
162	runCcObjectTestCase(t, Bp2buildTestCase{
163		Description: "cc_object with include_build_dir: false",
164		Filesystem: map[string]string{
165			"a/b/c.c": "",
166			"x/y/z.c": "",
167		},
168		Blueprint: `cc_object {
169    name: "foo",
170    system_shared_libs: [],
171    srcs: ["a/b/c.c"],
172    include_build_directory: false,
173}
174`,
175		ExpectedBazelTargets: []string{
176			MakeBazelTarget("cc_object", "foo", AttrNameToString{
177				"copts":               `["-fno-addrsig"]`,
178				"srcs":                `["a/b/c.c"]`,
179				"system_dynamic_deps": `[]`,
180			}),
181		},
182	})
183}
184
185func TestCcObjectProductVariable(t *testing.T) {
186	runCcObjectTestCase(t, Bp2buildTestCase{
187		Description: "cc_object with product variable",
188		Blueprint: `cc_object {
189    name: "foo",
190    system_shared_libs: [],
191    include_build_directory: false,
192    product_variables: {
193        platform_sdk_version: {
194            asflags: ["-DPLATFORM_SDK_VERSION=%d"],
195        },
196    },
197    srcs: ["src.S"],
198}
199`,
200		ExpectedBazelTargets: []string{
201			MakeBazelTarget("cc_object", "foo", AttrNameToString{
202				"asflags": `select({
203        "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
204        "//conditions:default": [],
205    })`,
206				"copts":               `["-fno-addrsig"]`,
207				"srcs_as":             `["src.S"]`,
208				"system_dynamic_deps": `[]`,
209			}),
210		},
211	})
212}
213
214func TestCcObjectCflagsOneArch(t *testing.T) {
215	runCcObjectTestCase(t, Bp2buildTestCase{
216		Description: "cc_object setting cflags for one arch",
217		Blueprint: `cc_object {
218    name: "foo",
219    system_shared_libs: [],
220    srcs: ["a.cpp"],
221    arch: {
222        x86: {
223            cflags: ["-fPIC"], // string list
224        },
225        arm: {
226            srcs: ["arch/arm/file.cpp"], // label list
227        },
228    },
229    include_build_directory: false,
230}
231`,
232		ExpectedBazelTargets: []string{
233			MakeBazelTarget("cc_object", "foo", AttrNameToString{
234				"copts": `["-fno-addrsig"] + select({
235        "//build/bazel/platforms/arch:x86": ["-fPIC"],
236        "//conditions:default": [],
237    })`,
238				"srcs": `["a.cpp"] + select({
239        "//build/bazel/platforms/arch:arm": ["arch/arm/file.cpp"],
240        "//conditions:default": [],
241    })`,
242				"system_dynamic_deps": `[]`,
243			}),
244		},
245	})
246}
247
248func TestCcObjectCflagsFourArch(t *testing.T) {
249	runCcObjectTestCase(t, Bp2buildTestCase{
250		Description: "cc_object setting cflags for 4 architectures",
251		Blueprint: `cc_object {
252    name: "foo",
253    system_shared_libs: [],
254    srcs: ["base.cpp"],
255    arch: {
256        x86: {
257            srcs: ["x86.cpp"],
258            cflags: ["-fPIC"],
259        },
260        x86_64: {
261            srcs: ["x86_64.cpp"],
262            cflags: ["-fPIC"],
263        },
264        arm: {
265            srcs: ["arm.cpp"],
266            cflags: ["-Wall"],
267        },
268        arm64: {
269            srcs: ["arm64.cpp"],
270            cflags: ["-Wall"],
271        },
272    },
273    include_build_directory: false,
274}
275`,
276		ExpectedBazelTargets: []string{
277			MakeBazelTarget("cc_object", "foo", AttrNameToString{
278				"copts": `["-fno-addrsig"] + select({
279        "//build/bazel/platforms/arch:arm": ["-Wall"],
280        "//build/bazel/platforms/arch:arm64": ["-Wall"],
281        "//build/bazel/platforms/arch:x86": ["-fPIC"],
282        "//build/bazel/platforms/arch:x86_64": ["-fPIC"],
283        "//conditions:default": [],
284    })`,
285				"srcs": `["base.cpp"] + select({
286        "//build/bazel/platforms/arch:arm": ["arm.cpp"],
287        "//build/bazel/platforms/arch:arm64": ["arm64.cpp"],
288        "//build/bazel/platforms/arch:x86": ["x86.cpp"],
289        "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
290        "//conditions:default": [],
291    })`,
292				"system_dynamic_deps": `[]`,
293			}),
294		},
295	})
296}
297
298func TestCcObjectLinkerScript(t *testing.T) {
299	runCcObjectTestCase(t, Bp2buildTestCase{
300		Description: "cc_object setting linker_script",
301		Blueprint: `cc_object {
302    name: "foo",
303    srcs: ["base.cpp"],
304    linker_script: "bunny.lds",
305    include_build_directory: false,
306}
307`,
308		ExpectedBazelTargets: []string{
309			MakeBazelTarget("cc_object", "foo", AttrNameToString{
310				"copts":         `["-fno-addrsig"]`,
311				"linker_script": `"bunny.lds"`,
312				"srcs":          `["base.cpp"]`,
313			}),
314		},
315	})
316}
317
318func TestCcObjectDepsAndLinkerScriptSelects(t *testing.T) {
319	runCcObjectTestCase(t, Bp2buildTestCase{
320		Description: "cc_object setting deps and linker_script across archs",
321		Blueprint: `cc_object {
322    name: "foo",
323    srcs: ["base.cpp"],
324    arch: {
325        x86: {
326            objs: ["x86_obj"],
327            linker_script: "x86.lds",
328        },
329        x86_64: {
330            objs: ["x86_64_obj"],
331            linker_script: "x86_64.lds",
332        },
333        arm: {
334            objs: ["arm_obj"],
335            linker_script: "arm.lds",
336        },
337    },
338    include_build_directory: false,
339}
340
341cc_object {
342    name: "x86_obj",
343    system_shared_libs: [],
344    srcs: ["x86.cpp"],
345    include_build_directory: false,
346    bazel_module: { bp2build_available: false },
347}
348
349cc_object {
350    name: "x86_64_obj",
351    system_shared_libs: [],
352    srcs: ["x86_64.cpp"],
353    include_build_directory: false,
354    bazel_module: { bp2build_available: false },
355}
356
357cc_object {
358    name: "arm_obj",
359    system_shared_libs: [],
360    srcs: ["arm.cpp"],
361    include_build_directory: false,
362    bazel_module: { bp2build_available: false },
363}
364`,
365		ExpectedBazelTargets: []string{
366			MakeBazelTarget("cc_object", "foo", AttrNameToString{
367				"copts": `["-fno-addrsig"]`,
368				"objs": `select({
369        "//build/bazel/platforms/arch:arm": [":arm_obj"],
370        "//build/bazel/platforms/arch:x86": [":x86_obj"],
371        "//build/bazel/platforms/arch:x86_64": [":x86_64_obj"],
372        "//conditions:default": [],
373    })`,
374				"linker_script": `select({
375        "//build/bazel/platforms/arch:arm": "arm.lds",
376        "//build/bazel/platforms/arch:x86": "x86.lds",
377        "//build/bazel/platforms/arch:x86_64": "x86_64.lds",
378        "//conditions:default": None,
379    })`,
380				"srcs": `["base.cpp"]`,
381			}),
382		},
383	})
384}
385
386func TestCcObjectSelectOnLinuxAndBionicArchs(t *testing.T) {
387	runCcObjectTestCase(t, Bp2buildTestCase{
388		Description: "cc_object setting srcs based on linux and bionic archs",
389		Blueprint: `cc_object {
390    name: "foo",
391    srcs: ["base.cpp"],
392    target: {
393        linux_arm64: {
394            srcs: ["linux_arm64.cpp",]
395        },
396        linux_x86: {
397            srcs: ["linux_x86.cpp",]
398        },
399        bionic_arm64: {
400            srcs: ["bionic_arm64.cpp",]
401        },
402    },
403    include_build_directory: false,
404}
405`,
406		ExpectedBazelTargets: []string{
407			MakeBazelTarget("cc_object", "foo", AttrNameToString{
408				"copts": `["-fno-addrsig"]`,
409				"srcs": `["base.cpp"] + select({
410        "//build/bazel/platforms/os_arch:android_arm64": [
411            "linux_arm64.cpp",
412            "bionic_arm64.cpp",
413        ],
414        "//build/bazel/platforms/os_arch:android_x86": ["linux_x86.cpp"],
415        "//build/bazel/platforms/os_arch:linux_bionic_arm64": [
416            "linux_arm64.cpp",
417            "bionic_arm64.cpp",
418        ],
419        "//build/bazel/platforms/os_arch:linux_glibc_x86": ["linux_x86.cpp"],
420        "//build/bazel/platforms/os_arch:linux_musl_arm64": ["linux_arm64.cpp"],
421        "//build/bazel/platforms/os_arch:linux_musl_x86": ["linux_x86.cpp"],
422        "//conditions:default": [],
423    })`,
424			}),
425		},
426	})
427}
428
429func TestCcObjectHeaderLib(t *testing.T) {
430	runCcObjectTestCase(t, Bp2buildTestCase{
431		Description: "simple cc_object generates cc_object with include header dep",
432		Filesystem: map[string]string{
433			"a/b/foo.h":     "",
434			"a/b/bar.h":     "",
435			"a/b/exclude.c": "",
436			"a/b/c.c":       "",
437		},
438		Blueprint: `cc_object {
439    name: "foo",
440	header_libs: ["libheaders"],
441    system_shared_libs: [],
442    cflags: [
443        "-Wno-gcc-compat",
444        "-Wall",
445        "-Werror",
446    ],
447    srcs: [
448        "a/b/*.c"
449    ],
450    exclude_srcs: ["a/b/exclude.c"],
451    sdk_version: "current",
452    min_sdk_version: "29",
453}
454
455cc_library_headers {
456    name: "libheaders",
457	export_include_dirs: ["include"],
458}
459`,
460		ExpectedBazelTargets: []string{
461			MakeBazelTarget("cc_object", "foo", AttrNameToString{
462				"copts": `[
463        "-fno-addrsig",
464        "-Wno-gcc-compat",
465        "-Wall",
466        "-Werror",
467    ]`,
468				"deps":                `[":libheaders"]`,
469				"local_includes":      `["."]`,
470				"srcs":                `["a/b/c.c"]`,
471				"system_dynamic_deps": `[]`,
472				"sdk_version":         `"current"`,
473				"min_sdk_version":     `"29"`,
474			}),
475			MakeBazelTarget("cc_library_headers", "libheaders", AttrNameToString{
476				"export_includes": `["include"]`,
477			}),
478		},
479	})
480}
481