blob: 4220f325522bb8bbf04b3db68e3f682407aebdd7 [file] [log] [blame]
Liz Kammer3b0f36c2022-09-16 12:39:27 -04001// Copyright 2021 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 Kammer3b0f36c2022-09-16 12:39:27 -040018 "strings"
19 "testing"
20
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +000021 "android/soong/android"
22
Liz Kammer3b0f36c2022-09-16 12:39:27 -040023 "github.com/google/blueprint"
24)
25
26func TestThinLtoDeps(t *testing.T) {
Liz Kammer7c5d1592022-10-31 16:27:38 -040027 t.Parallel()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040028 bp := `
Liz Kammer81d09502022-10-31 14:44:46 -040029 cc_library_shared {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040030 name: "lto_enabled",
31 srcs: ["src.c"],
Liz Kammer81d09502022-10-31 14:44:46 -040032 static_libs: ["foo", "lib_never_lto"],
Liz Kammer3b0f36c2022-09-16 12:39:27 -040033 shared_libs: ["bar"],
34 lto: {
35 thin: true,
36 }
37 }
Liz Kammer81d09502022-10-31 14:44:46 -040038 cc_library_static {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040039 name: "foo",
40 static_libs: ["baz"],
41 }
Liz Kammer81d09502022-10-31 14:44:46 -040042 cc_library_shared {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040043 name: "bar",
44 static_libs: ["qux"],
45 }
Liz Kammer81d09502022-10-31 14:44:46 -040046 cc_library_static {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040047 name: "baz",
48 }
Liz Kammer81d09502022-10-31 14:44:46 -040049 cc_library_static {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040050 name: "qux",
51 }
Liz Kammer81d09502022-10-31 14:44:46 -040052 cc_library_static {
53 name: "lib_never_lto",
54 lto: {
55 never: true,
56 },
57 }
Liz Kammer3b0f36c2022-09-16 12:39:27 -040058`
59
60 result := android.GroupFixturePreparers(
61 prepareForCcTest,
62 ).RunTestWithBp(t, bp)
63
64 libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040065
66 hasDep := func(m android.Module, wantDep android.Module) bool {
67 var found bool
68 result.VisitDirectDeps(m, func(dep blueprint.Module) {
69 if dep == wantDep {
70 found = true
71 }
72 })
73 return found
74 }
75
Liz Kammer81d09502022-10-31 14:44:46 -040076 libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040077 if !hasDep(libLto, libFoo) {
78 t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
79 }
80
Liz Kammer81d09502022-10-31 14:44:46 -040081 libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040082 if !hasDep(libFoo, libBaz) {
Liz Kammer81d09502022-10-31 14:44:46 -040083 t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
84 }
85
86 libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static_lto-thin").Module()
87 if !hasDep(libLto, libNeverLto) {
88 t.Errorf("'lto_enabled' missing dependency on NO-thin lto variant of 'lib_never_lto'")
89 }
90
91 libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module()
92 if !hasDep(libLto, libBar) {
93 t.Errorf("'lto_enabled' missing dependency on non-thin lto variant of 'bar'")
Liz Kammer3b0f36c2022-09-16 12:39:27 -040094 }
95
96 barVariants := result.ModuleVariantsForTests("bar")
97 for _, v := range barVariants {
98 if strings.Contains(v, "lto-thin") {
99 t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
100 }
101 }
102 quxVariants := result.ModuleVariantsForTests("qux")
103 for _, v := range quxVariants {
104 if strings.Contains(v, "lto-thin") {
105 t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
106 }
107 }
108}
Liz Kammer81d09502022-10-31 14:44:46 -0400109
110func TestThinLtoOnlyOnStaticDep(t *testing.T) {
Liz Kammer7c5d1592022-10-31 16:27:38 -0400111 t.Parallel()
Liz Kammer81d09502022-10-31 14:44:46 -0400112 bp := `
113 cc_library_shared {
114 name: "root",
115 srcs: ["src.c"],
116 static_libs: ["foo"],
117 }
118 cc_library_shared {
119 name: "root_no_lto",
120 srcs: ["src.c"],
121 static_libs: ["foo"],
122 lto: {
123 never: true,
124 }
125 }
126 cc_library_static {
127 name: "foo",
128 srcs: ["foo.c"],
129 static_libs: ["baz"],
130 lto: {
131 thin: true,
132 }
133 }
134 cc_library_static {
135 name: "baz",
136 srcs: ["baz.c"],
137 }
138`
139
140 result := android.GroupFixturePreparers(
141 prepareForCcTest,
142 ).RunTestWithBp(t, bp)
143
144 libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
145 libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()
146
147 hasDep := func(m android.Module, wantDep android.Module) bool {
148 var found bool
149 result.VisitDirectDeps(m, func(dep blueprint.Module) {
150 if dep == wantDep {
151 found = true
152 }
153 })
154 return found
155 }
156
157 libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static")
158 if !hasDep(libRoot, libFoo.Module()) {
159 t.Errorf("'root' missing dependency on thin lto variant of 'foo'")
160 }
161
162 if !hasDep(libRootLtoNever, libFoo.Module()) {
163 t.Errorf("'root_no_lto' missing dependency on thin lto variant of 'foo'")
164 }
165
166 libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
167 if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libFooCFlags, w) {
168 t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags)
169 }
170
171 libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin")
172 if !hasDep(libFoo.Module(), libBaz.Module()) {
173 t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
174 }
175
176 libBazCFlags := libFoo.Rule("cc").Args["cFlags"]
177 if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libBazCFlags, w) {
178 t.Errorf("'baz' expected to have flags %q, but got %q", w, libFooCFlags)
179 }
180}
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000181
182func TestLtoDisabledButEnabledForArch(t *testing.T) {
183 t.Parallel()
184 bp := `
185 cc_library {
186 name: "libfoo",
187 srcs: ["foo.c"],
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000188 lto: {
189 never: true,
190 },
191 target: {
Trevor Radcliffee22f3842023-02-09 19:01:31 +0000192 android_arm: {
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000193 lto: {
194 never: false,
195 thin: true,
196 },
197 },
198 },
199 }`
200 result := android.GroupFixturePreparers(
201 prepareForCcTest,
202 ).RunTestWithBp(t, bp)
203
Trevor Radcliffee22f3842023-02-09 19:01:31 +0000204 libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
205 libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000206
207 android.AssertStringDoesContain(t, "missing flag for LTO in variant that expects it",
208 libFooWithLto.Args["ldFlags"], "-flto=thin")
209 android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it",
210 libFooWithoutLto.Args["ldFlags"], "-flto=thin")
211}
Trevor Radcliffecb7c4482023-02-10 20:29:20 +0000212
213func TestLtoDoesNotPropagateToRuntimeLibs(t *testing.T) {
214 t.Parallel()
215 bp := `
216 cc_library {
217 name: "runtime_libbar",
218 srcs: ["bar.c"],
219 }
220
221 cc_library {
222 name: "libfoo",
223 srcs: ["foo.c"],
224 runtime_libs: ["runtime_libbar"],
225 lto: {
226 thin: true,
227 },
228 }`
229
230 result := android.GroupFixturePreparers(
231 prepareForCcTest,
232 ).RunTestWithBp(t, bp)
233
234 libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
235 libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
236
237 android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library",
238 libFoo.Args["ldFlags"], "-flto=thin")
239 android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib",
240 libBar.Args["ldFlags"], "-flto=thin")
241}