blob: 40f705b877111a094657c25eca304640d74a17ee [file] [log] [blame]
Yi Kongd5954a22022-01-26 17:36:26 +08001// Copyright 2022 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 (
Liz Kammer8c8e8d52022-10-31 15:53:36 -040018 "strings"
Yi Kongd5954a22022-01-26 17:36:26 +080019 "testing"
20
21 "android/soong/android"
Liz Kammer8c8e8d52022-10-31 15:53:36 -040022
Yi Kongd5954a22022-01-26 17:36:26 +080023 "github.com/google/blueprint"
24)
25
Liz Kammer8c8e8d52022-10-31 15:53:36 -040026type visitDirectDepsInterface interface {
27 VisitDirectDeps(blueprint.Module, func(dep blueprint.Module))
28}
29
30func hasDirectDep(ctx visitDirectDepsInterface, m android.Module, wantDep android.Module) bool {
31 var found bool
32 ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
33 if dep == wantDep {
34 found = true
35 }
36 })
37 return found
38}
39
Yi Kongd5954a22022-01-26 17:36:26 +080040func TestAfdoDeps(t *testing.T) {
Liz Kammer7c5d1592022-10-31 16:27:38 -040041 t.Parallel()
Yi Kongd5954a22022-01-26 17:36:26 +080042 bp := `
Liz Kammer8c8e8d52022-10-31 15:53:36 -040043 cc_library_shared {
Yi Kongd5954a22022-01-26 17:36:26 +080044 name: "libTest",
Liz Kammer8c8e8d52022-10-31 15:53:36 -040045 srcs: ["test.c"],
Yi Kongd5954a22022-01-26 17:36:26 +080046 static_libs: ["libFoo"],
47 afdo: true,
48 }
49
Liz Kammer8c8e8d52022-10-31 15:53:36 -040050 cc_library_static {
Yi Kongd5954a22022-01-26 17:36:26 +080051 name: "libFoo",
Liz Kammer8c8e8d52022-10-31 15:53:36 -040052 srcs: ["foo.c"],
Yi Kongd5954a22022-01-26 17:36:26 +080053 static_libs: ["libBar"],
54 }
55
Liz Kammer8c8e8d52022-10-31 15:53:36 -040056 cc_library_static {
Yi Kongd5954a22022-01-26 17:36:26 +080057 name: "libBar",
Liz Kammer8c8e8d52022-10-31 15:53:36 -040058 srcs: ["bar.c"],
Yi Kongd5954a22022-01-26 17:36:26 +080059 }
60 `
61 prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
62
63 result := android.GroupFixturePreparers(
64 prepareForCcTest,
65 prepareForAfdoTest,
66 ).RunTestWithBp(t, bp)
67
Liz Kammer8c8e8d52022-10-31 15:53:36 -040068 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
69 libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
70 libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
Yi Kongd5954a22022-01-26 17:36:26 +080071
Liz Kammer8c8e8d52022-10-31 15:53:36 -040072 if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
Yi Kongd5954a22022-01-26 17:36:26 +080073 t.Errorf("libTest missing dependency on afdo variant of libFoo")
74 }
75
Liz Kammer8c8e8d52022-10-31 15:53:36 -040076 if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
Yi Kongd5954a22022-01-26 17:36:26 +080077 t.Errorf("libTest missing dependency on afdo variant of libBar")
78 }
Liz Kammer8c8e8d52022-10-31 15:53:36 -040079
80 cFlags := libTest.Rule("cc").Args["cFlags"]
81 if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
82 t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", w, cFlags)
83 }
84
85 cFlags = libFoo.Rule("cc").Args["cFlags"]
86 if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
87 t.Errorf("Expected 'libFoo' to enable afdo, but did not find %q in cflags %q", w, cFlags)
88 }
89
90 cFlags = libBar.Rule("cc").Args["cFlags"]
91 if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
92 t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", w, cFlags)
93 }
94}
95
96func TestAfdoEnabledOnStaticDepNoAfdo(t *testing.T) {
Liz Kammer7c5d1592022-10-31 16:27:38 -040097 t.Parallel()
Liz Kammer8c8e8d52022-10-31 15:53:36 -040098 bp := `
99 cc_library_shared {
100 name: "libTest",
101 srcs: ["foo.c"],
102 static_libs: ["libFoo"],
103 }
104
105 cc_library_static {
106 name: "libFoo",
107 srcs: ["foo.c"],
108 static_libs: ["libBar"],
109 afdo: true, // TODO(b/256670524): remove support for enabling afdo from static only libraries, this can only propagate from shared libraries/binaries
110 }
111
112 cc_library_static {
113 name: "libBar",
114 }
115 `
116 prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libFoo.afdo", "TEST")
117
118 result := android.GroupFixturePreparers(
119 prepareForCcTest,
120 prepareForAfdoTest,
121 ).RunTestWithBp(t, bp)
122
123 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
124 libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
125 libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static").Module()
126
127 if !hasDirectDep(result, libTest, libFoo.Module()) {
128 t.Errorf("libTest missing dependency on afdo variant of libFoo")
129 }
130
131 if !hasDirectDep(result, libFoo.Module(), libBar) {
132 t.Errorf("libFoo missing dependency on afdo variant of libBar")
133 }
134
135 fooVariants := result.ModuleVariantsForTests("foo")
136 for _, v := range fooVariants {
137 if strings.Contains(v, "afdo-") {
138 t.Errorf("Expected no afdo variant of 'foo', got %q", v)
139 }
140 }
141
142 cFlags := libFoo.Rule("cc").Args["cFlags"]
143 if w := "-fprofile-sample-accurate"; strings.Contains(cFlags, w) {
144 t.Errorf("Expected 'foo' to not enable afdo, but found %q in cflags %q", w, cFlags)
145 }
146
147 barVariants := result.ModuleVariantsForTests("bar")
148 for _, v := range barVariants {
149 if strings.Contains(v, "afdo-") {
150 t.Errorf("Expected no afdo variant of 'bar', got %q", v)
151 }
152 }
153
Yi Kongd5954a22022-01-26 17:36:26 +0800154}
Vinh Tran9c6080c2022-12-05 14:55:38 -0500155
156func TestAfdoEnabledWithRuntimeDepNoAfdo(t *testing.T) {
157 bp := `
158 cc_library {
159 name: "libTest",
160 srcs: ["foo.c"],
161 runtime_libs: ["libFoo"],
162 afdo: true,
163 }
164
165 cc_library {
166 name: "libFoo",
167 }
168 `
169 prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
170
171 result := android.GroupFixturePreparers(
172 prepareForCcTest,
173 prepareForAfdoTest,
174 ).RunTestWithBp(t, bp)
175
176 libFooVariants := result.ModuleVariantsForTests("libFoo")
177 for _, v := range libFooVariants {
178 if strings.Contains(v, "afdo-") {
179 t.Errorf("Expected no afdo variant of 'foo', got %q", v)
180 }
181 }
182}
Vinh Tran2e7b0fd2023-03-27 11:30:19 -0400183
184func TestAfdoEnabledWithMultiArchs(t *testing.T) {
185 t.Parallel()
186 bp := `
187 cc_library_shared {
188 name: "foo",
189 srcs: ["test.c"],
190 afdo: true,
191 compile_multilib: "both",
192 }
193`
194 result := android.GroupFixturePreparers(
195 prepareForCcTest,
196 android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", "TEST"),
197 android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", "TEST"),
198 ).RunTestWithBp(t, bp)
199
200 fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
201 fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
202 if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
203 t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
204 }
205
206 fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
207 fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
208 if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
209 t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
210 }
211}
212
213func TestMultipleAfdoRDeps(t *testing.T) {
214 t.Parallel()
215 bp := `
216 cc_library_shared {
217 name: "libTest",
218 srcs: ["test.c"],
219 static_libs: ["libFoo"],
220 afdo: true,
221 }
222
223 cc_library_shared {
224 name: "libBar",
225 srcs: ["bar.c"],
226 static_libs: ["libFoo"],
227 afdo: true,
228 }
229
230 cc_library_static {
231 name: "libFoo",
232 srcs: ["foo.c"],
233 }
234 `
235
236 result := android.GroupFixturePreparers(
237 prepareForCcTest,
238 android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST"),
239 android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libBar.afdo", "TEST"),
240 ).RunTestWithBp(t, bp)
241
242 expectedCFlagLibTest := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libTest.afdo"
243 expectedCFlagLibBar := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libBar.afdo"
244
245 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
246 libTestAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
247
248 libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
249 libBarAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
250
251 // Check cFlags of afdo-enabled modules and the afdo-variant of their static deps
252 cFlags := libTest.Rule("cc").Args["cFlags"]
253 if !strings.Contains(cFlags, expectedCFlagLibTest) {
254 t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
255 }
256 cFlags = libBar.Rule("cc").Args["cFlags"]
257 if !strings.Contains(cFlags, expectedCFlagLibBar) {
258 t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
259 }
260
261 cFlags = libTestAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
262 if !strings.Contains(cFlags, expectedCFlagLibTest) {
263 t.Errorf("Expected 'libTestAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
264 }
265
266 cFlags = libBarAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
267 if !strings.Contains(cFlags, expectedCFlagLibBar) {
268 t.Errorf("Expected 'libBarAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
269 }
270
271 // Check dependency edges of static deps
272 if !hasDirectDep(result, libTest.Module(), libTestAfdoVariantOfLibFoo.Module()) {
273 t.Errorf("libTest missing dependency on afdo variant of libFoo")
274 }
275
276 if !hasDirectDep(result, libBar.Module(), libBarAfdoVariantOfLibFoo.Module()) {
277 t.Errorf("libBar missing dependency on afdo variant of libFoo")
278 }
279}