| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 1 | // 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 |  | 
 | 15 | package cc | 
 | 16 |  | 
 | 17 | import ( | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 18 | 	"strings" | 
 | 19 | 	"testing" | 
 | 20 |  | 
| Trevor Radcliffe | 07cf4ed | 2023-02-07 19:46:51 +0000 | [diff] [blame] | 21 | 	"android/soong/android" | 
 | 22 |  | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 23 | 	"github.com/google/blueprint" | 
 | 24 | ) | 
 | 25 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 26 | var LTOPreparer = android.GroupFixturePreparers( | 
| Yi Kong | f1d0ba4 | 2023-06-12 14:50:26 +0800 | [diff] [blame] | 27 | 	prepareForCcTest, | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 28 | ) | 
 | 29 |  | 
 | 30 | func hasDep(result *android.TestResult, m android.Module, wantDep android.Module) bool { | 
 | 31 | 	var found bool | 
 | 32 | 	result.VisitDirectDeps(m, func(dep blueprint.Module) { | 
 | 33 | 		if dep == wantDep { | 
 | 34 | 			found = true | 
 | 35 | 		} | 
 | 36 | 	}) | 
 | 37 | 	return found | 
 | 38 | } | 
| Yi Kong | f1d0ba4 | 2023-06-12 14:50:26 +0800 | [diff] [blame] | 39 |  | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 40 | func TestThinLtoDeps(t *testing.T) { | 
| Liz Kammer | 7c5d159 | 2022-10-31 16:27:38 -0400 | [diff] [blame] | 41 | 	t.Parallel() | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 42 | 	bp := ` | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 43 | 	cc_library_shared { | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 44 | 		name: "lto_enabled", | 
 | 45 | 		srcs: ["src.c"], | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 46 | 		static_libs: ["foo", "lib_never_lto"], | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 47 | 		shared_libs: ["bar"], | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 48 | 	} | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 49 | 	cc_library_static { | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 50 | 		name: "foo", | 
 | 51 | 		static_libs: ["baz"], | 
 | 52 | 	} | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 53 | 	cc_library_shared { | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 54 | 		name: "bar", | 
 | 55 | 		static_libs: ["qux"], | 
 | 56 | 	} | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 57 | 	cc_library_static { | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 58 | 		name: "baz", | 
 | 59 | 	} | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 60 | 	cc_library_static { | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 61 | 		name: "qux", | 
 | 62 | 	} | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 63 | 	cc_library_static { | 
 | 64 | 		name: "lib_never_lto", | 
 | 65 | 		lto: { | 
 | 66 | 			never: true, | 
 | 67 | 		}, | 
 | 68 | 	} | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 69 | ` | 
 | 70 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 71 | 	result := LTOPreparer.RunTestWithBp(t, bp) | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 72 |  | 
 | 73 | 	libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module() | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 74 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 75 | 	libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static").Module() | 
 | 76 | 	if !hasDep(result, libLto, libFoo) { | 
 | 77 | 		t.Errorf("'lto_enabled' missing dependency on the default variant of 'foo'") | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 78 | 	} | 
 | 79 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 80 | 	libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static").Module() | 
 | 81 | 	if !hasDep(result, libFoo, libBaz) { | 
 | 82 | 		t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'") | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 83 | 	} | 
 | 84 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 85 | 	libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static").Module() | 
 | 86 | 	if !hasDep(result, libLto, libNeverLto) { | 
 | 87 | 		t.Errorf("'lto_enabled' missing dependency on the default variant of 'lib_never_lto'") | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 88 | 	} | 
 | 89 |  | 
 | 90 | 	libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module() | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 91 | 	if !hasDep(result, libLto, libBar) { | 
 | 92 | 		t.Errorf("'lto_enabled' missing dependency on the default variant of 'bar'") | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 93 | 	} | 
 | 94 |  | 
 | 95 | 	barVariants := result.ModuleVariantsForTests("bar") | 
 | 96 | 	for _, v := range barVariants { | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 97 | 		if strings.Contains(v, "lto-none") { | 
 | 98 | 			t.Errorf("Expected variants for 'bar' to not contain 'lto-none', but found %q", v) | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 99 | 		} | 
 | 100 | 	} | 
 | 101 | 	quxVariants := result.ModuleVariantsForTests("qux") | 
 | 102 | 	for _, v := range quxVariants { | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 103 | 		if strings.Contains(v, "lto-none") { | 
 | 104 | 			t.Errorf("Expected variants for 'qux' to not contain 'lto-none', but found %q", v) | 
| Liz Kammer | 3b0f36c | 2022-09-16 12:39:27 -0400 | [diff] [blame] | 105 | 		} | 
 | 106 | 	} | 
 | 107 | } | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 108 |  | 
 | 109 | func TestThinLtoOnlyOnStaticDep(t *testing.T) { | 
| Liz Kammer | 7c5d159 | 2022-10-31 16:27:38 -0400 | [diff] [blame] | 110 | 	t.Parallel() | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 111 | 	bp := ` | 
 | 112 | 	cc_library_shared { | 
 | 113 | 		name: "root", | 
 | 114 | 		srcs: ["src.c"], | 
 | 115 | 		static_libs: ["foo"], | 
 | 116 | 	} | 
 | 117 | 	cc_library_shared { | 
 | 118 | 		name: "root_no_lto", | 
 | 119 | 		srcs: ["src.c"], | 
 | 120 | 		static_libs: ["foo"], | 
 | 121 | 		lto: { | 
 | 122 | 			never: true, | 
 | 123 | 		} | 
 | 124 | 	} | 
 | 125 | 	cc_library_static { | 
 | 126 | 		name: "foo", | 
 | 127 | 		srcs: ["foo.c"], | 
 | 128 | 		static_libs: ["baz"], | 
 | 129 | 		lto: { | 
 | 130 | 			thin: true, | 
 | 131 | 		} | 
 | 132 | 	} | 
 | 133 | 	cc_library_static { | 
 | 134 | 		name: "baz", | 
 | 135 | 		srcs: ["baz.c"], | 
 | 136 | 	} | 
 | 137 | ` | 
 | 138 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 139 | 	result := LTOPreparer.RunTestWithBp(t, bp) | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 140 |  | 
 | 141 | 	libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module() | 
 | 142 | 	libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module() | 
 | 143 |  | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 144 | 	libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static") | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 145 | 	if !hasDep(result, libRoot, libFoo.Module()) { | 
 | 146 | 		t.Errorf("'root' missing dependency on the default variant of 'foo'") | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 147 | 	} | 
 | 148 |  | 
| Colin Cross | 6ac83a8 | 2024-01-23 11:23:10 -0800 | [diff] [blame] | 149 | 	libFooNoLto := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-none") | 
 | 150 | 	if !hasDep(result, libRootLtoNever, libFooNoLto.Module()) { | 
 | 151 | 		t.Errorf("'root_no_lto' missing dependency on the lto_none variant of 'foo'") | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 152 | 	} | 
 | 153 |  | 
 | 154 | 	libFooCFlags := libFoo.Rule("cc").Args["cFlags"] | 
 | 155 | 	if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libFooCFlags, w) { | 
 | 156 | 		t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags) | 
 | 157 | 	} | 
 | 158 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 159 | 	libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static") | 
 | 160 | 	if !hasDep(result, libFoo.Module(), libBaz.Module()) { | 
 | 161 | 		t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'") | 
| Liz Kammer | 81d0950 | 2022-10-31 14:44:46 -0400 | [diff] [blame] | 162 | 	} | 
 | 163 |  | 
 | 164 | 	libBazCFlags := libFoo.Rule("cc").Args["cFlags"] | 
 | 165 | 	if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libBazCFlags, w) { | 
 | 166 | 		t.Errorf("'baz' expected to have flags %q, but got %q", w, libFooCFlags) | 
 | 167 | 	} | 
 | 168 | } | 
