• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 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	"runtime"
19	"testing"
20
21	"android/soong/android"
22	"android/soong/bazel/cquery"
23
24	"github.com/google/blueprint"
25)
26
27var prepareForPrebuiltTest = android.GroupFixturePreparers(
28	prepareForCcTest,
29	android.PrepareForTestWithAndroidMk,
30)
31
32func testPrebuilt(t *testing.T, bp string, fs android.MockFS, handlers ...android.FixturePreparer) *android.TestContext {
33	t.Helper()
34	result := android.GroupFixturePreparers(
35		prepareForPrebuiltTest,
36		fs.AddToFixture(),
37		android.GroupFixturePreparers(handlers...),
38	).RunTestWithBp(t, bp)
39
40	return result.TestContext
41}
42
43type configCustomizer func(config android.Config)
44
45func TestPrebuilt(t *testing.T) {
46	bp := `
47		cc_library {
48			name: "liba",
49		}
50
51		cc_prebuilt_library_shared {
52			name: "liba",
53			srcs: ["liba.so"],
54		}
55
56		cc_library {
57			name: "libb",
58		}
59
60		cc_prebuilt_library_static {
61			name: "libb",
62			srcs: ["libb.a"],
63		}
64
65		cc_library_shared {
66			name: "libd",
67		}
68
69		cc_prebuilt_library_shared {
70			name: "libd",
71			srcs: ["libd.so"],
72		}
73
74		cc_library_static {
75			name: "libe",
76		}
77
78		cc_prebuilt_library_static {
79			name: "libe",
80			srcs: ["libe.a"],
81		}
82
83		cc_library {
84			name: "libf",
85		}
86
87		cc_prebuilt_library {
88			name: "libf",
89			static: {
90				srcs: ["libf.a"],
91			},
92			shared: {
93				srcs: ["libf.so"],
94			},
95		}
96
97		cc_object {
98			name: "crtx",
99		}
100
101		cc_prebuilt_object {
102			name: "crtx",
103			srcs: ["crtx.o"],
104		}
105	`
106
107	ctx := testPrebuilt(t, bp, map[string][]byte{
108		"liba.so": nil,
109		"libb.a":  nil,
110		"libd.so": nil,
111		"libe.a":  nil,
112		"libf.a":  nil,
113		"libf.so": nil,
114		"crtx.o":  nil,
115	})
116
117	// Verify that all the modules exist and that their dependencies were connected correctly
118	liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
119	libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
120	libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
121	libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
122	libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
123	libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
124	crtx := ctx.ModuleForTests("crtx", "android_arm64_armv8-a").Module()
125
126	prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
127	prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
128	prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
129	prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
130	prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
131	prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
132	prebuiltCrtx := ctx.ModuleForTests("prebuilt_crtx", "android_arm64_armv8-a").Module()
133
134	hasDep := func(m android.Module, wantDep android.Module) bool {
135		t.Helper()
136		var found bool
137		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
138			if dep == wantDep {
139				found = true
140			}
141		})
142		return found
143	}
144
145	if !hasDep(liba, prebuiltLiba) {
146		t.Errorf("liba missing dependency on prebuilt_liba")
147	}
148
149	if !hasDep(libb, prebuiltLibb) {
150		t.Errorf("libb missing dependency on prebuilt_libb")
151	}
152
153	if !hasDep(libd, prebuiltLibd) {
154		t.Errorf("libd missing dependency on prebuilt_libd")
155	}
156
157	if !hasDep(libe, prebuiltLibe) {
158		t.Errorf("libe missing dependency on prebuilt_libe")
159	}
160
161	if !hasDep(libfStatic, prebuiltLibfStatic) {
162		t.Errorf("libf static missing dependency on prebuilt_libf")
163	}
164
165	if !hasDep(libfShared, prebuiltLibfShared) {
166		t.Errorf("libf shared missing dependency on prebuilt_libf")
167	}
168
169	if !hasDep(crtx, prebuiltCrtx) {
170		t.Errorf("crtx missing dependency on prebuilt_crtx")
171	}
172}
173
174func TestPrebuiltLibraryShared(t *testing.T) {
175	ctx := testPrebuilt(t, `
176	cc_prebuilt_library_shared {
177		name: "libtest",
178		srcs: ["libf.so"],
179    strip: {
180        none: true,
181    },
182	}
183	`, map[string][]byte{
184		"libf.so": nil,
185	})
186
187	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
188	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
189}
190
191func TestPrebuiltLibraryStatic(t *testing.T) {
192	ctx := testPrebuilt(t, `
193	cc_prebuilt_library_static {
194		name: "libtest",
195		srcs: ["libf.a"],
196	}
197	`, map[string][]byte{
198		"libf.a": nil,
199	})
200
201	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
202	assertString(t, static.OutputFile().Path().Base(), "libf.a")
203}
204
205func TestPrebuiltLibrary(t *testing.T) {
206	ctx := testPrebuilt(t, `
207	cc_prebuilt_library {
208		name: "libtest",
209		static: {
210			srcs: ["libf.a"],
211		},
212		shared: {
213			srcs: ["libf.so"],
214		},
215    strip: {
216        none: true,
217    },
218	}
219	`, map[string][]byte{
220		"libf.a":  nil,
221		"libf.so": nil,
222	})
223
224	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
225	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
226
227	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
228	assertString(t, static.OutputFile().Path().Base(), "libf.a")
229}
230
231func TestPrebuiltLibraryStem(t *testing.T) {
232	ctx := testPrebuilt(t, `
233	cc_prebuilt_library {
234		name: "libfoo",
235		stem: "libbar",
236		static: {
237			srcs: ["libfoo.a"],
238		},
239		shared: {
240			srcs: ["libfoo.so"],
241		},
242		strip: {
243			none: true,
244		},
245	}
246	`, map[string][]byte{
247		"libfoo.a":  nil,
248		"libfoo.so": nil,
249	})
250
251	static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
252	assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
253
254	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
255	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
256}
257
258func TestPrebuiltLibrarySharedStem(t *testing.T) {
259	ctx := testPrebuilt(t, `
260	cc_prebuilt_library_shared {
261		name: "libfoo",
262		stem: "libbar",
263		srcs: ["libfoo.so"],
264		strip: {
265			none: true,
266		},
267	}
268	`, map[string][]byte{
269		"libfoo.so": nil,
270	})
271
272	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
273	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
274}
275
276func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
277	if runtime.GOOS != "linux" {
278		t.Skipf("Skipping host prebuilt testing that is only supported on linux not %s", runtime.GOOS)
279	}
280
281	ctx := testPrebuilt(t, `
282	cc_prebuilt_library_shared {
283		name: "libfoo",
284		device_supported: false,
285		host_supported: true,
286		target: {
287			linux_glibc_x86_64: {
288				srcs: ["linux_glibc_x86_64/lib64/libfoo.so"],
289			},
290		},
291	}
292
293	cc_prebuilt_binary {
294		name: "foo",
295		device_supported: false,
296		host_supported: true,
297		shared_libs: ["libfoo"],
298		target: {
299			linux_glibc_x86_64: {
300				srcs: ["linux_glibc_x86_64/bin/foo"],
301			},
302		},
303	}
304	`, map[string][]byte{
305		"libfoo.so": nil,
306		"foo":       nil,
307	})
308
309	fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
310	assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo")
311	assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
312
313	var libfooDep android.Path
314	for _, dep := range fooRule.Implicits {
315		if dep.Base() == "libfoo.so" {
316			libfooDep = dep
317			break
318		}
319	}
320	assertString(t, libfooDep.String(), "out/soong/.intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so")
321}
322
323func TestPrebuiltLibrarySanitized(t *testing.T) {
324	bp := `cc_prebuilt_library {
325	name: "libtest",
326		static: {
327                        sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
328		},
329		shared: {
330                        sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
331		},
332	}
333	cc_prebuilt_library_static {
334		name: "libtest_static",
335                sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
336	}
337	cc_prebuilt_library_shared {
338		name: "libtest_shared",
339                sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
340	}`
341
342	fs := map[string][]byte{
343		"libf.a":         nil,
344		"libf.hwasan.a":  nil,
345		"libf.so":        nil,
346		"hwasan/libf.so": nil,
347	}
348
349	// Without SANITIZE_TARGET.
350	ctx := testPrebuilt(t, bp, fs)
351
352	shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
353	assertString(t, shared_rule.Input.String(), "libf.so")
354
355	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
356	assertString(t, static.OutputFile().Path().Base(), "libf.a")
357
358	shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
359	assertString(t, shared_rule2.Input.String(), "libf.so")
360
361	static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
362	assertString(t, static2.OutputFile().Path().Base(), "libf.a")
363
364	// With SANITIZE_TARGET=hwaddress
365	ctx = testPrebuilt(t, bp, fs,
366		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
367			variables.SanitizeDevice = []string{"hwaddress"}
368		}),
369	)
370
371	shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
372	assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
373
374	static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
375	assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
376
377	shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
378	assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
379
380	static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
381	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
382}
383
384func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) {
385	const bp = `
386cc_prebuilt_library_shared {
387	name: "foo",
388	srcs: ["foo.so"],
389	bazel_module: { label: "//foo/bar:bar" },
390}`
391	outBaseDir := "outputbase"
392	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
393	config.BazelContext = android.MockBazelContext{
394		OutputBaseDir: outBaseDir,
395		LabelToCcInfo: map[string]cquery.CcInfo{
396			"//foo/bar:bar": cquery.CcInfo{
397				CcSharedLibraryFiles: []string{"foo.so"},
398			},
399		},
400	}
401	ctx := testCcWithConfig(t, config)
402	sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
403	pathPrefix := outBaseDir + "/execroot/__main__/"
404
405	info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
406	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
407		pathPrefix+"foo.so", info.SharedLibrary)
408	android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC",
409		pathPrefix+"foo.so", info.TableOfContents.Path())
410
411	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
412	if err != nil {
413		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
414	}
415	expectedOutputFiles := []string{pathPrefix + "foo.so"}
416	android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
417}
418
419func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) {
420	const bp = `
421cc_prebuilt_library_shared {
422	name: "foo",
423	srcs: ["foo.so"],
424	bazel_module: { label: "//foo/bar:bar" },
425}`
426	outBaseDir := "outputbase"
427	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
428	config.BazelContext = android.MockBazelContext{
429		OutputBaseDir: outBaseDir,
430		LabelToCcInfo: map[string]cquery.CcInfo{
431			"//foo/bar:bar": cquery.CcInfo{
432				CcSharedLibraryFiles: []string{"foo.so"},
433				TocFile:              "toc",
434			},
435		},
436	}
437	ctx := testCcWithConfig(t, config)
438	sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
439	pathPrefix := outBaseDir + "/execroot/__main__/"
440
441	info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
442	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC",
443		pathPrefix+"toc", info.TableOfContents.Path())
444	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
445		pathPrefix+"foo.so", info.SharedLibrary)
446
447	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
448	if err != nil {
449		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
450	}
451	expectedOutputFiles := []string{pathPrefix + "foo.so"}
452	android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
453}
454
455func TestPrebuiltStubNoinstall(t *testing.T) {
456	testFunc := func(t *testing.T, bp string) {
457		result := android.GroupFixturePreparers(
458			prepareForPrebuiltTest,
459			android.PrepareForTestWithMakevars,
460		).RunTestWithBp(t, bp)
461
462		installRules := result.InstallMakeRulesForTesting(t)
463		var installedlibRule *android.InstallMakeRule
464		for i, rule := range installRules {
465			if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" {
466				if installedlibRule != nil {
467					t.Errorf("Duplicate install rules for %s", rule.Target)
468				}
469				installedlibRule = &installRules[i]
470			}
471		}
472		if installedlibRule == nil {
473			t.Errorf("No install rule found for installedlib")
474			return
475		}
476
477		android.AssertStringListDoesNotContain(t,
478			"installedlib has install dependency on stub",
479			installedlibRule.Deps,
480			"out/target/product/test_device/system/lib/stublib.so")
481		android.AssertStringListDoesNotContain(t,
482			"installedlib has order-only install dependency on stub",
483			installedlibRule.OrderOnlyDeps,
484			"out/target/product/test_device/system/lib/stublib.so")
485	}
486
487	const prebuiltStublibBp = `
488		cc_prebuilt_library {
489			name: "stublib",
490			prefer: true,
491			srcs: ["foo.so"],
492			stubs: {
493				versions: ["1"],
494			},
495		}
496	`
497
498	const installedlibBp = `
499		cc_library {
500			name: "installedlib",
501			shared_libs: ["stublib"],
502		}
503	`
504
505	t.Run("prebuilt without source", func(t *testing.T) {
506		testFunc(t, prebuiltStublibBp+installedlibBp)
507	})
508
509	const disabledSourceStublibBp = `
510		cc_library {
511			name: "stublib",
512			enabled: false,
513			stubs: {
514				versions: ["1"],
515			},
516		}
517	`
518
519	t.Run("prebuilt with disabled source", func(t *testing.T) {
520		testFunc(t, disabledSourceStublibBp+prebuiltStublibBp+installedlibBp)
521	})
522}
523