• 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	entries := android.AndroidMkEntriesForTest(t, ctx, prebuiltLiba)[0]
174	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_prebuilt_library_shared", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
175	entries = android.AndroidMkEntriesForTest(t, ctx, prebuiltLibb)[0]
176	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_prebuilt_library_static", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
177}
178
179func TestPrebuiltLibraryShared(t *testing.T) {
180	ctx := testPrebuilt(t, `
181	cc_prebuilt_library_shared {
182		name: "libtest",
183		srcs: ["libf.so"],
184    strip: {
185        none: true,
186    },
187	}
188	`, map[string][]byte{
189		"libf.so": nil,
190	})
191
192	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
193	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
194}
195
196func TestPrebuiltLibraryStatic(t *testing.T) {
197	ctx := testPrebuilt(t, `
198	cc_prebuilt_library_static {
199		name: "libtest",
200		srcs: ["libf.a"],
201	}
202	`, map[string][]byte{
203		"libf.a": nil,
204	})
205
206	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
207	assertString(t, static.OutputFile().Path().Base(), "libf.a")
208}
209
210func TestPrebuiltLibrary(t *testing.T) {
211	ctx := testPrebuilt(t, `
212	cc_prebuilt_library {
213		name: "libtest",
214		static: {
215			srcs: ["libf.a"],
216		},
217		shared: {
218			srcs: ["libf.so"],
219		},
220    strip: {
221        none: true,
222    },
223	}
224	`, map[string][]byte{
225		"libf.a":  nil,
226		"libf.so": nil,
227	})
228
229	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
230	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
231
232	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
233	assertString(t, static.OutputFile().Path().Base(), "libf.a")
234}
235
236func TestPrebuiltLibraryStem(t *testing.T) {
237	ctx := testPrebuilt(t, `
238	cc_prebuilt_library {
239		name: "libfoo",
240		stem: "libbar",
241		static: {
242			srcs: ["libfoo.a"],
243		},
244		shared: {
245			srcs: ["libfoo.so"],
246		},
247		strip: {
248			none: true,
249		},
250	}
251	`, map[string][]byte{
252		"libfoo.a":  nil,
253		"libfoo.so": nil,
254	})
255
256	static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
257	assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
258
259	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
260	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
261}
262
263func TestPrebuiltLibrarySharedStem(t *testing.T) {
264	ctx := testPrebuilt(t, `
265	cc_prebuilt_library_shared {
266		name: "libfoo",
267		stem: "libbar",
268		srcs: ["libfoo.so"],
269		strip: {
270			none: true,
271		},
272	}
273	`, map[string][]byte{
274		"libfoo.so": nil,
275	})
276
277	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
278	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
279}
280
281func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
282	if runtime.GOOS != "linux" {
283		t.Skipf("Skipping host prebuilt testing that is only supported on linux not %s", runtime.GOOS)
284	}
285
286	ctx := testPrebuilt(t, `
287	cc_prebuilt_library_shared {
288		name: "libfoo",
289		device_supported: false,
290		host_supported: true,
291		target: {
292			linux_glibc_x86_64: {
293				srcs: ["linux_glibc_x86_64/lib64/libfoo.so"],
294			},
295		},
296	}
297
298	cc_prebuilt_binary {
299		name: "foo",
300		device_supported: false,
301		host_supported: true,
302		shared_libs: ["libfoo"],
303		target: {
304			linux_glibc_x86_64: {
305				srcs: ["linux_glibc_x86_64/bin/foo"],
306			},
307		},
308	}
309	`, map[string][]byte{
310		"libfoo.so": nil,
311		"foo":       nil,
312	})
313
314	fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
315	assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo")
316	assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
317
318	var libfooDep android.Path
319	for _, dep := range fooRule.Implicits {
320		if dep.Base() == "libfoo.so" {
321			libfooDep = dep
322			break
323		}
324	}
325	assertString(t, libfooDep.String(), "out/soong/.intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so")
326}
327
328func TestPrebuiltLibrarySanitized(t *testing.T) {
329	bp := `cc_prebuilt_library {
330	name: "libtest",
331		static: {
332                        sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
333		},
334		shared: {
335                        sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
336		},
337	}
338	cc_prebuilt_library_static {
339		name: "libtest_static",
340                sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
341	}
342	cc_prebuilt_library_shared {
343		name: "libtest_shared",
344                sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
345	}`
346
347	fs := map[string][]byte{
348		"libf.a":         nil,
349		"libf.hwasan.a":  nil,
350		"libf.so":        nil,
351		"hwasan/libf.so": nil,
352	}
353
354	// Without SANITIZE_TARGET.
355	ctx := testPrebuilt(t, bp, fs)
356
357	shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
358	assertString(t, shared_rule.Input.String(), "libf.so")
359
360	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
361	assertString(t, static.OutputFile().Path().Base(), "libf.a")
362
363	shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
364	assertString(t, shared_rule2.Input.String(), "libf.so")
365
366	static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
367	assertString(t, static2.OutputFile().Path().Base(), "libf.a")
368
369	// With SANITIZE_TARGET=hwaddress
370	ctx = testPrebuilt(t, bp, fs,
371		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
372			variables.SanitizeDevice = []string{"hwaddress"}
373		}),
374	)
375
376	shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
377	assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
378
379	static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
380	assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
381
382	shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
383	assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
384
385	static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
386	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
387}
388
389func TestPrebuiltLibraryWithBazel(t *testing.T) {
390	const bp = `
391cc_prebuilt_library {
392	name: "foo",
393	shared: {
394		srcs: ["foo.so"],
395	},
396	static: {
397		srcs: ["foo.a"],
398	},
399	bazel_module: { label: "//foo/bar:bar" },
400}`
401	outBaseDir := "outputbase"
402	result := android.GroupFixturePreparers(
403		prepareForPrebuiltTest,
404		android.FixtureModifyConfig(func(config android.Config) {
405			config.BazelContext = android.MockBazelContext{
406				OutputBaseDir: outBaseDir,
407				LabelToCcInfo: map[string]cquery.CcInfo{
408					"//foo/bar:bar": cquery.CcInfo{
409						CcSharedLibraryFiles: []string{"foo.so"},
410					},
411					"//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
412						CcStaticLibraryFiles: []string{"foo.a"},
413					},
414				},
415			}
416		}),
417	).RunTestWithBp(t, bp)
418	sharedFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
419	pathPrefix := outBaseDir + "/execroot/__main__/"
420
421	sharedInfo := result.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
422	android.AssertPathRelativeToTopEquals(t,
423		"prebuilt library shared target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
424		pathPrefix+"foo.so", sharedInfo.SharedLibrary)
425
426	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
427	if err != nil {
428		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
429	}
430	expectedOutputFiles := []string{pathPrefix + "foo.so"}
431	android.AssertDeepEquals(t,
432		"prebuilt library shared target output files did not match expected.",
433		expectedOutputFiles, outputFiles.Strings())
434
435	staticFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
436	staticInfo := result.ModuleProvider(staticFoo, StaticLibraryInfoProvider).(StaticLibraryInfo)
437	android.AssertPathRelativeToTopEquals(t,
438		"prebuilt library static target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
439		pathPrefix+"foo.a", staticInfo.StaticLibrary)
440
441	staticOutputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
442	if err != nil {
443		t.Errorf("Unexpected error getting cc_object staticOutputFiles %s", err)
444	}
445	expectedStaticOutputFiles := []string{pathPrefix + "foo.a"}
446	android.AssertDeepEquals(t,
447		"prebuilt library static target output files did not match expected.",
448		expectedStaticOutputFiles, staticOutputFiles.Strings())
449}
450
451func TestPrebuiltLibraryWithBazelValidations(t *testing.T) {
452	const bp = `
453cc_prebuilt_library {
454	name: "foo",
455	shared: {
456		srcs: ["foo.so"],
457	},
458	static: {
459		srcs: ["foo.a"],
460	},
461	bazel_module: { label: "//foo/bar:bar" },
462	tidy: true,
463}`
464	outBaseDir := "outputbase"
465	result := android.GroupFixturePreparers(
466		prepareForPrebuiltTest,
467		android.FixtureMergeEnv(map[string]string{
468			"ALLOW_LOCAL_TIDY_TRUE": "1",
469		}),
470		android.FixtureModifyConfig(func(config android.Config) {
471			config.BazelContext = android.MockBazelContext{
472				OutputBaseDir: outBaseDir,
473				LabelToCcInfo: map[string]cquery.CcInfo{
474					"//foo/bar:bar": cquery.CcInfo{
475						CcSharedLibraryFiles: []string{"foo.so"},
476						TidyFiles:            []string{"foo.c.tidy"},
477					},
478					"//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
479						CcStaticLibraryFiles: []string{"foo.a"},
480						TidyFiles:            []string{"foo.c.tidy"},
481					},
482				},
483			}
484		}),
485	).RunTestWithBp(t, bp)
486	sharedFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
487
488	expectedOutputFile := "out/soong/.intermediates/foo/android_arm_armv7-a-neon_shared/validated/foo.so"
489	sharedInfo := result.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
490	android.AssertPathRelativeToTopEquals(t,
491		"prebuilt library shared target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
492		expectedOutputFile, sharedInfo.SharedLibrary)
493
494	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
495	if err != nil {
496		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
497	}
498	expectedOutputFiles := []string{expectedOutputFile}
499	android.AssertPathsRelativeToTopEquals(t,
500		"prebuilt library shared target output files did not match expected.",
501		expectedOutputFiles, outputFiles)
502
503	staticFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
504	staticInfo := result.ModuleProvider(staticFoo, StaticLibraryInfoProvider).(StaticLibraryInfo)
505	expectedStaticOutputFile := "out/soong/.intermediates/foo/android_arm_armv7-a-neon_static/validated/foo.a"
506	android.AssertPathRelativeToTopEquals(t,
507		"prebuilt library static target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
508		expectedStaticOutputFile, staticInfo.StaticLibrary)
509
510	staticOutputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
511	if err != nil {
512		t.Errorf("Unexpected error getting cc_object staticOutputFiles %s", err)
513	}
514	expectedStaticOutputFiles := []string{expectedStaticOutputFile}
515	android.AssertPathsRelativeToTopEquals(t,
516		"prebuilt library static target output files did not match expected.",
517		expectedStaticOutputFiles, staticOutputFiles)
518}
519
520func TestPrebuiltLibraryWithBazelStaticDisabled(t *testing.T) {
521	const bp = `
522cc_prebuilt_library {
523	name: "foo",
524	shared: {
525		srcs: ["foo.so"],
526	},
527	static: {
528		enabled: false
529	},
530	bazel_module: { label: "//foo/bar:bar" },
531}`
532	outBaseDir := "outputbase"
533	result := android.GroupFixturePreparers(
534		prepareForPrebuiltTest,
535		android.FixtureModifyConfig(func(config android.Config) {
536			config.BazelContext = android.MockBazelContext{
537				OutputBaseDir: outBaseDir,
538				LabelToCcInfo: map[string]cquery.CcInfo{
539					"//foo/bar:bar": cquery.CcInfo{
540						CcSharedLibraryFiles: []string{"foo.so"},
541					},
542				},
543			}
544		}),
545	).RunTestWithBp(t, bp)
546	sharedFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
547	pathPrefix := outBaseDir + "/execroot/__main__/"
548
549	sharedInfo := result.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
550	android.AssertPathRelativeToTopEquals(t,
551		"prebuilt library shared target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
552		pathPrefix+"foo.so", sharedInfo.SharedLibrary)
553
554	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
555	if err != nil {
556		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
557	}
558	expectedOutputFiles := []string{pathPrefix + "foo.so"}
559	android.AssertDeepEquals(t,
560		"prebuilt library shared target output files did not match expected.",
561		expectedOutputFiles, outputFiles.Strings())
562}
563
564func TestPrebuiltLibraryStaticWithBazel(t *testing.T) {
565	const bp = `
566cc_prebuilt_library_static {
567	name: "foo",
568	srcs: ["foo.so"],
569	bazel_module: { label: "//foo/bar:bar" },
570}`
571	outBaseDir := "outputbase"
572	result := android.GroupFixturePreparers(
573		prepareForPrebuiltTest,
574		android.FixtureModifyConfig(func(config android.Config) {
575			config.BazelContext = android.MockBazelContext{
576				OutputBaseDir: outBaseDir,
577				LabelToCcInfo: map[string]cquery.CcInfo{
578					"//foo/bar:bar": cquery.CcInfo{
579						CcStaticLibraryFiles: []string{"foo.so"},
580					},
581				},
582			}
583		}),
584	).RunTestWithBp(t, bp)
585	staticFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
586	pathPrefix := outBaseDir + "/execroot/__main__/"
587
588	info := result.ModuleProvider(staticFoo, StaticLibraryInfoProvider).(StaticLibraryInfo)
589	android.AssertPathRelativeToTopEquals(t,
590		"prebuilt library static path did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
591		pathPrefix+"foo.so", info.StaticLibrary)
592
593	outputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
594	if err != nil {
595		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
596	}
597	expectedOutputFiles := []string{pathPrefix + "foo.so"}
598	android.AssertDeepEquals(t, "prebuilt library static output files did not match expected.", expectedOutputFiles, outputFiles.Strings())
599}
600
601func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) {
602	const bp = `
603cc_prebuilt_library_shared {
604	name: "foo",
605	srcs: ["foo.so"],
606	bazel_module: { label: "//foo/bar:bar" },
607}`
608	outBaseDir := "outputbase"
609	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
610	config.BazelContext = android.MockBazelContext{
611		OutputBaseDir: outBaseDir,
612		LabelToCcInfo: map[string]cquery.CcInfo{
613			"//foo/bar:bar": cquery.CcInfo{
614				CcSharedLibraryFiles: []string{"foo.so"},
615			},
616		},
617	}
618	ctx := testCcWithConfig(t, config)
619	sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
620	pathPrefix := outBaseDir + "/execroot/__main__/"
621
622	info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
623	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
624		pathPrefix+"foo.so", info.SharedLibrary)
625	android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC",
626		pathPrefix+"foo.so", info.TableOfContents.Path())
627
628	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
629	if err != nil {
630		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
631	}
632	expectedOutputFiles := []string{pathPrefix + "foo.so"}
633	android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
634}
635
636func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) {
637	const bp = `
638cc_prebuilt_library_shared {
639	name: "foo",
640	srcs: ["foo.so"],
641	bazel_module: { label: "//foo/bar:bar" },
642}`
643	outBaseDir := "outputbase"
644	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
645	config.BazelContext = android.MockBazelContext{
646		OutputBaseDir: outBaseDir,
647		LabelToCcInfo: map[string]cquery.CcInfo{
648			"//foo/bar:bar": cquery.CcInfo{
649				CcSharedLibraryFiles: []string{"foo.so"},
650				TocFile:              "toc",
651			},
652		},
653	}
654	ctx := testCcWithConfig(t, config)
655	sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
656	pathPrefix := outBaseDir + "/execroot/__main__/"
657
658	info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
659	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC",
660		pathPrefix+"toc", info.TableOfContents.Path())
661	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
662		pathPrefix+"foo.so", info.SharedLibrary)
663
664	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
665	if err != nil {
666		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
667	}
668	expectedOutputFiles := []string{pathPrefix + "foo.so"}
669	android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
670}
671
672func TestPrebuiltStubNoinstall(t *testing.T) {
673	testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
674		result := android.GroupFixturePreparers(
675			prepareForPrebuiltTest,
676			android.PrepareForTestWithMakevars,
677			android.FixtureMergeMockFs(fs),
678		).RunTest(t)
679
680		ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
681		android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
682
683		installRules := result.InstallMakeRulesForTesting(t)
684		var installedlibRule *android.InstallMakeRule
685		for i, rule := range installRules {
686			if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" {
687				if installedlibRule != nil {
688					t.Errorf("Duplicate install rules for %s", rule.Target)
689				}
690				installedlibRule = &installRules[i]
691			}
692		}
693		if installedlibRule == nil {
694			t.Errorf("No install rule found for installedlib")
695			return
696		}
697
698		if expectLibfooOnSystemLib {
699			android.AssertStringListContains(t,
700				"installedlib doesn't have install dependency on libfoo impl",
701				installedlibRule.OrderOnlyDeps,
702				"out/target/product/test_device/system/lib/libfoo.so")
703		} else {
704			android.AssertStringListDoesNotContain(t,
705				"installedlib has install dependency on libfoo stub",
706				installedlibRule.Deps,
707				"out/target/product/test_device/system/lib/libfoo.so")
708			android.AssertStringListDoesNotContain(t,
709				"installedlib has order-only install dependency on libfoo stub",
710				installedlibRule.OrderOnlyDeps,
711				"out/target/product/test_device/system/lib/libfoo.so")
712		}
713	}
714
715	prebuiltLibfooBp := []byte(`
716		cc_prebuilt_library {
717			name: "libfoo",
718			prefer: true,
719			srcs: ["libfoo.so"],
720			stubs: {
721				versions: ["1"],
722			},
723		}
724	`)
725
726	installedlibBp := []byte(`
727		cc_library {
728			name: "installedlib",
729			shared_libs: ["libfoo"],
730		}
731	`)
732
733	t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
734		testFunc(
735			t,
736			/*expectLibfooOnSystemLib=*/ false,
737			android.MockFS{
738				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
739				"Android.bp": installedlibBp,
740			},
741		)
742	})
743
744	disabledSourceLibfooBp := []byte(`
745		cc_library {
746			name: "libfoo",
747			enabled: false,
748			stubs: {
749				versions: ["1"],
750			},
751		}
752	`)
753
754	t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
755		testFunc(
756			t,
757			/*expectLibfooOnSystemLib=*/ false,
758			android.MockFS{
759				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
760				"impl/Android.bp": disabledSourceLibfooBp,
761				"Android.bp":      installedlibBp,
762			},
763		)
764	})
765
766	t.Run("prebuilt impl (with `stubs` property set): install", func(t *testing.T) {
767		testFunc(
768			t,
769			/*expectLibfooOnSystemLib=*/ true,
770			android.MockFS{
771				"impl/Android.bp": prebuiltLibfooBp,
772				"Android.bp":      installedlibBp,
773			},
774		)
775	})
776}
777
778func TestPrebuiltBinaryNoSrcsNoError(t *testing.T) {
779	const bp = `
780cc_prebuilt_binary {
781	name: "bintest",
782	srcs: [],
783}`
784	ctx := testPrebuilt(t, bp, map[string][]byte{})
785	mod := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
786	android.AssertBoolEquals(t, `expected no srcs to yield no output file`, false, mod.OutputFile().Valid())
787}
788
789func TestPrebuiltBinaryMultipleSrcs(t *testing.T) {
790	const bp = `
791cc_prebuilt_binary {
792	name: "bintest",
793	srcs: ["foo", "bar"],
794}`
795	testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
796}
797
798func TestPrebuiltBinaryWithBazel(t *testing.T) {
799	const bp = `
800cc_prebuilt_binary {
801	name: "bintest",
802	srcs: ["bin"],
803	bazel_module: { label: "//bin/foo:foo" },
804}`
805	const outBaseDir = "outputbase"
806	const expectedOut = outBaseDir + "/execroot/__main__/bin"
807	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
808	config.BazelContext = android.MockBazelContext{
809		OutputBaseDir:      outBaseDir,
810		LabelToOutputFiles: map[string][]string{"//bin/foo:foo": []string{"bin"}},
811	}
812	ctx := testCcWithConfig(t, config)
813	bin := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
814	out := bin.OutputFile()
815	if !out.Valid() {
816		t.Error("Invalid output file")
817		return
818	}
819	android.AssertStringEquals(t, "output file", expectedOut, out.String())
820}
821