blob: e0afd4a73f6308daa04a01e5801060c2e4c993da [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
Yi Kongf1d0ba42023-06-12 14:50:26 +080026var NoGlobalThinLTOPreparer = android.GroupFixturePreparers(
27 prepareForCcTest,
28 android.FixtureModifyEnv(func(env map[string]string) {
29 env["GLOBAL_THINLTO"] = "false"
30 }))
31
Liz Kammer3b0f36c2022-09-16 12:39:27 -040032func TestThinLtoDeps(t *testing.T) {
Liz Kammer7c5d1592022-10-31 16:27:38 -040033 t.Parallel()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040034 bp := `
Liz Kammer81d09502022-10-31 14:44:46 -040035 cc_library_shared {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040036 name: "lto_enabled",
37 srcs: ["src.c"],
Liz Kammer81d09502022-10-31 14:44:46 -040038 static_libs: ["foo", "lib_never_lto"],
Liz Kammer3b0f36c2022-09-16 12:39:27 -040039 shared_libs: ["bar"],
40 lto: {
41 thin: true,
42 }
43 }
Liz Kammer81d09502022-10-31 14:44:46 -040044 cc_library_static {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040045 name: "foo",
46 static_libs: ["baz"],
47 }
Liz Kammer81d09502022-10-31 14:44:46 -040048 cc_library_shared {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040049 name: "bar",
50 static_libs: ["qux"],
51 }
Liz Kammer81d09502022-10-31 14:44:46 -040052 cc_library_static {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040053 name: "baz",
54 }
Liz Kammer81d09502022-10-31 14:44:46 -040055 cc_library_static {
Liz Kammer3b0f36c2022-09-16 12:39:27 -040056 name: "qux",
57 }
Liz Kammer81d09502022-10-31 14:44:46 -040058 cc_library_static {
59 name: "lib_never_lto",
60 lto: {
61 never: true,
62 },
63 }
Liz Kammer3b0f36c2022-09-16 12:39:27 -040064`
65
Yi Kongf1d0ba42023-06-12 14:50:26 +080066 result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
Liz Kammer3b0f36c2022-09-16 12:39:27 -040067
68 libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040069
70 hasDep := func(m android.Module, wantDep android.Module) bool {
71 var found bool
72 result.VisitDirectDeps(m, func(dep blueprint.Module) {
73 if dep == wantDep {
74 found = true
75 }
76 })
77 return found
78 }
79
Liz Kammer81d09502022-10-31 14:44:46 -040080 libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040081 if !hasDep(libLto, libFoo) {
82 t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
83 }
84
Liz Kammer81d09502022-10-31 14:44:46 -040085 libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
Liz Kammer3b0f36c2022-09-16 12:39:27 -040086 if !hasDep(libFoo, libBaz) {
Liz Kammer81d09502022-10-31 14:44:46 -040087 t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
88 }
89
90 libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static_lto-thin").Module()
91 if !hasDep(libLto, libNeverLto) {
92 t.Errorf("'lto_enabled' missing dependency on NO-thin lto variant of 'lib_never_lto'")
93 }
94
95 libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module()
96 if !hasDep(libLto, libBar) {
97 t.Errorf("'lto_enabled' missing dependency on non-thin lto variant of 'bar'")
Liz Kammer3b0f36c2022-09-16 12:39:27 -040098 }
99
100 barVariants := result.ModuleVariantsForTests("bar")
101 for _, v := range barVariants {
102 if strings.Contains(v, "lto-thin") {
103 t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
104 }
105 }
106 quxVariants := result.ModuleVariantsForTests("qux")
107 for _, v := range quxVariants {
108 if strings.Contains(v, "lto-thin") {
109 t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
110 }
111 }
112}
Liz Kammer81d09502022-10-31 14:44:46 -0400113
114func TestThinLtoOnlyOnStaticDep(t *testing.T) {
Liz Kammer7c5d1592022-10-31 16:27:38 -0400115 t.Parallel()
Liz Kammer81d09502022-10-31 14:44:46 -0400116 bp := `
117 cc_library_shared {
118 name: "root",
119 srcs: ["src.c"],
120 static_libs: ["foo"],
121 }
122 cc_library_shared {
123 name: "root_no_lto",
124 srcs: ["src.c"],
125 static_libs: ["foo"],
126 lto: {
127 never: true,
128 }
129 }
130 cc_library_static {
131 name: "foo",
132 srcs: ["foo.c"],
133 static_libs: ["baz"],
134 lto: {
135 thin: true,
136 }
137 }
138 cc_library_static {
139 name: "baz",
140 srcs: ["baz.c"],
141 }
142`
143
Yi Kongf1d0ba42023-06-12 14:50:26 +0800144 result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
Liz Kammer81d09502022-10-31 14:44:46 -0400145
146 libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
147 libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()
148
149 hasDep := func(m android.Module, wantDep android.Module) bool {
150 var found bool
151 result.VisitDirectDeps(m, func(dep blueprint.Module) {
152 if dep == wantDep {
153 found = true
154 }
155 })
156 return found
157 }
158
159 libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static")
160 if !hasDep(libRoot, libFoo.Module()) {
161 t.Errorf("'root' missing dependency on thin lto variant of 'foo'")
162 }
163
164 if !hasDep(libRootLtoNever, libFoo.Module()) {
165 t.Errorf("'root_no_lto' missing dependency on thin lto variant of 'foo'")
166 }
167
168 libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
169 if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libFooCFlags, w) {
170 t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags)
171 }
172
173 libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin")
174 if !hasDep(libFoo.Module(), libBaz.Module()) {
175 t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
176 }
177
178 libBazCFlags := libFoo.Rule("cc").Args["cFlags"]
179 if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libBazCFlags, w) {
180 t.Errorf("'baz' expected to have flags %q, but got %q", w, libFooCFlags)
181 }
182}
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000183
184func TestLtoDisabledButEnabledForArch(t *testing.T) {
185 t.Parallel()
186 bp := `
187 cc_library {
188 name: "libfoo",
189 srcs: ["foo.c"],
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000190 lto: {
191 never: true,
192 },
193 target: {
Trevor Radcliffee22f3842023-02-09 19:01:31 +0000194 android_arm: {
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000195 lto: {
196 never: false,
197 thin: true,
198 },
199 },
200 },
201 }`
Yi Kongf1d0ba42023-06-12 14:50:26 +0800202 result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
Trevor Radcliffe07cf4ed2023-02-07 19:46:51 +0000203
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
Yi Kongf1d0ba42023-06-12 14:50:26 +0800230 result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
Trevor Radcliffecb7c4482023-02-10 20:29:20 +0000231
232 libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
233 libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
234
235 android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library",
236 libFoo.Args["ldFlags"], "-flto=thin")
237 android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib",
238 libBar.Args["ldFlags"], "-flto=thin")
239}