| Trevor Radcliffe | 07cf4ed | 2023-02-07 19:46:51 +0000 | [diff] [blame] | 169 |  | 
 | 170 | func TestLtoDisabledButEnabledForArch(t *testing.T) { | 
 | 171 | 	t.Parallel() | 
 | 172 | 	bp := ` | 
 | 173 | 	cc_library { | 
 | 174 | 		name: "libfoo", | 
 | 175 | 		srcs: ["foo.c"], | 
| Trevor Radcliffe | 07cf4ed | 2023-02-07 19:46:51 +0000 | [diff] [blame] | 176 | 		lto: { | 
 | 177 | 			never: true, | 
 | 178 | 		}, | 
 | 179 | 		target: { | 
| Trevor Radcliffe | e22f384 | 2023-02-09 19:01:31 +0000 | [diff] [blame] | 180 | 			android_arm: { | 
| Trevor Radcliffe | 07cf4ed | 2023-02-07 19:46:51 +0000 | [diff] [blame] | 181 | 				lto: { | 
 | 182 | 					never: false, | 
 | 183 | 					thin: true, | 
 | 184 | 				}, | 
 | 185 | 			}, | 
 | 186 | 		}, | 
 | 187 | 	}` | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 188 | 	result := LTOPreparer.RunTestWithBp(t, bp) | 
| Trevor Radcliffe | 07cf4ed | 2023-02-07 19:46:51 +0000 | [diff] [blame] | 189 |  | 
| Trevor Radcliffe | e22f384 | 2023-02-09 19:01:31 +0000 | [diff] [blame] | 190 | 	libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") | 
 | 191 | 	libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld") | 
| Trevor Radcliffe | 07cf4ed | 2023-02-07 19:46:51 +0000 | [diff] [blame] | 192 |  | 
 | 193 | 	android.AssertStringDoesContain(t, "missing flag for LTO in variant that expects it", | 
 | 194 | 		libFooWithLto.Args["ldFlags"], "-flto=thin") | 
 | 195 | 	android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it", | 
 | 196 | 		libFooWithoutLto.Args["ldFlags"], "-flto=thin") | 
 | 197 | } | 
