• 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 cc
16
17import (
18	_ "fmt"
19	_ "sort"
20
21	"testing"
22
23	"android/soong/android"
24
25	"github.com/google/blueprint"
26)
27
28func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool {
29	t.Helper()
30	var found bool
31	ctx.VisitDirectDeps(from, func(dep blueprint.Module) {
32		if dep == to {
33			found = true
34		}
35	})
36	return found
37}
38
39func TestApiLibraryReplacesExistingModule(t *testing.T) {
40	bp := `
41		cc_library {
42			name: "libfoo",
43			shared_libs: ["libbar"],
44			vendor_available: true,
45		}
46
47		cc_library {
48			name: "libbar",
49		}
50
51		cc_api_library {
52			name: "libbar",
53			vendor_available: true,
54			src: "libbar.so",
55		}
56
57		api_imports {
58			name: "api_imports",
59			shared_libs: [
60				"libbar",
61			],
62		}
63	`
64
65	ctx := prepareForCcTest.RunTestWithBp(t, bp)
66
67	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
68	libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
69	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
70
71	android.AssertBoolEquals(t, "original library should be linked with non-stub variant", true, hasDirectDependency(t, ctx, libfoo, libbar))
72	android.AssertBoolEquals(t, "Stub library from API surface should be not linked with non-stub variant", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
73
74	libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
75	libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
76
77	android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfooVendor, libbar))
78	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfooVendor, libbarApiImportVendor))
79}
80
81func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
82	bp := `
83		cc_library {
84			name: "libfoo",
85			shared_libs: ["libbar"],
86			vendor: true,
87		}
88
89		cc_api_library {
90			name: "libbar",
91			src: "libbar.so",
92			vendor_available: true,
93		}
94
95		api_imports {
96			name: "api_imports",
97			shared_libs: [
98				"libbar",
99			],
100		}
101	`
102
103	ctx := prepareForCcTest.RunTestWithBp(t, bp)
104
105	libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
106	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
107
108	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
109}
110
111func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) {
112	bp := `
113		cc_library {
114			name: "libfoo",
115			shared_libs: ["libbar"],
116			vendor_available: true,
117		}
118
119		cc_library {
120			name: "libbar",
121			vendor_available: true,
122		}
123
124		cc_api_library {
125			name: "libbar",
126			src: "libbar.so",
127			vendor_available: true,
128		}
129
130		api_imports {
131			name: "api_imports",
132			shared_libs: [],
133		}
134	`
135
136	ctx := prepareForCcTest.RunTestWithBp(t, bp)
137
138	libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
139	libbar := ctx.ModuleForTests("libbar", "android_vendor.29_arm64_armv8-a_shared").Module()
140	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
141
142	android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
143	android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
144}
145
146func TestExportDirFromStubLibrary(t *testing.T) {
147	bp := `
148		cc_library {
149			name: "libfoo",
150			export_include_dirs: ["source_include_dir"],
151			export_system_include_dirs: ["source_system_include_dir"],
152			vendor_available: true,
153		}
154		cc_api_library {
155			name: "libfoo",
156			export_include_dirs: ["stub_include_dir"],
157			export_system_include_dirs: ["stub_system_include_dir"],
158			vendor_available: true,
159			src: "libfoo.so",
160		}
161		api_imports {
162			name: "api_imports",
163			shared_libs: [
164				"libfoo",
165			],
166			header_libs: [],
167		}
168		// vendor binary
169		cc_binary {
170			name: "vendorbin",
171			vendor: true,
172			srcs: ["vendor.cc"],
173			shared_libs: ["libfoo"],
174		}
175	`
176	ctx := prepareForCcTest.RunTestWithBp(t, bp)
177	vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
178	android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir")
179	android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir")
180	android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir")
181	android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir")
182
183	vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
184	// Building the stub.so file first assembles its .h files in multi-tree out.
185	// These header files are required for compiling the other API domain (vendor in this case)
186	android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
187}
188
189func TestApiLibraryWithLlndkVariant(t *testing.T) {
190	bp := `
191		cc_binary {
192			name: "binfoo",
193			vendor: true,
194			srcs: ["binfoo.cc"],
195			shared_libs: ["libbar"],
196		}
197
198		cc_api_library {
199			name: "libbar",
200			// TODO(b/244244438) Remove src property once all variants are implemented.
201			src: "libbar.so",
202			vendor_available: true,
203			variants: [
204				"llndk",
205			],
206		}
207
208		cc_api_variant {
209			name: "libbar",
210			variant: "llndk",
211			src: "libbar_llndk.so",
212			export_include_dirs: ["libbar_llndk_include"]
213		}
214
215		api_imports {
216			name: "api_imports",
217			shared_libs: [
218				"libbar",
219			],
220			header_libs: [],
221		}
222	`
223
224	ctx := prepareForCcTest.RunTestWithBp(t, bp)
225
226	binfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
227	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
228	libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()
229
230	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport))
231	android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
232
233	binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
234	android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar.llndk.apiimport.so")
235
236	binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
237	android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include")
238}
239
240func TestApiLibraryWithNdkVariant(t *testing.T) {
241	bp := `
242		cc_binary {
243			name: "binfoo",
244			sdk_version: "29",
245			srcs: ["binfoo.cc"],
246			shared_libs: ["libbar"],
247			stl: "c++_shared",
248		}
249
250		cc_binary {
251			name: "binbaz",
252			sdk_version: "30",
253			srcs: ["binbaz.cc"],
254			shared_libs: ["libbar"],
255			stl: "c++_shared",
256		}
257
258		cc_binary {
259			name: "binqux",
260			srcs: ["binfoo.cc"],
261			shared_libs: ["libbar"],
262		}
263
264		cc_library {
265			name: "libbar",
266			srcs: ["libbar.cc"],
267		}
268
269		cc_api_library {
270			name: "libbar",
271			// TODO(b/244244438) Remove src property once all variants are implemented.
272			src: "libbar.so",
273			variants: [
274				"ndk.29",
275				"ndk.30",
276				"ndk.current",
277			],
278		}
279
280		cc_api_variant {
281			name: "libbar",
282			variant: "ndk",
283			version: "29",
284			src: "libbar_ndk_29.so",
285			export_include_dirs: ["libbar_ndk_29_include"]
286		}
287
288		cc_api_variant {
289			name: "libbar",
290			variant: "ndk",
291			version: "30",
292			src: "libbar_ndk_30.so",
293			export_include_dirs: ["libbar_ndk_30_include"]
294		}
295
296		cc_api_variant {
297			name: "libbar",
298			variant: "ndk",
299			version: "current",
300			src: "libbar_ndk_current.so",
301			export_include_dirs: ["libbar_ndk_current_include"]
302		}
303
304		api_imports {
305			name: "api_imports",
306			shared_libs: [
307				"libbar",
308			],
309			header_libs: [],
310		}
311	`
312
313	ctx := prepareForCcTest.RunTestWithBp(t, bp)
314
315	binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
316	libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
317	libbarApiVariantv29 := ctx.ModuleForTests("libbar.ndk.29.apiimport", "android_arm64_armv8-a_sdk").Module()
318	libbarApiImportv30 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_30").Module()
319	libbarApiVariantv30 := ctx.ModuleForTests("libbar.ndk.30.apiimport", "android_arm64_armv8-a_sdk").Module()
320
321	android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
322	android.AssertBoolEquals(t, "Stub library variant from API surface should be linked with target version", true, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv29))
323	android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportv30))
324	android.AssertBoolEquals(t, "Stub library variant from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv30))
325
326	binbaz := ctx.ModuleForTests("binbaz", "android_arm64_armv8-a_sdk").Module()
327
328	android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportv30))
329	android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
330
331	binFooLibFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("ld").Args["libFlags"]
332	android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar.ndk.29.apiimport.so")
333
334	binFooCFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("cc").Args["cFlags"]
335	android.AssertStringDoesContain(t, "Binary using sdk should include headers from the NDK variant source", binFooCFlags, "-Ilibbar_ndk_29_include")
336
337	binQux := ctx.ModuleForTests("binqux", "android_arm64_armv8-a").Module()
338	android.AssertBoolEquals(t, "NDK Stub library from API surface should not be linked with nonSdk binary", false,
339		(hasDirectDependency(t, ctx, binQux, libbarApiImportv30) || hasDirectDependency(t, ctx, binQux, libbarApiImportv29)))
340}
341
342func TestApiLibraryWithMultipleVariants(t *testing.T) {
343	bp := `
344		cc_binary {
345			name: "binfoo",
346			sdk_version: "29",
347			srcs: ["binfoo.cc"],
348			shared_libs: ["libbar"],
349			stl: "c++_shared",
350		}
351
352		cc_binary {
353			name: "binbaz",
354			vendor: true,
355			srcs: ["binbaz.cc"],
356			shared_libs: ["libbar"],
357		}
358
359		cc_library {
360			name: "libbar",
361			srcs: ["libbar.cc"],
362		}
363
364		cc_api_library {
365			name: "libbar",
366			// TODO(b/244244438) Remove src property once all variants are implemented.
367			src: "libbar.so",
368			vendor_available: true,
369			variants: [
370				"llndk",
371				"ndk.29",
372				"ndk.30",
373				"ndk.current",
374				"apex.29",
375				"apex.30",
376				"apex.current",
377			],
378		}
379
380		cc_api_variant {
381			name: "libbar",
382			variant: "ndk",
383			version: "29",
384			src: "libbar_ndk_29.so",
385			export_include_dirs: ["libbar_ndk_29_include"]
386		}
387
388		cc_api_variant {
389			name: "libbar",
390			variant: "ndk",
391			version: "30",
392			src: "libbar_ndk_30.so",
393			export_include_dirs: ["libbar_ndk_30_include"]
394		}
395
396		cc_api_variant {
397			name: "libbar",
398			variant: "ndk",
399			version: "current",
400			src: "libbar_ndk_current.so",
401			export_include_dirs: ["libbar_ndk_current_include"]
402		}
403
404		cc_api_variant {
405			name: "libbar",
406			variant: "apex",
407			version: "29",
408			src: "libbar_apex_29.so",
409			export_include_dirs: ["libbar_apex_29_include"]
410		}
411
412		cc_api_variant {
413			name: "libbar",
414			variant: "apex",
415			version: "30",
416			src: "libbar_apex_30.so",
417			export_include_dirs: ["libbar_apex_30_include"]
418		}
419
420		cc_api_variant {
421			name: "libbar",
422			variant: "apex",
423			version: "current",
424			src: "libbar_apex_current.so",
425			export_include_dirs: ["libbar_apex_current_include"]
426		}
427
428		cc_api_variant {
429			name: "libbar",
430			variant: "llndk",
431			src: "libbar_llndk.so",
432			export_include_dirs: ["libbar_llndk_include"]
433		}
434
435		api_imports {
436			name: "api_imports",
437			shared_libs: [
438				"libbar",
439			],
440			apex_shared_libs: [
441				"libbar",
442			],
443		}
444	`
445	ctx := prepareForCcTest.RunTestWithBp(t, bp)
446
447	binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
448	libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
449	libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
450
451	android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
452	android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk))
453
454	binbaz := ctx.ModuleForTests("binbaz", "android_vendor.29_arm64_armv8-a").Module()
455
456	android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk))
457	android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
458
459}
460