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	"testing"
19
20	"android/soong/android"
21
22	"github.com/google/blueprint"
23)
24
25var prepareForPrebuiltTest = android.GroupFixturePreparers(
26	prepareForCcTest,
27	android.PrepareForTestWithAndroidMk,
28)
29
30func testPrebuilt(t *testing.T, bp string, fs android.MockFS, handlers ...android.FixturePreparer) *android.TestContext {
31	result := android.GroupFixturePreparers(
32		prepareForPrebuiltTest,
33		fs.AddToFixture(),
34		android.GroupFixturePreparers(handlers...),
35	).RunTestWithBp(t, bp)
36
37	return result.TestContext
38}
39
40type configCustomizer func(config android.Config)
41
42func TestPrebuilt(t *testing.T) {
43	bp := `
44		cc_library {
45			name: "liba",
46		}
47
48		cc_prebuilt_library_shared {
49			name: "liba",
50			srcs: ["liba.so"],
51		}
52
53		cc_library {
54			name: "libb",
55		}
56
57		cc_prebuilt_library_static {
58			name: "libb",
59			srcs: ["libb.a"],
60		}
61
62		cc_library_shared {
63			name: "libd",
64		}
65
66		cc_prebuilt_library_shared {
67			name: "libd",
68			srcs: ["libd.so"],
69		}
70
71		cc_library_static {
72			name: "libe",
73		}
74
75		cc_prebuilt_library_static {
76			name: "libe",
77			srcs: ["libe.a"],
78		}
79
80		cc_library {
81			name: "libf",
82		}
83
84		cc_prebuilt_library {
85			name: "libf",
86			static: {
87				srcs: ["libf.a"],
88			},
89			shared: {
90				srcs: ["libf.so"],
91			},
92		}
93
94		cc_object {
95			name: "crtx",
96		}
97
98		cc_prebuilt_object {
99			name: "crtx",
100			srcs: ["crtx.o"],
101		}
102	`
103
104	ctx := testPrebuilt(t, bp, map[string][]byte{
105		"liba.so": nil,
106		"libb.a":  nil,
107		"libd.so": nil,
108		"libe.a":  nil,
109		"libf.a":  nil,
110		"libf.so": nil,
111		"crtx.o":  nil,
112	})
113
114	// Verify that all the modules exist and that their dependencies were connected correctly
115	liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
116	libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
117	libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
118	libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
119	libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
120	libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
121	crtx := ctx.ModuleForTests("crtx", "android_arm64_armv8-a").Module()
122
123	prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
124	prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
125	prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
126	prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
127	prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
128	prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
129	prebuiltCrtx := ctx.ModuleForTests("prebuilt_crtx", "android_arm64_armv8-a").Module()
130
131	hasDep := func(m android.Module, wantDep android.Module) bool {
132		t.Helper()
133		var found bool
134		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
135			if dep == wantDep {
136				found = true
137			}
138		})
139		return found
140	}
141
142	if !hasDep(liba, prebuiltLiba) {
143		t.Errorf("liba missing dependency on prebuilt_liba")
144	}
145
146	if !hasDep(libb, prebuiltLibb) {
147		t.Errorf("libb missing dependency on prebuilt_libb")
148	}
149
150	if !hasDep(libd, prebuiltLibd) {
151		t.Errorf("libd missing dependency on prebuilt_libd")
152	}
153
154	if !hasDep(libe, prebuiltLibe) {
155		t.Errorf("libe missing dependency on prebuilt_libe")
156	}
157
158	if !hasDep(libfStatic, prebuiltLibfStatic) {
159		t.Errorf("libf static missing dependency on prebuilt_libf")
160	}
161
162	if !hasDep(libfShared, prebuiltLibfShared) {
163		t.Errorf("libf shared missing dependency on prebuilt_libf")
164	}
165
166	if !hasDep(crtx, prebuiltCrtx) {
167		t.Errorf("crtx missing dependency on prebuilt_crtx")
168	}
169}
170
171func TestPrebuiltLibraryShared(t *testing.T) {
172	ctx := testPrebuilt(t, `
173	cc_prebuilt_library_shared {
174		name: "libtest",
175		srcs: ["libf.so"],
176    strip: {
177        none: true,
178    },
179	}
180	`, map[string][]byte{
181		"libf.so": nil,
182	})
183
184	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
185	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
186}
187
188func TestPrebuiltLibraryStatic(t *testing.T) {
189	ctx := testPrebuilt(t, `
190	cc_prebuilt_library_static {
191		name: "libtest",
192		srcs: ["libf.a"],
193	}
194	`, map[string][]byte{
195		"libf.a": nil,
196	})
197
198	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
199	assertString(t, static.OutputFile().Path().Base(), "libf.a")
200}
201
202func TestPrebuiltLibrary(t *testing.T) {
203	ctx := testPrebuilt(t, `
204	cc_prebuilt_library {
205		name: "libtest",
206		static: {
207			srcs: ["libf.a"],
208		},
209		shared: {
210			srcs: ["libf.so"],
211		},
212    strip: {
213        none: true,
214    },
215	}
216	`, map[string][]byte{
217		"libf.a":  nil,
218		"libf.so": nil,
219	})
220
221	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
222	assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
223
224	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
225	assertString(t, static.OutputFile().Path().Base(), "libf.a")
226}
227
228func TestPrebuiltLibraryStem(t *testing.T) {
229	ctx := testPrebuilt(t, `
230	cc_prebuilt_library {
231		name: "libfoo",
232		stem: "libbar",
233		static: {
234			srcs: ["libfoo.a"],
235		},
236		shared: {
237			srcs: ["libfoo.so"],
238		},
239		strip: {
240			none: true,
241		},
242	}
243	`, map[string][]byte{
244		"libfoo.a":  nil,
245		"libfoo.so": nil,
246	})
247
248	static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
249	assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
250
251	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
252	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
253}
254
255func TestPrebuiltLibrarySharedStem(t *testing.T) {
256	ctx := testPrebuilt(t, `
257	cc_prebuilt_library_shared {
258		name: "libfoo",
259		stem: "libbar",
260		srcs: ["libfoo.so"],
261		strip: {
262			none: true,
263		},
264	}
265	`, map[string][]byte{
266		"libfoo.so": nil,
267	})
268
269	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
270	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
271}
272
273func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
274	if android.BuildOs != android.Linux {
275		t.Skipf("Skipping host prebuilt testing that is only supported on %s not %s", android.Linux, android.BuildOs)
276	}
277
278	ctx := testPrebuilt(t, `
279	cc_prebuilt_library_shared {
280		name: "libfoo",
281		device_supported: false,
282		host_supported: true,
283		target: {
284			linux_glibc_x86_64: {
285				srcs: ["linux_glibc_x86_64/lib64/libfoo.so"],
286			},
287		},
288	}
289
290	cc_prebuilt_binary {
291		name: "foo",
292		device_supported: false,
293		host_supported: true,
294		shared_libs: ["libfoo"],
295		target: {
296			linux_glibc_x86_64: {
297				srcs: ["linux_glibc_x86_64/bin/foo"],
298			},
299		},
300	}
301	`, map[string][]byte{
302		"libfoo.so": nil,
303		"foo":       nil,
304	})
305
306	fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
307	assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo")
308	assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
309
310	var libfooDep android.Path
311	for _, dep := range fooRule.Implicits {
312		if dep.Base() == "libfoo.so" {
313			libfooDep = dep
314			break
315		}
316	}
317	assertString(t, libfooDep.String(), "out/soong/.intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so")
318}
319
320func TestPrebuiltLibrarySanitized(t *testing.T) {
321	bp := `cc_prebuilt_library {
322	name: "libtest",
323		static: {
324                        sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
325		},
326		shared: {
327                        sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
328		},
329	}
330	cc_prebuilt_library_static {
331		name: "libtest_static",
332                sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, },
333	}
334	cc_prebuilt_library_shared {
335		name: "libtest_shared",
336                sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, },
337	}`
338
339	fs := map[string][]byte{
340		"libf.a":         nil,
341		"libf.hwasan.a":  nil,
342		"libf.so":        nil,
343		"hwasan/libf.so": nil,
344	}
345
346	// Without SANITIZE_TARGET.
347	ctx := testPrebuilt(t, bp, fs)
348
349	shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
350	assertString(t, shared_rule.Input.String(), "libf.so")
351
352	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
353	assertString(t, static.OutputFile().Path().Base(), "libf.a")
354
355	shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
356	assertString(t, shared_rule2.Input.String(), "libf.so")
357
358	static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
359	assertString(t, static2.OutputFile().Path().Base(), "libf.a")
360
361	// With SANITIZE_TARGET=hwaddress
362	ctx = testPrebuilt(t, bp, fs,
363		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
364			variables.SanitizeDevice = []string{"hwaddress"}
365		}),
366	)
367
368	shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
369	assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
370
371	static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
372	assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
373
374	shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
375	assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
376
377	static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
378	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
379}
380