| Trevor Radcliffe | cb7c448 | 2023-02-10 20:29:20 +0000 | [diff] [blame] | 198 |  | 
 | 199 | func TestLtoDoesNotPropagateToRuntimeLibs(t *testing.T) { | 
 | 200 | 	t.Parallel() | 
 | 201 | 	bp := ` | 
 | 202 | 	cc_library { | 
 | 203 | 		name: "runtime_libbar", | 
 | 204 | 		srcs: ["bar.c"], | 
 | 205 | 	} | 
 | 206 |  | 
 | 207 | 	cc_library { | 
 | 208 | 		name: "libfoo", | 
 | 209 | 		srcs: ["foo.c"], | 
 | 210 | 		runtime_libs: ["runtime_libbar"], | 
 | 211 | 		lto: { | 
 | 212 | 			thin: true, | 
 | 213 | 		}, | 
 | 214 | 	}` | 
 | 215 |  | 
| Yi Kong | 577a73a | 2023-10-05 05:03:42 +0000 | [diff] [blame] | 216 | 	result := LTOPreparer.RunTestWithBp(t, bp) | 
| Trevor Radcliffe | cb7c448 | 2023-02-10 20:29:20 +0000 | [diff] [blame] | 217 |  | 
 | 218 | 	libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") | 
 | 219 | 	libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld") | 
 | 220 |  | 
 | 221 | 	android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library", | 
 | 222 | 		libFoo.Args["ldFlags"], "-flto=thin") | 
 | 223 | 	android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib", | 
 | 224 | 		libBar.Args["ldFlags"], "-flto=thin") | 
 | 225 | } |