xref: /aosp_15_r20/build/soong/cc/orderfile_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2023 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	"strings"
19	"testing"
20
21	"android/soong/android"
22)
23
24func TestOrderfileProfileSharedLibrary(t *testing.T) {
25	t.Parallel()
26	bp := `
27	cc_library_shared {
28		name: "libTest",
29		srcs: ["test.c"],
30		orderfile : {
31			instrumentation: true,
32			load_order_file: false,
33			order_file_path: "",
34		},
35	}
36	`
37
38	result := android.GroupFixturePreparers(
39		prepareForCcTest,
40	).RunTestWithBp(t, bp)
41
42	expectedCFlag := "-forder-file-instrumentation"
43
44	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
45
46	// Check cFlags of orderfile-enabled module
47	cFlags := libTest.Rule("cc").Args["cFlags"]
48	if !strings.Contains(cFlags, expectedCFlag) {
49		t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
50	}
51
52	// Check ldFlags of orderfile-enabled module
53	ldFlags := libTest.Rule("ld").Args["ldFlags"]
54	if !strings.Contains(ldFlags, expectedCFlag) {
55		t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
56	}
57}
58
59func TestOrderfileLoadSharedLibrary(t *testing.T) {
60	t.Parallel()
61	bp := `
62	cc_library_shared {
63		name: "libTest",
64		srcs: ["test.c"],
65		orderfile : {
66			instrumentation: true,
67			load_order_file: true,
68			order_file_path: "libTest.orderfile",
69		},
70	}
71	`
72
73	result := android.GroupFixturePreparers(
74		prepareForCcTest,
75		android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/libTest.orderfile", "TEST"),
76	).RunTestWithBp(t, bp)
77
78	expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/libTest.orderfile"
79
80	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
81
82	// Check ldFlags of orderfile-enabled module
83	ldFlags := libTest.Rule("ld").Args["ldFlags"]
84	if !strings.Contains(ldFlags, expectedCFlag) {
85		t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
86	}
87}
88
89func TestOrderfileProfileBinary(t *testing.T) {
90	t.Parallel()
91	bp := `
92	cc_binary {
93		name: "test",
94		srcs: ["test.c"],
95		orderfile : {
96			instrumentation: true,
97			load_order_file: false,
98			order_file_path: "",
99		},
100	}
101	`
102
103	result := android.GroupFixturePreparers(
104		prepareForCcTest,
105	).RunTestWithBp(t, bp)
106
107	expectedCFlag := "-forder-file-instrumentation"
108
109	test := result.ModuleForTests("test", "android_arm64_armv8-a")
110
111	// Check cFlags of orderfile-enabled module
112	cFlags := test.Rule("cc").Args["cFlags"]
113	if !strings.Contains(cFlags, expectedCFlag) {
114		t.Errorf("Expected 'test' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
115	}
116
117	// Check ldFlags of orderfile-enabled module
118	ldFlags := test.Rule("ld").Args["ldFlags"]
119	if !strings.Contains(ldFlags, expectedCFlag) {
120		t.Errorf("Expected 'test' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
121	}
122}
123
124func TestOrderfileLoadBinary(t *testing.T) {
125	t.Parallel()
126	bp := `
127	cc_binary {
128		name: "test",
129		srcs: ["test.c"],
130		orderfile : {
131			instrumentation: true,
132			load_order_file: true,
133			order_file_path: "test.orderfile",
134		},
135	}
136	`
137
138	result := android.GroupFixturePreparers(
139		prepareForCcTest,
140		android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"),
141	).RunTestWithBp(t, bp)
142
143	expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
144
145	test := result.ModuleForTests("test", "android_arm64_armv8-a")
146
147	// Check ldFlags of orderfile-enabled module
148	ldFlags := test.Rule("ld").Args["ldFlags"]
149	if !strings.Contains(ldFlags, expectedCFlag) {
150		t.Errorf("Expected 'test' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
151	}
152}
153
154// Profile flags should propagate through static libraries
155func TestOrderfileProfilePropagateStaticDeps(t *testing.T) {
156	t.Parallel()
157	bp := `
158	cc_library_shared {
159		name: "libTest",
160		srcs: ["test.c"],
161		static_libs: ["libFoo"],
162		orderfile : {
163			instrumentation: true,
164			load_order_file: false,
165			order_file_path: "",
166		},
167	}
168
169	cc_library_static {
170		name: "libFoo",
171		srcs: ["foo.c"],
172		static_libs: ["libBar"],
173	}
174
175	cc_library_static {
176		name: "libBar",
177		srcs: ["bar.c"],
178	}
179	`
180
181	result := android.GroupFixturePreparers(
182		prepareForCcTest,
183	).RunTestWithBp(t, bp)
184
185	expectedCFlag := "-forder-file-instrumentation"
186
187	// Check cFlags of orderfile-enabled module
188	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
189
190	cFlags := libTest.Rule("cc").Args["cFlags"]
191	if !strings.Contains(cFlags, expectedCFlag) {
192		t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
193	}
194
195	// Check cFlags of orderfile variant static libraries
196	libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
197	libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
198
199	cFlags = libFooOfVariant.Rule("cc").Args["cFlags"]
200	if !strings.Contains(cFlags, expectedCFlag) {
201		t.Errorf("Expected 'libFooOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
202	}
203
204	cFlags = libBarOfVariant.Rule("cc").Args["cFlags"]
205	if !strings.Contains(cFlags, expectedCFlag) {
206		t.Errorf("Expected 'libBarOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
207	}
208
209	// Check dependency edge from orderfile-enabled module to orderfile variant static libraries
210	if !hasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) {
211		t.Errorf("libTest missing dependency on orderfile variant of libFoo")
212	}
213
214	if !hasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) {
215		t.Errorf("libTest missing dependency on orderfile variant of libBar")
216	}
217
218	// Check cFlags of the non-orderfile variant static libraries
219	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
220	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
221
222	cFlags = libFoo.Rule("cc").Args["cFlags"]
223	if strings.Contains(cFlags, expectedCFlag) {
224		t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
225	}
226
227	cFlags = libBar.Rule("cc").Args["cFlags"]
228	if strings.Contains(cFlags, expectedCFlag) {
229		t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
230	}
231
232	// Check no dependency edge from orderfile-enabled module to non-orderfile variant static libraries
233	if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
234		t.Errorf("libTest has dependency on non-orderfile variant of libFoo")
235	}
236
237	if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
238		t.Errorf("libTest has dependency on non-orderfile variant of libBar")
239	}
240}
241
242// Load flags should never propagate
243func TestOrderfileLoadPropagateStaticDeps(t *testing.T) {
244	t.Parallel()
245	bp := `
246	cc_library_shared {
247		name: "libTest",
248		srcs: ["test.c"],
249		static_libs: ["libFoo"],
250		orderfile : {
251			instrumentation: true,
252			load_order_file: true,
253			order_file_path: "test.orderfile",
254		},
255	}
256
257	cc_library_static {
258		name: "libFoo",
259		srcs: ["foo.c"],
260		static_libs: ["libBar"],
261	}
262
263	cc_library_static {
264		name: "libBar",
265		srcs: ["bar.c"],
266	}
267	`
268
269	result := android.GroupFixturePreparers(
270		prepareForCcTest,
271		android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"),
272	).RunTestWithBp(t, bp)
273
274	expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
275
276	// Check ldFlags of orderfile-enabled module
277	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
278
279	ldFlags := libTest.Rule("ld").Args["ldFlags"]
280	if !strings.Contains(ldFlags, expectedCFlag) {
281		t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags)
282	}
283
284	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
285	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
286
287	// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
288	if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
289		t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
290	}
291
292	if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
293		t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
294	}
295
296	// Make sure no orderfile variants are created for static libraries because the flags were not propagated
297	libFooVariants := result.ModuleVariantsForTests("libFoo")
298	for _, v := range libFooVariants {
299		if strings.Contains(v, "orderfile") {
300			t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
301		}
302	}
303
304	libBarVariants := result.ModuleVariantsForTests("libBar")
305	for _, v := range libBarVariants {
306		if strings.Contains(v, "orderfile") {
307			t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
308		}
309	}
310}
311
312// Profile flags should not propagate through shared libraries
313func TestOrderfileProfilePropagateSharedDeps(t *testing.T) {
314	t.Parallel()
315	bp := `
316	cc_library_shared {
317		name: "libTest",
318		srcs: ["test.c"],
319		shared_libs: ["libFoo"],
320		orderfile : {
321			instrumentation: true,
322			load_order_file: false,
323			order_file_path: "",
324		},
325	}
326
327	cc_library_shared {
328		name: "libFoo",
329		srcs: ["foo.c"],
330		static_libs: ["libBar"],
331	}
332
333	cc_library_static {
334		name: "libBar",
335		srcs: ["bar.c"],
336	}
337	`
338
339	result := android.GroupFixturePreparers(
340		prepareForCcTest,
341	).RunTestWithBp(t, bp)
342
343	expectedCFlag := "-forder-file-instrumentation"
344
345	// Check cFlags of orderfile-enabled module
346	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
347
348	cFlags := libTest.Rule("cc").Args["cFlags"]
349	if !strings.Contains(cFlags, expectedCFlag) {
350		t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
351	}
352
353	// Check cFlags of the static and shared libraries
354	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
355	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
356
357	cFlags = libFoo.Rule("cc").Args["cFlags"]
358	if strings.Contains(cFlags, expectedCFlag) {
359		t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
360	}
361
362	cFlags = libBar.Rule("cc").Args["cFlags"]
363	if strings.Contains(cFlags, expectedCFlag) {
364		t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
365	}
366
367	// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
368	if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
369		t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
370	}
371
372	if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
373		t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
374	}
375
376	// Make sure no orderfile variants are created for libraries because the flags were not propagated
377	libFooVariants := result.ModuleVariantsForTests("libFoo")
378	for _, v := range libFooVariants {
379		if strings.Contains(v, "orderfile") {
380			t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
381		}
382	}
383
384	libBarVariants := result.ModuleVariantsForTests("libBar")
385	for _, v := range libBarVariants {
386		if strings.Contains(v, "orderfile") {
387			t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
388		}
389	}
390}
391
392// Profile flags should not work or be propagated if orderfile flags start at a static library
393func TestOrderfileProfileStaticLibrary(t *testing.T) {
394	t.Parallel()
395	bp := `
396	cc_library_static {
397		name: "libTest",
398		srcs: ["test.c"],
399		static_libs: ["libFoo"],
400		orderfile : {
401			instrumentation: true,
402			load_order_file: false,
403			order_file_path: "",
404		},
405	}
406
407	cc_library_static {
408		name: "libFoo",
409		srcs: ["foo.c"],
410		static_libs: ["libBar"],
411	}
412
413	cc_library_static {
414		name: "libBar",
415		srcs: ["bar.c"],
416	}
417	`
418
419	result := android.GroupFixturePreparers(
420		prepareForCcTest,
421	).RunTestWithBp(t, bp)
422
423	expectedCFlag := "-forder-file-instrumentation"
424
425	// Check cFlags of module
426	libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_static")
427
428	cFlags := libTest.Rule("cc").Args["cFlags"]
429	if strings.Contains(cFlags, expectedCFlag) {
430		t.Errorf("Expected 'libTest' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
431	}
432
433	// Check cFlags of the static libraries
434	libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
435	libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
436
437	cFlags = libFoo.Rule("cc").Args["cFlags"]
438	if strings.Contains(cFlags, expectedCFlag) {
439		t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
440	}
441
442	cFlags = libBar.Rule("cc").Args["cFlags"]
443	if strings.Contains(cFlags, expectedCFlag) {
444		t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
445	}
446
447	// Check dependency edge from orderfile-enabled module to non-orderfile variant libraries
448	if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
449		t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
450	}
451
452	if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
453		t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
454	}
455
456	// Make sure no orderfile variants are created for static libraries because the flags were not propagated
457	libFooVariants := result.ModuleVariantsForTests("libFoo")
458	for _, v := range libFooVariants {
459		if strings.Contains(v, "orderfile") {
460			t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
461		}
462	}
463
464	libBarVariants := result.ModuleVariantsForTests("libBar")
465	for _, v := range libBarVariants {
466		if strings.Contains(v, "orderfile") {
467			t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
468		}
469	}
470}
471