• 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
24const (
25	// See cc/testing.go for more context
26	soongCcLibraryHeadersPreamble = `
27cc_defaults {
28    name: "linux_bionic_supported",
29}`
30)
31
32func TestCcLibraryHeadersLoadStatement(t *testing.T) {
33	testCases := []struct {
34		bazelTargets           BazelTargets
35		expectedLoadStatements string
36	}{
37		{
38			bazelTargets: BazelTargets{
39				BazelTarget{
40					name:      "cc_library_headers_target",
41					ruleClass: "cc_library_headers",
42					// Note: no bzlLoadLocation for native rules
43				},
44			},
45			expectedLoadStatements: ``,
46		},
47	}
48
49	for _, testCase := range testCases {
50		actual := testCase.bazelTargets.LoadStatements()
51		expected := testCase.expectedLoadStatements
52		if actual != expected {
53			t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
54		}
55	}
56}
57
58func registerCcLibraryHeadersModuleTypes(ctx android.RegistrationContext) {
59	cc.RegisterCCBuildComponents(ctx)
60}
61
62func runCcLibraryHeadersTestCase(t *testing.T, tc Bp2buildTestCase) {
63	t.Helper()
64	RunBp2BuildTestCase(t, registerCcLibraryHeadersModuleTypes, tc)
65}
66
67func TestCcLibraryHeadersSimple(t *testing.T) {
68	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
69		Description:                "cc_library_headers test",
70		ModuleTypeUnderTest:        "cc_library_headers",
71		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
72		Filesystem: map[string]string{
73			"lib-1/lib1a.h":                        "",
74			"lib-1/lib1b.h":                        "",
75			"lib-2/lib2a.h":                        "",
76			"lib-2/lib2b.h":                        "",
77			"dir-1/dir1a.h":                        "",
78			"dir-1/dir1b.h":                        "",
79			"dir-2/dir2a.h":                        "",
80			"dir-2/dir2b.h":                        "",
81			"arch_arm64_exported_include_dir/a.h":  "",
82			"arch_x86_exported_include_dir/b.h":    "",
83			"arch_x86_64_exported_include_dir/c.h": "",
84		},
85		Blueprint: soongCcLibraryHeadersPreamble + `
86cc_library_headers {
87    name: "foo_headers",
88    export_include_dirs: ["dir-1", "dir-2"],
89    header_libs: ["lib-1", "lib-2"],
90
91    arch: {
92        arm64: {
93      // We expect dir-1 headers to be dropped, because dir-1 is already in export_include_dirs
94            export_include_dirs: ["arch_arm64_exported_include_dir", "dir-1"],
95        },
96        x86: {
97            export_include_dirs: ["arch_x86_exported_include_dir"],
98        },
99        x86_64: {
100            export_include_dirs: ["arch_x86_64_exported_include_dir"],
101        },
102    },
103    sdk_version: "current",
104    min_sdk_version: "29",
105
106    // TODO: Also support export_header_lib_headers
107}`,
108		ExpectedBazelTargets: []string{
109			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
110				"export_includes": `select({
111        "//build/bazel/platforms/arch:arm64": ["arch_arm64_exported_include_dir"],
112        "//build/bazel/platforms/arch:x86": ["arch_x86_exported_include_dir"],
113        "//build/bazel/platforms/arch:x86_64": ["arch_x86_64_exported_include_dir"],
114        "//conditions:default": [],
115    }) + [
116        "dir-1",
117        "dir-2",
118    ]`,
119				"sdk_version":     `"current"`,
120				"min_sdk_version": `"29"`,
121			}),
122		},
123	})
124}
125
126func TestCcApiHeaders(t *testing.T) {
127	fs := map[string]string{
128		"bar/Android.bp": `cc_library_headers { name: "bar_headers", }`,
129	}
130	bp := `
131	cc_library_headers {
132		name: "foo_headers",
133		export_include_dirs: ["dir1", "dir2"],
134		export_header_lib_headers: ["bar_headers"],
135
136		arch: {
137			arm: {
138				export_include_dirs: ["dir_arm"],
139			},
140			x86: {
141				export_include_dirs: ["dir_x86"],
142			},
143		},
144
145		target: {
146			android: {
147				export_include_dirs: ["dir1", "dir_android"],
148			},
149			windows: {
150				export_include_dirs: ["dir_windows"],
151			},
152		}
153	}
154	`
155	expectedBazelTargets := []string{
156		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.arm", AttrNameToString{
157			"export_includes": `["dir_arm"]`,
158			"arch":            `"arm"`,
159		}),
160		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.x86", AttrNameToString{
161			"export_includes": `["dir_x86"]`,
162			"arch":            `"x86"`,
163		}),
164		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.androidos", AttrNameToString{
165			"export_includes": `["dir_android"]`, // common includes are deduped
166		}),
167		// Windows headers are not exported
168		MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution", AttrNameToString{
169			"export_includes": `[
170        "dir1",
171        "dir2",
172    ]`,
173			"deps": `[
174        "//bar:bar_headers.contribution",
175        ":foo_headers.contribution.arm",
176        ":foo_headers.contribution.x86",
177        ":foo_headers.contribution.androidos",
178    ]`,
179		}),
180	}
181	RunApiBp2BuildTestCase(t, cc.RegisterLibraryHeadersBuildComponents, Bp2buildTestCase{
182		Blueprint:            bp,
183		Description:          "Header library contributions to API surfaces",
184		ExpectedBazelTargets: expectedBazelTargets,
185		Filesystem:           fs,
186	})
187}
188
189// header_libs has "variant_prepend" tag. In bp2build output,
190// variant info(select) should go before general info.
191func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
192	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
193		Description:                "cc_library_headers test with os-specific header_libs props",
194		ModuleTypeUnderTest:        "cc_library_headers",
195		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
196		Filesystem:                 map[string]string{},
197		Blueprint: soongCcLibraryPreamble + `
198cc_library_headers {
199    name: "android-lib",
200    bazel_module: { bp2build_available: false },
201}
202cc_library_headers {
203    name: "base-lib",
204    bazel_module: { bp2build_available: false },
205}
206cc_library_headers {
207    name: "darwin-lib",
208    bazel_module: { bp2build_available: false },
209}
210cc_library_headers {
211    name: "linux-lib",
212    bazel_module: { bp2build_available: false },
213}
214cc_library_headers {
215    name: "linux_bionic-lib",
216    bazel_module: { bp2build_available: false },
217}
218cc_library_headers {
219    name: "windows-lib",
220    bazel_module: { bp2build_available: false },
221}
222cc_library_headers {
223    name: "foo_headers",
224    header_libs: ["base-lib"],
225		export_header_lib_headers: ["base-lib"],
226    target: {
227        android: {
228						header_libs: ["android-lib"],
229						export_header_lib_headers: ["android-lib"],
230				},
231        darwin: {
232						header_libs: ["darwin-lib"],
233						export_header_lib_headers: ["darwin-lib"],
234				},
235        linux_bionic: {
236						header_libs: ["linux_bionic-lib"],
237						export_header_lib_headers: ["linux_bionic-lib"],
238				},
239        linux_glibc: {
240						header_libs: ["linux-lib"],
241						export_header_lib_headers: ["linux-lib"],
242				},
243        windows: {
244						header_libs: ["windows-lib"],
245						export_header_lib_headers: ["windows-lib"],
246				},
247    },
248    include_build_directory: false,
249}`,
250		ExpectedBazelTargets: []string{
251			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
252				"deps": `select({
253        "//build/bazel/platforms/os:android": [":android-lib"],
254        "//build/bazel/platforms/os:darwin": [":darwin-lib"],
255        "//build/bazel/platforms/os:linux_bionic": [":linux_bionic-lib"],
256        "//build/bazel/platforms/os:linux_glibc": [":linux-lib"],
257        "//build/bazel/platforms/os:windows": [":windows-lib"],
258        "//conditions:default": [],
259    }) + [":base-lib"]`,
260			}),
261		},
262	})
263}
264
265func TestCcLibraryHeadersOsSpecficHeaderLibsExportHeaderLibHeaders(t *testing.T) {
266	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
267		Description:                "cc_library_headers test with os-specific header_libs and export_header_lib_headers props",
268		ModuleTypeUnderTest:        "cc_library_headers",
269		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
270		Filesystem:                 map[string]string{},
271		Blueprint: soongCcLibraryPreamble + `
272cc_library_headers {
273    name: "android-lib",
274    bazel_module: { bp2build_available: false },
275  }
276cc_library_headers {
277    name: "exported-lib",
278    bazel_module: { bp2build_available: false },
279}
280cc_library_headers {
281    name: "foo_headers",
282    target: {
283        android: {
284            header_libs: ["android-lib", "exported-lib"],
285            export_header_lib_headers: ["exported-lib"]
286        },
287    },
288    include_build_directory: false,
289}`,
290		ExpectedBazelTargets: []string{
291			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
292				"deps": `select({
293        "//build/bazel/platforms/os:android": [":exported-lib"],
294        "//conditions:default": [],
295    })`,
296			}),
297		},
298	})
299}
300
301func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) {
302	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
303		Description:                "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props",
304		ModuleTypeUnderTest:        "cc_library_headers",
305		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
306		Filesystem:                 map[string]string{},
307		Blueprint: soongCcLibraryPreamble + `cc_library_headers {
308    name: "foo_headers",
309    export_system_include_dirs: [
310        "shared_include_dir",
311    ],
312    target: {
313        android: {
314            export_system_include_dirs: [
315                "android_include_dir",
316            ],
317        },
318        linux_glibc: {
319            export_system_include_dirs: [
320                "linux_include_dir",
321            ],
322        },
323        darwin: {
324            export_system_include_dirs: [
325                "darwin_include_dir",
326            ],
327        },
328    },
329    arch: {
330        arm: {
331            export_system_include_dirs: [
332                "arm_include_dir",
333            ],
334        },
335        x86_64: {
336            export_system_include_dirs: [
337                "x86_64_include_dir",
338            ],
339        },
340    },
341    include_build_directory: false,
342}`,
343		ExpectedBazelTargets: []string{
344			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
345				"export_system_includes": `select({
346        "//build/bazel/platforms/os:android": ["android_include_dir"],
347        "//build/bazel/platforms/os:darwin": ["darwin_include_dir"],
348        "//build/bazel/platforms/os:linux_glibc": ["linux_include_dir"],
349        "//conditions:default": [],
350    }) + select({
351        "//build/bazel/platforms/arch:arm": ["arm_include_dir"],
352        "//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"],
353        "//conditions:default": [],
354    }) + ["shared_include_dir"]`,
355			}),
356		},
357	})
358}
359
360func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) {
361	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
362		Description:                "cc_library_headers test",
363		ModuleTypeUnderTest:        "cc_library_headers",
364		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
365		Filesystem: map[string]string{
366			"lib-1/lib1a.h":                        "",
367			"lib-1/lib1b.h":                        "",
368			"lib-2/lib2a.h":                        "",
369			"lib-2/lib2b.h":                        "",
370			"dir-1/dir1a.h":                        "",
371			"dir-1/dir1b.h":                        "",
372			"dir-2/dir2a.h":                        "",
373			"dir-2/dir2b.h":                        "",
374			"arch_arm64_exported_include_dir/a.h":  "",
375			"arch_x86_exported_include_dir/b.h":    "",
376			"arch_x86_64_exported_include_dir/c.h": "",
377		},
378		Blueprint: soongCcLibraryHeadersPreamble + `
379cc_library_headers {
380    name: "lib-1",
381    export_include_dirs: ["lib-1"],
382    no_libcrt: true,
383    include_build_directory: false,
384}`,
385		ExpectedBazelTargets: []string{
386			MakeBazelTarget("cc_library_headers", "lib-1", AttrNameToString{
387				"export_includes": `["lib-1"]`,
388			}),
389		},
390	})
391}
392
393func TestCcLibraryHeadersExportedStaticLibHeadersReexported(t *testing.T) {
394	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
395		Description:                "cc_library_headers exported_static_lib_headers is reexported",
396		ModuleTypeUnderTest:        "cc_library_headers",
397		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
398		Filesystem:                 map[string]string{},
399		Blueprint: soongCcLibraryHeadersPreamble + `
400cc_library_headers {
401		name: "foo_headers",
402		export_static_lib_headers: ["foo_export"],
403		static_libs: ["foo_export", "foo_no_reexport"],
404    bazel_module: { bp2build_available: true },
405}
406` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
407		ExpectedBazelTargets: []string{
408			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
409				"deps": `[":foo_export"]`,
410			}),
411		},
412	})
413}
414
415func TestCcLibraryHeadersExportedSharedLibHeadersReexported(t *testing.T) {
416	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
417		Description:                "cc_library_headers exported_shared_lib_headers is reexported",
418		ModuleTypeUnderTest:        "cc_library_headers",
419		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
420		Filesystem:                 map[string]string{},
421		Blueprint: soongCcLibraryHeadersPreamble + `
422cc_library_headers {
423		name: "foo_headers",
424		export_shared_lib_headers: ["foo_export"],
425		shared_libs: ["foo_export", "foo_no_reexport"],
426    bazel_module: { bp2build_available: true },
427}
428` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
429		ExpectedBazelTargets: []string{
430			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
431				"deps": `[":foo_export"]`,
432			}),
433		},
434	})
435}
436
437func TestCcLibraryHeadersExportedHeaderLibHeadersReexported(t *testing.T) {
438	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
439		Description:                "cc_library_headers exported_header_lib_headers is reexported",
440		ModuleTypeUnderTest:        "cc_library_headers",
441		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
442		Filesystem:                 map[string]string{},
443		Blueprint: soongCcLibraryHeadersPreamble + `
444cc_library_headers {
445		name: "foo_headers",
446		export_header_lib_headers: ["foo_export"],
447		header_libs: ["foo_export", "foo_no_reexport"],
448    bazel_module: { bp2build_available: true },
449}
450` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
451		ExpectedBazelTargets: []string{
452			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
453				"deps": `[":foo_export"]`,
454			}),
455		},
456	})
457}
458
459func TestCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) {
460	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
461		Description:                "cc_library_headers whole_static_libs is reexported",
462		ModuleTypeUnderTest:        "cc_library_headers",
463		ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
464		Filesystem:                 map[string]string{},
465		Blueprint: soongCcLibraryHeadersPreamble + `
466cc_library_headers {
467		name: "foo_headers",
468		whole_static_libs: ["foo_export"],
469    bazel_module: { bp2build_available: true },
470}
471` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
472		ExpectedBazelTargets: []string{
473			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
474				"deps": `[":foo_export"]`,
475			}),
476		},
477	})
478}
479